nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] input: interpret commands of the form {functionname} inside stri


From: Benno Schulenberg
Subject: [PATCH] input: interpret commands of the form {functionname} inside string binds
Date: Fri, 12 Aug 2022 15:00:44 +0200

This allows specifying bindable functions in a string bind by name
instead of by the literal control code or escape sequence to which
they are bound, which makes for a much more readable string bind,
and also allows specifying functions that are not bound to any key.

The opening brace, {, is made into a special symbol inside a string
bind, and each literal occurrence there needs to be escaped as {{}.

This fulfills https://savannah.gnu.org/bugs/?61692.
Requested-by: Tasos Papastylianou <tpapastylianou@hotmail.com>

Original-idea-by: Brand Huntsman <alpha@qzx.com>
  https://lists.gnu.org/archive/html/nano-devel/2018-02/msg00006.html
---
 src/definitions.h | 12 +++++++++
 src/global.c      |  7 ++++++
 src/nano.c        |  4 +++
 src/prototypes.h  |  4 +++
 src/winio.c       | 63 +++++++++++++++++++++++++++++++++++++++++++----
 5 files changed, 85 insertions(+), 5 deletions(-)

diff --git a/src/definitions.h b/src/definitions.h
index 58012553..b064891a 100644
--- a/src/definitions.h
+++ b/src/definitions.h
@@ -214,6 +214,18 @@
 #define SHIFT_DELETE    0x45D
 #define SHIFT_TAB       0x45F
 
+/* A special keycode for when a string bind has been partially implanted. */
+#define MORE_PLANTS       0x4EA
+
+/* A special keycode for when a string bind has an unpaired opening brace. */
+#define MISSING_BRACE     0x4EB
+
+/* A special keycode for when a function in a string bind needs execution. */
+#define PLANTED_COMMAND   0x4EC
+
+/* A special keycode for when a function name in a string bind is invalid. */
+#define NO_SUCH_FUNCTION  0x4EF
+
 /* A special keycode for when <Tab> is pressed while the mark is on. */
 #define INDENT_KEY  0x4F1
 
diff --git a/src/global.c b/src/global.c
index 80adf6e9..df88c92d 100644
--- a/src/global.c
+++ b/src/global.c
@@ -266,6 +266,9 @@ char *startup_problem = NULL;
 #endif
 #ifdef ENABLE_NANORC
 char *custom_nanorc = NULL;
+
+char *commandname = NULL;
+keystruct *planted_shortcut = NULL;
 #endif
 
 bool spotlighted = FALSE;
@@ -466,6 +469,10 @@ const keystruct *get_shortcut(int *keycode)
        if (bracketed_paste && *keycode != BRACKETED_PASTE_MARKER)
                return NULL;
 #endif
+#ifdef ENABLE_NANORC
+       if (*keycode == PLANTED_COMMAND)
+               return planted_shortcut;
+#endif
 
        for (keystruct *sc = sclist; sc != NULL; sc = sc->next) {
                if ((sc->menus & currmenu) && *keycode == sc->keycode)
diff --git a/src/nano.c b/src/nano.c
index fe139486..1fe0f1f1 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1267,6 +1267,10 @@ void unbound_key(int code)
                /* TRANSLATORS: This refers to a sequence of escape codes
                 * (from the keyboard) that nano does not recognize. */
                statusline(AHEM, _("Unknown sequence"));
+       else if (code == MISSING_BRACE)
+               statusline(AHEM, _("Missing }"));
+       else if (code == NO_SUCH_FUNCTION)
+               statusline(AHEM, _("No such function: %s"), commandname);
 #ifndef NANO_TINY
        else if (code > KEY_F0 && code < KEY_F0 + 25)
                /* TRANSLATORS: This refers to an unbound function key. */
diff --git a/src/prototypes.h b/src/prototypes.h
index 473779ed..dbe8dad8 100644
--- a/src/prototypes.h
+++ b/src/prototypes.h
@@ -181,6 +181,9 @@ extern char *startup_problem;
 #endif
 #ifdef ENABLE_NANORC
 extern char *custom_nanorc;
+
+extern char *commandname;
+extern keystruct *planted_shortcut;
 #endif
 
 extern bool spotlighted;
@@ -441,6 +444,7 @@ void display_rcfile_errors(void);
 void jot_error(const char *msg, ...);
 #endif
 #ifdef ENABLE_NANORC
+keystruct *strtosc(const char *input);
 #ifdef ENABLE_COLOR
 void parse_one_include(char *file, syntaxtype *syntax);
 void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
diff --git a/src/winio.c b/src/winio.c
index e7dce7ff..98c4b4bc 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -64,6 +64,8 @@ static bool has_more = FALSE;
                /* Whether the current line has more text after the displayed 
part. */
 static bool is_shorter = TRUE;
                /* Whether a row's text is narrower than the screen's width. */
+static const char *plants_pointer = NULL;
+               /* Points into the expansion string for the current 
implantation. */
 #ifndef NANO_TINY
 static size_t sequel_column = 0;
                /* The starting column of the next chunk when softwrapping. */
@@ -326,14 +328,60 @@ void put_back(int keycode)
 }
 
 #ifdef ENABLE_NANORC
-/* Insert the given string into the keyboard buffer. */
+/* Set up the given expansion string to be ingested by the keyboard routines. 
*/
 void implant(const char *string)
 {
-       for (int i = strlen(string); i > 0; i--)
-               put_back((unsigned char)string[i - 1]);
+       plants_pointer = string;
+       put_back(MORE_PLANTS);
 
        mute_modifiers = TRUE;
 }
+
+/* Continue processing an expansion string.  Returns either an error code,
+ * a plain keycode, or a placeholder for a command shortcut. */
+int get_code_from_plantation(void)
+{
+       if (*plants_pointer == '{') {
+               char *closing = strchr(plants_pointer + 1, '}');
+
+               if (!closing)
+                       return MISSING_BRACE;
+
+               if (plants_pointer[1] == '{' && plants_pointer[2] == '}') {
+                       plants_pointer += 3;
+                       if (*plants_pointer != '\0')
+                               put_back(MORE_PLANTS);
+                       return '{';
+               }
+
+               free(commandname);
+               free(planted_shortcut);
+
+               commandname = measured_copy(plants_pointer + 1, closing - 
plants_pointer - 1);
+               planted_shortcut = strtosc(commandname);
+
+               if (planted_shortcut) {
+                       plants_pointer = closing + 1;
+                       if (*plants_pointer != '\0')
+                               put_back(MORE_PLANTS);
+                       return PLANTED_COMMAND;
+               } else
+                       return NO_SUCH_FUNCTION;
+       } else {
+               char *opening = strchr(plants_pointer, '{');
+               int length = (opening ? opening - plants_pointer : 
strlen(plants_pointer));
+
+               if (opening)
+                       put_back(MORE_PLANTS);
+
+               for (int index = length - 1; index >= 0; index--)
+                       put_back((unsigned char)plants_pointer[index]);
+
+               plants_pointer += length;
+
+               return ERR;
+       }
+}
 #endif
 
 /* Return one code from the keystroke buffer.  If the buffer is empty
@@ -347,7 +395,11 @@ int get_input(WINDOW *frame)
 
        if (waiting_codes > 0) {
                waiting_codes--;
-               return *(nextcodes++);
+               if (*nextcodes == MORE_PLANTS) {
+                       nextcodes++;
+                       return get_code_from_plantation();
+               } else
+                       return *(nextcodes++);
        } else
                return ERR;
 }
@@ -940,7 +992,8 @@ int parse_kbinput(WINDOW *frame)
                } else if (++escapes > 2)
                        escapes = (last_escape_was_alone ? 0 : 1);
                return ERR;
-       }
+       } else if (keycode == ERR)
+               return ERR;
 
        if (escapes == 0) {
                /* Most key codes in byte range cannot be special keys. */
-- 
2.35.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]