Add bind --list-modes option

Fixes #3872.
This commit is contained in:
Fabian Homborg 2017-03-16 18:35:44 +01:00
parent 536b1220fd
commit 70354f9f5e
5 changed files with 47 additions and 8 deletions

View file

@ -7,6 +7,7 @@ bind [(-M | --mode) MODE] [(-m | --sets-mode) NEW_MODE]
bind [(-M | --mode) MODE] [(-k | --key)] SEQUENCE bind [(-M | --mode) MODE] [(-k | --key)] SEQUENCE
bind (-K | --key-names) [(-a | --all)] bind (-K | --key-names) [(-a | --all)]
bind (-f | --function-names) bind (-f | --function-names)
bind (-L | --list-modes)
bind (-e | --erase) [(-M | --mode) MODE] bind (-e | --erase) [(-M | --mode) MODE]
(-a | --all | [(-k | --key)] SEQUENCE [SEQUENCE...]) (-a | --all | [(-k | --key)] SEQUENCE [SEQUENCE...])
\endfish \endfish
@ -43,6 +44,8 @@ The following parameters are available:
- `-f` or `--function-names` Display a list of available input functions - `-f` or `--function-names` Display a list of available input functions
- `-L` or `--list-modes` Display a list of defined bind modes
- `-M MODE` or `--mode MODE` Specify a bind mode that the bind is used in. Defaults to "default" - `-M MODE` or `--mode MODE` Specify a bind mode that the bind is used in. Defaults to "default"
- `-m NEW_MODE` or `--sets-mode NEW_MODE` Change the current mode to `NEW_MODE` after this binding is executed - `-m NEW_MODE` or `--sets-mode NEW_MODE` Change the current mode to `NEW_MODE` after this binding is executed

View file

@ -126,18 +126,14 @@ function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mod
# #
# See http://thejh.net/misc/website-terminal-copy-paste. The second case will not be caught in KDE konsole. # See http://thejh.net/misc/website-terminal-copy-paste. The second case will not be caught in KDE konsole.
# Bind the starting sequence in every bind mode, even user-defined ones. # Bind the starting sequence in every bind mode, even user-defined ones.
# HACK: We introspect `bind` here to list all modes.
# Re-running `bind` multiple times per mode is still faster than trying to make the list unique,
# even without calling `sort -u` or `uniq`, for the vi-bindings.
# TODO: This can be solved better once #3872 is implemented.
# We usually just pass the text through as-is to facilitate pasting code, # We usually just pass the text through as-is to facilitate pasting code,
# but when the current token contains an unbalanced single-quote (`'`), # but when the current token contains an unbalanced single-quote (`'`),
# we escape all single-quotes and backslashes, effectively turning the paste # we escape all single-quotes and backslashes, effectively turning the paste
# into one literal token, to facilitate pasting non-code (e.g. markdown or git commitishes) # into one literal token, to facilitate pasting non-code (e.g. markdown or git commitishes)
set -l allmodes default
set allmodes $allmodes (bind -a | string match -r -- '-M \w+' | string replace -- '-M ' '') # Exclude paste mode or there'll be an additional binding after switching between emacs and vi
for mode in $allmodes for mode in (bind --list-modes | string match -v paste)
bind -M $mode -m paste \e\[200~ '__fish_start_bracketed_paste' bind -M $mode -m paste \e\[200~ '__fish_start_bracketed_paste'
end end
# This sequence ends paste-mode and returns to the previous mode we have saved before. # This sequence ends paste-mode and returns to the previous mode we have saved before.

View file

@ -34,6 +34,7 @@
#include <memory> #include <memory>
#include <random> #include <random>
#include <string> #include <string>
#include <set>
#include <utility> #include <utility>
#include "builtin.h" #include "builtin.h"
@ -445,6 +446,22 @@ static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int u
return res; return res;
} }
/// List all current bind modes.
static void builtin_bind_list_modes(io_streams_t &streams) {
const std::vector<input_mapping_name_t> lst = input_mapping_get_names();
// A set accomplishes two things for us here:
// - It removes duplicates (no twenty "default" entries).
// - It sorts it, which makes it nicer on the user.
std::set<wcstring> modes;
for (const input_mapping_name_t &binding : lst) {
modes.insert(binding.mode);
}
for (const auto& mode : modes) {
streams.out.append_format(L"%ls\n", mode.c_str());
}
}
/// The bind builtin, used for setting character sequences. /// The bind builtin, used for setting character sequences.
static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) { static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
wgetopter_t w; wgetopter_t w;
@ -467,12 +484,13 @@ static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{L"key", no_argument, 0, 'k'}, {L"key", no_argument, 0, 'k'},
{L"key-names", no_argument, 0, 'K'}, {L"key-names", no_argument, 0, 'K'},
{L"mode", required_argument, 0, 'M'}, {L"mode", required_argument, 0, 'M'},
{L"list-modes", no_argument, 0, 'L'},
{L"sets-mode", required_argument, 0, 'm'}, {L"sets-mode", required_argument, 0, 'm'},
{0, 0, 0, 0}}; {0, 0, 0, 0}};
while (1) { while (1) {
int opt_index = 0; int opt_index = 0;
int opt = w.wgetopt_long_only(argc, argv, L"aehkKfM:m:", long_options, &opt_index); int opt = w.wgetopt_long_only(argc, argv, L"aehkKfM:Lm:", long_options, &opt_index);
if (opt == -1) break; if (opt == -1) break;
switch (opt) { switch (opt) {
@ -516,6 +534,10 @@ static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv)
sets_bind_mode = w.woptarg; sets_bind_mode = w.woptarg;
break; break;
} }
case 'L': {
builtin_bind_list_modes(streams);
return STATUS_BUILTIN_OK;
}
case '?': { case '?': {
builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]); builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;

View file

@ -41,6 +41,14 @@ expect_prompt -re {\r\nmno pqrt\r\n} {
puts stderr "emacs transpose words fail, default timeout: long delay" puts stderr "emacs transpose words fail, default timeout: long delay"
} }
# Now test that exactly the expected bind modes are defined
send "bind --list-modes\r"
expect_prompt -re {\r\ndefault\r\npaste} {
puts "emacs bind modes"
} unmatched {
puts stderr "Unexpected bind modes"
}
# Test vi key bindings. # Test vi key bindings.
# This should leave vi mode in the insert state. # This should leave vi mode in the insert state.
send "set -g fish_key_bindings fish_vi_key_bindings\r" send "set -g fish_key_bindings fish_vi_key_bindings\r"
@ -147,6 +155,14 @@ expect_prompt -re {\r\nTENT\r\n} {
puts stderr "Couldn't find expected output 'TENT'" puts stderr "Couldn't find expected output 'TENT'"
} }
# Now test that exactly the expected bind modes are defined
send "bind --list-modes\r"
expect_prompt -re {\r\ndefault\r\ninsert\r\npaste\r\nreplace-one\r\nvisual\r\n} {
puts "vi bind modes"
} unmatched {
puts stderr "Unexpected vi bind modes"
}
# Switch back to regular (emacs mode) key bindings. # Switch back to regular (emacs mode) key bindings.
send "set -g fish_key_bindings fish_default_key_bindings\r" send "set -g fish_key_bindings fish_default_key_bindings\r"
expect_prompt expect_prompt

View file

@ -1,6 +1,7 @@
emacs transpose words, default timeout: no delay emacs transpose words, default timeout: no delay
emacs transpose words, default timeout: short delay emacs transpose words, default timeout: short delay
emacs transpose words, default timeout: long delay emacs transpose words, default timeout: long delay
emacs bind modes
prime vi mode, default timeout prime vi mode, default timeout
vi-mode default timeout set correctly vi-mode default timeout set correctly
vi replace line, default timeout: long delay vi replace line, default timeout: long delay
@ -9,6 +10,7 @@ vi mode delete char, default timeout: long delay
vi replace line, 100ms timeout: long delay vi replace line, 100ms timeout: long delay
vi replace line, 100ms timeout: short delay vi replace line, 100ms timeout: short delay
t-binding success t-binding success
vi bind modes
default-mode custom timeout set correctly default-mode custom timeout set correctly
emacs transpose words, 100ms timeout: no delay emacs transpose words, 100ms timeout: no delay
emacs transpose words, 100ms timeout: short delay emacs transpose words, 100ms timeout: short delay