feat: cycle command completions backward with Shift+Tab
This commit is contained in:
+29
-9
@@ -810,6 +810,11 @@ core_actions![
|
||||
Action::CommandComplete,
|
||||
&[Mode::Command],
|
||||
),
|
||||
(
|
||||
"core.command_complete_previous",
|
||||
Action::CommandCompletePrevious,
|
||||
&[Mode::Command],
|
||||
),
|
||||
(
|
||||
"core.palette",
|
||||
Action::Palette,
|
||||
@@ -1589,10 +1594,15 @@ fn default_bindings() -> HashMap<Mode, HashMap<Input, Binding>> {
|
||||
.insert(key, Binding::Action(action));
|
||||
}
|
||||
}
|
||||
bindings
|
||||
.entry(Mode::Command)
|
||||
.or_default()
|
||||
.insert(Input::Char('\t'), Binding::Action(CommandComplete));
|
||||
for (key, action) in [
|
||||
(Input::Char('\t'), CommandComplete),
|
||||
(Input::BackTab, CommandCompletePrevious),
|
||||
] {
|
||||
bindings
|
||||
.entry(Mode::Command)
|
||||
.or_default()
|
||||
.insert(key, Binding::Action(action));
|
||||
}
|
||||
for mode in [Mode::Command, Mode::Search] {
|
||||
for (key, action) in [(Input::Up, Up), (Input::Ctrl('k'), Up), (Input::Down, Down)] {
|
||||
bindings
|
||||
@@ -8020,7 +8030,9 @@ impl Editor {
|
||||
let mode = self.binding_mode();
|
||||
if !matches!(
|
||||
self.bindings.get(&mode).and_then(|keys| keys.get(&input)),
|
||||
Some(Binding::Action(Action::CommandComplete))
|
||||
Some(Binding::Action(
|
||||
Action::CommandComplete | Action::CommandCompletePrevious
|
||||
))
|
||||
) {
|
||||
self.active.view.command_completion_prefix = None;
|
||||
}
|
||||
@@ -8437,7 +8449,7 @@ impl Editor {
|
||||
self.active.view.mode = Mode::Command;
|
||||
}
|
||||
|
||||
fn complete_command(&mut self) {
|
||||
fn complete_command(&mut self, forward: bool) {
|
||||
let view = &mut self.active.view;
|
||||
let command = view.command_line.trim_start();
|
||||
let name = command.strip_prefix(':').unwrap_or(command);
|
||||
@@ -8449,6 +8461,9 @@ impl Editor {
|
||||
let prefix = view
|
||||
.command_completion_prefix
|
||||
.get_or_insert_with(|| name.to_owned());
|
||||
let precedes = |left: &str, right: &str| {
|
||||
if forward { left < right } else { left > right }
|
||||
};
|
||||
let mut first = None;
|
||||
let mut next = None;
|
||||
for candidate in self.features.values().flat_map(|feature| &feature.commands) {
|
||||
@@ -8456,10 +8471,13 @@ impl Editor {
|
||||
if !candidate.starts_with(prefix.as_str()) {
|
||||
continue;
|
||||
}
|
||||
if first.is_none_or(|first| candidate < first) {
|
||||
if first.is_none_or(|first| precedes(candidate, first)) {
|
||||
first = Some(candidate);
|
||||
}
|
||||
if cycling && candidate > name && next.is_none_or(|next| candidate < next) {
|
||||
if cycling
|
||||
&& precedes(name, candidate)
|
||||
&& next.is_none_or(|next| precedes(candidate, next))
|
||||
{
|
||||
next = Some(candidate);
|
||||
}
|
||||
}
|
||||
@@ -8563,7 +8581,9 @@ impl Editor {
|
||||
let count = self.count.take().unwrap_or(1);
|
||||
self.clear_sequence();
|
||||
match action {
|
||||
Action::CommandComplete => self.complete_command(),
|
||||
Action::CommandComplete | Action::CommandCompletePrevious => {
|
||||
self.complete_command(action == Action::CommandComplete);
|
||||
}
|
||||
Action::SnippetNext => {
|
||||
if self.snippet.is_some() {
|
||||
self.navigate_snippet(true);
|
||||
|
||||
Reference in New Issue
Block a user