feat(custom): escape variables so they expand on remote host
feat(ui): show command in global search results chore: bump version to 0.1.19
This commit is contained in:
parent
bc8f0de5c3
commit
498803fc55
5 changed files with 69 additions and 9 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -825,7 +825,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lines"
|
||||
version = "0.1.17"
|
||||
version = "0.1.19"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "lines"
|
||||
version = "0.1.18"
|
||||
version = "0.1.19"
|
||||
edition = "2024"
|
||||
authors = ["janvete"]
|
||||
description = "TUI for running frequently used commands"
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ Use `{}` as a placeholder if your lines are just addresses:
|
|||
ssh {} lsblk
|
||||
```
|
||||
|
||||
Variables like `$HOME` or `$USER` are treated as remote-shell variables, so they are expanded on the target host, not by your local shell.
|
||||
|
||||
## Global search
|
||||
|
||||
Press `/` to search across all commands, files, groups, and section names. Type your query, use `↑/↓` to select a result, and press `Enter` to run it.
|
||||
|
|
|
|||
|
|
@ -26,15 +26,32 @@ pub fn build_commands(state: &CustomState) -> Vec<String> {
|
|||
let built = if command.is_empty() {
|
||||
line.to_string()
|
||||
} else if command.contains("{}") {
|
||||
command.replace("{}", line)
|
||||
escape_dollars(&command.replace("{}", line))
|
||||
} else {
|
||||
format!("{} \"{}\"", line, command.replace('"', "\\\""))
|
||||
let escaped = escape_dollars(command).replace('"', "\\\"");
|
||||
format!("{} \"{}\"", line, escaped)
|
||||
};
|
||||
format!("{}{}", prefix, built)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Escape `$` as `\$` unless it is already escaped, so that variables are
|
||||
/// expanded by the remote shell rather than the local one when the built
|
||||
/// command is passed to `ssh`.
|
||||
fn escape_dollars(command: &str) -> String {
|
||||
let mut result = String::with_capacity(command.len());
|
||||
let mut prev_backslash = false;
|
||||
for c in command.chars() {
|
||||
if c == '$' && !prev_backslash {
|
||||
result.push('\\');
|
||||
}
|
||||
result.push(c);
|
||||
prev_backslash = c == '\\' && !prev_backslash;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
@ -125,4 +142,41 @@ mod tests {
|
|||
let state = make_state(vec!["ssh root@ip1", "ssh root@ip2"], vec![false, true], "", "lview");
|
||||
assert_eq!(build_commands(&state), vec!["lview ssh root@ip2"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_commands_escapes_dollar_variables() {
|
||||
let state = make_state(
|
||||
vec!["ssh root@ip1"],
|
||||
vec![true],
|
||||
"echo $HOME && echo $USER",
|
||||
"",
|
||||
);
|
||||
assert_eq!(
|
||||
build_commands(&state),
|
||||
vec!["ssh root@ip1 \"echo \\$HOME && echo \\$USER\""]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_commands_preserves_already_escaped_dollars() {
|
||||
let state = make_state(
|
||||
vec!["ssh root@ip1"],
|
||||
vec![true],
|
||||
"echo \\$HOME",
|
||||
"",
|
||||
);
|
||||
assert_eq!(
|
||||
build_commands(&state),
|
||||
vec!["ssh root@ip1 \"echo \\$HOME\""]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_commands_placeholder_escapes_dollars() {
|
||||
let state = make_state(vec!["root@ip1"], vec![true], "ssh {} echo $HOSTNAME", "");
|
||||
assert_eq!(
|
||||
build_commands(&state),
|
||||
vec!["ssh root@ip1 echo \\$HOSTNAME"]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
src/ui.rs
14
src/ui.rs
|
|
@ -173,11 +173,15 @@ fn draw_search(f: &mut Frame, app: &mut App) {
|
|||
} else {
|
||||
Style::default()
|
||||
};
|
||||
ListItem::new(format!(
|
||||
"[{}] {} — {}",
|
||||
result.group, result.file, result.section
|
||||
))
|
||||
.style(style)
|
||||
let label = if result.command.is_empty() {
|
||||
format!("[{}] {} — {}", result.group, result.file, result.section)
|
||||
} else {
|
||||
format!(
|
||||
"[{}] {} — {} — {}",
|
||||
result.group, result.file, result.section, result.command
|
||||
)
|
||||
};
|
||||
ListItem::new(label).style(style)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue