Cargo.lock 🔗
@@ -13507,6 +13507,7 @@ dependencies = [
"schemars",
"serde",
"serde_json",
+ "settings",
"shlex",
"smol",
"tempfile",
Conrad Irwin created
Cargo.lock | 1
crates/agent_settings/src/agent_settings.rs | 6
crates/agent_ui/src/agent_configuration.rs | 35 +++-
crates/agent_ui/src/agent_configuration/tool_picker.rs | 19 +-
crates/agent_ui/src/agent_panel.rs | 41 ++---
crates/agent_ui/src/text_thread_editor.rs | 22 ++
crates/collab/src/tests/editor_tests.rs | 20 +-
crates/outline_panel/src/outline_panel.rs | 18 -
crates/recent_projects/src/recent_projects.rs | 9
crates/recent_projects/src/remote_connections.rs | 86 ++---------
crates/recent_projects/src/remote_servers.rs | 39 ++---
crates/remote/Cargo.toml | 1
crates/remote/src/transport/ssh.rs | 24 +-
crates/settings/src/settings_content.rs | 52 +++++++
crates/settings/src/settings_content/project.rs | 2
crates/settings_ui/src/settings_ui.rs | 2
16 files changed, 195 insertions(+), 182 deletions(-)
@@ -13507,6 +13507,7 @@ dependencies = [
"schemars",
"serde",
"serde_json",
+ "settings",
"shlex",
"smol",
"tempfile",
@@ -8,8 +8,8 @@ use language_model::LanguageModel;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{
- DefaultAgentView, LanguageModelParameters, LanguageModelSelection, NotifyWhenAgentWaiting,
- Settings, SettingsContent,
+ DefaultAgentView, DockPosition, LanguageModelParameters, LanguageModelSelection,
+ NotifyWhenAgentWaiting, Settings, SettingsContent,
};
use util::MergeFrom;
@@ -24,7 +24,7 @@ pub fn init(cx: &mut App) {
AgentSettings::register(cx);
}
-#[derive(Default, Clone, Debug)]
+#[derive(Clone, Debug)]
pub struct AgentSettings {
pub enabled: bool,
pub button: bool,
@@ -413,8 +413,8 @@ impl AgentConfiguration {
always_allow_tool_actions,
move |state, _window, cx| {
let allow = state == &ToggleState::Selected;
- update_settings_file::<AgentSettings>(fs.clone(), cx, move |settings, _| {
- settings.set_always_allow_tool_actions(allow);
+ update_settings_file(fs.clone(), cx, move |settings, _| {
+ settings.agent.get_or_insert_default.set_always_allow_tool_actions(allow);
});
},
)
@@ -431,8 +431,11 @@ impl AgentConfiguration {
single_file_review,
move |state, _window, cx| {
let allow = state == &ToggleState::Selected;
- update_settings_file::<AgentSettings>(fs.clone(), cx, move |settings, _| {
- settings.set_single_file_review(allow);
+ update_settings_file(fs.clone(), cx, move |settings, _| {
+ settings
+ .agent
+ .get_or_insert_default()
+ .set_single_file_review(allow);
});
},
)
@@ -1279,7 +1282,7 @@ async fn open_new_agent_servers_entry_in_settings_editor(
let settings = cx.global::<SettingsStore>();
let mut unique_server_name = None;
- let edits = settings.edits_for_update::<AllAgentServersSettings>(&text, |file| {
+ let edits = settings.edits_for_update(&text, |settings| {
let server_name: Option<SharedString> = (0..u8::MAX)
.map(|i| {
if i == 0 {
@@ -1288,20 +1291,26 @@ async fn open_new_agent_servers_entry_in_settings_editor(
format!("your_agent_{}", i).into()
}
})
- .find(|name| !file.custom.contains_key(name));
+ .find(|name| {
+ !settings
+ .agent_servers
+ .is_some_and(|agent_servers| agent_servers.custom.contains_key(name))
+ });
if let Some(server_name) = server_name {
unique_server_name = Some(server_name.clone());
- file.custom.insert(
- server_name,
- CustomAgentServerSettings {
- command: AgentServerCommand {
+ settings
+ .agent_servers
+ .get_or_insert_default()
+ .custom
+ .insert(
+ server_name,
+ settings::CustomAgentServerSettings {
path: "path_to_executable".into(),
args: vec![],
env: Some(HashMap::default()),
+ default_mode: None,
},
- default_mode: None,
- },
- );
+ );
}
});
@@ -1,14 +1,11 @@
use std::{collections::BTreeMap, sync::Arc};
-use agent_settings::{
- AgentProfileContent, AgentProfileId, AgentProfileSettings, AgentSettings, AgentSettingsContent,
- ContextServerPresetContent,
-};
+use agent_settings::{AgentProfileId, AgentProfileSettings};
use assistant_tool::{ToolSource, ToolWorkingSet};
use fs::Fs;
use gpui::{App, Context, DismissEvent, Entity, EventEmitter, Focusable, Task, WeakEntity, Window};
use picker::{Picker, PickerDelegate};
-use settings::update_settings_file;
+use settings::{AgentProfileContent, ContextServerPresetContent, update_settings_file};
use ui::{ListItem, ListItemSpacing, prelude::*};
use util::ResultExt as _;
@@ -266,15 +263,19 @@ impl PickerDelegate for ToolPickerDelegate {
is_enabled
};
- update_settings_file::<AgentSettings>(self.fs.clone(), cx, {
+ update_settings_file(self.fs.clone(), cx, {
let profile_id = self.profile_id.clone();
let default_profile = self.profile_settings.clone();
let server_id = server_id.clone();
let tool_name = tool_name.clone();
- move |settings: &mut AgentSettingsContent, _cx| {
- let profiles = settings.profiles.get_or_insert_default();
+ move |settings, _cx| {
+ let profiles = settings
+ .agent
+ .get_or_insert_default()
+ .profiles
+ .get_or_insert_default();
let profile = profiles
- .entry(profile_id)
+ .entry(profile_id.0)
.or_insert_with(|| AgentProfileContent {
name: default_profile.name.into(),
tools: default_profile.tools,
@@ -1059,17 +1059,14 @@ impl AgentPanel {
match self.active_view.which_font_size_used() {
WhichFontSize::AgentFont => {
if persist {
- update_settings_file::<ThemeSettings>(
- self.fs.clone(),
- cx,
- move |settings, cx| {
- let agent_font_size =
- ThemeSettings::get_global(cx).agent_font_size(cx) + delta;
- let _ = settings
- .agent_font_size
- .insert(Some(theme::clamp_font_size(agent_font_size).into()));
- },
- );
+ update_settings_file(self.fs.clone(), cx, move |settings, cx| {
+ let agent_font_size =
+ ThemeSettings::get_global(cx).agent_font_size(cx) + delta;
+ let _ = settings
+ .theme
+ .agent_font_size
+ .insert(Some(theme::clamp_font_size(agent_font_size).into()));
+ });
} else {
theme::adjust_agent_font_size(cx, |size| size + delta);
}
@@ -1176,11 +1173,9 @@ impl AgentPanel {
.is_none_or(|model| model.provider.id() != provider.id())
&& let Some(model) = provider.default_model(cx)
{
- update_settings_file::<AgentSettings>(
- self.fs.clone(),
- cx,
- move |settings, _| settings.set_model(model),
- );
+ update_settings_file(self.fs.clone(), cx, move |settings, _| {
+ settings.agent.get_or_insert_default().set_model(model)
+ });
}
self.new_thread(&NewThread::default(), window, cx);
@@ -1425,7 +1420,7 @@ impl Focusable for AgentPanel {
}
fn agent_panel_dock_position(cx: &App) -> DockPosition {
- AgentSettings::get_global(cx).dock
+ AgentSettings::get_global(cx).dock.into()
}
impl EventEmitter<PanelEvent> for AgentPanel {}
@@ -1444,13 +1439,11 @@ impl Panel for AgentPanel {
}
fn set_position(&mut self, position: DockPosition, _: &mut Window, cx: &mut Context<Self>) {
- settings::update_settings_file::<AgentSettings>(self.fs.clone(), cx, move |settings, _| {
- let dock = match position {
- DockPosition::Left => AgentDockPosition::Left,
- DockPosition::Bottom => AgentDockPosition::Bottom,
- DockPosition::Right => AgentDockPosition::Right,
- };
- settings.set_dock(dock);
+ settings::update_settings_file(self.fs.clone(), cx, move |settings, _| {
+ settings
+ .agent
+ .get_or_insert_default()
+ .set_dock(position.into());
});
}
@@ -3,7 +3,7 @@ use crate::{
language_model_selector::{LanguageModelSelector, language_model_selector},
ui::BurnModeTooltip,
};
-use agent_settings::{AgentSettings, CompletionMode};
+use agent_settings::CompletionMode;
use anyhow::Result;
use assistant_slash_command::{SlashCommand, SlashCommandOutputSection, SlashCommandWorkingSet};
use assistant_slash_commands::{DefaultSlashCommand, FileSlashCommand, selections_creases};
@@ -41,7 +41,10 @@ use project::{Project, Worktree};
use project::{ProjectPath, lsp_store::LocalLspAdapterDelegate};
use rope::Point;
use serde::{Deserialize, Serialize};
-use settings::{Settings, SettingsStore, update_settings_file};
+use settings::{
+ LanguageModelProviderSetting, LanguageModelSelection, Settings, SettingsStore,
+ update_settings_file,
+};
use std::{
any::TypeId,
cmp,
@@ -294,11 +297,16 @@ impl TextThreadEditor {
language_model_selector(
|cx| LanguageModelRegistry::read_global(cx).default_model(),
move |model, cx| {
- update_settings_file::<AgentSettings>(
- fs.clone(),
- cx,
- move |settings, _| settings.set_model(model.clone()),
- );
+ update_settings_file(fs.clone(), cx, move |settings, _| {
+ let provider = model.provider_id().0.to_string();
+ let model = model.id().0.to_string();
+ settings.agent.get_or_insert_default().set_model(
+ LanguageModelSelection {
+ provider: LanguageModelProviderSetting(provider),
+ model: model.clone(),
+ },
+ )
+ });
},
window,
cx,
@@ -1789,8 +1789,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
cx_a.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
- store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
- settings.defaults.inlay_hints = Some(InlayHintSettings {
+ store.update_user_settings(cx, |settings| {
+ settings.project.all_languages.defaults.inlay_hints = Some(InlayHintSettings {
enabled: true,
show_value_hints: true,
edit_debounce_ms: 0,
@@ -1806,8 +1806,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
});
cx_b.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
- store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
- settings.defaults.inlay_hints = Some(InlayHintSettings {
+ store.update_user_settings(cx, |settings| {
+ settings.project.all_languages.defaults.inlay_hints = Some(InlayHintSettings {
show_value_hints: true,
enabled: true,
edit_debounce_ms: 0,
@@ -2039,8 +2039,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
cx_a.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
- store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
- settings.defaults.inlay_hints = Some(InlayHintSettings {
+ store.update_user_settings(cx, |settings| {
+ settings.project.all_languages.defaults.inlay_hints = Some(InlayHintSettings {
show_value_hints: true,
enabled: false,
edit_debounce_ms: 0,
@@ -2056,8 +2056,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
});
cx_b.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
- store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
- settings.defaults.inlay_hints = Some(InlayHintSettings {
+ store.update_user_settings(cx, |settings| {
+ settings.project.all_languages.defaults.inlay_hints = Some(InlayHintSettings {
show_value_hints: true,
enabled: true,
edit_debounce_ms: 0,
@@ -2242,14 +2242,14 @@ async fn test_lsp_document_color(cx_a: &mut TestAppContext, cx_b: &mut TestAppCo
cx_a.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
store.update_user_settings::<EditorSettings>(cx, |settings| {
- settings.lsp_document_colors = Some(DocumentColorsRenderMode::None);
+ settings.editor.lsp_document_colors = Some(DocumentColorsRenderMode::None);
});
});
});
cx_b.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
store.update_user_settings::<EditorSettings>(cx, |settings| {
- settings.lsp_document_colors = Some(DocumentColorsRenderMode::Inlay);
+ settings.editor.lsp_document_colors = Some(DocumentColorsRenderMode::Inlay);
});
});
});
@@ -4846,17 +4846,13 @@ impl Panel for OutlinePanel {
}
fn set_position(&mut self, position: DockPosition, _: &mut Window, cx: &mut Context<Self>) {
- settings::update_settings_file::<OutlinePanelSettings>(
- self.fs.clone(),
- cx,
- move |settings, _| {
- let dock = match position {
- DockPosition::Left | DockPosition::Bottom => OutlinePanelDockPosition::Left,
- DockPosition::Right => OutlinePanelDockPosition::Right,
- };
- settings.dock = Some(dock);
- },
- );
+ settings::update_settings_file(self.fs.clone(), cx, move |settings, _| {
+ let dock = match position {
+ DockPosition::Left | DockPosition::Bottom => OutlinePanelDockPosition::Left,
+ DockPosition::Right => OutlinePanelDockPosition::Right,
+ };
+ settings.outline_panel.get_or_insert_default().dock = Some(dock);
+ });
}
fn size(&self, _: &Window, cx: &App) -> Pixels {
@@ -626,7 +626,7 @@ mod tests {
use dap::debugger_settings::DebuggerSettings;
use editor::Editor;
use gpui::{TestAppContext, UpdateGlobal, WindowHandle};
- use project::{Project, project_settings::ProjectSettings};
+ use project::Project;
use serde_json::json;
use settings::SettingsStore;
use util::path;
@@ -640,8 +640,11 @@ mod tests {
cx.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
- store.update_user_settings::<ProjectSettings>(cx, |settings| {
- settings.session.restore_unsaved_buffers = false
+ store.update_user_settings(cx, |settings| {
+ settings
+ .session
+ .get_or_insert_default()
+ .restore_unsaved_buffers = Some(false)
});
});
});
@@ -1,4 +1,3 @@
-use std::collections::BTreeSet;
use std::{path::PathBuf, sync::Arc};
use anyhow::{Context as _, Result};
@@ -17,30 +16,26 @@ use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use release_channel::ReleaseChannel;
use remote::{
ConnectionIdentifier, RemoteClient, RemoteConnectionOptions, RemotePlatform,
- SshConnectionOptions, SshPortForwardOption,
+ SshConnectionOptions,
};
-use schemars::JsonSchema;
-use serde::{Deserialize, Serialize};
-use settings::{Settings, SettingsKey, SettingsSources, SettingsUi};
+use settings::Settings;
+pub use settings::SshConnection;
use theme::ThemeSettings;
use ui::{
ActiveTheme, Color, CommonAnimationExt, Context, Icon, IconName, IconSize, InteractiveElement,
IntoElement, Label, LabelCommon, Styled, Window, prelude::*,
};
-use util::serde::default_true;
+use util::MergeFrom;
use workspace::{AppState, ModalView, Workspace};
-#[derive(Deserialize)]
pub struct SshSettings {
- pub ssh_connections: Option<Vec<SshConnection>>,
- /// Whether to read ~/.ssh/config for ssh connection sources.
- #[serde(default = "default_true")]
+ pub ssh_connections: Vec<SshConnection>,
pub read_ssh_config: bool,
}
impl SshSettings {
pub fn ssh_connections(&self) -> impl Iterator<Item = SshConnection> + use<> {
- self.ssh_connections.clone().into_iter().flatten()
+ self.ssh_connections.clone().into_iter()
}
pub fn fill_connection_options_from_settings(&self, options: &mut SshConnectionOptions) {
@@ -75,67 +70,22 @@ impl SshSettings {
}
}
-#[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema)]
-pub struct SshConnection {
- pub host: SharedString,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub username: Option<String>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub port: Option<u16>,
- #[serde(skip_serializing_if = "Vec::is_empty")]
- #[serde(default)]
- pub args: Vec<String>,
- #[serde(default)]
- pub projects: BTreeSet<SshProject>,
- /// Name to use for this server in UI.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub nickname: Option<String>,
- // By default Zed will download the binary to the host directly.
- // If this is set to true, Zed will download the binary to your local machine,
- // and then upload it over the SSH connection. Useful if your SSH server has
- // limited outbound internet access.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub upload_binary_over_ssh: Option<bool>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub port_forwards: Option<Vec<SshPortForwardOption>>,
-}
-
-impl From<SshConnection> for SshConnectionOptions {
- fn from(val: SshConnection) -> Self {
- SshConnectionOptions {
- host: val.host.into(),
- username: val.username,
- port: val.port,
- password: None,
- args: Some(val.args),
- nickname: val.nickname,
- upload_binary_over_ssh: val.upload_binary_over_ssh.unwrap_or_default(),
- port_forwards: val.port_forwards,
+impl Settings for SshSettings {
+ fn from_defaults(content: &settings::SettingsContent, _cx: &mut App) -> Self {
+ let remote = &content.remote;
+ Self {
+ ssh_connections: remote.ssh_connections.clone().unwrap_or_default(),
+ read_ssh_config: remote.read_ssh_config.unwrap(),
}
}
-}
-
-#[derive(Clone, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema)]
-pub struct SshProject {
- pub paths: Vec<String>,
-}
-#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, SettingsUi, SettingsKey)]
-#[settings_key(None)]
-pub struct RemoteSettingsContent {
- pub ssh_connections: Option<Vec<SshConnection>>,
- pub read_ssh_config: Option<bool>,
-}
-
-impl Settings for SshSettings {
- type FileContent = RemoteSettingsContent;
-
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
- sources.json_merge()
+ fn refine(&mut self, content: &settings::SettingsContent, _cx: &mut App) {
+ if let Some(ssh_connections) = content.remote.ssh_connections.clone() {
+ self.ssh_connections.extend(ssh_connections)
+ }
+ self.read_ssh_config
+ .merge_from(&content.remote.read_ssh_config);
}
-
- fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
}
pub struct RemoteConnectionPrompt {
@@ -1,7 +1,7 @@
use crate::{
remote_connections::{
- RemoteConnectionModal, RemoteConnectionPrompt, RemoteSettingsContent, SshConnection,
- SshConnectionHeader, SshProject, SshSettings, connect_over_ssh, open_remote_project,
+ RemoteConnectionModal, RemoteConnectionPrompt, SshConnection, SshConnectionHeader,
+ SshSettings, connect_over_ssh, open_remote_project,
},
ssh_config::parse_ssh_config_hosts,
};
@@ -20,7 +20,10 @@ use remote::{
RemoteClient, RemoteConnectionOptions, SshConnectionOptions,
remote_client::ConnectionIdentifier,
};
-use settings::{Settings, SettingsStore, update_settings_file, watch_config_file};
+use settings::{
+ RemoteSettingsContent, Settings, SettingsStore, SshProject, update_settings_file,
+ watch_config_file,
+};
use smol::stream::StreamExt as _;
use std::{
borrow::Cow,
@@ -173,13 +176,14 @@ impl ProjectPicker {
cx.update(|_, cx| {
let fs = app_state.fs.clone();
- update_settings_file::<SshSettings>(fs, cx, {
+ update_settings_file(fs, cx, {
let paths = paths
.iter()
.map(|path| path.to_string_lossy().to_string())
.collect();
move |setting, _| {
if let Some(server) = setting
+ .remote
.ssh_connections
.as_mut()
.and_then(|connections| connections.get_mut(ix))
@@ -987,7 +991,7 @@ impl RemoteServerProjects {
else {
return;
};
- update_settings_file::<SshSettings>(fs, cx, move |setting, cx| f(setting, cx));
+ update_settings_file(fs, cx, move |setting, cx| f(&mut setting.remote, cx));
}
fn delete_ssh_server(&mut self, server: usize, cx: &mut Context<Self>) {
@@ -1403,24 +1407,15 @@ impl RemoteServerProjects {
cx: &mut Context<Self>,
) -> impl IntoElement {
let ssh_settings = SshSettings::get_global(cx);
- let mut should_rebuild = false;
-
- if ssh_settings
- .ssh_connections
- .as_ref()
- .is_some_and(|connections| {
- state
- .servers
- .iter()
- .filter_map(|server| match server {
- RemoteEntry::Project { connection, .. } => Some(connection),
- RemoteEntry::SshConfig { .. } => None,
- })
- .ne(connections.iter())
+
+ let mut should_rebuild = state
+ .servers
+ .iter()
+ .filter_map(|server| match server {
+ RemoteEntry::Project { connection, .. } => Some(connection),
+ RemoteEntry::SshConfig { .. } => None,
})
- {
- should_rebuild = true;
- };
+ .ne(&ssh_settings.ssh_connections);
if !should_rebuild && ssh_settings.read_ssh_config {
let current_ssh_hosts: BTreeSet<SharedString> = state
@@ -35,6 +35,7 @@ rpc = { workspace = true, features = ["gpui"] }
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
+settings.workspace = true
shlex.workspace = true
smol.workspace = true
tempfile.workspace = true
@@ -15,8 +15,7 @@ use itertools::Itertools;
use parking_lot::Mutex;
use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
use rpc::proto::Envelope;
-use schemars::JsonSchema;
-use serde::{Deserialize, Serialize};
+pub use settings::SshPortForwardOption;
use smol::{
fs,
process::{self, Child, Stdio},
@@ -53,14 +52,19 @@ pub struct SshConnectionOptions {
pub upload_binary_over_ssh: bool,
}
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema)]
-pub struct SshPortForwardOption {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub local_host: Option<String>,
- pub local_port: u16,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub remote_host: Option<String>,
- pub remote_port: u16,
+impl From<settings::SshConnection> for SshConnectionOptions {
+ fn from(val: settings::SshConnection) -> Self {
+ SshConnectionOptions {
+ host: val.host.into(),
+ username: val.username,
+ port: val.port,
+ password: None,
+ args: Some(val.args),
+ nickname: val.nickname,
+ upload_binary_over_ssh: val.upload_binary_over_ssh.unwrap_or_default(),
+ port_forwards: val.port_forwards,
+ }
+ }
}
#[derive(Clone)]
@@ -44,6 +44,9 @@ pub struct SettingsContent {
#[serde(flatten)]
pub editor: EditorSettingsContent,
+ #[serde(flatten)]
+ pub remote: RemoteSettingsContent,
+
/// Settings related to the file finder.
pub file_finder: Option<FileFinderSettingsContent>,
@@ -712,3 +715,52 @@ pub enum ImageFileSizeUnit {
/// Displays file size in decimal units (e.g., KB, MB).
Decimal,
}
+
+#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
+pub struct RemoteSettingsContent {
+ pub ssh_connections: Option<Vec<SshConnection>>,
+ pub read_ssh_config: Option<bool>,
+}
+
+#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)]
+pub struct SshConnection {
+ pub host: SharedString,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub username: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub port: Option<u16>,
+ #[serde(skip_serializing_if = "Vec::is_empty")]
+ #[serde(default)]
+ pub args: Vec<String>,
+ #[serde(default)]
+ pub projects: collections::BTreeSet<SshProject>,
+ /// Name to use for this server in UI.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub nickname: Option<String>,
+ // By default Zed will download the binary to the host directly.
+ // If this is set to true, Zed will download the binary to your local machine,
+ // and then upload it over the SSH connection. Useful if your SSH server has
+ // limited outbound internet access.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub upload_binary_over_ssh: Option<bool>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub port_forwards: Option<Vec<SshPortForwardOption>>,
+}
+
+#[derive(
+ Clone, Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema,
+)]
+pub struct SshProject {
+ pub paths: Vec<String>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema)]
+pub struct SshPortForwardOption {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub local_host: Option<String>,
+ pub local_port: u16,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub remote_host: Option<String>,
+ pub remote_port: u16,
+}
@@ -139,7 +139,7 @@ pub struct DapSettings {
pub args: Vec<String>,
}
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)]
+#[derive(Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)]
pub struct SessionSettingsContent {
/// Whether or not to restore unsaved buffers on restart.
///
@@ -5,7 +5,7 @@ use std::{
};
use anyhow::Context as _;
-use editor::{Editor, EditorSettingsControls};
+use editor::Editor;
use feature_flags::{FeatureFlag, FeatureFlagAppExt};
use gpui::{App, Entity, EventEmitter, FocusHandle, Focusable, ReadGlobal, ScrollHandle, actions};
use settings::{