@@ -65,7 +65,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.
///
@@ -236,7 +236,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
@@ -252,7 +263,19 @@ pub enum CursorShapeContent {
Hollow,
}
-#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom)]
+#[derive(
+ Copy,
+ Clone,
+ Debug,
+ Serialize,
+ Deserialize,
+ PartialEq,
+ Eq,
+ JsonSchema,
+ MergeFrom,
+ strum::VariantArray,
+ strum::VariantNames,
+)]
#[serde(rename_all = "snake_case")]
pub enum TerminalBlink {
/// Never blink the cursor, ignoring the terminal mode.
@@ -264,7 +287,19 @@ pub enum TerminalBlink {
On,
}
-#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom)]
+#[derive(
+ Clone,
+ Copy,
+ Debug,
+ Serialize,
+ Deserialize,
+ PartialEq,
+ Eq,
+ JsonSchema,
+ MergeFrom,
+ strum::VariantArray,
+ strum::VariantNames,
+)]
#[serde(rename_all = "snake_case")]
pub enum AlternateScroll {
On,
@@ -3916,6 +3916,519 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
}),
],
},
+ SettingsPage {
+ title: "Terminal",
+ items: vec![
+ SettingsPageItem::SectionHeader("Environment"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Shell",
+ description: "What shell to use when opening a terminal",
+ field: Box::new(
+ SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.project.shell
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .project
+ .shell
+ },
+ }
+ .unimplemented(),
+ ),
+ metadata: None,
+ files: USER | LOCAL,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Working Directory",
+ description: "What working directory to use when launching the terminal",
+ field: Box::new(
+ SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.project.working_directory
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .project
+ .working_directory
+ },
+ }
+ .unimplemented(),
+ ),
+ metadata: None,
+ files: USER | LOCAL,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Environment Variables",
+ description: "Key-value pairs to add to the terminal's environment",
+ field: Box::new(
+ SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.project.env
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .project
+ .env
+ },
+ }
+ .unimplemented(),
+ ),
+ metadata: None,
+ files: USER | LOCAL,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Detect Virtual Environment",
+ description: "Activates the python virtual environment, if one is found, in the terminal's working directory",
+ field: Box::new(
+ SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.project.detect_venv
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .project
+ .detect_venv
+ },
+ }
+ .unimplemented(),
+ ),
+ metadata: None,
+ files: USER | LOCAL,
+ }),
+ SettingsPageItem::SectionHeader("Font"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Font Size",
+ description: "Font size for terminal text. If not set, defaults to buffer font size",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.font_size
+ } else if settings_content.theme.buffer_font_size.is_some() {
+ &settings_content.theme.buffer_font_size
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content.terminal.get_or_insert_default().font_size
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Font Family",
+ description: "Font family for terminal text. If not set, defaults to buffer font family",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal
+ && terminal.font_family.is_some()
+ {
+ &terminal.font_family
+ } else if settings_content.theme.buffer_font_family.is_some() {
+ &settings_content.theme.buffer_font_family
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .font_family
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Font Fallbacks",
+ description: "Font fallbacks for terminal text. If not set, defaults to buffer font fallbacks",
+ field: Box::new(
+ SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.font_fallbacks
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .font_fallbacks
+ },
+ }
+ .unimplemented(),
+ ),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Font Weight",
+ description: "Font weight for terminal text in CSS weight units (100-900)",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.font_weight
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .font_weight
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Font Features",
+ description: "Font features for terminal text",
+ field: Box::new(
+ SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.font_features
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .font_features
+ },
+ }
+ .unimplemented(),
+ ),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SectionHeader("Display Settings"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Line Height",
+ description: "Line height for terminal text",
+ field: Box::new(
+ SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.line_height
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .line_height
+ },
+ }
+ .unimplemented(),
+ ),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Cursor Shape",
+ description: "Default cursor shape for the terminal (bar, block, underline, or hollow)",
+ 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,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Cursor Blinking",
+ description: "Sets the cursor blinking behavior in the terminal",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.blinking
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content.terminal.get_or_insert_default().blinking
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Alternate Scroll",
+ description: "Whether Alternate Scroll mode is active by default (converts mouse scroll to arrow keys in apps like vim)",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.alternate_scroll
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .alternate_scroll
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Minimum Contrast",
+ description: "The minimum APCA perceptual contrast between foreground and background colors (0-106)",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.minimum_contrast
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .minimum_contrast
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SectionHeader("Behavior Settings"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Option As Meta",
+ description: "Whether the option key behaves as the meta key",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.option_as_meta
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .option_as_meta
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Copy On Select",
+ description: "Whether selecting text in the terminal automatically copies to the system clipboard",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.copy_on_select
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .copy_on_select
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Keep Selection On Copy",
+ description: "Whether to keep the text selection after copying it to the clipboard",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.keep_selection_on_copy
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .keep_selection_on_copy
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SectionHeader("Layout Settings"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Default Width",
+ description: "Default width when the terminal is docked to the left or right (in pixels)",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.default_width
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .default_width
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Default Height",
+ description: "Default height when the terminal is docked to the bottom (in pixels)",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.default_height
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .default_height
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SectionHeader("Advanced Settings"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Max Scroll History Lines",
+ description: "Maximum number of lines to keep in scrollback history (max: 100,000; 0 disables scrolling)",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ &terminal.max_scroll_history_lines
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .max_scroll_history_lines
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SectionHeader("Toolbar"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Breadcrumbs",
+ description: "Whether to display the terminal title in breadcrumbs inside the terminal pane",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal {
+ if let Some(toolbar) = &terminal.toolbar {
+ &toolbar.breadcrumbs
+ } else {
+ &None
+ }
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .toolbar
+ .get_or_insert_default()
+ .breadcrumbs
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SectionHeader("Scrollbar"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Show Scrollbar",
+ description: "When to show the scrollbar in the terminal",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(terminal) = &settings_content.terminal
+ && let Some(scrollbar) = &terminal.scrollbar
+ && scrollbar.show.is_some()
+ {
+ &scrollbar.show
+ } else if let Some(scrollbar) = &settings_content.editor.scrollbar {
+ &scrollbar.show
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .terminal
+ .get_or_insert_default()
+ .scrollbar
+ .get_or_insert_default()
+ .show
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ ],
+ },
]
}
@@ -200,10 +200,19 @@ impl SettingFieldRenderer {
if let Some(renderer) = self.renderers.borrow().get(&key) {
renderer(any_setting_field, settings_file, metadata, window, cx)
} else {
- panic!(
- "No renderer found for type: {}",
- any_setting_field.type_name()
- )
+ Button::new("no-renderer", "NO RENDERER")
+ .style(ButtonStyle::Outlined)
+ .size(ButtonSize::Medium)
+ .icon(Some(IconName::XCircle))
+ .icon_position(IconPosition::Start)
+ .icon_color(Color::Error)
+ .tab_index(0_isize)
+ .tooltip(Tooltip::text(any_setting_field.type_name()))
+ .into_any_element()
+ // panic!(
+ // "No renderer found for type: {}",
+ // any_setting_field.type_name()
+ // )
}
}
}
@@ -409,6 +418,15 @@ fn init_renderers(cx: &mut App) {
.add_renderer::<settings::LspInsertMode>(|settings_field, file, _, window, cx| {
render_dropdown(*settings_field, file, window, cx)
})
+ .add_renderer::<settings::AlternateScroll>(|settings_field, file, _, window, cx| {
+ render_dropdown(*settings_field, file, window, cx)
+ })
+ .add_renderer::<settings::TerminalBlink>(|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)
+ })
.add_renderer::<f32>(|settings_field, file, _, window, cx| {
render_number_field(*settings_field, file, window, cx)
})