stdin_readlines/
lib.rs

1use std::io;
2
3/// std::io::stdin().read_line(&buf)
4pub fn stdin_read_line(input: &mut String) -> bool {
5    match io::stdin().read_line(input) {
6        Ok(_) => {},
7        Err(err) => {
8            println!("Error when read line from stdin: {}", err);
9            return false
10        },
11    }
12
13    true
14}
15
16/// Default use `EOF` as end of the reading stage.
17pub fn stdin_readlines(input: &mut String) -> bool {
18    let eof = String::from("EOF");
19    stdin_readlines_end_with(input, &eof)
20}
21
22/// CMDS
23///     C_H: show help.
24///     C_C: clear all input data.
25///     C_D N: if N exist, delete the line N, else delete the last line
26///     C_I N: insert new lines start with line N.
27///     C_P: print the current inputed lines, if more the than 10 lines,
28///         every time print 10 lines, then you can input `n` to print the next,
29///         use `q` to quit print mode.
30pub fn stdin_readlines_end_with(input: &mut String, eof: &String) -> bool {
31    let mut lines: Vec<String> = Vec::new();
32    let mut index = 0;
33    let mut failed_times = 0;
34
35    println!("> `{}` to stop reading from stdin, and `C_H` show help", eof.trim_end());
36    // start reading until get eof str.
37    loop {
38        let mut line = String::new();
39
40        match io::stdin().read_line(&mut line) {
41            Ok(_) => {
42                if line.trim_end().eq(eof) {
43                    break
44                }
45                if line.eq("C_H\n") {
46                    show_help();
47                } else if line.eq("C_C\n") {
48                    lines = Vec::new();
49                } else if line.eq("C_P\n") {
50                    printlines(&lines);
51                // delete mode
52                } else if line.starts_with("C_D") {
53                    let args: Vec<_> = line.split(" ").collect();
54                    if args.len() == 1 {
55                        if lines.len() > 1 {
56                            lines.pop().unwrap();
57                            // update index
58                            index -= 1;
59                        } else {
60                            println!("No line to drop!");
61                        }
62                    } else if args.len() == 2 {
63                        let max = lines.len();
64                        if let Ok(num) = args[1].trim_end().parse::<usize>() {
65                            if num < 1 {
66                                println!("Delete line must in 1 to {}", max);
67                                continue;
68                            } else if num > max {
69                                println!("Delete line must in 1 to {}", max);
70                                continue;
71                            }
72                            lines.remove(index - 1);
73                            // update index
74                            index -= 1;
75                        } else {
76                            println!("Delete line must in 1 to {}", max);
77                            show_help();
78                        }
79                    } else {
80                        show_help();
81                    }
82                // reset insert index
83                } else if line.starts_with("C_I") {
84                    let max = lines.len() + 1;
85                    let args: Vec<_> = line.split(" ").collect();
86                    if args.len() == 2 {
87                        if let Ok(num) = args[1].trim_end().parse::<usize>() {
88                            if num < 1 {
89                                println!("Insert line must in 1 to {}", max);
90                                continue;
91                            } else if num > max {
92                                println!("Insert line must in 1 to {}", max);
93                                continue;
94                            }
95                            index = num - 1;
96                        } else {}
97                    } else {
98                        show_help();
99                    }
100                } else {
101                    lines.insert(index, line);
102                    index += 1;
103                }
104            },
105            Err(err) => {
106                println!("Error when read line from stdin: {}", err);
107                failed_times += 1;
108                if failed_times > 3 {
109                    println!("Failed more than 3 times, stop and exit.");
110                    return false
111                }
112            },
113        }
114    }
115    for line in &lines {
116        input.push_str(line);
117    }
118
119    true
120}
121
122fn show_help() {
123    let help_info = "
124Usage:
125    C_H         Show this help
126    C_C         Clear all the inputed data
127    C_D [N]     Delete the line N, or delete the last line
128    C_I [N]     Move the insert index to line N
129    C_P         print the current inputed lines, if more the than 10 lines,
130                every time print 10 lines, then you can input `n` to print
131                the next, use `q` to quit print mode
132    EOF         Stop readlines
133";
134
135    println!("{}", help_info);
136}
137
138fn printlines(lines: &Vec<String>) {
139    let mut num = 0;
140    let mut lnum = 1;
141    let mut input = String::new();
142    for line in lines {
143        print!("{:2}  {}", lnum, line);
144        num += 1;
145        lnum += 1;
146        if num == 10 {
147            io::stdin().read_line(&mut input).unwrap();
148            if input.eq("n\n") {
149                num = 0;
150            } else if input.eq("q\n") {
151                break;
152            }
153        }
154    }
155}