diff --git a/Cargo.lock b/Cargo.lock index cfb2ba816a4b314454236f2b8bf72638e34a4923..6dd0ba845149f621ed904504743161018baabf9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14871,6 +14871,7 @@ dependencies = [ "editor", "feature_flags", "gpui", + "menu", "serde", "serde_json", "settings", diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 07539e9cbff85eafda0e69228ff33d8631f8f522..7c7692ac46f5d680207df43483a067373341433c 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -341,7 +341,7 @@ "enter": "agent::Chat", "shift-ctrl-r": "agent::OpenAgentDiff", "ctrl-shift-y": "agent::KeepAll", - "ctrl-shift-n": "agent::RejectAll", + "ctrl-shift-n": "agent::RejectAll" } }, { diff --git a/crates/dap/src/debugger_settings.rs b/crates/dap/src/debugger_settings.rs index 8d53fdea8649f1c62fa74cc6f0ddd6aec6ecff6d..4b841450462f1f59787df584cc4ba48eddf792c1 100644 --- a/crates/dap/src/debugger_settings.rs +++ b/crates/dap/src/debugger_settings.rs @@ -12,7 +12,7 @@ pub enum DebugPanelDockPosition { Right, } -#[derive(Serialize, Deserialize, JsonSchema, Clone, Copy, SettingsUi, SettingsKey)] +#[derive(Serialize, Deserialize, JsonSchema, Clone, SettingsUi, SettingsKey)] #[serde(default)] // todo(settings_ui) @ben: I'm pretty sure not having the fields be optional here is a bug, // it means the defaults will override previously set values if a single key is missing diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 61d15cb3ed41751ce08c00599bbe28fc0c0cadb2..c230a4c7aa58af3d89c71b4093cd7c6b8816252a 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -2578,7 +2578,7 @@ impl Window { &mut self, key: impl Into, cx: &mut App, - init: impl FnOnce(&mut Self, &mut App) -> S, + init: impl FnOnce(&mut Self, &mut Context) -> S, ) -> Entity { let current_view = self.current_view(); self.with_global_id(key.into(), |global_id, window| { @@ -2611,7 +2611,7 @@ impl Window { pub fn use_state( &mut self, cx: &mut App, - init: impl FnOnce(&mut Self, &mut App) -> S, + init: impl FnOnce(&mut Self, &mut Context) -> S, ) -> Entity { self.use_keyed_state( ElementId::CodeLocation(*core::panic::Location::caller()), diff --git a/crates/settings/src/settings_ui_core.rs b/crates/settings/src/settings_ui_core.rs index 09505e63a3ea960ce80ffcfbb63039fb53778469..c3366641a8991796082ed1e89d0bafa729dfc7ce 100644 --- a/crates/settings/src/settings_ui_core.rs +++ b/crates/settings/src/settings_ui_core.rs @@ -43,6 +43,7 @@ pub struct SettingsUiEntry { #[derive(Clone)] pub enum SettingsUiItemSingle { SwitchField, + TextField, /// A numeric stepper for a specific type of number NumericStepper(NumType), ToggleGroup { @@ -150,6 +151,18 @@ impl SettingsUi for Option { } } +impl SettingsUi for String { + fn settings_ui_item() -> SettingsUiItem { + SettingsUiItem::Single(SettingsUiItemSingle::TextField) + } +} + +impl SettingsUi for SettingsUiItem { + fn settings_ui_item() -> SettingsUiItem { + SettingsUiItem::Single(SettingsUiItemSingle::TextField) + } +} + #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum NumType { diff --git a/crates/settings_ui/Cargo.toml b/crates/settings_ui/Cargo.toml index 3ecef880d2bb551c79df67aefa420796829c68ef..1d8e5e11226103e2ef7778816f5c1b41cd934b05 100644 --- a/crates/settings_ui/Cargo.toml +++ b/crates/settings_ui/Cargo.toml @@ -21,8 +21,9 @@ command_palette_hooks.workspace = true editor.workspace = true feature_flags.workspace = true gpui.workspace = true -serde_json.workspace = true +menu.workspace = true serde.workspace = true +serde_json.workspace = true settings.workspace = true smallvec.workspace = true theme.workspace = true diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 9866dcdb3eb7fe60697a383f25a21e0c8d51fa14..4c9419491c34df05bb818ce718dfab16c31730a1 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -6,7 +6,7 @@ use std::ops::{Not, Range}; use anyhow::Context as _; use command_palette_hooks::CommandPaletteFilter; -use editor::EditorSettingsControls; +use editor::{Editor, EditorSettingsControls}; use feature_flags::{FeatureFlag, FeatureFlagViewExt}; use gpui::{App, Entity, EventEmitter, FocusHandle, Focusable, ReadGlobal, ScrollHandle, actions}; use settings::{ @@ -612,6 +612,7 @@ fn render_item_single( SettingsUiItemSingle::DropDown { .. } => { unimplemented!("This") } + SettingsUiItemSingle::TextField => render_text_field(settings_value, window, cx), } } @@ -798,6 +799,54 @@ fn render_switch_field( .into_any_element() } +fn render_text_field( + value: SettingsValue, + window: &mut Window, + cx: &mut App, +) -> AnyElement { + let value = downcast_any_item::(value); + let path = value.path.clone(); + let editor = window.use_state(cx, { + let path = path.clone(); + move |window, cx| { + let mut editor = Editor::single_line(window, cx); + + cx.observe_global_in::(window, move |editor, window, cx| { + let user_settings = SettingsStore::global(cx).raw_user_settings(); + if let Some(value) = read_settings_value_from_path(&user_settings, &path).cloned() + && let Some(value) = value.as_str() + { + editor.set_text(value, window, cx); + } + }) + .detach(); + + editor.set_text(value.read().clone(), window, cx); + editor + } + }); + + let weak_editor = editor.downgrade(); + let theme_colors = cx.theme().colors(); + + div() + .child(editor) + .bg(theme_colors.editor_background) + .border_1() + .rounded_lg() + .border_color(theme_colors.border) + .on_action::({ + move |_, _, cx| { + let new_value = weak_editor.read_with(cx, |editor, cx| editor.text(cx)).ok(); + + if let Some(new_value) = new_value { + SettingsValue::write_value(&path, serde_json::Value::String(new_value), cx); + } + } + }) + .into_any_element() +} + fn render_toggle_button_group( value: SettingsValue, variants: &'static [&'static str],