hugr_cli/
lib.rs

1//! Standard command line tools for the HUGR format.
2//!
3//! This library provides utilities for the HUGR CLI.
4//!
5//! ## CLI Usage
6//!
7//! Run `cargo install hugr-cli` to install the CLI tools. This will make the
8//! `hugr` executable available in your shell as long as you have [cargo's bin
9//! directory](https://doc.rust-lang.org/book/ch14-04-installing-binaries.html)
10//! in your path.
11//!
12//! The CLI provides two subcommands:
13//!
14//! - `validate` for validating HUGR files.
15//! - `mermaid` for visualizing HUGR files as mermaid diagrams.
16//!
17//! ### Validate
18//!
19//! Validate and visualize a HUGR file
20//!
21//! Usage: `hugr validate [OPTIONS] [INPUT]`
22//!
23//! ```text
24//! Options:
25//!   -v, --verbose...  Increase logging verbosity
26//!   -q, --quiet...    Decrease logging verbosity
27//!   -h, --help        Print help (see more with '--help')
28//!   -V, --version     Print version
29//!
30//! Input:
31//!       --no-std                   Don't use standard extensions when validating hugrs. Prelude is still used.
32//!   -e, --extensions <EXTENSIONS>  Paths to serialised extensions to validate against.
33//!       --hugr-json                Read the input as a HUGR JSON file instead of an envelope
34//!   [INPUT]                    Input file. Defaults to `-` for stdin
35//! ```
36//!
37//! ### Mermaid
38//!
39//! Write HUGR as mermaid diagrams
40//!
41//! Usage: `hugr mermaid [OPTIONS] [INPUT]`
42//!
43//! ```text
44//! Options:
45//!       --validate         Validate before rendering, includes extension inference.
46//!   -o, --output <OUTPUT>  Output file '-' for stdout [default: -]
47//!   -v, --verbose...       Increase logging verbosity
48//!   -q, --quiet...         Decrease logging verbosity
49//!   -h, --help             Print help (see more with '--help')
50//!   -V, --version          Print version
51//!
52//! Input:
53//!       --no-std                   Don't use standard extensions when validating hugrs. Prelude is still used.
54//!   -e, --extensions <EXTENSIONS>  Paths to serialised extensions to validate against.
55//!       --hugr-json                Read the input as a HUGR JSON file instead of an envelope
56//!   [INPUT]                    Input file. Defaults to `-` for stdin.
57//! ```
58
59use clap::{Parser, crate_version};
60use clap_verbosity_flag::log::Level;
61use clap_verbosity_flag::{InfoLevel, Verbosity};
62use hugr::envelope::EnvelopeError;
63use hugr::package::PackageValidationError;
64use std::ffi::OsString;
65
66pub mod extensions;
67pub mod hugr_io;
68pub mod mermaid;
69pub mod validate;
70
71/// CLI arguments.
72#[derive(Parser, Debug)]
73#[clap(version = crate_version!(), long_about = None)]
74#[clap(about = "HUGR CLI tools.")]
75#[group(id = "hugr")]
76#[non_exhaustive]
77pub enum CliArgs {
78    /// Validate and visualize a HUGR file.
79    Validate(validate::ValArgs),
80    /// Write standard extensions out in serialized form.
81    GenExtensions(extensions::ExtArgs),
82    /// Write HUGR as mermaid diagrams.
83    Mermaid(mermaid::MermaidArgs),
84    /// External commands
85    #[command(external_subcommand)]
86    External(Vec<OsString>),
87}
88
89/// Error type for the CLI.
90#[derive(Debug, derive_more::Display, derive_more::Error, derive_more::From)]
91#[non_exhaustive]
92pub enum CliError {
93    /// Error reading input.
94    #[display("Error reading from path: {_0}")]
95    InputFile(std::io::Error),
96    /// Error parsing input.
97    #[display("Error parsing package: {_0}")]
98    Parse(serde_json::Error),
99    #[display("Error validating HUGR: {_0}")]
100    /// Errors produced by the `validate` subcommand.
101    Validate(PackageValidationError),
102    #[display("Error decoding HUGR envelope: {_0}")]
103    /// Errors produced by the `validate` subcommand.
104    Envelope(EnvelopeError),
105    /// Pretty error when the user passes a non-envelope file.
106    #[display(
107        "Input file is not a HUGR envelope. Invalid magic number.\n\nUse `--hugr-json` to read a raw HUGR JSON file instead."
108    )]
109    NotAnEnvelope,
110}
111
112/// Other arguments affecting the HUGR CLI runtime.
113#[derive(Parser, Debug)]
114pub struct OtherArgs {
115    /// Verbosity.
116    #[command(flatten)]
117    pub verbose: Verbosity<InfoLevel>,
118}
119
120impl OtherArgs {
121    /// Test whether a `level` message should be output.
122    #[must_use]
123    pub fn verbosity(&self, level: Level) -> bool {
124        self.verbose.log_level_filter() >= level
125    }
126}