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 #[serde(default)]
37 pub terminal_bypass: bool,
38}
39
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)]
42#[serde(deny_unknown_fields)]
43#[ts(export, rename = "PromptSuggestion")]
44pub struct Suggestion {
45 pub text: String,
47 #[serde(default)]
49 #[ts(optional)]
50 pub description: Option<String>,
51 #[serde(default)]
53 #[ts(optional)]
54 pub value: Option<String>,
55 #[serde(default)]
57 #[ts(optional)]
58 pub disabled: Option<bool>,
59 #[serde(default)]
61 #[ts(optional)]
62 pub keybinding: Option<String>,
63 #[serde(skip)]
65 #[ts(skip)]
66 pub source: Option<CommandSource>,
67}
68
69#[cfg(feature = "plugins")]
70impl<'js> rquickjs::FromJs<'js> for Suggestion {
71 fn from_js(_ctx: &rquickjs::Ctx<'js>, value: rquickjs::Value<'js>) -> rquickjs::Result<Self> {
72 rquickjs_serde::from_value(value).map_err(|e| rquickjs::Error::FromJs {
73 from: "object",
74 to: "Suggestion",
75 message: Some(e.to_string()),
76 })
77 }
78}
79
80impl Suggestion {
81 pub fn new(text: String) -> Self {
82 Self {
83 text,
84 description: None,
85 value: None,
86 disabled: None,
87 keybinding: None,
88 source: None,
89 }
90 }
91
92 pub fn is_disabled(&self) -> bool {
94 self.disabled.unwrap_or(false)
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
104 fn is_disabled_reflects_disabled_field() {
105 let mut s = Suggestion::new("foo".into());
106 assert!(!s.is_disabled(), "None defaults to enabled");
107
108 s.disabled = Some(false);
109 assert!(!s.is_disabled());
110
111 s.disabled = Some(true);
112 assert!(s.is_disabled());
113 }
114
115 #[cfg(feature = "plugins")]
119 #[test]
120 fn suggestion_from_js_decodes_distinguishing_fields() {
121 use rquickjs::{Context, FromJs, Runtime, Value};
122 let rt = Runtime::new().unwrap();
123 let ctx = Context::full(&rt).unwrap();
124 ctx.with(|ctx| {
125 let v: Value = ctx
126 .eval::<Value, _>(b"({text: 'hello', description: 'world'})".as_slice())
127 .unwrap();
128 let got = Suggestion::from_js(&ctx, v).unwrap();
129 assert_eq!(got.text, "hello");
130 assert_eq!(got.description.as_deref(), Some("world"));
131 });
132 }
133}