lchat

A line oriented chat front end for ii.
git clone git://git.suckless.org/lchat
Log | Files | Refs | README

commit aa7afafc6710c68811bbc33d8b781edfa8c17109
parent 0c1a66c482d9ffa4e0e3f8fdb60aa1a02755da37
Author: Tom Schwindl <schwindl@posteo.de>
Date:   Fri,  9 Sep 2022 21:40:55 +0200

slackline: implement ctrl+w and ctrl+l

ctrl+w is part of the canonical line disciplines on most systems, thus
it is convenient to implement it.

ctrl+l is part of the emacs-mode, but generic and useful enough to be
implemented regardless of the current mode.

Additionally, we now check for control key combinations. This makes it
possible to ignore "invalid" key combinations. It also helps with the
implementation of an emacs-mode. Previously, pressing something like ctrl+f
would insert invisible characters, which is very irritating.

Last, it isn't weird that ctrl+u emits a NAK, since ctrl key combinations
map the letters A-Z to the ASCII codes 1-26. "u" is the 21. character in
the alphabet and NAK has the ASCII code 21.

Diffstat:
Mslackline.c | 63+++++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 43 insertions(+), 20 deletions(-)

diff --git a/slackline.c b/slackline.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -104,6 +104,30 @@ sl_postoptr(struct slackline *sl, size_t pos) return ptr; } +static void +sl_backspace(struct slackline *sl) +{ + char *ncur; + + if (sl->rcur == 0) + return; + + ncur = sl_postoptr(sl, sl->rcur - 1); + + if (sl->rcur < sl->rlen) + memmove(ncur, sl->ptr, sl->last - sl->ptr); + + sl->rcur--; + sl->rlen--; + sl->bcur = sl_postobyte(sl, sl->rcur); + sl->blen = sl_postobyte(sl, sl->rlen); + + sl->last -= sl->ptr - ncur; + *sl->last = '\0'; + + sl->ptr = ncur; +} + int sl_keystroke(struct slackline *sl, int key) { @@ -192,6 +216,9 @@ sl_keystroke(struct slackline *sl, int key) } } + if (!iscntrl((unsigned char) key)) + goto compose; + /* handle ctl keys */ switch (key) { case 27: /* Escape */ @@ -199,30 +226,26 @@ sl_keystroke(struct slackline *sl, int key) return 0; case 127: /* backspace */ case 8: /* backspace */ - if (sl->rcur == 0) - return 0; - - char *ncur = sl_postoptr(sl, sl->rcur - 1); - - if (sl->rcur < sl->rlen) - memmove(ncur, sl->ptr, sl->last - sl->ptr); - - sl->rcur--; - sl->rlen--; - sl->bcur = sl_postobyte(sl, sl->rcur); - sl->blen = sl_postobyte(sl, sl->rlen); - - sl->last -= sl->ptr - ncur; - *sl->last = '\0'; - - sl->ptr = ncur; - + sl_backspace(sl); return 0; - case 21: /* ctrl+u or clearline, weird that it's a NAK */ + case 21: /* ctrl+u -- clearline */ sl_reset(sl); return 0; + case 12: /* ctrl+l -- clear screen, same as clear(1) */ + printf("\x1b[2J\x1b[H"); + return 0; + case 23: /* ctrl+w -- erase previous word */ + while (sl->rcur != 0 && isspace((unsigned char) *(sl->ptr-1))) + sl_backspace(sl); + + while (sl->rcur != 0 && !isspace((unsigned char) *(sl->ptr-1))) + sl_backspace(sl); + return 0; + default: + return 0; } +compose: /* byte-wise composing of UTF-8 runes */ sl->ubuf[sl->ubuf_len++] = key; if (fullrune(sl->ubuf, sl->ubuf_len) == 0)