Skip to main content

libaki_mcycle/
lib.rs

1/*!
2the mark up text with cycling color program.
3
4# Features
5
6- mark up text with cycling color.
7- **Stateful Color Consistency**: Reuses the same color for identical matches within a 50-line window for better visual tracing.
8- minimum support rustc 1.68.0 (2c8cc3432 2023-03-06)
9
10# Key Feature: Stateful Color Consistency
11
12Unlike simple color cyclers, `aki-mcycle` remembers the color assigned to a specific match. If the same string appears again within a sliding window (default 50 lines), it reuses the same color. This provides excellent visual continuity when tracing identifiers or specific patterns in log files.
13
14# Performance
15
16`aki-mcycle` is designed for high-performance text processing. It efficiently handles large input streams and extremely long lines by using a sparse memory representation for color segments. This ensures minimal memory footprint even when processing single lines that span multiple megabytes, making it suitable for heavy-duty log analysis.
17
18# Command help
19
20```text
21aki-mcycle --help
22```
23
24```text
25Usage:
26  aki-mcycle [options]
27
28mark up text with the cyclic color.
29
30Options:
31  -e, --exp <exp>   write it in the cyclic color (default: ' ([0-9A-Z]{3,}):')
32
33  -H, --help        display this help and exit
34  -V, --version     display version information and exit
35
36Option Parameters:
37  <exp>     regular expression, color the entire match with the cyclic color.
38
39Environments:
40  AKI_MCYCLE_COLOR_SEQ_RED_ST       red start sequence specified by ansi
41  AKI_MCYCLE_COLOR_SEQ_GREEN_ST     green start sequence specified by ansi
42  AKI_MCYCLE_COLOR_SEQ_BLUE_ST      blue start sequence specified by ansi
43  AKI_MCYCLE_COLOR_SEQ_CYAN_ST      cyan start sequence specified by ansi
44  AKI_MCYCLE_COLOR_SEQ_MAGENTA_ST   magenta start sequence specified by ansi
45  AKI_MCYCLE_COLOR_SEQ_YELLOW_ST    yellow start sequence specified by ansi
46  AKI_MCYCLE_COLOR_SEQ_ED           color end sequence specified by ansi
47```
48
49# Quick install
50
511. you can install this into cargo bin path:
52
53```text
54cargo install aki-mcycle
55```
56
572. you can build debian package:
58
59```text
60cargo deb
61```
62
63and install **.deb** into your local repository of debian package.
64
65# Examples
66
67## Command line example 1
68
69Extract "`arm`" from the rustup target list and make "`linux-[^ ]+`" **color**.
70
71- 1st match: makes '`linux-musl`' **red**
72- 2nd match: makes '`linux-musleabi`' **green**
73- 3rd match: makes '`linux-musleabihf`' **blue**
74- 4th match: makes '`linux-muslabi64`' **cyan**
75
76```text
77rustup target list | aki-mline -e arm | aki-mcycle -e "linux-[^ ]+"
78```
79
80result output :
81
82![out rustup image]
83
84[out rustup image]: https://raw.githubusercontent.com/aki-akaguma/aki-mcycle/main/img/out-rustup-1.png
85
86- [aki-mline](https://crates.io/crates/aki-mline): extract match line command like grep.
87
88# Library example
89
90See [`fn execute()`] for this library examples.
91
92[`fn execute()`]: crate::execute
93
94*/
95#[macro_use]
96extern crate anyhow;
97
98pub mod conf;
99mod run;
100mod util;
101
102use flood_tide::HelpVersion;
103use runnel::*;
104
105const TRY_HELP_MSG: &str = "Try --help for help.";
106
107///
108/// execute mcycle
109///
110/// params:
111///   - sioe: stream in/out/err
112///   - program: program name. etc. "mcycle"
113///   - args: parameter arguments.
114///
115/// return:
116///   - ok: ()
117///   - err: anyhow
118///
119/// example:
120///
121/// ```
122/// use runnel::RunnelIoeBuilder;
123///
124/// let r = libaki_mcycle::execute(&RunnelIoeBuilder::new().build(),
125///     "mcycle", ["-e", "Message: *[^ ]+"]);
126/// ```
127///
128pub fn execute<I, S>(sioe: &RunnelIoe, prog_name: &str, args: I) -> anyhow::Result<()>
129where
130    I: IntoIterator<Item = S>,
131    S: AsRef<std::ffi::OsStr>,
132{
133    execute_with_env(sioe, prog_name, args, vec![("", "")])
134}
135
136///
137/// execute mcycle with environments
138///
139/// params:
140///   - sioe: stream in/out/err
141///   - program: program name. etc. "mcycle"
142///   - args: parameter arguments.
143///   - env: environments array.
144///
145/// return:
146///   - ok: ()
147///   - err: anyhow
148///
149/// example:
150///
151/// ```rust
152/// use runnel::RunnelIoeBuilder;
153///
154/// let r = libaki_mcycle::execute_with_env(&RunnelIoeBuilder::new().build(),
155///     "mcycle",
156///     ["-e", "Message: *[^ ]+"],
157///     vec![
158///         ("AKI_MCYCLE_COLOR_SEQ_RED_ST", "<R>"),
159///         ("AKI_MCYCLE_COLOR_SEQ_GREEN_ST", "<G>"),
160///         ("AKI_MCYCLE_COLOR_SEQ_BLUE_ST", "<B>"),
161///         ("AKI_MCYCLE_COLOR_SEQ_CYAN_ST", "<C>"),
162///         ("AKI_MCYCLE_COLOR_SEQ_MAGENTA_ST", "<M>"),
163///         ("AKI_MCYCLE_COLOR_SEQ_YELLOW_ST", "<Y>"),
164///         ("AKI_MCYCLE_COLOR_SEQ_ED","<E>"),
165///     ]
166/// );
167/// ```
168///
169pub fn execute_with_env<I, S, IKV, K, V>(
170    sioe: &RunnelIoe,
171    prog_name: &str,
172    args: I,
173    env: IKV,
174) -> anyhow::Result<()>
175where
176    I: IntoIterator<Item = S>,
177    S: AsRef<std::ffi::OsStr>,
178    IKV: IntoIterator<Item = (K, V)>,
179    K: AsRef<std::ffi::OsStr>,
180    V: AsRef<std::ffi::OsStr>,
181{
182    let args: Vec<String> = args
183        .into_iter()
184        .map(|s| s.as_ref().to_string_lossy().into_owned())
185        .collect();
186    let args_str: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
187    let env_cnf: conf::EnvConf = env.into();
188    //
189    match conf::parse_cmdopts(prog_name, &args_str) {
190        Ok(conf) => run::run(sioe, &conf, &env_cnf),
191        Err(errs) => {
192            if let Some(err) = errs.iter().find(|e| e.is_help() || e.is_version()) {
193                sioe.pg_out().write_line(err.to_string())?;
194                Ok(())
195            } else {
196                Err(anyhow!("{errs}\n{TRY_HELP_MSG}"))
197            }
198        }
199    }
200}