Add AutoIndent action and '=' vim operator (#21427)
Release Notes: - vim: Added the `=` operator, for auto-indent Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
@@ -303,6 +303,7 @@ gpui::actions!(
|
||||
OpenPermalinkToLine,
|
||||
OpenUrl,
|
||||
Outdent,
|
||||
AutoIndent,
|
||||
PageDown,
|
||||
PageUp,
|
||||
Paste,
|
||||
|
||||
@@ -6297,6 +6297,25 @@ impl Editor {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn autoindent(&mut self, _: &AutoIndent, cx: &mut ViewContext<Self>) {
|
||||
if self.read_only(cx) {
|
||||
return;
|
||||
}
|
||||
let selections = self
|
||||
.selections
|
||||
.all::<usize>(cx)
|
||||
.into_iter()
|
||||
.map(|s| s.range());
|
||||
|
||||
self.transact(cx, |this, cx| {
|
||||
this.buffer.update(cx, |buffer, cx| {
|
||||
buffer.autoindent_ranges(selections, cx);
|
||||
});
|
||||
let selections = this.selections.all::<usize>(cx);
|
||||
this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
|
||||
});
|
||||
}
|
||||
|
||||
pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let selections = self.selections.all::<Point>(cx);
|
||||
|
||||
@@ -34,6 +34,7 @@ use serde_json::{self, json};
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::{self, AtomicBool};
|
||||
use std::{cell::RefCell, future::Future, rc::Rc, time::Instant};
|
||||
use test::editor_lsp_test_context::rust_lang;
|
||||
use unindent::Unindent;
|
||||
use util::{
|
||||
assert_set_eq,
|
||||
@@ -5458,7 +5459,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
|
||||
async fn test_autoindent(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let language = Arc::new(
|
||||
@@ -5520,6 +5521,89 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
{
|
||||
let mut cx = EditorLspTestContext::new_rust(Default::default(), cx).await;
|
||||
cx.set_state(indoc! {"
|
||||
impl A {
|
||||
|
||||
fn b() {}
|
||||
|
||||
«fn c() {
|
||||
|
||||
}ˇ»
|
||||
}
|
||||
"});
|
||||
|
||||
cx.update_editor(|editor, cx| {
|
||||
editor.autoindent(&Default::default(), cx);
|
||||
});
|
||||
|
||||
cx.assert_editor_state(indoc! {"
|
||||
impl A {
|
||||
|
||||
fn b() {}
|
||||
|
||||
«fn c() {
|
||||
|
||||
}ˇ»
|
||||
}
|
||||
"});
|
||||
}
|
||||
|
||||
{
|
||||
let mut cx = EditorTestContext::new_multibuffer(
|
||||
cx,
|
||||
[indoc! { "
|
||||
impl A {
|
||||
«
|
||||
// a
|
||||
fn b(){}
|
||||
»
|
||||
«
|
||||
}
|
||||
fn c(){}
|
||||
»
|
||||
"}],
|
||||
);
|
||||
|
||||
let buffer = cx.update_editor(|editor, cx| {
|
||||
let buffer = editor.buffer().update(cx, |buffer, _| {
|
||||
buffer.all_buffers().iter().next().unwrap().clone()
|
||||
});
|
||||
buffer.update(cx, |buffer, cx| buffer.set_language(Some(rust_lang()), cx));
|
||||
buffer
|
||||
});
|
||||
|
||||
cx.run_until_parked();
|
||||
cx.update_editor(|editor, cx| {
|
||||
editor.select_all(&Default::default(), cx);
|
||||
editor.autoindent(&Default::default(), cx)
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.update(|cx| {
|
||||
pretty_assertions::assert_eq!(
|
||||
buffer.read(cx).text(),
|
||||
indoc! { "
|
||||
impl A {
|
||||
|
||||
// a
|
||||
fn b(){}
|
||||
|
||||
|
||||
}
|
||||
fn c(){}
|
||||
|
||||
" }
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_autoclose_and_auto_surround_pairs(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
@@ -13933,20 +14017,6 @@ pub(crate) fn init_test(cx: &mut TestAppContext, f: fn(&mut AllLanguageSettingsC
|
||||
update_test_language_settings(cx, f);
|
||||
}
|
||||
|
||||
pub(crate) fn rust_lang() -> Arc<Language> {
|
||||
Arc::new(Language::new(
|
||||
LanguageConfig {
|
||||
name: "Rust".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["rs".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
Some(tree_sitter_rust::LANGUAGE.into()),
|
||||
))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn assert_hunk_revert(
|
||||
not_reverted_text_with_selections: &str,
|
||||
|
||||
@@ -189,6 +189,7 @@ impl EditorElement {
|
||||
register_action(view, cx, Editor::tab_prev);
|
||||
register_action(view, cx, Editor::indent);
|
||||
register_action(view, cx, Editor::outdent);
|
||||
register_action(view, cx, Editor::autoindent);
|
||||
register_action(view, cx, Editor::delete_line);
|
||||
register_action(view, cx, Editor::join_lines);
|
||||
register_action(view, cx, Editor::sort_lines_case_sensitive);
|
||||
|
||||
@@ -1258,6 +1258,7 @@ pub mod tests {
|
||||
|
||||
use crate::{
|
||||
scroll::{scroll_amount::ScrollAmount, Autoscroll},
|
||||
test::editor_lsp_test_context::rust_lang,
|
||||
ExcerptRange,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
@@ -2274,7 +2275,7 @@ pub mod tests {
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
||||
language_registry.add(crate::editor_tests::rust_lang());
|
||||
language_registry.add(rust_lang());
|
||||
let mut fake_servers = language_registry.register_fake_lsp(
|
||||
"Rust",
|
||||
FakeLspAdapter {
|
||||
@@ -2570,7 +2571,7 @@ pub mod tests {
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
||||
let language = crate::editor_tests::rust_lang();
|
||||
let language = rust_lang();
|
||||
language_registry.add(language);
|
||||
let mut fake_servers = language_registry.register_fake_lsp(
|
||||
"Rust",
|
||||
@@ -2922,7 +2923,7 @@ pub mod tests {
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
||||
language_registry.add(crate::editor_tests::rust_lang());
|
||||
language_registry.add(rust_lang());
|
||||
let mut fake_servers = language_registry.register_fake_lsp(
|
||||
"Rust",
|
||||
FakeLspAdapter {
|
||||
@@ -3153,7 +3154,7 @@ pub mod tests {
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
||||
language_registry.add(crate::editor_tests::rust_lang());
|
||||
language_registry.add(rust_lang());
|
||||
let mut fake_servers = language_registry.register_fake_lsp(
|
||||
"Rust",
|
||||
FakeLspAdapter {
|
||||
@@ -3396,7 +3397,7 @@ pub mod tests {
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
||||
language_registry.add(crate::editor_tests::rust_lang());
|
||||
language_registry.add(rust_lang());
|
||||
let mut fake_servers = language_registry.register_fake_lsp(
|
||||
"Rust",
|
||||
FakeLspAdapter {
|
||||
|
||||
@@ -31,6 +31,47 @@ pub struct EditorLspTestContext {
|
||||
pub buffer_lsp_url: lsp::Url,
|
||||
}
|
||||
|
||||
pub(crate) fn rust_lang() -> Arc<Language> {
|
||||
let language = Language::new(
|
||||
LanguageConfig {
|
||||
name: "Rust".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["rs".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
line_comments: vec!["// ".into(), "/// ".into(), "//! ".into()],
|
||||
..Default::default()
|
||||
},
|
||||
Some(tree_sitter_rust::LANGUAGE.into()),
|
||||
)
|
||||
.with_queries(LanguageQueries {
|
||||
indents: Some(Cow::from(indoc! {r#"
|
||||
[
|
||||
((where_clause) _ @end)
|
||||
(field_expression)
|
||||
(call_expression)
|
||||
(assignment_expression)
|
||||
(let_declaration)
|
||||
(let_chain)
|
||||
(await_expression)
|
||||
] @indent
|
||||
|
||||
(_ "[" "]" @end) @indent
|
||||
(_ "<" ">" @end) @indent
|
||||
(_ "{" "}" @end) @indent
|
||||
(_ "(" ")" @end) @indent"#})),
|
||||
brackets: Some(Cow::from(indoc! {r#"
|
||||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("<" @open ">" @close)
|
||||
("\"" @open "\"" @close)
|
||||
(closure_parameters "|" @open "|" @close)"#})),
|
||||
..Default::default()
|
||||
})
|
||||
.expect("Could not parse queries");
|
||||
Arc::new(language)
|
||||
}
|
||||
impl EditorLspTestContext {
|
||||
pub async fn new(
|
||||
language: Language,
|
||||
@@ -119,46 +160,7 @@ impl EditorLspTestContext {
|
||||
capabilities: lsp::ServerCapabilities,
|
||||
cx: &mut gpui::TestAppContext,
|
||||
) -> EditorLspTestContext {
|
||||
let language = Language::new(
|
||||
LanguageConfig {
|
||||
name: "Rust".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["rs".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
line_comments: vec!["// ".into(), "/// ".into(), "//! ".into()],
|
||||
..Default::default()
|
||||
},
|
||||
Some(tree_sitter_rust::LANGUAGE.into()),
|
||||
)
|
||||
.with_queries(LanguageQueries {
|
||||
indents: Some(Cow::from(indoc! {r#"
|
||||
[
|
||||
((where_clause) _ @end)
|
||||
(field_expression)
|
||||
(call_expression)
|
||||
(assignment_expression)
|
||||
(let_declaration)
|
||||
(let_chain)
|
||||
(await_expression)
|
||||
] @indent
|
||||
|
||||
(_ "[" "]" @end) @indent
|
||||
(_ "<" ">" @end) @indent
|
||||
(_ "{" "}" @end) @indent
|
||||
(_ "(" ")" @end) @indent"#})),
|
||||
brackets: Some(Cow::from(indoc! {r#"
|
||||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("<" @open ">" @close)
|
||||
("\"" @open "\"" @close)
|
||||
(closure_parameters "|" @open "|" @close)"#})),
|
||||
..Default::default()
|
||||
})
|
||||
.expect("Could not parse queries");
|
||||
|
||||
Self::new(language, capabilities, cx).await
|
||||
Self::new(Arc::into_inner(rust_lang()).unwrap(), capabilities, cx).await
|
||||
}
|
||||
|
||||
pub async fn new_typescript(
|
||||
|
||||
Reference in New Issue
Block a user