diff --git a/Cargo.lock b/Cargo.lock index f08007c942..2ff7d2a80b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1123,6 +1123,7 @@ dependencies = [ "serde_derive", "settings", "smol", + "staff_mode", "sum_tree", "tempfile", "thiserror", @@ -1351,6 +1352,7 @@ dependencies = [ "serde_derive", "settings", "smol", + "staff_mode", "theme", "util", "workspace", @@ -5948,6 +5950,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "sqlez", + "staff_mode", "theme", "toml", "tree-sitter", @@ -6358,6 +6361,14 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "staff_mode" +version = "0.1.0" +dependencies = [ + "anyhow", + "gpui", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -6676,6 +6687,7 @@ dependencies = [ "postage", "settings", "smol", + "staff_mode", "theme", "util", "workspace", @@ -8576,6 +8588,7 @@ dependencies = [ "simplelog", "smallvec", "smol", + "staff_mode", "sum_tree", "tempdir", "terminal_view", diff --git a/Cargo.toml b/Cargo.toml index 8fad52c8f4..75178371d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ members = [ "crates/snippet", "crates/sqlez", "crates/sqlez_macros", + "crates/staff_mode", "crates/sum_tree", "crates/terminal", "crates/text", diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index c75adf5bfa..86a608a00b 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -17,6 +17,7 @@ db = { path = "../db" } gpui = { path = "../gpui" } util = { path = "../util" } rpc = { path = "../rpc" } +staff_mode = { path = "../staff_mode" } sum_tree = { path = "../sum_tree" } anyhow = "1.0.38" async-recursion = "0.3" diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index 8c6b141001..6b3aa7e442 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -6,9 +6,10 @@ use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task}; use postage::{sink::Sink, watch}; use rpc::proto::{RequestMessage, UsersResponse}; use settings::Settings; +use staff_mode::StaffMode; use std::sync::{Arc, Weak}; use util::http::HttpClient; -use util::{StaffMode, TryFutureExt as _}; +use util::TryFutureExt as _; #[derive(Default, Debug)] pub struct User { diff --git a/crates/copilot/Cargo.toml b/crates/copilot/Cargo.toml index 343186c526..52b9c223bd 100644 --- a/crates/copilot/Cargo.toml +++ b/crates/copilot/Cargo.toml @@ -15,6 +15,7 @@ gpui = { path = "../gpui" } language = { path = "../language" } settings = { path = "../settings" } theme = { path = "../theme" } +staff_mode = { path = "../staff_mode" } lsp = { path = "../lsp" } node_runtime = { path = "../node_runtime"} util = { path = "../util" } diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 0a7851bb0d..d3a47c6068 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -18,6 +18,8 @@ use node_runtime::NodeRuntime; use request::{LogMessage, StatusNotification}; use settings::Settings; use smol::{fs, io::BufReader, stream::StreamExt}; +use staff_mode::{not_staff_mode, staff_mode}; + use std::{ ffi::OsString, ops::Range, @@ -35,28 +37,57 @@ const COPILOT_NAMESPACE: &'static str = "copilot"; actions!(copilot, [NextSuggestion, PreviousSuggestion, Reinstall]); pub fn init(client: Arc, node_runtime: Arc, cx: &mut MutableAppContext) { - let copilot = cx.add_model(|cx| Copilot::start(client.http_client(), node_runtime, cx)); - cx.set_global(copilot.clone()); + staff_mode(cx, { + move |cx| { + cx.update_global::(|filter, _cx| { + filter.filtered_namespaces.remove(COPILOT_NAMESPACE); + filter.filtered_namespaces.remove(COPILOT_AUTH_NAMESPACE); + }); + + let copilot = cx.add_model({ + let node_runtime = node_runtime.clone(); + let http = client.http_client().clone(); + move |cx| Copilot::start(http, node_runtime, cx) + }); + cx.set_global(copilot.clone()); + + observe_namespaces(cx, copilot); + + sign_in::init(cx); + } + }); + not_staff_mode(cx, |cx| { + cx.update_global::(|filter, _cx| { + filter.filtered_namespaces.insert(COPILOT_NAMESPACE); + filter.filtered_namespaces.insert(COPILOT_AUTH_NAMESPACE); + }); + }); + cx.add_global_action(|_: &SignIn, cx| { - let copilot = Copilot::global(cx).unwrap(); - copilot - .update(cx, |copilot, cx| copilot.sign_in(cx)) - .detach_and_log_err(cx); + if let Some(copilot) = Copilot::global(cx) { + copilot + .update(cx, |copilot, cx| copilot.sign_in(cx)) + .detach_and_log_err(cx); + } }); cx.add_global_action(|_: &SignOut, cx| { - let copilot = Copilot::global(cx).unwrap(); - copilot - .update(cx, |copilot, cx| copilot.sign_out(cx)) - .detach_and_log_err(cx); + if let Some(copilot) = Copilot::global(cx) { + copilot + .update(cx, |copilot, cx| copilot.sign_out(cx)) + .detach_and_log_err(cx); + } }); cx.add_global_action(|_: &Reinstall, cx| { - let copilot = Copilot::global(cx).unwrap(); - copilot - .update(cx, |copilot, cx| copilot.reinstall(cx)) - .detach(); + if let Some(copilot) = Copilot::global(cx) { + copilot + .update(cx, |copilot, cx| copilot.reinstall(cx)) + .detach(); + } }); +} +fn observe_namespaces(cx: &mut MutableAppContext, copilot: ModelHandle) { cx.observe(&copilot, |handle, cx| { let status = handle.read(cx).status(); cx.update_global::( @@ -77,8 +108,6 @@ pub fn init(client: Arc, node_runtime: Arc, cx: &mut Mutabl ); }) .detach(); - - sign_in::init(cx); } enum CopilotServer { diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index 5972808396..fbb3ad63f3 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -20,6 +20,7 @@ fs = { path = "../fs" } anyhow = "1.0.38" futures = "0.3" theme = { path = "../theme" } +staff_mode = { path = "../staff_mode" } util = { path = "../util" } json_comments = "0.2" postage = { workspace = true } diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index 0988b2d6d9..feb4017018 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -177,6 +177,7 @@ pub struct EditorSettings { pub ensure_final_newline_on_save: Option, pub formatter: Option, pub enable_language_server: Option, + #[schemars(skip)] pub copilot: Option, } @@ -436,6 +437,7 @@ pub struct SettingsFileContent { #[serde(default)] pub base_keymap: Option, #[serde(default)] + #[schemars(skip)] pub enable_copilot_integration: Option, } @@ -779,6 +781,7 @@ pub fn settings_file_json_schema( settings.option_add_null_type = false; }); let generator = SchemaGenerator::new(settings); + let mut root_schema = generator.into_root_schema_for::(); // Create a schema for a theme name. @@ -791,6 +794,7 @@ pub fn settings_file_json_schema( // Create a schema for a 'languages overrides' object, associating editor // settings with specific langauges. assert!(root_schema.definitions.contains_key("EditorSettings")); + let languages_object_schema = SchemaObject { instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Object))), object: Some(Box::new(ObjectValidation { diff --git a/crates/staff_mode/Cargo.toml b/crates/staff_mode/Cargo.toml new file mode 100644 index 0000000000..cb8729f382 --- /dev/null +++ b/crates/staff_mode/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "staff_mode" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/staff_mode.rs" + +[dependencies] +gpui = { path = "../gpui" } +anyhow = "1.0.38" diff --git a/crates/staff_mode/src/staff_mode.rs b/crates/staff_mode/src/staff_mode.rs new file mode 100644 index 0000000000..3dbd6c2500 --- /dev/null +++ b/crates/staff_mode/src/staff_mode.rs @@ -0,0 +1,42 @@ +use gpui::MutableAppContext; + +#[derive(Debug, Default)] +pub struct StaffMode(pub bool); + +impl std::ops::Deref for StaffMode { + type Target = bool; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// Despite what the type system requires me to tell you, the init function will only be called a once +/// as soon as we know that the staff mode is enabled. +pub fn staff_mode( + cx: &mut MutableAppContext, + mut init: F, +) { + if **cx.default_global::() { + init(cx) + } else { + let mut once = Some(()); + cx.observe_global::(move |cx| { + if **cx.global::() && once.take().is_some() { + init(cx); + } + }) + .detach(); + } +} + +/// Immediately checks and runs the init function if the staff mode is not enabled. +/// This is only included for symettry with staff_mode() above +pub fn not_staff_mode( + cx: &mut MutableAppContext, + init: F, +) { + if !**cx.default_global::() { + init(cx) + } +} diff --git a/crates/theme_selector/Cargo.toml b/crates/theme_selector/Cargo.toml index 2c922200b2..db9d21fbd9 100644 --- a/crates/theme_selector/Cargo.toml +++ b/crates/theme_selector/Cargo.toml @@ -15,6 +15,7 @@ gpui = { path = "../gpui" } picker = { path = "../picker" } theme = { path = "../theme" } settings = { path = "../settings" } +staff_mode = { path = "../staff_mode" } workspace = { path = "../workspace" } util = { path = "../util" } log = { version = "0.4.16", features = ["kv_unstable_serde"] } diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index ae3278b711..0b8d4db7d4 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -5,9 +5,9 @@ use gpui::{ }; use picker::{Picker, PickerDelegate}; use settings::{settings_file::SettingsFile, Settings}; +use staff_mode::StaffMode; use std::sync::Arc; use theme::{Theme, ThemeMeta, ThemeRegistry}; -use util::StaffMode; use workspace::{AppState, Workspace}; pub struct ThemeSelector { diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index d9db47c2bb..903b0eec59 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -17,17 +17,6 @@ pub use backtrace::Backtrace; use futures::Future; use rand::{seq::SliceRandom, Rng}; -#[derive(Debug, Default)] -pub struct StaffMode(pub bool); - -impl std::ops::Deref for StaffMode { - type Target = bool; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - #[macro_export] macro_rules! debug_panic { ( $($fmt_arg:tt)* ) => { diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index a313fcab19..7a38630482 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -55,6 +55,7 @@ project_symbols = { path = "../project_symbols" } recent_projects = { path = "../recent_projects" } rpc = { path = "../rpc" } settings = { path = "../settings" } +staff_mode = { path = "../staff_mode" } sum_tree = { path = "../sum_tree" } text = { path = "../text" } terminal_view = { path = "../terminal_view" } diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs index 6bb3d94c5a..657ebca8ff 100644 --- a/crates/zed/src/languages/json.rs +++ b/crates/zed/src/languages/json.rs @@ -8,6 +8,7 @@ use node_runtime::NodeRuntime; use serde_json::json; use settings::{keymap_file_json_schema, settings_file_json_schema}; use smol::fs; +use staff_mode::StaffMode; use std::{ any::Any, ffi::OsString, @@ -16,8 +17,7 @@ use std::{ sync::Arc, }; use theme::ThemeRegistry; -use util::{fs::remove_matching, http::HttpClient}; -use util::{paths, ResultExt, StaffMode}; +use util::{fs::remove_matching, http::HttpClient, paths, ResultExt}; const SERVER_PATH: &'static str = "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 8f7b858dfd..8f1be827d6 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -38,9 +38,9 @@ use welcome::{show_welcome_experience, FIRST_OPEN}; use fs::RealFs; use settings::watched_json::WatchedJsonFile; -use theme::ThemeRegistry; #[cfg(debug_assertions)] -use util::StaffMode; +use staff_mode::StaffMode; +use theme::ThemeRegistry; use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt}; use workspace::{ self, dock::FocusDock, item::ItemHandle, notifications::NotifyResultExt, AppState, NewFile,