fix: catch some edge cases

This commit is contained in:
əlemi 2023-04-11 17:12:22 +02:00
parent de153c798c
commit 228f6a54f0
3 changed files with 59 additions and 22 deletions

View file

@ -21,18 +21,23 @@ M.attach = function(path)
{ {
callback = function() callback = function()
local cursor = vim.api.nvim_win_get_cursor(0) local cursor = vim.api.nvim_win_get_cursor(0)
M.insert(path, vim.v.char, cursor[2]) local off = vim.fn.line2byte(cursor[1]) + cursor[2] - 1
M.insert(path, vim.v.char, off)
end, end,
} }
) )
vim.keymap.set('i', '<BS>', function() vim.keymap.set('i', '<BS>', function()
local cursor = vim.api.nvim_win_get_cursor(0) local cursor = vim.api.nvim_win_get_cursor(0)
M.delete(path, cursor[2], 1) local off = vim.fn.line2byte(cursor[1]) + cursor[2] - 1
if off > 0 then
M.delete(path, off, 1)
end
return '<BS>' return '<BS>'
end, {expr = true}) end, {expr = true})
vim.keymap.set('i', '<CR>', function() vim.keymap.set('i', '<CR>', function()
local cursor = vim.api.nvim_win_get_cursor(0) local cursor = vim.api.nvim_win_get_cursor(0)
M.insert(path, "\n", cursor[2]) local off = vim.fn.line2byte(cursor[1]) + cursor[2] - 1
M.insert(path, "\n", off)
return '<CR>' return '<CR>'
end, {expr = true}) end, {expr = true})
return vim.rpcrequest(vim.g.codemp_jobid, "attach", path) return vim.rpcrequest(vim.g.codemp_jobid, "attach", path)

View file

@ -1,3 +1,5 @@
use std::{net::TcpStream, sync::Mutex};
use codemp::client::CodempClient; use codemp::client::CodempClient;
use codemp::proto::buffer_client::BufferClient; use codemp::proto::buffer_client::BufferClient;
use rmpv::Value; use rmpv::Value;
@ -19,6 +21,18 @@ fn nullable_optional_str(args: &Vec<Value>, index: usize) -> Option<String> {
Some(args.get(index)?.as_str()?.to_string()) Some(args.get(index)?.as_str()?.to_string())
} }
fn default_empty_str(args: &Vec<Value>, index: usize) -> String {
nullable_optional_str(args, index).unwrap_or("".into())
}
fn nullable_optional_number(args: &Vec<Value>, index: usize) -> Option<u64> {
Some(args.get(index)?.as_u64()?)
}
fn default_zero_number(args: &Vec<Value>, index: usize) -> u64 {
nullable_optional_number(args, index).unwrap_or(0)
}
#[async_trait] #[async_trait]
impl Handler for NeovimHandler { impl Handler for NeovimHandler {
type Writer = Compat<Stdout>; type Writer = Compat<Stdout>;
@ -29,6 +43,7 @@ impl Handler for NeovimHandler {
args: Vec<Value>, args: Vec<Value>,
nvim: Neovim<Compat<Stdout>>, nvim: Neovim<Compat<Stdout>>,
) -> Result<Value, Value> { ) -> Result<Value, Value> {
debug!("processing '{}' - {:?}", name, args);
match name.as_ref() { match name.as_ref() {
"ping" => Ok(Value::from("pong")), "ping" => Ok(Value::from("pong")),
@ -38,7 +53,7 @@ impl Handler for NeovimHandler {
if args.len() < 1 { if args.len() < 1 {
return Err(Value::from("no path given")); return Err(Value::from("no path given"));
} }
let path = args.get(0).unwrap().as_str().unwrap().into(); let path = default_empty_str(&args, 0);
let content = nullable_optional_str(&args, 1); let content = nullable_optional_str(&args, 1);
let mut c = self.client.clone(); let mut c = self.client.clone();
match c.create(path, content).await { match c.create(path, content).await {
@ -54,9 +69,9 @@ impl Handler for NeovimHandler {
if args.len() < 3 { if args.len() < 3 {
return Err(Value::from("not enough arguments")); return Err(Value::from("not enough arguments"));
} }
let path = args.get(0).unwrap().as_str().unwrap().into(); let path = default_empty_str(&args, 0);
let txt = args.get(1).unwrap().as_str().unwrap().into(); let txt = default_empty_str(&args, 1);
let pos = args.get(2).unwrap().as_u64().unwrap(); let pos = default_zero_number(&args, 2);
let mut c = self.client.clone(); let mut c = self.client.clone();
match c.insert(path, txt, pos).await { match c.insert(path, txt, pos).await {
@ -72,9 +87,9 @@ impl Handler for NeovimHandler {
if args.len() < 3 { if args.len() < 3 {
return Err(Value::from("not enough arguments")); return Err(Value::from("not enough arguments"));
} }
let path = args.get(0).unwrap().as_str().unwrap().into(); let path = default_empty_str(&args, 0);
let pos = args.get(1).unwrap().as_u64().unwrap(); let pos = default_zero_number(&args, 1);
let count = args.get(2).unwrap().as_u64().unwrap(); let count = default_zero_number(&args, 2);
let mut c = self.client.clone(); let mut c = self.client.clone();
match c.delete(path, pos, count).await { match c.delete(path, pos, count).await {
@ -90,8 +105,12 @@ impl Handler for NeovimHandler {
if args.len() < 1 { if args.len() < 1 {
return Err(Value::from("no path given")); return Err(Value::from("no path given"));
} }
let path = args.get(0).unwrap().as_str().unwrap().into(); let path = default_empty_str(&args, 0);
let buf = nvim.get_current_buf().await.unwrap(); let buf = match nvim.get_current_buf().await {
Ok(b) => b,
Err(e) => return Err(Value::from(format!("could not get current buffer: {}", e))),
};
let mut c = self.client.clone(); let mut c = self.client.clone();
match c.attach(path, move |x| { match c.attach(path, move |x| {
@ -138,13 +157,22 @@ struct CliArgs {
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = CliArgs::parse(); let args = CliArgs::parse();
tracing_subscriber::fmt() let sub = tracing_subscriber::fmt()
.compact() .compact()
.without_time() .without_time()
.with_ansi(false) .with_ansi(false);
.with_writer(std::io::stderr) match TcpStream::connect("127.0.0.1:6969") {
.with_max_level(if args.debug { tracing::Level::DEBUG } else { tracing::Level::INFO }) Ok(stream) => {
.init(); sub.with_writer(Mutex::new(stream))
.with_max_level(if args.debug { tracing::Level::DEBUG } else { tracing::Level::INFO })
.init();
},
Err(_) => {
sub.with_writer(std::io::stderr)
.with_max_level(if args.debug { tracing::Level::DEBUG } else { tracing::Level::INFO })
.init();
},
}
let client = BufferClient::connect(args.host).await?; let client = BufferClient::connect(args.host).await?;
debug!("client connected"); debug!("client connected");

View file

@ -111,11 +111,15 @@ impl CodempClient {
match stream.message().await { match stream.message().await {
Ok(v) => match v { Ok(v) => match v {
Some(operation) => { Some(operation) => {
let op = serde_json::from_str(&operation.opseq).unwrap(); match serde_json::from_str(&operation.opseq) {
let res = { factory.lock().unwrap().process(op) }; Ok(op) => {
match res { let res = { factory.lock().unwrap().process(op) };
Ok(x) => callback(x), match res {
Err(e) => break error!("desynched: {}", e), Ok(x) => callback(x),
Err(e) => break error!("desynched: {}", e),
}
},
Err(e) => break error!("could not deserialize opseq: {}", e),
} }
} }
None => break warn!("stream closed"), None => break warn!("stream closed"),