Incremental search

This commit is contained in:
Timothy Warren 2019-08-20 15:36:54 -04:00
parent 827be306ef
commit be036bbee3

128
kilo.c
View File

@ -69,7 +69,7 @@ struct editorConfig E;
void editorSetStatusMessage(const char *fmt, ...);
void editorRefreshScreen();
char *editorPrompt(char *prompt);
char *editorPrompt(char *prompt, void (*callback)(char *, int));
/*** terminal ***/
@ -269,6 +269,27 @@ 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 += (KILO_TAB_STOP - 1) - (cur_rx % KILO_TAB_STOP);
}
cur_rx++;
if (cur_rx > rx)
{
return rx;
}
}
return cx;
}
void editorUpdateRow(erow *row)
{
int tabs = 0;
@ -501,7 +522,7 @@ 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");
@ -532,6 +553,87 @@ 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;
int i;
for (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 {
@ -735,7 +837,7 @@ void editorSetStatusMessage(const char *fmt, ...)
/*** input ***/
char *editorPrompt(char *prompt)
char *editorPrompt(char *prompt, void (*callback)(char *, int))
{
size_t bufsize = 128;
char *buf = malloc(bufsize);
@ -759,6 +861,10 @@ char *editorPrompt(char *prompt)
else if (c == '\x1b')
{
editorSetStatusMessage("");
if (callback)
{
callback(buf, c);
}
free(buf);
return NULL;
}
@ -767,6 +873,10 @@ char *editorPrompt(char *prompt)
if (buflen != 0)
{
editorSetStatusMessage("");
if (callback)
{
callback(buf, c);
}
return buf;
}
}
@ -780,6 +890,11 @@ char *editorPrompt(char *prompt)
buf[buflen++] = c;
buf[buflen] = '\0';
}
if (callback)
{
callback(buf, c);
}
}
}
@ -876,6 +991,10 @@ void editorProcessKeypress()
}
break;
case CTRL_KEY('f'):
editorFind();
break;
case BACKSPACE:
case CTRL_KEY('h'):
case DEL_KEY:
@ -962,7 +1081,8 @@ int main(int argc, char *argv[])
editorOpen(argv[1]);
}
editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = quit");
editorSetStatusMessage(
"HELP: Ctrl-S = save | Ctrl-Q = quit | Ctrl-F = find");
while (1)
{