1 use super::{completer::IonCompleter, InteractiveShell};
2 use ion_shell::Shell;
3 use std::io::ErrorKind;
4 
5 impl<'a> InteractiveShell<'a> {
6     /// Ion's interface to Liner's `read_line` method, which handles everything related to
7     /// rendering, controlling, and getting input from the prompt.
readln<T: Fn(&mut Shell<'_>)>(&self, prep_for_exit: &T) -> Option<String>8     pub fn readln<T: Fn(&mut Shell<'_>)>(&self, prep_for_exit: &T) -> Option<String> {
9         let prompt = self.prompt();
10         let line = self.context.borrow_mut().read_line(
11             prompt,
12             None,
13             &mut IonCompleter::new(&self.shell.borrow()),
14         );
15 
16         match line {
17             Ok(line) => {
18                 if line.bytes().next() != Some(b'#')
19                     && line.bytes().any(|c| !c.is_ascii_whitespace())
20                 {
21                     self.terminated.set(false);
22                 }
23                 Some(line)
24             }
25             // Handles Ctrl + C
26             Err(ref err) if err.kind() == ErrorKind::Interrupted => None,
27             // Handles Ctrl + D
28             Err(ref err) if err.kind() == ErrorKind::UnexpectedEof => {
29                 let mut shell = self.shell.borrow_mut();
30                 if self.terminated.get() && shell.exit_block().is_err() {
31                     prep_for_exit(&mut shell);
32                     std::process::exit(shell.previous_status().as_os_code())
33                 }
34                 None
35             }
36             Err(err) => {
37                 eprintln!("ion: liner: {}", err);
38                 None
39             }
40         }
41     }
42 }
43