From fdb338fe12da6b21b6a7aa8c1090621a359dd9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Wed, 7 Jul 2021 20:30:46 +0200 Subject: Allow binding to custom key sequences And document this feature in the manual page. --- LICENSE | 2 +- sdn.1 | 14 ++++++++++++++ sdn.cpp | 24 ++++++++++++++++++------ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/LICENSE b/LICENSE index 3bfb256..5e342a0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017 - 2020, Přemysl Eric Janouch +Copyright (c) 2017 - 2021, Přemysl Eric Janouch Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. diff --git a/sdn.1 b/sdn.1 index 07da89e..097a5de 100644 --- a/sdn.1 +++ b/sdn.1 @@ -98,6 +98,20 @@ normal h parent normal l choose normal M-f4 quit .Ed +.Pp +Midnight Commander binds the same traversal actions to sequences normally +unknown to ncurses, due to them being missing from terminfo. +You'll need to define them manually to match your terminal. +For rxvt, that would be: +.Bd -literal -offset indent +define C-ppage ^[[5^ +define C-npage ^[[6^ +normal C-ppage parent +normal C-npage choose +.Ed +.Pp +Escape characters must be inserted verbatim, e.g., by pressing C-v ESC in vi, +or C-q ESC in Emacs. .Ss Pa look Terminal attributes are accepted in a format similar to that of .Xr git-config 1 , diff --git a/sdn.cpp b/sdn.cpp index 30cdb83..4636ff3 100644 --- a/sdn.cpp +++ b/sdn.cpp @@ -1,7 +1,7 @@ // // sdn: simple directory navigator // -// Copyright (c) 2017 - 2020, Přemysl Eric Janouch +// Copyright (c) 2017 - 2021, Přemysl Eric Janouch // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted. @@ -544,6 +544,7 @@ static struct { map name_to_key; map key_to_name; + map custom_keys; string action_names[ACTION_COUNT]; ///< Stylized action names // Refreshed by reload(): @@ -1566,7 +1567,9 @@ fun parse_key (const string &key_name) -> wint_t { c |= ALT; p += 2; } - if (!strncmp (p, "C-", 2)) { + if (g.name_to_key.count (p)) { + return c | g.name_to_key.at (p); + } else if (!strncmp (p, "C-", 2)) { p += 2; if (*p < '?' || *p > 'z') { cerr << "bindings: invalid combination: " << key_name << endl; @@ -1574,8 +1577,6 @@ fun parse_key (const string &key_name) -> wint_t { } c |= CTRL (toupper (*p)); p += 1; - } else if (g.name_to_key.count (p)) { - return c | g.name_to_key.at (p); } else { wchar_t w; mbstate_t mb {}; auto len = strlen (p) + 1, res = mbrtowc (&w, p, len, &mb); @@ -1604,7 +1605,9 @@ fun learn_named_key (const string &name, wint_t key) { fun load_bindings () { learn_named_key ("space", ' '); learn_named_key ("escape", 0x1b); - for (int kc = KEY_MIN; kc < KEY_MAX; kc++) { + + int kc = 0; + for (kc = KEY_MIN; kc <= KEY_MAX; kc++) { const char *name = keyname (kc); if (!name) continue; @@ -1638,11 +1641,18 @@ fun load_bindings () { if (tokens.empty ()) continue; if (tokens.size () < 3) { - cerr << "bindings: expected: context binding action"; + cerr << "bindings: expected: define name key-sequence" + " | context binding action"; continue; } auto context = tokens[0], key_name = tokens[1], action = tokens[2]; + if (context == "define") { + // We haven't run initscr() yet, so define_key() would fail here + learn_named_key (key_name, SYM | (g.custom_keys[action] = ++kc)); + continue; + } + auto m = g_binding_contexts.find (context); if (m == g_binding_contexts.end ()) { cerr << "bindings: invalid context: " << context << endl; @@ -1754,6 +1764,8 @@ int main (int argc, char *argv[]) { cerr << "cannot initialize screen" << endl; return 1; } + for (const auto &definition_kc : g.custom_keys) + define_key (definition_kc.first.c_str (), definition_kc.second); load_colors (); load_cmdline (argc, argv); -- cgit v1.2.3