From dbb47ec2ee4e8323efe9092b021444e43c55fb3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?=
Date: Sat, 8 Aug 2026 14:04:56 +0200 Subject: [PATCH] Adjust key bindings Now they should actually be more friendly to WeeChat users. --- NEWS | 3 + README.adoc | 2 +- xA/xA.go | 16 +++--- xC.c | 7 ++- xF.c | 150 +++++++++++++++++++++++++++--------------------- xP/public/xP.js | 5 +- xT/xT.cpp | 6 +- 7 files changed, 109 insertions(+), 80 deletions(-) diff --git a/NEWS b/NEWS index 2541ba2..7a577de 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ Unreleased * xP: fixed channel title layout for narrow browser windows + * Adjusted key bindings; most notably M-Up/M-Down replace M-PageUp/M-PageDown, + and M-/ supplements M-Tab + 2.3.0 (2026-07-31) "Clean" diff --git a/README.adoc b/README.adoc index d9a0232..77bed17 100644 --- a/README.adoc +++ b/README.adoc @@ -11,7 +11,7 @@ They're all lean on dependencies, and offer a maximally permissive licence. xC -- The IRC client, and the core of 'xK'. Its interface should feel somewhat -familiar for weechat or irssi users. Currently the terminal interface +familiar for WeeChat or irssi users. Currently the terminal interface experience deserves some polishing, because we've just got rid of Readline/Editline dependencies, which kept breaking in exciting ways. diff --git a/xA/xA.go b/xA/xA.go index f1ebdb7..c211a08 100644 --- a/xA/xA.go +++ b/xA/xA.go @@ -1452,13 +1452,19 @@ func actionBufferNext() { } } +func actionBufferLast() { + if bufferLast != "" { + bufferActivate(bufferLast) + } +} + var shortcuts = map[desktop.CustomShortcut]func(){ { KeyName: fyne.KeyPageUp, Modifier: fyne.KeyModifierControl, }: actionBufferPrevious, { - KeyName: fyne.KeyPageUp, + KeyName: fyne.KeyUp, Modifier: fyne.KeyModifierAlt, }: actionBufferPrevious, { @@ -1470,7 +1476,7 @@ var shortcuts = map[desktop.CustomShortcut]func(){ Modifier: fyne.KeyModifierControl, }: actionBufferNext, { - KeyName: fyne.KeyPageDown, + KeyName: fyne.KeyDown, Modifier: fyne.KeyModifierAlt, }: actionBufferNext, { @@ -1480,11 +1486,7 @@ var shortcuts = map[desktop.CustomShortcut]func(){ { KeyName: fyne.KeyTab, Modifier: fyne.KeyModifierAlt, - }: func() { - if bufferLast != "" { - bufferActivate(bufferLast) - } - }, + }: actionBufferLast, { // XXX: This makes an assumption on the keyboard layout (we want '!'). KeyName: fyne.Key1, diff --git a/xC.c b/xC.c index 183eb52..6e84d91 100644 --- a/xC.c +++ b/xC.c @@ -918,10 +918,10 @@ g_input_actions[] = (const char *[]) { "C-f", "Right", NULL } }, { "backward-word", "Go back a word", input_backward_word, - (const char *[]) { "M-b", NULL } }, + (const char *[]) { "M-b", "M-Left", NULL } }, { "forward-word", "Go forward a word", input_forward_word, - (const char *[]) { "M-f", NULL } }, + (const char *[]) { "M-f", "M-Right", NULL } }, { "backward-delete-char", "Delete last character", input_backward_delete_char, @@ -14628,6 +14628,8 @@ app_input_init (struct input *self) input_bind (self, "C-p", "previous-buffer"); input_bind (self, "C-n", "next-buffer"); + input_bind (self, "M-Up", "previous-buffer"); + input_bind (self, "M-Down", "next-buffer"); input_bind (self, "F5", "previous-buffer"); input_bind (self, "F6", "next-buffer"); @@ -14635,6 +14637,7 @@ app_input_init (struct input *self) input_bind (self, (char[]) { 'M', '-', '0' + i }, "goto-buffer"); input_bind (self, "M-Tab", "switch-buffer"); + input_bind (self, "M-/", "switch-buffer"); input_bind (self, "M-!", "goto-highlight"); input_bind (self, "M-a", "goto-activity"); input_bind (self, "M-m", "insert-attribute"); diff --git a/xF.c b/xF.c index 015fc27..792440f 100644 --- a/xF.c +++ b/xF.c @@ -285,6 +285,8 @@ enum action ACTION_SCROLL_BOTTOM, ACTION_BUFFER_LIST_SCROLL_UP, ACTION_BUFFER_LIST_SCROLL_DOWN, + ACTION_BUFFER_LIST_SCROLL_TOP, + ACTION_BUFFER_LIST_SCROLL_BOTTOM, ACTION_SUBMIT, ACTION_COMPLETE, ACTION_HISTORY_PREVIOUS, @@ -3889,6 +3891,10 @@ app_process_action (enum action action) return app_scroll (WIDGET_BUFFER_LIST_SCROLLBAR, -page); case ACTION_BUFFER_LIST_SCROLL_DOWN: return app_scroll (WIDGET_BUFFER_LIST_SCROLLBAR, +page); + case ACTION_BUFFER_LIST_SCROLL_TOP: + return app_scroll (WIDGET_BUFFER_LIST_SCROLLBAR, INT_MIN); + case ACTION_BUFFER_LIST_SCROLL_BOTTOM: + return app_scroll (WIDGET_BUFFER_LIST_SCROLLBAR, INT_MAX); case ACTION_SUBMIT: app_submit_input (); return true; @@ -4004,6 +4010,9 @@ app_binding_cmp (const void *a, const void *b) return termo_keycmp (g_xui.tk, &aa->decoded, &bb->decoded); } +// Trying to map the origin of various bindings. +// https://tiswww.cwru.edu/php/chet/readline/rluserman.html +// https://weechat.org/files/doc/weechat/stable/weechat_user.en.html#key_bindings static const struct { const char *key; ///< Key definition @@ -4011,72 +4020,81 @@ static const struct } g_default_bindings[] = { - { "C-q", ACTION_QUIT }, - { "C-l", ACTION_REDRAW }, - { "C-F5", ACTION_RECONNECT }, - { "M-PageUp", ACTION_BUFFER_PREVIOUS }, - { "C-PageUp", ACTION_BUFFER_PREVIOUS }, - { "C-p", ACTION_BUFFER_PREVIOUS }, - { "F5", ACTION_BUFFER_PREVIOUS }, - { "M-PageDown", ACTION_BUFFER_NEXT }, - { "C-PageDown", ACTION_BUFFER_NEXT }, - { "C-n", ACTION_BUFFER_NEXT }, - { "F6", ACTION_BUFFER_NEXT }, - { "M-Tab", ACTION_BUFFER_LAST }, - { "M-!", ACTION_BUFFER_HIGHLIGHT }, - { "M-a", ACTION_BUFFER_ACTIVITY }, - { "M-H", ACTION_TOGGLE_UNIMPORTANT }, - { "M-h", ACTION_LOG }, - { "M-e", ACTION_EDIT_INPUT }, - { "M-E", ACTION_VIEW_TRANSCRIPT }, - { "C-o", ACTION_OPEN }, - { "M-m", ACTION_FORMAT }, - { "PageUp", ACTION_SCROLL_UP }, - { "PageDown", ACTION_SCROLL_DOWN }, - { "C-Home", ACTION_SCROLL_TOP }, - { "C-End", ACTION_SCROLL_BOTTOM }, - { "S-PageUp", ACTION_BUFFER_LIST_SCROLL_UP }, - { "S-PageDown", ACTION_BUFFER_LIST_SCROLL_DOWN }, - { "Enter", ACTION_SUBMIT }, - { "C-j", ACTION_SUBMIT }, - { "Tab", ACTION_COMPLETE }, - { "M-p", ACTION_HISTORY_PREVIOUS }, - { "Up", ACTION_HISTORY_PREVIOUS }, - { "M-n", ACTION_HISTORY_NEXT }, - { "Down", ACTION_HISTORY_NEXT }, - { "M-<", ACTION_HISTORY_FIRST }, - { "M->", ACTION_HISTORY_LAST }, - { "C-a", ACTION_EDITOR_HOME }, - { "Home", ACTION_EDITOR_HOME }, - { "C-e", ACTION_EDITOR_END }, - { "End", ACTION_EDITOR_END }, - { "C-b", ACTION_EDITOR_B_CHAR }, - { "Left", ACTION_EDITOR_B_CHAR }, - { "C-f", ACTION_EDITOR_F_CHAR }, - { "Right", ACTION_EDITOR_F_CHAR }, - { "M-b", ACTION_EDITOR_B_WORD }, - { "M-f", ACTION_EDITOR_F_WORD }, - { "M-u", ACTION_EDITOR_UPCASE_WORD }, - { "M-l", ACTION_EDITOR_DOWNCASE_WORD }, - { "M-c", ACTION_EDITOR_CAPITALIZE_WORD }, - { "C-h", ACTION_EDITOR_B_DELETE }, - { "DEL", ACTION_EDITOR_B_DELETE }, - { "Backspace", ACTION_EDITOR_B_DELETE }, - { "C-d", ACTION_EDITOR_F_DELETE }, - { "Delete", ACTION_EDITOR_F_DELETE }, - { "C-w", ACTION_EDITOR_B_KILL_WORD }, - { "C-u", ACTION_EDITOR_B_KILL_LINE }, - { "C-k", ACTION_EDITOR_F_KILL_LINE }, - { "M-1", ACTION_BUFFER_1 }, - { "M-2", ACTION_BUFFER_2 }, - { "M-3", ACTION_BUFFER_3 }, - { "M-4", ACTION_BUFFER_4 }, - { "M-5", ACTION_BUFFER_5 }, - { "M-6", ACTION_BUFFER_6 }, - { "M-7", ACTION_BUFFER_7 }, - { "M-8", ACTION_BUFFER_8 }, - { "M-9", ACTION_BUFFER_9 }, - { "M-0", ACTION_BUFFER_10 }, + { "C-q", ACTION_QUIT }, + { "C-l", ACTION_REDRAW }, + { "C-F5", ACTION_RECONNECT }, // xF + { "C-PageUp", ACTION_BUFFER_PREVIOUS }, // browsers + { "C-p", ACTION_BUFFER_PREVIOUS }, // WeeChat + { "M-Up", ACTION_BUFFER_PREVIOUS }, // WeeChat + { "F5", ACTION_BUFFER_PREVIOUS }, // WeeChat + { "C-PageDown", ACTION_BUFFER_NEXT }, // browsers + { "C-n", ACTION_BUFFER_NEXT }, // WeeChat + { "M-Down", ACTION_BUFFER_NEXT }, // WeeChat + { "F6", ACTION_BUFFER_NEXT }, // WeeChat + { "M-Tab", ACTION_BUFFER_LAST }, // xC + { "M-/", ACTION_BUFFER_LAST }, // WeeChat + { "M-!", ACTION_BUFFER_HIGHLIGHT }, // xC + { "M-a", ACTION_BUFFER_ACTIVITY }, // xC + { "M-H", ACTION_TOGGLE_UNIMPORTANT }, // xC + { "M-h", ACTION_LOG }, // xC + { "M-e", ACTION_EDIT_INPUT }, // xC + { "M-E", ACTION_VIEW_TRANSCRIPT }, // xF + { "C-o", ACTION_OPEN }, // xF + { "M-m", ACTION_FORMAT }, // xC + { "PageUp", ACTION_SCROLL_UP }, + { "PageDown", ACTION_SCROLL_DOWN }, + { "C-Home", ACTION_SCROLL_TOP }, // irssi + { "C-End", ACTION_SCROLL_BOTTOM }, // irssi + { "M-Home", ACTION_SCROLL_TOP }, // WeeChat + { "M-End", ACTION_SCROLL_BOTTOM }, // WeeChat + { "F1", ACTION_BUFFER_LIST_SCROLL_UP }, // WeeChat + { "F2", ACTION_BUFFER_LIST_SCROLL_DOWN }, // WeeChat + { "M-F1", ACTION_BUFFER_LIST_SCROLL_TOP }, // WeeChat + { "M-F2", ACTION_BUFFER_LIST_SCROLL_BOTTOM }, // WeeChat + { "Enter", ACTION_SUBMIT }, + { "C-j", ACTION_SUBMIT }, + { "Tab", ACTION_COMPLETE }, // Readline + { "M-p", ACTION_HISTORY_PREVIOUS }, // xP/xC + { "Up", ACTION_HISTORY_PREVIOUS }, // Readline + { "M-n", ACTION_HISTORY_NEXT }, // xP/xC + { "Down", ACTION_HISTORY_NEXT }, // Readline + { "M-<", ACTION_HISTORY_FIRST }, // Readline + { "M->", ACTION_HISTORY_LAST }, // Readline + { "C-a", ACTION_EDITOR_HOME }, // Readline/macOS + { "Home", ACTION_EDITOR_HOME }, + { "C-e", ACTION_EDITOR_END }, // Readline/macOS + { "End", ACTION_EDITOR_END }, + { "C-b", ACTION_EDITOR_B_CHAR }, // Readline/macOS + { "Left", ACTION_EDITOR_B_CHAR }, + { "C-f", ACTION_EDITOR_F_CHAR }, // Readline/macOS + { "Right", ACTION_EDITOR_F_CHAR }, + { "M-b", ACTION_EDITOR_B_WORD }, // Readline + { "M-Left", ACTION_EDITOR_B_WORD }, // macOS + { "C-Left", ACTION_EDITOR_B_WORD }, // WeeChat/... + { "M-f", ACTION_EDITOR_F_WORD }, // Readline + { "M-Right", ACTION_EDITOR_F_WORD }, // macOS + { "C-Right", ACTION_EDITOR_F_WORD }, // WeeChat/... + { "M-u", ACTION_EDITOR_UPCASE_WORD }, // Readline + { "M-l", ACTION_EDITOR_DOWNCASE_WORD }, // Readline + { "M-c", ACTION_EDITOR_CAPITALIZE_WORD }, // Readline + { "C-h", ACTION_EDITOR_B_DELETE }, // Readline/macOS + { "DEL", ACTION_EDITOR_B_DELETE }, + { "Backspace", ACTION_EDITOR_B_DELETE }, + { "C-d", ACTION_EDITOR_F_DELETE }, // Readline/macOS + { "Delete", ACTION_EDITOR_F_DELETE }, + { "C-w", ACTION_EDITOR_B_KILL_WORD }, // Readline + { "C-u", ACTION_EDITOR_B_KILL_LINE }, // Readline + { "C-k", ACTION_EDITOR_F_KILL_LINE }, // Readline/macOS + { "M-1", ACTION_BUFFER_1 }, // WeeChat + { "M-2", ACTION_BUFFER_2 }, // WeeChat + { "M-3", ACTION_BUFFER_3 }, // WeeChat + { "M-4", ACTION_BUFFER_4 }, // WeeChat + { "M-5", ACTION_BUFFER_5 }, // WeeChat + { "M-6", ACTION_BUFFER_6 }, // WeeChat + { "M-7", ACTION_BUFFER_7 }, // WeeChat + { "M-8", ACTION_BUFFER_8 }, // WeeChat + { "M-9", ACTION_BUFFER_9 }, // WeeChat + { "M-0", ACTION_BUFFER_10 }, // WeeChat }; static void diff --git a/xP/public/xP.js b/xP/public/xP.js index f6c3199..c3213a1 100644 --- a/xP/public/xP.js +++ b/xP/public/xP.js @@ -1261,14 +1261,15 @@ document.addEventListener('keydown', event => { } break case 'Tab': + case '/': if (bufferLast !== undefined) bufferActivate(bufferLast) break - case 'PageUp': + case 'ArrowUp': if (names.length > 1) bufferActivate(names.at(-1)) break - case 'PageDown': + case 'ArrowDown': if (names.length > 1) bufferActivate(names.at(+1)) break diff --git a/xT/xT.cpp b/xT/xT.cpp index b53a3a1..f5e2751 100644 --- a/xT/xT.cpp +++ b/xT/xT.cpp @@ -1664,16 +1664,18 @@ bind_shortcuts() g.wMain, switch_buffer); new QShortcut(QKeyCombination(Qt::AltModifier, Qt::Key_Tab), g.wMain, switch_buffer); + new QShortcut(QKeyCombination(Qt::AltModifier, Qt::Key_Slash), + g.wMain, switch_buffer); new QShortcut(QKeyCombination(Qt::NoModifier, Qt::Key_F5), g.wMain, previous_buffer); - new QShortcut(QKeyCombination(Qt::AltModifier, Qt::Key_PageUp), + new QShortcut(QKeyCombination(Qt::AltModifier, Qt::Key_Up), g.wMain, previous_buffer); new QShortcut(QKeyCombination(Qt::ControlModifier, Qt::Key_PageUp), g.wMain, previous_buffer); new QShortcut(QKeyCombination(Qt::NoModifier, Qt::Key_F6), g.wMain, next_buffer); - new QShortcut(QKeyCombination(Qt::AltModifier, Qt::Key_PageDown), + new QShortcut(QKeyCombination(Qt::AltModifier, Qt::Key_Down), g.wMain, next_buffer); new QShortcut(QKeyCombination(Qt::ControlModifier, Qt::Key_PageDown), g.wMain, next_buffer);