mirror of git://git.sv.gnu.org/nano.git
input: interpret commands of the form {functionname} inside string binds
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
This commit is contained in:
parent
3a781fd719
commit
958ec294b2
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -460,6 +463,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)
|
||||
|
|
|
@ -1269,6 +1269,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. */
|
||||
|
|
|
@ -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;
|
||||
|
@ -440,6 +443,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);
|
||||
|
|
63
src/winio.c
63
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. */
|
||||
|
|
Loading…
Reference in New Issue