From 6d111c93430690c37d102a769542841d833ea149 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg <bensberg@telfort.nl> Date: Sat, 20 Jan 2018 13:01:43 +0100 Subject: [PATCH] new feature: allow binding a key to a string (in a nanorc file) In this way a single keystroke can produce a fragment of text or a series of commands, or a mix of the two. It is like a prerecorded macro. This fulfills https://savannah.gnu.org/bugs/?52931. --- src/global.c | 14 ++++++++++++++ src/nano.c | 3 ++- src/nano.h | 2 ++ src/prompt.c | 2 +- src/proto.h | 3 +++ src/rcfile.c | 14 ++++++++++++-- 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/global.c b/src/global.c index 20eeb62c..d6af4e7d 100644 --- a/src/global.c +++ b/src/global.c @@ -318,6 +318,9 @@ void flip_newbuffer(void) void discard_buffer(void) { } +void implant(void) +{ +} /* Add a function to the function list. */ void add_to_funcs(void (*func)(void), int menus, const char *desc, const char *help, @@ -1379,6 +1382,17 @@ void set_spell_shortcuts(void) } #endif /* ENABLE_COLOR && ENABLE_SPELLER */ +/* Execute the function of the given shortcut. */ +void execute(const sc *shortcut) +{ + if (shortcut->scfunc == implant) + /* Insert the corresponding string into the keyboard buffer. */ + for (int i = strlen(shortcut->expansion); i > 0; i--) + put_back(shortcut->expansion[i - 1]); + else + shortcut->scfunc(); +} + const subnfunc *sctofunc(const sc *s) { subnfunc *f = allfuncs; diff --git a/src/nano.c b/src/nano.c index 12543dd4..c57b457d 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1753,7 +1753,8 @@ int do_input(bool allow_funcs) } #endif /* Execute the function of the shortcut. */ - s->scfunc(); + execute(s); + #ifndef NANO_TINY /* When the marked region changes without Shift being held, * discard a soft mark. And when the marked region covers a diff --git a/src/nano.h b/src/nano.h index 92f8e296..44d71949 100644 --- a/src/nano.h +++ b/src/nano.h @@ -439,6 +439,8 @@ typedef struct sc { int ordinal; /* The how-manieth toggle this is, in order to be able to * keep them in sequence. */ + char *expansion; + /* The string of keycodes to which this shortcut is expanded. */ #endif struct sc *next; /* Next in the list. */ diff --git a/src/prompt.c b/src/prompt.c index c067a3fb..0b73c40b 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -180,7 +180,7 @@ int do_statusbar_input(bool *ran_func, bool *finished) *ran_func = TRUE; if (f && (!ISSET(VIEW_MODE) || f->viewok) && f->scfunc != do_gotolinecolumn_void) - f->scfunc(); + execute(s); } *finished = TRUE; } diff --git a/src/proto.h b/src/proto.h index c4f6f074..18995490 100644 --- a/src/proto.h +++ b/src/proto.h @@ -318,6 +318,7 @@ char *input_tab(char *buf, bool allow_files, size_t *place, /* Some functions in global.c. */ size_t length_of_list(int menu); +void implant(void); const sc *first_sc_for(int menu, void (*func)(void)); int the_code_for(void (*func)(void), int defaultval); functionptrtype func_from_key(int *kbinput); @@ -329,6 +330,7 @@ void shortcut_init(void); void set_lint_or_format_shortcuts(void); void set_spell_shortcuts(void); #endif +void execute(const sc *shortcut); const subnfunc *sctofunc(const sc *s); const char *flagtostr(int flag); sc *strtosc(const char *input); @@ -619,6 +621,7 @@ void dump_filestruct(const filestruct *inptr); void record_macro(void); void run_macro(void); size_t get_key_buffer_len(void); +void put_back(int keycode); void unget_kbinput(int kbinput, bool metakey); int get_kbinput(WINDOW *win, bool showcursor); int parse_kbinput(WINDOW *win); diff --git a/src/rcfile.c b/src/rcfile.c index ddfbd003..84dc57aa 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -336,6 +336,7 @@ bool is_universal(void (*func)(void)) func == do_home || func == do_end || #ifndef NANO_TINY func == do_prev_word_void || func == do_next_word_void || + func == implant || #endif func == do_delete || func == do_backspace || func == do_cut_text_void || func == do_uncut_text || @@ -396,7 +397,7 @@ void parse_binding(char *ptr, bool dobind) if (dobind) { funcptr = ptr; - ptr = parse_next_word(ptr); + ptr = parse_argument(ptr); if (funcptr[0] == '\0') { rcfile_error(N_("Must specify a function to bind the key to")); @@ -414,7 +415,16 @@ void parse_binding(char *ptr, bool dobind) } if (dobind) { - newsc = strtosc(funcptr); + /* If the thing to bind starts with a double quote, it is a string, + * otherwise it is the name of a function. */ + if (*funcptr == '"') { + newsc = nmalloc(sizeof(sc)); + newsc->scfunc = implant; + newsc->expansion = mallocstrcpy(NULL, funcptr + 1); + newsc->toggle = 0; + } else + newsc = strtosc(funcptr); + if (newsc == NULL) { rcfile_error(N_("Cannot map name \"%s\" to a function"), funcptr); goto free_things; -- GitLab