1use project::ContextProviderWithTasks;
2use task::{TaskTemplate, TaskTemplates, VariableName};
3
4pub(super) fn bash_task_context() -> ContextProviderWithTasks {
5 ContextProviderWithTasks::new(TaskTemplates(vec![
6 TaskTemplate {
7 label: "execute selection".to_owned(),
8 command: VariableName::SelectedText.template_value(),
9 ..TaskTemplate::default()
10 },
11 TaskTemplate {
12 label: format!("run '{}'", VariableName::File.template_value()),
13 command: VariableName::File.template_value(),
14 ..TaskTemplate::default()
15 },
16 ]))
17}
18
19#[cfg(test)]
20mod tests {
21 use gpui::{AppContext as _, BorrowAppContext, Context, TestAppContext};
22 use language::{AutoindentMode, Buffer};
23 use settings::SettingsStore;
24 use std::num::NonZeroU32;
25 use unindent::Unindent;
26 use util::test::marked_text_offsets;
27
28 #[gpui::test]
29 async fn test_bash_autoindent(cx: &mut TestAppContext) {
30 cx.executor().set_block_on_ticks(usize::MAX..=usize::MAX);
31 let language = crate::language("bash", tree_sitter_bash::LANGUAGE.into());
32 cx.update(|cx| {
33 let test_settings = SettingsStore::test(cx);
34 cx.set_global(test_settings);
35 cx.update_global::<SettingsStore, _>(|store, cx| {
36 store.update_user_settings(cx, |s| {
37 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2)
38 });
39 });
40 });
41
42 cx.new(|cx| {
43 let mut buffer = Buffer::local("", cx).with_language_immediate(language, cx);
44
45 let expect_indents_to =
46 |buffer: &mut Buffer, cx: &mut Context<Buffer>, input: &str, expected: &str| {
47 buffer.edit(
48 [(0..buffer.len(), input)],
49 Some(AutoindentMode::EachLine),
50 cx,
51 );
52 assert_eq!(buffer.text(), expected);
53 };
54
55 // Do not indent after shebang
56 expect_indents_to(
57 &mut buffer,
58 cx,
59 "#!/usr/bin/env bash\n#",
60 "#!/usr/bin/env bash\n#",
61 );
62
63 // indent function correctly
64 expect_indents_to(
65 &mut buffer,
66 cx,
67 "function name() {\necho \"Hello, World!\"\n}",
68 "function name() {\n echo \"Hello, World!\"\n}",
69 );
70
71 // indent if-else correctly
72 expect_indents_to(
73 &mut buffer,
74 cx,
75 "if true;then\nfoo\nelse\nbar\nfi",
76 "if true;then\n foo\nelse\n bar\nfi",
77 );
78
79 // indent if-elif-else correctly
80 expect_indents_to(
81 &mut buffer,
82 cx,
83 "if true;then\nfoo\nelif true;then\nbar\nelse\nbar\nfi",
84 "if true;then\n foo\nelif true;then\n bar\nelse\n bar\nfi",
85 );
86
87 // indent case-when-else correctly
88 expect_indents_to(
89 &mut buffer,
90 cx,
91 "case $1 in\nfoo) echo \"Hello, World!\";;\n*) echo \"Unknown argument\";;\nesac",
92 "case $1 in\n foo) echo \"Hello, World!\";;\n *) echo \"Unknown argument\";;\nesac",
93 );
94
95 // indent for-loop correctly
96 expect_indents_to(
97 &mut buffer,
98 cx,
99 "for i in {1..10};do\nfoo\ndone",
100 "for i in {1..10};do\n foo\ndone",
101 );
102
103 // indent while-loop correctly
104 expect_indents_to(
105 &mut buffer,
106 cx,
107 "while true; do\nfoo\ndone",
108 "while true; do\n foo\ndone",
109 );
110
111 // indent array correctly
112 expect_indents_to(
113 &mut buffer,
114 cx,
115 "array=(\n1\n2\n3\n)",
116 "array=(\n 1\n 2\n 3\n)",
117 );
118
119 // indents non-"function" function correctly
120 expect_indents_to(
121 &mut buffer,
122 cx,
123 "foo() {\necho \"Hello, World!\"\n}",
124 "foo() {\n echo \"Hello, World!\"\n}",
125 );
126
127 let (input, offsets) = marked_text_offsets(
128 &r#"
129 if foo; then
130 1ˇ
131 else
132 3
133 fi
134 "#
135 .unindent(),
136 );
137
138 buffer.edit([(0..buffer.len(), input)], None, cx);
139 buffer.edit(
140 [(offsets[0]..offsets[0], "\n")],
141 Some(AutoindentMode::EachLine),
142 cx,
143 );
144 buffer.edit(
145 [(offsets[0] + 3..offsets[0] + 3, "elif")],
146 Some(AutoindentMode::EachLine),
147 cx,
148 );
149 let expected = r#"
150 if foo; then
151 1
152 elif
153 else
154 3
155 fi
156 "#
157 .unindent();
158
159 pretty_assertions::assert_eq!(buffer.text(), expected);
160
161 buffer
162 });
163 }
164}