use std::sync::Arc;
use remowt_link_shared::editor::{EditorBackend, Error};
use russh::client::Handle;
use tokio::net::UnixListener;
use tracing::error;
use crate::SshHandler;
pub struct SshEditor {
pub sess: Arc<Handle<SshHandler>>,
}
impl EditorBackend for SshEditor {
async fn open_editor(&self, socket_path: String) -> Result<(), Error> {
let local = std::env::temp_dir().join(format!("remowt-nvim-{}.sock", uuid::Uuid::new_v4()));
let _ = std::fs::remove_file(&local);
let listener = UnixListener::bind(&local).map_err(|e| Error::Failed(e.to_string()))?;
let sess = self.sess.clone();
let forward = tokio::spawn(async move {
loop {
let Ok((mut stream, _)) = listener.accept().await else {
break;
};
let sess = sess.clone();
let remote = socket_path.clone();
tokio::spawn(async move {
match sess.channel_open_direct_streamlocal(remote).await {
Ok(ch) => {
let mut remote = ch.into_stream();
let _ = tokio::io::copy_bidirectional(&mut stream, &mut remote).await;
}
Err(e) => error!("opening direct-streamlocal to nvim failed: {e}"),
}
});
}
});
let status = tokio::process::Command::new("neovide")
.arg("--no-fork")
.arg("--server")
.arg(&local)
.status()
.await
.map_err(|e| Error::Failed(format!("spawning neovide: {e}")));
forward.abort();
let _ = std::fs::remove_file(&local);
match status? {
s if s.success() => Ok(()),
s => Err(Error::Failed(format!("neovide exited with {s}"))),
}
}
}