vim: Sort whole buffer when no range is specified (#42376)
- Introduce a `default_range` field to `VimCommand`, to be optionally used when no range is specified for the command - Update `VimCommand.parse` to take into consideration the `default_range` - Introduce `CommandRange::buffer` to obtain the `CommandRange` which corresponds to the whole buffer - Update the `VimCommand` definitions for both `sort` and `sort i` to default to the whole buffer when no range is specified Closes #41750 Release Notes: - Improved vim's `:sort` command to sort the buffer's content when no selection is used
This commit is contained in:
+131
-2
@@ -725,6 +725,8 @@ struct VimCommand {
|
||||
args: Option<
|
||||
Box<dyn Fn(Box<dyn Action>, String) -> Option<Box<dyn Action>> + Send + Sync + 'static>,
|
||||
>,
|
||||
/// Optional range Range to use if no range is specified.
|
||||
default_range: Option<CommandRange>,
|
||||
range: Option<
|
||||
Box<
|
||||
dyn Fn(Box<dyn Action>, &CommandRange) -> Option<Box<dyn Action>>
|
||||
@@ -793,6 +795,11 @@ impl VimCommand {
|
||||
self
|
||||
}
|
||||
|
||||
fn default_range(mut self, range: CommandRange) -> Self {
|
||||
self.default_range = Some(range);
|
||||
self
|
||||
}
|
||||
|
||||
fn count(mut self) -> Self {
|
||||
self.has_count = true;
|
||||
self
|
||||
@@ -923,6 +930,7 @@ impl VimCommand {
|
||||
self.args.as_ref()?(action, args)?
|
||||
};
|
||||
|
||||
let range = range.as_ref().or(self.default_range.as_ref());
|
||||
if let Some(range) = range {
|
||||
self.range.as_ref().and_then(|f| f(action, range))
|
||||
} else {
|
||||
@@ -1121,6 +1129,7 @@ impl CommandRange {
|
||||
self.end.as_ref().unwrap_or(&self.start)
|
||||
}
|
||||
|
||||
/// Convert the `CommandRange` into a `Range<MultiBufferRow>`.
|
||||
pub(crate) fn buffer_range(
|
||||
&self,
|
||||
vim: &Vim,
|
||||
@@ -1152,6 +1161,14 @@ impl CommandRange {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// The `CommandRange` representing the entire buffer.
|
||||
fn buffer() -> Self {
|
||||
Self {
|
||||
start: Position::Line { row: 1, offset: 0 },
|
||||
end: Some(Position::LastLine { offset: 0 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_commands(_: &App) -> Vec<VimCommand> {
|
||||
@@ -1421,8 +1438,12 @@ fn generate_commands(_: &App) -> Vec<VimCommand> {
|
||||
VimCommand::new(("delm", "arks"), ArgumentRequired)
|
||||
.bang(DeleteMarks::AllLocal)
|
||||
.args(|_, args| Some(DeleteMarks::Marks(args).boxed_clone())),
|
||||
VimCommand::new(("sor", "t"), SortLinesCaseSensitive).range(select_range),
|
||||
VimCommand::new(("sort i", ""), SortLinesCaseInsensitive).range(select_range),
|
||||
VimCommand::new(("sor", "t"), SortLinesCaseSensitive)
|
||||
.range(select_range)
|
||||
.default_range(CommandRange::buffer()),
|
||||
VimCommand::new(("sort i", ""), SortLinesCaseInsensitive)
|
||||
.range(select_range)
|
||||
.default_range(CommandRange::buffer()),
|
||||
VimCommand::str(("E", "xplore"), "project_panel::ToggleFocus"),
|
||||
VimCommand::str(("H", "explore"), "project_panel::ToggleFocus"),
|
||||
VimCommand::str(("L", "explore"), "project_panel::ToggleFocus"),
|
||||
@@ -2898,4 +2919,112 @@ mod test {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_sort_commands(cx: &mut TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
«hornet
|
||||
quirrel
|
||||
elderbug
|
||||
cornifer
|
||||
idaˇ»
|
||||
"},
|
||||
Mode::Visual,
|
||||
);
|
||||
|
||||
cx.simulate_keystrokes(": sort");
|
||||
cx.simulate_keystrokes("enter");
|
||||
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
ˇcornifer
|
||||
elderbug
|
||||
hornet
|
||||
ida
|
||||
quirrel
|
||||
"},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// Assert that, by default, `:sort` takes case into consideration.
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
«hornet
|
||||
quirrel
|
||||
Elderbug
|
||||
cornifer
|
||||
idaˇ»
|
||||
"},
|
||||
Mode::Visual,
|
||||
);
|
||||
|
||||
cx.simulate_keystrokes(": sort");
|
||||
cx.simulate_keystrokes("enter");
|
||||
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
ˇElderbug
|
||||
cornifer
|
||||
hornet
|
||||
ida
|
||||
quirrel
|
||||
"},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// Assert that, if the `i` option is passed, `:sort` ignores case.
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
«hornet
|
||||
quirrel
|
||||
Elderbug
|
||||
cornifer
|
||||
idaˇ»
|
||||
"},
|
||||
Mode::Visual,
|
||||
);
|
||||
|
||||
cx.simulate_keystrokes(": sort space i");
|
||||
cx.simulate_keystrokes("enter");
|
||||
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
ˇcornifer
|
||||
Elderbug
|
||||
hornet
|
||||
ida
|
||||
quirrel
|
||||
"},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// When no range is provided, sorts the whole buffer.
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
ˇhornet
|
||||
quirrel
|
||||
elderbug
|
||||
cornifer
|
||||
ida
|
||||
"},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.simulate_keystrokes(": sort");
|
||||
cx.simulate_keystrokes("enter");
|
||||
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
ˇcornifer
|
||||
elderbug
|
||||
hornet
|
||||
ida
|
||||
quirrel
|
||||
"},
|
||||
Mode::Normal,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user