From 2195cb28b82e1ebe3f8fa100347ee66d6802841d Mon Sep 17 00:00:00 2001 From: alemidev Date: Sat, 16 Jul 2022 03:45:32 +0200 Subject: [PATCH] feat: implemented basic create/sync client --- src/client/manager.rs | 72 -------------------------------- src/client/nvim/mod.rs | 93 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 90 deletions(-) delete mode 100644 src/client/manager.rs diff --git a/src/client/manager.rs b/src/client/manager.rs deleted file mode 100644 index 28e74f5..0000000 --- a/src/client/manager.rs +++ /dev/null @@ -1,72 +0,0 @@ -pub mod proto_core { - tonic::include_proto!("session"); -} - -use tonic::transport::Channel; - -use proto_core::workspace_client::WorkspaceClient; -use proto_core::SessionRequest; - -use tokio::sync::{mpsc, oneshot}; - -use self::proto_core::SessionResponse; - -#[derive(Debug)] -pub enum Command { - CreateSession { - key: String, - resp: oneshot::Sender, - }, - JoinSession { - key: String, - resp: oneshot::Sender, - }, -} - -impl Command { - pub fn create_session_cmd(key: String) -> (Command, oneshot::Receiver) { - let (resp, x) = oneshot::channel(); - ( Command::CreateSession { key, resp }, x ) - } -} - -#[derive(Debug)] -pub struct ConnectionManager { - client: WorkspaceClient, - rx: mpsc::Receiver -} - - -impl ConnectionManager { - pub async fn new(addr:String, outbound:mpsc::Receiver) -> Result> { - Ok(ConnectionManager { - client: WorkspaceClient::connect(addr).await?, - rx: outbound - }) - } - - pub async fn process_packets(&mut self) { - { - let request = tonic::Request::new(SessionRequest { - session_id: -1, - session_key: "INIT".to_string(), - }); - let response = self.client.create(request).await.unwrap(); - eprintln!("RESPONSE={:?}", response); - } - loop { - if let Some(cmd) = self.rx.recv().await { - match cmd { - Command::CreateSession { key, resp } => { - let request = tonic::Request::new(SessionRequest {session_id: 1, session_key: key}); - let response = self.client.create(request).await.unwrap(); - resp.send(response.into_inner()).unwrap(); - }, - _ => eprintln!("[!] Received unexpected command") - } - } else { - break - } - } - } -} diff --git a/src/client/nvim/mod.rs b/src/client/nvim/mod.rs index f55851e..b94684c 100644 --- a/src/client/nvim/mod.rs +++ b/src/client/nvim/mod.rs @@ -1,20 +1,21 @@ use rmpv::Value; use tokio::io::Stdout; -use tokio::sync::mpsc; use nvim_rs::{compat::tokio::Compat, Handler, Neovim}; +use nvim_rs::create::tokio::new_parent; +use tonic::transport::Channel; -use crate::manager::Command; +use crate::proto::{SessionRequest, workspace_client::WorkspaceClient}; #[derive(Clone)] pub struct NeovimHandler { - tx: mpsc::Sender, + client: WorkspaceClient, } impl NeovimHandler { - pub async fn new(tx: mpsc::Sender) -> Result { - Ok(NeovimHandler { tx }) + pub fn new(client: WorkspaceClient) -> Self { + NeovimHandler { client } } } @@ -25,23 +26,65 @@ impl Handler for NeovimHandler { async fn handle_request( &self, name: String, - _args: Vec, - _neovim: Neovim>, + args: Vec, + neovim: Neovim>, ) -> Result { match name.as_ref() { "ping" => Ok(Value::from("pong")), - "rpc" => { - let (cmd, rx) = Command::create_session_cmd("asd".to_string()); - self.tx.send(cmd).await.unwrap(); - let resp = rx.await.unwrap(); - Ok(Value::from(format!("{:?}", resp))) + "create" => { + if args.len() < 1 { + return Err(Value::from("[!] no session key")); + } + let buf = neovim.get_current_buf().await.unwrap(); + let content = buf.get_lines(0, buf.line_count().await.unwrap(), false).await.unwrap().join("\n"); + let request = tonic::Request::new(SessionRequest { + session_key: args[0].to_string(), content: Some(content), + }); + let mut c = self.client.clone(); + let resp = c.create(request).await.unwrap().into_inner(); + if resp.accepted { + Ok(Value::from(resp.session_key)) + } else { + Err(Value::from("[!] rejected")) + } + }, + "sync" => { + if args.len() < 1 { + return Err(Value::from("[!] no session key")); + } + let buf = neovim.get_current_buf().await.unwrap(); + let request = tonic::Request::new(SessionRequest { + session_key: args[0].to_string(), content: None, + }); + let mut c = self.client.clone(); + let resp = c.sync(request).await.unwrap().into_inner(); + if let Some(content) = resp.content { + buf.set_lines( + 0, + buf.line_count().await.unwrap(), + false, + content.split("\n").map(|s| s.to_string()).collect() + ).await.unwrap(); + Ok(Value::from("")) + } else { + Err(Value::from("[!] no content")) + } + }, + "leave" => { + if args.len() < 1 { + return Err(Value::from("[!] no session key")); + } + let request = tonic::Request::new(SessionRequest { + session_key: args[0].to_string(), content: None, + }); + let mut c = self.client.clone(); + let resp = c.leave(request).await.unwrap().into_inner(); + if resp.accepted { + Ok(Value::from(format!("closed session #{}", resp.session_key))) + } else { + Err(Value::from("[!] could not close session")) + } }, - "buffer" => { - let buf = _neovim.create_buf(true, false).await.unwrap(); - buf.set_lines(0, 1, false, vec!["codeMP".to_string()]).await.unwrap(); - _neovim.set_current_buf(&buf).await.unwrap(); - Ok(Value::from("ok")) - } _ => { eprintln!("[!] unexpected call"); Ok(Value::from("")) @@ -62,3 +105,17 @@ impl Handler for NeovimHandler { } } } + +pub async fn run_nvim_client(c: WorkspaceClient) -> Result<(), Box> { + let handler: NeovimHandler = NeovimHandler::new(c); + let (_nvim, io_handler) = new_parent(handler).await; + + // Any error should probably be logged, as stderr is not visible to users. + match io_handler.await { + Err(err) => eprintln!("Error joining IO loop: {:?}", err), + Ok(Err(err)) => eprintln!("Process ended with error: {:?}", err), + Ok(Ok(())) => eprintln!("Finished"), + } + + Ok(()) +}