Skip to content

Commit

Permalink
Merge pull request #3 from boxofrox/feature/unix-sockets
Browse files Browse the repository at this point in the history
Feature/unix sockets
  • Loading branch information
daa84 authored Mar 13, 2017
2 parents 485b45a + 21d0adc commit d7af4a4
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 0 deletions.
36 changes: 36 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ travis-ci = { repository = "https://github.com/daa84/neovim-lib", branch = "mast
[dependencies]
rmp = "0.8"
log = "0.3"

[target.'cfg(unix)'.dependencies]
unix_socket = "0.5.0"

[dev-dependencies]
tempdir = "0.3"
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ extern crate rmp;
#[macro_use]
extern crate log;

#[cfg(unix)]
extern crate unix_socket;

mod rpc;
#[macro_use]
pub mod session;
Expand Down
31 changes: 31 additions & 0 deletions src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ use std::process::{Command, Child, ChildStdin, ChildStdout};
use std::thread::JoinHandle;
use std::time::Duration;

#[cfg(unix)]
use std::path::Path;
#[cfg(unix)]
use unix_socket::UnixStream;

use rpc::value::Value;

use rpc::Client;
Expand Down Expand Up @@ -39,6 +44,17 @@ impl Session {
})
}

#[cfg(unix)]
/// Connect to nvim instance via unix socket
pub fn new_unix_socket<P: AsRef<Path>>(path: P) -> Result<Session> {
let stream = UnixStream::connect(path)?;
let read = stream.try_clone()?;
Ok(Session {
client: ClientConnection::UnixSocket(Client::new(stream, read)),
timeout: Some(Duration::new(5, 0)),
})
}

/// Connect to a Neovim instance by spawning a new one.
pub fn new_child() -> Result<Session> {
if cfg!(target_os = "linux") || cfg!(target_os = "freebsd") {
Expand Down Expand Up @@ -81,6 +97,9 @@ impl Session {
match self.client {
ClientConnection::Child(ref mut client, _) => client.start_event_loop_cb(cb),
ClientConnection::Tcp(ref mut client) => client.start_event_loop_cb(cb),

#[cfg(unix)]
ClientConnection::UnixSocket(ref mut client) => client.start_event_loop_cb(cb),
}
}

Expand All @@ -89,6 +108,9 @@ impl Session {
match self.client {
ClientConnection::Child(ref mut client, _) => client.start_event_loop(),
ClientConnection::Tcp(ref mut client) => client.start_event_loop(),

#[cfg(unix)]
ClientConnection::UnixSocket(ref mut client) => client.start_event_loop(),
}
}

Expand All @@ -97,6 +119,9 @@ impl Session {
match self.client {
ClientConnection::Child(ref mut client, _) => client.call(method, args, self.timeout),
ClientConnection::Tcp(ref mut client) => client.call(method, args, self.timeout),

#[cfg(unix)]
ClientConnection::UnixSocket(ref mut client) => client.call(method, args, self.timeout),
}
}

Expand All @@ -107,11 +132,17 @@ impl Session {
match self.client {
ClientConnection::Child(ref mut client, _) => client.take_dispatch_guard(),
ClientConnection::Tcp(ref mut client) => client.take_dispatch_guard(),

#[cfg(unix)]
ClientConnection::UnixSocket(ref mut client) => client.take_dispatch_guard(),
}
}
}

enum ClientConnection {
Child(Client<ChildStdout, ChildStdin>, Child),
Tcp(Client<TcpStream, TcpStream>),

#[cfg(unix)]
UnixSocket(Client<UnixStream, UnixStream>),
}
69 changes: 69 additions & 0 deletions tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
extern crate neovim_lib;
extern crate rmp;
extern crate tempdir;

use neovim_lib::session::Session;
use neovim_lib::neovim::Neovim;
use neovim_lib::neovim_api::NeovimApi;
use neovim_lib::Value;

use std::process::Command;
use tempdir::TempDir;

#[ignore]
#[test]
Expand Down Expand Up @@ -41,3 +46,67 @@ fn edit_test() {
let windows = nvim.get_windows().unwrap();
windows[0].set_width(&mut nvim, 10).unwrap();
}

#[cfg(unix)]
#[ignore]
#[test]
fn can_connect_via_unix_socket() {
use std::path::Path;
use std::thread::sleep;
use std::time::{Duration, Instant};

let dir = TempDir::new("neovim-lib.test").expect("Cannot create temporary directory for test.");

let socket_path = dir.path().join("unix_socket");

let _child = Command::new("nvim")
.arg("--embed")
.env("NVIM_LISTEN_ADDRESS", &socket_path)
.spawn()
.expect("Cannot start neovim");

// wait at least 1 second for neovim to start and create socket path.
{
let start = Instant::now();
let one_second = Duration::from_secs(1);
loop {
sleep(Duration::from_millis(100));

if let Ok(_) = std::fs::metadata(&socket_path) {
break;
}

if one_second <= start.elapsed() {
panic!(format!("neovim socket not found at '{:?}'", &socket_path));
}
}
}


let mut session = Session::new_unix_socket(&socket_path)
.expect(&format!("Unable to connect to neovim's unix socket at {:?}",
&socket_path));

session.start_event_loop();

let mut nvim = Neovim::new(session);

let servername = nvim.get_vvar("servername")
.expect("Error retrieving servername from neovim over unix socket");

// let's make sure the servername string and socket path string both match.
match servername {
Value::String(ref name) => {
if Path::new(name) != socket_path {
panic!(format!("Server name does not match socket path! {} != {}",
name,
socket_path.to_str().unwrap()));
}
}
_ => {
panic!(format!("Server name does not match socket path! {:?} != {}",
servername,
socket_path.to_str().unwrap()))
}
}
}

0 comments on commit d7af4a4

Please sign in to comment.