Skip to content

Commit bc63d31

Browse files
committed
Add support for custom piece sets
1 parent 4db3f0b commit bc63d31

File tree

2 files changed

+64
-81
lines changed

2 files changed

+64
-81
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ clap = { version = "4.5.4", features = ["derive"] }
1717
crossterm = "0.27.0"
1818
eyre = "0.6.12"
1919
rand = "0.8.5"
20+
unicode-segmentation = "1.11.0"
2021

2122
[features]
2223
default = ["alternate-screen"]

src/main.rs

+63-81
Original file line numberDiff line numberDiff line change
@@ -20,81 +20,31 @@ use std::{
2020
panic::{set_hook, take_hook},
2121
time::Duration,
2222
};
23+
use unicode_segmentation::UnicodeSegmentation;
24+
25+
/// Map of default piece sets.
26+
const DEFAULT_PIECE_SETS: [[char; 6]; 7] = [
27+
['|', '-', '+', '+', '+', '+'],
28+
['·', '·', '·', '·', '·', '·'],
29+
['•', '•', '•', '•', '•', '•'],
30+
['│', '─', '┌', '┐', '└', '┘'],
31+
['│', '─', '╭', '╮', '╰', '╯'],
32+
['║', '═', '╔', '╗', '╚', '╝'],
33+
['┃', '━', '┏', '┓', '┗', '┛'], // default
34+
];
2335

24-
/// Map of different piece sets.
36+
/// Map from directions to indices for indexing default piece sets.
2537
///
26-
/// Index via `[PIPE_SET_IDX][DIRECTION OF THE PREVIOUS PIECE][CURRENT DIRECTION]`
27-
const PIPE_MAP: [[[char; 4]; 4]; 7] = [
28-
[
29-
// Up
30-
['|', '|', '+', '+'],
31-
// Down
32-
['|', '|', '+', '+'],
33-
// Right
34-
['+', '+', '-', '-'],
35-
// Left
36-
['+', '+', '-', '-'],
37-
],
38-
[
39-
// Up
40-
['·', '·', '·', '·'],
41-
// Down
42-
['·', '·', '·', '·'],
43-
// Right
44-
['·', '·', '·', '·'],
45-
// Left
46-
['·', '·', '·', '·'],
47-
],
48-
[
49-
// Up
50-
['•', '•', '•', '•'],
51-
// Down
52-
['•', '•', '•', '•'],
53-
// Right
54-
['•', '•', '•', '•'],
55-
// Left
56-
['•', '•', '•', '•'],
57-
],
58-
[
59-
// Up
60-
['│', '│', '┌', '┐'],
61-
// Down
62-
['│', '│', '└', '┘'],
63-
// Right
64-
['┘', '┐', '─', '─'],
65-
// Left
66-
['└', '┌', '─', '─'],
67-
],
68-
[
69-
// Up
70-
['│', '│', '╭', '╮'],
71-
// Down
72-
['│', '│', '╰', '╯'],
73-
// Right
74-
['╯', '╮', '─', '─'],
75-
// Left
76-
['╰', '╭', '─', '─'],
77-
],
78-
[
79-
// Up
80-
['║', '║', '╔', '╗'],
81-
// Down
82-
['║', '║', '╚', '╝'],
83-
// Right
84-
['╝', '╗', '═', '═'],
85-
// Left
86-
['╚', '╔', '═', '═'],
87-
],
88-
[
89-
// Up
90-
['┃', '┃', '┏', '┓'],
91-
// Down
92-
['┃', '┃', '┗', '┛'],
93-
// Right
94-
['┛', '┓', '━', '━'],
95-
// Left
96-
['┗', '┏', '━', '━'],
97-
],
38+
/// Index via `[DIRECTION OF THE PREVIOUS PIECE][CURRENT DIRECTION]`
39+
const PIECE_SETS_IDX_MAP: [[usize; 4]; 4] = [
40+
// Up
41+
[0, 0, 2, 3],
42+
// Down
43+
[0, 0, 4, 5],
44+
// Right
45+
[5, 3, 1, 1],
46+
// Left
47+
[4, 2, 1, 1],
9848
];
9949

10050
/// Main four (cardinal) directions.
@@ -258,9 +208,9 @@ impl Canvas {
258208
.wrap_err("failed to set a foreground color")
259209
}
260210

261-
/// Print char at current position of the cursor.
262-
fn put_char(&mut self, ch: char) -> Result<()> {
263-
print!("{}", ch);
211+
/// Print string at the current position of the cursor.
212+
fn put_str(&mut self, s: impl AsRef<str>) -> Result<()> {
213+
print!("{}", s.as_ref());
264214
Ok(())
265215
}
266216

@@ -330,7 +280,7 @@ struct Config {
330280
/// The RGB option is for terminals with true color support (all 16 million colors).
331281
#[arg(short, long, default_value_t, value_enum, verbatim_doc_comment)]
332282
palette: ColorPalette,
333-
/// A set of pieces to use.
283+
/// A default set of pieces to use.
334284
/// Available piece sets:
335285
/// 0 - ASCII pipes:
336286
/// |- ++ ++ +- -+ -|-
@@ -349,6 +299,16 @@ struct Config {
349299
/// This parameter expects a numeric ID.
350300
#[arg(short = 'P', long, default_value_t = 6, value_parser = 0..=6, verbatim_doc_comment)]
351301
piece_set: i64,
302+
/// A string representing custom piece set (takes precedence over -P/--piece-set).
303+
/// The string must have length of 6 characters. Write it according to `│─┌┐└┘`.
304+
/// This string must define all 6 pieces, otherwise rxpipes will crash.
305+
/// Unicode grapheme clusters are supported and treated as single characters.
306+
#[arg(name = "custom-piece-set", short = 'c', long, verbatim_doc_comment)]
307+
custom_piece_set_: Option<String>,
308+
309+
// TODO: implement validation of length for custom-piece-set.
310+
#[clap(skip)]
311+
custom_piece_set: Option<Vec<String>>,
352312
}
353313

354314
/// State of the screensaver.
@@ -466,9 +426,17 @@ impl Screensaver {
466426
let piece = &mut state.pipe_piece;
467427

468428
canv.move_to(piece.pos)?;
469-
canv.put_char(
470-
PIPE_MAP[cfg.piece_set as usize][piece.prev_dir as usize][piece.dir as usize],
471-
)?;
429+
430+
let piece_idx = PIECE_SETS_IDX_MAP[piece.prev_dir as usize][piece.dir as usize];
431+
432+
if let Some(pieces) = &cfg.custom_piece_set {
433+
canv.put_str(&pieces[piece_idx])?;
434+
} else {
435+
canv.put_str(format!(
436+
"{}",
437+
DEFAULT_PIECE_SETS[cfg.piece_set as usize][piece_idx]
438+
))?;
439+
}
472440

473441
state.drawn_pieces += 1;
474442

@@ -537,9 +505,23 @@ fn set_panic_hook() {
537505
}));
538506
}
539507

508+
fn parse_cli() -> Config {
509+
let mut cfg = Config::parse();
510+
511+
if let Some(s) = &cfg.custom_piece_set_ {
512+
cfg.custom_piece_set = Some(
513+
s.graphemes(true) // true here means iterate over extended grapheme clusters (UAX #29).
514+
.map(|s| s.to_string())
515+
.collect(),
516+
);
517+
}
518+
519+
cfg
520+
}
521+
540522
/// An entry point.
541523
fn main() -> Result<()> {
542-
let cfg = Config::parse();
524+
let cfg = parse_cli();
543525

544526
let mut canv = Canvas::new(
545527
io::stdout(),

0 commit comments

Comments
 (0)