diff options
| author | Daniel Jankowski <daniel.jankowski@rub.de> | 2023-11-22 20:15:14 +0100 |
|---|---|---|
| committer | Daniel Jankowski <daniel.jankowski@rub.de> | 2023-11-22 20:15:14 +0100 |
| commit | 326c00e7e3620e7b93670e91070342f2a7c3d12e (patch) | |
| tree | e804b384a37cc46bdf92797333588314a948c2f9 /src | |
| parent | chore: update cargo dependencies (diff) | |
| download | sl0pstatus-326c00e7e3620e7b93670e91070342f2a7c3d12e.tar.gz sl0pstatus-326c00e7e3620e7b93670e91070342f2a7c3d12e.tar.xz sl0pstatus-326c00e7e3620e7b93670e91070342f2a7c3d12e.zip | |
fix: handle groups when running commands
Instead of naively splitting at spaces, zjstatus now
respects groups with " and ' to enable using more complex
arguments, e.g. bash -c "pwd | base64".
Resolves #22
Diffstat (limited to 'src')
| -rw-r--r-- | src/widgets/command.rs | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/src/widgets/command.rs b/src/widgets/command.rs index 42297da..be54c73 100644 --- a/src/widgets/command.rs +++ b/src/widgets/command.rs @@ -108,7 +108,8 @@ fn run_command_if_needed(command_config: CommandConfig, name: &str, state: crate ts.format(TIMESTAMP_FORMAT).to_string(), ); - let command = command_config.command.split(' ').collect::<Vec<&str>>(); + let command = commandline_parser(&command_config.command); + let command = command.iter().map(|x| x.as_str()).collect::<Vec<&str>>(); run_command(&command, context); } } @@ -116,8 +117,8 @@ fn run_command_if_needed(command_config: CommandConfig, name: &str, state: crate fn parse_config(zj_conf: BTreeMap<String, String>) -> BTreeMap<String, CommandConfig> { let mut keys: Vec<String> = zj_conf .keys() - .cloned() .filter(|k| k.starts_with("command_")) + .cloned() .collect(); keys.sort(); @@ -206,3 +207,78 @@ fn release(name: &str, state: crate::ZellijState) { let _ = remove_file(path); } } + +fn commandline_parser(input: &str) -> Vec<String> { + let mut output: Vec<String> = Vec::new(); + + let special_chars = ['"', '\'']; + + let mut found_special_char = '\0'; + let mut buffer = "".to_owned(); + let mut is_escaped = false; + let mut is_in_group = false; + + for character in input.chars() { + if is_escaped { + is_escaped = false; + buffer = format!("{}\\{}", buffer.to_owned(), character); + continue; + } + + if character == '\\' { + is_escaped = true; + continue; + } + + if found_special_char == character && is_in_group { + is_in_group = false; + found_special_char = '\0'; + output.push(buffer.clone()); + buffer = "".to_owned(); + continue; + } + + if special_chars.contains(&character) && !is_in_group { + is_in_group = true; + found_special_char = character; + continue; + } + + if character == ' ' && !is_in_group { + output.push(buffer.clone()); + buffer = "".to_owned(); + continue; + } + + buffer = format!("{}{}", buffer, character); + } + + if !buffer.is_empty() { + output.push(buffer.clone()); + } + + output +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + pub fn test_commandline_parser() { + let input = "pwd"; + let result = commandline_parser(input); + let expected = Vec::from(["pwd"]); + assert_eq!(result, expected); + + let input = "bash -c \"pwd | base64 -c \\\"bla\\\"\""; + let result = commandline_parser(input); + let expected = Vec::from(["bash", "-c", "pwd | base64 -c \\\"bla\\\""]); + assert_eq!(result, expected); + + let input = "bash -c \"pwd | base64 -c 'bla' | xxd\""; + let result = commandline_parser(input); + let expected = Vec::from(["bash", "-c", "pwd | base64 -c 'bla' | xxd"]); + assert_eq!(result, expected); + } +} |
