summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2024-02-12 16:28:37 +0100
committerAlbert Cervin <albert@acervin.com>2024-02-14 13:08:51 +0100
commit0b524a94a5e34148716832f1b6cada02e35369b0 (patch)
treec0b31aab359c2bac7300a3c95a2f50ee62572048
parent7baa6f58d4fe8b00ec5ee7dd72a8cb32ef52c079 (diff)
downloaddged-0b524a94a5e34148716832f1b6cada02e35369b0.tar.gz
dged-0b524a94a5e34148716832f1b6cada02e35369b0.tar.xz
dged-0b524a94a5e34148716832f1b6cada02e35369b0.zip
Improve word deletion
Now it only deletes the word under dot.
-rw-r--r--src/dged/buffer.c19
-rw-r--r--src/dged/buffer.h11
-rw-r--r--src/dged/buffer_view.c17
-rw-r--r--src/dged/buffer_view.h3
-rw-r--r--src/main/bindings.c1
-rw-r--r--src/main/cmds.c6
-rw-r--r--test/buffer.c33
7 files changed, 70 insertions, 20 deletions
diff --git a/src/dged/buffer.c b/src/dged/buffer.c
index a512c60..749dba7 100644
--- a/src/dged/buffer.c
+++ b/src/dged/buffer.c
@@ -328,6 +328,11 @@ static struct match_result find_prev_in_line(struct buffer *buffer,
--bytei;
}
+ // first byte on line can also be a match
+ if (predicate(line.text[bytei])) {
+ found = true;
+ }
+
uint32_t target_col = text_byteindex_to_col(buffer->text, start.line, bytei);
return (struct match_result){
.at = (struct location){.line = start.line, .col = target_col},
@@ -595,6 +600,20 @@ struct location buffer_next_char(struct buffer *buffer, struct location dot) {
return dot;
}
+struct region buffer_word_at(struct buffer *buffer, struct location at) {
+ struct match_result prev_word_break =
+ find_prev_in_line(buffer, at, is_word_break);
+ struct match_result next_word_break =
+ find_next_in_line(buffer, at, is_word_break);
+
+ if (prev_word_break.at.col != next_word_break.at.col &&
+ prev_word_break.found) {
+ moveh(buffer, 1, &prev_word_break.at);
+ }
+
+ return region_new(prev_word_break.at, next_word_break.at);
+}
+
struct location buffer_next_word(struct buffer *buffer, struct location dot) {
struct match_result res = find_next_in_line(buffer, dot, is_word_break);
if (!res.found) {
diff --git a/src/dged/buffer.h b/src/dged/buffer.h
index 2e71fb3..3cb8d03 100644
--- a/src/dged/buffer.h
+++ b/src/dged/buffer.h
@@ -245,6 +245,17 @@ struct location buffer_next_word(struct buffer *buffer, struct location dot);
struct location buffer_next_line(struct buffer *buffer, struct location dot);
/**
+ * Get the extents of the word located at @ref at.
+ *
+ * @param [in] buffer The buffer to look in.
+ * @param [in] at The location to start from.
+ *
+ * @returns The extent of the closest word as a region. If
+ * there is no word, the region will be zero-sized.
+ */
+struct region buffer_word_at(struct buffer *buffer, struct location at);
+
+/**
* Clamp a buffer position to the boundaries of the buffer.
*
* Note that both @ref line and @ref col can be negative or bigger than the
diff --git a/src/dged/buffer_view.c b/src/dged/buffer_view.c
index aeee2f6..15aa812 100644
--- a/src/dged/buffer_view.c
+++ b/src/dged/buffer_view.c
@@ -186,24 +186,17 @@ void buffer_view_backward_delete_char(struct buffer_view *view) {
region_new(buffer_previous_char(view->buffer, view->dot), view->dot));
}
-void buffer_view_forward_delete_word(struct buffer_view *view) {
+void buffer_view_delete_word(struct buffer_view *view) {
if (maybe_delete_region(view)) {
return;
}
- view->dot = buffer_delete(
- view->buffer,
- region_new(view->dot, buffer_next_word(view->buffer, view->dot)));
-}
+ struct region word = buffer_word_at(view->buffer, view->dot);
-void buffer_view_backward_delete_word(struct buffer_view *view) {
- if (maybe_delete_region(view)) {
- return;
+ if (region_has_size(word)) {
+ buffer_delete(view->buffer, word);
+ view->dot = word.begin;
}
-
- view->dot = buffer_delete(
- view->buffer,
- region_new(buffer_previous_word(view->buffer, view->dot), view->dot));
}
void buffer_view_kill_line(struct buffer_view *view) {
diff --git a/src/dged/buffer_view.h b/src/dged/buffer_view.h
index 1c8fa6a..620c261 100644
--- a/src/dged/buffer_view.h
+++ b/src/dged/buffer_view.h
@@ -62,8 +62,7 @@ void buffer_view_backward_nlines(struct buffer_view *view, uint32_t nlines);
void buffer_view_forward_delete_char(struct buffer_view *view);
void buffer_view_backward_delete_char(struct buffer_view *view);
-void buffer_view_forward_delete_word(struct buffer_view *view);
-void buffer_view_backward_delete_word(struct buffer_view *view);
+void buffer_view_delete_word(struct buffer_view *view);
void buffer_view_kill_line(struct buffer_view *view);
diff --git a/src/main/bindings.c b/src/main/bindings.c
index ad63974..9038f37 100644
--- a/src/main/bindings.c
+++ b/src/main/bindings.c
@@ -55,7 +55,6 @@ void set_default_buffer_bindings(struct keymap *keymap) {
BINDING(DELETE, "delete-char"),
BINDING(Ctrl, 'D', "delete-char"),
BINDING(Meta, 'd', "delete-word"),
- BINDING(Meta, 'D', "backward-delete-word"),
BINDING(BACKSPACE, "backward-delete-char"),
BINDING(Ctrl, '@', "set-mark"),
diff --git a/src/main/cmds.c b/src/main/cmds.c
index 838f2ea..e24643e 100644
--- a/src/main/cmds.c
+++ b/src/main/cmds.c
@@ -404,8 +404,7 @@ BUFFER_WRAPCMD(reload);
BUFFER_VIEW_WRAPCMD(kill_line);
BUFFER_VIEW_WRAPCMD(forward_delete_char);
BUFFER_VIEW_WRAPCMD(backward_delete_char);
-BUFFER_VIEW_WRAPCMD(forward_delete_word);
-BUFFER_VIEW_WRAPCMD(backward_delete_word);
+BUFFER_VIEW_WRAPCMD(delete_word);
BUFFER_VIEW_WRAPCMD(backward_char);
BUFFER_VIEW_WRAPCMD(backward_word);
BUFFER_VIEW_WRAPCMD(forward_char);
@@ -475,8 +474,7 @@ static int32_t insert_tab(struct command_ctx ctx, int argc,
void register_buffer_commands(struct commands *commands) {
static struct command buffer_commands[] = {
{.name = "kill-line", .fn = kill_line_cmd},
- {.name = "delete-word", .fn = forward_delete_word_cmd},
- {.name = "backward-delete-word", .fn = backward_delete_word_cmd},
+ {.name = "delete-word", .fn = delete_word_cmd},
{.name = "delete-char", .fn = forward_delete_char_cmd},
{.name = "backward-delete-char", .fn = backward_delete_char_cmd},
{.name = "backward-char", .fn = backward_char_cmd},
diff --git a/test/buffer.c b/test/buffer.c
index 19fca8c..f4aefc5 100644
--- a/test/buffer.c
+++ b/test/buffer.c
@@ -17,4 +17,35 @@ void test_add() {
"Expected buffer to have one line with characters");
}
-void run_buffer_tests() { run_test(test_add); }
+void test_word_at() {
+ struct buffer b = buffer_create("test-word-at-buffer");
+ const char *txt = "word1 (word2). Another";
+ buffer_add(&b, (struct location){.line = 0, .col = 0}, (uint8_t *)txt,
+ strlen(txt));
+
+ struct region word1 =
+ buffer_word_at(&b, (struct location){.line = 0, .col = 0});
+ ASSERT(region_has_size(word1), "expected 0,0 to be a word");
+ ASSERT(word1.begin.col == 0 && word1.end.col == 5,
+ "Expected word to end at col 5");
+
+ // test that dot can be in the middle of a word
+ // and that '(' and ')' works as a delimiter
+ struct region word2 =
+ buffer_word_at(&b, (struct location){.line = 0, .col = 8});
+ ASSERT(region_has_size(word2), "expected 0,8 to be in a word");
+ ASSERT(word2.begin.col == 7 && word2.end.col == 12,
+ "Expected word to span cols 7..12");
+
+ // test that clamping works correctly
+ struct region word3 =
+ buffer_word_at(&b, (struct location){.line = 0, .col = 100});
+ ASSERT(region_has_size(word3), "expected 0,100 to be in the last word");
+ ASSERT(word3.begin.col == 15 && word3.end.col == 22,
+ "Expected word to span cols 15..22");
+}
+
+void run_buffer_tests() {
+ run_test(test_add);
+ run_test(test_word_at);
+}