Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/edi/lsp_mn/stdio.rs')
-rw-r--r--src/edi/lsp_mn/stdio.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/edi/lsp_mn/stdio.rs b/src/edi/lsp_mn/stdio.rs
new file mode 100644
index 0000000..fa5a480
--- /dev/null
+++ b/src/edi/lsp_mn/stdio.rs
@@ -0,0 +1,75 @@
+use std::io::{self, Read, Stdin, Stdout, Write, stdin, stdout};
+use std::thread;
+
+use crossbeam_channel::{Receiver, Sender, bounded, unbounded};
+use log::trace;
+use lsp_server::{Connection, Message};
+/// Creates an LSP connection via stdio.
+pub fn transport(
+ mut read_from: impl Read + std::io::BufRead + Sync + Send + 'static,
+ mut write_to: impl Write + Sync + Send + 'static,
+) -> (Connection, IoThreads) {
+ let (writer_sender, writer_receiver) = unbounded::<Message>();
+ let writer = thread::Builder::new()
+ .name("send to lsp".to_owned())
+ .spawn(move || {
+ loop {
+ let it = writer_receiver.recv().unwrap();
+ trace!("sent message {it:#?}");
+ let result = it.write(&mut write_to).unwrap();
+ result
+ }
+ })
+ .unwrap();
+ let (reader_sender, reader_receiver) = bounded::<Message>(0);
+ let reader: thread::JoinHandle<Result<(), io::Error>> = thread::Builder::new()
+ .name("read from lsp".to_owned())
+ .spawn(move || {
+ while let Some(msg) = Message::read(&mut read_from)? {
+ let is_exit = matches!(&msg, Message::Notification(n) if n.method == "exit");
+ trace!("received message {msg:#?}");
+ if let Err(e) = reader_sender.send(msg) {
+ return Err(io::Error::other(e));
+ }
+
+ if is_exit {
+ break;
+ }
+ }
+ Ok(())
+ })
+ .unwrap();
+ let threads = IoThreads { reader, writer };
+ (
+ Connection { sender: writer_sender, receiver: reader_receiver },
+ threads,
+ )
+}
+
+// Creates an IoThreads
+pub(crate) fn make_io_threads(
+ reader: thread::JoinHandle<io::Result<()>>,
+ writer: thread::JoinHandle<io::Result<()>>,
+) -> IoThreads {
+ IoThreads { reader, writer }
+}
+
+pub struct IoThreads {
+ pub reader: thread::JoinHandle<io::Result<()>>,
+ pub writer: thread::JoinHandle<io::Result<()>>,
+}
+
+impl IoThreads {
+ pub fn join(self) -> io::Result<()> {
+ match self.reader.join() {
+ Ok(r) => r?,
+ Err(err) => std::panic::panic_any(err),
+ }
+ match self.writer.join() {
+ Ok(r) => r,
+ Err(err) => {
+ std::panic::panic_any(err);
+ }
+ }
+ }
+}