From 4a561550c46992938b7a62402b93395ed2d66cb7 Mon Sep 17 00:00:00 2001 From: Urja Rannikko Date: Fri, 11 Aug 2017 15:23:56 +0300 Subject: [PATCH] keys: support binding alt-left/right/up/down keys Signed-off-by: Urja Rannikko --- doc/nanorc.5 | 2 +- src/global.c | 74 +++++++++++++++++++++++++++++++++++++++++++++--------------- src/nano.c | 5 ++++ src/nano.h | 4 ++++ src/proto.h | 5 ++++ src/rcfile.c | 7 +----- src/winio.c | 22 ++++++++++++++++++ 7 files changed, 94 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..d8d3cbe8 100644 --- a/src/global.c +++ b/src/global.c @@ -78,6 +78,7 @@ int controlleft, controlright, controlup, controldown, controlhome, controlend; int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown; int shiftcontrolhome, shiftcontrolend; int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown; +int altleft, altright, altup, altdown; #endif #ifndef DISABLE_WRAPJUSTIFY @@ -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 +}; + +/* Validate and parse keystring to a keycode. */ +int string_to_keycode(const char *keystring) +{ + int meta = (keystring[0] == 'M'); + + if (keystring[0] == '^') { + if (strcasecmp(keystring, "^Space") == 0) + return 0; + else if (strlen(keystring) == 2) + return keystring[1] - 64; + else + return -1; + } else if (meta) { + 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 ((strlen(keystring) != 3)||(keystring[1] != '-')) + return -1; + return tolower((unsigned char)keystring[2]); + } else if (keystring[0] == 'F') { + int fn = atoi(&keystring[1]); + if ( (strlen(keystring) < 2) || (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; + 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) { @@ -427,24 +478,11 @@ void assign_keyinfo(sc *s, const char *keystring, const int keycode) assert(strlen(keystring) > 1 && (!s->meta || strlen(keystring) > 2)); - 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; + if (!keycode) s->keycode = string_to_keycode(keystring); + else s->keycode = keycode; + + assert(s->keycode>=0); + } #ifdef DEBUG diff --git a/src/nano.c b/src/nano.c index 935e07c4..bbe29648 100644 --- a/src/nano.c +++ b/src/nano.c @@ -2521,6 +2521,11 @@ int main(int argc, char **argv) shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT); shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP); shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN); + /* 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); #endif #ifdef HAVE_SET_ESCDELAY diff --git a/src/nano.h b/src/nano.h index 7c52da8b..aacb669e 100644 --- a/src/nano.h +++ b/src/nano.h @@ -576,6 +576,10 @@ enum #define SHIFT_PAGEDOWN 0x40e #define SHIFT_HOME 0x40f #define SHIFT_END 0x410 +#define ALT_LEFT 0x411 +#define ALT_RIGHT 0x412 +#define ALT_UP 0x413 +#define ALT_DOWN 0x414 #ifdef USE_SLANG #ifdef ENABLE_UTF8 diff --git a/src/proto.h b/src/proto.h index 6c36c4ac..9432ff92 100644 --- a/src/proto.h +++ b/src/proto.h @@ -75,6 +75,10 @@ extern int shiftaltleft; extern int shiftaltright; extern int shiftaltup; extern int shiftaltdown; +extern int altleft; +extern int altright; +extern int altup; +extern int altdown; #endif #ifndef DISABLE_WRAPJUSTIFY @@ -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 string_to_keycode(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..efa7760f 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 (string_to_keycode(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..375db5c6 100644 --- a/src/winio.c +++ b/src/winio.c @@ -535,6 +535,18 @@ int parse_kbinput(WINDOW *win) } else if (retval == shiftaltdown) { shift_held = TRUE; return KEY_NPAGE; + } 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; } #endif @@ -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. */ -- 2.13.3