multi responce find feature
This commit is contained in:
1 file changed
+81
-5
@@ -73,7 +73,7 @@ struct editorConfig E;
|
||||
|
||||
void editorSetStatusMessage(const char* fmt, ...);
|
||||
void editorRefreshScreen();
|
||||
char *editorPrompt(const char *prompt);
|
||||
char *editorPrompt(const char *prompt, void (*callback)(char *, int));
|
||||
|
||||
/*** terminal ***/
|
||||
|
||||
@@ -208,6 +208,19 @@ int editorRowCxToRx(erow *row, int cx) {
|
||||
return rx;
|
||||
}
|
||||
|
||||
int editorRowRxToCx(erow *row, int rx) {
|
||||
int cur_rx = 0;
|
||||
int cx;
|
||||
for (cx = 0; cx < row->size; cx++) {
|
||||
if (row->chars[cx] == '\t')
|
||||
cur_rx += (LEVEL_TAB_STOP - 1) - (cur_rx % LEVEL_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++) {
|
||||
@@ -359,7 +372,7 @@ char* editorRowsToString(int* buflen) {
|
||||
|
||||
void editorOpen(char *filename) {
|
||||
free(E.filename);
|
||||
E.filename = strdup(filename);
|
||||
E.filename = strdup(filename);
|
||||
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if (!fp) die("fopen");
|
||||
@@ -380,7 +393,7 @@ E.filename = strdup(filename);
|
||||
|
||||
void editorSave() {
|
||||
if (E.filename == NULL) {
|
||||
E.filename = editorPrompt("Save as: %s (ESC) to cancel");
|
||||
E.filename = editorPrompt("Save as: %s (ESC) to cancel", NULL);
|
||||
if (E.filename == NULL) {
|
||||
editorSetStatusMessage("Save aborted");
|
||||
return;
|
||||
@@ -408,6 +421,61 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
free(query);
|
||||
}
|
||||
|
||||
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 (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 {
|
||||
@@ -536,7 +604,7 @@ void editorSetStatusMessage(const char* fmt, ...) {
|
||||
|
||||
/*** input ***/
|
||||
|
||||
char *editorPrompt(const char* prompt) {
|
||||
char *editorPrompt(const char* prompt, void (*callback)(char *, int)) {
|
||||
size_t bufsize = 128;
|
||||
char* buf = (char*)malloc(bufsize);
|
||||
|
||||
@@ -553,11 +621,13 @@ char *editorPrompt(const char* prompt) {
|
||||
if (buflen != 0) buf[--buflen] = '\0';
|
||||
} else if (c == ESCAPE_CONST) {
|
||||
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) {
|
||||
@@ -568,6 +638,8 @@ char *editorPrompt(const char* prompt) {
|
||||
buf[buflen++] = c;
|
||||
buf[buflen] = '\0';
|
||||
}
|
||||
|
||||
if (callback) callback(buf, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,6 +701,10 @@ 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:
|
||||
@@ -694,7 +770,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();
|
||||
|
||||
Reference in new issue
Block a user