update
This commit is contained in:
parent
5b2fdd380a
commit
d9e9ce628c
|
|
@ -223,6 +223,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dyn-clone"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
|
@ -466,7 +472,9 @@ dependencies = [
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"regex",
|
"regex",
|
||||||
"rsn",
|
"rsn",
|
||||||
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"stringlit",
|
"stringlit",
|
||||||
"toml",
|
"toml",
|
||||||
|
|
@ -495,6 +503,31 @@ version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc6e7ed6919cb46507fb01ff1654309219f62b4d603822501b0b80d42f6f21ef"
|
||||||
|
dependencies = [
|
||||||
|
"dyn-clone",
|
||||||
|
"indexmap",
|
||||||
|
"schemars_derive",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars_derive"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "185f2b7aa7e02d418e453790dde16890256bbd2bcd04b7dc5348811052b53f49"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde_derive_internals",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
|
@ -521,6 +554,29 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive_internals"
|
||||||
|
version = "0.29.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.117"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "0.6.5"
|
version = "0.6.5"
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ indexmap = { version = "2.2.6", features = ["serde"] }
|
||||||
ratatui = "0.26.2"
|
ratatui = "0.26.2"
|
||||||
regex = "1.10.4"
|
regex = "1.10.4"
|
||||||
rsn = "0.1.0"
|
rsn = "0.1.0"
|
||||||
|
schemars = { version = "0.8.19", features = ["indexmap2"] }
|
||||||
serde = { version = "1.0.201", features = ["derive"] }
|
serde = { version = "1.0.201", features = ["derive"] }
|
||||||
|
serde_json = { version = "1.0.117", features = ["indexmap", "preserve_order"] }
|
||||||
serde_yaml = "0.9.34"
|
serde_yaml = "0.9.34"
|
||||||
stringlit = "2.1.0"
|
stringlit = "2.1.0"
|
||||||
toml = { version = "0.8.12", features = ["indexmap", "preserve_order"] }
|
toml = { version = "0.8.12", features = ["indexmap", "preserve_order"] }
|
||||||
|
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use clap::Parser;
|
|
||||||
use indexmap::{
|
|
||||||
map::{Keys, Values},
|
|
||||||
IndexMap,
|
|
||||||
};
|
|
||||||
use regex::Regex;
|
|
||||||
use req::*;
|
|
||||||
use stringlit::s;
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
struct Args {
|
|
||||||
#[arg(short, long, default_value = "REQ-.*")]
|
|
||||||
allowed_requirements: String,
|
|
||||||
requirements: PathBuf,
|
|
||||||
test_results: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn nl() -> String {
|
|
||||||
s!("")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_requirements(
|
|
||||||
test_results: &str,
|
|
||||||
output: &mut Vec<String>,
|
|
||||||
requirements: &IndexMap<String, Requirement>,
|
|
||||||
allowed_requirements: &Regex,
|
|
||||||
) {
|
|
||||||
for (id, requirement) in requirements {
|
|
||||||
if allowed_requirements.is_match(&id) {
|
|
||||||
let status = if test_results.contains(&format!("{id} succeeded")) {
|
|
||||||
":white_check_mark:"
|
|
||||||
} else if test_results.contains(&format!("{id} failed")) {
|
|
||||||
":x:"
|
|
||||||
} else {
|
|
||||||
":warning:"
|
|
||||||
};
|
|
||||||
output.push(format!("- _{id}_ - {}: {status}", requirement.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_valid_requirements(
|
|
||||||
mut requirements: Keys<String, Requirement>,
|
|
||||||
allowed_requirements: &Regex,
|
|
||||||
) -> bool {
|
|
||||||
requirements.any(|id| allowed_requirements.is_match(&id))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_valid_topics(mut topics: Values<String, Topic>, allowed_requirements: &Regex) -> bool {
|
|
||||||
topics.any(|topic| {
|
|
||||||
has_valid_requirements(topic.requirements.keys(), allowed_requirements)
|
|
||||||
|| has_valid_topics(topic.subtopics.values(), allowed_requirements)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_topics(
|
|
||||||
test_results: &str,
|
|
||||||
output: &mut Vec<String>,
|
|
||||||
topics: &IndexMap<String, Topic>,
|
|
||||||
allowed_requirements: &Regex,
|
|
||||||
level: usize,
|
|
||||||
) {
|
|
||||||
if !has_valid_topics(topics.values(), allowed_requirements) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (id, topic) in topics {
|
|
||||||
if !has_valid_topics(topic.subtopics.values(), allowed_requirements)
|
|
||||||
&& !has_valid_requirements(topic.requirements.keys(), allowed_requirements)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
output.push(format!("{} _{id}_ - {}", "#".repeat(level), topic.name));
|
|
||||||
if !topic.requirements.is_empty() {
|
|
||||||
check_requirements(
|
|
||||||
test_results,
|
|
||||||
output,
|
|
||||||
&topic.requirements,
|
|
||||||
allowed_requirements,
|
|
||||||
);
|
|
||||||
output.push(nl());
|
|
||||||
}
|
|
||||||
if !topic.subtopics.is_empty() {
|
|
||||||
check_topics(
|
|
||||||
test_results,
|
|
||||||
output,
|
|
||||||
&topic.subtopics,
|
|
||||||
allowed_requirements,
|
|
||||||
level + 1,
|
|
||||||
);
|
|
||||||
output.push(nl());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
|
||||||
let Args {
|
|
||||||
allowed_requirements,
|
|
||||||
requirements,
|
|
||||||
test_results,
|
|
||||||
} = Args::parse();
|
|
||||||
let re = Regex::new(&allowed_requirements).unwrap();
|
|
||||||
let test_results = std::fs::read_to_string(test_results)?;
|
|
||||||
let project: Project = serde_yaml::from_str(&std::fs::read_to_string(requirements)?)?;
|
|
||||||
let mut output = vec![format!("# Test Results - {}", project.name)];
|
|
||||||
check_topics(&test_results, &mut output, &project.topics, &re, 2);
|
|
||||||
|
|
||||||
let output = output.join("\n");
|
|
||||||
println!("{output}");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
23
src/lib.rs
23
src/lib.rs
|
|
@ -1,15 +1,16 @@
|
||||||
use indexmap::{indexmap, IndexMap};
|
use indexmap::{indexmap, IndexMap};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize, Serializer};
|
use serde::{Deserialize, Serialize, Serializer};
|
||||||
use stringlit::s;
|
use stringlit::s;
|
||||||
|
|
||||||
pub fn my_trim<S>(v: &String, s: S) -> Result<S::Ok, S::Error>
|
pub fn my_trim<S>(v: &str, s: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
s.serialize_str(v.trim())
|
s.serialize_str(v.trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(JsonSchema, Debug, Deserialize, Serialize)]
|
||||||
pub struct Requirement {
|
pub struct Requirement {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(serialize_with = "my_trim")]
|
#[serde(serialize_with = "my_trim")]
|
||||||
|
|
@ -18,7 +19,7 @@ pub struct Requirement {
|
||||||
pub requires: Vec<String>,
|
pub requires: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(JsonSchema, Debug, Deserialize, Serialize)]
|
||||||
pub struct Topic {
|
pub struct Topic {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(default, skip_serializing_if = "IndexMap::is_empty")]
|
#[serde(default, skip_serializing_if = "IndexMap::is_empty")]
|
||||||
|
|
@ -27,7 +28,7 @@ pub struct Topic {
|
||||||
pub subtopics: IndexMap<String, Topic>,
|
pub subtopics: IndexMap<String, Topic>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(JsonSchema, Debug, Deserialize, Serialize)]
|
||||||
pub struct Definition {
|
pub struct Definition {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
|
|
@ -35,7 +36,7 @@ pub struct Definition {
|
||||||
pub additional_info: Vec<String>,
|
pub additional_info: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(JsonSchema, Debug, Deserialize, Serialize)]
|
||||||
pub struct ConfigDefault {
|
pub struct ConfigDefault {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
|
|
@ -50,7 +51,7 @@ pub struct ConfigDefault {
|
||||||
pub hint: Option<String>,
|
pub hint: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(JsonSchema, Debug, Deserialize, Serialize)]
|
||||||
pub struct Project {
|
pub struct Project {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(serialize_with = "my_trim")]
|
#[serde(serialize_with = "my_trim")]
|
||||||
|
|
@ -66,10 +67,10 @@ pub struct Project {
|
||||||
pub fn demo_project() -> Project {
|
pub fn demo_project() -> Project {
|
||||||
Project {
|
Project {
|
||||||
name: s!("journal-uploader"),
|
name: s!("journal-uploader"),
|
||||||
description: s!(r#"
|
description: s!(r"
|
||||||
The journal-uploader has two main functionalities.
|
The journal-uploader has two main functionalities.
|
||||||
- Take a stream of log messages and filter them depending on their severity
|
- Take a stream of log messages and filter them depending on their severity
|
||||||
- Upload journal logs for a specified time when activated through cloud call"#),
|
- Upload journal logs for a specified time when activated through cloud call"),
|
||||||
topics: indexmap! {
|
topics: indexmap! {
|
||||||
s!("FEAT-1") => Topic {
|
s!("FEAT-1") => Topic {
|
||||||
name: s!("Traced Logging"),
|
name: s!("Traced Logging"),
|
||||||
|
|
@ -79,7 +80,7 @@ The journal-uploader has two main functionalities.
|
||||||
requirements: indexmap! {
|
requirements: indexmap! {
|
||||||
s!("REQ-1") => Requirement {
|
s!("REQ-1") => Requirement {
|
||||||
name: s!("Continuous Monitoring"),
|
name: s!("Continuous Monitoring"),
|
||||||
description: s!(r#"The tool must continuously monitor a designated directory."#),
|
description: s!(r"The tool must continuously monitor a designated directory."),
|
||||||
requires: vec! [],
|
requires: vec! [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -90,12 +91,12 @@ The journal-uploader has two main functionalities.
|
||||||
requirements: indexmap! {
|
requirements: indexmap! {
|
||||||
s!("REQ-1") => Requirement {
|
s!("REQ-1") => Requirement {
|
||||||
name: s!("Detection of New Files"),
|
name: s!("Detection of New Files"),
|
||||||
description: s!(r#"The tool must detect the addition of new files in the monitored directory."#),
|
description: s!(r"The tool must detect the addition of new files in the monitored directory."),
|
||||||
requires: vec! [],
|
requires: vec! [],
|
||||||
},
|
},
|
||||||
s!("REQ-2") => Requirement {
|
s!("REQ-2") => Requirement {
|
||||||
name: s!("Avoid Re-processing"),
|
name: s!("Avoid Re-processing"),
|
||||||
description: s!(r#"The tool must not process files that have already been processed."#),
|
description: s!(r"The tool must not process files that have already been processed."),
|
||||||
requires: vec! [],
|
requires: vec! [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
230
src/main.rs
230
src/main.rs
|
|
@ -1,8 +1,13 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use indexmap::IndexMap;
|
use indexmap::{
|
||||||
|
map::{Keys, Values},
|
||||||
|
IndexMap,
|
||||||
|
};
|
||||||
|
use regex::Regex;
|
||||||
use req::*;
|
use req::*;
|
||||||
|
use schemars::schema_for;
|
||||||
use stringlit::s;
|
use stringlit::s;
|
||||||
|
|
||||||
pub const WORD_DESCRIPTION: &str = //
|
pub const WORD_DESCRIPTION: &str = //
|
||||||
|
|
@ -28,6 +33,79 @@ fn nl() -> String {
|
||||||
s!("")
|
s!("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_requirements(
|
||||||
|
test_results: &str,
|
||||||
|
output: &mut Vec<String>,
|
||||||
|
requirements: &IndexMap<String, Requirement>,
|
||||||
|
allowed_requirements: &Regex,
|
||||||
|
) {
|
||||||
|
for (id, requirement) in requirements {
|
||||||
|
if allowed_requirements.is_match(id) {
|
||||||
|
let status = if test_results.contains(&format!("{id} succeeded")) {
|
||||||
|
":white_check_mark:"
|
||||||
|
} else if test_results.contains(&format!("{id} failed")) {
|
||||||
|
":x:"
|
||||||
|
} else {
|
||||||
|
":warning:"
|
||||||
|
};
|
||||||
|
output.push(format!("- _{id}_ - {}: {status}", requirement.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_valid_requirements(
|
||||||
|
mut requirements: Keys<String, Requirement>,
|
||||||
|
allowed_requirements: &Regex,
|
||||||
|
) -> bool {
|
||||||
|
requirements.any(|id| allowed_requirements.is_match(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_valid_topics(mut topics: Values<String, Topic>, allowed_requirements: &Regex) -> bool {
|
||||||
|
topics.any(|topic| {
|
||||||
|
has_valid_requirements(topic.requirements.keys(), allowed_requirements)
|
||||||
|
|| has_valid_topics(topic.subtopics.values(), allowed_requirements)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_topics(
|
||||||
|
test_results: &str,
|
||||||
|
output: &mut Vec<String>,
|
||||||
|
topics: &IndexMap<String, Topic>,
|
||||||
|
allowed_requirements: &Regex,
|
||||||
|
level: usize,
|
||||||
|
) {
|
||||||
|
if !has_valid_topics(topics.values(), allowed_requirements) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (id, topic) in topics {
|
||||||
|
if !has_valid_topics(topic.subtopics.values(), allowed_requirements)
|
||||||
|
&& !has_valid_requirements(topic.requirements.keys(), allowed_requirements)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
output.push(format!("{} _{id}_ - {}", "#".repeat(level), topic.name));
|
||||||
|
if !topic.requirements.is_empty() {
|
||||||
|
check_requirements(
|
||||||
|
test_results,
|
||||||
|
output,
|
||||||
|
&topic.requirements,
|
||||||
|
allowed_requirements,
|
||||||
|
);
|
||||||
|
output.push(nl());
|
||||||
|
}
|
||||||
|
if !topic.subtopics.is_empty() {
|
||||||
|
check_topics(
|
||||||
|
test_results,
|
||||||
|
output,
|
||||||
|
&topic.subtopics,
|
||||||
|
allowed_requirements,
|
||||||
|
level + 1,
|
||||||
|
);
|
||||||
|
output.push(nl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn add_requirements(output: &mut Vec<String>, requirements: &IndexMap<String, Requirement>) {
|
fn add_requirements(output: &mut Vec<String>, requirements: &IndexMap<String, Requirement>) {
|
||||||
for (id, requirement) in requirements {
|
for (id, requirement) in requirements {
|
||||||
output.push(format!(
|
output.push(format!(
|
||||||
|
|
@ -51,77 +129,115 @@ fn add_topics(output: &mut Vec<String>, topics: &IndexMap<String, Topic>, level:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
enum Command {
|
||||||
|
Schema,
|
||||||
|
#[clap(alias = "md")]
|
||||||
|
Markdown {
|
||||||
|
requirements: PathBuf,
|
||||||
|
},
|
||||||
|
Check {
|
||||||
|
#[arg(short, long, default_value = "REQ-.*")]
|
||||||
|
allowed_requirements: String,
|
||||||
|
requirements: PathBuf,
|
||||||
|
test_results: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Args {
|
struct Args {
|
||||||
input: PathBuf,
|
#[clap(subcommand)]
|
||||||
|
command: Command,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let Args { input } = Args::parse();
|
let Args { command } = Args::parse();
|
||||||
let project: Project = serde_yaml::from_str(&std::fs::read_to_string(input)?)?;
|
match command {
|
||||||
|
Command::Schema => {
|
||||||
let mut output = vec![
|
let schema = schema_for!(Project);
|
||||||
format!("# Requirements for {}", project.name),
|
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
nl(),
|
|
||||||
s!("[[_TOC_]]"),
|
|
||||||
nl(),
|
|
||||||
WORD_DESCRIPTION.to_string(),
|
|
||||||
nl(),
|
|
||||||
s!("## Description"),
|
|
||||||
project.description,
|
|
||||||
nl(),
|
|
||||||
];
|
|
||||||
|
|
||||||
if !project.topics.is_empty() {
|
|
||||||
output.push(s!("## Requirements"));
|
|
||||||
add_topics(&mut output, &project.topics, 3);
|
|
||||||
output.push(nl());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !project.definitions.is_empty() {
|
|
||||||
output.push(s!("## Definitions"));
|
|
||||||
for definition in project.definitions {
|
|
||||||
output.push(format!("- {}: {}", definition.name, definition.value));
|
|
||||||
for info in definition.additional_info {
|
|
||||||
output.push(format!(" - {info}"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
output.push(nl());
|
Command::Markdown { requirements } => {
|
||||||
}
|
let project: Project = serde_yaml::from_str(&std::fs::read_to_string(requirements)?)?;
|
||||||
|
|
||||||
if !project.config_defaults.is_empty() {
|
let mut output = vec![
|
||||||
output.push(s!("## Config Defaults"));
|
format!("# Requirements for {}", project.name),
|
||||||
for default in project.config_defaults {
|
nl(),
|
||||||
output.push(format!("- **{}**", default.name));
|
s!("[[_TOC_]]"),
|
||||||
output.push(format!(" - Type: {}", default.typ));
|
nl(),
|
||||||
if let Some(unit) = default.unit {
|
WORD_DESCRIPTION.to_string(),
|
||||||
output.push(format!(" - Unit: {unit}"));
|
nl(),
|
||||||
|
s!("## Description"),
|
||||||
|
project.description,
|
||||||
|
nl(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if !project.topics.is_empty() {
|
||||||
|
output.push(s!("## Requirements"));
|
||||||
|
add_topics(&mut output, &project.topics, 3);
|
||||||
|
output.push(nl());
|
||||||
}
|
}
|
||||||
if let Some(valid_values) = default.valid_values {
|
|
||||||
output.push(format!(" - Valid Values: _{}_", valid_values.join(", ")));
|
if !project.definitions.is_empty() {
|
||||||
|
output.push(s!("## Definitions"));
|
||||||
|
for definition in project.definitions {
|
||||||
|
output.push(format!("- {}: {}", definition.name, definition.value));
|
||||||
|
for info in definition.additional_info {
|
||||||
|
output.push(format!(" - {info}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.push(nl());
|
||||||
}
|
}
|
||||||
if let Some(default_value) = default.default_value {
|
|
||||||
output.push(format!(
|
if !project.config_defaults.is_empty() {
|
||||||
" - Default Value: _{}_{}",
|
output.push(s!("## Config Defaults"));
|
||||||
default_value,
|
for default in project.config_defaults {
|
||||||
default.hint.map(|h| format!(" {h}")).unwrap_or_default()
|
output.push(format!("- **{}**", default.name));
|
||||||
));
|
output.push(format!(" - Type: {}", default.typ));
|
||||||
} else {
|
if let Some(unit) = default.unit {
|
||||||
output.push(format!(
|
output.push(format!(" - Unit: {unit}"));
|
||||||
|
}
|
||||||
|
if let Some(valid_values) = default.valid_values {
|
||||||
|
output.push(format!(" - Valid Values: _{}_", valid_values.join(", ")));
|
||||||
|
}
|
||||||
|
if let Some(default_value) = default.default_value {
|
||||||
|
output.push(format!(
|
||||||
|
" - Default Value: _{}_{}",
|
||||||
|
default_value,
|
||||||
|
default.hint.map(|h| format!(" {h}")).unwrap_or_default()
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
output.push(format!(
|
||||||
" - **Required**: This value **_MUST_** be provided as a start parameter.{}",
|
" - **Required**: This value **_MUST_** be provided as a start parameter.{}",
|
||||||
default.hint.map(|h| format!(" {h}")).unwrap_or_default()
|
default.hint.map(|h| format!(" {h}")).unwrap_or_default()
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
output.push(nl());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output.push(nl());
|
|
||||||
|
let mut output = output.join("\n");
|
||||||
|
for word in HIGHLIGHTED_WORDS {
|
||||||
|
output = output.replace(word, &format!("**_{}_**", word.to_uppercase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{output}");
|
||||||
|
}
|
||||||
|
Command::Check {
|
||||||
|
allowed_requirements,
|
||||||
|
requirements,
|
||||||
|
test_results,
|
||||||
|
} => {
|
||||||
|
let re = Regex::new(&allowed_requirements).unwrap();
|
||||||
|
let test_results = std::fs::read_to_string(test_results)?;
|
||||||
|
let project: Project = serde_yaml::from_str(&std::fs::read_to_string(requirements)?)?;
|
||||||
|
let mut output = vec![format!("# Test Results - {}", project.name)];
|
||||||
|
check_topics(&test_results, &mut output, &project.topics, &re, 2);
|
||||||
|
|
||||||
|
let output = output.join("\n");
|
||||||
|
println!("{output}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = output.join("\n");
|
|
||||||
for word in HIGHLIGHTED_WORDS {
|
|
||||||
output = output.replace(word, &format!("**_{}_**", word.to_uppercase()));
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{output}");
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue