tMake marks work with selections and motion callbacks - ledit - Text editor (WI… | |
git clone git://lumidify.org/ledit.git (fast, but not encrypted) | |
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow) | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 91a730677ac95f922d6e5bca531f9cf0811e0fd6 | |
parent 61c47698d180e2e9e81df98c5ac9d7304594a95b | |
Author: lumidify <[email protected]> | |
Date: Thu, 11 Nov 2021 00:02:36 +0100 | |
Make marks work with selections and motion callbacks | |
Diffstat: | |
M buffer.c | 43 ++++++++++++++++++++++++++++++ | |
M buffer.h | 13 +++++++++++++ | |
M keys_basic.c | 74 +++++++++++++++++++++++++++++… | |
M keys_basic_config.h | 4 ++-- | |
M keys_command.c | 80 +----------------------------… | |
M keys_command.h | 4 +--- | |
M keys_command_config.h | 6 +----- | |
7 files changed, 131 insertions(+), 93 deletions(-) | |
--- | |
diff --git a/buffer.c b/buffer.c | |
t@@ -52,6 +52,47 @@ ledit_buffer_set_mode(ledit_buffer *buffer, enum ledit_mode… | |
ledit_change_mode_group(buffer->undo); | |
} | |
+static void | |
+marklist_destroy(ledit_buffer_marklist *marklist) { | |
+ for (size_t i = 0; i < marklist->len; i++) { | |
+ free(marklist->marks[i].text); | |
+ } | |
+ free(marklist->marks); | |
+ free(marklist); | |
+} | |
+ | |
+void | |
+ledit_buffer_insert_mark(ledit_buffer *buffer, char *mark, int len, int line, … | |
+ ledit_buffer_marklist *marklist = buffer->marklist; | |
+ for (size_t i = 0; i < marklist->len; i++) { | |
+ if (!strncmp(mark, marklist->marks[i].text, len)) { | |
+ marklist->marks[i].line = line; | |
+ marklist->marks[i].byte = byte; | |
+ return; | |
+ } | |
+ } | |
+ if (marklist->len == marklist->alloc) { | |
+ size_t new_alloc = marklist->alloc > 0 ? marklist->alloc * 2 :… | |
+ marklist->marks = ledit_realloc( | |
+ marklist->marks, new_alloc * sizeof(ledit_buffer_mark) | |
+ ); | |
+ marklist->alloc = new_alloc; | |
+ } | |
+ ledit_buffer_mark *m = &marklist->marks[marklist->len]; | |
+ m->text = ledit_strndup(mark, len); | |
+ m->line = line; | |
+ m->byte = byte; | |
+ marklist->len++; | |
+} | |
+ | |
+static ledit_buffer_marklist * | |
+marklist_create(void) { | |
+ ledit_buffer_marklist *marklist = ledit_malloc(sizeof(ledit_buffer_mar… | |
+ marklist->len = marklist->alloc = 0; | |
+ marklist->marks = NULL; | |
+ return marklist; | |
+} | |
+ | |
ledit_buffer * | |
ledit_buffer_create(ledit_common *common, ledit_theme *theme, ledit_window *wi… | |
if (basic_attrs == NULL) { | |
t@@ -85,6 +126,7 @@ ledit_buffer_create(ledit_common *common, ledit_theme *them… | |
buffer->cache = ledit_cache_create(common); | |
buffer->undo = ledit_undo_stack_create(); | |
buffer->theme = theme; | |
+ buffer->marklist = marklist_create(); | |
ledit_window_set_scroll_callback(window, &ledit_buffer_scroll_handler,… | |
ledit_window_set_button_callback(window, &ledit_buffer_button_handler,… | |
t@@ -182,6 +224,7 @@ ledit_buffer_destroy(ledit_buffer *buffer) { | |
free(buffer->lines); | |
if (buffer->filename) | |
free(buffer->filename); | |
+ marklist_destroy(buffer->marklist); | |
free(buffer); | |
} | |
diff --git a/buffer.h b/buffer.h | |
t@@ -18,6 +18,17 @@ typedef struct { | |
char h_dirty; /* whether height needs to be recalculated still */ | |
} ledit_line; | |
+typedef struct { | |
+ char *text; | |
+ int line; | |
+ int byte; | |
+} ledit_buffer_mark; | |
+ | |
+typedef struct { | |
+ size_t len, alloc; | |
+ ledit_buffer_mark *marks; | |
+} ledit_buffer_marklist; | |
+ | |
/* TODO: advisory lock on file? also check if modification date changed before… | |
struct ledit_buffer { | |
ledit_common *common; /* common stuff, e.g. display, window, etc. */ | |
t@@ -39,6 +50,7 @@ struct ledit_buffer { | |
ledit_cache *cache; | |
ledit_undo_stack *undo; | |
ledit_window *window; | |
+ ledit_buffer_marklist *marklist; | |
}; | |
ledit_buffer *ledit_buffer_create(ledit_common *common, ledit_theme *theme, le… | |
t@@ -159,3 +171,4 @@ void ledit_buffer_scroll_to_pos_bottom(ledit_buffer *buffe… | |
/* FIXME: just make generic sort range */ | |
void ledit_buffer_sort_selection(int *line1, int *byte1, int *line2, int *byte… | |
int ledit_line_next_non_whitespace(ledit_line *line, int byte); | |
+void ledit_buffer_insert_mark(ledit_buffer *buffer, char *mark, int len, int l… | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -1836,14 +1836,80 @@ enter_searchedit_backward(ledit_buffer *buffer, char *… | |
return (struct action){ACTION_GRABKEY, &ledit_command_key_handler}; | |
} | |
+/* FIXME: differentiate between jumping to line and index like nvi */ | |
+static struct action | |
+mark_line_cb(ledit_buffer *buffer, char *text, int len) { | |
+ grab_char_cb = NULL; | |
+ ledit_buffer_insert_mark( | |
+ buffer, text, len, buffer->cur_line, buffer->cur_index | |
+ ); | |
+ return (struct action){ACTION_NONE, NULL}; | |
+} | |
+ | |
+/* FIXME: check that byte is actually in at grapheme boundary */ | |
+static struct action | |
+jump_to_mark_cb(ledit_buffer *buffer, char *text, int len) { | |
+ grab_char_cb = NULL; | |
+ ledit_buffer_marklist *marklist = buffer->marklist; | |
+ motion_callback cb; | |
+ int num = get_key_repeat_and_motion_cb(&cb); | |
+ if (num > 0) | |
+ return err_invalid_key(buffer); | |
+ int line = -1, index = -1; | |
+ for (size_t i = 0; i < marklist->len; i++) { | |
+ if (!strncmp(text, marklist->marks[i].text, len)) { | |
+ ledit_line *ll; | |
+ ledit_buffer_mark *m = &marklist->marks[i]; | |
+ if (m->line >= buffer->lines_num) { | |
+ line = buffer->lines_num - 1; | |
+ ll = ledit_buffer_get_line(buffer, line); | |
+ index = ll->len; | |
+ } else { | |
+ line = m->line; | |
+ ll = ledit_buffer_get_line(buffer, m->line); | |
+ if (m->byte >= ll->len) | |
+ index = ll->len; | |
+ else | |
+ index = m->byte; | |
+ } | |
+ break; | |
+ } | |
+ } | |
+ if (line == -1) | |
+ return err_invalid_key(buffer); | |
+ if (buffer->common->mode == VISUAL) { | |
+ ledit_buffer_set_selection( | |
+ buffer, buffer->sel.line1, buffer->sel.byte1, line, index | |
+ ); | |
+ buffer->cur_line = line; | |
+ buffer->cur_index = index; | |
+ } else { | |
+ if (cb) { | |
+ cb(buffer, line, index, KEY_MOTION_LINE); | |
+ } else { | |
+ ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cu… | |
+ buffer->cur_line = line; | |
+ buffer->cur_index = index; | |
+ buffer->cur_index = ledit_buffer_get_legal_normal_pos( | |
+ buffer, buffer->cur_line, buffer->cur_index | |
+ ); | |
+ ledit_buffer_set_line_cursor_attrs( | |
+ buffer, buffer->cur_line, buffer->cur_index | |
+ ); | |
+ discard_repetition_stack(); | |
+ } | |
+ } | |
+ return (struct action){ACTION_NONE, NULL}; | |
+} | |
+ | |
static struct action | |
mark_line(ledit_buffer *buffer, char *text, int len) { | |
(void)buffer; | |
(void)text; | |
(void)len; | |
- ledit_command_set_type(CMD_MARKLINE); | |
+ grab_char_cb = &mark_line_cb; | |
discard_repetition_stack(); | |
- return (struct action){ACTION_GRABKEY, &ledit_command_key_handler}; | |
+ return (struct action){ACTION_NONE, NULL}; | |
} | |
static struct action | |
t@@ -1851,9 +1917,9 @@ jump_to_mark(ledit_buffer *buffer, char *text, int len) { | |
(void)buffer; | |
(void)text; | |
(void)len; | |
- ledit_command_set_type(CMD_JUMPTOMARK); | |
+ grab_char_cb = &jump_to_mark_cb; | |
discard_repetition_stack(); | |
- return (struct action){ACTION_GRABKEY, &ledit_command_key_handler}; | |
+ return (struct action){ACTION_NONE, NULL}; | |
} | |
/* FIXME: support visual mode, i.e. change selection to new place? */ | |
diff --git a/keys_basic_config.h b/keys_basic_config.h | |
t@@ -169,8 +169,8 @@ static struct key keys_en[] = { | |
{"a", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_after_cursor}, | |
{"O", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_line_above}, | |
{"o", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_line_below}, | |
- {"m", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &mark_line}, | |
- {"'", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &jump_to_mark}, | |
+ {"m", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &mark_line}, | |
+ {"'", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &jump_to_mark}, | |
{"C", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &change_to_eol}, | |
{"D", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &delete_to_eol}, | |
{"r", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &replace}, | |
diff --git a/keys_command.c b/keys_command.c | |
t@@ -30,87 +30,9 @@ | |
/* this must first be set by caller before jumping to key handler */ | |
static enum ledit_command_type cur_type; | |
-struct mark { | |
- char *text; | |
- int line; | |
- int byte; | |
-}; | |
- | |
-/* FIXME: this should be part of buffer! */ | |
-struct { | |
- size_t len, alloc; | |
- struct mark *marks; | |
-} marklist = {0, 0, NULL}; | |
- | |
void | |
command_key_cleanup(void) { | |
- for (size_t i = 0; i < marklist.len; i++) { | |
- free(marklist.marks[i].text); | |
- } | |
- free(marklist.marks); | |
-} | |
- | |
-static void | |
-insert_mark(char *mark, int len, int line, int byte) { | |
- for (size_t i = 0; i < marklist.len; i++) { | |
- if (!strncmp(mark, marklist.marks[i].text, len)) { | |
- marklist.marks[i].line = line; | |
- marklist.marks[i].byte = byte; | |
- return; | |
- } | |
- } | |
- if (marklist.len == marklist.alloc) { | |
- size_t new_alloc = marklist.alloc > 0 ? marklist.alloc * 2 : 4; | |
- marklist.marks = ledit_realloc( | |
- marklist.marks, new_alloc * sizeof(struct mark) | |
- ); | |
- marklist.alloc = new_alloc; | |
- } | |
- struct mark *m = &marklist.marks[marklist.len]; | |
- m->text = ledit_strndup(mark, len); | |
- m->line = line; | |
- m->byte = byte; | |
- marklist.len++; | |
-} | |
- | |
-/* FIXME: differentiate between jumping to line and index like nvi */ | |
-static int | |
-mark_line(ledit_buffer *buffer, char *key_text, int len) { | |
- insert_mark(key_text, len, buffer->cur_line, buffer->cur_index); | |
- return 0; | |
-} | |
- | |
-/* FIXME: check that byte is actually in at grapheme boundary */ | |
-/* FIXME: make this work with selections! */ | |
-static int | |
-jump_to_mark(ledit_buffer *buffer, char *key_text, int len) { | |
- ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); | |
- for (size_t i = 0; i < marklist.len; i++) { | |
- if (!strncmp(key_text, marklist.marks[i].text, len)) { | |
- ledit_line *ll; | |
- struct mark *m = &marklist.marks[i]; | |
- if (m->line >= buffer->lines_num) { | |
- buffer->cur_line = buffer->lines_num - 1; | |
- ll = ledit_buffer_get_line(buffer, buffer->cur… | |
- buffer->cur_index = ll->len; | |
- } else { | |
- buffer->cur_line = m->line; | |
- ll = ledit_buffer_get_line(buffer, m->line); | |
- if (m->byte >= ll->len) | |
- buffer->cur_index = ll->len; | |
- else | |
- buffer->cur_index = m->byte; | |
- } | |
- break; | |
- } | |
- } | |
- if (buffer->common->mode == NORMAL) { | |
- buffer->cur_index = ledit_buffer_get_legal_normal_pos( | |
- buffer, buffer->cur_line, buffer->cur_index | |
- ); | |
- } | |
- ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->c… | |
- return 0; | |
+ /* nothing right now */ | |
} | |
void | |
diff --git a/keys_command.h b/keys_command.h | |
t@@ -4,9 +4,7 @@ enum ledit_command_type { | |
CMD_EDITSEARCHB, | |
CMD_SEARCH, | |
CMD_SEARCHB, | |
- CMD_SUBSTITUTE, | |
- CMD_MARKLINE, | |
- CMD_JUMPTOMARK | |
+ CMD_SUBSTITUTE | |
}; | |
/* these are only here so they can also be used by keys_basic */ | |
diff --git a/keys_command_config.h b/keys_command_config.h | |
t@@ -6,8 +6,6 @@ static int edit_insert_text(ledit_buffer *buffer, char *key_te… | |
static int edit_submit(ledit_buffer *buffer, char *key_text, int len); | |
static int editsearch_submit(ledit_buffer *buffer, char *key_text, int len); | |
static int editsearchb_submit(ledit_buffer *buffer, char *key_text, int len); | |
-static int mark_line(ledit_buffer *buffer, char *key_text, int len); | |
-static int jump_to_mark(ledit_buffer *buffer, char *key_text, int len); | |
struct key { | |
char *text; /* for keys that correspond… | |
t@@ -28,9 +26,7 @@ static struct key keys_en[] = { | |
{NULL, 0, XK_Return, CMD_EDITSEARCHB, &editsearchb_submit}, | |
{"", 0, 0, CMD_EDIT, &edit_insert_text}, | |
{"", 0, 0, CMD_EDITSEARCH, &edit_insert_text}, | |
- {"", 0, 0, CMD_EDITSEARCHB, &edit_insert_text}, | |
- {"", 0, 0, CMD_MARKLINE, &mark_line}, | |
- {"", 0, 0, CMD_JUMPTOMARK, &jump_to_mark} | |
+ {"", 0, 0, CMD_EDITSEARCHB, &edit_insert_text} | |
}; | |
static struct key keys_de[] = { |