1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)]
5#[ts(export)]
6pub enum CommandSource {
7 Builtin,
9 Plugin(String),
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS)]
16#[ts(export)]
17pub struct Command {
18 pub name: String,
20 pub description: String,
22 pub action_name: String,
24 pub plugin_name: String,
26 pub custom_contexts: Vec<String>,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)]
32#[serde(deny_unknown_fields)]
33#[ts(export, rename = "PromptSuggestion")]
34pub struct Suggestion {
35 pub text: String,
37 #[serde(default)]
39 #[ts(optional)]
40 pub description: Option<String>,
41 #[serde(default)]
43 #[ts(optional)]
44 pub value: Option<String>,
45 #[serde(default)]
47 #[ts(optional)]
48 pub disabled: Option<bool>,
49 #[serde(default)]
51 #[ts(optional)]
52 pub keybinding: Option<String>,
53 #[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 pub fn is_disabled(&self) -> bool {
84 self.disabled.unwrap_or(false)
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
94 fn is_disabled_reflects_disabled_field() {
95 let mut s = Suggestion::new("foo".into());
96 assert!(!s.is_disabled(), "None defaults to enabled");
97
98 s.disabled = Some(false);
99 assert!(!s.is_disabled());
100
101 s.disabled = Some(true);
102 assert!(s.is_disabled());
103 }
104
105 #[cfg(feature = "plugins")]
109 #[test]
110 fn suggestion_from_js_decodes_distinguishing_fields() {
111 use rquickjs::{Context, FromJs, Runtime, Value};
112 let rt = Runtime::new().unwrap();
113 let ctx = Context::full(&rt).unwrap();
114 ctx.with(|ctx| {
115 let v: Value = ctx
116 .eval::<Value, _>(b"({text: 'hello', description: 'world'})".as_slice())
117 .unwrap();
118 let got = Suggestion::from_js(&ctx, v).unwrap();
119 assert_eq!(got.text, "hello");
120 assert_eq!(got.description.as_deref(), Some("world"));
121 });
122 }
123}