add_ed/ui/
scripted_ui.rs

1//! This module is for supporting scripts.
2//! The entire script is put into a vector of strings and treated as input.
3//! It optionally takes a mutable UI reference, to support printing when the script requests it.
4
5use super::{UI, UILock};
6use super::Ed;
7
8use super::Result;
9
10use std::collections::VecDeque;
11
12#[cfg(feature = "initial_input_data")]
13use crate::error::UIError;
14
15/// Error type for Scripted UI which can only occur if you enable the feature
16/// `initial_input_data` and given initial data to [`ScriptedUI::get_input`]
17#[cfg(feature = "initial_input_data")]
18#[derive(Debug)]
19pub struct UnsupportedInitialData{}
20#[cfg(feature = "initial_input_data")]
21impl std::fmt::Display for UnsupportedInitialData {
22  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23    write!(f, "You cannot take input with initial data in a script.")
24  }
25}
26#[cfg(feature = "initial_input_data")]
27impl std::error::Error for UnsupportedInitialData {}
28#[cfg(feature = "initial_input_data")]
29impl crate::error::UIErrorTrait for UnsupportedInitialData {}
30
31/// This is a scripted UI. It returns the scripted input without querying user.
32///
33/// How to use:
34/// * Put the input to simulate line-by-line in the input variable.
35///   (terminating '\n' required, errors may arize if missing)
36/// * If you want output from print commands put a UI to print with in
37///   `print_ui`.
38///   (If none given prints will be quietly ignored)
39
40// Things not derived here since they would require the same being implemented
41// on the UI trait, which is too extreme for me at this stage. If you have need,
42// complain and I'll add it.
43pub struct ScriptedUI<'a> {
44  pub input: VecDeque<String>,
45  pub print_ui: Option<&'a mut dyn UI>,
46}
47impl <'a> UI for ScriptedUI<'a> {
48  fn get_command(&mut self,
49    _ed: &Ed,
50    _prefix: Option<char>
51  ) -> Result<String> {
52    match self.input.pop_front() {
53      Some(x) => Ok(x),
54      // Returns from the macro execution no matter what.
55      None => Ok("Q\n".to_string()),
56    }
57  }
58  fn get_input(&mut self,
59    _ed: &Ed,
60    terminator: char,
61    #[cfg(feature = "initial_input_data")]
62    initial_buffer: Option<Vec<String>>, // causes error
63  ) -> Result<Vec<String>> {
64    #[cfg(feature = "initial_input_data")]
65    {
66      if initial_buffer.is_some() {
67        return Err(Into::<UIError>::into(UnsupportedInitialData{}).into())
68      }
69    }
70    let mut ret = Vec::new();
71    let term = format!("{}\n", terminator);
72    // Loop until we run out of data or find the terminator
73    loop {
74      match self.input.pop_front() {
75        None => return Ok(ret), // Return what we have
76        Some(x) => {
77          if x == term { return Ok(ret); }
78          ret.push(x)
79        }
80      }
81    }
82  }
83  // Printing is handed to the print_ui if one was given, else ignored
84  fn print_message(
85    &mut self,
86    text: &str
87  ) -> Result<()> {
88    match &mut self.print_ui {
89      Some(ui) => ui.print_message(text),
90      None => Ok(()),
91    }
92  }
93  fn print_commands(&mut self) -> Result<()> {
94    match &mut self.print_ui {
95      Some(ui) => ui.print_commands(),
96      None => Ok(()),
97    }
98  }
99  fn print_command_documentation(&mut self) -> Result<()> {
100    match &mut self.print_ui {
101      Some(ui) => ui.print_command_documentation(),
102      None => Ok(()),
103    }
104  }
105  fn print_selection(&mut self,
106    ed: &Ed,
107    selection: (usize, usize),
108    numbered: bool,
109    literal: bool,
110  ) -> Result<()> {
111    match &mut self.print_ui {
112      Some(ui) => {
113        ui.print_selection(ed, selection, numbered, literal)
114      },
115      None => Ok(()),
116    }
117  }
118  fn lock_ui(&mut self) -> UILock<'_> {
119    match self.print_ui {
120      Some(ref mut i) => i.lock_ui(),
121      None => UILock::new(self),
122    }
123  }
124  // Will only be called if no inner UI, beware
125  fn unlock_ui(&mut self) {}
126}