/// Handles key input by the user into the REPL
Handles key input by the user into the REPL
Handles key input by the user into the REPL
async fn handle_key(&mut self, code: KeyCode, modifier: KeyModifiers) -> Result<()> {
        match code {
            KeyCode::Char(c) => {
                self.input_state
                    .input
                    .insert(self.input_state.input_cursor, c);
                self.input_state.input_cursor += 1;
            }
            KeyCode::Left => {
                if self.input_state.input_cursor > 0 {
                    self.input_state.input_cursor -= 1
                }
            }
            KeyCode::Right => {
                if self.input_state.input_cursor < self.input_state.input.len() {
                    self.input_state.input_cursor += 1
                }
            }
            KeyCode::Up => {
                if modifier == KeyModifiers::SHIFT
                    && self.output_state.output_cursor > 0
                    && self.output_state.output_scroll > 0
                {
                    self.output_state.output_cursor -= 1;
                } else if self.input_state.history_cursor > 0 && modifier == KeyModifiers::NONE {
                    self.input_state.history_cursor -= 1;
                    self.input_state.input =
                        self.input_state.history[self.input_state.history_cursor].clone();
                    self.input_state.input_cursor = self.input_state.input.len();
                }
            }
            KeyCode::Down => {
                if modifier == KeyModifiers::SHIFT
                    && self.output_state.output_cursor < self.output_state.output.len()
                {
                    self.output_state.output_cursor += 1;
                } else if modifier == KeyModifiers::NONE {
                    if self.input_state.history.is_empty() {
                        return Ok(());
                    };
                    if self.input_state.history_cursor < self.input_state.history.len() - 1
                        && self.input_state.history_cursor > 0
                    {
                        self.input_state.history_cursor += 1;
                        self.input_state.input =
                            self.input_state.history[self.input_state.history_cursor].clone();
                        self.input_state.input_cursor = self.input_state.input.len();
                    } else if self.input_state.history_cursor >= self.input_state.history.len() - 1
                    {
                        self.input_state.history_cursor = self.input_state.history.len();
                        self.input_state.input.clear();
                        self.input_state.input_cursor = 0;
                    }
                }
            }
            KeyCode::Backspace => {
                if self.input_state.input_cursor > 0
                    && self.input_state.input_cursor <= self.input_state.input.len()
                {
                    self.input_state.input_cursor -= 1;
                    self.input_state.input.remove(self.input_state.input_cursor);
                };
            }
            KeyCode::Enter => {
                let cmd: String = self.input_state.input.iter().collect();
                let iter = cmd.split_ascii_whitespace();
                let cli = ReplCli::from_iter_safe(iter);
                let multilines = self.input_state.input.len() / self.input_state.input_width;
                if multilines >= 1 {
                    self.input_state.multiline_history += multilines as u16;
                };
                self.input_state
                    .history
                    .push(self.input_state.input.clone());
                self.input_state.history_cursor = self.input_state.history.len();
                self.input_state.input.clear();
                self.input_state.input_cursor = 0;
                match cli {
                    Ok(ReplCli { cmd }) => {
                        use ReplCliCommand::*;
                        //TODO(brooksmtownsend): Add loading / fetching messages to longer / blocking calls
                        match cmd {
                            Clear => {
                                info!(target: WASH_LOG_INFO, "Clearing REPL history");
                                self.input_state = InputState::default();
                            }
                            Quit => {
                                info!(target: WASH_CMD_INFO, "Goodbye");
                                return Err("REPL Quit".into());
                            }
                            ReplCliCommand::Ctl(ctlcmd) => {
                                match handle_ctl(ctlcmd, &mut self.output_state).await {
                                    Ok(r) => r,
                                    Err(e) => error!("Error handling ctl: {}", e),
                                }
                            }
                            ReplCliCommand::Claims(claimscmd) => {
                                match handle_claims(claimscmd, &mut self.output_state).await {
                                    Ok(r) => r,
                                    Err(e) => error!("Error handling claims: {}", e),
                                };
                            }
                            ReplCliCommand::Keys(keyscmd) => {
                                match handle_keys(keyscmd, &mut self.output_state).await {
                                    Ok(r) => r,
                                    Err(e) => error!("Error handling key: {}", e),
                                }
                            }
                            ReplCliCommand::Par(parcmd) => {
                                match handle_par(parcmd, &mut self.output_state).await {
                                    Ok(r) => r,
                                    Err(e) => error!("Error handling par: {}", e),
                                }
                            }
                            ReplCliCommand::Reg(regcmd) => {
                                match handle_reg(regcmd, &mut self.output_state).await {
                                    Ok(r) => r,
                                    Err(e) => error!("Error handling reg: {}", e),
                                }
                            }
                        }
                    }
                    Err(e) => {
                        use structopt::clap::ErrorKind::*;
                        // HelpDisplayed is the StructOpt help text error, which should be displayed as info
                        match e.kind {
                            HelpDisplayed => info!(target: WASH_CMD_INFO, "\n{}", e.message),
                            _ => error!(target: WASH_CMD_INFO, "\n{}", e.message),
                        }
                    }
                };
            }
            _ => (),
        };
        Ok(())
    }
async fn handle_key ( & mut self , code : KeyCode , modifier : KeyModifiers ) -> Result < ( ) > { match code { KeyCode :: Char ( c ) => { self . input_state . input . insert ( self . input_state . input_cursor , c ) ; self . input_state . input_cursor += 1 ; } KeyCode :: Left => { if self . input_state . input_cursor > 0 { self . input_state . input_cursor -= 1 } } KeyCode :: Right => { if self . input_state . input_cursor < self . input_state . input . len ( ) { self . input_state . input_cursor += 1 } } KeyCode :: Up => { if modifier == KeyModifiers :: SHIFT && self . output_state . output_cursor > 0 && self . output_state . output_scroll > 0 { self . output_state . output_cursor -= 1 ; } else if self . input_state . history_cursor > 0 && modifier == KeyModifiers :: NONE { self . input_state . history_cursor -= 1 ; self . input_state . input = self . input_state . history [ self . input_state . history_cursor ] . clone ( ) ; self . input_state . input_cursor = self . input_state . input . len ( ) ; } } KeyCode :: Down => { if modifier == KeyModifiers :: SHIFT && self . output_state . output_cursor < self . output_state . output . len ( ) { self . output_state . output_cursor += 1 ; } else if modifier == KeyModifiers :: NONE { if self . input_state . history . is_empty ( ) { return Ok ( ( ) ) ; } ; if self . input_state . history_cursor < self . input_state . history . len ( ) - 1 && self . input_state . history_cursor > 0 { self . input_state . history_cursor += 1 ; self . input_state . input = self . input_state . history [ self . input_state . history_cursor ] . clone ( ) ; self . input_state . input_cursor = self . input_state . input . len ( ) ; } else if self . input_state . history_cursor >= self . input_state . history . len ( ) - 1 { self . input_state . history_cursor = self . input_state . history . len ( ) ; self . input_state . input . clear ( ) ; self . input_state . input_cursor = 0 ; } } } KeyCode :: Backspace => { if self . input_state . input_cursor > 0 && self . input_state . input_cursor <= self . input_state . input . len ( ) { self . input_state . input_cursor -= 1 ; self . input_state . input . remove ( self . input_state . input_cursor ) ; } ; } KeyCode :: Enter => { let cmd : String = self . input_state . input . iter ( ) . collect ( ) ; let iter = cmd . split_ascii_whitespace ( ) ; let cli = ReplCli :: from_iter_safe ( iter ) ; let multilines = self . input_state . input . len ( ) / self . input_state . input_width ; if multilines >= 1 { self . input_state . multiline_history += multilines as u16 ; } ; self . input_state . history . push ( self . input_state . input . clone ( ) ) ; self . input_state . history_cursor = self . input_state . history . len ( ) ; self . input_state . input . clear ( ) ; self . input_state . input_cursor = 0 ; match cli { Ok ( ReplCli { cmd } ) => { use ReplCliCommand :: * ; //TODO(brooksmtownsend): Add loading / fetching messages to longer / blocking calls match cmd { Clear => { info ! ( target WASH_LOG_INFO " " ) ; self . input_state = InputState :: default ( ) ; } Quit => { info ! ( target WASH_CMD_INFO " " ) ; return Err ( " " . into ( ) ) ; } ReplCliCommand :: Ctl ( ctlcmd ) => { match handle_ctl ( ctlcmd , & mut self . output_state ) . await { Ok ( r ) => r , Err ( e ) => error ! ( " " e ) , } } ReplCliCommand :: Claims ( claimscmd ) => { match handle_claims ( claimscmd , & mut self . output_state ) . await { Ok ( r ) => r , Err ( e ) => error ! ( " " e ) , } ; } ReplCliCommand :: Keys ( keyscmd ) => { match handle_keys ( keyscmd , & mut self . output_state ) . await { Ok ( r ) => r , Err ( e ) => error ! ( " " e ) , } } ReplCliCommand :: Par ( parcmd ) => { match handle_par ( parcmd , & mut self . output_state ) . await { Ok ( r ) => r , Err ( e ) => error ! ( " " e ) , } } ReplCliCommand :: Reg ( regcmd ) => { match handle_reg ( regcmd , & mut self . output_state ) . await { Ok ( r ) => r , Err ( e ) => error ! ( " " e ) , } } } } Err ( e ) => { use structopt :: clap :: ErrorKind :: * ; // HelpDisplayed is the StructOpt help text error, which should be displayed as info match e . kind { HelpDisplayed => info ! ( target WASH_CMD_INFO " \n " e message ) , _ => error ! ( target WASH_CMD_INFO " \n " e message ) , } } } ; } _ => ( ) , } ; Ok ( ( ) ) }
Handles key input by the user into the REPL
Handles key input by the user into the REPL
&mut self
code
KeyCode
modifier
KeyModifiers