blob: 48e2d85c04608af5945dc08d24823d180f4d10d5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
use std::io::{self, Read, Write};
use std::sync::{Arc, Mutex};
// STDIN is file descriptor (fd) 0 on Linux and other UN*X-likes
pub const STDIN: i32 = 0;
/// Retrieve a single byte of input
///
/// Requires some setup beforehand (see beginning of repl())
fn getchar() -> u8 {
let mut b = [0; 1];
io::stdout().lock().flush().unwrap();
io::stdin().read_exact(&mut b).unwrap();
b[0]
}
/// Handle user input at the repl prompt
///
/// This is required instead of io::stdin().read_line(), because certain
/// keys like `<tab>` and `<up>` have special functions (cycle through
/// autocomplete options, and history, respectively). It leverages
/// [getchar] to read each character as the user inputs it. This also
/// means special cases for handling backspace, newlines, etc. Assumes
/// that (ICANON and ECHO) are off. See the beginning of [crate::repl]
/// for more details.
pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>) -> usize {
loop {
let c = getchar();
match c {
// enter/return
b'\n' => break,
// tab
b'\t' => {
print!(" ");
buffer.lock().unwrap().push(b' ');
}
// ctrl-d
4 => return 0,
// backspace
127 => {
buffer.lock().unwrap().pop();
print!("\u{8} \u{8}");
}
// everything else
_ => {
print!("{}", c as char);
buffer.lock().unwrap().push(c);
}
}
}
println!();
buffer.lock().unwrap().push(b'\n');
buffer.lock().unwrap().len()
}
|