decasify 0.7.6__tar.gz → 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,9 +37,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
37
37
 
38
38
  [[package]]
39
39
  name = "anstream"
40
- version = "0.6.15"
40
+ version = "0.6.17"
41
41
  source = "registry+https://github.com/rust-lang/crates.io-index"
42
- checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
42
+ checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
43
43
  dependencies = [
44
44
  "anstyle",
45
45
  "anstyle-parse",
@@ -52,36 +52,36 @@ dependencies = [
52
52
 
53
53
  [[package]]
54
54
  name = "anstyle"
55
- version = "1.0.8"
55
+ version = "1.0.9"
56
56
  source = "registry+https://github.com/rust-lang/crates.io-index"
57
- checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
57
+ checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
58
58
 
59
59
  [[package]]
60
60
  name = "anstyle-parse"
61
- version = "0.2.5"
61
+ version = "0.2.6"
62
62
  source = "registry+https://github.com/rust-lang/crates.io-index"
63
- checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
63
+ checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
64
64
  dependencies = [
65
65
  "utf8parse",
66
66
  ]
67
67
 
68
68
  [[package]]
69
69
  name = "anstyle-query"
70
- version = "1.1.1"
70
+ version = "1.1.2"
71
71
  source = "registry+https://github.com/rust-lang/crates.io-index"
72
- checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
72
+ checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
73
73
  dependencies = [
74
- "windows-sys 0.52.0",
74
+ "windows-sys 0.59.0",
75
75
  ]
76
76
 
77
77
  [[package]]
78
78
  name = "anstyle-wincon"
79
- version = "3.0.4"
79
+ version = "3.0.6"
80
80
  source = "registry+https://github.com/rust-lang/crates.io-index"
81
- checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
81
+ checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
82
82
  dependencies = [
83
83
  "anstyle",
84
- "windows-sys 0.52.0",
84
+ "windows-sys 0.59.0",
85
85
  ]
86
86
 
87
87
  [[package]]
@@ -213,9 +213,9 @@ dependencies = [
213
213
 
214
214
  [[package]]
215
215
  name = "clap_complete"
216
- version = "4.5.33"
216
+ version = "4.5.35"
217
217
  source = "registry+https://github.com/rust-lang/crates.io-index"
218
- checksum = "9646e2e245bf62f45d39a0f3f36f1171ad1ea0d6967fd114bca72cb02a8fcdfb"
218
+ checksum = "07a13ab5b8cb13dbe35e68b83f6c12f9293b2f601797b71bc9f23befdb329feb"
219
219
  dependencies = [
220
220
  "clap",
221
221
  ]
@@ -256,9 +256,9 @@ checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59"
256
256
 
257
257
  [[package]]
258
258
  name = "colorchoice"
259
- version = "1.0.2"
259
+ version = "1.0.3"
260
260
  source = "registry+https://github.com/rust-lang/crates.io-index"
261
- checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
261
+ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
262
262
 
263
263
  [[package]]
264
264
  name = "crc32fast"
@@ -306,7 +306,7 @@ dependencies = [
306
306
 
307
307
  [[package]]
308
308
  name = "decasify"
309
- version = "0.7.6"
309
+ version = "0.8.0"
310
310
  dependencies = [
311
311
  "anyhow",
312
312
  "assert_cmd",
@@ -317,6 +317,7 @@ dependencies = [
317
317
  "predicates",
318
318
  "pyo3",
319
319
  "regex",
320
+ "snafu",
320
321
  "strum",
321
322
  "strum_macros",
322
323
  "titlecase",
@@ -383,6 +384,12 @@ version = "1.0.5"
383
384
  source = "registry+https://github.com/rust-lang/crates.io-index"
384
385
  checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
385
386
 
387
+ [[package]]
388
+ name = "either"
389
+ version = "1.13.0"
390
+ source = "registry+https://github.com/rust-lang/crates.io-index"
391
+ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
392
+
386
393
  [[package]]
387
394
  name = "errno"
388
395
  version = "0.3.9"
@@ -1103,23 +1110,24 @@ dependencies = [
1103
1110
 
1104
1111
  [[package]]
1105
1112
  name = "mlua"
1106
- version = "0.9.9"
1113
+ version = "0.10.0"
1107
1114
  source = "registry+https://github.com/rust-lang/crates.io-index"
1108
- checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7"
1115
+ checksum = "0f6ddbd668297c46be4bdea6c599dcc1f001a129586272d53170b7ac0a62961e"
1109
1116
  dependencies = [
1110
1117
  "bstr",
1118
+ "either",
1111
1119
  "mlua-sys",
1112
1120
  "mlua_derive",
1113
1121
  "num-traits",
1114
- "once_cell",
1122
+ "parking_lot",
1115
1123
  "rustc-hash",
1116
1124
  ]
1117
1125
 
1118
1126
  [[package]]
1119
1127
  name = "mlua-sys"
1120
- version = "0.6.3"
1128
+ version = "0.6.4"
1121
1129
  source = "registry+https://github.com/rust-lang/crates.io-index"
1122
- checksum = "ebe026d6bd1583a9cf9080e189030ddaea7e6f5f0deb366a8e26f8a26c4135b8"
1130
+ checksum = "e9eebac25c35a13285456c88ee2fde93d9aee8bcfdaf03f9d6d12be3391351ec"
1123
1131
  dependencies = [
1124
1132
  "cc",
1125
1133
  "cfg-if",
@@ -1128,9 +1136,9 @@ dependencies = [
1128
1136
 
1129
1137
  [[package]]
1130
1138
  name = "mlua_derive"
1131
- version = "0.9.3"
1139
+ version = "0.10.0"
1132
1140
  source = "registry+https://github.com/rust-lang/crates.io-index"
1133
- checksum = "09697a6cec88e7f58a02c7ab5c18c611c6907c8654613df9cc0192658a4fb859"
1141
+ checksum = "2cfc5faa2e0d044b3f5f0879be2920e0a711c97744c42cf1c295cb183668933e"
1134
1142
  dependencies = [
1135
1143
  "proc-macro2",
1136
1144
  "quote",
@@ -1348,9 +1356,9 @@ dependencies = [
1348
1356
 
1349
1357
  [[package]]
1350
1358
  name = "regex"
1351
- version = "1.11.0"
1359
+ version = "1.11.1"
1352
1360
  source = "registry+https://github.com/rust-lang/crates.io-index"
1353
- checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
1361
+ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
1354
1362
  dependencies = [
1355
1363
  "aho-corasick",
1356
1364
  "memchr",
@@ -1514,6 +1522,27 @@ version = "1.13.2"
1514
1522
  source = "registry+https://github.com/rust-lang/crates.io-index"
1515
1523
  checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
1516
1524
 
1525
+ [[package]]
1526
+ name = "snafu"
1527
+ version = "0.8.5"
1528
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1529
+ checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019"
1530
+ dependencies = [
1531
+ "snafu-derive",
1532
+ ]
1533
+
1534
+ [[package]]
1535
+ name = "snafu-derive"
1536
+ version = "0.8.5"
1537
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1538
+ checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917"
1539
+ dependencies = [
1540
+ "heck",
1541
+ "proc-macro2",
1542
+ "quote",
1543
+ "syn",
1544
+ ]
1545
+
1517
1546
  [[package]]
1518
1547
  name = "strsim"
1519
1548
  version = "0.11.1"
@@ -1541,9 +1570,9 @@ dependencies = [
1541
1570
 
1542
1571
  [[package]]
1543
1572
  name = "syn"
1544
- version = "2.0.82"
1573
+ version = "2.0.85"
1545
1574
  source = "registry+https://github.com/rust-lang/crates.io-index"
1546
- checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021"
1575
+ checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
1547
1576
  dependencies = [
1548
1577
  "proc-macro2",
1549
1578
  "quote",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "decasify"
3
- version = "0.7.6"
3
+ version = "0.8.0"
4
4
  authors = ["Caleb Maclennan <caleb@alerque.com>"]
5
5
  edition = "2021"
6
6
  rust-version = "1.73.0"
@@ -23,12 +23,12 @@ required-features = ["cli"]
23
23
  [features]
24
24
  default = []
25
25
  full = ["cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh"]
26
- completions = ["cli", "clap_complete"]
27
- cli = ["clap"]
26
+ completions = ["cli", "dep:clap_complete"]
27
+ cli = ["dep:clap"]
28
28
  bash = ["completions"]
29
29
  elvish = ["completions"]
30
30
  fish = ["completions"]
31
- manpage = ["clap_mangen"]
31
+ manpage = ["dep:clap_mangen"]
32
32
  powershell = ["completions"]
33
33
  zsh = ["completions"]
34
34
  luamodule = []
@@ -37,17 +37,19 @@ lua53 = ["luamodule", "mlua/lua53"]
37
37
  lua52 = ["luamodule", "mlua/lua52"]
38
38
  lua51 = ["luamodule", "mlua/lua51"]
39
39
  luajit = ["luamodule", "mlua/luajit"]
40
- pythonmodule = ["pyo3"]
41
- wasm = ["wasm-bindgen"]
40
+ pythonmodule = ["dep:pyo3"]
41
+ unstable-trait = []
42
+ wasm = ["dep:wasm-bindgen"]
42
43
 
43
44
  [profile.release]
44
45
  lto = true
45
46
 
46
47
  [dependencies]
47
- regex = "1.10"
48
+ regex = "1.11"
49
+ snafu = "0.8"
48
50
  strum = "0.26"
49
51
  strum_macros = "0.26"
50
- unicode_titlecase = "2.3"
52
+ unicode_titlecase = "2.4"
51
53
 
52
54
  [dependencies.clap]
53
55
  version = "4.5"
@@ -55,7 +57,7 @@ unicode_titlecase = "2.3"
55
57
  features = ["derive", "wrap_help"]
56
58
 
57
59
  [dependencies.mlua]
58
- version = "0.9"
60
+ version = "0.10.0"
59
61
  optional = true
60
62
  features = ["module"]
61
63
 
@@ -73,6 +75,7 @@ unicode_titlecase = "2.3"
73
75
  optional = true
74
76
 
75
77
  [build-dependencies]
78
+ snafu = "0.8"
76
79
  strum = "0.26"
77
80
  strum_macros = "0.26"
78
81
 
@@ -104,6 +107,10 @@ predicates = "3.1"
104
107
  [lints.rust]
105
108
  unexpected_cfgs = { level = "warn", check-cfg = ['cfg(build)'] }
106
109
 
110
+ [package.metadata.docs.rs]
111
+ features = ["luamodule", "luajit", "pythonmodule", "wasm", "unstable-trait"]
112
+ rustdoc-args = ["--cfg", "docsrs"]
113
+
107
114
  [package.metadata.git-cliff.git]
108
115
  protect_breaking_commits = true
109
116
  commit_parsers = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: decasify
3
- Version: 0.7.6
3
+ Version: 0.8.0
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Natural Language :: English
@@ -54,15 +54,6 @@ The AP style is largely unimplemented.
54
54
 
55
55
  Contributions are welcome for better style guide support or further languages.
56
56
 
57
- ``` console
58
- $ decasify -l tr ILIK SU VE İTEN RÜZGARLAR
59
- Ilık Su ve İten Rüzgarlar
60
- $ echo ILIK SU VE İTEN RÜZGARLAR | decasify -l tr
61
- Ilık Su ve İten Rüzgarlar
62
- $ echo foo BAR AND baz: an alter ego | decasify -l en -s gruber
63
- Foo BAR and Baz: An Alter Ego
64
- ```
65
-
66
57
  [tdk]: https://tdk.gov.tr/icerik/yazim-kurallari/buyuk-harflerin-kullanildigi-yerler/
67
58
  [titlecase_crate]: https://crates.io/crates/titlecase
68
59
 
@@ -70,27 +61,23 @@ Foo BAR and Baz: An Alter Ego
70
61
 
71
62
  Use of the CLI is pretty simple.
72
63
  Input may be either shell arguments or STDIN.
64
+ Arguments can control the various options.
65
+ For full usage information check `decasify --help` or `man decasify`.
73
66
 
74
- ```console
75
- $ decasify --help
76
- A CLI tool to convert all-caps strings to title-case or other less aggressive tones that supports
77
- Turkish input
78
-
79
- Usage: decasify [OPTIONS] [INPUT]...
80
-
81
- Arguments:
82
- [INPUT]... Input string
83
-
84
- Options:
85
- -l, --locale <LOCALE> Locale [default: EN] [possible values: EN, TR]
86
- -c, --case <CASE> Target case [default: Title] [possible values: Lower, Sentence, Title,
87
- Upper]
88
- -s, --style <STYLE> Style Guide [possible values: ap, cmos, gruber]
89
- -h, --help Print help
90
- -V, --version Print version
67
+ ``` console
68
+ $ decasify -l tr ILIK SU VE İTEN RÜZGARLAR
69
+ Ilık Su ve İten Rüzgarlar
70
+
71
+ $ echo ILIK SU VE İTEN RÜZGARLAR | decasify -l tr
72
+ Ilık Su ve İten Rüzgarlar
73
+
74
+ $ echo foo BAR AND baz: an alter ego | decasify -l en -s gruber
75
+ Foo BAR and Baz: An Alter Ego
91
76
  ```
92
77
 
93
- First, check your distro for packages, e.g. for Arch Linux get it [from the AUR](https://aur.archlinux.org/packages/decasify).
78
+ ### Installation
79
+
80
+ To install, first check your distro for packages, e.g. for [Arch Linux](https://archlinux.org/packages/extra/x86_64/decasify/) just install via `pacman -S decasify`.
94
81
 
95
82
  Otherwise for many platforms you can run it directly or install it to a shell using Nix Flakes:
96
83
 
@@ -126,21 +113,21 @@ In your `Cargo.toml` file.
126
113
 
127
114
  ```toml
128
115
  [dependencies]
129
- decasify = "0.7"
116
+ decasify = "0.8"
130
117
  ```
131
118
 
132
119
  Then use the crate functions and types in your project something like this:
133
120
 
134
121
  ```rust
135
- use decasify::to_titlecase;
122
+ use decasify::titlecase;
136
123
  use decasify::{Locale, StyleGuide};
137
124
 
138
125
  fn demo() {
139
126
  let input = "ILIK SU VE İTEN RÜZGARLAR";
140
- let output = to_titlecase(input, Locale::TR, StyleGuide::LanguageDefault);
127
+ let output = titlecase(input, Locale::TR, StyleGuide::LanguageDefault);
141
128
  eprintln! {"{output}"};
142
129
  let input = "title with a twist: a colon";
143
- let output = to_titlecase(input, Locale::EN, StyleGuide::DaringFireball);
130
+ let output = titlecase(input, Locale::EN, StyleGuide::DaringFireball);
144
131
  eprintln! {"{output}"};
145
132
  }
146
133
  ```
@@ -32,15 +32,6 @@ The AP style is largely unimplemented.
32
32
 
33
33
  Contributions are welcome for better style guide support or further languages.
34
34
 
35
- ``` console
36
- $ decasify -l tr ILIK SU VE İTEN RÜZGARLAR
37
- Ilık Su ve İten Rüzgarlar
38
- $ echo ILIK SU VE İTEN RÜZGARLAR | decasify -l tr
39
- Ilık Su ve İten Rüzgarlar
40
- $ echo foo BAR AND baz: an alter ego | decasify -l en -s gruber
41
- Foo BAR and Baz: An Alter Ego
42
- ```
43
-
44
35
  [tdk]: https://tdk.gov.tr/icerik/yazim-kurallari/buyuk-harflerin-kullanildigi-yerler/
45
36
  [titlecase_crate]: https://crates.io/crates/titlecase
46
37
 
@@ -48,27 +39,23 @@ Foo BAR and Baz: An Alter Ego
48
39
 
49
40
  Use of the CLI is pretty simple.
50
41
  Input may be either shell arguments or STDIN.
42
+ Arguments can control the various options.
43
+ For full usage information check `decasify --help` or `man decasify`.
51
44
 
52
- ```console
53
- $ decasify --help
54
- A CLI tool to convert all-caps strings to title-case or other less aggressive tones that supports
55
- Turkish input
56
-
57
- Usage: decasify [OPTIONS] [INPUT]...
58
-
59
- Arguments:
60
- [INPUT]... Input string
61
-
62
- Options:
63
- -l, --locale <LOCALE> Locale [default: EN] [possible values: EN, TR]
64
- -c, --case <CASE> Target case [default: Title] [possible values: Lower, Sentence, Title,
65
- Upper]
66
- -s, --style <STYLE> Style Guide [possible values: ap, cmos, gruber]
67
- -h, --help Print help
68
- -V, --version Print version
45
+ ``` console
46
+ $ decasify -l tr ILIK SU VE İTEN RÜZGARLAR
47
+ Ilık Su ve İten Rüzgarlar
48
+
49
+ $ echo ILIK SU VE İTEN RÜZGARLAR | decasify -l tr
50
+ Ilık Su ve İten Rüzgarlar
51
+
52
+ $ echo foo BAR AND baz: an alter ego | decasify -l en -s gruber
53
+ Foo BAR and Baz: An Alter Ego
69
54
  ```
70
55
 
71
- First, check your distro for packages, e.g. for Arch Linux get it [from the AUR](https://aur.archlinux.org/packages/decasify).
56
+ ### Installation
57
+
58
+ To install, first check your distro for packages, e.g. for [Arch Linux](https://archlinux.org/packages/extra/x86_64/decasify/) just install via `pacman -S decasify`.
72
59
 
73
60
  Otherwise for many platforms you can run it directly or install it to a shell using Nix Flakes:
74
61
 
@@ -104,21 +91,21 @@ In your `Cargo.toml` file.
104
91
 
105
92
  ```toml
106
93
  [dependencies]
107
- decasify = "0.7"
94
+ decasify = "0.8"
108
95
  ```
109
96
 
110
97
  Then use the crate functions and types in your project something like this:
111
98
 
112
99
  ```rust
113
- use decasify::to_titlecase;
100
+ use decasify::titlecase;
114
101
  use decasify::{Locale, StyleGuide};
115
102
 
116
103
  fn demo() {
117
104
  let input = "ILIK SU VE İTEN RÜZGARLAR";
118
- let output = to_titlecase(input, Locale::TR, StyleGuide::LanguageDefault);
105
+ let output = titlecase(input, Locale::TR, StyleGuide::LanguageDefault);
119
106
  eprintln! {"{output}"};
120
107
  let input = "title with a twist: a colon";
121
- let output = to_titlecase(input, Locale::EN, StyleGuide::DaringFireball);
108
+ let output = titlecase(input, Locale::EN, StyleGuide::DaringFireball);
122
109
  eprintln! {"{output}"};
123
110
  }
124
111
  ```
@@ -36,6 +36,9 @@ fn main() -> AnyhowResult<()> {
36
36
  if let Ok(val) = env::var("VERSION_FROM_AUTOTOOLS") {
37
37
  println!("cargo:rustc-env=VERGEN_GIT_DESCRIBE={val}");
38
38
  builder.add_instructions(&RustcBuilder::all_rustc()?)?;
39
+ } else if let Ok(val) = env::var("LUA_ROCKSPEC_VERSION") {
40
+ println!("cargo:rustc-env=VERGEN_GIT_DESCRIBE=v{val}");
41
+ builder.add_instructions(&RustcBuilder::all_rustc()?)?;
39
42
  } else {
40
43
  builder.add_instructions(&GixBuilder::all_git()?)?;
41
44
  };
@@ -0,0 +1,88 @@
1
+ // SPDX-FileCopyrightText: © 2023 Caleb Maclennan <caleb@alerque.com>
2
+ // SPDX-License-Identifier: LGPL-3.0-only
3
+
4
+ use decasify::cli::Cli;
5
+ use decasify::{lowercase, sentencecase, titlecase, uppercase};
6
+ use decasify::{Case, Locale, StyleGuide};
7
+
8
+ use snafu::prelude::*;
9
+
10
+ use clap::CommandFactory;
11
+ use std::io;
12
+ use std::io::BufRead;
13
+
14
+ #[derive(Snafu)]
15
+ enum Error {
16
+ #[snafu(display("Failed to identify input"))]
17
+ Input {},
18
+
19
+ #[snafu(display("Failed to resolve a known locale"))]
20
+ Locale {},
21
+
22
+ #[snafu(display("Failed to resolve a known case"))]
23
+ Case {},
24
+
25
+ #[snafu(display("Failed to resolve a known style guide"))]
26
+ StyleGuide {},
27
+ }
28
+
29
+ // Clap CLI errors are reported using the Debug trait, but Snafu sets up the Display trait.
30
+ // So we delegate. c.f. https://github.com/shepmaster/snafu/issues/110
31
+ impl std::fmt::Debug for Error {
32
+ fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
33
+ std::fmt::Display::fmt(self, fmt)
34
+ }
35
+ }
36
+
37
+ type Result<T, E = Error> = std::result::Result<T, E>;
38
+
39
+ fn main() -> Result<()> {
40
+ let version = option_env!("VERGEN_GIT_DESCRIBE").unwrap_or_else(|| env!("CARGO_PKG_VERSION"));
41
+ let app = Cli::command().version(version);
42
+ let matches = app.get_matches();
43
+ let locale = matches.get_one::<Locale>("locale").context(LocaleSnafu)?;
44
+ let case = matches
45
+ .get_one::<Case>("case")
46
+ .context(CaseSnafu)?
47
+ .to_owned();
48
+ let style = matches
49
+ .get_one::<StyleGuide>("style")
50
+ .context(StyleGuideSnafu)?
51
+ .to_owned();
52
+ match matches.contains_id("input") {
53
+ true => {
54
+ let input: Vec<String> = matches
55
+ .get_many::<String>("input")
56
+ .context(InputSnafu)?
57
+ .cloned()
58
+ .collect();
59
+ let input: Vec<String> = vec![input.join(" ")];
60
+ process(input.iter().map(|ln| ln.to_string()), *locale, case, style);
61
+ }
62
+ false => process(
63
+ io::stdin().lock().lines().map(|ln| ln.unwrap()),
64
+ *locale,
65
+ case,
66
+ style,
67
+ ),
68
+ }
69
+ Ok(())
70
+ }
71
+
72
+ fn process<I: IntoIterator<Item = String>>(
73
+ strings: I,
74
+ locale: Locale,
75
+ case: Case,
76
+ style: StyleGuide,
77
+ ) {
78
+ for string in strings {
79
+ let output = match case {
80
+ Case::Title => titlecase(string, locale, style),
81
+ Case::Lower => lowercase(string, locale),
82
+ Case::Upper => uppercase(string, locale),
83
+ Case::Sentence => sentencecase(string, locale),
84
+ _ => unreachable!(),
85
+ };
86
+ println!("{output}")
87
+ }
88
+ }
@@ -0,0 +1,56 @@
1
+ // SPDX-FileCopyrightText: © 2023 Caleb Maclennan <caleb@alerque.com>
2
+ // SPDX-License-Identifier: LGPL-3.0-only
3
+
4
+ #[cfg(build)]
5
+ use crate::{Case, Locale, StyleGuide};
6
+
7
+ use clap::{builder, Parser};
8
+ use strum::VariantNames;
9
+
10
+ #[macro_export]
11
+ macro_rules! clap_enum_variants {
12
+ ($e: ty) => {{
13
+ use builder::TypedValueParser;
14
+ builder::PossibleValuesParser::new(<$e>::VARIANTS).map(|s| s.parse::<$e>().unwrap())
15
+ }};
16
+ }
17
+
18
+ /// Convert prose strings to other cases following locale specific rule sets.
19
+ ///
20
+ /// Can convert input in any supported language from any case to any other case.
21
+ #[derive(Parser, Debug)]
22
+ #[clap(author, bin_name = "decasify")]
23
+ pub struct Cli {
24
+ /// The locale of the input text
25
+ ///
26
+ /// Used to identify what language-specific handling needs to be done. This can affect how
27
+ /// individual Unicode characters are coveted to other cases as well as change which style
28
+ /// guides are considered.
29
+ #[clap(short, long, default_value_t, ignore_case = true, value_parser = clap_enum_variants!(Locale))]
30
+ pub locale: Locale,
31
+
32
+ /// The desired output case
33
+ ///
34
+ /// What case to convert to. Note the output *can* be affected by the input case, so in some
35
+ /// cases (pun intended) you may need to to either process twice or avoid doing so depending on
36
+ /// the expected result. For example title-casing in some English styles tries to preserve
37
+ /// capitalized acronyms, but lower-casing does not. First converting to lower-case then to
38
+ /// title-case would give a different result than directly to title-case.
39
+ #[clap(short, long, default_value_t, ignore_case = true, value_parser = clap_enum_variants!(Case))]
40
+ pub case: Case,
41
+
42
+ /// Proffered style guide
43
+ ///
44
+ /// For languages with more than one style guide, this picks which set of guidelines to follow.
45
+ /// Each language will have a default (typically the one we have the most robust implementation
46
+ /// for or implemented first).
47
+ #[clap(short, long, default_value_t, ignore_case = true, value_parser = clap_enum_variants!(StyleGuide))]
48
+ pub style: StyleGuide,
49
+
50
+ /// The input string or strings (note STDIN also accepted)
51
+ ///
52
+ /// Note that all input arguments are processed together joined with a space, and STDIN streams
53
+ /// are processed line by line. This can effect the output, for example if using sentence case
54
+ /// the input should be on a single line, not broken across several.
55
+ pub input: Vec<String>,
56
+ }
@@ -1,9 +1,10 @@
1
1
  // SPDX-FileCopyrightText: © 2023 Caleb Maclennan <caleb@alerque.com>
2
2
  // SPDX-License-Identifier: LGPL-3.0-only
3
3
 
4
- use crate::types::Result;
5
4
  use regex::Regex;
6
- use std::{borrow::Cow, error, fmt, fmt::Display, str::FromStr};
5
+ use std::{borrow::Cow, fmt, fmt::Display, str::FromStr};
6
+
7
+ use snafu::prelude::*;
7
8
 
8
9
  #[derive(Clone, Debug, PartialEq)]
9
10
  #[non_exhaustive]
@@ -12,12 +13,28 @@ pub enum Segment {
12
13
  Word(String),
13
14
  }
14
15
 
15
- #[derive(Debug, Clone)]
16
+ #[derive(Clone, Debug)]
16
17
  #[non_exhaustive]
17
18
  pub struct Chunk {
18
19
  pub segments: Vec<Segment>,
19
20
  }
20
21
 
22
+ #[derive(Snafu)]
23
+ pub enum Error {
24
+ #[snafu(display("Unable to cast str to Chunk"))]
25
+ StrToChunk {},
26
+ }
27
+
28
+ // Clap CLI errors are reported using the Debug trait, but Snafu sets up the Display trait.
29
+ // So we delegate. c.f. https://github.com/shepmaster/snafu/issues/110
30
+ impl std::fmt::Debug for Error {
31
+ fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
32
+ std::fmt::Display::fmt(self, fmt)
33
+ }
34
+ }
35
+
36
+ pub type Result<T, E = Error> = std::result::Result<T, E>;
37
+
21
38
  fn split_chunk(s: &str) -> Chunk {
22
39
  let mut segments: Vec<Segment> = Vec::new();
23
40
  let captures = Regex::new(r"(?<separator>\p{Whitespace}+)|(?<word>\P{Whitespace}+)").unwrap();
@@ -56,7 +73,7 @@ impl From<&Cow<'_, str>> for Chunk {
56
73
  }
57
74
 
58
75
  impl FromStr for Chunk {
59
- type Err = Box<dyn error::Error>;
76
+ type Err = Error;
60
77
  fn from_str(s: &str) -> Result<Self> {
61
78
  Ok(split_chunk(s))
62
79
  }