Skip to main content

fresh_core/
command.rs

1use serde::{Deserialize, Serialize};
2
3/// Source of a command (builtin or from a plugin)
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)]
5#[ts(export)]
6pub enum CommandSource {
7    /// Built-in editor command
8    Builtin,
9    /// Command registered by a plugin (contains plugin filename without extension)
10    Plugin(String),
11}
12
13/// A command registered by a plugin via the service bridge.
14/// This is a simplified version that the editor converts to its internal Command type.
15#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS)]
16#[ts(export)]
17pub struct Command {
18    /// Command name (e.g., "Open File")
19    pub name: String,
20    /// Command description
21    pub description: String,
22    /// The action name to trigger (for plugin commands, this is the function name)
23    pub action_name: String,
24    /// Plugin that registered this command
25    pub plugin_name: String,
26    /// Custom contexts required for this command (plugin-defined contexts like "vi-mode")
27    pub custom_contexts: Vec<String>,
28}
29
30/// A single suggestion item for autocomplete
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)]
32#[serde(deny_unknown_fields)]
33#[ts(export, rename = "PromptSuggestion")]
34pub struct Suggestion {
35    /// The text to display
36    pub text: String,
37    /// Optional description
38    #[serde(default)]
39    #[ts(optional)]
40    pub description: Option<String>,
41    /// The value to use when selected (defaults to text if None)
42    #[serde(default)]
43    #[ts(optional)]
44    pub value: Option<String>,
45    /// Whether this suggestion is disabled (greyed out, defaults to false)
46    #[serde(default)]
47    #[ts(optional)]
48    pub disabled: Option<bool>,
49    /// Optional keyboard shortcut
50    #[serde(default)]
51    #[ts(optional)]
52    pub keybinding: Option<String>,
53    /// Source of the command (for command palette) - internal, not settable by plugins
54    #[serde(skip)]
55    #[ts(skip)]
56    pub source: Option<CommandSource>,
57}
58
59#[cfg(feature = "plugins")]
60impl<'js> rquickjs::FromJs<'js> for Suggestion {
61    fn from_js(_ctx: &rquickjs::Ctx<'js>, value: rquickjs::Value<'js>) -> rquickjs::Result<Self> {
62        rquickjs_serde::from_value(value).map_err(|e| rquickjs::Error::FromJs {
63            from: "object",
64            to: "Suggestion",
65            message: Some(e.to_string()),
66        })
67    }
68}
69
70impl Suggestion {
71    pub fn new(text: String) -> Self {
72        Self {
73            text,
74            description: None,
75            value: None,
76            disabled: None,
77            keybinding: None,
78            source: None,
79        }
80    }
81
82    /// Check if this suggestion is disabled
83    pub fn is_disabled(&self) -> bool {
84        self.disabled.unwrap_or(false)
85    }
86}