Skip to content

Commit bf9676f

Browse files
committed
✨ Added styled module && Improved docs
1 parent b1c9780 commit bf9676f

File tree

7 files changed

+356
-65
lines changed

7 files changed

+356
-65
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "console-utils"
3-
version = "1.6.1"
3+
version = "1.7.0"
44
edition = "2021"
55
authors = ["Nils Wrenger <[email protected]>"]
66
description = "Simple CLI Input and Control Utilities"
@@ -14,7 +14,7 @@ license = "MIT"
1414
[lib]
1515

1616
[target.'cfg(unix)'.dependencies.libc]
17-
version = "0.2.169"
17+
version = "0.2.171"
1818

1919
[target.'cfg(windows)'.dependencies.windows-sys]
2020
version = "0.59.0"

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ To use Console Utils in your Rust project, you can add the following dependency
1616

1717
```toml
1818
[dependencies]
19-
console-utils = "1.6.1"
19+
console-utils = "1.7.0"
2020
```
2121

2222
After adding the dependency, you can import the modules you need in your Rust code. For example:
@@ -68,6 +68,21 @@ let selected_indices = multiselect("Select options:", &options);
6868
println!("Selected indices: {:?}", selected_indices);
6969
```
7070

71+
### Text styling
72+
73+
```rust
74+
use console_utils::styled::{StyledText, Color};
75+
76+
let text = StyledText::new("Hello, world!")
77+
.fg(Color::Red)
78+
.bg(Color::Black)
79+
.bold()
80+
.underline();
81+
82+
// Prints now a `Hello, world!` with red, bold and underlined text on a black background
83+
println!("{}", text);
84+
```
85+
7186
### Console Control
7287

7388
```rust
@@ -96,7 +111,7 @@ use console_utils::input::{spinner, SpinnerType};
96111
// Display a standard spinner for 3 seconds
97112
spinner(3.0, SpinnerType::Standard);
98113
// Display a custom spinner for 2 seconds
99-
spinner(2.0, SpinnerType::Custom(vec!["1", "2", "3", "4", "3", "2"]));
114+
spinner(2.0, SpinnerType::Custom(&["1", "2", "3", "4", "3", "2"]));
100115
```
101116

102117
### Gradual String Reveal

src/input.rs

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
use std::{io, str::FromStr, thread, time::Duration};
66

77
use crate::{
8-
control::*,
8+
control::{clear_line, flush, move_cursor_down, move_cursor_up, Visibility},
99
read::{read_key, Key},
10+
styled::{Color, StyledText},
1011
};
1112

1213
/// A Wrapper for empty inputs returning a None
@@ -51,15 +52,20 @@ where
5152
T::Err: std::fmt::Debug,
5253
{
5354
loop {
54-
print!("\x1b[31m?\x1b[0m {before} \x1b[90m›\x1b[0m ");
55+
let quest = StyledText::new("?").fg(Color::Red);
56+
let caret = StyledText::new("›").fg(Color::BrightBlack);
57+
print!("{quest} {before} {caret} ");
5558
flush();
5659

5760
let mut cli = String::new();
5861
io::stdin().read_line(&mut cli).unwrap();
5962

6063
match cli.parse() {
6164
Ok(value) => return value,
62-
Err(_) => println!("\n\x1b[31mX\x1b[0m Invalid Input Type\n"),
65+
Err(_) => {
66+
let x = StyledText::new("X").fg(Color::Red);
67+
println!("\n{x} Invalid Input Type\n")
68+
}
6369
}
6470
}
6571
}
@@ -82,7 +88,9 @@ pub fn select<'a>(before: &'a str, options: &'a [&'a str]) -> usize {
8288
let mut i = 0;
8389

8490
// print everything
85-
println!("\x1b[31m?\x1b[0m {before} \x1b[90m›\x1b[0m ");
91+
let quest = StyledText::new("?").fg(Color::Red);
92+
let caret = StyledText::new("›").fg(Color::BrightBlack);
93+
println!("{quest} {before} {caret} ");
8694

8795
populate(options, None, 0);
8896

@@ -140,7 +148,9 @@ pub fn multiselect(before: &str, options: &[&str]) -> Vec<bool> {
140148
let mut i = 0;
141149

142150
// print everything
143-
println!("\x1b[31m?\x1b[0m {before} \x1b[90m›\x1b[0m ");
151+
let quest = StyledText::new("?").fg(Color::Red);
152+
let caret = StyledText::new("›").fg(Color::BrightBlack);
153+
println!("{quest} {before} {caret} ");
144154

145155
populate(options, Some(&matrix), 0);
146156

@@ -185,22 +195,21 @@ pub fn multiselect(before: &str, options: &[&str]) -> Vec<bool> {
185195
matrix
186196
}
187197

188-
/// Populate function for multiselect
198+
/// Populate function for select/multiselect
189199
fn populate(options: &[&str], matrix: Option<&[bool]>, cursor: usize) {
190200
for (i, option) in options.iter().enumerate() {
191201
clear_line();
192202
if i == cursor {
193-
println!(
194-
"\x1b[36m ›\x1b[0m\x1b[3{}m {}\x1b[0m",
195-
if matrix.is_some() && matrix.unwrap()[i] {
196-
"2"
197-
} else {
198-
"6"
199-
},
200-
option
201-
);
203+
let caret = StyledText::new("›").fg(Color::Green);
204+
let option = if matrix.is_some() && matrix.unwrap()[i] {
205+
StyledText::new(option).fg(Color::Green)
206+
} else {
207+
StyledText::new(option).fg(Color::Cyan)
208+
};
209+
println!(" {caret} {option}");
202210
} else if matrix.is_some() && matrix.unwrap()[i] {
203-
println!("\x1b[32m {}\x1b[0m", option);
211+
let option = StyledText::new(option).fg(Color::Green);
212+
println!(" {}", option);
204213
} else {
205214
println!(" {}", option);
206215
}
@@ -211,27 +220,27 @@ fn populate(options: &[&str], matrix: Option<&[bool]>, cursor: usize) {
211220
/// Enumeration representing different types of spinners.
212221
#[derive(Debug, Clone)]
213222
pub enum SpinnerType {
223+
/// Spinner with characters `/` `-` `\` `|`.
214224
Standard,
225+
/// Spinner with dots `.` `..` `...` `.....`.
215226
Dots,
227+
/// Spinner with box characters `▌` `▀` `▐` `▄`.
216228
Box,
229+
/// Spinner with flip characters `_` `_` `_` `-` `\` `'` `´` `-` `_` `_` `_`.
217230
Flip,
218-
Custom(Vec<&'static str>),
231+
/// Custom spinner with user-defined frames.
232+
Custom(&'static [&'static str]),
219233
}
220234

221235
impl SpinnerType {
222-
/// Converts the spinner type to a vector of frames, gives back the following variants:
223-
/// - `SpinnerType::Standard`: Standard spinner with characters / - \ |.
224-
/// - `SpinnerType::Dots`: Spinner with dots . .. ... .....
225-
/// - `SpinnerType::Box`: Spinner with box characters ▌ ▀ ▐ ▄.
226-
/// - `SpinnerType::Flip`: Spinner with flip characters _ _ _ - \ ' ´ - _ _ _.
227-
/// - `SpinnerType::Custom(frames)`: Custom spinner with user-defined frames.
228-
pub fn to_frames(&self) -> Vec<&'static str> {
236+
/// Returns the frames of the spinner type.
237+
pub fn frames(&self) -> &'static [&'static str] {
229238
match self {
230-
SpinnerType::Standard => vec!["/", "-", "\\", "|"],
231-
SpinnerType::Dots => vec![".", "..", "...", "....", "...", ".."],
232-
SpinnerType::Box => vec!["▌", "▀", "▐", "▄"],
233-
SpinnerType::Flip => vec!["_", "_", "_", "-", "`", "`", "'", "´", "-", "_", "_", "_"],
234-
SpinnerType::Custom(frames) => frames.to_owned(),
239+
SpinnerType::Standard => &["/", "-", "\\", "|"],
240+
SpinnerType::Dots => &[".", "..", "...", "....", "...", ".."],
241+
SpinnerType::Box => &["▌", "▀", "▐", "▄"],
242+
SpinnerType::Flip => &["_", "_", "_", "-", "`", "`", "'", "´", "-", "_", "_", "_"],
243+
SpinnerType::Custom(frames) => frames,
235244
}
236245
}
237246
}
@@ -246,7 +255,7 @@ impl SpinnerType {
246255
/// - `time`: A floating-point number representing the duration of the spinner animation in seconds.
247256
/// - `spinner_type`: The type of spinner to display.
248257
pub fn spinner(mut time: f64, spinner_type: SpinnerType) {
249-
let frames = spinner_type.to_frames();
258+
let frames = spinner_type.frames();
250259
let mut i = 0;
251260

252261
while time > 0.0 {

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
pub mod control;
55
pub mod input;
66
pub mod read;
7+
pub mod styled;

src/read.rs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,32 @@
55
66
use std::io;
77

8-
/// # Key Enum
9-
///
10-
/// The `Key` enum represents different keyboard keys that can be captured by the
11-
/// `read_key` function.
12-
///
13-
/// - `ArrowUp`: Represents the arrow up key.
14-
/// - `ArrowDown`: Represents the arrow down key.
15-
/// - `ArrowRight`: Represents the arrow right key.
16-
/// - `ArrowLeft`: Represents the arrow left key.
17-
/// - `Enter`: Represents the Enter/Return key.
18-
/// - `Tab`: Represents the Tab key.
19-
/// - `Backspace`: Represents the Backspace key.
20-
/// - `Escape`: Represents the Escape key.
21-
/// - `Char(char)`: Represents any printable character on the keyboard.
8+
/// Represents different keyboard keys that can be captured by the `read_key` function.
229
#[derive(Debug, Clone, PartialEq, Eq)]
2310
pub enum Key {
11+
/// Arrow up key.
2412
ArrowUp,
13+
/// Arrow down key.
2514
ArrowDown,
15+
/// Arrow right key.
2616
ArrowRight,
17+
/// Arrow left key.
2718
ArrowLeft,
19+
/// Enter/Return key.
2820
Enter,
21+
/// Tab key.
2922
Tab,
23+
/// Backspace key.
3024
Backspace,
25+
/// Escape key.
3126
Escape,
27+
/// Any printable character on the keyboard.
3228
Char(char),
29+
/// Any unrecognized key.
3330
Unknown,
3431
}
3532

36-
/// # Read Key Function
37-
///
38-
/// The `read_key` function reads a single key event from the console input
39-
/// and returns a `Key` enum.
33+
/// Reads a single key event from the console input and returns a `Key` enum.
4034
pub fn read_key() -> io::Result<Key> {
4135
#[cfg(windows)]
4236
{
@@ -49,10 +43,8 @@ pub fn read_key() -> io::Result<Key> {
4943
}
5044
}
5145

52-
/// # Windows Module
53-
///
54-
/// The `windows` module contains Windows-specific implementation details for reading
55-
/// keyboard input. It utilizes the `windows-sys` crate to interact with Windows Console API.
46+
/// Contains Windows-specific implementation details for reading keyboard
47+
/// input. It utilizes the `windows-sys` crate to interact with Windows Console API.
5648
#[cfg(windows)]
5749
pub mod windows {
5850
use super::Key;
@@ -103,10 +95,8 @@ pub mod windows {
10395
}
10496
}
10597

106-
/// # Unix Module
107-
///
108-
/// The `unix` module contains Unix-specific implementation details for reading
109-
/// keyboard input. It uses the `libc` crate to manipulate terminal attributes.
98+
/// Contains Unix-specific implementation details for reading keyboard
99+
/// input. It uses the `libc` crate to manipulate terminal attributes.
110100
#[cfg(unix)]
111101
pub mod unix {
112102
use libc::{tcgetattr, tcsetattr, ECHO, ICANON, STDIN_FILENO, TCSANOW};
@@ -115,7 +105,7 @@ pub mod unix {
115105

116106
use super::Key;
117107

118-
// Internal function for disabling line buffering.
108+
// Disables line buffering.
119109
fn disable_line_buffering() -> io::Result<()> {
120110
let mut termios = unsafe { mem::zeroed() };
121111
if unsafe { tcgetattr(STDIN_FILENO, &mut termios) } != 0 {
@@ -131,7 +121,7 @@ pub mod unix {
131121
Ok(())
132122
}
133123

134-
// Internal function for enabling line buffering.
124+
// Enables line buffering.
135125
fn enable_line_buffering() -> io::Result<()> {
136126
let mut termios = unsafe { mem::zeroed() };
137127
if unsafe { tcgetattr(STDIN_FILENO, &mut termios) } != 0 {
@@ -147,7 +137,7 @@ pub mod unix {
147137
Ok(())
148138
}
149139

150-
// Internal function for reading a key from the console.
140+
// Reads a key from the console.
151141
pub(crate) fn read_key() -> io::Result<Key> {
152142
let mut buffer = [0; 3];
153143
disable_line_buffering()?;

0 commit comments

Comments
 (0)