diff --git a/Cargo.lock b/Cargo.lock index 6190534f0f3383db2b9aa95544b27956042f87b3..ffc66d93a070deb136c59465362a4c761165a449 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14508,6 +14508,7 @@ version = "0.1.0" dependencies = [ "anyhow", "assets", + "client", "command_palette_hooks", "editor", "feature_flags", @@ -14516,9 +14517,11 @@ dependencies = [ "gpui", "language", "menu", + "node_runtime", "paths", "project", "serde", + "session", "settings", "theme", "ui", diff --git a/crates/session/src/session.rs b/crates/session/src/session.rs index 438059fef78adb6b83853335bfe1d38113a768d9..e8151f97fd4290058ed9928ba17a700fddbf3d35 100644 --- a/crates/session/src/session.rs +++ b/crates/session/src/session.rs @@ -43,7 +43,7 @@ impl Session { } } - #[cfg(any(test, feature = "test-support"))] + // #[cfg(any(test, feature = "test-support"))] pub fn test() -> Self { Self { session_id: Uuid::new_v4().to_string(), diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index f98bc7b74a1210a0ab3b79b4fdf70f79f60a873d..3a8dcfb8546c9a13ffd0927052d3a514c772b547 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -24,7 +24,8 @@ pub use keymap_file::{ pub use settings_file::*; pub use settings_json::*; pub use settings_store::{ - InvalidSettingsError, LocalSettingsKind, Settings, SettingsKey, SettingsLocation, SettingsStore, + InvalidSettingsError, LocalSettingsKind, Settings, SettingsFile, SettingsKey, SettingsLocation, + SettingsStore, }; pub use vscode_import::{VsCodeSettings, VsCodeSettingsSource}; diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 913014cf43e30dc3e41a6b08b8630abe0af43568..0ed87760f5339fc063a81892c899cac06beb11ef 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -156,6 +156,16 @@ pub struct SettingsStore { mpsc::UnboundedSender LocalBoxFuture<'static, Result<()>>>>, } +#[derive(Clone, PartialEq)] +pub enum SettingsFile { + User, + Global, + Extension, + Server, + Default, + Local((WorktreeId, Arc)), +} + #[derive(Clone)] pub struct Editorconfig { pub is_root: bool, @@ -479,6 +489,36 @@ impl SettingsStore { }) }) } + + pub fn get_all_files(&self) -> Vec { + let mut files = Vec::from_iter( + self.local_settings + .keys() + // rev because these are sorted by path, so highest precedence is last + .rev() + .cloned() + .map(SettingsFile::Local), + ); + + if self.server_settings.is_some() { + files.push(SettingsFile::Server); + } + // ignoring profiles + // ignoring os profiles + // ignoring release channel profiles + + if self.user_settings.is_some() { + files.push(SettingsFile::User); + } + if self.extension_settings.is_some() { + files.push(SettingsFile::Extension); + } + if self.global_settings.is_some() { + files.push(SettingsFile::Global); + } + files.push(SettingsFile::Default); + files + } } impl SettingsStore { diff --git a/crates/settings_ui/Cargo.toml b/crates/settings_ui/Cargo.toml index 4dd1ecdb7f2a425b20f04a623853af75d3006ec2..00e79567ba863a3fbe3440f58cb3ee48ea088db2 100644 --- a/crates/settings_ui/Cargo.toml +++ b/crates/settings_ui/Cargo.toml @@ -32,12 +32,15 @@ workspace-hack.workspace = true workspace.workspace = true [dev-dependencies] -settings = { workspace = true, features = ["test-support"] } +settings.workspace = true futures.workspace = true language.workspace = true assets.workspace = true paths.workspace = true zlog.workspace = true +client.workspace = true +session.workspace = true +node_runtime.workspace = true [[example]] name = "ui" diff --git a/crates/settings_ui/examples/.zed/settings.json b/crates/settings_ui/examples/.zed/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..0967ef424bce6791893e9a57bb952f80fd536e93 --- /dev/null +++ b/crates/settings_ui/examples/.zed/settings.json @@ -0,0 +1 @@ +{} diff --git a/crates/settings_ui/examples/ui.rs b/crates/settings_ui/examples/ui.rs index 46b5fa02a45d94d0094a12db90746b7889ce6ba5..ae8847c5635b39a9e7afce11f31d6d87e3cb95f2 100644 --- a/crates/settings_ui/examples/ui.rs +++ b/crates/settings_ui/examples/ui.rs @@ -1,11 +1,42 @@ use std::sync::Arc; use futures::StreamExt; +use gpui::AppContext as _; use settings::{DEFAULT_KEYMAP_PATH, KeymapFile, SettingsStore, watch_config_file}; use settings_ui::open_settings_editor; use ui::BorrowAppContext; +fn merge_paths(a: &std::path::Path, b: &std::path::Path) -> std::path::PathBuf { + let a_parts: Vec<_> = a.components().collect(); + let b_parts: Vec<_> = b.components().collect(); + + let mut overlap = 0; + for i in 0..=a_parts.len().min(b_parts.len()) { + if a_parts[a_parts.len() - i..] == b_parts[..i] { + overlap = i; + } + } + + let mut result = std::path::PathBuf::new(); + for part in &a_parts { + result.push(part.as_os_str()); + } + for part in &b_parts[overlap..] { + result.push(part.as_os_str()); + } + result +} + fn main() { + zlog::init(); + zlog::init_output_stderr(); + + let [crate_path, file_path] = [env!("CARGO_MANIFEST_DIR"), file!()].map(std::path::Path::new); + let example_dir_abs_path = merge_paths(crate_path, file_path) + .parent() + .unwrap() + .to_path_buf(); + let app = gpui::Application::new().with_assets(assets::Assets); let fs = Arc::new(fs::RealFs::new(None, app.background_executor())); @@ -14,15 +45,49 @@ fn main() { fs.clone(), paths::settings_file().clone(), ); - zlog::init(); - zlog::init_output_stderr(); app.run(move |cx| { ::set_global(fs.clone(), cx); settings::init(cx); theme::init(theme::LoadThemes::JustBase, cx); + + client::init_settings(cx); workspace::init_settings(cx); - project::Project::init_settings(cx); + // production client because fake client requires gpui/test-support + // and that causes issues with the real stuff we want to do + let client = client::Client::production(cx); + let user_store = cx.new(|cx| client::UserStore::new(client.clone(), cx)); + let languages = Arc::new(language::LanguageRegistry::new( + cx.background_executor().clone(), + )); + + client::init(&client, cx); + + project::Project::init(&client, cx); + + zlog::info!( + "Creating fake worktree in {}", + example_dir_abs_path.display(), + ); + let project = project::Project::local( + client.clone(), + node_runtime::NodeRuntime::unavailable(), + user_store, + languages, + fs.clone(), + Some(Default::default()), // WARN: if None is passed here, prepare to be process bombed + cx, + ); + let worktree_task = project.update(cx, |project, cx| { + project.create_worktree(example_dir_abs_path, true, cx) + }); + cx.spawn(async move |_| { + let worktree = worktree_task.await.unwrap(); + std::mem::forget(worktree); + }) + .detach(); + std::mem::forget(project); + language::init(cx); editor::init(cx); menu::init(); diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 86e8b61ec6a439033f43a9e085282383ad619c26..d13dd5cd50378a66d03a7a403fe20bd68b7850f5 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -200,7 +200,7 @@ struct SettingItem { } #[allow(unused)] -#[derive(Clone)] +#[derive(Clone, PartialEq)] enum SettingsFile { User, // Uses all settings. Local((WorktreeId, Arc)), // Has a special name, and special set of settings @@ -216,11 +216,11 @@ impl SettingsFile { } } - fn name(&self) -> String { + fn name(&self) -> SharedString { match self { - SettingsFile::User => "User".to_string(), - SettingsFile::Local((_, path)) => format!("Local ({})", path.display()), - SettingsFile::Server(file) => format!("Server ({})", file), + SettingsFile::User => SharedString::new_static("User"), + SettingsFile::Local((_, path)) => format!("Local ({})", path.display()).into(), + SettingsFile::Server(file) => format!("Server ({})", file).into(), } } } @@ -234,22 +234,18 @@ impl SettingsWindow { editor }); let mut this = Self { - files: vec![ - SettingsFile::User, - SettingsFile::Local(( - WorktreeId::from_usize(0), - Arc::from(Path::new("/my-project/")), - )), - ], + files: vec![], current_file: current_file, pages: vec![], current_page: 0, search, }; - cx.observe_global_in::(window, move |_, _, cx| { + cx.observe_global_in::(window, move |this, _, cx| { + this.fetch_files(cx); cx.notify(); }) .detach(); + this.fetch_files(cx); this.build_ui(); this @@ -259,7 +255,36 @@ impl SettingsWindow { self.pages = self.current_file.pages(); } + fn fetch_files(&mut self, cx: &mut App) { + let settings_store = cx.global::(); + let mut ui_files = vec![]; + let all_files = settings_store.get_all_files(); + for file in all_files { + let settings_ui_file = match file { + settings::SettingsFile::User => SettingsFile::User, + settings::SettingsFile::Global => continue, + settings::SettingsFile::Extension => continue, + settings::SettingsFile::Server => SettingsFile::Server("todo: server name"), + settings::SettingsFile::Default => continue, + settings::SettingsFile::Local(location) => SettingsFile::Local(location), + }; + ui_files.push(settings_ui_file); + } + ui_files.reverse(); + if !ui_files.contains(&self.current_file) { + self.change_file(0); + } + self.files = ui_files; + } + fn change_file(&mut self, ix: usize) { + if ix >= self.files.len() { + self.current_file = SettingsFile::User; + return; + } + if self.files[ix] == self.current_file { + return; + } self.current_file = self.files[ix].clone(); self.build_ui(); }