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