Skip to content

feat: Add include-path CLI parameter with clap #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 122 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "protols"
description = "Language server for proto3 files"
version = "0.11.2"
version = "0.11.5"
edition = "2024"
license = "MIT"
homepage = "https://github.com/coder3101/protols"
Expand All @@ -28,6 +28,7 @@ tempfile = "3.12.0"
serde = { version = "1.0.209", features = ["derive"] }
basic-toml = "0.1.9"
pkg-config = "0.3.31"
clap = { version = "4.5.5", features = ["derive"] }

[dev-dependencies]
insta = { version = "1.39.0", features = ["yaml"] }
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

- [Installation](#installation)
- [For Neovim](#for-neovim)
- [Command Line Options](#command-line-options)
- [For Visual Studio Code](#for-visual-studio-code)
- [Configuration](#configuration)
- [Basic Configuration](#basic-configuration)
Expand Down Expand Up @@ -57,6 +58,25 @@ Then, configure it in your `init.lua` using [nvim-lspconfig](https://github.com/
require'lspconfig'.protols.setup{}
```

### Command Line Options

Protols supports various command line options to customize its behavior:

```
protols [OPTIONS]

Options:
-i, --include-paths <INCLUDE_PATHS> Include paths for proto files, comma-separated
-V, --version Print version information
-h, --help Print help information
```

For example, to specify include paths when starting the language server:

```bash
protols --include-paths=/path/to/protos,/another/path/to/protos
```

### For Visual Studio Code

If you're using Visual Studio Code, you can install the [Protobuf Language Support](https://marketplace.visualstudio.com/items?itemName=ianandhum.protobuf-support) extension, which uses this LSP under the hood.
Expand Down Expand Up @@ -86,7 +106,7 @@ protoc = "protoc"

The `[config]` section contains stable settings that should generally remain unchanged.

- `include_paths`: Directories to search for `.proto` files. Absolute or relative to LSP workspace root. Worspace root is already included in include_paths
- `include_paths`: These are directories where `.proto` files are searched. Paths can be absolute or relative to the LSP workspace root, which is already included in the `include_paths`. You can also specify this using the `--include-paths` flag in the command line. The include paths from the CLI are combined with those from the configuration. While configuration-based include paths are specific to a workspace, the CLI-specified paths apply to all workspaces on the server.

#### Path Configuration

Expand Down
52 changes: 48 additions & 4 deletions src/config/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ pub struct WorkspaceProtoConfigs {
configs: HashMap<Url, ProtolsConfig>,
formatters: HashMap<Url, ClangFormatter>,
protoc_include_prefix: Vec<PathBuf>,
cli_include_paths: Vec<PathBuf>,
}

impl WorkspaceProtoConfigs {
pub fn new() -> Self {
pub fn new(cli_include_paths: Vec<PathBuf>) -> Self {
// Try to find protobuf library and get its include paths
// Do not emit metadata on stdout as LSP programs can consider
// it part of spec
Expand All @@ -38,6 +39,7 @@ impl WorkspaceProtoConfigs {
formatters: HashMap::new(),
configs: HashMap::new(),
protoc_include_prefix,
cli_include_paths,
}
}

Expand Down Expand Up @@ -100,6 +102,15 @@ impl WorkspaceProtoConfigs {
.map(|p| if p.is_relative() { w.join(p) } else { p })
.collect();

// Add CLI include paths
for path in &self.cli_include_paths {
if path.is_relative() {
ipath.push(w.join(path));
} else {
ipath.push(path.clone());
}
}

ipath.push(w.to_path_buf());
ipath.extend_from_slice(&self.protoc_include_prefix);
Some(ipath)
Expand Down Expand Up @@ -139,6 +150,7 @@ mod test {
use async_lsp::lsp_types::{Url, WorkspaceFolder};
use insta::assert_yaml_snapshot;
use tempfile::tempdir;
use std::path::PathBuf;

use super::{CONFIG_FILE_NAMES, WorkspaceProtoConfigs};

Expand All @@ -149,7 +161,7 @@ mod test {
let f = tmpdir.path().join("protols.toml");
std::fs::write(f, include_str!("input/protols-valid.toml")).unwrap();

let mut ws = WorkspaceProtoConfigs::new();
let mut ws = WorkspaceProtoConfigs::new(vec![]);
ws.add_workspace(&WorkspaceFolder {
uri: Url::from_directory_path(tmpdir.path()).unwrap(),
name: "Test".to_string(),
Expand Down Expand Up @@ -183,7 +195,7 @@ mod test {
let f = tmpdir.path().join("protols.toml");
std::fs::write(f, include_str!("input/protols-valid.toml")).unwrap();

let mut ws = WorkspaceProtoConfigs::new();
let mut ws = WorkspaceProtoConfigs::new(vec![]);
ws.add_workspace(&WorkspaceFolder {
uri: Url::from_directory_path(tmpdir.path()).unwrap(),
name: "Test".to_string(),
Expand Down Expand Up @@ -218,7 +230,7 @@ mod test {
let f = tmpdir.path().join(file);
std::fs::write(f, include_str!("input/protols-valid.toml")).unwrap();

let mut ws = WorkspaceProtoConfigs::new();
let mut ws = WorkspaceProtoConfigs::new(vec![]);
ws.add_workspace(&WorkspaceFolder {
uri: Url::from_directory_path(tmpdir.path()).unwrap(),
name: "Test".to_string(),
Expand All @@ -229,4 +241,36 @@ mod test {
assert!(ws.get_workspace_for_uri(&workspace).is_some());
}
}

#[test]
fn test_cli_include_paths() {
let tmpdir = tempdir().expect("failed to create temp directory");
let f = tmpdir.path().join("protols.toml");
std::fs::write(f, include_str!("input/protols-valid.toml")).unwrap();

// Set CLI include paths
let cli_paths = vec![
PathBuf::from("/path/to/protos"),
PathBuf::from("relative/path"),
];
let mut ws = WorkspaceProtoConfigs::new(cli_paths);
ws.add_workspace(&WorkspaceFolder {
uri: Url::from_directory_path(tmpdir.path()).unwrap(),
name: "Test".to_string(),
});

let inworkspace = Url::from_file_path(tmpdir.path().join("foobar.proto")).unwrap();
let include_paths = ws.get_include_paths(&inworkspace).unwrap();

// Check that CLI paths are included in the result
assert!(include_paths.iter().any(|p| p.ends_with("relative/path") ||
p == &PathBuf::from("/path/to/protos")));

// The relative path should be resolved relative to the workspace
let resolved_relative_path = tmpdir.path().join("relative/path");
assert!(include_paths.contains(&resolved_relative_path));

// The absolute path should be included as is
assert!(include_paths.contains(&PathBuf::from("/path/to/protos")));
}
}
Loading