diff options
author | June McEnroe <june@causal.agency> | 2018-08-07 23:03:08 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2018-08-07 23:03:08 -0400 |
commit | 9114d0555cff0d11a8c744a1a6e323f7fd098228 (patch) | |
tree | b24c9ddac3e1e2b8bd6dfec4ad948c15811cceaf /ui.c | |
parent | Implement cycling tab complete (diff) | |
download | catgirl-9114d0555cff0d11a8c744a1a6e323f7fd098228.tar.gz catgirl-9114d0555cff0d11a8c744a1a6e323f7fd098228.zip |
Add tab complete UI
This definitely needs refactoring.
Diffstat (limited to 'ui.c')
-rw-r--r-- | ui.c | 95 |
1 files changed, 78 insertions, 17 deletions
diff --git a/ui.c b/ui.c index 7bcd461..3453242 100644 --- a/ui.c +++ b/ui.c @@ -369,26 +369,87 @@ static void enter(void) { line.end = line.buf; } +static struct { + wchar_t *word; + char *prefix; +} tab; + +static void accept(void) { + if (!tab.word) return; + tab.word = NULL; + free(tab.prefix); + tabAccept(); +} + +static void reject(void) { + if (!tab.word) return; + tab.word = NULL; + free(tab.prefix); + tabReject(); +} + +static void complete(void) { + if (!tab.word) { + wchar_t ch = *line.ptr; + *line.ptr = L'\0'; + tab.word = wcsrchr(line.buf, L' '); + tab.word = (tab.word ? &tab.word[1] : line.buf); + tab.prefix = awcstombs(tab.word); + if (!tab.prefix) err(EX_DATAERR, "awcstombs"); + *line.ptr = ch; + } + + const char *complete = tabNext(tab.prefix); + if (!complete) { + reject(); + return; + } + + wchar_t *wcs = ambstowcs(complete); + if (!wcs) err(EX_DATAERR, "ambstowcs"); + + size_t i; + for (i = 0; wcs[i] && line.ptr > &tab.word[i]; ++i) { + tab.word[i] = wcs[i]; + } + while (line.ptr > &tab.word[i]) { + backspace(); + } + for (; wcs[i]; ++i) { + insert(wcs[i]); + } + free(wcs); + + if (tab.word == line.buf) insert(L':'); + insert(L' '); +} + static void keyChar(wint_t ch) { switch (ch) { break; case CTRL('L'): uiRedraw(); - break; case CTRL('B'): left(); - break; case CTRL('F'): right(); - break; case CTRL('A'): home(); - break; case CTRL('E'): end(); - break; case CTRL('D'): delete(); - break; case CTRL('K'): kill(); - break; case '\b': backspace(); - break; case '\177': backspace(); - break; case '\n': enter(); - break; case CTRL('C'): insert(IRC_COLOR); - break; case CTRL('N'): insert(IRC_RESET); - break; case CTRL('O'): insert(IRC_BOLD); - break; case CTRL('R'): insert(IRC_COLOR); - break; case CTRL('T'): insert(IRC_ITALIC); - break; case CTRL('U'): insert(IRC_UNDERLINE); - break; case CTRL('V'): insert(IRC_REVERSE); - break; default: if (iswprint(ch)) insert(ch); + break; case CTRL('B'): reject(); left(); + break; case CTRL('F'): reject(); right(); + break; case CTRL('A'): reject(); home(); + break; case CTRL('E'): reject(); end(); + break; case CTRL('D'): reject(); delete(); + break; case CTRL('K'): reject(); kill(); + break; case L'\b': reject(); backspace(); + break; case L'\177': reject(); backspace(); + break; case L'\t': complete(); + break; case L'\n': accept(); enter(); + break; case CTRL('C'): accept(); insert(IRC_COLOR); + break; case CTRL('N'): accept(); insert(IRC_RESET); + break; case CTRL('O'): accept(); insert(IRC_BOLD); + break; case CTRL('R'): accept(); insert(IRC_COLOR); + break; case CTRL('T'): accept(); insert(IRC_ITALIC); + break; case CTRL('U'): accept(); insert(IRC_UNDERLINE); + break; case CTRL('V'): accept(); insert(IRC_REVERSE); + break; default: { + if (iswprint(ch)) { + accept(); + insert(ch); + } + } } } |