ledit

Text editor (WIP)
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 657c25540c4b349068c4c24f82b6b5bb1f94c459
parent 133041cbe8f5b106c95984a743b852fcdac6eda9
Author: lumidify <nobody@lumidify.org>
Date:   Thu,  4 Nov 2021 13:22:00 +0100

Add basic support for marks

Diffstat:
Mkeys_basic.c | 21+++++++++++++++++++++
Mkeys_basic_config.h | 4++++
Mkeys_command.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mkeys_command.h | 5++++-
Mkeys_command_config.h | 8+++++++-
Mledit.c | 2++
6 files changed, 121 insertions(+), 2 deletions(-)

diff --git a/keys_basic.c b/keys_basic.c @@ -396,6 +396,7 @@ get_key_repeat(void) { return num; } +/* FIXME: allow motion callback! */ static struct action move_to_line(ledit_buffer *buffer, char *text, int len) { (void)text; @@ -1382,6 +1383,26 @@ enter_searchedit_backward(ledit_buffer *buffer, char *text, int len) { return (struct action){ACTION_GRABKEY, &ledit_command_key_handler}; } +static struct action +mark_line(ledit_buffer *buffer, char *text, int len) { + (void)buffer; + (void)text; + (void)len; + ledit_command_set_type(CMD_MARKLINE); + discard_repetition_stack(); + return (struct action){ACTION_GRABKEY, &ledit_command_key_handler}; +} + +static struct action +jump_to_mark(ledit_buffer *buffer, char *text, int len) { + (void)buffer; + (void)text; + (void)len; + ledit_command_set_type(CMD_JUMPTOMARK); + discard_repetition_stack(); + return (struct action){ACTION_GRABKEY, &ledit_command_key_handler}; +} + /* FIXME: support visual mode, i.e. change selection to new place? */ static struct action key_search_next(ledit_buffer *buffer, char *text, int len) { diff --git a/keys_basic_config.h b/keys_basic_config.h @@ -68,6 +68,8 @@ static struct action paste_normal(ledit_buffer *buffer, char *text, int len); static struct action paste_normal_backwards(ledit_buffer *buffer, char *text, int len); static struct action change(ledit_buffer *buffer, char *text, int len); static struct action move_to_eol(ledit_buffer *buffer, char *text, int len); +static struct action mark_line(ledit_buffer *buffer, char *text, int len); +static struct action jump_to_mark(ledit_buffer *buffer, char *text, int len); /* FIXME: maybe sort these and use binary search -> but that would mess with the catch-all keys */ @@ -129,6 +131,8 @@ static struct key keys_en[] = { {"G", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &move_to_line}, {"p", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &paste_normal}, {"P", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &paste_normal_backwards}, + {"m", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &mark_line}, + {"'", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &jump_to_mark}, {"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text} }; diff --git a/keys_command.c b/keys_command.c @@ -30,6 +30,89 @@ /* 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_line); + 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->cur_index); + return 0; +} + void ledit_command_set_type(enum ledit_command_type type) { cur_type = type; diff --git a/keys_command.h b/keys_command.h @@ -4,12 +4,15 @@ enum ledit_command_type { CMD_EDITSEARCHB, CMD_SEARCH, CMD_SEARCHB, - CMD_SUBSTITUTE + CMD_SUBSTITUTE, + CMD_MARKLINE, + CMD_JUMPTOMARK }; /* these are only here so they can also be used by keys_basic */ void search_next(ledit_buffer *buffer); void search_prev(ledit_buffer *buffer); +void command_key_cleanup(void); void ledit_command_set_type(enum ledit_command_type type); struct action ledit_command_key_handler(ledit_buffer *buffer, XEvent *event, int lang_index); diff --git a/keys_command_config.h b/keys_command_config.h @@ -6,6 +6,8 @@ static int edit_insert_text(ledit_buffer *buffer, char *key_text, int len); 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 with text */ @@ -26,7 +28,11 @@ 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_EDITSEARCHB, &edit_insert_text}, + /* FIXME: also allow non-text keys for marks? + OpenBSD nvi seems to allow it, at least sort of. */ + {"", 0, 0, CMD_MARKLINE, &mark_line}, + {"", 0, 0, CMD_JUMPTOMARK, &jump_to_mark} }; static struct key keys_de[] = { diff --git a/ledit.c b/ledit.c @@ -41,6 +41,7 @@ #include "search.h" #include "keys.h" #include "keys_basic.h" +#include "keys_command.h" static void resize_window(int w, int h); static void mainloop(void); @@ -234,6 +235,7 @@ cleanup(void) { /* FIXME: check for other things to clean up */ ledit_search_cleanup(); basic_key_cleanup(); + command_key_cleanup(); ledit_buffer_destroy(buffer); ledit_window_destroy(window); ledit_theme_destroy(&common, theme);