Show file location when querying bindings with bind

Closes #12215
Closes #12504
Closes #12221
This commit is contained in:
ritoban23
2025-12-28 08:44:36 +05:30
committed by Johannes Altmanninger
parent eb535322d0
commit 11d6e92cb5
9 changed files with 242 additions and 165 deletions

View File

@@ -11,6 +11,7 @@ Interactive improvements
This means that on systems where fish version 3.x was installed originally, the update will avoid creating that file (:issue:`12725`).
- ``fish_hg_prompt``, ``fish_git_prompt`` and ``fish_fossil_prompt`` now strip control characters from VCS state read off disk, matching ``prompt_pwd``.
- The sample informative and minimalist prompts now use ``prompt_pwd`` instead of printing ``$PWD`` directly.
- ``bind`` shows the file where bindings were defined (:issue:`12504`).
For distributors and developers
-------------------------------

View File

@@ -1,12 +0,0 @@
# localization: skip(private)
function __fish_per_os_bind
set -l macos $argv[-2]
set -l non_macos $argv[-1]
set -e argv[-2..-1]
for varname in macos non_macos
if contains -- $$varname (bind --function-names)
set $varname 'commandline -f '$$varname
end
end
bind $argv "if fish_in_macos_terminal; $macos; else $non_macos; end"
end

View File

@@ -0,0 +1,14 @@
# localization: skip(private)
function __fish_per_os_bind_body
printf %s '
set -l macos $argv[-2]
set -l non_macos $argv[-1]
set -e argv[-2..-1]
for varname in macos non_macos
if contains -- $$varname (bind --function-names)
set $varname \'commandline -f \'$$varname
end
end
bind $argv "if fish_in_macos_terminal; $macos; else $non_macos; end"
'
end

View File

@@ -1,132 +1,131 @@
# localization: skip(private)
function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mode"
function __fish_shared_key_bindings -d "Prints function body for bindings shared between emacs and vi mode"
# These are some bindings that are supposed to be shared between vi mode and default mode.
# They are supposed to be unrelated to text-editing (or movement).
# This takes $argv so the vi-bindings can pass the mode they are valid in.
if contains -- -h $argv
or contains -- --help $argv
echo "Sorry but this function doesn't support -h or --help" >&2
return 1
end
bind --preset $argv ctrl-y yank
or return # protect against invalid $argv
bind --preset $argv alt-y yank-pop
# Left/Right arrow
bind --preset $argv right forward-char
bind --preset $argv left backward-char
# Ctrl-left/right - these also work in vim.
__fish_per_os_bind --preset $argv ctrl-right forward-token forward-word
__fish_per_os_bind --preset $argv ctrl-left backward-token backward-word
bind --preset $argv pageup beginning-of-history
bind --preset $argv pagedown end-of-history
# Interaction with the system clipboard.
bind --preset $argv ctrl-x fish_clipboard_copy
bind --preset $argv ctrl-v fish_clipboard_paste
bind --preset $argv escape cancel
bind --preset $argv ctrl-\[ cancel
bind --preset $argv tab complete
bind --preset $argv ctrl-i complete
bind --preset $argv ctrl-s pager-toggle-search
# shift-tab does a tab complete followed by a search.
bind --preset $argv shift-tab complete-and-search
bind --preset $argv shift-delete history-delete or backward-delete-char
bind --preset $argv down down-or-search
bind --preset $argv up up-or-search
bind --preset $argv shift-right forward-bigword
bind --preset $argv shift-left backward-bigword
bind --preset $argv alt-b prevd-or-backward-word
bind --preset $argv alt-f nextd-or-forward-word
for alt_right in alt-right \e\[1\;9C # TODO(terminal-workaround) iTerm2 < 3.5.12
__fish_per_os_bind --preset $argv $alt_right \
nextd-or-forward-word nextd-or-forward-token
end
for alt_left in alt-left \e\[1\;9D # TODO(terminal-workaround) iTerm2 < 3.5.12
__fish_per_os_bind --preset $argv $alt_left \
prevd-or-backward-word prevd-or-backward-token
end
bind --preset $argv alt-up history-token-search-backward
bind --preset $argv alt-down history-token-search-forward
# TODO(terminal-workaround)
bind --preset $argv \e\[1\;9A history-token-search-backward # iTerm2 < 3.5.12
bind --preset $argv \e\[1\;9B history-token-search-forward # iTerm2 < 3.5.12
# Bash compatibility
# https://github.com/fish-shell/fish-shell/issues/89
bind --preset $argv alt-. history-token-search-backward
bind --preset $argv alt-l __fish_list_current_token
bind --preset $argv alt-o __fish_preview_current_file
bind --preset $argv alt-w __fish_whatis_current_token
bind --preset $argv ctrl-l \
'status test-terminal-feature scroll-content-up && commandline -f scrollback-push' \
clear-screen
bind --preset $argv ctrl-c clear-commandline
bind --preset $argv ctrl-u backward-kill-line
bind --preset $argv ctrl-k kill-line
bind --preset $argv ctrl-w backward-kill-path-component
bind --preset $argv end end-of-line
bind --preset $argv home beginning-of-line
bind --preset $argv alt-d 'if test "$(commandline; printf .)" = \n.; __fish_echo dirh; else; commandline -f kill-word; end'
bind --preset $argv ctrl-d delete-or-exit
bind --preset $argv alt-s 'for cmd in sudo doas please run0; if command -q $cmd; fish_commandline_prepend $cmd; break; end; end'
# Allow reading manpages by pressing f1 (many GUI applications) or Alt+h (like in zsh).
bind --preset $argv f1 __fish_man_page
bind --preset $argv alt-h __fish_man_page
# This will make sure the output of the current command is paged using the default pager when
# you press Meta-p.
# If none is set, less will be used.
bind --preset $argv alt-p __fish_paginate
# Make it easy to turn an unexecuted command into a comment in the shell history. Also,
# remove the commenting chars so the command can be further edited then executed.
bind --preset $argv alt-# __fish_toggle_comment_commandline
# These keystrokes invoke an external editor on the command buffer.
bind --preset $argv alt-e edit_command_buffer
bind --preset $argv alt-v edit_command_buffer
# Bindings that are shared in text-insertion modes.
if not set -l index (contains --index -- -M $argv)
or test $argv[(math $index + 1)] = insert
# This is the default binding, i.e. the one used if no other binding matches
bind --preset $argv "" self-insert
or exit # protect against invalid $argv
# Space and other command terminators expands abbrs _and_ inserts itself.
bind --preset $argv space self-insert expand-abbr
bind --preset $argv ";" self-insert expand-abbr
bind --preset $argv "|" self-insert expand-abbr
bind --preset $argv "&" self-insert expand-abbr
bind --preset $argv ">" self-insert expand-abbr
bind --preset $argv "<" self-insert expand-abbr
set -l maybe_search_field '(commandline --search-field >/dev/null && echo --search-field)'
bind --preset $argv shift-enter "commandline -i \n $maybe_search_field" expand-abbr
bind --preset $argv alt-enter "commandline -i \n $maybe_search_field" expand-abbr
bind --preset $argv ")" self-insert expand-abbr # Closing a command substitution.
bind --preset $argv ctrl-space 'test -n "$(commandline)" && commandline -i " " '$maybe_search_field
# Shift-space behaves like space because it's easy to mistype.
bind --preset $argv shift-space 'commandline -i " " '$maybe_search_field expand-abbr
bind --preset $argv enter execute
bind --preset $argv ctrl-j execute
bind --preset $argv ctrl-m execute
# Make Control+Return behave like Return because it's easy to mistype after accepting an autosuggestion.
bind --preset $argv ctrl-enter execute
end
printf %s '
if contains -- -h $argv
or contains -- --help $argv
echo "Sorry but this function doesn\'t support -h or --help" >&2
return 1
end
bind --preset $argv ctrl-y yank
or return # protect against invalid $argv
bind --preset $argv alt-y yank-pop
# Left/Right arrow
bind --preset $argv right forward-char
bind --preset $argv left backward-char
# Ctrl-left/right - these also work in vim.
__fish_per_os_bind --preset $argv ctrl-right forward-token forward-word
__fish_per_os_bind --preset $argv ctrl-left backward-token backward-word
bind --preset $argv pageup beginning-of-history
bind --preset $argv pagedown end-of-history
# Interaction with the system clipboard.
bind --preset $argv ctrl-x fish_clipboard_copy
bind --preset $argv ctrl-v fish_clipboard_paste
bind --preset $argv escape cancel
bind --preset $argv ctrl-\[ cancel
bind --preset $argv tab complete
bind --preset $argv ctrl-i complete
bind --preset $argv ctrl-s pager-toggle-search
# shift-tab does a tab complete followed by a search.
bind --preset $argv shift-tab complete-and-search
bind --preset $argv shift-delete history-delete or backward-delete-char
bind --preset $argv down down-or-search
bind --preset $argv up up-or-search
bind --preset $argv shift-right forward-bigword
bind --preset $argv shift-left backward-bigword
bind --preset $argv alt-b prevd-or-backward-word
bind --preset $argv alt-f nextd-or-forward-word
for alt_right in alt-right \e\[1\;9C # TODO(terminal-workaround) iTerm2 < 3.5.12
__fish_per_os_bind --preset $argv $alt_right \
nextd-or-forward-word nextd-or-forward-token
end
for alt_left in alt-left \e\[1\;9D # TODO(terminal-workaround) iTerm2 < 3.5.12
__fish_per_os_bind --preset $argv $alt_left \
prevd-or-backward-word prevd-or-backward-token
end
bind --preset $argv alt-up history-token-search-backward
bind --preset $argv alt-down history-token-search-forward
# TODO(terminal-workaround)
bind --preset $argv \e\[1\;9A history-token-search-backward # iTerm2 < 3.5.12
bind --preset $argv \e\[1\;9B history-token-search-forward # iTerm2 < 3.5.12
# Bash compatibility
# https://github.com/fish-shell/fish-shell/issues/89
bind --preset $argv alt-. history-token-search-backward
bind --preset $argv alt-l __fish_list_current_token
bind --preset $argv alt-o __fish_preview_current_file
bind --preset $argv alt-w __fish_whatis_current_token
bind --preset $argv ctrl-l \
"status test-terminal-feature scroll-content-up && commandline -f scrollback-push" \
clear-screen
bind --preset $argv ctrl-c clear-commandline
bind --preset $argv ctrl-u backward-kill-line
bind --preset $argv ctrl-k kill-line
bind --preset $argv ctrl-w backward-kill-path-component
bind --preset $argv end end-of-line
bind --preset $argv home beginning-of-line
bind --preset $argv alt-d \'if test "$(commandline; printf .)" = \n.; __fish_echo dirh; else; commandline -f kill-word; end\'
bind --preset $argv ctrl-d delete-or-exit
bind --preset $argv alt-s \'for cmd in sudo doas please run0; if command -q $cmd; fish_commandline_prepend $cmd; break; end; end\'
# Allow reading manpages by pressing f1 (many GUI applications) or Alt+h (like in zsh).
bind --preset $argv f1 __fish_man_page
bind --preset $argv alt-h __fish_man_page
# This will make sure the output of the current command is paged using the default pager when
# you press Meta-p.
# If none is set, less will be used.
bind --preset $argv alt-p __fish_paginate
# Make it easy to turn an unexecuted command into a comment in the shell history. Also,
# remove the commenting chars so the command can be further edited then executed.
bind --preset $argv alt-# __fish_toggle_comment_commandline
# These keystrokes invoke an external editor on the command buffer.
bind --preset $argv alt-e edit_command_buffer
bind --preset $argv alt-v edit_command_buffer
# Bindings that are shared in text-insertion modes.
if not set -l index (contains --index -- -M $argv)
or test $argv[(math $index + 1)] = insert
# This is the default binding, i.e. the one used if no other binding matches
bind --preset $argv "" self-insert
or exit # protect against invalid $argv
# Space and other command terminators expands abbrs _and_ inserts itself.
bind --preset $argv space self-insert expand-abbr
bind --preset $argv ";" self-insert expand-abbr
bind --preset $argv "|" self-insert expand-abbr
bind --preset $argv "&" self-insert expand-abbr
bind --preset $argv ">" self-insert expand-abbr
bind --preset $argv "<" self-insert expand-abbr
set -l maybe_search_field "(commandline --search-field >/dev/null && echo --search-field)"
bind --preset $argv shift-enter "commandline -i \n $maybe_search_field" expand-abbr
bind --preset $argv alt-enter "commandline -i \n $maybe_search_field" expand-abbr
bind --preset $argv ")" self-insert expand-abbr # Closing a command substitution.
bind --preset $argv ctrl-space \'test -n "$(commandline)" && commandline -i " " \'$maybe_search_field
# Shift-space behaves like space because it\'s easy to mistype.
bind --preset $argv shift-space \'commandline -i " " \'$maybe_search_field expand-abbr
bind --preset $argv enter execute
bind --preset $argv ctrl-j execute
bind --preset $argv ctrl-m execute
# Make Control+Return behave like Return because it\'s easy to mistype after accepting an autosuggestion.
bind --preset $argv ctrl-enter execute
end'
end

View File

@@ -13,13 +13,12 @@ function fish_default_key_bindings -d "emacs-like key binds"
end
end
# Silence warnings about unavailable keys. See #4431, 4188
if not contains -- -s $argv
set argv -s $argv
function __fish_per_os_bind
eval "$(__fish_per_os_bind_body)"
end
# These are shell-specific bindings that we share with vi mode.
__fish_shared_key_bindings $argv
eval "$(__fish_shared_key_bindings)" $argv
or return # protect against invalid $argv
bind --preset $argv right forward-char
@@ -50,11 +49,13 @@ function fish_default_key_bindings -d "emacs-like key binds"
bind --preset $argv alt-u upcase-word
bind --preset $argv alt-c capitalize-word
__fish_per_os_bind --preset $argv alt-backspace backward-kill-word backward-kill-token
__fish_per_os_bind --preset $argv ctrl-alt-h backward-kill-word backward-kill-token
__fish_per_os_bind --preset $argv ctrl-backspace backward-kill-token backward-kill-word
__fish_per_os_bind --preset $argv alt-delete kill-word kill-token
__fish_per_os_bind --preset $argv ctrl-delete kill-token kill-word
functions --erase __fish_per_os_bind
bind --preset $argv alt-\< beginning-of-buffer
bind --preset $argv alt-\> end-of-buffer

View File

@@ -324,13 +324,22 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
echo "Unknown argument $argv" >&2
end
function __fish_vi_key_bindings_shared
eval "$(__fish_shared_key_bindings)"
end
function __fish_per_os_bind
eval "$(__fish_per_os_bind_body)"
end
# Inherit shared key bindings.
# Do this first so vi-bindings win over default.
for mode in insert default visual
__fish_shared_key_bindings -M $mode
__fish_vi_key_bindings_shared -M $mode
__fish_per_os_bind --preset -M $mode ctrl-right forward-token forward-word-vi
# ctrl-left is same as emacs mode
end
functions -e __fish_vi_key_bindings_shared
functions -e __fish_per_os_bind
# Add a way to switch from insert to normal (command) mode.
# Note if we are paging, we want to stay in insert mode

View File

@@ -5,7 +5,7 @@
builtins::error::Error,
common::valid_var_name,
err_fmt, err_raw, err_str,
highlight::highlight_and_colorize,
highlight::{colorize, highlight_and_colorize, highlight_shell},
input::{
InputMapping, InputMappingSet, KeyNameStyle, input_function_get_names, input_mappings,
},
@@ -137,6 +137,7 @@ fn generate_output_string(seq: &[Key], user: bool, bind: &InputMapping) -> WStri
out.push(' ');
out.push_utfstr(&escape(ecmd));
}
out.push('\n');
out
@@ -209,11 +210,32 @@ fn list(
streams: &mut IoStreams,
) {
let lst = self.input_mappings.get_names(user);
let mut cur_file = None;
for binding in lst {
let mut out = WString::new();
let definition_file =
&self.input_mappings.get(&binding.seq, bind_mode, user)[0].definition_file;
if let Some(def_file) = definition_file {
if Some(def_file) != cur_file {
out.push_utfstr(&L!("# Defined in "));
out.push_utfstr(&**def_file);
out.push_utfstr(&L!(":\n"));
streams.out.append(&if streams.out_is_redirected {
out
} else {
let mut colors = Vec::new();
highlight_shell(&out, &mut colors, &mut parser.context(), false, None);
let colored = colorize(&out, &colors, parser.vars());
bytes2wcstring(&colored)
});
cur_file = Some(def_file);
}
}
if bind_mode.is_some_and(|m| m != binding.mode) {
continue;
}
self.list_one(&binding.seq, Some(&binding.mode), user, parser, streams);
}
}
@@ -243,6 +265,7 @@ fn function_names(&self, streams: &mut IoStreams) {
}
/// Add specified key binding.
#[allow(clippy::too_many_arguments)]
fn add(
&mut self,
seq: &wstr,
@@ -250,6 +273,7 @@ fn add(
mode: WString,
sets_mode: Option<WString>,
user: bool,
parser: &Parser,
streams: &mut IoStreams,
) -> bool {
let cmds = cmds.iter().map(|&s| s.to_owned()).collect();
@@ -262,8 +286,16 @@ fn add(
} else {
KeyNameStyle::Plain
};
self.input_mappings
.add(key_seq, key_name_style, cmds, mode, sets_mode, user);
let definition_file = parser.current_filename();
self.input_mappings.add(
key_seq,
key_name_style,
cmds,
mode,
sets_mode,
user,
definition_file,
);
false
}
@@ -383,6 +415,7 @@ fn insert(
.unwrap_or(DEFAULT_BIND_MODE.to_owned()),
self.opts.sets_bind_mode.clone(),
self.opts.user,
parser,
streams,
) {
return true;
@@ -410,11 +443,11 @@ fn list_modes(&mut self, streams: &mut IoStreams) {
}
fn parse_cmd_opts(
parser: &Parser,
streams: &mut IoStreams,
opts: &mut Options,
optind: &mut usize,
argv: &mut [&wstr],
parser: &mut Parser,
streams: &mut IoStreams,
) -> BuiltinResult {
let cmd = argv[0];
let short_options = L!("aehkKfM:Lm:s");
@@ -521,7 +554,7 @@ pub fn bind(
) -> BuiltinResult {
let cmd = argv[0];
let mut optind = 0;
parse_cmd_opts(&mut self.opts, &mut optind, argv, parser, streams)?;
parse_cmd_opts(parser, streams, &mut self.opts, &mut optind, argv)?;
if self.opts.list_modes {
self.list_modes(streams);

View File

@@ -11,7 +11,7 @@
reader::{Reader, reader_reset_interrupted},
threads::assert_is_main_thread,
};
use fish_common::{Named, assert_sorted_by_name, escape, get_by_sorted_name};
use fish_common::{FilenameRef, Named, assert_sorted_by_name, escape, get_by_sorted_name};
use std::{
mem,
sync::{
@@ -53,6 +53,8 @@ pub struct InputMapping {
pub sets_mode: Option<WString>,
/// Perhaps this binding was created using a raw escape sequence.
pub key_name_style: KeyNameStyle,
/// The file from which the binding was created, or None if not from a file.
pub definition_file: Option<FilenameRef>,
}
impl InputMapping {
@@ -63,6 +65,7 @@ fn new(
mode: WString,
sets_mode: Option<WString>,
key_name_style: KeyNameStyle,
definition_file: Option<FilenameRef>,
) -> InputMapping {
static LAST_INPUT_MAP_SPEC_ORDER: AtomicU32 = AtomicU32::new(0);
let specification_order = 1 + LAST_INPUT_MAP_SPEC_ORDER.fetch_add(1, Ordering::Relaxed);
@@ -77,6 +80,7 @@ fn new(
mode,
sets_mode,
key_name_style,
definition_file,
}
}
@@ -289,6 +293,7 @@ fn input_mapping_insert_sorted(ml: &mut Vec<InputMapping>, new_mapping: InputMap
impl InputMappingSet {
/// Adds an input mapping.
#[allow(clippy::too_many_arguments)]
pub fn add(
&mut self,
sequence: Vec<Key>,
@@ -297,6 +302,7 @@ pub fn add(
mode: WString,
sets_mode: Option<WString>,
user: bool,
definition_file: Option<FilenameRef>,
) {
// Update any existing mapping with this sequence.
// FIXME: this makes adding multiple bindings quadratic.
@@ -309,16 +315,25 @@ pub fn add(
if m.seq == sequence && m.mode == mode {
m.commands = commands;
m.sets_mode = sets_mode;
m.definition_file = definition_file;
return;
}
}
// Add a new mapping, using the next order.
let new_mapping = InputMapping::new(sequence, commands, mode, sets_mode, key_name_style);
let new_mapping = InputMapping::new(
sequence,
commands,
mode,
sets_mode,
key_name_style,
definition_file,
);
input_mapping_insert_sorted(ml, new_mapping);
}
// Like add(), but takes a single command.
#[allow(clippy::too_many_arguments)]
pub fn add1(
&mut self,
sequence: Vec<Key>,
@@ -327,6 +342,7 @@ pub fn add1(
mode: WString,
sets_mode: Option<WString>,
user: bool,
definition_file: Option<FilenameRef>,
) {
self.add(
sequence,
@@ -335,6 +351,7 @@ pub fn add1(
mode,
sets_mode,
user,
definition_file,
);
}
}
@@ -357,7 +374,15 @@ pub fn init_input() {
let mut add = |key: Vec<Key>, cmd: &str| {
let mode = DEFAULT_BIND_MODE.to_owned();
let sets_mode = Some(DEFAULT_BIND_MODE.to_owned());
input_mapping.add1(key, KeyNameStyle::Plain, cmd.into(), mode, sets_mode, false);
input_mapping.add1(
key,
KeyNameStyle::Plain,
cmd.into(),
mode,
sets_mode,
false,
None,
);
};
add(vec![], "self-insert");
@@ -390,6 +415,7 @@ pub fn init_input() {
mode,
sets_mode,
false,
None,
);
};
add_raw("\x1B[A", "up-line");
@@ -1044,6 +1070,7 @@ fn test_input() {
bind_mode(),
None,
true,
None,
);
input_mappings.add1(
desired_binding.clone(),
@@ -1052,6 +1079,7 @@ fn test_input() {
bind_mode(),
None,
true,
None,
);
// Push the desired binding to the queue.

View File

@@ -8,11 +8,11 @@ for bindings in true fish_default_key_bindings fish_vi_key_bindings
$fish -c "
$bindings
or echo >&2 error setting bindings: status=\$status
bind > $tmpdir/old
bind | string match -r -v '^# Defined in' > $tmpdir/old
bind --erase --all --preset
bind --erase --all
source $tmpdir/old
bind >$tmpdir/new
bind | string match -r -v '^# Defined in' >$tmpdir/new
diff -u $tmpdir/{old,new}
"
end
@@ -35,8 +35,12 @@ bind -M bind-mode \cX true
bind -M bind_mode \cX true
# Listing bindings
bind | string match -v '*\e\\[*' # Hide raw bindings.
bind --user --preset | string match -v '*\e\\[*'
{
bind
bind --user --preset
} |
string match -v '*\e\\[*' | # Hide raw bindings.
string match -r -v '^# Defined in'
# CHECK: bind --preset '' self-insert
# CHECK: bind --preset enter execute
# CHECK: bind --preset tab complete
@@ -75,7 +79,7 @@ bind --user --preset | string match -v '*\e\\[*'
# CHECK: bind -M bind_mode ctrl-x true
# Preset only
bind --preset | string match -v '*\e\\[*'
bind --preset | string match -v '*\e\\[*' | string match -r -v '^# Defined in'
# CHECK: bind --preset '' self-insert
# CHECK: bind --preset enter execute
# CHECK: bind --preset tab complete
@@ -95,12 +99,12 @@ bind --preset | string match -v '*\e\\[*'
# CHECK: bind --preset ctrl-f forward-char
# User only
bind --user | string match -v '*\e\\[*'
bind --user | string match -v '*\e\\[*' | string match -r -v '^# Defined in'
# CHECK: bind -M bind_mode ctrl-x true
# Adding bindings
bind tab 'echo banana'
bind | string match -v '*\e\\[*'
bind | string match -v '*\e\\[*' | string match -r -v '^# Defined in'
# CHECK: bind --preset '' self-insert
# CHECK: bind --preset enter execute
# CHECK: bind --preset tab complete
@@ -132,15 +136,15 @@ bind super-alt-\~
# Legacy
bind \cx\cax 'echo foo'
bind \cx\cax
bind \cx\cax | string match -r -v '^# Defined in'
# CHECK: bind ctrl-x,ctrl-a,x 'echo foo'
bind \ef forward-word
bind \ef
bind \ef | string match -r -v '^# Defined in'
# CHECK: bind alt-f forward-word
# Erasing bindings
bind --erase tab
bind tab
bind tab | string match -r -v '^# Defined in'
bind tab 'echo wurst'
# CHECK: bind --preset tab complete
bind --erase --user --preset tab
@@ -154,7 +158,7 @@ bind -k nul 'echo foo'
# CHECKERR: bind: the -k/--key syntax is no longer supported. See `bind --help` and `bind --key-names`
# Either Return or ctrl-m.
bind \r
bind \r | string match -r -v '^# Defined in'
# CHECK: bind --preset enter execute
# Never Return, probably always ctrl-j.
bind \n 2>&1