diff options
| author | chitao1234 <chotaotao1qaz2wsx@gmail.com> | 2025-09-14 23:18:41 +0800 |
|---|---|---|
| committer | Ellie Huxtable <ellie@elliehuxtable.com> | 2025-09-15 10:31:09 -0700 |
| commit | 0aedb4ddd9e6413d4025122675fe7423f43b5d7b (patch) | |
| tree | 5b015f8ec15c7dd022a93aedfb3cac057ff7931b /crates | |
| parent | chore(deps): bump debian (diff) | |
| download | atuin-0aedb4ddd9e6413d4025122675fe7423f43b5d7b.zip | |
feat: add session-preload filter mode to include global history from before session start
This mode mimics the default behavior for many shells.
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/atuin-client/config.toml | 4 | ||||
| -rw-r--r-- | crates/atuin-client/src/database.rs | 29 | ||||
| -rw-r--r-- | crates/atuin-client/src/settings.rs | 14 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/search/engines/skim.rs | 49 |
4 files changed, 93 insertions, 3 deletions
diff --git a/crates/atuin-client/config.toml b/crates/atuin-client/config.toml index 31294b38..80cdf809 100644 --- a/crates/atuin-client/config.toml +++ b/crates/atuin-client/config.toml @@ -41,7 +41,7 @@ # search_mode = "fuzzy" ## which filter mode to use by default -## possible values: "global", "host", "session", "directory", "workspace" +## possible values: "global", "host", "session", "session-preload", "directory", "workspace" ## consider using search.filters to customize the enablement and order of filter modes # filter_mode = "global" @@ -281,4 +281,4 @@ records = true ## The list of enabled filter modes, in order of priority. ## The "workspace" mode is skipped when not in a workspace or workspaces = false. ## Default filter mode can be overridden with the filter_mode setting. -# filters = [ "global", "host", "session", "workspace", "directory" ] +# filters = [ "global", "host", "session", "session-preload", "workspace", "directory" ] diff --git a/crates/atuin-client/src/database.rs b/crates/atuin-client/src/database.rs index fac0eb89..3c88350f 100644 --- a/crates/atuin-client/src/database.rs +++ b/crates/atuin-client/src/database.rs @@ -20,6 +20,7 @@ use sqlx::{ }, }; use time::OffsetDateTime; +use uuid::Uuid; use crate::{ history::{HistoryId, HistoryStats}, @@ -75,6 +76,16 @@ pub fn current_context() -> Context { } } +fn get_session_start_time(session_id: &str) -> Option<i64> { + if let Ok(uuid) = Uuid::parse_str(session_id) { + if let Some(timestamp) = uuid.get_timestamp() { + let (seconds, nanos) = timestamp.to_unix(); + return Some(seconds as i64 * 1_000_000_000 + nanos as i64); + } + } + None +} + #[async_trait] pub trait Database: Send + Sync + 'static { async fn save(&self, h: &History) -> Result<()>; @@ -316,11 +327,20 @@ impl Database for Sqlite { context.cwd.clone() }; + let session_start = get_session_start_time(&context.session); + for filter in filters { match filter { FilterMode::Global => &mut query, FilterMode::Host => query.and_where_eq("hostname", quote(&context.hostname)), FilterMode::Session => query.and_where_eq("session", quote(&context.session)), + FilterMode::SessionPreload => { + query.and_where_eq("session", quote(&context.session)); + if let Some(session_start) = session_start { + query.or_where_lt("timestamp", session_start); + } + &mut query + } FilterMode::Directory => query.and_where_eq("cwd", quote(&context.cwd)), FilterMode::Workspace => query.and_where_like_left("cwd", &git_root), }; @@ -437,12 +457,21 @@ impl Database for Sqlite { context.cwd.clone() }; + let session_start = get_session_start_time(&context.session); + match filter { FilterMode::Global => &mut sql, FilterMode::Host => { sql.and_where_eq("lower(hostname)", quote(context.hostname.to_lowercase())) } FilterMode::Session => sql.and_where_eq("session", quote(&context.session)), + FilterMode::SessionPreload => { + sql.and_where_eq("session", quote(&context.session)); + if let Some(session_start) = session_start { + sql.or_where_lt("timestamp", session_start); + } + &mut sql + } FilterMode::Directory => sql.and_where_eq("cwd", quote(&context.cwd)), FilterMode::Workspace => sql.and_where_like_left("cwd", git_root), }; diff --git a/crates/atuin-client/src/settings.rs b/crates/atuin-client/src/settings.rs index d9ebe00b..78d1f9b2 100644 --- a/crates/atuin-client/src/settings.rs +++ b/crates/atuin-client/src/settings.rs @@ -86,6 +86,9 @@ pub enum FilterMode { #[serde(rename = "workspace")] Workspace = 4, + + #[serde(rename = "session-preload")] + SessionPreload = 5, } impl FilterMode { @@ -96,6 +99,7 @@ impl FilterMode { FilterMode::Session => "SESSION", FilterMode::Directory => "DIRECTORY", FilterMode::Workspace => "WORKSPACE", + FilterMode::SessionPreload => "SESSION+", } } } @@ -420,6 +424,7 @@ impl Default for Search { FilterMode::Global, FilterMode::Host, FilterMode::Session, + FilterMode::SessionPreload, FilterMode::Workspace, FilterMode::Directory, ], @@ -814,7 +819,14 @@ impl Settings { .set_default("scripts.db_path", scripts_path.to_str())? .set_default( "search.filters", - vec!["global", "host", "session", "workspace", "directory"], + vec![ + "global", + "host", + "session", + "workspace", + "directory", + "session-preload", + ], )? .set_default("theme.name", "default")? .set_default("theme.debug", None::<bool>)? diff --git a/crates/atuin/src/command/client/search/engines/skim.rs b/crates/atuin/src/command/client/search/engines/skim.rs index e8aff7b4..dcf06e61 100644 --- a/crates/atuin/src/command/client/search/engines/skim.rs +++ b/crates/atuin/src/command/client/search/engines/skim.rs @@ -7,6 +7,7 @@ use fuzzy_matcher::{FuzzyMatcher, skim::SkimMatcherV2}; use itertools::Itertools; use time::OffsetDateTime; use tokio::task::yield_now; +use uuid; use super::{SearchEngine, SearchState}; @@ -83,6 +84,54 @@ async fn fuzzy_search( .as_bytes() .chunks(32) .contains(&context.session.as_bytes()) => {} + // SessionPreload: include current session + global history from before session start + FilterMode::SessionPreload => { + let is_current_session = { + history + .session + .as_bytes() + .chunks(32) + .any(|chunk| chunk == context.session.as_bytes()) + }; + + if !is_current_session { + let uuid = match uuid::Uuid::parse_str(&context.session) { + Ok(uuid) => uuid, + Err(_) => { + log::warn!("failed to parse session id '{}'", context.session); + continue; + } + }; + let timestamp = match uuid.get_timestamp() { + Some(timestamp) => timestamp, + None => { + log::warn!( + "failed to get timestamp from uuid '{}'", + uuid.as_hyphenated() + ); + continue; + } + }; + let (seconds, nanos) = timestamp.to_unix(); + let session_start = match time::OffsetDateTime::from_unix_timestamp_nanos( + seconds as i128 * 1_000_000_000 + nanos as i128, + ) { + Ok(session_start) => session_start, + Err(_) => { + log::warn!( + "failed to create OffsetDateTime from second: {}, nanosecond: {}", + seconds, + nanos + ); + continue; + } + }; + + if history.timestamp >= session_start { + continue; + } + } + } // we aggregate directory by ':' separating them FilterMode::Directory if history.cwd.split(':').contains(&context.cwd.as_str()) => {} FilterMode::Workspace if history.cwd.split(':').contains(&git_root) => {} |
