commit 657c25540c4b349068c4c24f82b6b5bb1f94c459
parent 133041cbe8f5b106c95984a743b852fcdac6eda9
Author: lumidify <nobody@lumidify.org>
Date: Thu, 4 Nov 2021 13:22:00 +0100
Add basic support for marks
Diffstat:
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);