Detailed changes
@@ -400,6 +400,19 @@
"model": "gpt-4o"
}
},
+ // The settings for slash commands.
+ "slash_commands": {
+ // Settings for the `/docs` slash command.
+ "docs": {
+ // Whether `/docs` is enabled.
+ "enabled": false
+ },
+ // Settings for the `/project` slash command.
+ "project": {
+ // Whether `/project` is enabled.
+ "enabled": false
+ }
+ },
// Whether the screen sharing icon is shown in the os status bar.
"show_call_status_icon": true,
// Whether to use language servers to provide code intelligence.
@@ -10,6 +10,7 @@ mod model_selector;
mod prompt_library;
mod prompts;
mod slash_command;
+pub mod slash_command_settings;
mod streaming_diff;
mod terminal_inline_assistant;
@@ -43,6 +44,8 @@ use std::sync::Arc;
pub(crate) use streaming_diff::*;
use util::ResultExt;
+use crate::slash_command_settings::SlashCommandSettings;
+
actions!(
assistant,
[
@@ -177,6 +180,7 @@ pub fn init(
) -> Arc<PromptBuilder> {
cx.set_global(Assistant::default());
AssistantSettings::register(cx);
+ SlashCommandSettings::register(cx);
// TODO: remove this when 0.148.0 is released.
if AssistantSettings::get_global(cx).using_outdated_settings_version {
@@ -290,6 +294,7 @@ fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut
slash_command_registry.register_command(terminal_command::TerminalSlashCommand, true);
slash_command_registry.register_command(now_command::NowSlashCommand, false);
slash_command_registry.register_command(diagnostics_command::DiagnosticsSlashCommand, true);
+
if let Some(prompt_builder) = prompt_builder {
slash_command_registry.register_command(
workflow_command::WorkflowSlashCommand::new(prompt_builder),
@@ -298,15 +303,10 @@ fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut
}
slash_command_registry.register_command(fetch_command::FetchSlashCommand, false);
- cx.observe_flag::<docs_command::DocsSlashCommandFeatureFlag, _>({
- let slash_command_registry = slash_command_registry.clone();
- move |is_enabled, _cx| {
- if is_enabled {
- slash_command_registry.register_command(docs_command::DocsSlashCommand, true);
- }
- }
- })
- .detach();
+ update_slash_commands_from_settings(cx);
+ cx.observe_global::<SettingsStore>(update_slash_commands_from_settings)
+ .detach();
+
cx.observe_flag::<search_command::SearchSlashCommandFeatureFlag, _>({
let slash_command_registry = slash_command_registry.clone();
move |is_enabled, _cx| {
@@ -318,6 +318,23 @@ fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut
.detach();
}
+fn update_slash_commands_from_settings(cx: &mut AppContext) {
+ let slash_command_registry = SlashCommandRegistry::global(cx);
+ let settings = SlashCommandSettings::get_global(cx);
+
+ if settings.docs.enabled {
+ slash_command_registry.register_command(docs_command::DocsSlashCommand, true);
+ } else {
+ slash_command_registry.unregister_command(docs_command::DocsSlashCommand);
+ }
+
+ if settings.project.enabled {
+ slash_command_registry.register_command(project_command::ProjectSlashCommand, true);
+ } else {
+ slash_command_registry.unregister_command(project_command::ProjectSlashCommand);
+ }
+}
+
pub fn humanize_token_count(count: usize) -> String {
match count {
0..=999 => count.to_string(),
@@ -7,7 +7,6 @@ use anyhow::{anyhow, bail, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
};
-use feature_flags::FeatureFlag;
use gpui::{AppContext, BackgroundExecutor, Model, Task, WeakView};
use indexed_docs::{
DocsDotRsProvider, IndexedDocsRegistry, IndexedDocsStore, LocalRustdocProvider, PackageName,
@@ -19,12 +18,6 @@ use ui::prelude::*;
use util::{maybe, ResultExt};
use workspace::Workspace;
-pub(crate) struct DocsSlashCommandFeatureFlag;
-
-impl FeatureFlag for DocsSlashCommandFeatureFlag {
- const NAME: &'static str = "docs-slash-command";
-}
-
pub(crate) struct DocsSlashCommand;
impl DocsSlashCommand {
@@ -0,0 +1,44 @@
+use anyhow::Result;
+use gpui::AppContext;
+use schemars::JsonSchema;
+use serde::{Deserialize, Serialize};
+use settings::{Settings, SettingsSources};
+
+/// Settings for slash commands.
+#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema)]
+pub struct SlashCommandSettings {
+ /// Settings for the `/docs` slash command.
+ #[serde(default)]
+ pub docs: DocsCommandSettings,
+ /// Settings for the `/project` slash command.
+ #[serde(default)]
+ pub project: ProjectCommandSettings,
+}
+
+/// Settings for the `/docs` slash command.
+#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema)]
+pub struct DocsCommandSettings {
+ /// Whether `/docs` is enabled.
+ #[serde(default)]
+ pub enabled: bool,
+}
+
+/// Settings for the `/project` slash command.
+#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema)]
+pub struct ProjectCommandSettings {
+ /// Whether `/project` is enabled.
+ #[serde(default)]
+ pub enabled: bool,
+}
+
+impl Settings for SlashCommandSettings {
+ const KEY: Option<&'static str> = Some("slash_commands");
+
+ type FileContent = Self;
+
+ fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
+ SettingsSources::<Self::FileContent>::json_merge_with(
+ [sources.default].into_iter().chain(sources.user),
+ )
+ }
+}
@@ -56,6 +56,14 @@ impl SlashCommandRegistry {
state.commands.insert(command_name, Arc::new(command));
}
+ /// Unregisters the provided [`SlashCommand`].
+ pub fn unregister_command(&self, command: impl SlashCommand) {
+ let mut state = self.state.write();
+ let command_name: Arc<str> = command.name().into();
+ state.featured_commands.remove(&command_name);
+ state.commands.remove(&command_name);
+ }
+
/// Returns the names of registered [`SlashCommand`]s.
pub fn command_names(&self) -> Vec<Arc<str>> {
self.state.read().commands.keys().cloned().collect()