diff --git a/CHANGELOG.rst b/CHANGELOG.rst index aa1ddfcd8..ec0469d12 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -39,6 +39,10 @@ Interactive improvements - When using the exe name (``foo.exe``), fish will use to the description and completions for ``foo`` if there are none for ``foo.exe``. - Autosuggestions now also show soft-wrapped portions (:issue:`12045`). +New or improved bindings +------------------------ +- Added `backward-path-component`, `forward-path-component` and `kill-path-component` (:issue:`12127`). + Improved terminal support ------------------------- - Themes can now be made color-theme-aware (i.e. light mode vs. dark mode) by including both ``[light]`` and ``[dark]`` sections in the :ref:`theme file `. diff --git a/doc_src/cmds/bind.rst b/doc_src/cmds/bind.rst index a3c0d4fb0..e444c017c 100644 --- a/doc_src/cmds/bind.rst +++ b/doc_src/cmds/bind.rst @@ -145,12 +145,17 @@ The following special input functions are available: ``backward-kill-line`` move everything from the beginning of the line to the cursor to the killring +.. _cmd-bind-backward-kill-path-component: + ``backward-kill-path-component`` move one path component to the left of the cursor to the killring. A path component is everything likely to belong to a path component, i.e. not any of the following: `/={,}'\":@ |;<>&`, plus newlines and tabs. ``backward-kill-word`` move the word to the left of the cursor to the killring. The "word" here is everything up to punctuation or whitespace. +``backward-path-component`` + move one :ref:`path component ` to the left. + ``backward-word`` move one word to the left @@ -241,6 +246,9 @@ The following special input functions are available: commandline, does not accept the current autosuggestion (if any). Does not change the selected item in the completion pager, if shown. +``forward-path-component`` + move one :ref:`path component ` to the right; or if at the end of the commandline, accept a path component from the current autosuggestion. + ``forward-single-char`` move one character to the right; or if at the end of the commandline, accept a single char from the current autosuggestion. @@ -308,6 +316,9 @@ The following special input functions are available: ``kill-line`` move everything from the cursor to the end of the line to the killring +``kill-path-component`` + move one :ref:`path component ` to the killring. + ``kill-selection`` move the selected text to the killring diff --git a/src/input.rs b/src/input.rs index bb55ab0ea..6a138295d 100644 --- a/src/input.rs +++ b/src/input.rs @@ -118,6 +118,7 @@ const fn make_md(name: &'static wstr, code: ReadlineCmd) -> InputFunctionMetadat make_md(L!("backward-kill-path-component"), ReadlineCmd::BackwardKillPathComponent), make_md(L!("backward-kill-token"), ReadlineCmd::BackwardKillToken), make_md(L!("backward-kill-word"), ReadlineCmd::BackwardKillWord), + make_md(L!("backward-path-component"), ReadlineCmd::BackwardPathComponent), make_md(L!("backward-token"), ReadlineCmd::BackwardToken), make_md(L!("backward-word"), ReadlineCmd::BackwardWord), make_md(L!("begin-selection"), ReadlineCmd::BeginSelection), @@ -151,6 +152,7 @@ const fn make_md(name: &'static wstr, code: ReadlineCmd) -> InputFunctionMetadat make_md(L!("forward-char-passive"), ReadlineCmd::ForwardCharPassive), make_md(L!("forward-jump"), ReadlineCmd::ForwardJump), make_md(L!("forward-jump-till"), ReadlineCmd::ForwardJumpTill), + make_md(L!("forward-path-component"), ReadlineCmd::ForwardPathComponent), make_md(L!("forward-single-char"), ReadlineCmd::ForwardSingleChar), make_md(L!("forward-token"), ReadlineCmd::ForwardToken), make_md(L!("forward-word"), ReadlineCmd::ForwardWord), @@ -173,6 +175,7 @@ const fn make_md(name: &'static wstr, code: ReadlineCmd) -> InputFunctionMetadat make_md(L!("kill-bigword"), ReadlineCmd::KillBigword), make_md(L!("kill-inner-line"), ReadlineCmd::KillInnerLine), make_md(L!("kill-line"), ReadlineCmd::KillLine), + make_md(L!("kill-path-component"), ReadlineCmd::KillPathComponent), make_md(L!("kill-selection"), ReadlineCmd::KillSelection), make_md(L!("kill-token"), ReadlineCmd::KillToken), make_md(L!("kill-whole-line"), ReadlineCmd::KillWholeLine), diff --git a/src/input_common.rs b/src/input_common.rs index d111429b1..d1198da43 100644 --- a/src/input_common.rs +++ b/src/input_common.rs @@ -53,7 +53,9 @@ pub enum ReadlineCmd { BackwardWord, ForwardBigword, BackwardBigword, + ForwardPathComponent, ForwardToken, + BackwardPathComponent, BackwardToken, NextdOrForwardWord, PrevdOrBackwardWord, @@ -80,6 +82,7 @@ pub enum ReadlineCmd { KillInnerLine, KillWord, KillBigword, + KillPathComponent, KillToken, BackwardKillWord, BackwardKillPathComponent, diff --git a/src/reader/reader.rs b/src/reader/reader.rs index 23cd86e40..e639567ae 100644 --- a/src/reader/reader.rs +++ b/src/reader/reader.rs @@ -3419,13 +3419,14 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) { newv, ) } - rl::KillWord | rl::KillBigword => { + rl::KillWord | rl::KillPathComponent | rl::KillBigword => { // The "bigword" functions differ only in that they move to the next whitespace, not // punctuation. - let style = if c == rl::KillWord { - MoveWordStyle::Punctuation - } else { - MoveWordStyle::Whitespace + let style = match c { + rl::KillBigword => MoveWordStyle::Whitespace, + rl::KillPathComponent => MoveWordStyle::PathComponents, + rl::KillWord => MoveWordStyle::Punctuation, + _ => unreachable!(), }; self.data.move_word( self.active_edit_line_tag(), @@ -3496,7 +3497,10 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) { self.update_buff_pos(elt, Some(new_position)); } } - rl::BackwardWord | rl::BackwardBigword | rl::PrevdOrBackwardWord => { + rl::BackwardWord + | rl::BackwardPathComponent + | rl::BackwardBigword + | rl::PrevdOrBackwardWord => { if c == rl::PrevdOrBackwardWord && self.command_line.is_empty() { self.eval_bind_cmd(L!("prevd")); self.force_exec_prompt_and_repaint = true; @@ -3505,10 +3509,11 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) { return; } - let style = if c != rl::BackwardBigword { - MoveWordStyle::Punctuation - } else { - MoveWordStyle::Whitespace + let style = match c { + rl::BackwardBigword => MoveWordStyle::Whitespace, + rl::BackwardPathComponent => MoveWordStyle::PathComponents, + rl::BackwardWord | rl::PrevdOrBackwardWord => MoveWordStyle::Punctuation, + _ => unreachable!(), }; self.data.move_word( self.active_edit_line_tag(), @@ -3518,7 +3523,10 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) { false, ); } - rl::ForwardWord | rl::ForwardBigword | rl::NextdOrForwardWord => { + rl::ForwardWord + | rl::ForwardPathComponent + | rl::ForwardBigword + | rl::NextdOrForwardWord => { if c == rl::NextdOrForwardWord && self.command_line.is_empty() { self.eval_bind_cmd(L!("nextd")); self.force_exec_prompt_and_repaint = true; @@ -3527,11 +3535,13 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) { return; } - let style = if c != rl::ForwardBigword { - MoveWordStyle::Punctuation - } else { - MoveWordStyle::Whitespace + let style = match c { + rl::ForwardBigword => MoveWordStyle::Whitespace, + rl::ForwardPathComponent => MoveWordStyle::PathComponents, + rl::ForwardWord | rl::NextdOrForwardWord => MoveWordStyle::Punctuation, + _ => unreachable!(), }; + if self.is_at_autosuggestion() { self.accept_autosuggestion(AutosuggestionPortion::PerMoveWordStyle(style)); } else if !self.is_at_end() {