mirror of https://github.com/sgoudham/neovide.git
Remote TCP (#557)
* Remote TCP proof of concept * Allow usage of both tcp and child connections using `TxWrapper` * Tidy up and add flag to set tcp target * Add readme section * Remove the need for `Compat<TxWrapper>` as we are wrapping it anywaymacos-click-through
parent
799e043ffd
commit
d8d6f4eac2
@ -0,0 +1,65 @@
|
|||||||
|
//! This module contains adaptations of the functions found in
|
||||||
|
//! https://github.com/KillTheMule/nvim-rs/blob/master/src/create/tokio.rs
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
io::{self, Error, ErrorKind},
|
||||||
|
process::Stdio,
|
||||||
|
};
|
||||||
|
|
||||||
|
use tokio::{
|
||||||
|
io::split,
|
||||||
|
net::{TcpStream, ToSocketAddrs},
|
||||||
|
process::Command,
|
||||||
|
spawn,
|
||||||
|
task::JoinHandle,
|
||||||
|
};
|
||||||
|
|
||||||
|
use nvim_rs::compat::tokio::TokioAsyncReadCompatExt;
|
||||||
|
use nvim_rs::{error::LoopError, neovim::Neovim, Handler};
|
||||||
|
|
||||||
|
use crate::bridge::{TxWrapper, WrapTx};
|
||||||
|
|
||||||
|
/// Connect to a neovim instance via tcp
|
||||||
|
pub async fn new_tcp<A, H>(
|
||||||
|
addr: A,
|
||||||
|
handler: H,
|
||||||
|
) -> io::Result<(Neovim<TxWrapper>, JoinHandle<Result<(), Box<LoopError>>>)>
|
||||||
|
where
|
||||||
|
A: ToSocketAddrs,
|
||||||
|
H: Handler<Writer = TxWrapper>,
|
||||||
|
{
|
||||||
|
let stream = TcpStream::connect(addr).await?;
|
||||||
|
let (reader, writer) = split(stream);
|
||||||
|
let (neovim, io) = Neovim::<TxWrapper>::new(reader.compat_read(), writer.wrap_tx(), handler);
|
||||||
|
let io_handle = spawn(io);
|
||||||
|
|
||||||
|
Ok((neovim, io_handle))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect to a neovim instance by spawning a new one
|
||||||
|
///
|
||||||
|
/// stdin/stdout will be rewritten to `Stdio::piped()`
|
||||||
|
pub async fn new_child_cmd<H>(
|
||||||
|
cmd: &mut Command,
|
||||||
|
handler: H,
|
||||||
|
) -> io::Result<(Neovim<TxWrapper>, JoinHandle<Result<(), Box<LoopError>>>)>
|
||||||
|
where
|
||||||
|
H: Handler<Writer = TxWrapper>,
|
||||||
|
{
|
||||||
|
let mut child = cmd.stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
|
||||||
|
let stdout = child
|
||||||
|
.stdout
|
||||||
|
.take()
|
||||||
|
.ok_or_else(|| Error::new(ErrorKind::Other, "Can't open stdout"))?
|
||||||
|
.compat_read();
|
||||||
|
let stdin = child
|
||||||
|
.stdin
|
||||||
|
.take()
|
||||||
|
.ok_or_else(|| Error::new(ErrorKind::Other, "Can't open stdin"))?
|
||||||
|
.wrap_tx();
|
||||||
|
|
||||||
|
let (neovim, io) = Neovim::<TxWrapper>::new(stdout, stdin, handler);
|
||||||
|
let io_handle = spawn(io);
|
||||||
|
|
||||||
|
Ok((neovim, io_handle))
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
use pin_project::pin_project;
|
||||||
|
use std::io;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
use tokio::{
|
||||||
|
io::{AsyncWrite, WriteHalf},
|
||||||
|
net::TcpStream,
|
||||||
|
process::ChildStdin,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[pin_project(project = TxProj)]
|
||||||
|
pub enum TxWrapper {
|
||||||
|
Child(#[pin] ChildStdin),
|
||||||
|
Tcp(#[pin] WriteHalf<TcpStream>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl futures::io::AsyncWrite for TxWrapper {
|
||||||
|
fn poll_write(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Poll<Result<usize, io::Error>> {
|
||||||
|
match self.project() {
|
||||||
|
TxProj::Child(inner) => inner.poll_write(cx, buf),
|
||||||
|
TxProj::Tcp(inner) => inner.poll_write(cx, buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||||
|
match self.project() {
|
||||||
|
TxProj::Child(inner) => inner.poll_flush(cx),
|
||||||
|
TxProj::Tcp(inner) => inner.poll_flush(cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||||
|
match self.project() {
|
||||||
|
TxProj::Child(inner) => inner.poll_shutdown(cx),
|
||||||
|
TxProj::Tcp(inner) => inner.poll_shutdown(cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WrapTx {
|
||||||
|
fn wrap_tx(self) -> TxWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WrapTx for ChildStdin {
|
||||||
|
fn wrap_tx(self) -> TxWrapper {
|
||||||
|
TxWrapper::Child(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WrapTx for WriteHalf<TcpStream> {
|
||||||
|
fn wrap_tx(self) -> TxWrapper {
|
||||||
|
TxWrapper::Tcp(self)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue