lux_lib/progress/
client.rs1use std::io::{BufWriter, Write};
2use std::net::TcpStream;
3use std::sync::{Arc, Mutex, RwLock};
4use std::{io, num};
5
6use miette::Diagnostic;
7use serde::{Deserialize, Serialize};
8use thiserror::Error;
9
10use crate::workspace::Workspace;
11
12pub(crate) static CLIENT: RwLock<Option<Arc<LspClient>>> = RwLock::new(None);
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub enum ProgressMessage {
16 Begin { id: i32, title: String },
17 Report { id: i32, message: String },
18 End { id: i32 },
19}
20
21pub(crate) struct LspClient {
22 writer: Mutex<BufWriter<TcpStream>>,
23}
24
25impl LspClient {
26 pub(crate) fn connect(workspace: &Workspace) -> Result<Self, ConnectError> {
27 let port_path = super::lsp_port_path(workspace);
28
29 let port: u16 = std::fs::read_to_string(&port_path)
30 .map_err(ConnectError::ReadPort)?
31 .trim()
32 .parse()
33 .map_err(ConnectError::ParsePort)?;
34 let stream = TcpStream::connect(("127.0.0.1", port))
35 .map_err(|source| ConnectError::Connect { port, source })?;
36
37 Ok(Self {
38 writer: Mutex::new(BufWriter::new(stream)),
39 })
40 }
41
42 pub(crate) fn send(&self, msg: &ProgressMessage) {
43 if let Ok(mut w) = self.writer.lock() {
44 let _ = serde_json::to_writer(&mut *w, msg);
45 let _ = writeln!(w);
46 let _ = w.flush();
47 }
48 }
49}
50
51#[derive(Debug, Diagnostic, Error)]
52pub(crate) enum ConnectError {
53 #[error("failed to read LSP port file")]
54 ReadPort(#[from] io::Error),
55 #[error("invalid port in LSP port file")]
56 ParsePort(#[from] num::ParseIntError),
57 #[error("failed to connect to lx-lsp at 127.0.0.1:{port}")]
58 Connect {
59 port: u16,
60 #[source]
61 source: io::Error,
62 },
63}