Introduction
Introduction Statistics Contact Development Disclaimer Help
tAdd basic (buggy) support for command repetition - 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 bc282da2c2bfd820f810d1e03bc829fe3928f3e5
parent 9df066a3d594aeeca41677744f0f29a81901f124
Author: lumidify <[email protected]>
Date: Sun, 24 Oct 2021 13:48:53 +0200
Add basic (buggy) support for command repetition
Diffstat:
M keys_basic.c | 186 ++++++++++++++++++++++++++---…
M keys_basic_config.h | 2 ++
M memory.c | 8 ++++++++
M memory.h | 1 +
4 files changed, 171 insertions(+), 26 deletions(-)
---
diff --git a/keys_basic.c b/keys_basic.c
t@@ -28,6 +28,22 @@
/* this is supposed to be global for all buffers */
txtbuf *paste_buffer = NULL;
+struct repetition_stack_elem {
+ char *key_text;
+ int len;
+ KeySym sym;
+ unsigned int key_state;
+ int lang_index;
+};
+
+static struct {
+ int replaying;
+ size_t len, alloc, cur_pos;
+ struct repetition_stack_elem *stack;
+ size_t tmp_len, tmp_alloc;
+ struct repetition_stack_elem *tmp_stack;
+} repetition_stack = {0, 0, 0, 0, NULL, 0, 0, NULL};
+
struct key_stack_elem {
enum key_type key;
enum key_type followup; /* allowed keys to complete the keybinding */
t@@ -46,6 +62,14 @@ static struct {
struct key_stack_elem *stack;
} key_stack = {0, 0, NULL};
+/* No, this isn't actually a stack. So what? */
+static struct repetition_stack_elem *push_repetition_stack(void);
+static void finalize_repetition_stack(void);
+static struct repetition_stack_elem *get_cur_repetition_stack_elem(void);
+static void unwind_repetition_stack(void);
+static void advance_repetition_stack(void);
+static void discard_repetition_stack(void);
+
static struct key_stack_elem *push_key_stack(void);
static struct key_stack_elem *peek_key_stack(void);
static struct key_stack_elem *pop_key_stack(void);
t@@ -86,7 +110,7 @@ push_key_stack(void) {
e->data1 = 0;
e->data2 = 0;
key_stack.len++;
- return &key_stack.stack[key_stack.len - 1];
+ return e;
}
/* Note: for peek and pop, the returned element is only valid
t@@ -113,6 +137,67 @@ clear_key_stack(void) {
key_stack.len = 0;
}
+static struct repetition_stack_elem *
+push_repetition_stack(void) {
+ struct repetition_stack_elem *e;
+ if (repetition_stack.tmp_len >= repetition_stack.tmp_alloc) {
+ size_t new_alloc = repetition_stack.tmp_alloc > 0 ? repetition…
+ repetition_stack.tmp_stack = ledit_realloc(
+ repetition_stack.tmp_stack,
+ new_alloc * sizeof(struct repetition_stack_elem)
+ );
+ repetition_stack.tmp_alloc = new_alloc;
+ }
+ e = &repetition_stack.tmp_stack[repetition_stack.tmp_len];
+ e->key_text = NULL;
+ e->len = 0;
+ e->sym = 0;
+ e->key_state = 0;
+ e->lang_index = 0;
+ repetition_stack.tmp_len++;
+ return e;
+}
+
+static struct repetition_stack_elem *
+get_cur_repetition_stack_elem(void) {
+ if (repetition_stack.cur_pos >= repetition_stack.len)
+ return NULL;
+ return &repetition_stack.stack[repetition_stack.cur_pos];
+}
+
+static void
+unwind_repetition_stack(void) {
+ repetition_stack.cur_pos = 0;
+}
+
+static void
+discard_repetition_stack(void) {
+ if (repetition_stack.replaying)
+ return;
+ repetition_stack.tmp_len = 0;
+}
+
+static void
+advance_repetition_stack(void) {
+ repetition_stack.cur_pos++;
+}
+
+static void
+finalize_repetition_stack(void) {
+ if (repetition_stack.replaying)
+ return;
+ size_t tmp;
+ struct repetition_stack_elem *tmpstack;
+ repetition_stack.len = repetition_stack.tmp_len;
+ repetition_stack.tmp_len = 0;
+ tmp = repetition_stack.alloc;
+ repetition_stack.alloc = repetition_stack.tmp_alloc;
+ repetition_stack.tmp_alloc = tmp;
+ tmpstack = repetition_stack.stack;
+ repetition_stack.stack = repetition_stack.tmp_stack;
+ repetition_stack.tmp_stack = tmpstack;
+}
+
/* get the new line and softline when moving 'movement' softlines up or
down (negative means up, positive means down) */
static void
t@@ -295,6 +380,7 @@ key_d_cb(ledit_buffer *buffer, int line, int char_pos, enu…
line, char_pos
);
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->c…
+ finalize_repetition_stack();
}
static struct action
t@@ -523,6 +609,7 @@ move_cursor_left_right(ledit_buffer *buffer, int dir) {
} else if (buffer->common->mode == NORMAL) {
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur…
}
+ discard_repetition_stack();
}
clear_key_stack();
}
t@@ -621,6 +708,8 @@ escape_key(ledit_buffer *buffer, char *text, int len) {
(void)text;
(void)len;
clear_key_stack(); /* just in case... */
+ if (buffer->common->mode == INSERT)
+ finalize_repetition_stack();
if (buffer->common->mode == INSERT &&
(buffer->sel.line1 != buffer->sel.line2 ||
buffer->sel.byte1 != buffer->sel.byte2)) {
t@@ -708,6 +797,7 @@ move_cursor_up_down(ledit_buffer *buffer, int dir) {
} else if (buffer->common->mode == NORMAL) {
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur…
}
+ discard_repetition_stack();
}
clear_key_stack();
}
t@@ -749,6 +839,7 @@ cursor_to_beginning(ledit_buffer *buffer, char *text, int …
buffer, buffer->cur_line, buffer->cur_index
);
}
+ discard_repetition_stack();
}
clear_key_stack();
return (struct action){ACTION_NONE, NULL};
t@@ -788,6 +879,7 @@ enter_commandedit(ledit_buffer *buffer, char *text, int le…
ledit_window_set_bottom_bar_cursor(buffer->window, 1);
ledit_command_set_type(CMD_EDIT);
ledit_window_set_bottom_bar_text_shown(buffer->window, 1);
+ discard_repetition_stack();
return (struct action){ACTION_GRABKEY, &ledit_command_key_handler};
}
t@@ -799,6 +891,7 @@ enter_searchedit_forward(ledit_buffer *buffer, char *text,…
ledit_window_set_bottom_bar_cursor(buffer->window, 1);
ledit_command_set_type(CMD_EDITSEARCH);
ledit_window_set_bottom_bar_text_shown(buffer->window, 1);
+ discard_repetition_stack();
return (struct action){ACTION_GRABKEY, &ledit_command_key_handler};
}
t@@ -810,6 +903,7 @@ enter_searchedit_backward(ledit_buffer *buffer, char *text…
ledit_window_set_bottom_bar_cursor(buffer->window, 1);
ledit_command_set_type(CMD_EDITSEARCHB);
ledit_window_set_bottom_bar_text_shown(buffer->window, 1);
+ discard_repetition_stack();
return (struct action){ACTION_GRABKEY, &ledit_command_key_handler};
}
t@@ -819,6 +913,7 @@ key_search_next(ledit_buffer *buffer, char *text, int len)…
(void)text;
(void)len;
search_next(buffer);
+ discard_repetition_stack();
return (struct action){ACTION_NONE, NULL};
}
t@@ -827,6 +922,7 @@ key_search_prev(ledit_buffer *buffer, char *text, int len)…
(void)text;
(void)len;
search_prev(buffer);
+ discard_repetition_stack();
return (struct action){ACTION_NONE, NULL};
}
t@@ -838,6 +934,7 @@ show_line(ledit_buffer *buffer, char *text, int len) {
char *str = ledit_malloc(textlen + 1);
snprintf(str, textlen + 1, "Line %d of %d", buffer->cur_line + 1, buff…
ledit_window_show_message(buffer->window, str, textlen);
+ discard_repetition_stack();
return (struct action){ACTION_NONE, NULL};
}
t@@ -850,6 +947,7 @@ undo(ledit_buffer *buffer, char *text, int len) {
ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
ledit_buffer_undo(buffer);
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->c…
+ finalize_repetition_stack();
return (struct action){ACTION_NONE, NULL};
}
t@@ -861,6 +959,7 @@ redo(ledit_buffer *buffer, char *text, int len) {
ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
ledit_buffer_redo(buffer);
ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->c…
+ finalize_repetition_stack();
return (struct action){ACTION_NONE, NULL};
}
t@@ -877,6 +976,7 @@ clipcopy(ledit_buffer *buffer, char *text, int len) {
(void)len;
/* FIXME: abstract this through buffer */
clipboard_primary_to_clipboard(buffer->window);
+ discard_repetition_stack();
return (struct action){ACTION_NONE, NULL};
}
t@@ -885,53 +985,87 @@ clippaste(ledit_buffer *buffer, char *text, int len) {
(void)text;
(void)len;
ledit_buffer_paste_clipboard(buffer);
+ finalize_repetition_stack();
return (struct action){ACTION_NONE, NULL};
}
-struct action
-basic_key_handler(ledit_buffer *buffer, XEvent *event, int lang_index) {
- char buf[64];
- KeySym sym;
- int n;
-
+static struct action
+handle_key(ledit_buffer *buffer, char *key_text, int len, KeySym sym, unsigned…
+ struct action act = {ACTION_NONE, NULL};
struct key *cur_keys = keys[lang_index].keys;
int num_keys = keys[lang_index].num_keys;
- unsigned int key_state = event->xkey.state;
- preprocess_key(buffer->window, event, &sym, buf, sizeof(buf), &n);
-
- int found = 0;
struct key_stack_elem *e = peek_key_stack();
- /* FIXME: only hide when actually necessary */
- ledit_window_hide_message(buffer->window);
- struct action act;
+ *found = 0;
for (int i = 0; i < num_keys; i++) {
if (cur_keys[i].text) {
- if (n > 0 &&
+ if (len > 0 &&
(cur_keys[i].modes & buffer->common->mode) &&
(!e || (e->key & cur_keys[i].prev_keys)) &&
- ((!strncmp(cur_keys[i].text, buf, n) &&
+ ((!strncmp(cur_keys[i].text, key_text, len) &&
match_key(cur_keys[i].mods, key_state & ~ShiftM…
cur_keys[i].text[0] == '\0')) {
/* FIXME: seems a bit hacky to remove shift, b…
is needed to make keys that use shift match…
- act = cur_keys[i].func(buffer, buf, n);
- found = 1;
+ act = cur_keys[i].func(buffer, key_text, len);
+ *found = 1;
break;
}
} else if ((cur_keys[i].modes & buffer->common->mode) &&
cur_keys[i].keysym == sym &&
match_key(cur_keys[i].mods, key_state)) {
- act = cur_keys[i].func(buffer, buf, n);
- found = 1;
+ act = cur_keys[i].func(buffer, key_text, len);
+ *found = 1;
break;
}
}
+ return act;
+}
+
+static struct action
+repeat_command(ledit_buffer *buffer, char *text, int len) {
+ (void)buffer;
+ (void)text;
+ (void)len;
+ int found;
+ repetition_stack.replaying = 1;
+ clear_key_stack();
+ unwind_repetition_stack();
+ struct repetition_stack_elem *e = get_cur_repetition_stack_elem();
+ while (e) {
+ (void)handle_key(buffer, e->key_text, e->len, e->sym, e->key_s…
+ advance_repetition_stack();
+ e = get_cur_repetition_stack_elem();
+ }
+ repetition_stack.replaying = 0;
+ discard_repetition_stack();
+ clear_key_stack();
+ return (struct action){ACTION_NONE, NULL};
+}
+
+struct action
+basic_key_handler(ledit_buffer *buffer, XEvent *event, int lang_index) {
+ char buf[64];
+ KeySym sym;
+ int n;
+
+ unsigned int key_state = event->xkey.state;
+ preprocess_key(buffer->window, event, &sym, buf, sizeof(buf), &n);
+
+ struct repetition_stack_elem *re = push_repetition_stack();
+ re->key_text = ledit_strndup(buf, (size_t)n);
+ re->len = n;
+ re->sym = sym;
+ re->key_state = key_state;
+ re->lang_index = lang_index;
+
+ /* FIXME: only hide when actually necessary */
+ ledit_window_hide_message(buffer->window);
+ int found = 0;
+ struct action act = handle_key(buffer, buf, n, sym, key_state, lang_in…
+
/* FIXME: only do this when necessary */
- if (found) {
+ if (found)
ledit_buffer_ensure_cursor_shown(buffer);
- return act;
- } else {
- /* FIXME: maybe show error */
- return (struct action){ACTION_NONE, NULL};
- }
+ /* FIXME: maybe show error if not found */
+ return act;
}
diff --git a/keys_basic_config.h b/keys_basic_config.h
t@@ -56,6 +56,7 @@ static struct action key_search_prev(ledit_buffer *buffer, c…
static struct action undo(ledit_buffer *buffer, char *text, int len);
static struct action redo(ledit_buffer *buffer, char *text, int len);
static struct action insert_mode_insert_text(ledit_buffer *buffer, char *text,…
+static struct action repeat_command(ledit_buffer *buffer, char *text, int len);
/* FIXME: maybe sort these and use binary search
-> but that would mess with the catch-all keys */
t@@ -98,6 +99,7 @@ static struct key keys_en[] = {
{"N", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &key_search_prev},
{"u", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &undo},
{"U", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &redo},
+ {".", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &repeat_command}, /* FIXME: onl…
{"z", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &undo},
{"y", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &redo},
{"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text}
diff --git a/memory.c b/memory.c
t@@ -16,6 +16,14 @@ ledit_strdup(const char *s) {
return str;
}
+char *
+ledit_strndup(const char *s, size_t n) {
+ char *str = strndup(s, n);
+ if (!str)
+ fatal_err("Out of memory.\n");
+ return str;
+}
+
void *
ledit_malloc(size_t size) {
void *ptr = malloc(size);
diff --git a/memory.h b/memory.h
t@@ -1,4 +1,5 @@
char *ledit_strdup(const char *s);
+char *ledit_strndup(const char *s, size_t n);
void *ledit_malloc(size_t size);
void *ledit_calloc(size_t nmemb, size_t size);
void *ledit_realloc(void *ptr, size_t size);
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.