@@ -20,81 +20,31 @@ use std::{
20
20
panic:: { set_hook, take_hook} ,
21
21
time:: Duration ,
22
22
} ;
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
+ ] ;
23
35
24
- /// Map of different piece sets.
36
+ /// Map from directions to indices for indexing default piece sets.
25
37
///
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 ] ,
98
48
] ;
99
49
100
50
/// Main four (cardinal) directions.
@@ -258,9 +208,9 @@ impl Canvas {
258
208
. wrap_err ( "failed to set a foreground color" )
259
209
}
260
210
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 ( ) ) ;
264
214
Ok ( ( ) )
265
215
}
266
216
@@ -330,7 +280,7 @@ struct Config {
330
280
/// The RGB option is for terminals with true color support (all 16 million colors).
331
281
#[ arg( short, long, default_value_t, value_enum, verbatim_doc_comment) ]
332
282
palette : ColorPalette ,
333
- /// A set of pieces to use.
283
+ /// A default set of pieces to use.
334
284
/// Available piece sets:
335
285
/// 0 - ASCII pipes:
336
286
/// |- ++ ++ +- -+ -|-
@@ -349,6 +299,16 @@ struct Config {
349
299
/// This parameter expects a numeric ID.
350
300
#[ arg( short = 'P' , long, default_value_t = 6 , value_parser = 0 ..=6 , verbatim_doc_comment) ]
351
301
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 > > ,
352
312
}
353
313
354
314
/// State of the screensaver.
@@ -466,9 +426,17 @@ impl Screensaver {
466
426
let piece = & mut state. pipe_piece ;
467
427
468
428
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
+ }
472
440
473
441
state. drawn_pieces += 1 ;
474
442
@@ -537,9 +505,23 @@ fn set_panic_hook() {
537
505
} ) ) ;
538
506
}
539
507
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
+
540
522
/// An entry point.
541
523
fn main ( ) -> Result < ( ) > {
542
- let cfg = Config :: parse ( ) ;
524
+ let cfg = parse_cli ( ) ;
543
525
544
526
let mut canv = Canvas :: new (
545
527
io:: stdout ( ) ,
0 commit comments