mirror of
https://github.com/atuinsh/atuin.git
synced 2025-02-25 14:52:35 +01:00
feat: allow spaces in stats prefixes (#1414)
This commit is contained in:
parent
b530d39c3f
commit
e09571153c
@ -133,46 +133,44 @@ fn first_whitespace(s: &str) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn interesting_command<'a>(settings: &Settings, mut command: &'a str) -> &'a str {
|
fn interesting_command<'a>(settings: &Settings, mut command: &'a str) -> &'a str {
|
||||||
// compute command prefix
|
// Sort by length so that we match the longest prefix first
|
||||||
// we loop here because we might be working with a common command prefix (eg sudo) that we want to trim off
|
let mut common_prefix = settings.stats.common_prefix.clone();
|
||||||
let (i, prefix) = loop {
|
common_prefix.sort_by_key(|b| std::cmp::Reverse(b.len()));
|
||||||
let i = first_whitespace(command);
|
|
||||||
let prefix = &command[..i];
|
|
||||||
|
|
||||||
// is it a common prefix
|
// Trim off the common prefix, if it exists
|
||||||
if settings.stats.common_prefix.contains(&String::from(prefix)) {
|
for p in &common_prefix {
|
||||||
|
if command.starts_with(p) {
|
||||||
|
let i = p.len();
|
||||||
|
let prefix = &command[..i];
|
||||||
command = command[i..].trim_start();
|
command = command[i..].trim_start();
|
||||||
if command.is_empty() {
|
if command.is_empty() {
|
||||||
// no commands following, just use the prefix
|
// no commands following, just use the prefix
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
break (i, prefix);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// compute subcommand
|
|
||||||
let subcommand_indices = command
|
|
||||||
// after the end of the command prefix
|
|
||||||
.get(i..)
|
|
||||||
// find the first non whitespace character (start of subcommand)
|
|
||||||
.and_then(first_non_whitespace)
|
|
||||||
// then find the end of that subcommand
|
|
||||||
.map(|j| i + j + first_whitespace(&command[i + j..]));
|
|
||||||
|
|
||||||
match subcommand_indices {
|
|
||||||
// if there is a subcommand and it's a common one, then count the full prefix + subcommand
|
|
||||||
Some(end)
|
|
||||||
if settings
|
|
||||||
.stats
|
|
||||||
.common_subcommands
|
|
||||||
.contains(&String::from(prefix)) =>
|
|
||||||
{
|
|
||||||
&command[..end]
|
|
||||||
}
|
|
||||||
// otherwise just count the main command
|
|
||||||
_ => prefix,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort the common_subcommands by length so that we match the longest subcommand first
|
||||||
|
let mut common_subcommands = settings.stats.common_subcommands.clone();
|
||||||
|
common_subcommands.sort_by_key(|b| std::cmp::Reverse(b.len()));
|
||||||
|
|
||||||
|
// Check for a common subcommand
|
||||||
|
for p in &common_subcommands {
|
||||||
|
if command.starts_with(p) {
|
||||||
|
// if the subcommand is the same length as the command, then we just use the subcommand
|
||||||
|
if p.len() == command.len() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
// otherwise we need to use the subcommand + the next word
|
||||||
|
let non_whitespace = first_non_whitespace(&command[p.len()..]).unwrap_or(0);
|
||||||
|
let j =
|
||||||
|
p.len() + non_whitespace + first_whitespace(&command[p.len() + non_whitespace..]);
|
||||||
|
return &command[..j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return the first word if there is no subcommand
|
||||||
|
&command[..first_whitespace(command)]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -196,4 +194,87 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(interesting_command(&settings, "sudo"), "sudo");
|
assert_eq!(interesting_command(&settings, "sudo"), "sudo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test with spaces in the common_prefix
|
||||||
|
#[test]
|
||||||
|
fn interesting_commands_spaces() {
|
||||||
|
let mut settings = Settings::default();
|
||||||
|
settings.stats.common_prefix.push("sudo test".to_string());
|
||||||
|
|
||||||
|
assert_eq!(interesting_command(&settings, "sudo test"), "sudo test");
|
||||||
|
assert_eq!(interesting_command(&settings, "sudo test "), "sudo test");
|
||||||
|
assert_eq!(interesting_command(&settings, "sudo test foo bar"), "foo");
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "sudo test foo bar"),
|
||||||
|
"foo"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Works with a common_subcommand as well
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "sudo test cargo build foo bar"),
|
||||||
|
"cargo build"
|
||||||
|
);
|
||||||
|
|
||||||
|
// We still match on just the sudo prefix
|
||||||
|
assert_eq!(interesting_command(&settings, "sudo"), "sudo");
|
||||||
|
assert_eq!(interesting_command(&settings, "sudo foo"), "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with spaces in the common_subcommand
|
||||||
|
#[test]
|
||||||
|
fn interesting_commands_spaces_subcommand() {
|
||||||
|
let mut settings = Settings::default();
|
||||||
|
settings
|
||||||
|
.stats
|
||||||
|
.common_subcommands
|
||||||
|
.push("cargo build".to_string());
|
||||||
|
|
||||||
|
assert_eq!(interesting_command(&settings, "cargo build"), "cargo build");
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "cargo build "),
|
||||||
|
"cargo build"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "cargo build foo bar"),
|
||||||
|
"cargo build foo"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Works with a common_prefix as well
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "sudo cargo build foo bar"),
|
||||||
|
"cargo build foo"
|
||||||
|
);
|
||||||
|
|
||||||
|
// We still match on just cargo as a subcommand
|
||||||
|
assert_eq!(interesting_command(&settings, "cargo"), "cargo");
|
||||||
|
assert_eq!(interesting_command(&settings, "cargo foo"), "cargo foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with spaces in the common_prefix and common_subcommand
|
||||||
|
#[test]
|
||||||
|
fn interesting_commands_spaces_both() {
|
||||||
|
let mut settings = Settings::default();
|
||||||
|
settings.stats.common_prefix.push("sudo test".to_string());
|
||||||
|
settings
|
||||||
|
.stats
|
||||||
|
.common_subcommands
|
||||||
|
.push("cargo build".to_string());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "sudo test cargo build"),
|
||||||
|
"cargo build"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "sudo test cargo build"),
|
||||||
|
"cargo build"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "sudo test cargo build "),
|
||||||
|
"cargo build"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
interesting_command(&settings, "sudo test cargo build foo bar"),
|
||||||
|
"cargo build foo"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user