Add Cursor Shape

Anthony created

Change summary

assets/settings/default.json                     |  4 +-
crates/project/src/terminals.rs                  |  4 +-
crates/settings/src/settings_content/terminal.rs | 15 +++++++++++-
crates/settings_ui/src/page_data.rs              | 20 ++++++++++++++++++
crates/settings_ui/src/settings_ui.rs            |  3 ++
crates/terminal/src/terminal_settings.rs         |  4 +-
crates/terminal_view/src/terminal_view.rs        |  6 +---
7 files changed, 44 insertions(+), 12 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -1401,8 +1401,8 @@
     //  4. A box drawn around the following character
     //     "hollow"
     //
-    // Default: not set, defaults to "block"
-    "cursor_shape": null,
+    // Default: "block"
+    "cursor_shape": "block",
     // Set whether Alternate Scroll mode (code: ?1007) is active by default.
     // Alternate Scroll mode converts mouse scroll events into up / down key
     // presses when in the alternate screen (e.g. when running applications

crates/project/src/terminals.rs 🔗

@@ -235,7 +235,7 @@ impl Project {
                     task_state,
                     shell,
                     env,
-                    settings.cursor_shape.unwrap_or_default(),
+                    settings.cursor_shape,
                     settings.alternate_scroll,
                     settings.max_scroll_history_lines,
                     is_via_remote,
@@ -365,7 +365,7 @@ impl Project {
                     None,
                     shell,
                     env,
-                    settings.cursor_shape.unwrap_or_default(),
+                    settings.cursor_shape,
                     settings.alternate_scroll,
                     settings.max_scroll_history_lines,
                     is_via_remote,

crates/settings/src/settings_content/terminal.rs 🔗

@@ -53,7 +53,7 @@ pub struct TerminalSettingsContent {
     /// Default cursor shape for the terminal.
     /// Can be "bar", "block", "underline", or "hollow".
     ///
-    /// Default: None
+    /// Default: "block"
     pub cursor_shape: Option<CursorShapeContent>,
     /// Sets the cursor blinking behavior in the terminal.
     ///
@@ -226,7 +226,18 @@ pub enum ShowScrollbar {
 }
 
 #[derive(
-    Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom,
+    Clone,
+    Copy,
+    Debug,
+    Default,
+    Serialize,
+    Deserialize,
+    PartialEq,
+    Eq,
+    JsonSchema,
+    MergeFrom,
+    strum::VariantArray,
+    strum::VariantNames,
 )]
 #[serde(rename_all = "snake_case")]
 // todo() -> combine with CursorShape

crates/settings_ui/src/page_data.rs 🔗

@@ -2831,6 +2831,26 @@ pub(crate) fn user_settings_data() -> Vec<SettingsPage> {
                     }),
                     metadata: None,
                 }),
+                SettingsPageItem::SettingItem(SettingItem {
+                    title: "Cursor Shape",
+                    description: "Default cursor shape for the terminal",
+                    field: Box::new(SettingField {
+                        pick: |settings_content| {
+                            if let Some(terminal) = &settings_content.terminal {
+                                &terminal.cursor_shape
+                            } else {
+                                &None
+                            }
+                        },
+                        pick_mut: |settings_content| {
+                            &mut settings_content
+                                .terminal
+                                .get_or_insert_default()
+                                .cursor_shape
+                        },
+                    }),
+                    metadata: None,
+                }),
                 SettingsPageItem::SettingItem(SettingItem {
                     title: "Alternate Scroll",
                     description: "Sets whether Alternate Scroll mode is active by default",

crates/settings_ui/src/settings_ui.rs 🔗

@@ -427,6 +427,9 @@ fn init_renderers(cx: &mut App) {
         })
         .add_renderer::<settings::AlternateScroll>(|settings_field, file, _, window, cx| {
             render_dropdown(*settings_field, file, window, cx)
+        })
+        .add_renderer::<settings::CursorShapeContent>(|settings_field, file, _, window, cx| {
+            render_dropdown(*settings_field, file, window, cx)
         });
 
     // todo(settings_ui): Figure out how we want to handle discriminant unions

crates/terminal/src/terminal_settings.rs 🔗

@@ -30,7 +30,7 @@ pub struct TerminalSettings {
     pub font_weight: Option<FontWeight>,
     pub line_height: TerminalLineHeight,
     pub env: HashMap<String, String>,
-    pub cursor_shape: Option<CursorShape>,
+    pub cursor_shape: CursorShape,
     pub blinking: TerminalBlink,
     pub alternate_scroll: AlternateScroll,
     pub option_as_meta: bool,
@@ -91,7 +91,7 @@ impl settings::Settings for TerminalSettings {
             font_weight: content.font_weight.map(FontWeight),
             line_height: content.line_height.unwrap(),
             env: content.env.unwrap(),
-            cursor_shape: content.cursor_shape.map(Into::into),
+            cursor_shape: content.cursor_shape.map(Into::into).unwrap_or_default(),
             blinking: content.blinking.unwrap(),
             alternate_scroll: content.alternate_scroll.unwrap(),
             option_as_meta: content.option_as_meta.unwrap(),

crates/terminal_view/src/terminal_view.rs 🔗

@@ -234,9 +234,7 @@ impl TerminalView {
                 terminal_view.focus_out(window, cx);
             },
         );
-        let cursor_shape = TerminalSettings::get_global(cx)
-            .cursor_shape
-            .unwrap_or_default();
+        let cursor_shape = TerminalSettings::get_global(cx).cursor_shape;
 
         let scroll_handle = TerminalScrollHandle::new(terminal.read(cx));
 
@@ -427,7 +425,7 @@ impl TerminalView {
         let breadcrumb_visibility_changed = self.show_breadcrumbs != settings.toolbar.breadcrumbs;
         self.show_breadcrumbs = settings.toolbar.breadcrumbs;
 
-        let new_cursor_shape = settings.cursor_shape.unwrap_or_default();
+        let new_cursor_shape = settings.cursor_shape;
         let old_cursor_shape = self.cursor_shape;
         if old_cursor_shape != new_cursor_shape {
             self.cursor_shape = new_cursor_shape;