1use std::result;
2use std::sync::{mpsc, Arc};
3
4use neovim_lib::{Handler, RequestHandler, Value};
5
6use crate::ui::UiMutex;
7use crate::shell;
8use glib;
9
10use super::repaint_mode::RepaintMode;
11use super::redraw_handler;
12
13pub struct NvimHandler {
14 shell: Arc<UiMutex<shell::State>>,
15
16 delayed_redraw_event_id: Arc<UiMutex<Option<glib::SourceId>>>,
17}
18
19impl NvimHandler {
20 pub fn new(shell: Arc<UiMutex<shell::State>>) -> NvimHandler {
21 NvimHandler {
22 shell,
23 delayed_redraw_event_id: Arc::new(UiMutex::new(None)),
24 }
25 }
26
27 pub fn schedule_redraw_event(&self, event: Value) {
28 let shell = self.shell.clone();
29 let delayed_redraw_event_id = self.delayed_redraw_event_id.clone();
30
31 glib::idle_add(move || {
32 let id = Some(glib::timeout_add(
33 250,
34 clone!(shell, event, delayed_redraw_event_id => move || {
35 delayed_redraw_event_id.replace(None);
36
37 if let Err(msg) = call_redraw_handler(vec![event.clone()], &shell) {
38 error!("Error call function: {}", msg);
39 }
40
41 glib::Continue(false)
42 }),
43 ));
44
45 delayed_redraw_event_id.replace(id);
46
47 glib::Continue(false)
48 });
49 }
50
51 pub fn remove_scheduled_redraw_event(&self) {
52 let delayed_redraw_event_id = self.delayed_redraw_event_id.clone();
53 glib::idle_add(move || {
54 let id = delayed_redraw_event_id.replace(None);
55 if let Some(ev_id) = id {
56 glib::source_remove(ev_id);
57 }
58
59 glib::Continue(false)
60 });
61 }
62
63 fn nvim_cb(&self, method: &str, mut params: Vec<Value>) {
64 match method {
65 "redraw" => {
66 redraw_handler::remove_or_delay_uneeded_events(self, &mut params);
67
68 self.safe_call(move |ui| call_redraw_handler(params, ui));
69 }
70 "Gui" => {
71 if !params.is_empty() {
72 let mut params_iter = params.into_iter();
73 if let Some(ev_name) = params_iter.next() {
74 if let Value::String(ev_name) = ev_name {
75 let args = params_iter.collect();
76 self.safe_call(move |ui| {
77 let ui = &mut ui.borrow_mut();
78 redraw_handler::call_gui_event(
79 ui,
80 ev_name
81 .as_str()
82 .ok_or_else(|| "Event name does not exists")?,
83 args,
84 )?;
85 ui.on_redraw(&RepaintMode::All);
86 Ok(())
87 });
88 } else {
89 error!("Unsupported event");
90 }
91 } else {
92 error!("Event name does not exists");
93 }
94 } else {
95 error!("Unsupported event {:?}", params);
96 }
97 }
98 "subscription" => {
99 self.safe_call(move |ui| {
100 let ui = &ui.borrow();
101 ui.notify(params)
102 });
103 }
104 _ => {
105 error!("Notification {}({:?})", method, params);
106 }
107 }
108 }
109
110 fn nvim_cb_req(&self, method: &str, params: Vec<Value>) -> result::Result<Value, Value> {
111 match method {
112 "Gui" => {
113 if !params.is_empty() {
114 let mut params_iter = params.into_iter();
115 if let Some(req_name) = params_iter.next() {
116 if let Value::String(req_name) = req_name {
117 let args = params_iter.collect();
118 let (sender, receiver) = mpsc::channel();
119 self.safe_call(move |ui| {
120 sender
121 .send(redraw_handler::call_gui_request(
122 &ui.clone(),
123 req_name
124 .as_str()
125 .ok_or_else(|| "Event name does not exists")?,
126 &args,
127 ))
128 .unwrap();
129 {
130 let ui = &mut ui.borrow_mut();
131 ui.on_redraw(&RepaintMode::All);
132 }
133 Ok(())
134 });
135 Ok(receiver.recv().unwrap()?)
136 } else {
137 error!("Unsupported request");
138 Err(Value::Nil)
139 }
140 } else {
141 error!("Request name does not exist");
142 Err(Value::Nil)
143 }
144 } else {
145 error!("Unsupported request {:?}", params);
146 Err(Value::Nil)
147 }
148 }
149 _ => {
150 error!("Request {}({:?})", method, params);
151 Err(Value::Nil)
152 }
153 }
154 }
155
156 fn safe_call<F>(&self, cb: F)
157 where
158 F: FnOnce(&Arc<UiMutex<shell::State>>) -> result::Result<(), String> + 'static + Send,
159 {
160 safe_call(self.shell.clone(), cb);
161 }
162}
163
164fn call_redraw_handler(
165 params: Vec<Value>,
166 ui: &Arc<UiMutex<shell::State>>,
167) -> result::Result<(), String> {
168 let ui = &mut ui.borrow_mut();
169 let mut repaint_mode = RepaintMode::Nothing;
170
171 for ev in params {
172 if let Value::Array(ev_args) = ev {
173 let mut args_iter = ev_args.into_iter();
174 let ev_name = args_iter.next();
175 if let Some(ev_name) = ev_name {
176 if let Some(ev_name) = ev_name.as_str() {
177 for local_args in args_iter {
178 let args = match local_args {
179 Value::Array(ar) => ar,
180 _ => vec![],
181 };
182 let call_reapint_mode = match redraw_handler::call(ui, &ev_name, args) {
183 Ok(mode) => mode,
184 Err(desc) => return Err(format!("Event {}\n{}", ev_name, desc)),
185 };
186 repaint_mode = repaint_mode.join(call_reapint_mode);
187 }
188 } else {
189 error!("Unsupported event");
190 }
191 } else {
192 error!("Event name does not exists");
193 }
194 } else {
195 error!("Unsupported event type {:?}", ev);
196 }
197 }
198
199 ui.on_redraw(&repaint_mode);
200 Ok(())
201}
202
203fn safe_call<F>(shell: Arc<UiMutex<shell::State>>, cb: F)
204where
205 F: FnOnce(&Arc<UiMutex<shell::State>>) -> result::Result<(), String> + 'static + Send,
206{
207 let mut cb = Some(cb);
208 glib::idle_add(move || {
209 if let Err(msg) = cb.take().unwrap()(&shell) {
210 error!("Error call function: {}", msg);
211 }
212 glib::Continue(false)
213 });
214}
215
216impl Handler for NvimHandler {
217 fn handle_notify(&mut self, name: &str, args: Vec<Value>) {
218 self.nvim_cb(name, args);
219 }
220
221}
222
223impl RequestHandler for NvimHandler {
224 fn handle_request(&mut self, name: &str, args: Vec<Value>) -> result::Result<Value, Value> {
225 self.nvim_cb_req(name, args)
226 }
227}