1use std::time::Instant;
18
19use serde_json::{self, Value};
20use xi_rpc::{self, RpcPeer};
21
22use crate::config::Table;
23use crate::plugins::rpc::ClientPluginInfo;
24use crate::plugins::Command;
25use crate::styles::ThemeSettings;
26use crate::syntax::LanguageId;
27use crate::tabs::ViewId;
28use crate::width_cache::{WidthReq, WidthResponse};
29
30pub struct Client(RpcPeer);
32
33impl Client {
34 pub fn new(peer: RpcPeer) -> Self {
35 Client(peer)
36 }
37
38 pub fn update_view(&self, view_id: ViewId, update: &Update) {
39 self.0.send_rpc_notification(
40 "update",
41 &json!({
42 "view_id": view_id,
43 "update": update,
44 }),
45 );
46 }
47
48 pub fn scroll_to(&self, view_id: ViewId, line: usize, col: usize) {
49 self.0.send_rpc_notification(
50 "scroll_to",
51 &json!({
52 "view_id": view_id,
53 "line": line,
54 "col": col,
55 }),
56 );
57 }
58
59 pub fn config_changed(&self, view_id: ViewId, changes: &Table) {
60 self.0.send_rpc_notification(
61 "config_changed",
62 &json!({
63 "view_id": view_id,
64 "changes": changes,
65 }),
66 );
67 }
68
69 pub fn available_themes(&self, theme_names: Vec<String>) {
70 self.0.send_rpc_notification("available_themes", &json!({ "themes": theme_names }))
71 }
72
73 pub fn available_languages(&self, languages: Vec<LanguageId>) {
74 self.0.send_rpc_notification("available_languages", &json!({ "languages": languages }))
75 }
76
77 pub fn theme_changed(&self, name: &str, theme: &ThemeSettings) {
78 self.0.send_rpc_notification(
79 "theme_changed",
80 &json!({
81 "name": name,
82 "theme": theme,
83 }),
84 );
85 }
86
87 pub fn language_changed(&self, view_id: ViewId, new_lang: &LanguageId) {
88 self.0.send_rpc_notification(
89 "language_changed",
90 &json!({
91 "view_id": view_id,
92 "language_id": new_lang,
93 }),
94 );
95 }
96
97 pub fn plugin_started(&self, view_id: ViewId, plugin: &str) {
99 self.0.send_rpc_notification(
100 "plugin_started",
101 &json!({
102 "view_id": view_id,
103 "plugin": plugin,
104 }),
105 );
106 }
107
108 pub fn plugin_stopped(&self, view_id: ViewId, plugin: &str, code: i32) {
113 self.0.send_rpc_notification(
114 "plugin_stopped",
115 &json!({
116 "view_id": view_id,
117 "plugin": plugin,
118 "code": code,
119 }),
120 );
121 }
122
123 pub fn available_plugins(&self, view_id: ViewId, plugins: &[ClientPluginInfo]) {
125 self.0.send_rpc_notification(
126 "available_plugins",
127 &json!({
128 "view_id": view_id,
129 "plugins": plugins }),
130 );
131 }
132
133 pub fn update_cmds(&self, view_id: ViewId, plugin: &str, cmds: &[Command]) {
134 self.0.send_rpc_notification(
135 "update_cmds",
136 &json!({
137 "view_id": view_id,
138 "plugin": plugin,
139 "cmds": cmds,
140 }),
141 );
142 }
143
144 pub fn def_style(&self, style: &Value) {
145 self.0.send_rpc_notification("def_style", &style)
146 }
147
148 pub fn find_status(&self, view_id: ViewId, queries: &Value) {
149 self.0.send_rpc_notification(
150 "find_status",
151 &json!({
152 "view_id": view_id,
153 "queries": queries,
154 }),
155 );
156 }
157
158 pub fn replace_status(&self, view_id: ViewId, replace: &Value) {
159 self.0.send_rpc_notification(
160 "replace_status",
161 &json!({
162 "view_id": view_id,
163 "status": replace,
164 }),
165 );
166 }
167
168 pub fn measure_width(&self, reqs: &[WidthReq]) -> Result<WidthResponse, xi_rpc::Error> {
170 let req_json = serde_json::to_value(reqs).expect("failed to serialize width req");
171 let resp = self.0.send_rpc_request("measure_width", &req_json)?;
172 Ok(serde_json::from_value(resp).expect("failed to deserialize width response"))
173 }
174
175 pub fn alert<S: AsRef<str>>(&self, msg: S) {
176 self.0.send_rpc_notification("alert", &json!({ "msg": msg.as_ref() }));
177 }
178
179 pub fn add_status_item(
180 &self,
181 view_id: ViewId,
182 source: &str,
183 key: &str,
184 value: &str,
185 alignment: &str,
186 ) {
187 self.0.send_rpc_notification(
188 "add_status_item",
189 &json!({
190 "view_id": view_id,
191 "source": source,
192 "key": key,
193 "value": value,
194 "alignment": alignment
195 }),
196 );
197 }
198
199 pub fn update_status_item(&self, view_id: ViewId, key: &str, value: &str) {
200 self.0.send_rpc_notification(
201 "update_status_item",
202 &json!({
203 "view_id": view_id,
204 "key": key,
205 "value": value,
206 }),
207 );
208 }
209
210 pub fn remove_status_item(&self, view_id: ViewId, key: &str) {
211 self.0.send_rpc_notification(
212 "remove_status_item",
213 &json!({
214 "view_id": view_id,
215 "key": key,
216 }),
217 );
218 }
219
220 pub fn show_hover(&self, view_id: ViewId, request_id: usize, result: String) {
221 self.0.send_rpc_notification(
222 "show_hover",
223 &json!({
224 "view_id": view_id,
225 "request_id": request_id,
226 "result": result,
227 }),
228 )
229 }
230
231 pub fn schedule_idle(&self, token: usize) {
232 self.0.schedule_idle(token)
233 }
234
235 pub fn schedule_timer(&self, timeout: Instant, token: usize) {
236 self.0.schedule_timer(timeout, token);
237 }
238}
239
240#[derive(Debug, Serialize)]
241pub struct Update {
242 pub(crate) ops: Vec<UpdateOp>,
243 pub(crate) pristine: bool,
244 pub(crate) annotations: Vec<Value>,
245}
246
247#[derive(Debug, Serialize)]
248pub(crate) struct UpdateOp {
249 op: OpType,
250 n: usize,
251 #[serde(skip_serializing_if = "Option::is_none")]
252 lines: Option<Vec<Value>>,
253 #[serde(rename = "ln")]
254 #[serde(skip_serializing_if = "Option::is_none")]
255 first_line_number: Option<usize>,
256}
257
258impl UpdateOp {
259 pub(crate) fn invalidate(n: usize) -> Self {
260 UpdateOp { op: OpType::Invalidate, n, lines: None, first_line_number: None }
261 }
262
263 pub(crate) fn skip(n: usize) -> Self {
264 UpdateOp { op: OpType::Skip, n, lines: None, first_line_number: None }
265 }
266
267 pub(crate) fn copy(n: usize, line: usize) -> Self {
268 UpdateOp { op: OpType::Copy, n, lines: None, first_line_number: Some(line) }
269 }
270
271 pub(crate) fn insert(lines: Vec<Value>) -> Self {
272 UpdateOp { op: OpType::Insert, n: lines.len(), lines: Some(lines), first_line_number: None }
273 }
274}
275
276#[derive(Debug, Clone, Serialize)]
277#[serde(rename_all = "lowercase")]
278enum OpType {
279 #[serde(rename = "ins")]
280 Insert,
281 Skip,
282 Invalidate,
283 Copy,
284}