aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Jankowski <daniel.jankowski@rub.de>2023-11-22 20:15:14 +0100
committerDaniel Jankowski <daniel.jankowski@rub.de>2023-11-22 20:15:14 +0100
commit326c00e7e3620e7b93670e91070342f2a7c3d12e (patch)
treee804b384a37cc46bdf92797333588314a948c2f9 /src
parentchore: update cargo dependencies (diff)
downloadsl0pstatus-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.rs80
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);
+ }
+}