shrub_core/shell/readline.rs
1//! Readline edit buffer support for shell instances.
2
3use crate::variables::ShellVariable;
4use crate::{error, extensions};
5
6impl<SE: extensions::ShellExtensions> crate::Shell<SE> {
7 /// Updates the shell state to reflect the given edit buffer contents.
8 ///
9 /// # Arguments
10 ///
11 /// * `contents` - The contents of the edit buffer.
12 /// * `cursor` - The cursor position in the edit buffer.
13 ///
14 /// # Errors
15 ///
16 /// Returns [`crate::error::ErrorKind::MissingScopeForNewVariable`] if the
17 /// environment has no global scope to hold `READLINE_LINE` and
18 /// `READLINE_POINT`.
19 pub fn set_edit_buffer(&mut self, contents: String, cursor: usize) -> Result<(), error::Error> {
20 self.env
21 .set_global("READLINE_LINE", ShellVariable::new(contents))?;
22
23 self.env
24 .set_global("READLINE_POINT", ShellVariable::new(cursor.to_string()))?;
25
26 Ok(())
27 }
28
29 /// Returns the contents of the shell's edit buffer, if any. The buffer
30 /// state is cleared from the shell.
31 ///
32 /// # Errors
33 ///
34 /// Returns [`crate::error::ErrorKind::ReadonlyVariable`] if `READLINE_LINE`
35 /// or `READLINE_POINT` is readonly and so cannot be unset.
36 pub fn pop_edit_buffer(&mut self) -> Result<Option<(String, usize)>, error::Error> {
37 let line = self
38 .env
39 .unset("READLINE_LINE")?
40 .map(|line| line.value().to_cow_str(self).to_string());
41
42 let point = self
43 .env
44 .unset("READLINE_POINT")?
45 .and_then(|point| point.value().to_cow_str(self).parse::<usize>().ok())
46 .unwrap_or(0);
47
48 if let Some(line) = line {
49 Ok(Some((line, point)))
50 } else {
51 Ok(None)
52 }
53 }
54}