mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Implement jump-to-matching-bracket motion and bind % (percent) in vi mode
Part of #1842
This commit is contained in:
parent
c966c19c56
commit
f8ebe346a9
6 changed files with 81 additions and 0 deletions
|
@ -181,6 +181,7 @@ New or improved bindings
|
||||||
- When the cursor is at the start of a line, escaping from insert mode no longer moves the cursor to the previous line.
|
- When the cursor is at the start of a line, escaping from insert mode no longer moves the cursor to the previous line.
|
||||||
- Added bindings for clipboard interaction, like :kbd:`",+,p` and :kbd:`",+,y,y`.
|
- Added bindings for clipboard interaction, like :kbd:`",+,p` and :kbd:`",+,y,y`.
|
||||||
- Deleting in visual mode now moves the cursor back, matching vi (:issue:`10394`).
|
- Deleting in visual mode now moves the cursor back, matching vi (:issue:`10394`).
|
||||||
|
- Support :kbd:`%` motion.
|
||||||
|
|
||||||
Completions
|
Completions
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
|
|
@ -258,6 +258,11 @@ The following special input functions are available:
|
||||||
``repeat-jump`` and ``repeat-jump-reverse``
|
``repeat-jump`` and ``repeat-jump-reverse``
|
||||||
redo the last jump in the same/opposite direction
|
redo the last jump in the same/opposite direction
|
||||||
|
|
||||||
|
``jump-to-matching-bracket``
|
||||||
|
jump to matching bracket if the character under the cursor is bracket;
|
||||||
|
otherwise, jump to the next occurence of *any right* bracket after the cursor.
|
||||||
|
The following brackets are considered: ``([{}])``
|
||||||
|
|
||||||
``kill-bigword``
|
``kill-bigword``
|
||||||
move the next whitespace-delimited word to the killring
|
move the next whitespace-delimited word to the killring
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
|
||||||
bind -s --preset y,i backward-jump-till and repeat-jump-reverse and begin-selection repeat-jump kill-selection yank end-selection
|
bind -s --preset y,i backward-jump-till and repeat-jump-reverse and begin-selection repeat-jump kill-selection yank end-selection
|
||||||
bind -s --preset y,a backward-jump and repeat-jump-reverse and begin-selection repeat-jump kill-selection yank end-selection
|
bind -s --preset y,a backward-jump and repeat-jump-reverse and begin-selection repeat-jump kill-selection yank end-selection
|
||||||
|
|
||||||
|
bind -s --preset % jump-to-matching-bracket
|
||||||
bind -s --preset f forward-jump
|
bind -s --preset f forward-jump
|
||||||
bind -s --preset F backward-jump
|
bind -s --preset F backward-jump
|
||||||
bind -s --preset t forward-jump-till
|
bind -s --preset t forward-jump-till
|
||||||
|
@ -305,6 +306,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
|
||||||
bind -s --preset -M visual E 'set fish_cursor_end_mode exclusive' forward-single-char forward-bigword backward-char 'set fish_cursor_end_mode inclusive'
|
bind -s --preset -M visual E 'set fish_cursor_end_mode exclusive' forward-single-char forward-bigword backward-char 'set fish_cursor_end_mode inclusive'
|
||||||
bind -s --preset -M visual o swap-selection-start-stop repaint-mode
|
bind -s --preset -M visual o swap-selection-start-stop repaint-mode
|
||||||
|
|
||||||
|
bind -s --preset -M visual % jump-to-matching-bracket
|
||||||
bind -s --preset -M visual f forward-jump
|
bind -s --preset -M visual f forward-jump
|
||||||
bind -s --preset -M visual t forward-jump-till
|
bind -s --preset -M visual t forward-jump-till
|
||||||
bind -s --preset -M visual F backward-jump
|
bind -s --preset -M visual F backward-jump
|
||||||
|
|
|
@ -178,6 +178,7 @@ const INPUT_FUNCTION_METADATA: &[InputFunctionMetadata] = &[
|
||||||
make_md(L!("history-token-search-forward"), ReadlineCmd::HistoryTokenSearchForward),
|
make_md(L!("history-token-search-forward"), ReadlineCmd::HistoryTokenSearchForward),
|
||||||
make_md(L!("insert-line-over"), ReadlineCmd::InsertLineOver),
|
make_md(L!("insert-line-over"), ReadlineCmd::InsertLineOver),
|
||||||
make_md(L!("insert-line-under"), ReadlineCmd::InsertLineUnder),
|
make_md(L!("insert-line-under"), ReadlineCmd::InsertLineUnder),
|
||||||
|
make_md(L!("jump-to-matching-bracket"), ReadlineCmd::JumpToMatchingBracket),
|
||||||
make_md(L!("kill-bigword"), ReadlineCmd::KillBigword),
|
make_md(L!("kill-bigword"), ReadlineCmd::KillBigword),
|
||||||
make_md(L!("kill-inner-line"), ReadlineCmd::KillInnerLine),
|
make_md(L!("kill-inner-line"), ReadlineCmd::KillInnerLine),
|
||||||
make_md(L!("kill-line"), ReadlineCmd::KillLine),
|
make_md(L!("kill-line"), ReadlineCmd::KillLine),
|
||||||
|
|
|
@ -109,6 +109,7 @@ pub enum ReadlineCmd {
|
||||||
BackwardJump,
|
BackwardJump,
|
||||||
ForwardJumpTill,
|
ForwardJumpTill,
|
||||||
BackwardJumpTill,
|
BackwardJumpTill,
|
||||||
|
JumpToMatchingBracket,
|
||||||
FuncAnd,
|
FuncAnd,
|
||||||
FuncOr,
|
FuncOr,
|
||||||
ExpandAbbr,
|
ExpandAbbr,
|
||||||
|
|
|
@ -1739,6 +1739,42 @@ impl ReaderData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn jump_to_matching_bracket(
|
||||||
|
&mut self,
|
||||||
|
precision: JumpPrecision,
|
||||||
|
elt: EditableLineTag,
|
||||||
|
jump_from: usize,
|
||||||
|
l_bracket: char,
|
||||||
|
r_bracket: char,
|
||||||
|
) -> bool {
|
||||||
|
let el = self.edit_line(elt);
|
||||||
|
let mut tmp_r_pos: usize = 0;
|
||||||
|
let mut brackets_stack = Vec::new();
|
||||||
|
while tmp_r_pos < el.len() {
|
||||||
|
if el.at(tmp_r_pos) == l_bracket {
|
||||||
|
brackets_stack.push(tmp_r_pos);
|
||||||
|
} else if el.at(tmp_r_pos) == r_bracket {
|
||||||
|
match brackets_stack.pop() {
|
||||||
|
Some(tmp_l_pos) if jump_from == tmp_l_pos => {
|
||||||
|
return match precision {
|
||||||
|
JumpPrecision::Till => self.update_buff_pos(elt, Some(tmp_r_pos - 1)),
|
||||||
|
JumpPrecision::To => self.update_buff_pos(elt, Some(tmp_r_pos)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some(tmp_l_pos) if jump_from == tmp_r_pos => {
|
||||||
|
return match precision {
|
||||||
|
JumpPrecision::Till => self.update_buff_pos(elt, Some(tmp_l_pos + 1)),
|
||||||
|
JumpPrecision::To => self.update_buff_pos(elt, Some(tmp_l_pos)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp_r_pos += 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fn jump_and_remember_last_jump(
|
fn jump_and_remember_last_jump(
|
||||||
&mut self,
|
&mut self,
|
||||||
direction: JumpDirection,
|
direction: JumpDirection,
|
||||||
|
@ -3113,6 +3149,41 @@ impl<'a> Reader<'a> {
|
||||||
self.input_data.function_set_status(success);
|
self.input_data.function_set_status(success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rl::JumpToMatchingBracket => {
|
||||||
|
let (elt, _el) = self.active_edit_line();
|
||||||
|
let el = self.edit_line(elt);
|
||||||
|
let l_brackets = ['(', '[', '{'];
|
||||||
|
let r_brackets = [')', ']', '}'];
|
||||||
|
let jump_from_pos = el.position();
|
||||||
|
let precision = JumpPrecision::To;
|
||||||
|
let success = if l_brackets.contains(&el.at(jump_from_pos))
|
||||||
|
|| r_brackets.contains(&el.at(jump_from_pos))
|
||||||
|
{
|
||||||
|
let l_bracket = match el.at(jump_from_pos) {
|
||||||
|
'(' | ')' => '(',
|
||||||
|
'[' | ']' => '[',
|
||||||
|
'{' | '}' => '{',
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let r_bracket = match l_bracket {
|
||||||
|
'(' => ')',
|
||||||
|
'[' => ']',
|
||||||
|
'{' => '}',
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
self.jump_to_matching_bracket(
|
||||||
|
precision,
|
||||||
|
elt,
|
||||||
|
jump_from_pos,
|
||||||
|
l_bracket,
|
||||||
|
r_bracket,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// If we stand on non-bracket character, we prefer to jump forward
|
||||||
|
self.jump(JumpDirection::Forward, precision, elt, r_brackets.to_vec())
|
||||||
|
};
|
||||||
|
self.input_data.function_set_status(success);
|
||||||
|
}
|
||||||
rl::RepeatJump => {
|
rl::RepeatJump => {
|
||||||
let (elt, _el) = self.active_edit_line();
|
let (elt, _el) = self.active_edit_line();
|
||||||
let mut success = false;
|
let mut success = false;
|
||||||
|
|
Loading…
Reference in a new issue