libccanvas/bindings/request/
request.rs

1use std::{collections::BTreeMap, path::PathBuf};
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::{bindings::Discriminator, client::Client};
7
8use super::Subscription;
9
10#[derive(Serialize, Debug, Clone)]
11/// A single request to send to the server.
12pub struct Request {
13    /// recipient
14    target: Discriminator,
15    /// Content of the request
16    pub content: RequestContent,
17    /// confirmation identifier
18    id: u32,
19}
20
21impl Request {
22    /// Construct new self with unique ID.
23    pub fn new(target: Discriminator, content: RequestContent) -> Self {
24        Self {
25            target,
26            content,
27            id: Client::reqid(),
28        }
29    }
30
31    /// Returns ID of self.
32    pub fn id(&self) -> u32 {
33        self.id
34    }
35}
36
37#[derive(Serialize, Clone, PartialEq, Debug)]
38#[serde(tag = "type")]
39/// Real content of the request.
40pub enum RequestContent {
41    #[serde(rename = "confirm recieve")]
42    /// Confirm that an event has been recieved.
43    ConfirmRecieve {
44        /// Event ID
45        id: u32,
46        /// Whether to allow passing of the event or not.
47        /// - true = allow passing
48        /// - false = capture event
49        pass: bool,
50    },
51
52    #[serde(rename = "subscribe")]
53    /// Add a subscription to a channel with priority.
54    Subscribe {
55        channel: Subscription,
56        priority: Option<u32>,
57        component: Option<Discriminator>,
58    },
59
60    #[serde(rename = "Unsubscribe")]
61    /// Remove a subscription from a channel.
62    Unsubscribe {
63        channel: Subscription,
64        component: Option<Discriminator>,
65    },
66    #[serde(rename = "set socket")]
67    /// Hint server to use this socket for communication.
68    ///
69    /// This is ran when the client is created.
70    SetSocket { path: PathBuf },
71
72    #[serde(rename = "drop")]
73    /// Remove a single component.
74    Drop { discrim: Option<Discriminator> },
75
76    #[serde(rename = "render")]
77    /// Render something to the terminal.
78    Render { content: RenderRequest, flush: bool },
79
80    #[serde(rename = "spawn")]
81    /// Spawns a new process.
82    Spawn {
83        command: String,
84        args: Vec<String>,
85        env: BTreeMap<String, String>,
86        label: String,
87    },
88
89    #[serde(rename = "message")]
90    /// Send a message to another component.
91    /// If target specifies a space,
92    /// all components under that space will recieve the message.
93    Message {
94        content: Value,
95        sender: Discriminator,
96        target: Discriminator,
97        tag: String,
98    },
99
100    /// Create a new space at a space.
101    #[serde(rename = "new space")]
102    NewSpace { label: String },
103
104    /// Set focus to a specific space.
105    #[serde(rename = "focus at")]
106    FocusAt,
107
108    /// Get a state value.
109    ///
110    /// A state value is intrinsic to the state of the canvas, e.g. dimensions.
111    /// And cannot be modified programatically.
112    #[serde(rename = "get state")]
113    GetState { label: StateValue },
114
115    /// Get value of an entry (variable).
116    #[serde(rename = "get entry")]
117    GetEntry { label: String },
118
119    /// Remove an entry (variable).
120    #[serde(rename = "remove entry")]
121    RemoveEntry { label: String },
122
123    /// Set value of an entry (variable). Creates the entry if it does not already exist.
124    #[serde(rename = "set entry")]
125    SetEntry { label: String, value: Value },
126
127    /// Watch the value of an entry.
128    #[serde(rename = "watch")]
129    Watch { label: String },
130
131    /// Unwatch the value of an entry.
132    #[serde(rename = "unwatch")]
133    Unwatch {
134        label: String,
135        watcher: Discriminator,
136    },
137
138    /// Suppress all events from a channel for subscribers with a lower priority
139    #[serde(rename = "suppress")]
140    Suppress {
141        channel: Subscription,
142        priority: u32,
143    },
144
145    /// Remove a suppression
146    #[serde(rename = "unsuppress")]
147    Unsuppress { channel: Subscription, id: u32 },
148}
149
150#[derive(Serialize, Clone, PartialEq, Eq, Debug)]
151#[serde(tag = "type")]
152/// A render request to the server.
153pub enum RenderRequest {
154    /// Change a single character
155    #[serde(rename = "set char")]
156    SetChar { x: u32, y: u32, c: char },
157    /// Change a single character, coloured
158    #[serde(rename = "set colouredchar")]
159    SetCharColoured {
160        x: u32,
161        y: u32,
162        c: char,
163        fg: Colour,
164        bg: Colour,
165    },
166    /// Flush all changes, this is usually not needed
167    #[serde(rename = "flush")]
168    Flush,
169    /// Set cursor looks
170    #[serde(rename = "set cursorstyle")]
171    SetCursorStyle { style: CursorStyle },
172    /// Hide cursor
173    #[serde(rename = "hide cursor")]
174    HideCursor,
175    /// Unhide cursor
176    #[serde(rename = "show cursor")]
177    ShowCursor,
178    /// Clear terminal content
179    #[serde(rename = "clear all")]
180    ClearAll,
181
182    /// Clear terminal content within a specified area
183    #[serde(rename = "clear area")]
184    ClearArea {
185        x: u32,
186        y: u32,
187        width: u32,
188        height: u32,
189    },
190
191    /// Render multiple items at the same time - guaranteed to be rendered at the same time, and
192    /// socket performance is significantly better than sending individual requests.
193    #[serde(rename = "render multiple")]
194    RenderMultiple { tasks: Vec<Self> },
195}
196
197impl RenderRequest {
198    /// Create a setchar request
199    pub fn setchar(x: u32, y: u32, c: char) -> Self {
200        Self::SetChar { x, y, c }
201    }
202
203    /// Create a setchar coloured request
204    pub fn setchar_coloured(x: u32, y: u32, c: char, fg: Colour, bg: Colour) -> Self {
205        Self::SetCharColoured { x, y, c, fg, bg }
206    }
207
208    /// Create a setcursor request
209    pub fn setcursor(style: CursorStyle) -> Self {
210        Self::SetCursorStyle { style }
211    }
212}
213
214#[derive(Serialize, Clone, Copy, PartialEq, Eq, Debug)]
215/// A cursor style.
216pub enum CursorStyle {
217    #[serde(rename = "blinking bar")]
218    BlinkingBar,
219    #[serde(rename = "blinking block")]
220    BlinkingBlock,
221    #[serde(rename = "blinking underline")]
222    BlinkingUnderline,
223    #[serde(rename = "steady bar")]
224    SteadyBar,
225    #[serde(rename = "steady block")]
226    SteadyBlock,
227    #[serde(rename = "steady underline")]
228    SteadyUnderline,
229}
230
231#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug)]
232#[serde(tag = "type")]
233/// Terminal colours.
234pub enum Colour {
235    #[serde(rename = "black")]
236    Black,
237    #[serde(rename = "blue")]
238    Blue,
239    #[serde(rename = "cyan")]
240    Cyan,
241    #[serde(rename = "green")]
242    Green,
243    #[serde(rename = "magenta")]
244    Magenta,
245    #[serde(rename = "red")]
246    Red,
247    #[serde(rename = "white")]
248    White,
249    #[serde(rename = "yellow")]
250    Yellow,
251
252    #[serde(rename = "lightblack")]
253    LightBlack,
254    #[serde(rename = "lightblue")]
255    LightBlue,
256    #[serde(rename = "lightcyan")]
257    LightCyan,
258    #[serde(rename = "lightgreen")]
259    LightGreen,
260    #[serde(rename = "lightmagenta")]
261    LightMagenta,
262    #[serde(rename = "lightred")]
263    LightRed,
264    #[serde(rename = "lightwhite")]
265    LightWhite,
266    #[serde(rename = "lightyellow")]
267    LightYellow,
268
269    #[serde(rename = "reset")]
270    Reset,
271    #[serde(rename = "ansi")]
272    Ansi { value: u8 },
273    #[serde(rename = "rgb")]
274    Rgb { red: u8, green: u8, blue: u8 },
275}
276
277impl Colour {
278    /// Construct an ansi colour struct
279    pub fn ansi(value: u8) -> Self {
280        Self::Ansi { value }
281    }
282
283    /// Construct an rgb colour struct
284    pub fn rgb(r: u8, g: u8, b: u8) -> Self {
285        Self::Rgb {
286            red: r,
287            green: g,
288            blue: b,
289        }
290    }
291}
292
293/// Intrinsic state values
294#[derive(Serialize, Clone, PartialEq, Eq, Debug)]
295pub enum StateValue {
296    #[serde(rename = "focused")]
297    Focused,
298    #[serde(rename = "is focused")]
299    IsFocused,
300    #[serde(rename = "term size")]
301    TermSize,
302    #[serde(rename = "working dir")]
303    WorkingDir,
304}