summaryrefslogtreecommitdiffstats
path: root/src/command
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2020-07-20 20:10:56 +0200
committerCanop <cano.petrole@gmail.com>2020-07-20 20:10:56 +0200
commit84d857e7fa6e8749c21b3c937c96cce9c25356e9 (patch)
tree878688bea2b4c54fbcd5b996cf5d098194e0a399 /src/command
parentf0cd893b028cec09bd7a35b3f4d00c64c31cea0f (diff)
"client-server" feature
Diffstat (limited to 'src/command')
-rw-r--r--src/command/mod.rs2
-rw-r--r--src/command/sequence.rs135
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(())
+}