summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJune McEnroe2022-03-16 20:18:54 -0400
committerJune McEnroe2022-03-16 20:21:00 -0400
commit714b4bc76a239a7802715f13104cdcafa1020e7c (patch)
treea91f1a69bca57a8aaa12257c64e8b28e8e07cc63
parent1f9e3463c323056c2020e7dec573ea0e8a83d4a1 (diff)
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.
-rw-r--r--edit.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/edit.c b/edit.c
index bb92edf..effb623 100644
--- a/edit.c
+++ b/edit.c
@@ -105,13 +105,29 @@ int editDelete(struct Edit *e, bool cut, size_t index, size_t count) {
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 ret = 0;
switch (fn) {
break; case EditHead: e->pos = 0;
break; case EditTail: e->pos = e->len;
- break; case EditPrev: if (e->pos) e->pos--;
- break; case EditNext: if (e->pos < e->len) e->pos++;
+ break; case EditPrev: e->pos = prevSpacing(e, e->pos);
+ break; case EditNext: e->pos = nextSpacing(e, e->pos);
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--;
@@ -129,10 +145,12 @@ int editFn(struct Edit *e, enum EditFn fn) {
ret = editDelete(e, true, e->pos, e->len - e->pos);
}
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: {
- editDelete(e, false, e->pos, 1);
+ editDelete(e, false, e->pos, nextSpacing(e, e->pos) - e->pos);
}
break; case EditDeletePrevWord: {
if (!e->pos) break;