From 670d9d16e081f9b898526a148e34caf897619ecc Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Mon, 4 Dec 2023 15:35:49 +0900 Subject: [PATCH] feat(lsp): handle CLI args for different communication channels Implement handling of the common CLI arguments that define how to establish the client/server communication channel. The options are defined, but not all are supported as of yet. --- Cargo.lock | 1 + Cargo.toml | 1 + crates/stef-cli/Cargo.toml | 2 +- crates/stef-go/Cargo.toml | 2 +- crates/stef-lsp/Cargo.toml | 1 + crates/stef-lsp/src/cli.rs | 46 +++++++++++++++++++++++++++++++++++++ crates/stef-lsp/src/main.rs | 22 ++++++++++++++++-- 7 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 crates/stef-lsp/src/cli.rs diff --git a/Cargo.lock b/Cargo.lock index e278dcc..087cd73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1172,6 +1172,7 @@ dependencies = [ name = "stef-lsp" version = "0.1.0" dependencies = [ + "clap", "directories", "ouroboros", "stef-compiler", diff --git a/Cargo.toml b/Cargo.toml index ff07db4..3dab899 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ all = "deny" pedantic = "warn" [workspace.dependencies] +clap = { version = "4.4.10", features = ["derive", "wrap_help"] } color-eyre = { version = "0.6.2", default-features = false } glob = "0.3.1" indoc = "2.0.4" diff --git a/crates/stef-cli/Cargo.toml b/crates/stef-cli/Cargo.toml index 7ef3a30..503de4b 100644 --- a/crates/stef-cli/Cargo.toml +++ b/crates/stef-cli/Cargo.toml @@ -14,7 +14,7 @@ name = "stef" path = "src/main.rs" [dependencies] -clap = { version = "4.4.10", features = ["derive", "wrap_help"] } +clap.workspace = true color-eyre.workspace = true glob.workspace = true miette = { workspace = true, features = ["fancy-no-backtrace"] } diff --git a/crates/stef-go/Cargo.toml b/crates/stef-go/Cargo.toml index 2587bc7..4d7e18e 100644 --- a/crates/stef-go/Cargo.toml +++ b/crates/stef-go/Cargo.toml @@ -10,7 +10,7 @@ repository.workspace = true license.workspace = true [dependencies] -clap = { version = "4.4.10", features = ["derive"] } +clap.workspace = true heck = "0.4.1" miette = { workspace = true, features = ["fancy-no-backtrace"] } stef-compiler = { path = "../stef-compiler" } diff --git a/crates/stef-lsp/Cargo.toml b/crates/stef-lsp/Cargo.toml index ea0109b..a679ce3 100644 --- a/crates/stef-lsp/Cargo.toml +++ b/crates/stef-lsp/Cargo.toml @@ -10,6 +10,7 @@ repository.workspace = true license.workspace = true [dependencies] +clap.workspace = true directories = "5.0.1" ouroboros = "0.18.0" stef-compiler = { path = "../stef-compiler" } diff --git a/crates/stef-lsp/src/cli.rs b/crates/stef-lsp/src/cli.rs new file mode 100644 index 0000000..46c561a --- /dev/null +++ b/crates/stef-lsp/src/cli.rs @@ -0,0 +1,46 @@ +use std::path::PathBuf; + +use clap::{Parser, ValueHint}; + +#[derive(Parser)] +#[command(about, author, version)] +pub struct Cli { + /// Use standard I/O as the communication channel. + #[arg(long, conflicts_with_all = ["pipe", "socket"])] + pub stdio: bool, + /// Use pipes (Windows) or socket files (Linux, Mac) as the communication channel. + #[arg( + long, + conflicts_with_all = ["socket"], + value_name = "FILE", + value_hint = ValueHint::FilePath, + )] + pub pipe: Option, + /// Use a socket as the communication channel. + #[arg(long, exclusive = true, value_name = "PORT")] + pub socket: Option, + /// Process ID of the editor that started this server. + /// + /// To support the case that the editor starting a server crashes an editor should also pass + /// its process id to the server. This allows the server to monitor the editor process and to + /// shutdown itself if the editor process dies. + #[arg(long = "clientProcessId", value_name = "ID")] + pub client_process_id: Option, +} + +impl Cli { + pub fn parse() -> Self { + ::parse() + } +} + +#[cfg(test)] +mod tests { + use super::Cli; + + #[test] + fn verify_cli() { + use clap::CommandFactory; + Cli::command().debug_assert(); + } +} diff --git a/crates/stef-lsp/src/main.rs b/crates/stef-lsp/src/main.rs index da38c2d..f813be8 100644 --- a/crates/stef-lsp/src/main.rs +++ b/crates/stef-lsp/src/main.rs @@ -19,6 +19,9 @@ use tower_lsp::{ use tracing::{debug, Level}; use tracing_subscriber::{filter::Targets, fmt::MakeWriter, prelude::*}; +use self::cli::Cli; + +mod cli; mod compile; mod utf16; @@ -120,6 +123,8 @@ impl LanguageServer for Backend { #[tokio::main] async fn main() { + let cli = Cli::parse(); + let dirs = ProjectDirs::from("rocks", "dnaka91", env!("CARGO_PKG_NAME")).unwrap(); let file_appender = tracing_appender::rolling::daily(dirs.cache_dir(), "log"); @@ -147,8 +152,21 @@ async fn main() { } }); - let (stdin, stdout) = (tokio::io::stdin(), tokio::io::stdout()); - Server::new(stdin, stdout, socket).serve(service).await; + if cli.stdio { + let (stdin, stdout) = (tokio::io::stdin(), tokio::io::stdout()); + Server::new(stdin, stdout, socket).serve(service).await; + } else if let Some(file) = cli.pipe { + let file = tokio::fs::File::options() + .read(true) + .write(true) + .open(file) + .await + .expect("failed to open provided pipe/socket"); + let (read, write) = tokio::io::split(file); + Server::new(read, write, socket).serve(service).await; + } else if let Some(port) = cli.socket { + unimplemented!("open TCP connection on port {port}"); + } } struct ClientLogWriter {