blues-lsp 0.1.0

LSP language server for the Bluespec SystemVerilog language
Documentation
use blues_lsp::{
    cli::{self, Cli, ServerArgs},
    lsp::server::Server,
    util::data::either::Either,
};
use clap::Parser;
use lsp_server::Connection;
use tracing::info;
use tracing_subscriber::EnvFilter;

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

fn main() -> Result<()> {
    let cli = Cli::parse();

    match cli.command {
        cli::Command::Server(args) => do_server(args),
    }
}

fn do_server(args: ServerArgs) -> Result<()> {
    if let Some(output) = args.log {
        let filter = match args.verbosity {
            0 => EnvFilter::new("none"),
            1 => EnvFilter::new("error"),
            2 => EnvFilter::new("warn"),
            3 => EnvFilter::new("info"),
            4 => EnvFilter::new("debug,lsp_server=info"),
            5 => EnvFilter::new("trace,lsp_server=info"),
            6.. => EnvFilter::from_default_env(),
        };

        match output {
            cli::LogOutput::Stdout => tracing_subscriber::fmt()
                .with_env_filter(filter)
                .with_writer(std::io::stdout)
                .init(),
            cli::LogOutput::Stderr => tracing_subscriber::fmt()
                .with_env_filter(filter)
                .with_writer(std::io::stderr)
                .with_ansi(args.listen.is_some())
                .init(),
        };
    }

    let (connection, io_threads) = if let Some(sock) = args.listen {
        info!("Listenning for LSP client on tcp/{sock} ...");
        let (connection, io_threads) = Connection::listen("127.0.0.1:5000")?;
        info!("Accepted TCP connection");
        (connection, io_threads)
    } else {
        info!("Listenning for LSP client on stdio ...");
        Connection::stdio()
    };

    let mut server = match Server::initialize(&connection) {
        Ok(server) => server,
        Err(Either::Left(e)) => {
            if e.channel_is_disconnected() {
                io_threads.join()?;
            }
            return Err(e.into());
        }
        Err(Either::Right(e)) => {
            return Err(e.into());
        }
    };

    let _ = server.run(&connection);

    info!("Shutting down server ...");

    io_threads.join()?;

    Ok(())
}