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 (-K | --key-names) [(-a | --all)]
bind (-f | --function-names)
bind (-L | --list-modes)
bind (-e | --erase) [(-M | --mode) MODE]
(-a | --all | [(-k | --key)] SEQUENCE [SEQUENCE...])
\endfish
@ -43,6 +44,8 @@ The following parameters are available:
- `-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 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.
# 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,
# but when the current token contains an unbalanced single-quote (`'`),
# 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)
set -l allmodes default
set allmodes $allmodes (bind -a | string match -r -- '-M \w+' | string replace -- '-M ' '')
for mode in $allmodes
# Exclude paste mode or there'll be an additional binding after switching between emacs and vi
for mode in (bind --list-modes | string match -v paste)
bind -M $mode -m paste \e\[200~ '__fish_start_bracketed_paste'
end
# This sequence ends paste-mode and returns to the previous mode we have saved before.

View file

@ -34,6 +34,7 @@
#include <memory>
#include <random>
#include <string>
#include <set>
#include <utility>
#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;
}
/// 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.
static int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
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-names", no_argument, 0, 'K'},
{L"mode", required_argument, 0, 'M'},
{L"list-modes", no_argument, 0, 'L'},
{L"sets-mode", required_argument, 0, 'm'},
{0, 0, 0, 0}};
while (1) {
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;
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;
break;
}
case 'L': {
builtin_bind_list_modes(streams);
return STATUS_BUILTIN_OK;
}
case '?': {
builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
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"
}
# 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.
# This should leave vi mode in the insert state.
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'"
}
# 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.
send "set -g fish_key_bindings fish_default_key_bindings\r"
expect_prompt

View file

@ -1,6 +1,7 @@
emacs transpose words, default timeout: no delay
emacs transpose words, default timeout: short delay
emacs transpose words, default timeout: long delay
emacs bind modes
prime vi mode, default timeout
vi-mode default timeout set correctly
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: short delay
t-binding success
vi bind modes
default-mode custom timeout set correctly
emacs transpose words, 100ms timeout: no delay
emacs transpose words, 100ms timeout: short delay