diff --git a/Cargo.lock b/Cargo.lock index f7df83814a..c338d6346e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9942,6 +9942,13 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slash_commands_example" +version = "0.1.0" +dependencies = [ + "zed_extension_api 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slice-group-by" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 3bd85b5793..329688b34b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -149,6 +149,7 @@ members = [ "extensions/purescript", "extensions/ruff", "extensions/ruby", + "extensions/slash-commands-example", "extensions/snippets", "extensions/svelte", "extensions/terraform", diff --git a/extensions/slash-commands-example/Cargo.toml b/extensions/slash-commands-example/Cargo.toml new file mode 100644 index 0000000000..bebc9d6c7f --- /dev/null +++ b/extensions/slash-commands-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "slash_commands_example" +version = "0.1.0" +edition = "2021" +publish = false +license = "Apache-2.0" + +[lints] +workspace = true + +[lib] +path = "src/slash_commands_example.rs" +crate-type = ["cdylib"] + +[dependencies] +zed_extension_api = "0.1.0" diff --git a/extensions/slash-commands-example/LICENSE-APACHE b/extensions/slash-commands-example/LICENSE-APACHE new file mode 120000 index 0000000000..1cd601d0a3 --- /dev/null +++ b/extensions/slash-commands-example/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/slash-commands-example/README.md b/extensions/slash-commands-example/README.md new file mode 100644 index 0000000000..3a9d6de71a --- /dev/null +++ b/extensions/slash-commands-example/README.md @@ -0,0 +1,3 @@ +# Slash Commands Example Extension + +This is an example extension showcasing how to write slash commands. diff --git a/extensions/slash-commands-example/extension.toml b/extensions/slash-commands-example/extension.toml new file mode 100644 index 0000000000..b0e20d6b64 --- /dev/null +++ b/extensions/slash-commands-example/extension.toml @@ -0,0 +1,17 @@ +id = "slash-commands-example" +name = "Slash Commands Example" +description = "An example extension showcasing slash commands." +version = "0.1.0" +schema_version = 1 +authors = ["Zed Industries "] +repository = "https://github.com/zed-industries/zed" + +[slash_commands.echo] +description = "echoes the provided input" +requires_argument = true +tooltip_text = "Echoes the provided input" + +[slash_commands.pick-one] +description = "pick one of three options" +requires_argument = true +tooltip_text = "Pick one of three options" diff --git a/extensions/slash-commands-example/src/slash_commands_example.rs b/extensions/slash-commands-example/src/slash_commands_example.rs new file mode 100644 index 0000000000..5b170d63ee --- /dev/null +++ b/extensions/slash-commands-example/src/slash_commands_example.rs @@ -0,0 +1,90 @@ +use zed_extension_api::{ + self as zed, SlashCommand, SlashCommandArgumentCompletion, SlashCommandOutput, + SlashCommandOutputSection, Worktree, +}; + +struct SlashCommandsExampleExtension; + +impl zed::Extension for SlashCommandsExampleExtension { + fn new() -> Self { + SlashCommandsExampleExtension + } + + fn complete_slash_command_argument( + &self, + command: SlashCommand, + _args: Vec, + ) -> Result, String> { + match command.name.as_str() { + "echo" => Ok(vec![]), + "pick-one" => Ok(vec![ + SlashCommandArgumentCompletion { + label: "Option One".to_string(), + new_text: "option-1".to_string(), + run_command: true, + }, + SlashCommandArgumentCompletion { + label: "Option Two".to_string(), + new_text: "option-2".to_string(), + run_command: true, + }, + SlashCommandArgumentCompletion { + label: "Option Three".to_string(), + new_text: "option-3".to_string(), + run_command: true, + }, + ]), + command => Err(format!("unknown slash command: \"{command}\"")), + } + } + + fn run_slash_command( + &self, + command: SlashCommand, + args: Vec, + _worktree: Option<&Worktree>, + ) -> Result { + match command.name.as_str() { + "echo" => { + if args.is_empty() { + return Err("nothing to echo".to_string()); + } + + let text = args.join(" "); + + Ok(SlashCommandOutput { + sections: vec![SlashCommandOutputSection { + range: (0..text.len()).into(), + label: "Echo".to_string(), + }], + text, + }) + } + "pick-one" => { + let Some(selection) = args.first() else { + return Err("no option selected".to_string()); + }; + + match selection.as_str() { + "option-1" | "option-2" | "option-3" => {} + invalid_option => { + return Err(format!("{invalid_option} is not a valid option")); + } + } + + let text = format!("You chose {selection}."); + + Ok(SlashCommandOutput { + sections: vec![SlashCommandOutputSection { + range: (0..text.len()).into(), + label: format!("Pick One: {selection}"), + }], + text, + }) + } + command => Err(format!("unknown slash command: \"{command}\"")), + } + } +} + +zed::register_extension!(SlashCommandsExampleExtension);