Hook up tab-complete

weechat-hashes
C. McEnroe 2020-02-09 02:33:53 -05:00
parent 82cf445858
commit 40e362f505
1 changed files with 82 additions and 3 deletions

85
edit.c
View File

@ -60,7 +60,78 @@ static void delete(size_t index, size_t count) {
len -= count; len -= count;
} }
static struct {
size_t pos;
size_t pre;
size_t len;
} tab;
static void tabComplete(size_t id) {
if (!tab.len) {
tab.pos = pos;
while (tab.pos && buf[tab.pos - 1] != L' ') tab.pos--;
if (tab.pos == pos) return;
tab.pre = pos - tab.pos;
tab.len = tab.pre;
}
char mbs[MB_LEN_MAX * tab.pre + 1];
const wchar_t *ptr = &buf[tab.pos];
size_t n = wcsnrtombs(mbs, &ptr, tab.pre, sizeof(mbs) - 1, NULL);
assert(n != (size_t)-1);
mbs[n] = '\0';
const char *comp = complete(id, mbs);
if (!comp) comp = complete(id, mbs);
if (!comp) {
tab.len = 0;
return;
}
wchar_t wcs[strlen(comp) + 1];
n = mbstowcs(wcs, comp, sizeof(wcs));
assert(n != (size_t)-1);
if (tab.pos + n + 2 > Cap) {
completeReject();
tab.len = 0;
return;
}
delete(tab.pos, tab.len);
if (wcs[0] != L'/' && !tab.pos) {
tab.len = n + 2;
reserve(tab.pos, tab.len);
buf[tab.pos + n + 0] = L':';
buf[tab.pos + n + 1] = L' ';
} else if (
tab.pos >= 2 && (buf[tab.pos - 2] == L':' || buf[tab.pos - 2] == L',')
) {
tab.len = n + 2;
reserve(tab.pos, tab.len);
buf[tab.pos - 2] = L',';
buf[tab.pos + n + 0] = L':';
buf[tab.pos + n + 1] = L' ';
} else {
tab.len = n + 1;
reserve(tab.pos, tab.len);
buf[tab.pos + n] = L' ';
}
memcpy(&buf[tab.pos], wcs, sizeof(*wcs) * n);
pos = tab.pos + tab.len;
}
static void tabAccept(void) {
completeAccept();
tab.len = 0;
}
static void tabReject(void) {
completeReject();
tab.len = 0;
}
void edit(size_t id, enum Edit op, wchar_t ch) { void edit(size_t id, enum Edit op, wchar_t ch) {
size_t init = pos;
switch (op) { switch (op) {
break; case EditHome: pos = 0; break; case EditHome: pos = 0;
break; case EditEnd: pos = len; break; case EditEnd: pos = len;
@ -75,12 +146,20 @@ void edit(size_t id, enum Edit op, wchar_t ch) {
if (pos < Cap) buf[pos++] = ch; if (pos < Cap) buf[pos++] = ch;
} }
break; case EditComplete: { break; case EditComplete: {
// TODO tabComplete(id);
return;
} }
break; case EditEnter: { break; case EditEnter: {
pos = 0; tabAccept();
command(id, editBuffer(NULL)); command(id, editBuffer(NULL));
len = 0; len = pos = 0;
return;
} }
} }
if (pos < init) {
tabReject();
} else {
tabAccept();
}
} }