Skip to main content

lux_lib/progress/
client.rs

1use 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}