Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit 30d87d8

Browse files
author
Hendrik van Antwerpen
committed
Reorganize CLI code
1 parent 28e48f8 commit 30d87d8

File tree

7 files changed

+173
-101
lines changed

7 files changed

+173
-101
lines changed

languages/tree-sitter-stack-graphs-typescript/rust/bin.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@
55
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
66
// ------------------------------------------------------------------------------------------------
77

8-
use tree_sitter_stack_graphs::cli::LanguageConfigurationsCli as Cli;
8+
use clap::Parser;
9+
use tree_sitter_stack_graphs::cli::provided_languages::Subcommands;
910
use tree_sitter_stack_graphs::NoCancellation;
1011

1112
fn main() -> anyhow::Result<()> {
12-
Cli::main(vec![
13+
let cli = Cli::parse();
14+
cli.subcommand.run(vec![
1315
tree_sitter_stack_graphs_typescript::language_configuration(&NoCancellation),
1416
])
1517
}
18+
19+
#[derive(Parser)]
20+
#[clap(about, version)]
21+
pub struct Cli {
22+
#[clap(subcommand)]
23+
subcommand: Subcommands,
24+
}

languages/tree-sitter-stack-graphs-typescript/rust/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
// ------------------------------------------------------------------------------------------------
77

88
use std::path::PathBuf;
9-
use tree_sitter_stack_graphs::cli::CiTester;
9+
use tree_sitter_stack_graphs::ci::Tester;
1010
use tree_sitter_stack_graphs::NoCancellation;
1111

1212
fn main() -> anyhow::Result<()> {
1313
let test_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test");
14-
CiTester::new(
14+
Tester::new(
1515
vec![tree_sitter_stack_graphs_typescript::language_configuration(
1616
&NoCancellation,
1717
)],

tree-sitter-stack-graphs/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## Unreleased
9+
10+
### Library
11+
12+
#### Changed
13+
14+
- The `cli` module has been reorganized. Instead of providing a fully derived CLI type, the subcommands are now exposed, while deriving the CLI type is left to the user. This makes sure that the name and version reported by the version command are ones from the user crate, and not from this crate. Instead of using `cli::LanguageConfigurationsCli` and `cli::PathLoadingCli`, users should using from `cli::provided_languages::Subcommands` and `cli::path_loading::Subcommands` repsectively. The `cli` module documentation shows complete examples of how to do this.
15+
- The `cli::CiTester` type has been moved to `ci::Tester`. Because it uses `cli` code internally, it is still hidden behind the `cli` feature flag.
16+
817
## v0.5.1 -- 2023-01-10
918

1019
Patch release to update *all* version numbers.

tree-sitter-stack-graphs/src/bin/tree-sitter-stack-graphs/main.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,17 @@
55
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
66
// ------------------------------------------------------------------------------------------------
77

8-
use anyhow::Result;
9-
use tree_sitter_stack_graphs::cli::PathLoadingCli;
8+
use clap::Parser;
9+
use tree_sitter_stack_graphs::cli::path_loading::Subcommands;
1010

11-
fn main() -> Result<()> {
12-
PathLoadingCli::main()
11+
#[derive(Parser)]
12+
#[clap(about, version)]
13+
pub struct Cli {
14+
#[clap(subcommand)]
15+
subcommand: Subcommands,
16+
}
17+
18+
fn main() -> anyhow::Result<()> {
19+
let cli = Cli::parse();
20+
cli.subcommand.run()
1321
}

tree-sitter-stack-graphs/src/ci.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// -*- coding: utf-8 -*-
2+
// ------------------------------------------------------------------------------------------------
3+
// Copyright © 2022, stack-graphs authors.
4+
// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
5+
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
6+
// ------------------------------------------------------------------------------------------------
7+
8+
//! This crate defines a reusable CI test runner.
9+
//!
10+
//! Use the test runner as follows:
11+
//!
12+
//! ``` no_run
13+
//! use std::path::PathBuf;
14+
//! use tree_sitter_stack_graphs::ci::Tester;
15+
//! use tree_sitter_stack_graphs::NoCancellation;
16+
//!
17+
//! fn main() -> anyhow::Result<()> {
18+
//! let language_configurations = vec![/* add your language configurations here */];
19+
//! let test_paths = vec![PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test")];
20+
//! Tester::new(
21+
//! language_configurations,
22+
//! test_paths,
23+
//! )
24+
//! .run()
25+
//! }
26+
//! ```
27+
28+
use std::path::PathBuf;
29+
30+
use crate::cli::test::TestArgs;
31+
use crate::loader::{LanguageConfiguration, Loader};
32+
33+
/// Run tests for the given languages. Test locations are reported relative to the current directory, which
34+
/// results in better readable output when build tools only provides absolute test paths.
35+
pub struct Tester {
36+
configurations: Vec<LanguageConfiguration>,
37+
test_paths: Vec<PathBuf>,
38+
}
39+
40+
impl Tester {
41+
pub fn new(configurations: Vec<LanguageConfiguration>, test_paths: Vec<PathBuf>) -> Self {
42+
Self {
43+
configurations,
44+
test_paths,
45+
}
46+
}
47+
48+
pub fn run(self) -> anyhow::Result<()> {
49+
let test_paths = self
50+
.test_paths
51+
.into_iter()
52+
.map(|test_path| {
53+
std::env::current_dir()
54+
.ok()
55+
.and_then(|cwd| pathdiff::diff_paths(&test_path, &cwd))
56+
.unwrap_or(test_path)
57+
})
58+
.collect::<Vec<_>>();
59+
for test_path in &test_paths {
60+
if !test_path.exists() {
61+
panic!("Test path {} does not exist", test_path.display());
62+
}
63+
}
64+
let mut loader = Loader::from_language_configurations(self.configurations, None)
65+
.expect("Expected loader");
66+
TestArgs::new(test_paths).run(&mut loader)
67+
}
68+
}

tree-sitter-stack-graphs/src/cli.rs

Lines changed: 69 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,53 @@
55
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
66
// ------------------------------------------------------------------------------------------------
77

8-
//! Defines CLI
8+
//! This crate defines reusable subcommands for clap-based CLI implementations.
9+
//!
10+
//! ## Path loading CLIs
11+
//!
12+
//! Path loading CLIs load language configurations from the file system, based on
13+
//! tree-sitter configuration files and provided arguments. Derive a path loading
14+
//! CLI from as follows:
15+
//!
16+
//! ``` no_run
17+
//! use clap::Parser;
18+
//! use tree_sitter_stack_graphs::cli::path_loading::Subcommands;
19+
//!
20+
//! #[derive(Parser)]
21+
//! #[clap(about, version)]
22+
//! pub struct Cli {
23+
//! #[clap(subcommand)]
24+
//! subcommand: Subcommands,
25+
//! }
26+
//!
27+
//! fn main() -> anyhow::Result<()> {
28+
//! let cli = Cli::parse();
29+
//! cli.subcommand.run()
30+
//! }
31+
//! ```
32+
//!
33+
//! ## Provided langauges CLIs
34+
//!
35+
//! Provided languages CLIs use directly provided language configuration instances.
36+
//! Derive a language configuration CLI as follows:
37+
//!
38+
//! ``` no_run
39+
//! use clap::Parser;
40+
//! use tree_sitter_stack_graphs::cli::provided_languages::Subcommands;
41+
//!
42+
//! #[derive(Parser)]
43+
//! #[clap(about, version)]
44+
//! pub struct Cli {
45+
//! #[clap(subcommand)]
46+
//! subcommand: Subcommands,
47+
//! }
48+
//!
49+
//! fn main() -> anyhow::Result<()> {
50+
//! let language_configurations = vec![/* add your language configurations here */];
51+
//! let cli = Cli::parse();
52+
//! cli.subcommand.run(language_configurations)
53+
//! }
54+
//! ```
955
1056
pub(self) const MAX_PARSE_ERRORS: usize = 5;
1157

@@ -15,46 +61,31 @@ pub mod parse;
1561
pub mod test;
1662
mod util;
1763

18-
pub use ci::Tester as CiTester;
19-
pub use path_loading::Cli as PathLoadingCli;
20-
pub use provided_languages::Cli as LanguageConfigurationsCli;
21-
22-
mod path_loading {
23-
use anyhow::Result;
24-
use clap::Parser;
64+
pub mod path_loading {
2565
use clap::Subcommand;
2666

2767
use crate::cli::init::InitArgs;
2868
use crate::cli::load::PathLoaderArgs;
2969
use crate::cli::parse::ParseArgs;
3070
use crate::cli::test::TestArgs;
3171

32-
/// CLI implementation that loads grammars and stack graph definitions from paths.
33-
#[derive(Parser)]
34-
#[clap(about, version)]
35-
pub struct Cli {
36-
#[clap(subcommand)]
37-
command: Commands,
38-
}
39-
40-
impl Cli {
41-
pub fn main() -> Result<()> {
42-
let cli = Cli::parse();
43-
match &cli.command {
44-
Commands::Init(cmd) => cmd.run(),
45-
Commands::Parse(cmd) => cmd.run(),
46-
Commands::Test(cmd) => cmd.run(),
47-
}
48-
}
49-
}
50-
5172
#[derive(Subcommand)]
52-
enum Commands {
73+
pub enum Subcommands {
5374
Init(Init),
5475
Parse(Parse),
5576
Test(Test),
5677
}
5778

79+
impl Subcommands {
80+
pub fn run(&self) -> anyhow::Result<()> {
81+
match self {
82+
Self::Init(cmd) => cmd.run(),
83+
Self::Parse(cmd) => cmd.run(),
84+
Self::Test(cmd) => cmd.run(),
85+
}
86+
}
87+
}
88+
5889
/// Init command
5990
#[derive(clap::Parser)]
6091
pub struct Init {
@@ -101,9 +132,7 @@ mod path_loading {
101132
}
102133
}
103134

104-
mod provided_languages {
105-
use anyhow::Result;
106-
use clap::Parser;
135+
pub mod provided_languages {
107136
use clap::Subcommand;
108137

109138
use crate::cli::parse::ParseArgs;
@@ -112,30 +141,21 @@ mod provided_languages {
112141

113142
use super::load::LanguageConfigurationsLoaderArgs;
114143

115-
/// CLI implementation that loads from provided grammars and stack graph definitions.
116-
#[derive(Parser)]
117-
#[clap(about, version)]
118-
pub struct Cli {
119-
#[clap(subcommand)]
120-
command: Commands,
144+
#[derive(Subcommand)]
145+
pub enum Subcommands {
146+
Parse(Parse),
147+
Test(Test),
121148
}
122149

123-
impl Cli {
124-
pub fn main(configurations: Vec<LanguageConfiguration>) -> Result<()> {
125-
let cli = Cli::parse();
126-
match &cli.command {
127-
Commands::Parse(cmd) => cmd.run(configurations),
128-
Commands::Test(cmd) => cmd.run(configurations),
150+
impl Subcommands {
151+
pub fn run(&self, configurations: Vec<LanguageConfiguration>) -> anyhow::Result<()> {
152+
match self {
153+
Self::Parse(cmd) => cmd.run(configurations),
154+
Self::Test(cmd) => cmd.run(configurations),
129155
}
130156
}
131157
}
132158

133-
#[derive(Subcommand)]
134-
enum Commands {
135-
Parse(Parse),
136-
Test(Test),
137-
}
138-
139159
/// Parse command
140160
#[derive(clap::Parser)]
141161
pub struct Parse {
@@ -168,47 +188,3 @@ mod provided_languages {
168188
}
169189
}
170190
}
171-
172-
mod ci {
173-
use std::path::PathBuf;
174-
175-
use crate::cli::test::TestArgs;
176-
use crate::loader::{LanguageConfiguration, Loader};
177-
178-
/// Run tests for the given languages. Test locations are reported relative to the current directory, which
179-
/// results in better readable output when build tools only provides absolute test paths.
180-
pub struct Tester {
181-
configurations: Vec<LanguageConfiguration>,
182-
test_paths: Vec<PathBuf>,
183-
}
184-
185-
impl Tester {
186-
pub fn new(configurations: Vec<LanguageConfiguration>, test_paths: Vec<PathBuf>) -> Self {
187-
Self {
188-
configurations,
189-
test_paths,
190-
}
191-
}
192-
193-
pub fn run(self) -> anyhow::Result<()> {
194-
let test_paths = self
195-
.test_paths
196-
.into_iter()
197-
.map(|test_path| {
198-
std::env::current_dir()
199-
.ok()
200-
.and_then(|cwd| pathdiff::diff_paths(&test_path, &cwd))
201-
.unwrap_or(test_path)
202-
})
203-
.collect::<Vec<_>>();
204-
for test_path in &test_paths {
205-
if !test_path.exists() {
206-
panic!("Test path {} does not exist", test_path.display());
207-
}
208-
}
209-
let mut loader = Loader::from_language_configurations(self.configurations, None)
210-
.expect("Expected loader");
211-
TestArgs::new(test_paths).run(&mut loader)
212-
}
213-
}
214-
}

tree-sitter-stack-graphs/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@ use tree_sitter_graph::parse_error::ParseError;
333333
use tree_sitter_graph::parse_error::TreeWithParseErrorVec;
334334
use tree_sitter_graph::ExecutionConfig;
335335

336+
#[cfg(feature = "cli")]
337+
pub mod ci;
336338
#[cfg(feature = "cli")]
337339
pub mod cli;
338340
pub mod functions;

0 commit comments

Comments
 (0)