1use std::cmp::{self, Ordering};
16
17pub enum Pos {
19 Back,
20 Front,
21 Both,
22}
23
24impl Pos {
25 fn num(&self) -> u32 {
26 match *self {
27 Pos::Back => 0,
28 Pos::Front => 1,
29 Pos::Both => 2,
30 }
31 }
32}
33
34pub fn move_cursor(i: i32, j: i32) -> String {
37 let code0 = match i.cmp(&0) {
38 Ordering::Less => format!("\x1B[{}B", -i),
39 Ordering::Equal => format!(""),
40 Ordering::Greater => format!("\x1B[{}A", i),
41 };
42 let code1 = match j.cmp(&0) {
43 Ordering::Less => format!("\x1B[{}D", -j),
44 Ordering::Equal => format!(""),
45 Ordering::Greater => format!("\x1B[{}C", j),
46 };
47 format!("{}{}", code0, code1)
48}
49
50pub fn move_line(n: i32) -> String {
54 match n.cmp(&0) {
55 Ordering::Less => format!("\x1B[{}F", -n),
56 Ordering::Equal => format!(""),
57 Ordering::Greater => format!("\x1B[{}E", n),
58 }
59}
60
61pub fn set_column(n: u32) -> String {
63 format!("\x1B[{}G", cmp::max(1, n))
64}
65
66pub fn set_position(i: u32, j: u32) -> String {
68 format!("\x1B[{};{}H", cmp::max(1, i), cmp::max(1, j))
69}
70
71pub fn clear_display(pos: Pos) -> String {
76 format!("\x1B[{}J", pos.num())
77}
78
79pub fn clear_line(pos: Pos) -> String {
84 format!("\x1B[{}K", pos.num())
85}
86
87pub fn scroll(n: i32) -> String {
90 match n.cmp(&0) {
91 Ordering::Less => format!("\x1B[{}T", -n),
92 Ordering::Equal => format!(""),
93 Ordering::Greater => format!("\x1B[{}S", n),
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 macro_rules! test {
102 ($name: ident; $ctrl: expr => $result: expr) => {
103 #[test]
104 fn $name() {
105 assert_eq!($result, $ctrl)
106 }
107 };
108 }
109
110 test!(move_cursor0; move_cursor(2, -4) => "\x1B[2A\x1B[4D");
111 test!(move_cursor1; move_cursor(-2, 0) => "\x1B[2B");
112 test!(move_cursor2; move_cursor(0, 6) => "\x1B[6C");
113 test!(move_cursor3; move_cursor(0, 0) => "");
114
115 test!(move_line0; move_line(4) => "\x1B[4E");
116 test!(move_line1; move_line(-4) => "\x1B[4F");
117
118 test!(set_column0; set_column(3) => "\x1B[3G");
119 test!(set_column1; set_column(0) => "\x1B[1G");
120
121 test!(set_position0; set_position(3, 5) => "\x1B[3;5H");
122 test!(set_position1; set_position(0, 0) => "\x1B[1;1H");
123
124 test!(clear_display0; clear_display(Pos::Back) => "\x1B[0J");
125 test!(clear_display1; clear_display(Pos::Front) => "\x1B[1J");
126 test!(clear_display2; clear_display(Pos::Both) => "\x1B[2J");
127
128 test!(clear_line0; clear_line(Pos::Back) => "\x1B[0K");
129 test!(clear_line1; clear_line(Pos::Front) => "\x1B[1K");
130 test!(clear_line2; clear_line(Pos::Both) => "\x1B[2K");
131
132 test!(scroll0; scroll(7) => "\x1B[7S");
133 test!(scroll1; scroll(-5) => "\x1B[5T");
134}