>From 23a0162d5dedbd64f32146f0d0087079e09bb637 Mon Sep 17 00:00:00 2001 From: Urja Rannikko Date: Fri, 11 Aug 2017 15:23:56 +0300 Subject: [PATCH] bindings: allow assigning functions to the Alt+arrow keys Besides, this fixes https://savannah.gnu.org/bugs/?51735. Reported-by: Urja Rannikko Signed-off-by: Urja Rannikko --- doc/nanorc.5 | 2 +- src/global.c | 69 ++++++++++++++++++++++++++++++++++++++++------------ src/nano.c | 5 ++++ src/nano.h | 4 +++ src/proto.h | 5 ++++ src/rcfile.c | 7 +----- src/winio.c | 22 +++++++++++++++++ syntax/nanorc.nanorc | 4 +-- 8 files changed, 93 insertions(+), 25 deletions(-) diff --git a/doc/nanorc.5 b/doc/nanorc.5 index 629312e9..deaecea9 100644 --- a/doc/nanorc.5 +++ b/doc/nanorc.5 @@ -412,7 +412,7 @@ followed by an alpha character or the word "Space". Example: ^C .TP .B M- -followed by a printable character or the word "Space". +followed by a printable character or one of "Space", "Left", "Right", "Up" and "Down". Example: M-C .TP .B F diff --git a/src/global.c b/src/global.c index dca4c653..00d7b02c 100644 --- a/src/global.c +++ b/src/global.c @@ -77,6 +77,7 @@ int controlleft, controlright, controlup, controldown, controlhome, controlend; #ifndef NANO_TINY int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown; int shiftcontrolhome, shiftcontrolend; +int altleft, altright, altup, altdown; int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown; #endif @@ -419,6 +420,56 @@ functionptrtype func_from_key(int *kbinput) return NULL; } +/* Table for M-special. */ +struct special_key { + const char *str; + const int code; +} special_keys[] = { + { "M-Space", (int)' ' }, +#ifndef NANO_TINY + { "M-Left", KEY_LEFT }, + { "M-Right", KEY_RIGHT }, + { "M-Up", KEY_UP }, + { "M-Down", KEY_DOWN }, +#endif +}; + +/* Parse the given keystring and return the corresponding keycode, + * or return -1 when the string is invalid. */ +int keycode_from_string(const char *keystring) +{ + if (keystring[0] == '^') { + if (strcasecmp(keystring, "^Space") == 0) + return 0; + else if (strlen(keystring) == 2) + return keystring[1] - 64; + else + return -1; + } else if (keystring[0] == 'M') { + if (strlen(keystring) > 3) { + int i; + for(i = 0; i < sizeof(special_keys)/sizeof(special_keys[0]); i++) { + if (strcasecmp(keystring, special_keys[i].str) == 0) + return special_keys[i].code; + } + return -1; + } + if (keystring[1] != '-') + return -1; + return tolower((unsigned char)keystring[2]); + } else if (keystring[0] == 'F') { + int fn = atoi(&keystring[1]); + if ((fn < 0) || (fn > 63)) + return -1; + return KEY_F0 + fn; + } else if (!strcasecmp(keystring, "Ins")) + return KEY_IC; + else if (!strcasecmp(keystring, "Del")) + return KEY_DC; + else + return -1; +} + /* Set the string and its corresponding keycode for the given shortcut s. */ void assign_keyinfo(sc *s, const char *keystring, const int keycode) { @@ -429,22 +480,8 @@ void assign_keyinfo(sc *s, const char *keystring, const int keycode) if (keycode) s->keycode = keycode; - else if (keystring[0] == '^') { - if (strcasecmp(keystring, "^Space") == 0) - s->keycode = 0; - else - s->keycode = keystring[1] - 64; - } else if (s->meta) { - if (strcasecmp(keystring, "M-Space") == 0) - s->keycode = (int)' '; - else - s->keycode = tolower((unsigned char)keystring[2]); - } else if (keystring[0] == 'F') - s->keycode = KEY_F0 + atoi(&keystring[1]); - else if (!strcasecmp(keystring, "Ins")) - s->keycode = KEY_IC; - else if (!strcasecmp(keystring, "Del")) - s->keycode = KEY_DC; + else + s->keycode = keycode_from_string(keystring); } #ifdef DEBUG diff --git a/src/nano.c b/src/nano.c index 935e07c4..69d069dd 100644 --- a/src/nano.c +++ b/src/nano.c @@ -2516,6 +2516,11 @@ int main(int argc, char **argv) /* Ask for the codes for Shift+Control+Home/End. */ shiftcontrolhome = get_keycode("kHOM6", SHIFT_CONTROL_HOME); shiftcontrolend = get_keycode("kEND6", SHIFT_CONTROL_END); + /* Ask for the codes for Alt+Left/Right/Up/Down. */ + altleft = get_keycode("kLFT3", ALT_LEFT); + altright = get_keycode("kRIT3", ALT_RIGHT); + altup = get_keycode("kUP3", ALT_UP); + altdown = get_keycode("kDN3", ALT_DOWN); /* Ask for the codes for Shift+Alt+Left/Right/Up/Down. */ shiftaltleft = get_keycode("kLFT4", SHIFT_ALT_LEFT); shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT); diff --git a/src/nano.h b/src/nano.h index 7c52da8b..58b66619 100644 --- a/src/nano.h +++ b/src/nano.h @@ -568,6 +568,10 @@ enum #define SHIFT_CONTROL_DOWN 0x408 #define SHIFT_CONTROL_HOME 0x413 #define SHIFT_CONTROL_END 0x414 +#define ALT_LEFT 0x415 +#define ALT_RIGHT 0x416 +#define ALT_UP 0x417 +#define ALT_DOWN 0x418 #define SHIFT_ALT_LEFT 0x409 #define SHIFT_ALT_RIGHT 0x40a #define SHIFT_ALT_UP 0x40b diff --git a/src/proto.h b/src/proto.h index 6c36c4ac..888bee80 100644 --- a/src/proto.h +++ b/src/proto.h @@ -71,6 +71,10 @@ extern int shiftcontrolup; extern int shiftcontroldown; extern int shiftcontrolhome; extern int shiftcontrolend; +extern int altleft; +extern int altright; +extern int altup; +extern int altdown; extern int shiftaltleft; extern int shiftaltright; extern int shiftaltup; @@ -328,6 +332,7 @@ size_t length_of_list(int menu); 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); +int keycode_from_string(const char *keystring); void assign_keyinfo(sc *s, const char *keystring, const int keycode); void print_sclist(void); void shortcut_init(void); diff --git a/src/rcfile.c b/src/rcfile.c index db9f6fba..c4611bfd 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -410,12 +410,7 @@ void parse_binding(char *ptr, bool dobind) else if (keycopy[0] != '^' && keycopy[0] != 'M' && keycopy[0] != 'F') { rcfile_error(N_("Key name must begin with \"^\", \"M\", or \"F\"")); goto free_copy; - } else if ((keycopy[0] == 'M' && keycopy[1] != '-') || - (keycopy[0] == '^' && ((keycopy[1] < 'A' || keycopy[1] > 'z') || - keycopy[1] == '[' || keycopy[1] == '`' || - (strlen(keycopy) > 2 && strcmp(keycopy, "^Space") != 0))) || - (strlen(keycopy) > 3 && strcmp(keycopy, "^Space") != 0 && - strcmp(keycopy, "M-Space") != 0)) { + } else if (keycode_from_string(keycopy) < 0) { rcfile_error(N_("Key name %s is invalid"), keycopy); goto free_copy; } diff --git a/src/winio.c b/src/winio.c index a66a4a31..7afd10d6 100644 --- a/src/winio.c +++ b/src/winio.c @@ -523,6 +523,18 @@ int parse_kbinput(WINDOW *win) } else if (retval == shiftcontrolend) { shift_held = TRUE; return CONTROL_END; + } else if (retval == altleft) { + meta_key = TRUE; + return KEY_LEFT; + } else if (retval == altright) { + meta_key = TRUE; + return KEY_RIGHT; + } else if (retval == altup) { + meta_key = TRUE; + return KEY_UP; + } else if (retval == altdown) { + meta_key = TRUE; + return KEY_DOWN; } else if (retval == shiftaltleft) { shift_held = TRUE; return KEY_HOME; @@ -954,6 +966,16 @@ int convert_sequence(const int *seq, size_t seq_len) } break; #ifndef NANO_TINY + case '3': + switch (seq[4]) { + case 'A': /* Esc [ 1 ; 3 A == Alt-Up on xterm. */ + case 'B': /* Esc [ 1 ; 3 B == Alt-Down on xterm. */ + case 'C': /* Esc [ 1 ; 3 C == Alt-Right on xterm. */ + case 'D': /* Esc [ 1 ; 3 D == Alt-Left on xterm. */ + meta_key = TRUE; + return arrow_from_abcd(seq[4]); + } + break; case '4': /* When the arrow keys are held together with Shift+Meta, * act as if they are Home/End/PgUp/PgDown with Shift. */ diff --git a/syntax/nanorc.nanorc b/syntax/nanorc.nanorc index 8013a7f4..b52d25ae 100644 --- a/syntax/nanorc.nanorc +++ b/syntax/nanorc.nanorc @@ -10,8 +10,8 @@ icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comm icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|justifytrim|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|unix|view|wordbounds)\>" icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|selectedcolor|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+" -icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>address@hidden|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" -icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>address@hidden|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" +icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>address@hidden|}~-]|Space|Left|Right|Up|Down))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" +icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>address@hidden|}~-]|Space|Left|Right|Up|Down))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]+(i?color|header|magic|comment|linter|formatter)[[:space:]]+.*$" icolor brightgreen "^[[:space:]]*(linter|formatter)[[:space:]]+[[:alpha:]]+" icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|extendsyntax)\>" -- 2.14.1