Skip non-spacing when moving and deleting by "character"

I uh... don't think I can write tests for this, since macOS's wcwidth
is notoriously useless.
master
June McEnroe 2022-03-16 20:18:54 -04:00
parent 1f9e3463c3
commit 714b4bc76a
1 changed files with 22 additions and 4 deletions

26
edit.c
View File

@ -105,13 +105,29 @@ int editDelete(struct Edit *e, bool cut, size_t index, size_t count) {
return 0; return 0;
} }
static size_t prevSpacing(const struct Edit *e, size_t pos) {
if (!pos) return 0;
do {
pos--;
} while (pos && !wcwidth(e->buf[pos]));
return pos;
}
static size_t nextSpacing(const struct Edit *e, size_t pos) {
if (pos == e->len) return e->len;
do {
pos++;
} while (pos < e->len && !wcwidth(e->buf[pos]));
return pos;
}
int editFn(struct Edit *e, enum EditFn fn) { int editFn(struct Edit *e, enum EditFn fn) {
int ret = 0; int ret = 0;
switch (fn) { switch (fn) {
break; case EditHead: e->pos = 0; break; case EditHead: e->pos = 0;
break; case EditTail: e->pos = e->len; break; case EditTail: e->pos = e->len;
break; case EditPrev: if (e->pos) e->pos--; break; case EditPrev: e->pos = prevSpacing(e, e->pos);
break; case EditNext: if (e->pos < e->len) e->pos++; break; case EditNext: e->pos = nextSpacing(e, e->pos);
break; case EditPrevWord: { break; case EditPrevWord: {
while (e->pos && !isword(e->buf[e->pos-1])) e->pos--; while (e->pos && !isword(e->buf[e->pos-1])) e->pos--;
while (e->pos && isword(e->buf[e->pos-1])) e->pos--; while (e->pos && isword(e->buf[e->pos-1])) e->pos--;
@ -129,10 +145,12 @@ int editFn(struct Edit *e, enum EditFn fn) {
ret = editDelete(e, true, e->pos, e->len - e->pos); ret = editDelete(e, true, e->pos, e->len - e->pos);
} }
break; case EditDeletePrev: { break; case EditDeletePrev: {
if (e->pos) editDelete(e, false, --e->pos, 1); size_t prev = prevSpacing(e, e->pos);
editDelete(e, false, prev, e->pos - prev);
e->pos = prev;
} }
break; case EditDeleteNext: { break; case EditDeleteNext: {
editDelete(e, false, e->pos, 1); editDelete(e, false, e->pos, nextSpacing(e, e->pos) - e->pos);
} }
break; case EditDeletePrevWord: { break; case EditDeletePrevWord: {
if (!e->pos) break; if (!e->pos) break;