Add `convert to opposite case` command (#11290)

Joseph T. Lyons created

Change summary

crates/editor/src/actions.rs      |  7 ++++---
crates/editor/src/editor.rs       | 18 ++++++++++++++++++
crates/editor/src/editor_tests.rs |  8 ++++++++
crates/editor/src/element.rs      |  1 +
4 files changed, 31 insertions(+), 3 deletions(-)

Detailed changes

crates/editor/src/actions.rs 🔗

@@ -155,6 +155,7 @@ gpui::actions!(
         ConvertToKebabCase,
         ConvertToLowerCamelCase,
         ConvertToLowerCase,
+        ConvertToOppositeCase,
         ConvertToSnakeCase,
         ConvertToTitleCase,
         ConvertToUpperCamelCase,
@@ -175,8 +176,9 @@ gpui::actions!(
         DeleteToPreviousSubwordStart,
         DeleteToPreviousWordStart,
         DisplayCursorNames,
-        DuplicateLineUp,
         DuplicateLineDown,
+        DuplicateLineUp,
+        ExpandAllHunkDiffs,
         ExpandMacroRecursively,
         FindAllReferences,
         Fold,
@@ -267,7 +269,6 @@ gpui::actions!(
         ToggleGitBlame,
         ToggleGitBlameInline,
         ToggleHunkDiff,
-        ExpandAllHunkDiffs,
         ToggleInlayHints,
         ToggleLineNumbers,
         ToggleSoftWrap,
@@ -275,7 +276,7 @@ gpui::actions!(
         Undo,
         UndoSelection,
         UnfoldLines,
-        UniqueLinesCaseSensitive,
         UniqueLinesCaseInsensitive,
+        UniqueLinesCaseSensitive,
     ]
 );

crates/editor/src/editor.rs 🔗

@@ -5192,6 +5192,24 @@ impl Editor {
         self.manipulate_text(cx, |text| text.to_case(Case::Camel))
     }
 
+    pub fn convert_to_opposite_case(
+        &mut self,
+        _: &ConvertToOppositeCase,
+        cx: &mut ViewContext<Self>,
+    ) {
+        self.manipulate_text(cx, |text| {
+            text.chars()
+                .fold(String::with_capacity(text.len()), |mut t, c| {
+                    if c.is_uppercase() {
+                        t.extend(c.to_lowercase());
+                    } else {
+                        t.extend(c.to_uppercase());
+                    }
+                    t
+                })
+        })
+    }
+
     fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
     where
         Fn: FnMut(&str) -> String,

crates/editor/src/editor_tests.rs 🔗

@@ -3238,6 +3238,14 @@ async fn test_manipulate_text(cx: &mut TestAppContext) {
     cx.assert_editor_state(indoc! {"
         «aaaBbbˇ» «bbbCccˇ» «cccDddˇ»
     "});
+
+    cx.set_state(indoc! {"
+        «hElLo, WoRld!ˇ»
+    "});
+    cx.update_editor(|e, cx| e.convert_to_opposite_case(&ConvertToOppositeCase, cx));
+    cx.assert_editor_state(indoc! {"
+        «HeLlO, wOrLD!ˇ»
+    "});
 }
 
 #[gpui::test]

crates/editor/src/element.rs 🔗

@@ -176,6 +176,7 @@ impl EditorElement {
         register_action(view, cx, Editor::convert_to_kebab_case);
         register_action(view, cx, Editor::convert_to_upper_camel_case);
         register_action(view, cx, Editor::convert_to_lower_camel_case);
+        register_action(view, cx, Editor::convert_to_opposite_case);
         register_action(view, cx, Editor::delete_to_previous_word_start);
         register_action(view, cx, Editor::delete_to_previous_subword_start);
         register_action(view, cx, Editor::delete_to_next_word_end);