Skip to content

Commit 3298a6a

Browse files
authored
feat(cli): Add verbosity, return Hugr from run. (#1116)
1 parent f757cc8 commit 3298a6a

File tree

5 files changed

+48
-12
lines changed

5 files changed

+48
-12
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ typetag = "0.2.7"
5757
urlencoding = "2.1.2"
5858
webbrowser = "1.0.0"
5959
clap = { version = "4.5.4"}
60+
clap-stdin = "0.4.0"
61+
clap-verbosity-flag = "2.2.0"
6062
assert_cmd = "2.0.14"
6163
assert_fs = "1.1.1"
62-
clap-stdin = "0.4.0"
6364
predicates = "3.1.0"
6465

6566
[profile.dev.package]

hugr-cli/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ categories = ["compilers"]
1515

1616
[dependencies]
1717
clap = {workspace = true, features = ["derive"]}
18-
clap-stdin = { workspace = true }
18+
clap-stdin.workspace = true
19+
clap-verbosity-flag.workspace = true
1920
hugr-core = { path = "../hugr-core", version = "0.0.0" }
2021
serde_json.workspace = true
2122
thiserror.workspace = true

hugr-cli/src/lib.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
//! Standard command line tools, used by the hugr binary.
22
3-
pub use clap::Parser;
43
use clap_stdin::FileOrStdin;
5-
use hugr_core::{extension::ExtensionRegistry, Hugr, HugrView};
4+
use clap_verbosity_flag::{InfoLevel, Verbosity};
65
use thiserror::Error;
6+
/// We reexport some clap types that are used in the public API.
7+
pub use {clap::Parser, clap_verbosity_flag::Level};
8+
9+
use hugr_core::{extension::ExtensionRegistry, Hugr, HugrView};
10+
711
/// Validate and visualise a HUGR file.
812
#[derive(Parser, Debug)]
913
#[clap(version = "1.0", long_about = None)]
1014
#[clap(about = "Validate a HUGR.")]
15+
#[group(id = "hugr")]
1116
pub struct CmdLineArgs {
1217
input: FileOrStdin,
1318
/// Visualise with mermaid.
@@ -16,6 +21,9 @@ pub struct CmdLineArgs {
1621
/// Skip validation.
1722
#[arg(short, long, help = "Skip validation.")]
1823
no_validate: bool,
24+
/// Verbosity.
25+
#[command(flatten)]
26+
verbose: Verbosity<InfoLevel>,
1927
// TODO YAML extensions
2028
}
2129

@@ -38,17 +46,23 @@ pub const VALID_PRINT: &str = "HUGR valid!";
3846

3947
impl CmdLineArgs {
4048
/// Run the HUGR cli and validate against an extension registry.
41-
pub fn run(&self, registry: &ExtensionRegistry) -> Result<(), CliError> {
49+
pub fn run(&self, registry: &ExtensionRegistry) -> Result<Hugr, CliError> {
4250
let mut hugr: Hugr = serde_json::from_reader(self.input.into_reader()?)?;
4351
if self.mermaid {
4452
println!("{}", hugr.mermaid_string());
4553
}
4654

4755
if !self.no_validate {
4856
hugr.update_validate(registry)?;
49-
50-
println!("{}", VALID_PRINT);
57+
if self.verbosity(Level::Info) {
58+
eprintln!("{}", VALID_PRINT);
59+
}
5160
}
52-
Ok(())
61+
Ok(hugr)
62+
}
63+
64+
/// Test whether a `level` message should be output.
65+
pub fn verbosity(&self, level: Level) -> bool {
66+
self.verbose.log_level_filter() >= level
5367
}
5468
}

hugr/src/main.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use hugr::std_extensions::logic::EXTENSION as LOGICS_EXTENSION;
99

1010
use hugr::extension::{ExtensionRegistry, PRELUDE};
1111

12-
use hugr_cli::{CmdLineArgs, Parser};
12+
use hugr_cli::{CmdLineArgs, Level, Parser};
1313

1414
fn main() {
1515
let opts = CmdLineArgs::parse();
@@ -27,7 +27,9 @@ fn main() {
2727
.unwrap();
2828

2929
if let Err(e) = opts.run(&reg) {
30-
eprintln!("{}", e);
30+
if opts.verbosity(Level::Error) {
31+
eprintln!("{}", e);
32+
}
3133
std::process::exit(1);
3234
}
3335
}

hugr/tests/cli.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,23 @@ fn test_doesnt_exist(mut cmd: Command) {
4848
#[rstest]
4949
fn test_validate(test_hugr_file: NamedTempFile, mut cmd: Command) {
5050
cmd.arg(test_hugr_file.path());
51-
cmd.assert().success().stdout(contains(VALID_PRINT));
51+
cmd.assert().success().stderr(contains(VALID_PRINT));
5252
}
5353

5454
#[rstest]
5555
fn test_stdin(test_hugr_string: String, mut cmd: Command) {
5656
cmd.write_stdin(test_hugr_string);
5757
cmd.arg("-");
5858

59-
cmd.assert().success().stdout(contains(VALID_PRINT));
59+
cmd.assert().success().stderr(contains(VALID_PRINT));
60+
}
61+
62+
#[rstest]
63+
fn test_stdin_silent(test_hugr_string: String, mut cmd: Command) {
64+
cmd.args(["-", "-q"]);
65+
cmd.write_stdin(test_hugr_string);
66+
67+
cmd.assert().success().stderr(contains(VALID_PRINT).not());
6068
}
6169

6270
#[rstest]
@@ -91,3 +99,13 @@ fn test_bad_json(mut cmd: Command) {
9199
.failure()
92100
.stderr(contains("Error parsing input"));
93101
}
102+
103+
#[rstest]
104+
fn test_bad_json_silent(mut cmd: Command) {
105+
cmd.write_stdin(r#"{"foo": "bar"}"#);
106+
cmd.args(["-", "-qqq"]);
107+
108+
cmd.assert()
109+
.failure()
110+
.stderr(contains("Error parsing input").not());
111+
}

0 commit comments

Comments
 (0)