diff options
| author | Ellie Huxtable <ellie@elliehuxtable.com> | 2023-11-23 09:48:43 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-23 09:48:43 +0000 |
| commit | 0c9d7367c66d5042348c46869ca4a8aa71aa6c86 (patch) | |
| tree | dfce8f68edaffcf680e3ce54fb2e8e360d972ef2 | |
| parent | docs: Update Arch Linux package URL in advanced-install.md (#1407) (diff) | |
| download | atuin-0c9d7367c66d5042348c46869ca4a8aa71aa6c86.zip | |
feat: allow configuring stats prefix (#1411)
| -rw-r--r-- | atuin-client/src/settings.rs | 24 | ||||
| -rw-r--r-- | atuin/src/command/client/stats.rs | 40 |
2 files changed, 50 insertions, 14 deletions
diff --git a/atuin-client/src/settings.rs b/atuin-client/src/settings.rs index fca76004..c5e72025 100644 --- a/atuin-client/src/settings.rs +++ b/atuin-client/src/settings.rs @@ -144,6 +144,24 @@ pub enum WordJumpMode { } #[derive(Clone, Debug, Deserialize)] +pub struct Stats { + pub common_prefix: Vec<String>, // sudo, etc. commands we want to strip off + pub common_subcommands: Vec<String>, // kubectl, commands we should consider subcommands for +} + +impl Default for Stats { + fn default() -> Self { + Self { + common_prefix: vec!["sudo", "doas"].into_iter().map(String::from).collect(), + common_subcommands: vec!["cargo", "go", "git", "npm", "yarn", "pnpm", "kubectl"] + .into_iter() + .map(String::from) + .collect(), + } + } +} + +#[derive(Clone, Debug, Deserialize)] pub struct Settings { pub dialect: Dialect, pub style: Style, @@ -169,10 +187,13 @@ pub struct Settings { pub word_jump_mode: WordJumpMode, pub word_chars: String, pub scroll_context_lines: usize, + #[serde(with = "serde_regex", default = "RegexSet::empty")] pub history_filter: RegexSet, + #[serde(with = "serde_regex", default = "RegexSet::empty")] pub cwd_filter: RegexSet, + pub secrets_filter: bool, pub workspaces: bool, pub ctrl_n_shortcuts: bool, @@ -181,6 +202,9 @@ pub struct Settings { pub network_timeout: u64, pub enter_accept: bool, + #[serde(default)] + pub stats: Stats, + // This is automatically loaded when settings is created. Do not set in // config! Keep secrets and settings apart. pub session_token: String, diff --git a/atuin/src/command/client/stats.rs b/atuin/src/command/client/stats.rs index 625c6beb..27ff362d 100644 --- a/atuin/src/command/client/stats.rs +++ b/atuin/src/command/client/stats.rs @@ -23,14 +23,16 @@ pub struct Cmd { count: usize, } -fn compute_stats(history: &[History], count: usize) -> Result<()> { +fn compute_stats(settings: &Settings, history: &[History], count: usize) -> Result<()> { let mut commands = HashSet::<&str>::with_capacity(history.len()); let mut prefixes = HashMap::<&str, usize>::with_capacity(history.len()); for i in history { // just in case it somehow has a leading tab or space or something (legacy atuin didn't ignore space prefixes) let command = i.command.trim(); commands.insert(command); - *prefixes.entry(interesting_command(command)).or_default() += 1; + *prefixes + .entry(interesting_command(settings, command)) + .or_default() += 1; } let unique = commands.len(); @@ -109,15 +111,11 @@ impl Cmd { let end = start + Duration::days(1); db.range(start, end).await? }; - compute_stats(&history, self.count)?; + compute_stats(settings, &history, self.count)?; Ok(()) } } -// TODO: make this configurable? -static COMMON_COMMAND_PREFIX: &[&str] = &["sudo"]; -static COMMON_SUBCOMMAND_PREFIX: &[&str] = &["cargo", "go", "git", "npm", "yarn", "pnpm"]; - fn first_non_whitespace(s: &str) -> Option<usize> { s.char_indices() // find the first non whitespace char @@ -134,7 +132,7 @@ fn first_whitespace(s: &str) -> usize { .map_or(s.len(), |(i, _)| i) } -fn interesting_command(mut command: &str) -> &str { +fn interesting_command<'a>(settings: &Settings, mut command: &'a str) -> &'a str { // compute command prefix // we loop here because we might be working with a common command prefix (eg sudo) that we want to trim off let (i, prefix) = loop { @@ -142,7 +140,7 @@ fn interesting_command(mut command: &str) -> &str { let prefix = &command[..i]; // is it a common prefix - if COMMON_COMMAND_PREFIX.contains(&prefix) { + if settings.stats.common_prefix.contains(&String::from(prefix)) { command = command[i..].trim_start(); if command.is_empty() { // no commands following, just use the prefix @@ -164,7 +162,14 @@ fn interesting_command(mut command: &str) -> &str { match subcommand_indices { // if there is a subcommand and it's a common one, then count the full prefix + subcommand - Some(end) if COMMON_SUBCOMMAND_PREFIX.contains(&prefix) => &command[..end], + Some(end) + if settings + .stats + .common_subcommands + .contains(&String::from(prefix)) => + { + &command[..end] + } // otherwise just count the main command _ => prefix, } @@ -172,16 +177,23 @@ fn interesting_command(mut command: &str) -> &str { #[cfg(test)] mod tests { + use atuin_client::settings::Settings; + use super::interesting_command; #[test] fn interesting_commands() { - assert_eq!(interesting_command("cargo"), "cargo"); - assert_eq!(interesting_command("cargo build foo bar"), "cargo build"); + let settings = Settings::default(); + + assert_eq!(interesting_command(&settings, "cargo"), "cargo"); + assert_eq!( + interesting_command(&settings, "cargo build foo bar"), + "cargo build" + ); assert_eq!( - interesting_command("sudo cargo build foo bar"), + interesting_command(&settings, "sudo cargo build foo bar"), "cargo build" ); - assert_eq!(interesting_command("sudo"), "sudo"); + assert_eq!(interesting_command(&settings, "sudo"), "sudo"); } } |
