acorn_lib/util/
cli.rs

1//! # Command line interface (CLI) utilities
2//!
3//! Common utilities and structs used to create a command line interface using ACORN schemas
4use crate::util::{files_all, files_from_git_branch, files_from_git_commit, git_branch_name};
5use bon::Builder;
6use clap::ValueEnum;
7use derive_more::Display;
8use serde::Serialize;
9use std::path::PathBuf;
10
11/// Catagories available when analyzing ("checking") research activity data
12///
13/// Used primarily by ACORN CLI
14#[derive(Clone, Debug, Display, PartialEq, ValueEnum, Serialize)]
15#[serde(rename_all = "lowercase")]
16pub enum Check {
17    /// Static analysis of prose
18    #[display("analysis")]
19    Analysis,
20    /// Folder structure and file naming
21    #[display("conventions")]
22    Conventions,
23    /// Readability of prose
24    #[display("readability")]
25    Readability,
26    /// Schema validation via Rust type system
27    #[display("validation")]
28    Validation,
29}
30/// Catagories available when performing system diagnostics before using ACORN
31///
32/// Used primarily by ACORN CLI
33#[derive(Clone, Copy, Debug, Default, Display, PartialEq, ValueEnum, Serialize)]
34#[serde(rename_all = "lowercase")]
35pub enum Diagnostic {
36    /// All available diagnostics
37    #[default]
38    #[display("all")]
39    All,
40    /// System information (e.g. CPU count, OS, etc...)
41    #[display("system")]
42    System,
43    /// Memory information and usage
44    #[display("memory")]
45    Memory,
46    /// Network information
47    #[display("network")]
48    Network,
49    /// Graphics Processing Unit (GPU) information
50    #[display("gpu")]
51    Gpu,
52    /// Check for installed software
53    #[display("software")]
54    Software,
55}
56/// Target export file formats available when exporting research activity data using acorn
57///
58/// Used primarily by ACORN CLI
59#[derive(Clone, Debug, Default, Display, ValueEnum, Serialize)]
60pub enum FileFormat {
61    /// Portable Document Format
62    #[default]
63    #[display("pdf")]
64    Pdf,
65    /// Microsoft PowerPoint
66    ///
67    /// Only available for certain targets (e.g. highlights)
68    #[display("powerpoint")]
69    Powerpoint,
70}
71/// Target artifact aspect ratio size available when exporting research activity data using acorn
72///
73/// Used primarily by ACORN CLI
74#[derive(Clone, Debug, Default, Display, ValueEnum, Serialize)]
75#[serde(rename_all = "lowercase")]
76pub enum Size {
77    /// Standard size (4:3)
78    #[display("standard")]
79    Standard,
80    /// Widescreen size (16:9)
81    #[default]
82    #[display("widescreen")]
83    Widescreen,
84}
85/// Target artifact types available when exporting research activity data using acorn
86///
87/// Used primarily by ACORN CLI
88#[derive(Clone, Copy, Debug, Default, Display, ValueEnum, Serialize)]
89#[serde(rename_all = "lowercase")]
90pub enum Target {
91    /// US letter sized single page PDF document presenting a certain research activity data
92    #[default]
93    #[display("fact-sheet")]
94    FactSheet,
95    /// Single slide PowerPoint presentation for a certain research activity data
96    #[display("highlight")]
97    Highlight,
98    /// Poster sized presentation format intended for large printing and presentation
99    #[display("poster")]
100    Poster,
101}
102/// Target artifact branding available when exporting research activity data using acorn
103///
104/// Used primarily by ACORN CLI
105#[derive(Default, Clone, Copy, Debug, Display)]
106pub enum TargetLabel {
107    /// National Security Sciences Directorate
108    ///
109    /// See <https://www.ornl.gov/science-area/national-security>
110    #[default]
111    #[display("National Security Sciences")]
112    Nssd,
113    /// Biological and Environmental Systems Sciences Directorate
114    ///
115    /// See <https://www.ornl.gov/directorate/bessd>
116    #[display("Biological and Environmental Systems Sciences")]
117    Bessd,
118    /// ORNL Water Power Program
119    ///
120    /// See <https://www.ornl.gov/waterpower>
121    #[display("Water Power Program")]
122    Wpp,
123    /// General ORNL Branding
124    #[display("Solving Big Problems")]
125    Ornl,
126}
127/// Container struct for working with ACORN CLI subcommand run functions
128#[derive(Builder, Clone, Debug, Default)]
129#[builder(start_fn = init)]
130pub struct Options {
131    /// Path to file or folder to be used for input
132    pub path: Option<PathBuf>,
133    /// Git branch name
134    pub branch: Option<String>,
135    /// Git commit hash
136    pub commit: Option<String>,
137    /// Regex pattern of files to ignore at a given path desginated by `path`
138    pub ignore: Option<String>,
139    /// Path to file or folder to be used for output
140    pub output: Option<PathBuf>,
141    /// Path to reference file
142    ///
143    /// e.g. reference.pptx for exporting RAD to PowerPoint
144    pub reference: Option<PathBuf>,
145    /// Artifact aspect ratio size
146    pub size: Option<Size>,
147    /// Artifact target type
148    pub target: Option<Target>,
149    /// Flag used to indicate if a single error should cause the process to exit
150    #[builder(default)]
151    pub exit_on_first_error: bool,
152    /// Flag used to indicate if changed files should be obtained from a merge request
153    #[builder(default)]
154    pub merge_request: bool,
155}
156impl TargetLabel {
157    /// Returns a string representing the folder name for the given TargetLabel
158    pub fn folder(self) -> String {
159        match self {
160            | TargetLabel::Bessd => "bessd".to_string(),
161            | TargetLabel::Wpp => "wpp".to_string(),
162            | TargetLabel::Nssd => "nssd".to_string(),
163            | TargetLabel::Ornl => TargetLabel::default().folder().to_owned(),
164        }
165    }
166    /// Returns a TargetLabel based on the given organization name
167    pub fn from_organization(name: &str) -> Self {
168        match name {
169            | "Biological and Environmental Systems Science Directorate" => TargetLabel::Bessd,
170            | "National Security Sciences Division" => TargetLabel::Nssd,
171            | "Oak Ridge National Laboratory" => TargetLabel::Ornl,
172            | "Water Power Program" => TargetLabel::Wpp,
173            | _ => TargetLabel::default(),
174        }
175    }
176}
177/// Returns a vector of PathBuf from the given options
178///
179/// If the options specify a merge request, the files from the current branch are returned.
180/// If the options specify a commit, the files changed in the commit are returned.
181/// If the options specify a branch, the files changed in the branch are returned.
182/// If none of the above options are set, the files in the given path are returned.
183/// If the options include an ignore regex, it is applied to the files returned.
184pub fn paths_from_options(path: &Option<PathBuf>, options: &Option<Options>) -> Vec<PathBuf> {
185    let extension = Some("json");
186    match options {
187        | Some(Options {
188            branch,
189            commit,
190            ignore,
191            merge_request,
192            ..
193        }) => {
194            if *merge_request {
195                match git_branch_name() {
196                    | Some(name) => files_from_git_branch(&name, extension),
197                    | None => vec![],
198                }
199            } else {
200                match commit {
201                    | Some(hash) => files_from_git_commit(hash, extension),
202                    | None => match branch {
203                        | Some(name) => files_from_git_branch(name, extension),
204                        | None => {
205                            let value = match path {
206                                | Some(x) => x.clone(),
207                                | None => PathBuf::from("."),
208                            };
209                            files_all(value, extension, ignore.clone())
210                        }
211                    },
212                }
213            }
214        }
215        | None => {
216            let value = match path {
217                | Some(x) => x.clone(),
218                | None => PathBuf::from("."),
219            };
220            files_all(value, extension, None)
221        }
222    }
223}