delete.rs

  1use crate::{motion::Motion, Vim};
  2use collections::HashMap;
  3use editor::Bias;
  4use gpui::MutableAppContext;
  5
  6pub fn delete_over(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
  7    vim.update_active_editor(cx, |editor, cx| {
  8        editor.transact(cx, |editor, cx| {
  9            editor.set_clip_at_line_ends(false, cx);
 10            let mut original_columns: HashMap<_, _> = Default::default();
 11            editor.change_selections(true, cx, |s| {
 12                s.move_with(|map, selection| {
 13                    let original_head = selection.head();
 14                    motion.expand_selection(map, selection, true);
 15                    original_columns.insert(selection.id, original_head.column());
 16                });
 17            });
 18            editor.insert(&"", cx);
 19
 20            // Fixup cursor position after the deletion
 21            editor.set_clip_at_line_ends(true, cx);
 22            editor.change_selections(true, cx, |s| {
 23                s.move_with(|map, selection| {
 24                    let mut cursor = selection.head();
 25                    if motion.linewise() {
 26                        if let Some(column) = original_columns.get(&selection.id) {
 27                            *cursor.column_mut() = *column
 28                        }
 29                    }
 30                    cursor = map.clip_point(cursor, Bias::Left);
 31                    selection.collapse_to(cursor, selection.goal)
 32                });
 33            });
 34        });
 35    });
 36}
 37
 38#[cfg(test)]
 39mod test {
 40    use indoc::indoc;
 41
 42    use crate::vim_test_context::VimTestContext;
 43
 44    #[gpui::test]
 45    async fn test_delete_h(cx: &mut gpui::TestAppContext) {
 46        let cx = VimTestContext::new(cx, true).await;
 47        let mut cx = cx.binding(["d", "h"]);
 48        cx.assert("Te|st", "T|st");
 49        cx.assert("T|est", "|est");
 50        cx.assert("|Test", "|Test");
 51        cx.assert(
 52            indoc! {"
 53                Test
 54                |test"},
 55            indoc! {"
 56                Test
 57                |test"},
 58        );
 59    }
 60
 61    #[gpui::test]
 62    async fn test_delete_l(cx: &mut gpui::TestAppContext) {
 63        let cx = VimTestContext::new(cx, true).await;
 64        let mut cx = cx.binding(["d", "l"]);
 65        cx.assert("|Test", "|est");
 66        cx.assert("Te|st", "Te|t");
 67        cx.assert("Tes|t", "Te|s");
 68        cx.assert(
 69            indoc! {"
 70                Tes|t
 71                test"},
 72            indoc! {"
 73                Te|s
 74                test"},
 75        );
 76    }
 77
 78    #[gpui::test]
 79    async fn test_delete_w(cx: &mut gpui::TestAppContext) {
 80        let cx = VimTestContext::new(cx, true).await;
 81        let mut cx = cx.binding(["d", "w"]);
 82        cx.assert("Te|st", "T|e");
 83        cx.assert("T|est test", "T|test");
 84        cx.assert(
 85            indoc! {"
 86                Test te|st
 87                test"},
 88            indoc! {"
 89                Test t|e
 90                test"},
 91        );
 92        cx.assert(
 93            indoc! {"
 94                Test tes|t
 95                test"},
 96            indoc! {"
 97                Test te|s
 98                test"},
 99        );
100        cx.assert(
101            indoc! {"
102                Test test
103                |
104                test"},
105            indoc! {"
106                Test test
107                |
108                test"},
109        );
110
111        let mut cx = cx.binding(["d", "shift-W"]);
112        cx.assert("Test te|st-test test", "Test te|test");
113    }
114
115    #[gpui::test]
116    async fn test_delete_e(cx: &mut gpui::TestAppContext) {
117        let cx = VimTestContext::new(cx, true).await;
118        let mut cx = cx.binding(["d", "e"]);
119        cx.assert("Te|st Test", "Te| Test");
120        cx.assert("T|est test", "T| test");
121        cx.assert(
122            indoc! {"
123                Test te|st
124                test"},
125            indoc! {"
126                Test t|e
127                test"},
128        );
129        cx.assert(
130            indoc! {"
131                Test tes|t
132                test"},
133            "Test te|s",
134        );
135        cx.assert(
136            indoc! {"
137                Test test
138                |
139                test"},
140            indoc! {"
141                Test test
142                |
143                test"},
144        );
145
146        let mut cx = cx.binding(["d", "shift-E"]);
147        cx.assert("Test te|st-test test", "Test te| test");
148    }
149
150    #[gpui::test]
151    async fn test_delete_b(cx: &mut gpui::TestAppContext) {
152        let cx = VimTestContext::new(cx, true).await;
153        let mut cx = cx.binding(["d", "b"]);
154        cx.assert("Te|st Test", "|st Test");
155        cx.assert("Test |test", "|test");
156        cx.assert("Test1 test2 |test3", "Test1 |test3");
157        cx.assert(
158            indoc! {"
159                Test test
160                |test"},
161            // Trailing whitespace after cursor
162            indoc! {"
163                Test| 
164                test"},
165        );
166        cx.assert(
167            indoc! {"
168                Test test
169                |
170                test"},
171            // Trailing whitespace after cursor
172            indoc! {"
173                Test| 
174                
175                test"},
176        );
177
178        let mut cx = cx.binding(["d", "shift-B"]);
179        cx.assert("Test test-test |test", "Test |test");
180    }
181
182    #[gpui::test]
183    async fn test_delete_end_of_line(cx: &mut gpui::TestAppContext) {
184        let cx = VimTestContext::new(cx, true).await;
185        let mut cx = cx.binding(["d", "shift-$"]);
186        cx.assert(
187            indoc! {"
188                The q|uick
189                brown fox"},
190            indoc! {"
191                The |q
192                brown fox"},
193        );
194        cx.assert(
195            indoc! {"
196                The quick
197                |
198                brown fox"},
199            indoc! {"
200                The quick
201                |
202                brown fox"},
203        );
204    }
205
206    #[gpui::test]
207    async fn test_delete_0(cx: &mut gpui::TestAppContext) {
208        let cx = VimTestContext::new(cx, true).await;
209        let mut cx = cx.binding(["d", "0"]);
210        cx.assert(
211            indoc! {"
212                The q|uick
213                brown fox"},
214            indoc! {"
215                |uick
216                brown fox"},
217        );
218        cx.assert(
219            indoc! {"
220                The quick
221                |
222                brown fox"},
223            indoc! {"
224                The quick
225                |
226                brown fox"},
227        );
228    }
229
230    #[gpui::test]
231    async fn test_delete_k(cx: &mut gpui::TestAppContext) {
232        let cx = VimTestContext::new(cx, true).await;
233        let mut cx = cx.binding(["d", "k"]);
234        cx.assert(
235            indoc! {"
236                The quick
237                brown |fox
238                jumps over"},
239            "jumps |over",
240        );
241        cx.assert(
242            indoc! {"
243                The quick
244                brown fox
245                jumps |over"},
246            "The qu|ick",
247        );
248        cx.assert(
249            indoc! {"
250                The q|uick
251                brown fox
252                jumps over"},
253            indoc! {"
254                brown| fox
255                jumps over"},
256        );
257        cx.assert(
258            indoc! {"
259                |brown fox
260                jumps over"},
261            "|jumps over",
262        );
263    }
264
265    #[gpui::test]
266    async fn test_delete_j(cx: &mut gpui::TestAppContext) {
267        let cx = VimTestContext::new(cx, true).await;
268        let mut cx = cx.binding(["d", "j"]);
269        cx.assert(
270            indoc! {"
271                The quick
272                brown |fox
273                jumps over"},
274            "The qu|ick",
275        );
276        cx.assert(
277            indoc! {"
278                The quick
279                brown fox
280                jumps |over"},
281            indoc! {"
282                The quick
283                brown |fox"},
284        );
285        cx.assert(
286            indoc! {"
287                The q|uick
288                brown fox
289                jumps over"},
290            "jumps| over",
291        );
292        cx.assert(
293            indoc! {"
294                The quick
295                brown fox
296                |"},
297            indoc! {"
298                The quick
299                |brown fox"},
300        );
301    }
302
303    #[gpui::test]
304    async fn test_delete_end_of_document(cx: &mut gpui::TestAppContext) {
305        let cx = VimTestContext::new(cx, true).await;
306        let mut cx = cx.binding(["d", "shift-G"]);
307        cx.assert(
308            indoc! {"
309                The quick
310                brown| fox
311                jumps over
312                the lazy"},
313            "The q|uick",
314        );
315        cx.assert(
316            indoc! {"
317                The quick
318                brown| fox
319                jumps over
320                the lazy"},
321            "The q|uick",
322        );
323        cx.assert(
324            indoc! {"
325                The quick
326                brown fox
327                jumps over
328                the l|azy"},
329            indoc! {"
330                The quick
331                brown fox
332                jumps| over"},
333        );
334        cx.assert(
335            indoc! {"
336                The quick
337                brown fox
338                jumps over
339                |"},
340            indoc! {"
341                The quick
342                brown fox
343                |jumps over"},
344        );
345    }
346
347    #[gpui::test]
348    async fn test_delete_gg(cx: &mut gpui::TestAppContext) {
349        let cx = VimTestContext::new(cx, true).await;
350        let mut cx = cx.binding(["d", "g", "g"]);
351        cx.assert(
352            indoc! {"
353                The quick
354                brown| fox
355                jumps over
356                the lazy"},
357            indoc! {"
358                jumps| over
359                the lazy"},
360        );
361        cx.assert(
362            indoc! {"
363                The quick
364                brown fox
365                jumps over
366                the l|azy"},
367            "|",
368        );
369        cx.assert(
370            indoc! {"
371                The q|uick
372                brown fox
373                jumps over
374                the lazy"},
375            indoc! {"
376                brown| fox
377                jumps over
378                the lazy"},
379        );
380        cx.assert(
381            indoc! {"
382                |
383                brown fox
384                jumps over
385                the lazy"},
386            indoc! {"
387                |brown fox
388                jumps over
389                the lazy"},
390        );
391    }
392}