commit 5be27f6bdaff408ce8ec92b0133876f9085419ea
parent fb8f78d58b8f580820bf6ffbbde0942217572e06
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sun, 9 Apr 2023 13:44:55 +0200
Search
Diffstat:
M | kilo.c | | | 84 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
1 file changed, 80 insertions(+), 4 deletions(-)
diff --git a/kilo.c b/kilo.c
@@ -82,7 +82,7 @@ struct editorConfig E;
void editorSetStatusMessage(const char *fmt, ...);
void editorRefreshScreen();
-char *editorPrompt(char *prompt);
+char *editorPrompt(char *prompt, void (*callback)(char *, int));
/*** terminal ***/
@@ -207,6 +207,17 @@ int editorRowCxToRx(erow *row, int cx) {
return rx;
}
+int editorRowRxtoCx(erow *row, int rx) {
+ int cur_rx = 0, cx;
+ for (cx = 0; cx < row->size; cx++) {
+ if (row->chars[cx] == '\t')
+ cur_rx += (KILO_TAB_STOP - 1) - (cur_rx % KILO_TAB_STOP);
+ cur_rx++;
+ if (cur_rx > rx) return cx;
+ }
+ return cx;
+}
+
void editorUpdateRow(erow *row) {
int tabs = 0;
for (int j = 0; j < row->size; j++)
@@ -367,7 +378,7 @@ void editorOpen(char *filename) {
void editorSave() {
if (E.filename == NULL) {
- E.filename = editorPrompt("Save as: %s");
+ E.filename = editorPrompt("Save as: %s", NULL);
if (E.filename == NULL) {
editorSetStatusMessage("Save aborted");
return;
@@ -394,6 +405,65 @@ void editorSave() {
editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
}
+/*** find ***/
+
+void editorFindCallback(char *query, int key) {
+ static int last_match = -1;
+ static int direction = 1;
+
+ if (key == '\r' || key == '\x1b') {
+ last_match = -1;
+ direction = 1;
+ return;
+ } else if (key == ARROW_RIGHT || key == ARROW_DOWN) {
+ direction = 1;
+ } else if (key == ARROW_LEFT || key == ARROW_UP) {
+ direction = -1;
+ } else {
+ last_match = -1;
+ direction = 1;
+ }
+
+ if (last_match == -1) direction = 1;
+
+ int current = last_match;
+ for (int i = 0; i < E.numrows; i++) {
+ current += direction;
+ if (current == -1)
+ current = E.numrows - 1;
+ else if (current == E.numrows)
+ current = 0;
+
+ erow *row = &E.row[current];
+ char *match = strstr(row->render, query);
+ if (match) {
+ last_match = current;
+ E.cy = current;
+ E.cx = editorRowRxtoCx(row, match - row->render);
+ E.rowoff = E.numrows;
+ break;
+ }
+ }
+}
+
+void editorFind() {
+ int saved_cx = E.cx;
+ int saved_cy = E.cy;
+ int saved_coloff = E.coloff;
+ int saved_rowoff = E.rowoff;
+
+ char *query =
+ editorPrompt("Search: %s (Use ESC/Arrows/Enter)", editorFindCallback);
+ if (query) {
+ free(query);
+ } else {
+ E.cx = saved_cx;
+ E.cy = saved_cy;
+ E.coloff = saved_coloff;
+ E.rowoff = saved_rowoff;
+ }
+}
+
/*** append buffer ***/
struct abuf {
@@ -417,7 +487,7 @@ void abFree(struct abuf *ab) { free(ab->b); }
/*** input ***/
-char *editorPrompt(char *prompt) {
+char *editorPrompt(char *prompt, void (*callback)(char *, int)) {
size_t bufsize = 128, buflen;
char *buf = malloc(bufsize);
buf[buflen = 0] = '\0';
@@ -432,11 +502,13 @@ char *editorPrompt(char *prompt) {
if (buflen != 0) buf[--buflen] = '\0';
} else if (c == '\x1b') {
editorSetStatusMessage("");
+ if (callback) callback(buf, c);
free(buf);
return NULL;
} else if (c == '\r') {
if (buflen != 0) {
editorSetStatusMessage("");
+ if (callback) callback(buf, c);
return buf;
}
} else if (!iscntrl(c) && c < 128) {
@@ -447,6 +519,8 @@ char *editorPrompt(char *prompt) {
buf[buflen++] = c;
buf[buflen] = '\0';
}
+
+ if (callback) callback(buf, c);
}
}
@@ -512,6 +586,8 @@ void editorProcessKeypress() {
if (E.cy < E.numrows) E.cx = E.row[E.cy].size;
break;
+ case CTRL_KEY('f'): editorFind(); break;
+
case BACKSPACE:
case CTRL_KEY('h'):
case DEL_KEY:
@@ -672,7 +748,7 @@ int main(int argc, char *argv[]) {
initEditor();
if (argc >= 2) { editorOpen(argv[1]); }
- editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = quit");
+ editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = quit | Ctrl-F = find");
while (1) {
editorRefreshScreen();