diff options
author | Canop <cano.petrole@gmail.com> | 2020-07-20 20:10:56 +0200 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2020-07-20 20:10:56 +0200 |
commit | 84d857e7fa6e8749c21b3c937c96cce9c25356e9 (patch) | |
tree | 878688bea2b4c54fbcd5b996cf5d098194e0a399 /src/command | |
parent | f0cd893b028cec09bd7a35b3f4d00c64c31cea0f (diff) |
"client-server" feature
Diffstat (limited to 'src/command')
-rw-r--r-- | src/command/mod.rs | 2 | ||||
-rw-r--r-- | src/command/sequence.rs | 135 |
2 files changed, 87 insertions, 50 deletions
diff --git a/src/command/mod.rs b/src/command/mod.rs index 98fe403..7655b92 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -11,7 +11,7 @@ pub use { completion::Completions, event::PanelInput, parts::CommandParts, - sequence::parse_command_sequence, + sequence::Sequence, scroll::ScrollCommand, trigger_type::TriggerType, }; diff --git a/src/command/sequence.rs b/src/command/sequence.rs index 3b51738..a8d8fe0 100644 --- a/src/command/sequence.rs +++ b/src/command/sequence.rs @@ -10,58 +10,95 @@ use { }, }; -/// parse a string which is meant as a sequence of commands. -/// -/// The ';' separator is used to identify inputs unless it's -/// overriden in env variable BROOT_CMD_SEPARATOR. -/// Verbs are verified, to ensure the command sequence has -/// no unexpected holes. -pub fn parse_command_sequence<'a>( - sequence: &'a str, - con: &AppContext, -) -> Result<Vec<(&'a str, Command)>, ProgramError> { - let separator = match std::env::var("BROOT_CMD_SEPARATOR") { - Ok(sep) if !sep.is_empty() => sep, - _ => String::from(";"), - }; - debug!("Splitting cmd sequence with {:?}", separator); - let mut commands = Vec::new(); - for input in sequence.split(&separator) { - // an input may be made of two parts: - // - a search pattern - // - a verb followed by its arguments - // we need to build a command for each part so - // that the search is effectively done before - // the verb invocation - let raw_parts = CommandParts::from(input.to_string()); - let (pattern, verb_invocation) = raw_parts.split(); - if let Some(pattern) = pattern { - debug!("adding pattern: {:?}", pattern); - commands.push((input, Command::from_parts(pattern, false))); +/// an unparsed sequence with its separator (which may be +/// different from the one provided by local_separator()) +#[derive(Debug)] +pub struct Sequence { + pub separator: String, + pub raw: String, +} + +impl Sequence { + /// return the separator to use to parse sequences. + pub fn local_separator() -> String { + match std::env::var("BROOT_CMD_SEPARATOR") { + Ok(sep) if !sep.is_empty() => sep, + _ => String::from(";"), } - if let Some(verb_invocation) = verb_invocation { - debug!("adding verb_invocation: {:?}", verb_invocation); - let command = Command::from_parts(verb_invocation, true); - if let Command::VerbInvocate(invocation) = &command { - // we check that the verb exists to avoid running a sequence - // of actions with some missing - match con.verb_store.search(&invocation.name) { - PrefixSearchResult::NoMatch => { - return Err(ProgramError::UnknownVerb { - name: invocation.name.to_string(), - }); - } - PrefixSearchResult::Matches(_) => { - return Err(ProgramError::AmbiguousVerbName { - name: invocation.name.to_string(), - }); - } - _ => {} - } - commands.push((input, command)); + } + pub fn new(separator: String, raw: String) -> Self { + Self { + separator, + raw, + } + } + pub fn new_single(cmd: String) -> Self { + Self { + separator: "".to_string(), + raw: cmd, + } + } + pub fn new_local(raw: String) -> Self { + Self { + separator: Self::local_separator(), + raw, + } + } + pub fn parse( + &self, + con: &AppContext, + ) -> Result<Vec<(String, Command)>, ProgramError> { + debug!("Splitting cmd sequence with {:?}", &self.separator); + let mut commands = Vec::new(); + if self.separator.is_empty() { + add_commands(&self.raw, &mut commands, con)?; + } else { + for input in self.raw.split(&self.separator) { + add_commands(input, &mut commands, con)?; } } + Ok(commands) } - Ok(commands) } +/// an input may be made of two parts: +/// - a search pattern +/// - a verb followed by its arguments +/// we need to build a command for each part so +/// that the search is effectively done before +/// the verb invocation +fn add_commands( + input: &str, + commands: &mut Vec<(String, Command)>, + con: &AppContext, +) -> Result<(), ProgramError> { + let raw_parts = CommandParts::from(input.to_string()); + let (pattern, verb_invocation) = raw_parts.split(); + if let Some(pattern) = pattern { + debug!("adding pattern: {:?}", pattern); + commands.push((input.to_string(), Command::from_parts(pattern, false))); + } + if let Some(verb_invocation) = verb_invocation { + debug!("adding verb_invocation: {:?}", verb_invocation); + let command = Command::from_parts(verb_invocation, true); + if let Command::VerbInvocate(invocation) = &command { + // we check that the verb exists to avoid running a sequence + // of actions with some missing + match con.verb_store.search(&invocation.name) { + PrefixSearchResult::NoMatch => { + return Err(ProgramError::UnknownVerb { + name: invocation.name.to_string(), + }); + } + PrefixSearchResult::Matches(_) => { + return Err(ProgramError::AmbiguousVerbName { + name: invocation.name.to_string(), + }); + } + _ => {} + } + commands.push((input.to_string(), command)); + } + } + Ok(()) +} |