1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use rmpv::Value;
use std::net::TcpStream;
#[cfg(unix)]
use std::os::unix::net::UnixStream;
use crate::{
client::{Client, Connection},
error::Error,
handler::{NotificationHandler, RequestHandler},
};
/// The current Neovim session
///
/// Used to send and receive messages to the Neovim session
pub struct Session {
client: Connection,
}
impl Session {
/// Create a session using a TCP socket
///
/// This allows RPC communication with a Neovim instance started with
/// ```shell
/// nvim --listen 127.0.0.1:6666
/// ```
/// The current Neovim server can be found using
/// ```shell
/// :echo v:servername
/// ```
///
/// # Example
///
/// ```no_run
/// use rsnvim::session::Session;
///
/// let mut session = match Session::from_tcp("127.0.0.1:6666") {
/// Ok(session) => session,
/// Err(error) => panic!("Couldn't open TCP socket: {}", error)
/// };
/// ```
pub fn from_tcp(addr: &str) -> Result<Session, Error> {
let reader = TcpStream::connect(addr)?;
let writer = reader.try_clone()?;
let client = Client::new(reader, writer);
Ok(Session {
client: Connection::TCP(client),
})
}
/// Create a Neovim connection using stdin/stdout
///
/// This allows RPC communication with the Neovim instance that spawned
/// this process.
///
/// # Example
///
/// ```no_run
/// use rsnvim::api::Nvim;
///
/// let mut nvim = match Nvim::from_parent() {
/// Ok(nvim) => nvim,
/// Err(error) => panic!("Couldn't connect to parent session: {}", error)
/// };
/// ```
pub fn from_parent() -> Result<Session, Error> {
let client = Client::new(std::io::stdin(), std::io::stdout());
Ok(Session {
client: Connection::STDIO(client)
})
}
/// Create a session using a Unix socket
///
/// This allows RPC communication with any Neovim instance as it
/// creates a default RPC socket on startup.
///
/// The current Neovim server can be found using
/// ```shell
/// :echo v:servername
/// ```
///
/// # Example
///
/// ```no_run
/// use rsnvim::session::Session;
///
/// let mut session = match Session::from_unix("/run/user/1000/nvim.XXXXX.X") {
/// Ok(session) => session,
/// Err(error) => panic!("Couldn't open UNIX socket: {}", error)
/// };
/// ```
#[cfg(unix)]
pub fn from_unix(path: &str) -> Result<Session, Error> {
let reader = UnixStream::connect(path)?;
let writer = reader.try_clone()?;
let client = Client::new(reader, writer);
Ok(Session {
client: Connection::UNIX(client),
})
}
/// Begin the RPC event loop
///
/// This function must be called before RPC messages can be sent as it
/// handles the return values, though it is also exposed though the `Nvim`
/// struct.
///
/// This function allows for up to two custom handlers:
///
/// # request_handler
/// The `request_handler` struct must implement the `RequestHandler` trait
/// which then allows it to process incoming RPC requests from Neovim. If
/// `None` is passed the `DefaultHandler` will be used which responds with
/// a `NotImplemented` error.
///
/// # notification_handler
/// The `notification_handler` struct must implement the 'NotificationHandler'
/// trait which then allows it to process incoming RPC notifications from Neovim.
/// If 'None' is passed the `DefaultHandler` will be used which ignores all
/// RPC notifications.
pub fn start_event_loop(
&mut self,
request_handler: Option<Box<dyn RequestHandler + Send>>,
notification_handler: Option<Box<dyn NotificationHandler + Send>>,
) {
match self.client {
Connection::TCP(ref mut client) => {
client.start_event_loop(request_handler, notification_handler)
}
Connection::STDIO(ref mut client) => {
client.start_event_loop(request_handler, notification_handler)
}
#[cfg(unix)]
Connection::UNIX(ref mut client) => {
client.start_event_loop(request_handler, notification_handler)
}
}
}
/// Call a RPC function
///
/// This function allows for arbitrary Neovim function calls
pub fn call(&mut self, method: &str, args: Vec<Value>) -> Result<Value, Error> {
match self.client {
Connection::TCP(ref mut client) => Ok(client.call(method, args)?),
Connection::STDIO(ref mut client) => Ok(client.call(method, args)?),
#[cfg(unix)]
Connection::UNIX(ref mut client) => Ok(client.call(method, args)?),
}
}
}