Skip to main content

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}