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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
use std::env;
use std::io::{self, Write};
use std::sync::{Arc, Mutex};
mod path;
mod poem;
use poem::{read::Readable, recite::Reciteable, Poem};
mod compose;
use compose::Environment;
/// Starts the main shell loop
///
/// # Arguments
/// * `away` - A mutex, indicating whether or not user is at the prompt
/// * `env` - The global shell state
///
/// # Examples
/// ```
/// fn main() {
/// let mut env = compose::env();
/// let mut away = Arc::new(Mutex::new(false));
/// ...
/// repl(&mut away, &mut env);
/// }
/// ```
fn repl(away: &mut Arc<Mutex<bool>>, env: &mut Environment) {
// Initial path refresh on startup
env.bins = path::refresh();
// Main shell loop
loop {
// Get the prompt
let prompt = match env::var("PS1") {
Ok(val) => val,
Err(_) => String::from("|> "),
};
// Output the prompt
print!("{}", prompt);
io::stdout().flush().unwrap();
// At the prompt
*away.lock().unwrap() = false;
// Wait for user input
let mut poetry = String::new();
let bytes = io::stdin()
.read_line(&mut poetry)
.expect("dwvsh: error: unable to evaluate the input string");
// Check if we've reached EOF (i.e. <C-d>)
if bytes == 0 {
println!();
break;
}
// Trim the input
let poetry = String::from(poetry.trim());
// Skip parsing if there is no poetry
if poetry.is_empty() {
continue;
}
// Not at the prompt
*away.lock().unwrap() = true;
// Parse the poem
let poem = Poem::read(poetry, env);
let poem = match poem {
Ok(poem) => poem,
Err(e) => {
eprintln!("dwvsh: {}", e.to_string().to_lowercase());
continue;
}
};
// Recite the poem
match poem.recite(env, None) {
Ok(_) => {}
Err(e) => eprintln!("dwvsh: {}", e.to_string().to_lowercase()),
}
}
}
/// Shell entry
///
/// Shell setup and entry
fn main() {
// Compose the environment for dwvsh
let mut env = compose::env();
// Handle signals
let mut away = Arc::new(Mutex::new(true));
unsafe {
let away = Arc::clone(&away);
signal_hook::low_level::register(signal_hook::consts::SIGINT, move || {
if *away.lock().unwrap() {
println!();
} else {
let prompt = match env::var("PS1") {
Ok(val) => val,
Err(_) => String::from("|> "),
};
print!("\n{}", prompt);
io::stdout().flush().unwrap();
}
})
.unwrap();
};
// Begin evaluating commands
repl(&mut away, &mut env);
}
|