sync_lsp/workspace/
execute_command.rs

1//! Implementation for the `workspace/executeCommand` request.
2//! 
3//! # Usage
4//! Commands can be attached to certain actions on the client side and then be executed on the server side.
5//! This module provides a [`Command`] trait that can be implemented through a macro to define commands that
6//! can be executed by the server via [`Server::on_execute_command`].
7//! 
8//! # Example
9//! ```
10//!use sync_lsp::text_document::{Range, Position};
11//!use sync_lsp::text_document::code_lens::CodeLens;
12//!use sync_lsp::{Transport, TypeProvider, Server, UnitType};
13//!use sync_lsp::workspace::execute_command::Command;
14//!use log::info;
15//!
16//!// This enum defines all commands that can be executed by the server.
17//!// It could also be a struct or a tuple struct.
18//!// Even unit structs and enum variants are supported.
19//!#[derive(Clone, Command, Debug)]
20//!enum MyCommand {
21//!    #[command(title = "My first command")]
22//!    MyCommand,
23//!    #[command(title = "My command with arguments")]
24//!    MyCommandWithArguments(u32),
25//!}
26//!
27//!// For this example, we don't need any state.
28//!struct MyServerState;
29//!
30//!// This macro provides default implementations for all required types.
31//!#[sync_lsp::type_provider]
32//!impl TypeProvider for MyServerState {
33//!    type Command = MyCommand;
34//!}
35//!
36//!fn main() {
37//!    let transport = Transport::stdio();
38//!    let mut server = Server::new(MyServerState, transport);
39//!
40//!    // One example for a way to send commands to the client is the code lens request.
41//!    server.on_code_lens(|_, _| {
42//!        vec![
43//!            CodeLens {
44//!                // For this example, we just return a code lens at the beginning of the document.
45//!                range: Range {
46//!                    start: Position { line: 0, character: 0 },
47//!                    end: Position { line: 0, character: 0 }
48//!                },
49//!                // This command will be executed when the user clicks on the code lens.
50//!                command: Some(MyCommand::MyCommandWithArguments(1)),
51//!                // Since we didn't override TypeProvider::CodeLensData, we have to use UnitType here.
52//!                data: UnitType
53//!            }
54//!        ]
55//!    });
56//!
57//!    server.on_execute_command(|_, command| {
58//!        // Instead of executing the command here, we just log it.
59//!        info!("Received command: {:?}", command);
60//!    });
61//!
62//!    server.serve().unwrap();
63//!}
64//! ```
65
66use crate::TypeProvider;
67use crate::{Server, connection::Endpoint};
68use crate::connection::Callback;
69use serde::{Serialize, Serializer, Deserializer, Deserialize};
70pub use sync_lsp_derive::Command;
71
72#[derive(Serialize, Default, Clone)]
73pub(crate) struct ExecuteCommandOptions {
74    commands: Vec<String>
75}
76
77pub(crate) struct CommandContainer<C: Command>(pub C);
78
79/// A unit command is a command that does not take any arguments.
80/// Command arguments are always optional, which is why this type
81/// never needs to be instantiated and is therefore an empty enum.
82#[derive(Debug, Clone, Deserialize)]
83pub enum UnitCommand {}
84
85/// Defines a command that can be executed by this server.
86/// Instead of implementing this trait manually, you can use the `Command` derive macro.
87/// If you do so, you must also derive [`Clone`].
88/// Implementing this trait manually might break the connection if not done properly.
89pub trait Command: Clone {
90    /// Returns a vector of commands that can be executed by this server.
91    fn commands() -> Vec<String>;
92    /// This is beeing forwared to the `serde::Serialize::serialize` implementation.
93    fn serialize<T: Serializer>(&self, serializer: T) -> Result<T::Ok, T::Error>;
94    /// This is beeing forwared to the `serde::Deserialize::deserialize` implementation.
95    fn deserialize<'de, T: Deserializer<'de>>(deserializer: T) -> Result<Self, T::Error> where Self: Sized;
96}
97
98impl ExecuteCommandOptions {
99
100    pub(crate) const METHOD: &'static str = "workspace/executeCommand";
101    
102    pub(super) fn endpoint<T: TypeProvider>() -> Endpoint<T, ExecuteCommandOptions> {
103        let mut endpoint = Endpoint::<T, ExecuteCommandOptions>::new(Callback::request(|_, _: CommandContainer<T::Command>| ()));
104        endpoint.options_mut().commands = T::Command::commands();
105        endpoint
106    }
107}
108
109impl<T: TypeProvider> Server<T> {
110
111    /// Sets the callback that will be called to [execute a command](self).
112    /// 
113    /// # Argument
114    /// * `callback` - A callback which is called with the following parameters as soon as the corresponding request is received:
115    ///     * The server instance receiving the response.
116    ///     * The `Command` to be executed.
117    
118    pub fn on_execute_command<R: 'static + Serialize>(&mut self, callback: fn(&mut Server<T>, T::Command) -> R) {
119        self.workspace.execute_command.set_callback(Callback::request(move |server, params: CommandContainer<T::Command>| {
120            callback(server, params.0)
121        }))
122    }
123}
124
125pub(crate) fn deserialize_opt_command<'de, D: Deserializer<'de>, C: Command>(deserializer: D) -> Result<Option<C>, D::Error> {
126    Ok(Some(Command::deserialize(deserializer)?))
127}
128
129pub(crate) fn serialize_opt_command<S: Serializer, C: Command>(command: &Option<C>, serializer: S) -> Result<S::Ok, S::Error> {
130    if let Some(command) = command {
131        command.serialize(serializer)
132    } else {
133        serializer.serialize_none()
134    }
135}
136
137impl<C: Command> Serialize for CommandContainer<C> {
138    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
139        self.0.serialize(serializer)
140    }
141}
142
143impl<'de, C:Command> Deserialize<'de> for CommandContainer<C> {
144    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
145        Ok(CommandContainer(C::deserialize(deserializer)?))
146    }
147}
148
149impl Command for UnitCommand {
150    fn commands() -> Vec<String> {
151        vec![]
152    }
153
154    fn serialize<T: Serializer>(&self, _: T) -> Result<T::Ok, T::Error> {
155        match *self {}
156    }
157
158    fn deserialize<'de, T: Deserializer<'de>>(deserializer: T) -> Result<Self, T::Error> where Self: Sized {
159        <Self as Deserialize>::deserialize(deserializer)
160    }
161}