Commit
+5 -1119 +/-8 browse
1 | diff --git a/meli/docs/meli.1 b/meli/docs/meli.1 |
2 | index 856a30e..fb6daff 100644 |
3 | --- a/meli/docs/meli.1 |
4 | +++ b/meli/docs/meli.1 |
5 | @@ -649,7 +649,7 @@ catchall for general errors |
6 | process panic |
7 | .El |
8 | .Sh ENVIRONMENT |
9 | - .Bl -tag -width "$XDG_CONFIG_HOME/meli/plugins/*" -offset indent |
10 | + .Bl -tag -width "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -offset indent |
11 | .It Ev EDITOR |
12 | Specifies the editor to use |
13 | .It Ev MELI_CONFIG |
14 | @@ -665,7 +665,7 @@ overrides this. |
15 | .Sh FILES |
16 | .Nm |
17 | uses the following parts of the XDG standard: |
18 | - .Bl -tag -width "$XDG_CONFIG_HOME/meli/plugins/*" -offset indent |
19 | + .Bl -tag -width "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -offset indent |
20 | .It Ev XDG_CONFIG_HOME |
21 | defaults to |
22 | .Pa ~/.config/ |
23 | @@ -675,17 +675,13 @@ defaults to |
24 | .El |
25 | .Pp |
26 | and appropriates the following locations: |
27 | - .Bl -tag -width "$XDG_CONFIG_HOME/meli/plugins/*" -offset indent |
28 | + .Bl -tag -width "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -offset indent |
29 | .It Pa $XDG_CONFIG_HOME/meli/ |
30 | User configuration directory |
31 | .It Pa $XDG_CONFIG_HOME/meli/config.toml |
32 | User configuration file, see |
33 | .Xr meli.conf 5 |
34 | for its syntax and values. |
35 | - .It Pa $XDG_CONFIG_HOME/meli/hooks/* |
36 | - Reserved for event hooks. |
37 | - .It Pa $XDG_CONFIG_HOME/meli/plugins/* |
38 | - Reserved for plugin files. |
39 | .It Pa $XDG_CACHE_HOME/meli/* |
40 | Internal cached data used by meli. |
41 | .It Pa $XDG_DATA_HOME/meli/* |
42 | diff --git a/meli/src/plugins.rs b/meli/src/plugins.rs |
43 | deleted file mode 100644 |
44 | index 103df5b..0000000 |
45 | --- a/meli/src/plugins.rs |
46 | +++ /dev/null |
47 | @@ -1,303 +0,0 @@ |
48 | - /* |
49 | - * meli - ui plugins |
50 | - * |
51 | - * Copyright 2019 Manos Pitsidianakis |
52 | - * |
53 | - * This file is part of meli. |
54 | - * |
55 | - * meli is free software: you can redistribute it and/or modify |
56 | - * it under the terms of the GNU General Public License as published by |
57 | - * the Free Software Foundation, either version 3 of the License, or |
58 | - * (at your option) any later version. |
59 | - * |
60 | - * meli is distributed in the hope that it will be useful, |
61 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
62 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
63 | - * GNU General Public License for more details. |
64 | - * |
65 | - * You should have received a copy of the GNU General Public License |
66 | - * along with meli. If not, see <http://www.gnu.org/licenses/>. |
67 | - */ |
68 | - |
69 | - //! Plugins are executed by meli and communication is done by `messagepack` IPC. |
70 | - |
71 | - use melib::error::{Error, Result}; |
72 | - use std::collections::HashMap; |
73 | - use std::io::Write; |
74 | - use std::os::unix::net::{UnixListener, UnixStream}; |
75 | - use std::path::PathBuf; |
76 | - use std::process::Stdio; |
77 | - use uuid::Uuid; |
78 | - |
79 | - //pub mod backend; |
80 | - pub mod rpc; |
81 | - pub use rpc::*; |
82 | - |
83 | - pub const BACKEND_FN: i8 = 0; |
84 | - pub const BACKEND_OP_FN: i8 = 1; |
85 | - |
86 | - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] |
87 | - pub enum PluginKind { |
88 | - LongLived, |
89 | - Filter, |
90 | - Backend, |
91 | - } |
92 | - |
93 | - impl Default for PluginKind { |
94 | - fn default() -> Self { |
95 | - Self::LongLived |
96 | - } |
97 | - } |
98 | - |
99 | - #[derive(Default, Debug, Clone, Serialize, Deserialize)] |
100 | - pub struct Plugin { |
101 | - kind: PluginKind, |
102 | - executable: String, |
103 | - name: String, |
104 | - #[serde(default)] |
105 | - hooks: Vec<String>, |
106 | - } |
107 | - |
108 | - impl Plugin { |
109 | - pub fn kind(&self) -> PluginKind { |
110 | - self.kind |
111 | - } |
112 | - } |
113 | - |
114 | - #[derive(Debug)] |
115 | - pub struct PluginManager { |
116 | - plugins: HashMap<String, Plugin>, |
117 | - sessions: HashMap<Uuid, String>, |
118 | - instances: HashMap<Uuid, std::process::Child>, |
119 | - streams: HashMap<Uuid, RpcChannel>, |
120 | - hooks: HashMap<String, UIHook>, |
121 | - listener: UnixListener, |
122 | - } |
123 | - |
124 | - fn socket_path() -> PathBuf { |
125 | - xdg::BaseDirectories::new() |
126 | - .and_then(|base_dirs| { |
127 | - base_dirs |
128 | - .place_runtime_file("meli-plugins") |
129 | - .or_else(|_| base_dirs.place_cache_file("meli-plugins")) |
130 | - .or_else(|_| { |
131 | - let mut p = base_dirs.get_cache_home(); |
132 | - p.push("meli-plugins"); |
133 | - Ok(p) |
134 | - }) |
135 | - }) |
136 | - .unwrap_or_else(|_| PathBuf::from(".")) |
137 | - } |
138 | - |
139 | - impl Drop for PluginManager { |
140 | - fn drop(&mut self) { |
141 | - let _ = std::fs::remove_file(&socket_path()); |
142 | - for (k, c) in self.instances.iter_mut() { |
143 | - if let Err(err) = debug!(c.kill()) { |
144 | - eprintln!( |
145 | - "Error: could not kill process {} spawned by plugin {} ({})", |
146 | - c.id(), |
147 | - &self.plugins[&self.sessions[k]].name, |
148 | - err |
149 | - ); |
150 | - } |
151 | - } |
152 | - } |
153 | - } |
154 | - |
155 | - impl PluginManager { |
156 | - pub fn new() -> Self { |
157 | - let socket_path = socket_path(); |
158 | - let _ = std::fs::remove_file(&socket_path); |
159 | - let listener = UnixListener::bind(&socket_path).unwrap(); |
160 | - /* |
161 | - debug!("bound"); |
162 | - // accept connections and process them, spawning a new thread for each one |
163 | - thread::spawn(move || { |
164 | - debug!("spawn"); |
165 | - let stream = listener.accept(); |
166 | - debug!("socket stream {:?}", &stream); |
167 | - match stream { |
168 | - Ok((mut stream, _)) => { |
169 | - debug!("socket stream {:?}", &stream); |
170 | - /* connection succeeded */ |
171 | - thread::spawn(move || { |
172 | - debug!("socket listen {:?}", &stream); |
173 | - debug!(initialize(stream)); |
174 | - //let mut response = Vec::new(); |
175 | - //debug!(stream.read_to_end(&mut response)); |
176 | - //loop { |
177 | - // debug!("pre-flush 1"); |
178 | - // stream.flush(); |
179 | - // debug!("post-flush 1"); |
180 | - // if debug!(rmpv::decode::value::read_value(&mut stream)).is_err() { |
181 | - // return; |
182 | - // } |
183 | - // debug!("post-read_value"); |
184 | - // //debug!("socket response {}", unsafe { |
185 | - // // String::from_utf8_lossy(&response) |
186 | - // //}); |
187 | - // stream.flush(); |
188 | - // debug!("post-flush 2"); |
189 | - // if debug!(rmpv::encode::write_value( |
190 | - // &mut stream, |
191 | - // &rmpv::Value::String("hello 2 u 2".into()) |
192 | - // )) |
193 | - // .is_err() |
194 | - // { |
195 | - // return; |
196 | - // } |
197 | - // debug!("post-write_value"); |
198 | - //} |
199 | - }); |
200 | - } |
201 | - Err(err) => { |
202 | - /* connection failed */ |
203 | - debug!(err); |
204 | - } |
205 | - } |
206 | - }); |
207 | - */ |
208 | - let mut hooks: HashMap<String, UIHook> = Default::default(); |
209 | - |
210 | - hooks.insert( |
211 | - "attachment-view".to_string(), |
212 | - UIHook { |
213 | - name: "attachment-view".to_string(), |
214 | - wait_response: true, |
215 | - listeners: Vec::new(), |
216 | - }, |
217 | - ); |
218 | - |
219 | - hooks.insert( |
220 | - "refresh-account".to_string(), |
221 | - UIHook { |
222 | - name: "refresh-account".to_string(), |
223 | - wait_response: false, |
224 | - listeners: Vec::new(), |
225 | - }, |
226 | - ); |
227 | - |
228 | - PluginManager { |
229 | - plugins: Default::default(), |
230 | - sessions: Default::default(), |
231 | - instances: Default::default(), |
232 | - streams: Default::default(), |
233 | - hooks, |
234 | - listener, |
235 | - } |
236 | - } |
237 | - |
238 | - pub fn register(&mut self, plugin: Plugin) -> Result<()> { |
239 | - debug!(&plugin); |
240 | - match plugin.kind { |
241 | - PluginKind::LongLived => { |
242 | - /* spawn thread */ |
243 | - let inv = &plugin.executable; |
244 | - let child = std::process::Command::new("sh") |
245 | - .args(&["-c", inv]) |
246 | - .stdin(Stdio::piped()) |
247 | - .stdout(Stdio::piped()) |
248 | - .spawn()?; |
249 | - let (stream, _) = self.listener.accept()?; |
250 | - /* send init message to plugin to register hooks */ |
251 | - let session = Uuid::new_v4(); |
252 | - let channel = RpcChannel::new(stream, &session)?; |
253 | - |
254 | - for h in &plugin.hooks { |
255 | - self.add_listener(h, session); |
256 | - } |
257 | - |
258 | - self.instances.insert(session, child); |
259 | - self.sessions.insert(session, plugin.name.clone()); |
260 | - self.streams.insert(session, channel); |
261 | - self.plugins.insert(plugin.name.clone(), plugin); |
262 | - Ok(()) |
263 | - } |
264 | - PluginKind::Filter => { |
265 | - let session = Uuid::new_v4(); |
266 | - for h in &plugin.hooks { |
267 | - self.add_listener(h, session); |
268 | - } |
269 | - |
270 | - self.sessions.insert(session, plugin.name.clone()); |
271 | - self.plugins.insert(plugin.name.clone(), plugin); |
272 | - /* send init message to plugin to register hooks */ |
273 | - Ok(()) |
274 | - } |
275 | - PluginKind::Backend => { |
276 | - self.plugins.insert(plugin.name.clone(), plugin); |
277 | - /* send init message to plugin to register hooks */ |
278 | - Ok(()) |
279 | - } |
280 | - } |
281 | - } |
282 | - |
283 | - pub fn register_hook(&mut self, hook: UIHook) { |
284 | - self.hooks.insert(hook.name.clone(), hook); |
285 | - } |
286 | - |
287 | - pub fn add_listener(&mut self, hook: &str, session: Uuid) { |
288 | - self.hooks |
289 | - .entry(hook.to_string()) |
290 | - .and_modify(|entry| entry.listeners.push(session)); |
291 | - } |
292 | - |
293 | - pub fn activate_hook(&mut self, hook: &str, bytes: Vec<u8>) -> Result<FilterResult> { |
294 | - debug!("activate_hook {}", hook); |
295 | - debug!("bytes {:?}", &bytes); |
296 | - for l in &self.hooks[hook].listeners { |
297 | - let plugin = &self.plugins[&self.sessions[l]]; |
298 | - debug!(&plugin); |
299 | - match &plugin.kind { |
300 | - PluginKind::LongLived => { |
301 | - debug!("listener: {}", l); |
302 | - let channel = self.streams.get_mut(l).unwrap(); |
303 | - channel.write_ref(&rmpv::ValueRef::Binary(bytes.as_slice()))?; |
304 | - let reply: Result<FilterResult> = channel.from_read(); |
305 | - return reply; |
306 | - } |
307 | - PluginKind::Filter => { |
308 | - let inv = &plugin.executable; |
309 | - let mut child = std::process::Command::new("sh") |
310 | - .args(&["-c", inv]) |
311 | - .stdin(Stdio::piped()) |
312 | - .stdout(Stdio::piped()) |
313 | - .spawn()?; |
314 | - let (stream, _) = self.listener.accept()?; |
315 | - let mut channel = RpcChannel::new(stream, l)?; |
316 | - channel.write_ref(&rmpv::ValueRef::Binary(bytes.as_slice()))?; |
317 | - let reply: Result<FilterResult> = channel.from_read(); |
318 | - child.kill()?; |
319 | - return reply; |
320 | - } |
321 | - k => { |
322 | - debug!("got plugin kind {:?} in hook {}", k, hook); |
323 | - } |
324 | - } |
325 | - } |
326 | - Err(Error::new("no listeners for this hook")) |
327 | - } |
328 | - |
329 | - pub fn listener(&self) -> UnixListener { |
330 | - self.listener.try_clone().unwrap() |
331 | - } |
332 | - } |
333 | - |
334 | - #[derive(Debug)] |
335 | - pub struct UIHook { |
336 | - name: String, |
337 | - wait_response: bool, |
338 | - listeners: Vec<Uuid>, |
339 | - } |
340 | - |
341 | - #[derive(Debug, Clone, Serialize, Deserialize)] |
342 | - #[serde(rename_all = "snake_case")] |
343 | - #[serde(tag = "t", content = "c")] |
344 | - pub enum FilterResult { |
345 | - UiMessage(String), |
346 | - Text(String), |
347 | - Ansi(String), |
348 | - Binary(Vec<u8>), |
349 | - Error(String), |
350 | - } |
351 | diff --git a/meli/src/plugins/backend.rs b/meli/src/plugins/backend.rs |
352 | deleted file mode 100644 |
353 | index 2891b16..0000000 |
354 | --- a/meli/src/plugins/backend.rs |
355 | +++ /dev/null |
356 | @@ -1,303 +0,0 @@ |
357 | - /* |
358 | - * meli - plugins |
359 | - * |
360 | - * Copyright 2019 Manos Pitsidianakis |
361 | - * |
362 | - * This file is part of meli. |
363 | - * |
364 | - * meli is free software: you can redistribute it and/or modify |
365 | - * it under the terms of the GNU General Public License as published by |
366 | - * the Free Software Foundation, either version 3 of the License, or |
367 | - * (at your option) any later version. |
368 | - * |
369 | - * meli is distributed in the hope that it will be useful, |
370 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
371 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
372 | - * GNU General Public License for more details. |
373 | - * |
374 | - * You should have received a copy of the GNU General Public License |
375 | - * along with meli. If not, see <http://www.gnu.org/licenses/>. |
376 | - */ |
377 | - |
378 | - use super::*; |
379 | - use melib::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext}; |
380 | - use melib::backends::*; |
381 | - use melib::conf::AccountSettings; |
382 | - use melib::email::{Envelope, EnvelopeHash, Flag}; |
383 | - use melib::error::{Error, Result}; |
384 | - use std::collections::BTreeMap; |
385 | - use std::collections::HashMap; |
386 | - use std::sync::{Arc, Mutex, RwLock}; |
387 | - |
388 | - // fields/interface/deserializing |
389 | - #[derive(Debug, Clone, Serialize, Deserialize)] |
390 | - struct SimpleEnvelope { |
391 | - hash: EnvelopeHash, |
392 | - subject: String, |
393 | - from: String, |
394 | - to: String, |
395 | - date: String, |
396 | - message_id: String, |
397 | - references: String, |
398 | - } |
399 | - |
400 | - #[derive(Debug)] |
401 | - pub struct PluginBackend { |
402 | - plugin: Plugin, |
403 | - child: std::process::Child, |
404 | - channel: Arc<Mutex<RpcChannel>>, |
405 | - collection: melib::Collection, |
406 | - is_online: Arc<Mutex<(std::time::Instant, Result<()>)>>, |
407 | - } |
408 | - |
409 | - impl Drop for PluginBackend { |
410 | - fn drop(&mut self) { |
411 | - if let Err(err) = debug!(self.child.kill()) { |
412 | - eprintln!( |
413 | - "Error: could not kill process {} spawned by plugin {} ({})", |
414 | - self.child.id(), |
415 | - &self.plugin.name, |
416 | - err |
417 | - ); |
418 | - } |
419 | - } |
420 | - } |
421 | - |
422 | - impl MailBackend for PluginBackend { |
423 | - fn capabilities(&self) -> MailBackendCapabilities { |
424 | - const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities { |
425 | - is_async: false, |
426 | - is_remote: false, |
427 | - supports_search: false, |
428 | - extensions: None, |
429 | - supports_tags: false, |
430 | - supports_submission: false, |
431 | - }; |
432 | - CAPABILITIES |
433 | - } |
434 | - |
435 | - fn is_online(&self) -> Result<()> { |
436 | - if let Ok(mut is_online) = self.is_online.try_lock() { |
437 | - let now = std::time::Instant::now(); |
438 | - if now.duration_since(is_online.0) >= std::time::Duration::new(2, 0) { |
439 | - if let Ok(mut channel) = self.channel.try_lock() { |
440 | - channel.write_ref(&rmpv::ValueRef::Ext(BACKEND_FN, b"is_online"))?; |
441 | - debug!(channel.expect_ack())?; |
442 | - let ret: PluginResult<()> = debug!(channel.from_read())?; |
443 | - is_online.0 = now; |
444 | - is_online.1 = ret.into(); |
445 | - } |
446 | - } |
447 | - is_online.1.clone() |
448 | - } else { |
449 | - Err(Error::new("busy")) |
450 | - } |
451 | - } |
452 | - |
453 | - fn fetch(&mut self, _mailbox_hash: MailboxHash) -> Result<Async<Result<Vec<Envelope>>>> { |
454 | - let mut w = AsyncBuilder::new(); |
455 | - let channel = self.channel.clone(); |
456 | - let handle = { |
457 | - let tx = w.tx(); |
458 | - let closure = move |_work_context| { |
459 | - let mut channel = channel.lock().unwrap(); |
460 | - channel |
461 | - .write_ref(&rmpv::ValueRef::Ext(BACKEND_FN, b"get")) |
462 | - .unwrap(); |
463 | - channel.expect_ack().unwrap(); |
464 | - loop { |
465 | - let read_val: Result<PluginResult<Option<Vec<SimpleEnvelope>>>> = |
466 | - channel.from_read(); |
467 | - match read_val.map(Into::into).and_then(std::convert::identity) { |
468 | - Ok(Some(a)) => { |
469 | - tx.send(AsyncStatus::Payload(Ok(a |
470 | - .into_iter() |
471 | - .filter_map( |
472 | - |SimpleEnvelope { |
473 | - hash, |
474 | - date, |
475 | - from, |
476 | - to, |
477 | - subject, |
478 | - message_id, |
479 | - references, |
480 | - }| { |
481 | - let mut env = melib::Envelope::new(hash); |
482 | - env.set_date(date.as_bytes()); |
483 | - if let Ok(d) = |
484 | - melib::email::parser::generic::date(date.as_bytes()) |
485 | - { |
486 | - env.set_datetime(d); |
487 | - } |
488 | - env.set_message_id(message_id.as_bytes()); |
489 | - let parse_result = |
490 | - melib::email::parser::address::rfc2822address_list( |
491 | - from.as_bytes(), |
492 | - ); |
493 | - if parse_result.is_ok() { |
494 | - let value = parse_result.unwrap().1; |
495 | - env.set_from(value); |
496 | - } |
497 | - let parse_result = |
498 | - melib::email::parser::address::rfc2822address_list( |
499 | - to.as_bytes(), |
500 | - ); |
501 | - if parse_result.is_ok() { |
502 | - let value = parse_result.unwrap().1; |
503 | - env.set_to(value); |
504 | - } |
505 | - let parse_result = melib::email::parser::encodings::phrase( |
506 | - subject.as_bytes(), |
507 | - false, |
508 | - ); |
509 | - if parse_result.is_ok() { |
510 | - let value = parse_result.unwrap().1; |
511 | - env.set_subject(value); |
512 | - } |
513 | - if !references.is_empty() { |
514 | - env.set_references(references.as_bytes()); |
515 | - } |
516 | - |
517 | - Some(env) |
518 | - }, |
519 | - ) |
520 | - .collect::<Vec<Envelope>>()))) |
521 | - .unwrap(); |
522 | - } |
523 | - Ok(None) => { |
524 | - tx.send(AsyncStatus::Finished).unwrap(); |
525 | - return; |
526 | - } |
527 | - Err(err) => { |
528 | - tx.send(AsyncStatus::Payload(Err(err))).unwrap(); |
529 | - tx.send(AsyncStatus::Finished).unwrap(); |
530 | - return; |
531 | - } |
532 | - }; |
533 | - } |
534 | - }; |
535 | - Box::new(closure) |
536 | - }; |
537 | - Ok(w.build(handle)) |
538 | - } |
539 | - |
540 | - fn mailboxes(&self) -> ResultFuture<HashMap<MailboxHash, Mailbox>> { |
541 | - let mut ret: HashMap<MailboxHash, Mailbox> = Default::default(); |
542 | - ret.insert(0, Mailbox::default()); |
543 | - Ok(Box::pin(async { Ok(ret) })) |
544 | - } |
545 | - |
546 | - fn operation(&self, hash: EnvelopeHash) -> Result<Box<dyn BackendOp>> { |
547 | - Ok(Box::new(PluginOp { |
548 | - hash, |
549 | - channel: self.channel.clone(), |
550 | - bytes: None, |
551 | - })) |
552 | - } |
553 | - |
554 | - fn save( |
555 | - &self, |
556 | - _bytes: Vec<u8>, |
557 | - _mailbox_hash: MailboxHash, |
558 | - _flags: Option<Flag>, |
559 | - ) -> ResultFuture<()> { |
560 | - Err(Error::new("Saving is currently unimplemented for plugins")) |
561 | - } |
562 | - fn create_mailbox( |
563 | - &mut self, |
564 | - _name: String, |
565 | - ) -> ResultFuture<(MailboxHash, HashMap<MailboxHash, Mailbox>)> { |
566 | - Err(Error::new( |
567 | - "Creating a mailbox is currently unimplemented for plugins", |
568 | - )) |
569 | - } |
570 | - fn collection(&self) -> melib::Collection { |
571 | - self.collection.clone() |
572 | - } |
573 | - fn as_any(&self) -> &dyn ::std::any::Any { |
574 | - self |
575 | - } |
576 | - } |
577 | - |
578 | - impl PluginBackend { |
579 | - pub fn new( |
580 | - listener: UnixListener, |
581 | - plugin: Plugin, |
582 | - _s: &AccountSettings, |
583 | - _is_subscribed: Box<dyn Fn(&str) -> bool>, |
584 | - _ev: melib::backends::BackendEventConsumer, |
585 | - ) -> Result<Box<dyn MailBackend>> { |
586 | - if plugin.kind != PluginKind::Backend { |
587 | - return Err(Error::new(format!( |
588 | - "Error: Plugin `{}` is not a mail backend plugin, it's `{:?}`", |
589 | - &plugin.name, &plugin.kind |
590 | - ))); |
591 | - } |
592 | - let inv = &plugin.executable; |
593 | - let child = std::process::Command::new("sh") |
594 | - .args(&["-c", inv]) |
595 | - .stdin(Stdio::piped()) |
596 | - .stdout(Stdio::piped()) |
597 | - .spawn()?; |
598 | - let (stream, _) = listener.accept()?; |
599 | - /* send init message to plugin to register hooks */ |
600 | - let session = Uuid::new_v4(); |
601 | - let channel = RpcChannel::new(stream, &session)?; |
602 | - let now = std::time::Instant::now() - std::time::Duration::from_secs(5); |
603 | - |
604 | - Ok(Box::new(PluginBackend { |
605 | - child, |
606 | - plugin, |
607 | - channel: Arc::new(Mutex::new(channel)), |
608 | - collection: Default::default(), |
609 | - is_online: Arc::new(Mutex::new((now, Err(Error::new("Uninitialized"))))), |
610 | - })) |
611 | - } |
612 | - |
613 | - pub fn register(listener: UnixListener, plugin: Plugin, backends: &mut Backends) { |
614 | - backends.register( |
615 | - plugin.name.clone(), |
616 | - Backend { |
617 | - create_fn: Box::new(move || { |
618 | - let plugin = plugin.clone(); |
619 | - let listener = listener.try_clone().unwrap(); |
620 | - Box::new(move |f, i, ev| { |
621 | - let plugin = plugin.clone(); |
622 | - let listener = listener.try_clone().unwrap(); |
623 | - PluginBackend::new(listener, plugin, f, i, ev) |
624 | - }) |
625 | - }), |
626 | - validate_conf_fn: Box::new(|_| Ok(())), |
627 | - }, |
628 | - ); |
629 | - } |
630 | - } |
631 | - |
632 | - #[derive(Debug)] |
633 | - struct PluginOp { |
634 | - hash: EnvelopeHash, |
635 | - channel: Arc<Mutex<RpcChannel>>, |
636 | - bytes: Option<String>, |
637 | - } |
638 | - |
639 | - impl BackendOp for PluginOp { |
640 | - fn as_bytes(&self) -> ResultFuture<Vec<u8>> { |
641 | - let hash = self.hash; |
642 | - let channel = self.channel.clone(); |
643 | - Ok(Box::pin(async move { |
644 | - if let Ok(mut channel) = channel.try_lock() { |
645 | - channel.write_ref(&rmpv::ValueRef::Ext(BACKEND_OP_FN, b"as_bytes"))?; |
646 | - debug!(channel.expect_ack())?; |
647 | - channel.write_ref(&rmpv::ValueRef::Integer(hash.into()))?; |
648 | - debug!(channel.expect_ack())?; |
649 | - let bytes: Result<PluginResult<String>> = channel.from_read(); |
650 | - Ok(bytes |
651 | - .map(Into::into) |
652 | - .and_then(std::convert::identity)? |
653 | - .into_bytes()) |
654 | - } else { |
655 | - Err(Error::new("busy")) |
656 | - } |
657 | - })) |
658 | - } |
659 | - } |
660 | diff --git a/meli/src/plugins/python3/ansi-plugin.py b/meli/src/plugins/python3/ansi-plugin.py |
661 | deleted file mode 100755 |
662 | index 507cae7..0000000 |
663 | --- a/meli/src/plugins/python3/ansi-plugin.py |
664 | +++ /dev/null |
665 | @@ -1,48 +0,0 @@ |
666 | - #! /usr/bin/env python3 |
667 | - """ |
668 | - meli - sample plugin |
669 | - |
670 | - Copyright 2019 Manos Pitsidianakis |
671 | - |
672 | - This file is part of meli. |
673 | - |
674 | - meli is free software: you can redistribute it and/or modify |
675 | - it under the terms of the GNU General Public License as published by |
676 | - the Free Software Foundation, either version 3 of the License, or |
677 | - (at your option) any later version. |
678 | - |
679 | - meli is distributed in the hope that it will be useful, |
680 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
681 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
682 | - GNU General Public License for more details. |
683 | - |
684 | - You should have received a copy of the GNU General Public License |
685 | - along with meli. If not, see <http://www.gnu.org/licenses/>. |
686 | - """ |
687 | - |
688 | - import sys |
689 | - import subprocess |
690 | - print(sys.path, file=sys.stderr) |
691 | - from libmeliapi import Client |
692 | - |
693 | - if __name__ == "__main__": |
694 | - server_address = './soworkfile' |
695 | - client = Client(server_address) |
696 | - client.connect() |
697 | - try: |
698 | - _bytes = client.read() |
699 | - print('got bytes {!r}'.format(_bytes),file=sys.stderr, ) |
700 | - |
701 | - # run() returns a CompletedProcess object if it was successful |
702 | - # errors in the created process are raised here too |
703 | - process = subprocess.run(['tiv','-w', '120','-h', '40', _bytes[0]], check=True, stdout=subprocess.PIPE, universal_newlines=True) |
704 | - output = process.stdout |
705 | - print('tiv output len {}'.format(len(output)),file=sys.stderr, ) |
706 | - #print('tiv output bytes {!r}'.format(output),file=sys.stderr, ) |
707 | - |
708 | - message = { "t": "ansi", "c": output } |
709 | - #print('sending {!r}'.format(message),file=sys.stderr, ) |
710 | - print('returned :', client.send(message), file=sys.stderr,) |
711 | - except Exception as msg: |
712 | - print(msg, file=sys.stderr,) |
713 | - |
714 | diff --git a/meli/src/plugins/python3/libmeliapi.py b/meli/src/plugins/python3/libmeliapi.py |
715 | deleted file mode 100644 |
716 | index 6475f79..0000000 |
717 | --- a/meli/src/plugins/python3/libmeliapi.py |
718 | +++ /dev/null |
719 | @@ -1,179 +0,0 @@ |
720 | - """ |
721 | - meli - python3 api plugin |
722 | - |
723 | - Copyright 2019 Manos Pitsidianakis |
724 | - |
725 | - This file is part of meli. |
726 | - |
727 | - meli is free software: you can redistribute it and/or modify |
728 | - it under the terms of the GNU General Public License as published by |
729 | - the Free Software Foundation, either version 3 of the License, or |
730 | - (at your option) any later version. |
731 | - |
732 | - meli is distributed in the hope that it will be useful, |
733 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
734 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
735 | - GNU General Public License for more details. |
736 | - |
737 | - You should have received a copy of the GNU General Public License |
738 | - along with meli. If not, see <http://www.gnu.org/licenses/>. |
739 | - """ |
740 | - |
741 | - from collections import deque |
742 | - import errno |
743 | - import json |
744 | - import msgpack |
745 | - import socket |
746 | - import struct |
747 | - import sys |
748 | - import time |
749 | - |
750 | - class IPCError(Exception): |
751 | - pass |
752 | - |
753 | - class UnknownMessageClass(IPCError): |
754 | - pass |
755 | - |
756 | - class InvalidSerialization(IPCError): |
757 | - pass |
758 | - |
759 | - class ConnectionClosed(IPCError): |
760 | - pass |
761 | - |
762 | - |
763 | - def _read_objects(sock): |
764 | - unpacker = msgpack.Unpacker() |
765 | - ret = [] |
766 | - #reader = socket.socket.makefile(sock, 'rb') |
767 | - while True: |
768 | - try: |
769 | - buf = sock.recv(1024**2) |
770 | - if not buf: |
771 | - break |
772 | - unpacker.feed(buf) |
773 | - for o in unpacker: |
774 | - ret.append(o) |
775 | - except: |
776 | - break |
777 | - return ret |
778 | - |
779 | - #try: |
780 | - # for unpack in unpacker: |
781 | - # return unpack |
782 | - #except Exception as e: |
783 | - # print("[libmeliapi]: ", "_read_objects error ", e, file=sys.stderr,) |
784 | - # return None |
785 | - #finally: |
786 | - # reader.flush() |
787 | - |
788 | - def _write_objects(sock, objects): |
789 | - sys.stderr.flush() |
790 | - print("[libmeliapi]: ", "_write_objects ", objects, flush=True, file=sys.stderr, ) |
791 | - data = msgpack.packb(objects) |
792 | - #print("[libmeliapi]: ", "_write_objects data ", data, flush=True, file=sys.stderr, ) |
793 | - sent = 0 |
794 | - |
795 | - while sent < len(data): |
796 | - try: |
797 | - _len = min(len(data[sent:]), 2048) |
798 | - sent += sock.send(data[sent:sent+_len]) |
799 | - except IOError as e: |
800 | - print("[libmeliapi]: IOError: ", e, e.errno, flush=True, file=sys.stderr, ) |
801 | - sys.stderr.flush() |
802 | - if e.errno == errno.EWOULDBLOCK: |
803 | - break |
804 | - elif e.errno == errno.EAGAIN: |
805 | - time.sleep(0.001) |
806 | - continue |
807 | - else: |
808 | - raise |
809 | - |
810 | - class Client(object): |
811 | - def __init__(self, server_address): |
812 | - self.buffer = deque() |
813 | - self.addr = server_address |
814 | - address_family = socket.AF_UNIX |
815 | - self.sock = socket.socket(address_family, socket.SOCK_STREAM) |
816 | - self.sock.setblocking(0) |
817 | - |
818 | - def connect(self): |
819 | - try: |
820 | - self.sock.connect(self.addr) |
821 | - |
822 | - print("[libmeliapi]: ", "self.send({ \"version\": \"dev\" }) = ",self.send({ "version": "dev" }), flush=True, file=sys.stderr) |
823 | - self.expect_ack() |
824 | - self._session = self.read() |
825 | - self.ack() |
826 | - print("[libmeliapi]: ", "self.buffer =", self.buffer, flush=True, file=sys.stderr, ) |
827 | - print("[libmeliapi]: ", "connected, session id is", self._session, flush=True, file=sys.stderr) |
828 | - except socket.error as msg: |
829 | - print("[libmeliapi]: ", msg, flush=True, file=sys.stderr, ) |
830 | - sys.stderr.flush() |
831 | - sys.exit(1) |
832 | - |
833 | - def close(self): |
834 | - self.sock.close() |
835 | - |
836 | - def setblocking(self, new_val): |
837 | - self.sock.setblocking(new_val) |
838 | - |
839 | - def __enter__(self): |
840 | - self.connect() |
841 | - return self |
842 | - |
843 | - def __exit__(self, exc_type, exc_value, traceback): |
844 | - self.close() |
845 | - |
846 | - def send(self, objects): |
847 | - sys.stderr.flush() |
848 | - #print("[libmeliapi]: ", "stuck in send ", self.buffer, flush=True, file=sys.stderr, ) |
849 | - _write_objects(self.sock, objects) |
850 | - #print("[libmeliapi]: ", "unstuck wrote objs", flush=True, file=sys.stderr, ) |
851 | - #print("[libmeliapi]: ", "wrote object ", objects, file=sys.stderr) |
852 | - time.sleep(0.001) |
853 | - |
854 | - def ack(self): |
855 | - sys.stderr.flush() |
856 | - _write_objects(self.sock, 0x06) |
857 | - time.sleep(0.001) |
858 | - |
859 | - def expect_ack(self): |
860 | - #print("[libmeliapi]: expect_ack, ", self.buffer, flush=True, file=sys.stderr, ) |
861 | - while True: |
862 | - time.sleep(0.1) |
863 | - read_list = _read_objects(self.sock) |
864 | - self.buffer.extend(read_list) |
865 | - try: |
866 | - self.buffer.remove(0x6) |
867 | - #print("[libmeliapi]: got_ack, ", self.buffer, flush=True, file=sys.stderr, ) |
868 | - return |
869 | - except ValueError: |
870 | - pass |
871 | - |
872 | - def read(self): |
873 | - sys.stderr.flush() |
874 | - #print("[libmeliapi]: ", "stuck in read ", self.buffer, flush=True, file=sys.stderr, ) |
875 | - read_list = _read_objects(self.sock) |
876 | - time.sleep(0.01) |
877 | - self.buffer.extend(read_list) |
878 | - #print("[libmeliapi]: ", "unstuck read self.buffer =", self.buffer, flush=True, file=sys.stderr, ) |
879 | - if len(self.buffer) > 0: |
880 | - return self.buffer.popleft() |
881 | - else: |
882 | - return None |
883 | - |
884 | - @property |
885 | - def backend_fn_type(self): |
886 | - return 0 |
887 | - |
888 | - @property |
889 | - def backend_op_fn_type(self): |
890 | - return 1 |
891 | - |
892 | - def ok_send(self, objects): |
893 | - self.send({"t": "ok", "c": objects }) |
894 | - self.expect_ack() |
895 | - |
896 | - def err_send(self, objects): |
897 | - self.send({"t": "err", "c": objects }) |
898 | - self.expect_ack() |
899 | diff --git a/meli/src/plugins/python3/nntp-backend.py b/meli/src/plugins/python3/nntp-backend.py |
900 | deleted file mode 100755 |
901 | index e8a8c24..0000000 |
902 | --- a/meli/src/plugins/python3/nntp-backend.py |
903 | +++ /dev/null |
904 | @@ -1,119 +0,0 @@ |
905 | - #! /usr/bin/env python3 |
906 | - """ |
907 | - meli - sample plugin |
908 | - |
909 | - Copyright 2019 Manos Pitsidianakis |
910 | - |
911 | - This file is part of meli. |
912 | - |
913 | - meli is free software: you can redistribute it and/or modify |
914 | - it under the terms of the GNU General Public License as published by |
915 | - the Free Software Foundation, either version 3 of the License, or |
916 | - (at your option) any later version. |
917 | - |
918 | - meli is distributed in the hope that it will be useful, |
919 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
920 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
921 | - GNU General Public License for more details. |
922 | - |
923 | - You should have received a copy of the GNU General Public License |
924 | - along with meli. If not, see <http://www.gnu.org/licenses/>. |
925 | - """ |
926 | - |
927 | - import sys |
928 | - import time |
929 | - import subprocess |
930 | - import msgpack |
931 | - import nntplib |
932 | - import libmeliapi |
933 | - import itertools |
934 | - |
935 | - def chunks(iterable, n): |
936 | - while True: |
937 | - try: |
938 | - yield itertools.chain((next(iterable),), itertools.islice(iterable, n-1)) |
939 | - except: |
940 | - break |
941 | - |
942 | - class NNTPClient(libmeliapi.Client): |
943 | - def __init__(self, stream_address, server_address, newsgroup): |
944 | - super().__init__(stream_address) |
945 | - self.bytes_cache = {} |
946 | - self.conn = nntplib.NNTP(server_address) |
947 | - self.newsgroup = newsgroup |
948 | - def backend_req(self, req): |
949 | - print("[nntp-plugin]: backend_req = ", req, flush=True, file=sys.stderr) |
950 | - if req.data == b'is_online': |
951 | - self.ok_send(None) |
952 | - elif req.data == b'get': |
953 | - resp, count, first, last, name = self.conn.group(self.newsgroup) |
954 | - print('Group', name, 'has', count, 'articles, range', first, 'to', last, flush=True, file=sys.stderr) |
955 | - |
956 | - resp, overviews = self.conn.over((0, last)) |
957 | - for chunk in chunks(iter(reversed(overviews)), 100): |
958 | - ret = [] |
959 | - for id, over in chunk: |
960 | - #print(id, nntplib.decode_header(over['subject']), flush=True, file=sys.stderr) |
961 | - env = {} |
962 | - env["hash"] = id |
963 | - env["subject"] = nntplib.decode_header(over["subject"]) |
964 | - env["from"] = nntplib.decode_header(over["from"]) |
965 | - env["date"] = nntplib.decode_header(over["date"]) |
966 | - env["message_id"] = nntplib.decode_header(over["message-id"]) |
967 | - env["references"] = nntplib.decode_header(over["references"]) |
968 | - try: |
969 | - env["to"] = nntplib.decode_header(over["to"]) |
970 | - except KeyError: |
971 | - env["to"] = self.newsgroup |
972 | - ret.append(env) |
973 | - print("ret len = ", len(ret), flush=True,file=sys.stderr) |
974 | - self.ok_send(ret) |
975 | - self.ok_send(None) |
976 | - def backend_op_req(self, req): |
977 | - print("[nntp-plugin]: backend_op_req = ", req, flush=True, file=sys.stderr) |
978 | - if req.data == b'as_bytes': |
979 | - _hash = self.read() |
980 | - print("[nntp-plugin]: hash = ", _hash, flush=True, file=sys.stderr) |
981 | - self.ack() |
982 | - try: |
983 | - try: |
984 | - self.ok_send(self.bytes_cache[_hash]) |
985 | - except KeyError: |
986 | - resp, info = self.conn.article(_hash) |
987 | - #print(_id, " line0 = ", str(info.lines[0], 'utf-8', 'ignore')) |
988 | - elem = b'\n'.join(info.lines) |
989 | - self.bytes_cache[_hash] = str(elem, 'utf-8', 'ignore') |
990 | - self.ok_send(self.bytes_cache[_hash]) |
991 | - except Exception as e: |
992 | - self.err_send(str(e)) |
993 | - |
994 | - |
995 | - if __name__ == "__main__": |
996 | - import importlib |
997 | - importlib.reload(libmeliapi) |
998 | - stream_address = './soworkfile' |
999 | - server_address = 'news.gmane.org' |
1000 | - newsgroup = 'gmane.comp.python.committers' |
1001 | - client = NNTPClient(stream_address, server_address, newsgroup) |
1002 | - client.connect() |
1003 | - #client.setblocking(True) |
1004 | - try: |
1005 | - while True: |
1006 | - req = client.read() |
1007 | - if req is None: |
1008 | - time.sleep(0.15) |
1009 | - continue |
1010 | - #client.setblocking(True) |
1011 | - client.ack() |
1012 | - print("[nntp-plugin]: ", "req: ", req, flush=True, file=sys.stderr) |
1013 | - sys.stderr.flush() |
1014 | - if isinstance(req, msgpack.ExtType): |
1015 | - if req.code == client.backend_fn_type: |
1016 | - client.backend_req(req) |
1017 | - elif req.code == client.backend_op_fn_type: |
1018 | - client.backend_op_req(req) |
1019 | - print("[nntp-plugin]: ", req, flush=True, file=sys.stderr) |
1020 | - #client.setblocking(True) |
1021 | - time.sleep(0.15) |
1022 | - except: |
1023 | - raise RuntimeError("Something bad happened") |
1024 | diff --git a/meli/src/plugins/rpc.rs b/meli/src/plugins/rpc.rs |
1025 | deleted file mode 100644 |
1026 | index 88eaf06..0000000 |
1027 | --- a/meli/src/plugins/rpc.rs |
1028 | +++ /dev/null |
1029 | @@ -1,142 +0,0 @@ |
1030 | - /* |
1031 | - * meli - plugins |
1032 | - * |
1033 | - * Copyright 2019 Manos Pitsidianakis |
1034 | - * |
1035 | - * This file is part of meli. |
1036 | - * |
1037 | - * meli is free software: you can redistribute it and/or modify |
1038 | - * it under the terms of the GNU General Public License as published by |
1039 | - * the Free Software Foundation, either version 3 of the License, or |
1040 | - * (at your option) any later version. |
1041 | - * |
1042 | - * meli is distributed in the hope that it will be useful, |
1043 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1044 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1045 | - * GNU General Public License for more details. |
1046 | - * |
1047 | - * You should have received a copy of the GNU General Public License |
1048 | - * along with meli. If not, see <http://www.gnu.org/licenses/>. |
1049 | - */ |
1050 | - |
1051 | - use super::*; |
1052 | - |
1053 | - #[derive(Debug)] |
1054 | - pub struct RpcChannel { |
1055 | - stream: UnixStream, |
1056 | - session: Uuid, |
1057 | - } |
1058 | - |
1059 | - #[derive(Debug, Serialize, Deserialize)] |
1060 | - #[serde(rename_all = "snake_case")] |
1061 | - pub struct PluginGreeting { |
1062 | - version: String, |
1063 | - } |
1064 | - |
1065 | - impl RpcChannel { |
1066 | - pub fn new(stream: UnixStream, session: &Uuid) -> Result<RpcChannel> { |
1067 | - let mut ret = RpcChannel { |
1068 | - stream, |
1069 | - session: *session, |
1070 | - }; |
1071 | - let greeting: PluginGreeting = ret |
1072 | - .from_read() |
1073 | - .map_err(|err| Error::new(format!("Could not get correct plugin greeting: {}", err)))?; |
1074 | - debug!(&greeting); |
1075 | - //if greeting.version != "dev" { |
1076 | - // return Err("Plugin is not compatible with our API (dev)".into()); |
1077 | - //} |
1078 | - ret.write_ref(&rmpv::ValueRef::String(session.to_string().as_str().into()))?; |
1079 | - debug!(ret.expect_ack())?; |
1080 | - Ok(ret) |
1081 | - } |
1082 | - |
1083 | - pub fn expect_ack(&mut self) -> Result<()> { |
1084 | - debug!("expect_ack()"); |
1085 | - let ack: u32 = debug!(rmp_serde::decode::from_read(&mut self.stream)) |
1086 | - .map_err(|_| Error::new("Plugin did not return ACK."))?; |
1087 | - if 0x6 == ack { |
1088 | - Ok(()) |
1089 | - } else { |
1090 | - Err(Error::new("Plugin did not return ACK.")) |
1091 | - } |
1092 | - } |
1093 | - |
1094 | - pub fn ack(&mut self) -> Result<()> { |
1095 | - debug!("ack()"); |
1096 | - debug!(rmpv::encode::write_value_ref( |
1097 | - &mut self.stream, |
1098 | - &rmpv::ValueRef::Integer(0x6.into()) |
1099 | - )) |
1100 | - .map_err(|err| Error::new(err.to_string()))?; |
1101 | - let _ = self.stream.flush(); |
1102 | - Ok(()) |
1103 | - } |
1104 | - |
1105 | - pub fn write_ref(&mut self, value_ref: &rmpv::ValueRef) -> Result<()> { |
1106 | - debug!("write_ref() {:?}", value_ref); |
1107 | - debug!(rmpv::encode::write_value_ref(&mut self.stream, value_ref)) |
1108 | - .map_err(|err| Error::new(err.to_string()))?; |
1109 | - let _ = self.stream.flush(); |
1110 | - Ok(()) |
1111 | - } |
1112 | - |
1113 | - pub fn read(&mut self) -> Result<rmpv::Value> { |
1114 | - debug!("read()"); |
1115 | - let ret: RpcResult = debug!(rmp_serde::decode::from_read(&mut self.stream)) |
1116 | - .map_err(|err| Error::new(err.to_string()))?; |
1117 | - let _ = self.stream.flush(); |
1118 | - self.ack()?; |
1119 | - debug!("read() ret={:?}", &ret); |
1120 | - ret.into() |
1121 | - } |
1122 | - |
1123 | - pub fn from_read<T>(&mut self) -> Result<T> |
1124 | - where |
1125 | - T: std::fmt::Debug + serde::de::DeserializeOwned, |
1126 | - { |
1127 | - debug!("from_read()"); |
1128 | - let ret: Result<T> = debug!(rmp_serde::decode::from_read(&mut self.stream)) |
1129 | - .map_err(|err| Error::new(err.to_string())); |
1130 | - let _ = self.stream.flush(); |
1131 | - self.ack()?; |
1132 | - debug!("read() ret={:?}", &ret); |
1133 | - ret |
1134 | - } |
1135 | - } |
1136 | - |
1137 | - #[derive(Debug, Clone, Serialize, Deserialize)] |
1138 | - #[serde(rename_all = "snake_case")] |
1139 | - #[serde(tag = "t", content = "c")] |
1140 | - enum RpcResult { |
1141 | - Ok(rmpv::Value), |
1142 | - Err(String), |
1143 | - } |
1144 | - |
1145 | - impl RpcResult { |
1146 | - fn into(self) -> Result<rmpv::Value> { |
1147 | - match self { |
1148 | - RpcResult::Ok(v) => Ok(v), |
1149 | - RpcResult::Err(err) => Err(Error::new(err)), |
1150 | - } |
1151 | - } |
1152 | - } |
1153 | - |
1154 | - #[derive(Debug, Clone, Serialize, Deserialize)] |
1155 | - #[serde(rename_all = "snake_case")] |
1156 | - #[serde(tag = "t", content = "c")] |
1157 | - pub enum PluginResult<T: std::fmt::Debug + Clone> { |
1158 | - Ok(T), |
1159 | - Err(String), |
1160 | - } |
1161 | - |
1162 | - impl<T: std::fmt::Debug + Clone + serde::Serialize + serde::de::DeserializeOwned> Into<Result<T>> |
1163 | - for PluginResult<T> |
1164 | - { |
1165 | - fn into(self) -> Result<T> { |
1166 | - match self { |
1167 | - PluginResult::Ok(v) => Ok(v), |
1168 | - PluginResult::Err(err) => Err(Error::new(err)), |
1169 | - } |
1170 | - } |
1171 | - } |
1172 | diff --git a/meli/src/state.rs b/meli/src/state.rs |
1173 | index 2d228ce..817bee5 100644 |
1174 | --- a/meli/src/state.rs |
1175 | +++ b/meli/src/state.rs |
1176 | @@ -343,10 +343,8 @@ impl State { |
1177 | sender: Sender<ThreadEvent>, |
1178 | receiver: Receiver<ThreadEvent>, |
1179 | ) -> Result<Self> { |
1180 | - /* |
1181 | - * Create async channel to block the input-thread if we need to fork and stop |
1182 | - * it from reading stdin, see get_events() for details |
1183 | - */ |
1184 | + // Create async channel to block the input-thread if we need to fork and stop it |
1185 | + // from reading stdin, see get_events() for details |
1186 | let input_thread = unbounded(); |
1187 | let input_thread_pipe = crate::types::pipe()?; |
1188 | let backends = Backends::new(); |
1189 | @@ -355,20 +353,6 @@ impl State { |
1190 | } else { |
1191 | Settings::new()? |
1192 | }); |
1193 | - /* |
1194 | - let mut plugin_manager = PluginManager::new(); |
1195 | - for (_, p) in settings.plugins.clone() { |
1196 | - if crate::plugins::PluginKind::Backend == p.kind() { |
1197 | - debug!("registering {:?}", &p); |
1198 | - crate::plugins::backend::PluginBackend::register( |
1199 | - plugin_manager.listener(), |
1200 | - p.clone(), |
1201 | - &mut backends, |
1202 | - ); |
1203 | - } |
1204 | - plugin_manager.register(p)?; |
1205 | - } |
1206 | - */ |
1207 | |
1208 | let (cols, rows) = termion::terminal_size().chain_err_summary(|| { |
1209 | "Could not determine terminal size. Are you running this on a tty? If yes, do you need \ |