16 Commits

Author SHA1 Message Date
ae8615aa3a Add extended description for deb packages 2023-09-19 16:52:03 +02:00
8e504df06d Update dependencies and mark as v0.4.0 2023-09-19 16:46:36 +02:00
2493a58e9c Add optional field 'Kontaktliste' to forms 2023-09-19 16:41:09 +02:00
b3054f971e Package deb package containing bash completion 2023-09-04 17:46:55 +02:00
e27d31a8bf Use clap crate in version 4.4 2023-09-04 16:51:22 +02:00
d30c2991c0 Filter printed elements for list and tree sub command 2023-09-04 13:24:28 +02:00
ce8dca1c10 Use --sorted and --strip as options for productive use
This will keep old experimental options as alias.
2023-09-04 13:04:44 +02:00
bfa7cc3c6b Add sub command to calculate sha256 sum of an OSC file 2023-09-03 18:49:28 +02:00
9256e242eb Allow (actual) unused option 2023-09-03 18:40:43 +02:00
e33b1a3a4c Do not list form references twice as dataform and unterformular 2023-09-03 18:14:06 +02:00
42cbb9ce7e Combine matches to produce the same string 2023-09-03 18:06:56 +02:00
8edd50feb4 Show form references using tree sub command 2023-09-03 17:31:38 +02:00
31eda3efc9 Show notice if form has no field to be used as procedure date
This indicates that the form cannot be used as main form, but as subform only.
2023-09-03 14:03:31 +02:00
54cea88486 Inline additional information about subform mark 2023-09-03 13:58:28 +02:00
4040c49521 Update link to example files 2023-09-01 19:50:25 +02:00
e0b16c16d4 Remove xml-rs and update dependencies 2023-09-01 19:50:22 +02:00
12 changed files with 549 additions and 82 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.idea/* .idea/*
/target /target
/completion
*.iml *.iml

264
Cargo.lock generated
View File

@@ -3,37 +3,116 @@
version = 3 version = 3
[[package]] [[package]]
name = "anstyle" name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anstyle"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
[[package]]
name = "async-trait"
version = "0.1.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.4.1" version = "4.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c8d502cbaec4595d2e7d5f61e318f05417bd2b66fdc3809498f0d3fdf0bea27" checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
"once_cell",
] ]
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.4.1" version = "4.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5891c7bc0edb3e1c2204fc5e94009affabeb1821c9e5fdc3959536c5c0bb984d" checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"clap_lex", "clap_lex",
] ]
[[package]] [[package]]
name = "clap_derive" name = "clap_complete"
version = "4.4.0" version = "4.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a" checksum = "4110a1e6af615a9e6d0a36f805d5c99099f8bab9b8042f5bc1fa220a4a89e36f"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@@ -60,6 +139,35 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "cpufeatures"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]] [[package]]
name = "encode_unicode" name = "encode_unicode"
version = "0.3.6" version = "0.3.6"
@@ -72,6 +180,22 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "gimli"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.0" version = "0.14.0"
@@ -84,6 +208,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.0.0" version = "2.0.0"
@@ -108,39 +238,58 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.147" version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.6.2" version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]] [[package]]
name = "once_cell" name = "miniz_oxide"
version = "1.18.0" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "osc-variant" name = "osc-variant"
version = "0.3.0" version = "0.4.0"
dependencies = [ dependencies = [
"clap", "clap",
"clap_complete",
"console", "console",
"quick-xml", "quick-xml",
"serde", "serde",
"serde_yaml", "serde_yaml",
"xml-rs", "sha256",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "pin-project-lite"
version = "1.0.66" version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "proc-macro2"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@@ -164,6 +313,12 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.15" version = "1.0.15"
@@ -204,10 +359,34 @@ dependencies = [
] ]
[[package]] [[package]]
name = "syn" name = "sha2"
version = "2.0.29" version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha256"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386"
dependencies = [
"async-trait",
"bytes",
"hex",
"sha2",
"tokio",
]
[[package]]
name = "syn"
version = "2.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -215,10 +394,27 @@ dependencies = [
] ]
[[package]] [[package]]
name = "unicode-ident" name = "tokio"
version = "1.0.11" version = "1.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
dependencies = [
"backtrace",
"bytes",
"pin-project-lite",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
@@ -232,6 +428,12 @@ version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.45.0" version = "0.45.0"
@@ -297,9 +499,3 @@ name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "xml-rs"
version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1"

View File

@@ -1,19 +1,25 @@
[package] [package]
name = "osc-variant" name = "osc-variant"
version = "0.3.0" version = "0.4.0"
edition = "2021" edition = "2021"
authors = ["Paul-Christian Volkmer <volkmer_p@ukw.de>"] authors = ["Paul-Christian Volkmer <volkmer_p@ukw.de>"]
description = "Anwendung zum Anpassen einer OSC-Datei an einen Standort" description = "Anwendung zum Anpassen einer OSC-Datei an einen Standort"
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
build = "build.rs"
[dependencies] [dependencies]
clap = { version = "4.3", features = ["std", "help", "usage", "derive", "error-context"], default-features = false } clap = { version = "4.4", features = ["std", "help", "usage", "derive", "error-context"], default-features = false }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9" serde_yaml = "0.9"
quick-xml = { version = "0.30", features = ["escape-html", "serialize"], default-features = false } quick-xml = { version = "0.30", features = ["escape-html", "serialize"], default-features = false }
xml-rs = "0.8"
console = "0.15" console = "0.15"
sha256 = "1.4"
[build-dependencies]
clap = { version = "4.4", features = ["std", "help", "usage", "derive", "error-context"], default-features = false }
clap_complete = "4.4"
[profile.release] [profile.release]
opt-level = "s" opt-level = "s"
@@ -24,3 +30,7 @@ panic = "abort"
[package.metadata.deb] [package.metadata.deb]
copyright = "Copyright (c) 2023 Comprehensive Cancer Center Mainfranken" copyright = "Copyright (c) 2023 Comprehensive Cancer Center Mainfranken"
extended-description = "Anwendung zum Anpassen einer OSC-Datei an einen Standort."
assets = [
["completion/osc-variant.bash", "etc/bash_completion.d/", "644"]
]

View File

@@ -16,6 +16,13 @@ unvollständigen Ausgabedateien zu erzeugen.
### Beispiele ### Beispiele
Das Berechnen der SHA256 Prüfsumme ist mit dem Unterbefehl `sha256sum` auch unter Windows einfach möglich
und erzeugt eine Ausgabe analog dem Befehl auf Linux-Systemen:
```
osc-variant sha256sum meine-beispieldatei.osc
```
Zum Auflisten der Inhalte einer Datei wird folgender Befehl verwendet: Zum Auflisten der Inhalte einer Datei wird folgender Befehl verwendet:
``` ```
@@ -62,25 +69,24 @@ Ohne eine Angabe der Ausgabedatei wird auf die Standardausgabe ausgegeben.
OSC-Dateien sind XML-Dateien. Diese Anwendung ermöglicht optional die Ausgabe als kompaktere XML-Datei ohne Zeilenumbrüche. OSC-Dateien sind XML-Dateien. Diese Anwendung ermöglicht optional die Ausgabe als kompaktere XML-Datei ohne Zeilenumbrüche.
Hierzu ist die Option `--compact` vorgesehen. Es können, je nach Datei, bis zu 30% eingespart werden. Hierzu ist die Option `--compact` vorgesehen. Es können, je nach Datei, bis zu 30% eingespart werden.
#### Filter
Bei der Auflistung von Inhalten ist es möglich, die Ausgaben anhand des Namens zu filtern.
Hierzu ist die Option `--filter=` vorgesehen.
Wird diese angewendet, werden nur Inhalte ausgegeben, deren Name die angegebene Zeichenkette beinhalten.
#### Sortierung #### Sortierung
Bei der Auflistung der Inhalte, kann die Option `--sorted` dazu verwendet werden, die angezeigten Einträge alphabetisch zu sortieren. Bei der Auflistung der Inhalte, kann die Option `--sorted` dazu verwendet werden, die angezeigten Einträge alphabetisch zu sortieren.
Die Sortierung erfolgt dabei nach Namen des Katalogs oder des Formulars. Die Sortierung erfolgt dabei nach Namen des Katalogs oder des Formulars.
#### Experimentelle Funktionen Beim Modifizieren der Inhalte kann ebenfalls die Option `--sorted` dazu verwendet werden, die Einträge im Anschluss an die Modifikation
Neben den gebräuchlichen Funktionen gibt es weitere, derzeit noch experimentelle, Funktionen.
##### Sortierung bei Modifikation
Beim Modifizieren der Inhalte kann die experimentelle Option `--x-sorted` dazu verwendet werden, die Einträge im Anschluss an die Modifikation
nach Namen zu sortieren. nach Namen zu sortieren.
Dies erlaubt eine konsistente Reihenfolge der Einträge, wodurch ein direkter Vergleich mit Vorversionen ermöglicht wird. Dies erlaubt eine konsistente Reihenfolge der Einträge, wodurch ein direkter Vergleich mit Vorversionen ermöglicht wird.
ACHTUNG: Es kann sein, dass dadurch ein Import der resultierenden OSC-Datei nicht mehr möglich ist, da das genaue Verhalten des Imports aktuell noch nicht bekannt ist.
##### Entfernen von Inhalten der Systembibliothek bei Modifikation ##### Entfernen von Inhalten der Systembibliothek bei Modifikation
Mit der die experimentelle Option `--x-strip` ist es möglich, die in der OSC-Datei enthaltenen und beim Import nicht genutzten Inhalte aus der Systembibliothek zu entfernen. Mit der die experimentelle Option `--strip` ist es möglich, die in der OSC-Datei enthaltenen und beim Import nicht genutzten Inhalte aus der Systembibliothek zu entfernen.
Hierbei werden alle Inhalte entfernt, die im Ordner "ONKOSTAR Bibliothek" enthalten sind, beim Import jedoch ignoriert werden. Hierbei werden alle Inhalte entfernt, die im Ordner "ONKOSTAR Bibliothek" enthalten sind, beim Import jedoch ignoriert werden.
@@ -137,4 +143,4 @@ Wird sie angeben, sind die Felder `name`, `position` und `column` verpflichtend.
Es können beliebig viele Formulare mit beliebig vielen Änderungen zu Formularverweisen in einer Profildatei Es können beliebig viele Formulare mit beliebig vielen Änderungen zu Formularverweisen in einer Profildatei
hinterlegt werden, jedoch ist mindestens eine Angabe zu einem Formularfeld erforderlich. hinterlegt werden, jedoch ist mindestens eine Angabe zu einem Formularfeld erforderlich.
Beispiele für eine Profildatei sind unter [`examples/`](examples/) zu finden. Beispiele für eine Profildatei sind unter [`examples/`](/examples) zu finden.

44
build.rs Normal file
View File

@@ -0,0 +1,44 @@
/*
* MIT License
*
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
use std::fs;
use std::io::Error;
use clap_complete::generate_to;
use clap_complete::Shell::Bash;
include!("src/cli.rs");
fn main() -> Result<(), Error> {
let mut cmd = build_cli();
let package_name = std::env::var("CARGO_CRATE_NAME").unwrap_or("osc-variant".to_string());
fs::remove_dir_all("completion")?;
fs::create_dir("completion")?;
generate_to(Bash, &mut cmd, package_name.as_str(), "completion")?;
Ok(())
}

View File

@@ -22,18 +22,28 @@
* SOFTWARE. * SOFTWARE.
*/ */
use clap::{Parser, Subcommand}; use clap::{Command, CommandFactory, Parser, Subcommand};
#[allow(dead_code)]
fn build_cli() -> Command {
Cli::command()
}
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
#[command(propagate_version = true, arg_required_else_help(true))] #[command(propagate_version = true, arg_required_else_help(true))]
pub struct Cli { pub struct Cli {
#[command(subcommand)] #[command(subcommand)]
pub command: Command, pub cmd: SubCommand,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
pub enum Command { pub enum SubCommand {
#[command(
name = "sha256sum",
about = "Berechne SHA256 Prüfsumme für die angegebene Datei"
)]
Sha256Sum { inputfile: String },
#[command(about = "Zeigt alle enthaltenen Kataloge und Formulare mit Revision an.")] #[command(about = "Zeigt alle enthaltenen Kataloge und Formulare mit Revision an.")]
List { List {
inputfile: String, inputfile: String,
@@ -42,6 +52,8 @@ pub enum Command {
help = "Sortiere Kataloge und Formulare nach Name (Optional)" help = "Sortiere Kataloge und Formulare nach Name (Optional)"
)] )]
sorted: bool, sorted: bool,
#[arg(long = "filter", help = "Filtere Ausgabe nach Name (Optional)")]
filter: Option<String>,
}, },
#[command(about = "Zeigt Kataloge und Formulare mit Revision und Abhängigkeiten an.")] #[command(about = "Zeigt Kataloge und Formulare mit Revision und Abhängigkeiten an.")]
Tree { Tree {
@@ -51,6 +63,8 @@ pub enum Command {
help = "Sortiere Kataloge und Formulare nach Name (Optional)" help = "Sortiere Kataloge und Formulare nach Name (Optional)"
)] )]
sorted: bool, sorted: bool,
#[arg(long = "filter", help = "Filtere Ausgabe nach Name (Optional)")]
filter: Option<String>,
}, },
#[command(about = "Modifiziert die angegebene Datei anhand der Profildatei")] #[command(about = "Modifiziert die angegebene Datei anhand der Profildatei")]
Modify { Modify {
@@ -62,13 +76,15 @@ pub enum Command {
#[arg(long = "compact", help = "Kompakte Ausgabe, ohne Einrücken (Optional)")] #[arg(long = "compact", help = "Kompakte Ausgabe, ohne Einrücken (Optional)")]
compact: bool, compact: bool,
#[arg( #[arg(
long = "x-sorted", long = "sorted",
help = "EXPERIMENTELL: Sortiere Kataloge und Formulare nach Name (Optional).\nKann negative Auswirkungen auf den ordnungsgemäßen Import haben." alias = "x-sorted",
help = "Sortiere Kataloge und Formulare nach Name (Optional)."
)] )]
sorted: bool, sorted: bool,
#[arg( #[arg(
long = "x-strip", long = "strip",
help = "EXPERIMENTELL: Entferne Einträge aus der Systembibliothek die nicht importiert werden (Optional).\nKann negative Auswirkungen auf den ordnungsgemäßen Import haben." alias = "x-strip",
help = "Entferne Einträge aus der Systembibliothek die nicht importiert werden (Optional)."
)] )]
strip: bool, strip: bool,
}, },

View File

@@ -28,14 +28,16 @@ use std::fs;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::Write; use std::io::Write;
use std::ops::Add; use std::ops::Add;
use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use clap::Parser; use clap::Parser;
use console::style; use console::style;
use quick_xml::se::Serializer; use quick_xml::se::Serializer;
use serde::Serialize; use serde::Serialize;
use sha256::digest;
use crate::cli::{Cli, Command}; use crate::cli::{Cli, SubCommand};
use crate::model::onkostar_editor::OnkostarEditor; use crate::model::onkostar_editor::OnkostarEditor;
use crate::profile::Profile; use crate::profile::Profile;
@@ -109,22 +111,38 @@ fn read_profile(filename: String) -> Result<Profile, FileError> {
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let cli = Cli::parse(); let cli = Cli::parse();
match cli.command { match cli.cmd {
Command::List { inputfile, sorted } => { SubCommand::List {
inputfile,
sorted,
filter,
} => {
let mut data = read_inputfile(inputfile)?; let mut data = read_inputfile(inputfile)?;
if sorted { if sorted {
data.sorted() data.sorted()
} }
if let Some(name) = filter {
OnkostarEditor::print_list_filtered(&mut data, name.as_str());
return Ok(());
}
data.print_list(); data.print_list();
} }
Command::Tree { inputfile, sorted } => { SubCommand::Tree {
inputfile,
sorted,
filter,
} => {
let mut data = read_inputfile(inputfile)?; let mut data = read_inputfile(inputfile)?;
if sorted { if sorted {
data.sorted() data.sorted()
} }
if let Some(name) = filter {
OnkostarEditor::print_tree_filtered(&mut data, name.as_str());
return Ok(());
}
OnkostarEditor::print_tree(&data); OnkostarEditor::print_tree(&data);
} }
Command::Modify { SubCommand::Modify {
inputfile, inputfile,
profile, profile,
outputfile, outputfile,
@@ -175,7 +193,7 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
} }
} }
Command::Diff { SubCommand::Diff {
inputfile_a, inputfile_a,
inputfile_b, inputfile_b,
strict, strict,
@@ -191,6 +209,24 @@ fn main() -> Result<(), Box<dyn Error>> {
data_a.print_diff(data_b, strict); data_a.print_diff(data_b, strict);
} }
SubCommand::Sha256Sum { inputfile } => {
match fs::read_to_string(inputfile.clone()) {
Ok(content) => {
println!(
"{} {}",
digest(content).as_str(),
PathBuf::from(inputfile.clone())
.canonicalize()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
)
}
Err(err) => {
eprintln!("{}", FileError::Reading(inputfile, err.to_string()));
}
};
}
}; };
Ok(()) Ok(())

View File

@@ -127,10 +127,10 @@ impl Requires for DataCatalogue {
.iter() .iter()
.map(|entry| match entry { .map(|entry| match entry {
Requirement::PropertyCatalogue(_) => { Requirement::PropertyCatalogue(_) => {
Some(format!(" + {}\n", entry.to_string())) Some(format!(" - {}\n", entry.to_string()))
} }
Requirement::ExternalPropertyCatalogue(_) => { Requirement::ExternalPropertyCatalogue(_) => {
Some(format!(" + {}\n", entry.to_string())) Some(format!(" - {}\n", entry.to_string()))
} }
_ => None, _ => None,
}) })

View File

@@ -192,13 +192,25 @@ impl FormEntryContainer for DataForm {
impl Listable for DataForm { impl Listable for DataForm {
fn to_listed_string(&self) -> String { fn to_listed_string(&self) -> String {
format!( format!(
"Formular ({}) '{}' in Revision '{}'", "Formular ({}) '{}' in Revision '{}' {}",
match self.is_system_library_content() { match self.is_system_library_content() {
true => style("S").yellow(), true => style("S").yellow(),
_ => style("u"), _ => style("u"),
}, },
style(&self.name).yellow(), style(&self.name).yellow(),
style(&self.revision).yellow() style(&self.revision).yellow(),
if self
.entries
.entry
.iter()
.filter(|entry| entry.procedure_date_status != "none")
.count()
== 0
{
style("Formular hat keine Angabe zum Prozedurdatum!").red()
} else {
style("")
}
) )
} }
} }
@@ -244,7 +256,8 @@ impl Comparable for DataForm {
impl Requires for DataForm { impl Requires for DataForm {
fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement> { fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement> {
self.data_catalogues let mut result = self
.data_catalogues
.data_catalogue .data_catalogue
.iter() .iter()
.collect::<HashSet<_>>() .collect::<HashSet<_>>()
@@ -253,7 +266,30 @@ impl Requires for DataForm {
Some(contained) => Requirement::DataCatalogue(contained), Some(contained) => Requirement::DataCatalogue(contained),
None => Requirement::ExternalDataCatalogue(entry.to_string()), None => Requirement::ExternalDataCatalogue(entry.to_string()),
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>();
let referenced_forms = &mut self
.entries
.entry
.iter()
.filter(|&entry| entry.get_type() == "formReference")
.filter_map(|entry| match &entry.referenced_data_form {
Some(name) => Some(name),
None => None,
})
.collect::<HashSet<_>>()
.into_iter()
.map(|entry| match all.find_data_form(entry.as_str()) {
Some(contained) => Requirement::DataFormReference(contained),
None => match all.find_unterformular(entry.as_str()) {
Some(contained) => Requirement::UnterformularReference(contained),
None => Requirement::ExternalUnterformularReference(entry.to_string()),
},
})
.collect::<Vec<_>>();
result.append(referenced_forms);
result
} }
fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String { fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String {
@@ -289,6 +325,12 @@ impl Requires for DataForm {
Requirement::ExternalDataCatalogue(_) => { Requirement::ExternalDataCatalogue(_) => {
Some(format!(" + {}\n", entry.to_string())) Some(format!(" + {}\n", entry.to_string()))
} }
Requirement::DataFormReference(_)
| Requirement::ExternalDataFormReference(_)
| Requirement::UnterformularReference(_)
| Requirement::ExternalUnterformularReference(_) => {
Some(format!(" > {}\n", entry.to_string()))
}
_ => None, _ => None,
}) })
.filter(Option::is_some) .filter(Option::is_some)
@@ -486,6 +528,8 @@ pub struct Entry {
direction_pat_modul: String, direction_pat_modul: String,
#[serde(rename = "SeitenumbruchPatModul")] #[serde(rename = "SeitenumbruchPatModul")]
seitenumbruch_pat_modul: bool, seitenumbruch_pat_modul: bool,
#[serde(rename = "Kontaktliste")]
kontaktliste: Option<String>,
#[serde(rename = "MarkierungIgnorieren")] #[serde(rename = "MarkierungIgnorieren")]
markierung_ignorieren: bool, markierung_ignorieren: bool,
#[serde(rename = "SucheArt")] #[serde(rename = "SucheArt")]

View File

@@ -74,6 +74,32 @@ impl OnkostarEditor {
} }
} }
pub fn find_data_form<'a>(&'a self, name: &str) -> Option<&'a DataForm> {
match self
.editor
.data_form
.iter()
.filter(|&item| item.get_name().eq_ignore_ascii_case(name))
.nth(0)
{
Some(x) => Some(x),
_ => None,
}
}
pub fn find_unterformular<'a>(&'a self, name: &str) -> Option<&'a Unterformular> {
match self
.editor
.unterformular
.iter()
.filter(|&item| item.get_name().eq_ignore_ascii_case(name))
.nth(0)
{
Some(x) => Some(x),
_ => None,
}
}
pub fn apply_profile(&mut self, profile: &Profile) { pub fn apply_profile(&mut self, profile: &Profile) {
self.editor self.editor
.data_form .data_form
@@ -104,6 +130,37 @@ impl OnkostarEditor {
Self::print_items("Unterformulare", &self.editor.unterformular); Self::print_items("Unterformulare", &self.editor.unterformular);
} }
fn filter_by_name_contains(&mut self, name: &str) {
self.editor
.property_catalogue
.retain(|e| e.get_name().contains(name));
self.editor
.data_catalogue
.retain(|e| e.get_name().contains(name));
self.editor
.data_form
.retain(|e| e.get_name().contains(name));
self.editor
.unterformular
.retain(|e| e.get_name().contains(name));
}
pub fn print_list_filtered(&mut self, name: &str) {
println!(
"Die Datei wurde am {} mit {} in Version {} erstellt.\n\nFolgende Inhalte für '{}' sind gespeichert",
style(&self.info_xml.datum_xml).yellow(),
style(&self.info_xml.name).yellow(),
style(&self.info_xml.version).yellow(),
name
);
self.filter_by_name_contains(name);
Self::print_items("Merkmalskataloge", &self.editor.property_catalogue);
Self::print_items("Datenkataloge", &self.editor.data_catalogue);
Self::print_items("Formulare", &self.editor.data_form);
Self::print_items("Unterformulare", &self.editor.unterformular);
}
fn print_items(title: &str, list: &[impl Listable]) { fn print_items(title: &str, list: &[impl Listable]) {
print!("\n{} {}", list.len(), style(title).underlined()); print!("\n{} {}", list.len(), style(title).underlined());
println!( println!(
@@ -128,6 +185,23 @@ impl OnkostarEditor {
self.print_items_tree("Unterformulare", &self.editor.unterformular); self.print_items_tree("Unterformulare", &self.editor.unterformular);
} }
pub fn print_tree_filtered(&mut self, name: &str) {
println!(
"Die Datei wurde am {} mit {} in Version {} erstellt.\n\nFolgende Inhalte für '{}' sind gespeichert",
style(&self.info_xml.datum_xml).yellow(),
style(&self.info_xml.name).yellow(),
style(&self.info_xml.version).yellow(),
name
);
self.filter_by_name_contains(name);
Self::print_items("Merkmalskataloge", &self.editor.property_catalogue);
self.print_items_tree("Datenkataloge", &self.editor.data_catalogue);
self.print_items_tree("Formulare", &self.editor.data_form);
self.print_items_tree("Unterformulare", &self.editor.unterformular);
}
fn print_items_tree(&self, title: &str, list: &[impl Requires]) { fn print_items_tree(&self, title: &str, list: &[impl Requires]) {
print!("\n{} {}", list.len(), style(title).underlined()); print!("\n{} {}", list.len(), style(title).underlined());
println!( println!(

View File

@@ -23,8 +23,10 @@
*/ */
use crate::model::data_catalogue::DataCatalogue; use crate::model::data_catalogue::DataCatalogue;
use crate::model::data_form::DataForm;
use crate::model::onkostar_editor::OnkostarEditor; use crate::model::onkostar_editor::OnkostarEditor;
use crate::model::property_catalogue::PropertyCatalogue; use crate::model::property_catalogue::PropertyCatalogue;
use crate::model::unterformular::Unterformular;
use crate::model::Listable; use crate::model::Listable;
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
@@ -33,6 +35,11 @@ pub enum Requirement<'a> {
DataCatalogue(&'a DataCatalogue), DataCatalogue(&'a DataCatalogue),
ExternalPropertyCatalogue(String), ExternalPropertyCatalogue(String),
ExternalDataCatalogue(String), ExternalDataCatalogue(String),
DataFormReference(&'a DataForm),
UnterformularReference(&'a Unterformular),
#[allow(dead_code)]
ExternalDataFormReference(String),
ExternalUnterformularReference(String),
} }
impl ToString for Requirement<'_> { impl ToString for Requirement<'_> {
@@ -46,6 +53,14 @@ impl ToString for Requirement<'_> {
Requirement::ExternalDataCatalogue(name) => { Requirement::ExternalDataCatalogue(name) => {
format!("Datenkatalog (-) '{}' - hier nicht enthalten", name) format!("Datenkatalog (-) '{}' - hier nicht enthalten", name)
} }
Requirement::DataFormReference(item) => item.to_listed_string(),
Requirement::UnterformularReference(item) => item.to_listed_string(),
Requirement::ExternalDataFormReference(name) => {
format!("Formular (-) '{}' - hier nicht enthalten", name)
}
Requirement::ExternalUnterformularReference(name) => {
format!("Unterformular (-) '{}' - hier nicht enthalten", name)
}
} }
} }
} }

View File

@@ -202,26 +202,19 @@ impl FormEntryContainer for Unterformular {
impl Listable for Unterformular { impl Listable for Unterformular {
fn to_listed_string(&self) -> String { fn to_listed_string(&self) -> String {
if self.hat_unterformulare {
return format!(
"Unterformular ({}) '{}' in Revision '{}' {}",
match self.is_system_library_content() {
true => style("S").yellow(),
_ => style("u"),
},
style(&self.name).yellow(),
style(&self.revision).yellow(),
style("Unterformular mit Markierung 'hat Unterformulare'!").red()
);
}
format!( format!(
"Unterformular ({}) '{}' in Revision '{}'", "Unterformular ({}) '{}' in Revision '{}' {}",
match self.is_system_library_content() { match self.is_system_library_content() {
true => style("S").yellow(), true => style("S").yellow(),
_ => style("u"), _ => style("u"),
}, },
style(&self.name).yellow(), style(&self.name).yellow(),
style(&self.revision).yellow() style(&self.revision).yellow(),
if self.hat_unterformulare {
style("Unterformular mit Markierung 'hat Unterformulare'!").red()
} else {
style("")
}
) )
} }
} }
@@ -267,7 +260,8 @@ impl Comparable for Unterformular {
impl Requires for Unterformular { impl Requires for Unterformular {
fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement> { fn get_required_entries<'a>(&'a self, all: &'a OnkostarEditor) -> Vec<Requirement> {
self.data_catalogues let mut result = self
.data_catalogues
.data_catalogue .data_catalogue
.iter() .iter()
.collect::<HashSet<_>>() .collect::<HashSet<_>>()
@@ -276,7 +270,30 @@ impl Requires for Unterformular {
Some(contained) => Requirement::DataCatalogue(contained), Some(contained) => Requirement::DataCatalogue(contained),
None => Requirement::ExternalDataCatalogue(entry.to_string()), None => Requirement::ExternalDataCatalogue(entry.to_string()),
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>();
let referenced_forms = &mut self
.entries
.entry
.iter()
.filter(|&entry| entry.get_type() == "formReference")
.filter_map(|entry| match &entry.referenced_data_form {
Some(name) => Some(name),
None => None,
})
.collect::<HashSet<_>>()
.into_iter()
.map(|entry| match all.find_data_form(entry.as_str()) {
Some(contained) => Requirement::DataFormReference(contained),
None => match all.find_unterformular(entry.as_str()) {
Some(contained) => Requirement::UnterformularReference(contained),
None => Requirement::ExternalUnterformularReference(entry.to_string()),
},
})
.collect::<Vec<_>>();
result.append(referenced_forms);
result
} }
fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String { fn to_requirement_string<'a>(&'a self, all: &'a OnkostarEditor) -> String {
@@ -311,6 +328,12 @@ impl Requires for Unterformular {
Requirement::ExternalDataCatalogue(_) => { Requirement::ExternalDataCatalogue(_) => {
Some(format!(" + {}\n", entry.to_string())) Some(format!(" + {}\n", entry.to_string()))
} }
Requirement::DataFormReference(_)
| Requirement::ExternalDataFormReference(_)
| Requirement::UnterformularReference(_)
| Requirement::ExternalUnterformularReference(_) => {
Some(format!(" > {}\n", entry.to_string()))
}
_ => None, _ => None,
}) })
.filter(Option::is_some) .filter(Option::is_some)
@@ -509,6 +532,8 @@ pub struct Entry {
direction_pat_modul: String, direction_pat_modul: String,
#[serde(rename = "SeitenumbruchPatModul")] #[serde(rename = "SeitenumbruchPatModul")]
seitenumbruch_pat_modul: bool, seitenumbruch_pat_modul: bool,
#[serde(rename = "Kontaktliste")]
kontaktliste: Option<String>,
#[serde(rename = "MarkierungIgnorieren")] #[serde(rename = "MarkierungIgnorieren")]
markierung_ignorieren: bool, markierung_ignorieren: bool,
#[serde(rename = "SucheArt")] #[serde(rename = "SucheArt")]