diff options
| author | C. McEnroe | 2020-02-09 02:33:53 -0500 | 
|---|---|---|
| committer | C. McEnroe | 2020-02-09 02:33:53 -0500 | 
| commit | 40e362f505b2b48656791b25193d67ff4af9a11b (patch) | |
| tree | 86a163ab771a5008c52103729099375f82f62b78 | |
| parent | 82cf44585831ea5a237f3b603a9d8ffd2d350b54 (diff) | |
Hook up tab-complete
| -rw-r--r-- | edit.c | 85 | 
1 files changed, 82 insertions, 3 deletions
| @@ -60,7 +60,78 @@ static void delete(size_t index, size_t 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) { +	size_t init = pos;  	switch (op) {  		break; case EditHome:  pos = 0;  		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;  		}  		break; case EditComplete: { -			// TODO +			tabComplete(id); +			return;  		}  		break; case EditEnter: { -			pos = 0; +			tabAccept();  			command(id, editBuffer(NULL)); -			len = 0; +			len = pos = 0; +			return;  		}  	} + +	if (pos < init) { +		tabReject(); +	} else { +		tabAccept(); +	}  } | 
