diff options
| author | Braelyn Boynton <bboynton97@gmail.com> | 2026-01-09 17:55:29 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-09 17:55:29 -0800 |
| commit | 1fa6ee265476e1c08eb812e16e3dcd2e711a9e0e (patch) | |
| tree | d71206ffc687df0bcbea14cbd47c39e222b3f3b0 | |
| parent | chore: add AGENTS.md (diff) | |
| download | atuin-1fa6ee265476e1c08eb812e16e3dcd2e711a9e0e.zip | |
feat: consider atuin dotfile aliases when calculating atuin wrapped (#3048)
<!-- Thank you for making a PR! Bug fixes are always welcome, but if
you're adding a new feature or changing an existing one, we'd really
appreciate if you open an issue, post on the forum, or drop in on
Discord -->
when i run `atuin wrapped` currently, my aliases get in the way of
properly calculating my wrapped.
Ex: `ga` -> `git add` -- not added to the `git` count
This PR changes the wrapped calculation to pull the aliases managed by
`atuin dotfiles` and expand aliased commands to calculate them properly.
### Performance
Tested with three shots each
Before change: `0.064` to `0.077` seconds
After change: `0.075` to `0.085` seconds
## Checks
- [x] I am happy for maintainers to push small adjustments to this PR,
to speed up the review cycle
- [x] I have checked that there are no existing pull requests for the
same thing
| -rw-r--r-- | crates/atuin/src/command/client.rs | 2 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/wrapped.rs | 54 |
2 files changed, 51 insertions, 5 deletions
diff --git a/crates/atuin/src/command/client.rs b/crates/atuin/src/command/client.rs index 330fef0c..a0d4373f 100644 --- a/crates/atuin/src/command/client.rs +++ b/crates/atuin/src/command/client.rs @@ -176,7 +176,7 @@ impl Cmd { Ok(()) } - Self::Wrapped { year } => wrapped::run(year, &db, &settings, theme).await, + Self::Wrapped { year } => wrapped::run(year, &db, &settings, sqlite_store, theme).await, #[cfg(feature = "daemon")] Self::Daemon => daemon::run(settings, sqlite_store, db).await, diff --git a/crates/atuin/src/command/client/wrapped.rs b/crates/atuin/src/command/client/wrapped.rs index 12357ece..ad578f7b 100644 --- a/crates/atuin/src/command/client/wrapped.rs +++ b/crates/atuin/src/command/client/wrapped.rs @@ -3,7 +3,11 @@ use eyre::Result; use std::collections::{HashMap, HashSet}; use time::{Date, Duration, Month, OffsetDateTime, Time}; -use atuin_client::{database::Database, settings::Settings, theme::Theme}; +use atuin_client::{ + database::Database, encryption, record::sqlite_store::SqliteStore, settings::Settings, + theme::Theme, +}; +use atuin_dotfiles::store::AliasStore; use atuin_history::stats::{Stats, compute}; @@ -20,7 +24,26 @@ struct WrappedStats { impl WrappedStats { #[allow(clippy::too_many_lines, clippy::cast_precision_loss)] - fn new(settings: &Settings, stats: &Stats, history: &[atuin_client::history::History]) -> Self { + fn new( + settings: &Settings, + stats: &Stats, + history: &[atuin_client::history::History], + alias_map: &HashMap<String, String>, + ) -> Self { + // Helper to expand alias to its first command word + let expand_alias = |cmd: &str| -> String { + alias_map.get(cmd).map_or_else( + || cmd.to_string(), + |expanded| { + expanded + .split_whitespace() + .next() + .unwrap_or(cmd) + .to_string() + }, + ) + }; + let nav_commands = stats .top .iter() @@ -96,12 +119,13 @@ impl WrappedStats { let mut hours: HashMap<String, usize> = HashMap::new(); for entry in history { - let cmd = entry + let raw_cmd = entry .command .split_whitespace() .next() .unwrap_or("") .to_string(); + let cmd = expand_alias(&raw_cmd); let (total, errors) = command_errors.entry(cmd.clone()).or_insert((0, 0)); *total += 1; if entry.exit != 0 { @@ -266,6 +290,7 @@ pub async fn run( year: Option<i32>, db: &impl Database, settings: &Settings, + store: SqliteStore, theme: &Theme, ) -> Result<()> { let now = OffsetDateTime::now_utc().to_offset(settings.timezone.0); @@ -299,9 +324,30 @@ pub async fn run( return Ok(()); } + // Load aliases for expansion + let alias_map: HashMap<String, String> = if settings.dotfiles.enabled { + if let Ok(encryption_key) = encryption::load_key(settings) { + let encryption_key: [u8; 32] = encryption_key.into(); + let host_id = Settings::host_id().expect("failed to get host_id"); + let alias_store = AliasStore::new(store, host_id, encryption_key); + + alias_store + .aliases() + .await + .unwrap_or_default() + .into_iter() + .map(|a| (a.name, a.value)) + .collect() + } else { + HashMap::new() + } + } else { + HashMap::new() + }; + // Compute overall stats using existing functionality let stats = compute(settings, &history, 10, 1).expect("Failed to compute stats"); - let wrapped_stats = WrappedStats::new(settings, &stats, &history); + let wrapped_stats = WrappedStats::new(settings, &stats, &history, &alias_map); // Print wrapped format print_wrapped_header(year); |
