libaki_stats/lib.rs
1/*!
2output the statistics of text, like a wc of linux command.
3
4# Features
5
6- output the statistics of text, like a wc of linux command.
7- minimum support rustc 1.68.0 (2c8cc3432 2023-03-06)
8
9# Specifications
10
11## UTF-8 Only Support
12This tool is designed to process **UTF-8 encoded text** only. It does not support binary files or other character encodings. If non-UTF-8 data is encountered, the tool may return an error.
13
14## Byte Count Calculation
15Unlike the standard `wc` command, the byte count (`-b`, `--bytes`) provided by `aki-stats` **excludes line terminators** (such as `\n` or `\r\n`). It represents the total number of bytes of the actual text content within the lines.
16
17# Command help
18
19```text
20aki-stats --help
21```
22
23```text
24Usage:
25 aki-stats [options]
26
27output the statistics of text, like a wc of linux command.
28
29Options:
30 -a, --all output the all statistics of text
31 -b, --bytes output the byte counts
32 -c, --chars output the unicode character counts
33 -l, --lines output the line counts
34 -m, --max-line-bytes output the maximum byte counts of line
35 -w, --words output the word counts
36 --locale <loc> locale of number format: en, fr, ... posix
37 -?, --query <q> display available names of locale and exit
38
39 -H, --help display this help and exit
40 -V, --version display version information and exit
41
42Examples:
43 Outputs the line count:
44 echo -e "acbde fghi\njkln opqr" | aki-stats -l
45 Outputs the byte count:
46 echo -e "acbde fghi\njkln opqr" | aki-stats -b
47 Outputs the word count:
48 echo -e "acbde fghi\njkln opqr" | aki-stats -w
49```
50
51# Quick install
52
531. you can install this into cargo bin path:
54
55```text
56cargo install aki-stats
57```
58
592. you can build debian package:
60
61```text
62cargo deb
63```
64
65and install **.deb** into your local repository of debian package.
66
67# Examples
68
69## Example 1: the all statistics
70
71Output the all statistics of input text.
72
73command line:
74```text
75cat fixtures/sherlock.txt | aki-stats -a
76```
77
78result output:
79```text
80lines:"26", bytes:"1207", chars:"1207", words:"226", max:"83"
81```
82
83## Example 2: the line count
84
85Output the only line count.
86
87command line:
88```text
89cat fixtures/sherlock.txt | aki-stats -l
90```
91
92result output:
93```text
94lines:"26"
95```
96
97## Example 3: the byte count with locale en
98
99Output the only byte count.
100
101command line:
102```text
103cat fixtures/sherlock.txt | aki-stats -b --locale en
104```
105
106result output:
107```text
108bytes:"1,207"
109```
110
111# Library example
112
113See [`fn execute()`] for this library examples.
114
115[`fn execute()`]: crate::execute
116*/
117#[macro_use]
118extern crate anyhow;
119
120mod conf;
121mod run;
122mod util;
123
124use flood_tide::HelpVersion;
125use runnel::RunnelIoe;
126
127const TRY_HELP_MSG: &str = "Try --help for help.";
128
129/// execute stats
130///
131/// params:
132/// - sioe: stream in/out/err
133/// - program: program name. etc. "stats"
134/// - args: parameter arguments.
135///
136/// return:
137/// - ok: ()
138/// - err: anyhow
139///
140/// # Examples
141///
142/// ## Example 1: the all statistics
143///
144/// Output the all statistics of input text.
145///
146/// ```rust
147/// use runnel::RunnelIoeBuilder;
148///
149/// let r = libaki_stats::execute(&RunnelIoeBuilder::new().build(),
150/// "stats", ["-a"]);
151/// ```
152///
153/// ## Example 2: the line count
154///
155/// Output the only line count.
156///
157/// ```rust
158/// use runnel::RunnelIoeBuilder;
159///
160/// let r = libaki_stats::execute(&RunnelIoeBuilder::new().build(),
161/// "stats", ["-l"]);
162/// ```
163///
164pub fn execute<I, S>(sioe: &RunnelIoe, prog_name: &str, args: I) -> anyhow::Result<()>
165where
166 I: IntoIterator<Item = S>,
167 S: AsRef<std::ffi::OsStr>,
168{
169 let args: Vec<String> = args
170 .into_iter()
171 .map(|s| s.as_ref().to_string_lossy().into_owned())
172 .collect();
173 let args_str: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
174 //
175 match conf::parse_cmdopts(prog_name, &args_str) {
176 Ok(conf) => run::run(sioe, &conf),
177 Err(errs) => {
178 if let Some(err) = errs.iter().find(|e| e.is_help() || e.is_version()) {
179 sioe.pg_out().write_line(err.to_string())?;
180 Ok(())
181 } else {
182 Err(anyhow!("{errs}\n{TRY_HELP_MSG}"))
183 }
184 }
185 }
186}