From ca145f5e4b5aea49a629a37cd5afbab10418f7d2 Mon Sep 17 00:00:00 2001 From: Paul-Christian Volkmer Date: Sat, 3 Jun 2023 15:27:09 +0200 Subject: [PATCH] Add subcommands 'list' and 'modify' --- Cargo.lock | 104 ++++++++++++++++++++++++++ Cargo.toml | 1 + README.md | 25 ++++++- src/main.rs | 126 ++++++++++++++++++++------------ src/model/data_catalogue.rs | 9 +++ src/model/data_form.rs | 4 + src/model/onkostar_editor.rs | 44 +++++++++++ src/model/property_catalogue.rs | 9 +++ src/model/unterformular.rs | 16 ++++ 9 files changed, 290 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2f0f1b..1650594 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,25 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "hashbrown" version = "0.12.3" @@ -88,6 +107,18 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" + [[package]] name = "memchr" version = "2.5.0" @@ -105,6 +136,7 @@ name = "osc-variant" version = "0.1.0" dependencies = [ "clap", + "console", "quick-xml", "serde", "serde_yaml", @@ -195,12 +227,84 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "unsafe-libyaml" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "xml-rs" version = "0.8.13" diff --git a/Cargo.toml b/Cargo.toml index 634e199..12cdeb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,4 @@ serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" quick-xml = { version = "0.28", features = ["escape-html", "serialize"], default-features=false } xml-rs = "0.8" +console = "0.15" diff --git a/README.md b/README.md index 06b708f..77c83fe 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,35 @@ Anwendung zum Anpassen einer OSC-Datei an einen Standort. ## Funktion -Diese Anwendung passt eine OSC-Datei so an, dass (standortbezogene) Formularvarianten für Formularverweise +Diese Anwendung passt listet die Inhalte eine OSC-Datei auf oder passt sie so an, dass (standortbezogene) Formularvarianten für Formularverweise verwendet werden. Hierzu wird die Datei deserialisiert, die entsprechenden Formularfelder ermittelt und die Formularvariante sowie die Anzeige anhand eines Profils angepasst. +Wird in einer OSC-Datei eine noch nicht bekannte Eigenschaft erkannt, wird die weitere Bearbeitung abgebrochen um keine +unvollständigen Ausgabedateien zu erzeugen. + +### Beispiele + +Zum Auflisten der Inhalte einer Datei wird folgender Befehl verwendet: + +``` +osc-variant list meine-beispieldatei.osc +``` + +Zum Anpassen des Inhalts einer Datei: + +``` +osc-variant modify meine-beispieldatei.osc --profile ukw-profil.yml --output ukw-beispieldatei.osc +``` + +Die Parameter `--profile` und `--output` sind optional. + +Ohne Profildatei wird die Datei lediglich eingelesen, Leerzeichen am Ende eines XML-Tags entfernt und wieder ausgegeben. + +Ohne eine Angabe der Ausgabedatei wird auf die Standardausgabe ausgegeben. + ## Profile Zum Erstellen von Varianten einer OSC-Datei wird eine Profildatei im YAML-Format verwendet. diff --git a/src/main.rs b/src/main.rs index bec2b28..a4cec95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ use std::fs::OpenOptions; use std::io::Write; use std::ops::Add; -use clap::Parser; +use clap::{Parser, Subcommand}; use quick_xml::de::from_str; use quick_xml::se::Serializer; use serde::Serialize; @@ -41,59 +41,91 @@ mod profile; #[command(author, version, about, long_about = None)] #[command(propagate_version = true, arg_required_else_help(true))] struct Cli { - #[arg(long = "input", help = "Eingabedatei")] - input: String, - #[arg(long = "profile", help = "Profildatei (Optional)")] - profile: Option, - #[arg(long = "output", help = "Ausgabedatei (Optional)")] - output: Option, + #[command(subcommand)] + command: Command, +} + +#[derive(Subcommand)] +enum Command { + #[command(about = "Zeigt alle enthaltenen Kataloge und Formulare mit Revision an.")] + List { inputfile: String }, + #[command(about = "Modifiziert die angegebene Datei anhand der Profildatei")] + Modify { + inputfile: String, + #[arg(long = "profile", help = "Profildatei (Optional)")] + profile: Option, + #[arg(long = "output", help = "Ausgabedatei (Optional)")] + outputfile: Option, + }, } fn main() { let cli = Cli::parse(); - let contents = fs::read_to_string(cli.input).expect("Should have been able to read the file"); + match cli.command { + Command::List { inputfile } => { + let contents = + fs::read_to_string(inputfile).expect("Should have been able to read the file"); - if let Ok(mut data) = from_str::(contents.as_str()) { - data.apply_variant(); - - let mut buf = String::new(); - - let mut serializer = Serializer::new(&mut buf); - serializer.indent(' ', 2); - - data.serialize(serializer).expect("Generated XML"); - - let output = "\n" - .to_string() - .add( - buf - // Replace ' and " as used in original file - .replace("'", "'") - .replace(""", "\"") - .as_str(), - ); - - match cli.output { - Some(filename) => { - let mut file = OpenOptions::new() - .read(false) - .write(true) - .create(true) - .truncate(true) - .open(filename) - .unwrap(); - file.write_all(output.as_bytes()) - .expect("Should have written output file"); - } - None => { - println!("{}", output) + if let Ok(mut data) = from_str::(contents.as_str()) { + data.list_forms() + } else { + eprintln!("Kann Eingabedatei nicht lesen!"); + eprintln!( + "Die Datei ist entweder keine OSC-Datei, fehlerhaft oder enthält zusätzliche Inhalte." + ); + } + } + Command::Modify { + inputfile, + profile, + outputfile, + } => { + let contents = + fs::read_to_string(inputfile).expect("Should have been able to read the file"); + + if let Ok(mut data) = from_str::(contents.as_str()) { + data.apply_variant(); + + let mut buf = String::new(); + + let mut serializer = Serializer::new(&mut buf); + serializer.indent(' ', 2); + + data.serialize(serializer).expect("Generated XML"); + + let output = "\n" + .to_string() + .add( + buf + // Replace ' and " as used in original file + .replace("'", "'") + .replace(""", "\"") + .as_str(), + ); + + match outputfile { + Some(filename) => { + let mut file = OpenOptions::new() + .read(false) + .write(true) + .create(true) + .truncate(true) + .open(filename) + .unwrap(); + file.write_all(output.as_bytes()) + .expect("Should have written output file"); + } + None => { + println!("{}", output) + } + } + } else { + eprintln!("Kann Eingabedatei nicht lesen!"); + eprintln!( + "Die Datei ist entweder keine OSC-Datei, fehlerhaft oder enthält zusätzliche Inhalte." + ); } } - } else { - eprintln!("Kann Eingabedatei nicht lesen!"); - eprintln!( - "Die Datei ist entweder keine OSC-Datei, fehlerhaft oder enthält zusätzliche Inhalte." - ); } } diff --git a/src/model/data_catalogue.rs b/src/model/data_catalogue.rs index eba84c3..692fbd4 100644 --- a/src/model/data_catalogue.rs +++ b/src/model/data_catalogue.rs @@ -55,6 +55,15 @@ pub struct DataCatalogue { ordner: Ordner, } +impl DataCatalogue { + pub fn to_listed_string(&self) -> String { + format!( + "Datenkatalog '{}' in Revision '{}'", + self.name, self.revision + ) + } +} + #[derive(Serialize, Deserialize, Debug)] #[serde(deny_unknown_fields)] pub struct Entries { diff --git a/src/model/data_form.rs b/src/model/data_form.rs index ce0b1d3..5328722 100644 --- a/src/model/data_form.rs +++ b/src/model/data_form.rs @@ -160,6 +160,10 @@ impl DataForm { }) } } + + pub fn to_listed_string(&self) -> String { + format!("Formular '{}' in Revision '{}'", self.name, self.revision) + } } #[derive(Serialize, Deserialize, Debug)] diff --git a/src/model/onkostar_editor.rs b/src/model/onkostar_editor.rs index 2d2b51e..a6fdf8d 100644 --- a/src/model/onkostar_editor.rs +++ b/src/model/onkostar_editor.rs @@ -22,6 +22,7 @@ * SOFTWARE. */ +use console::style; use serde::{Deserialize, Serialize}; use crate::model::data_catalogue::DataCatalogue; @@ -47,6 +48,49 @@ impl OnkostarEditor { data_form.apply_variant(); }) } + + pub fn list_forms(&self) { + println!( + "{}", + style("In der Datei sind folgende Inhalte gespeichert\n").bold() + ); + println!( + "{} {}", + self.editor.property_catalogue.len(), + style("Merkmalskataloge").underlined() + ); + self.editor + .property_catalogue + .iter() + .for_each(|data_form| println!("{}", data_form.to_listed_string())); + println!( + "\n{} {}", + self.editor.data_catalogue.len(), + style("Datenkataloge").underlined() + ); + self.editor + .data_catalogue + .iter() + .for_each(|data_form| println!("{}", data_form.to_listed_string())); + println!( + "\n{} {}", + self.editor.data_form.len(), + style("Formulare").underlined() + ); + self.editor + .data_form + .iter() + .for_each(|data_form| println!("{}", data_form.to_listed_string())); + println!( + "\n{} {}", + self.editor.unterformular.len(), + style("Unterformulare").underlined() + ); + self.editor + .unterformular + .iter() + .for_each(|data_form| println!("{}", data_form.to_listed_string())); + } } #[derive(Serialize, Deserialize, Debug)] diff --git a/src/model/property_catalogue.rs b/src/model/property_catalogue.rs index 8507ea5..341b7ec 100644 --- a/src/model/property_catalogue.rs +++ b/src/model/property_catalogue.rs @@ -52,6 +52,15 @@ pub struct PropertyCatalogue { ordner: Ordner, } +impl PropertyCatalogue { + pub fn to_listed_string(&self) -> String { + format!( + "Merkmalskatalog '{}' in Revision '{}'", + self.name, self.revision + ) + } +} + #[derive(Serialize, Deserialize, Debug)] #[serde(deny_unknown_fields)] pub struct Versions { diff --git a/src/model/unterformular.rs b/src/model/unterformular.rs index 66d5eb9..cf6bad9 100644 --- a/src/model/unterformular.rs +++ b/src/model/unterformular.rs @@ -22,6 +22,7 @@ * SOFTWARE. */ +use console::style; use serde::{Deserialize, Serialize}; use crate::model::Ordner; @@ -168,6 +169,21 @@ impl Unterformular { }) } } + + pub fn to_listed_string(&self) -> String { + if self.hat_unterformulare { + return format!( + "Unterformular '{}' in Revision '{}' {}", + self.name, + self.revision, + style("Unterformular mit Markierung 'hat Unterformulare'!").red() + ); + } + format!( + "Unterformular '{}' in Revision '{}'", + self.name, self.revision + ) + } } #[derive(Serialize, Deserialize, Debug)]