diff options
Diffstat (limited to 'support/texlab/src/main.rs')
-rw-r--r-- | support/texlab/src/main.rs | 112 |
1 files changed, 70 insertions, 42 deletions
diff --git a/support/texlab/src/main.rs b/support/texlab/src/main.rs index 40209e5095..16c5be8f26 100644 --- a/support/texlab/src/main.rs +++ b/support/texlab/src/main.rs @@ -1,56 +1,49 @@ -use clap::{app_from_crate, crate_authors, crate_description, crate_name, crate_version, Arg}; -use futures::channel::mpsc; -use futures::prelude::*; +use futures::{channel::mpsc, prelude::*}; use jsonrpc::MessageHandler; -use std::error::Error; -use std::io::Write; -use std::sync::Arc; -use stderrlog::{ColorChoice, Timestamp}; -use texlab::client::LatexLspClient; -use texlab::codec::LspCodec; -use texlab::server::LatexLspServer; -use tokio::codec::{FramedRead, FramedWrite}; +use log::LevelFilter; +use std::path::PathBuf; +use std::{env, error, fs::OpenOptions, sync::Arc}; +use structopt::StructOpt; +use texlab::{ + protocol::{LatexLspClient, LspCodec}, + server::LatexLspServer, + tex::Distribution, +}; +use tokio_util::codec::{FramedRead, FramedWrite}; -#[tokio::main] -async fn main() -> Result<(), Box<dyn Error>> { - let matches = app_from_crate!() - .author("") - .arg( - Arg::with_name("verbosity") - .short("v") - .multiple(true) - .help("Increase message verbosity"), - ) - .arg( - Arg::with_name("quiet") - .long("quiet") - .short("q") - .help("No output printed to stderr"), - ) - .get_matches(); +/// An implementation of the Language Server Protocol for LaTeX +#[derive(Debug, StructOpt)] +struct Opts { + /// Increase message verbosity (-vvvv for max verbosity) + #[structopt(short, long, parse(from_occurrences))] + verbosity: u8, + + /// No output printed to stderr + #[structopt(short, long)] + quiet: bool, - stderrlog::new() - .module(module_path!()) - .module("jsonrpc") - .verbosity(matches.occurrences_of("verbosity") as usize) - .quiet(matches.is_present("quiet")) - .timestamp(Timestamp::Off) - .color(ColorChoice::Never) - .init() - .unwrap(); + /// Write the logging output to FILE + #[structopt(long, name = "FILE", parse(from_os_str))] + log_file: Option<PathBuf>, +} - let stdin = FramedRead::new(tokio::io::stdin(), LspCodec); +#[tokio::main] +async fn main() -> Result<(), Box<dyn error::Error>> { + let opts = Opts::from_args(); + setup_logger(opts); + + let mut stdin = FramedRead::new(tokio::io::stdin(), LspCodec); let (stdout_tx, mut stdout_rx) = mpsc::channel(0); let client = Arc::new(LatexLspClient::new(stdout_tx.clone())); let server = Arc::new(LatexLspServer::new( - Arc::new(tex::Distribution::detect().await), + Distribution::detect().await, Arc::clone(&client), + Arc::new(env::current_dir().expect("failed to get working directory")), )); let mut handler = MessageHandler { server, client, - input: stdin, output: stdout_tx, }; @@ -59,10 +52,45 @@ async fn main() -> Result<(), Box<dyn Error>> { loop { let message = stdout_rx.next().await.unwrap(); stdout.send(message).await.unwrap(); - std::io::stdout().flush().unwrap(); // Workaround for tokio-rs/tokio#1527 } }); - handler.listen().await; + while let Some(json) = stdin.next().await { + handler.handle(&json.unwrap()).await; + } + Ok(()) } + +fn setup_logger(opts: Opts) { + let verbosity_level = if !opts.quiet { + match opts.verbosity { + 0 => LevelFilter::Error, + 1 => LevelFilter::Warn, + 2 => LevelFilter::Info, + 3 => LevelFilter::Debug, + _ => LevelFilter::Trace, + } + } else { + LevelFilter::Off + }; + + let logger = fern::Dispatch::new() + .format(|out, message, record| out.finish(format_args!("{} - {}", record.level(), message))) + .level(verbosity_level) + .filter(|metadata| metadata.target() == "jsonrpc" || metadata.target().contains("texlab")) + .chain(std::io::stderr()); + + let logger = match opts.log_file { + Some(log_file) => logger.chain( + OpenOptions::new() + .write(true) + .create(true) + .open(log_file) + .expect("failed to open log file"), + ), + None => logger, + }; + + logger.apply().expect("failed to initialize logger"); +} |