[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
- [PATCH] input: interpret commands of the form {functionname} inside string binds,
Benno Schulenberg <=