rm_lisa/input/mod.rs
1//! Handle receiving input from somewhere, and use it to produce strings
2//! somewhere else.
3//!
4//! NOTE: Inputs do not actually have to come from STDIN. They can come from
5//! anywhere, e.g. a server listening on a unix socket. Of course accepting
6//! commands from remote places that aren't on STDIN could introduce security
7//! concerns, that's for you to deal with, but is possible.
8//!
9//! Input Providers also _are not in charge_ of rendering inputs, and should
10//! _hide_ any input that users are putting in. They should instead keep a
11//! buffer of the current input string, and pass it the display when asked for.
12//! The display will then render the command however it sees fit.
13
14pub mod autocomplete;
15pub mod history;
16pub mod stdin;
17
18use crate::{
19 errors::LisaError,
20 input::{autocomplete::AutocompleteProvider, history::HistoryProvider},
21};
22
23/// An input provider is something that is capable of receiving input from
24/// users, holding it, and producing a value to some console at some point
25/// in time.
26///
27/// The input providers job is to provide input events to displays (and
28/// potentially others) and keep state of the current input.
29pub trait InputProvider: Send + Sync {
30 /// If this input is coming from STDIN, and as such an input
31 /// display should be rendered.
32 #[must_use]
33 fn is_stdin(&self) -> bool;
34
35 /// If the input provider is active, and accepting input.
36 #[must_use]
37 fn is_active(&self) -> bool;
38 /// Set this terminal as 'active'.
39 ///
40 /// ## Errors
41 ///
42 /// If the underlying provider cannot do what it needs to be made active.
43 fn set_active(&mut self, active: bool) -> Result<(), LisaError>;
44
45 /// If this provider has some active input, and someone is actively
46 /// 'typing'.
47 #[must_use]
48 fn input_in_progress(&self) -> bool;
49 /// Get any current input that has been provided.
50 #[must_use]
51 fn current_input(&self) -> String;
52 /// Poll for any active input events.
53 #[must_use]
54 fn poll_for_input(&mut self, ansi_supported: bool) -> Vec<TerminalInputEvent>;
55
56 /// Set the current autocomplete provider for this input provider.
57 fn set_autocomplete_provider(&mut self, autocomplete: Box<dyn AutocompleteProvider>);
58 /// Get the current autocomplete suggestion.
59 #[must_use]
60 fn current_autocomplete_suggestion(&self) -> Option<String>;
61 /// If an autocomplete suggestion is pending, but not yet completed.
62 #[must_use]
63 fn autocomplete_suggestion_pending(&self) -> bool;
64
65 /// Set the current history provider.
66 fn set_history_provider(&mut self, history: Box<dyn HistoryProvider>);
67 /// Get the current history search value that is being found.
68 #[must_use]
69 fn current_history_search_value(&self) -> Option<String>;
70 // If we're actively doing a history search.
71 #[must_use]
72 fn is_doing_history_search(&self) -> bool;
73
74 /// Get any fully complete inputs that have occured since things last ran.
75 #[must_use]
76 fn inputs(&mut self) -> Vec<String>;
77}
78
79/// A terminal input event has occured.
80#[derive(Clone, Debug, PartialEq, Eq, Hash)]
81pub enum TerminalInputEvent {
82 /// Clear the screen if the renderer supports this.
83 ClearScreen,
84 /// Input has been cancelled.
85 InputCancelled,
86 /// The input has had text appended to the end of it.
87 ///
88 /// This will only ever be fired when a user has typed/pasted text at the end
89 /// of the line (e.g. not in the midddle).
90 InputAppend(char),
91 /// A lot of inputs have been appended all at once.
92 InputMassAppend(String),
93 /// The input has changed in a way that wasn't an append.
94 ///
95 /// A character has been removed, text has been pasted in the middle, etc.
96 InputChanged(usize),
97 /// The input has finished being applied.
98 InputFinished,
99 /// Input has started being input by the user.
100 InputStarted,
101 /// Cursor goes ahead and moves left 'backwards' through the input N spaces.
102 CursorMoveLeft(usize),
103 /// Cursor goes ahead and moves right 'forwards' through the input N spaces.
104 CursorMoveRight(usize),
105 /// Toggle pausing or un-pausing STDOUT/STDERR.
106 ToggleOutputPause,
107}