# HG changeset patch # User Matti Hamalainen # Date 1287945527 -10800 # Node ID 2a53156e7e12b9bc9dc6379bc9c54a3317097835 # Parent c4865ac2386c27ae325066ee131536449aca2364 Yay, tab-completion cycling now works (except for usernames with whitespaces, of course ...) diff -r c4865ac2386c -r 2a53156e7e12 nnchat.c --- a/nnchat.c Sun Oct 24 21:38:17 2010 +0300 +++ b/nnchat.c Sun Oct 24 21:38:47 2010 +0300 @@ -641,55 +641,85 @@ return TRUE; } -void performTabCompletion(nn_editbuf_t *buf) +/* +Different tab completion scenarios: + +Line start +"foo" -> + * store "foo" as pattern + * find match: "Foobar" + * replace "foo" with match + +"Foobar: " -> + * ": " -> cycle to next match + * "Foorulez" + * replace "Foobar: " with "Foorulez: " + +Same when completing in middle of line, but " " instead of ": ". +*/ +BOOL performTabCompletion(nn_editbuf_t *buf) { static char *previous = NULL; - static char *matsi = NULL; - char *b = buf->data; - ssize_t pos2 = 0, pos1 = buf->pos; - - if (pos1 > 0) pos1--; + static char *pattern = NULL; + int mode = 0; + char *str = buf->data; + ssize_t endPos = 0, startPos = buf->pos; - if (pos1 > 0 && b[pos1 - 1] == ':') { - pos1 -= 2; - pos2 = pos1; - while (pos1 > 0 && b[pos1 - 1] != ' ') pos1--; + if (startPos > 1 && str[startPos - 1] == ' ') { + startPos -= 2; + if (str[startPos] == ':') + startPos--; + if (startPos <= 0 || str[startPos] == ' ') + return FALSE; + endPos = startPos; + while (startPos > 0 && str[startPos - 1] != ' ') startPos--; + mode = 1; } else - if (b[pos1] != ' ' && b[pos1] != ':') { - pos2 = pos1; - while (pos1 > 0 && b[pos1 - 1] != ' ') pos1--; - while (pos2 < buf->len && b[pos2] != ' ') pos2++; - while (pos2 > 0 && b[pos2] == ' ') pos2--; - th_free(matsi); - matsi = nn_editbuf_get_string(buf, pos1, pos2); + if (str[startPos - 1] != ' ' && (startPos == buf->len || str[startPos] == ' ')) { + endPos = startPos; + while (startPos > 0 && str[startPos - 1] != ' ') startPos--; + while (endPos < buf->len && str[endPos] != ' ') endPos++; + while (endPos > 0 && str[endPos] == ' ') endPos--; + if (str[endPos] == ':') + return FALSE; + th_free(pattern); + pattern = nn_editbuf_get_string(buf, startPos, endPos); th_free(previous); previous = NULL; - } + mode = 2; + } +// printMsg("%d, %d <-> %d : '%s' (%d)\n", startPos, endPos, buf->len, pattern, mode); - if (matsi) { - nn_user_t *user = nn_user_match(nnUsers, matsi, previous); -// printMsg("pattern '%s'\n", matsi); + if (pattern) { + nn_user_t *user = nn_user_match(nnUsers, pattern, previous); if (user) { int i; char *c = user->name; // printMsg("match '%s'\n", user->name); - for (i = pos1; i <= pos2; i++) - nn_editbuf_delete(buf, pos1); + for (i = startPos; i <= endPos; i++) + nn_editbuf_delete(buf, startPos); - for (i = pos1; *c; i++, c++) + for (i = startPos; *c; i++, c++) nn_editbuf_insert(buf, i, *c); if (previous == NULL) { - nn_editbuf_insert(buf, i+1, ':'); - nn_editbuf_insert(buf, i+2, ' '); + if (startPos == 0) { + nn_editbuf_insert(buf, i++, ':'); + startPos++; + } + nn_editbuf_insert(buf, i++, ' '); } - nn_editbuf_setpos(buf, pos1 + 2 + strlen(user->name)); + nn_editbuf_setpos(buf, startPos + 2 + strlen(user->name)); th_free(previous); previous = th_strdup(user->name); + + return TRUE; } } + + return FALSE; } int main(int argc, char *argv[])