Skip to content

Commit

Permalink
feat(client): Allow sorting filter modes
Browse files Browse the repository at this point in the history
  • Loading branch information
dasJ committed May 19, 2024
1 parent 95c9168 commit 29fb01c
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 50 deletions.
7 changes: 6 additions & 1 deletion crates/atuin-client/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,15 @@
## possible values: prefix, fulltext, fuzzy, skim
# search_mode = "fuzzy"

## which filter mode to use
## which filter mode to use by default
## possible values: global, host, session, directory
## defaults to the first element of 'filter_modes'
# filter_mode = "global"

## which filter modes are available in which order.
## 'workspace' is skipped when not in a workspace or disabled
# filter_modes = [ "workspace", "global", "host", "session", "directory" ]

## With workspace filtering enabled, Atuin will filter for commands executed
## in any directory within a git repository tree (default: false)
# workspaces = false
Expand Down
9 changes: 7 additions & 2 deletions crates/atuin-client/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ pub struct Settings {
pub key_path: String,
pub session_path: String,
pub search_mode: SearchMode,
pub filter_mode: FilterMode,
pub filter_mode: Option<FilterMode>,
pub filter_modes: Vec<FilterMode>,
pub filter_mode_shell_up_key_binding: Option<FilterMode>,
pub search_mode_shell_up_key_binding: Option<SearchMode>,
pub shell_up_key_binding: bool,
Expand Down Expand Up @@ -671,7 +672,11 @@ impl Settings {
.set_default("sync_address", "https://api.atuin.sh")?
.set_default("sync_frequency", "10m")?
.set_default("search_mode", "fuzzy")?
.set_default("filter_mode", "global")?
.set_default("filter_mode", None::<String>)?
.set_default(
"filter_modes",
vec!["workspace", "global", "host", "session"],
)?
.set_default("style", "auto")?
.set_default("inline_height", 0)?
.set_default("show_preview", true)?
Expand Down
7 changes: 6 additions & 1 deletion crates/atuin/src/command/client/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,12 @@ impl Cmd {
(true, true) => [Session, Directory],
(true, false) => [Session, Global],
(false, true) => [Global, Directory],
(false, false) => [settings.filter_mode, Global],
(false, false) => [
settings
.filter_mode
.unwrap_or(*settings.filter_modes.first().unwrap_or(&Global)),
Global,
],
};

let history = db
Expand Down
18 changes: 12 additions & 6 deletions crates/atuin/src/command/client/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ impl Cmd {
settings.search_mode = self.search_mode.unwrap();
}
if self.filter_mode.is_some() {
settings.filter_mode = self.filter_mode.unwrap();
settings.filter_mode = self.filter_mode;
}
if self.inline_height.is_some() {
settings.inline_height = self.inline_height.unwrap();
Expand Down Expand Up @@ -287,11 +287,17 @@ async fn run_non_interactive(
};

let dir = dir.unwrap_or_else(|| "/".to_string());
let filter_mode = if settings.workspaces && utils::has_git_dir(dir.as_str()) {
FilterMode::Workspace
} else {
settings.filter_mode
};
let filter_mode = settings.filter_mode.unwrap_or(
*settings
.filter_modes
.iter()
.find(|item| {
*item != &FilterMode::Workspace
|| !settings.workspaces
|| utils::has_git_dir(dir.as_str())
})
.unwrap_or(&FilterMode::Global),
);

let results = db
.search(
Expand Down
11 changes: 9 additions & 2 deletions crates/atuin/src/command/client/search/engines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ pub fn engine(search_mode: SearchMode) -> Box<dyn SearchEngine> {

pub struct SearchState {
pub input: Cursor,
pub filter_mode: FilterMode,
pub filter_mode_index: usize,
pub available_filter_modes: Vec<FilterMode>,
pub context: Context,
}

Expand All @@ -35,7 +36,13 @@ pub trait SearchEngine: Send + Sync + 'static {
async fn query(&mut self, state: &SearchState, db: &mut dyn Database) -> Result<Vec<History>> {
if state.input.as_str().is_empty() {
Ok(db
.list(&[state.filter_mode], &state.context, Some(200), true, false)
.list(
&[state.available_filter_modes[state.filter_mode_index]],
&state.context,
Some(200),
true,
false,
)
.await?
.into_iter()
.collect::<Vec<_>>())
Expand Down
2 changes: 1 addition & 1 deletion crates/atuin/src/command/client/search/engines/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl SearchEngine for Search {
Ok(db
.search(
self.0,
state.filter_mode,
state.available_filter_modes[state.filter_mode_index],
&state.context,
state.input.as_str(),
OptFilters {
Expand Down
13 changes: 7 additions & 6 deletions crates/atuin/src/command/client/search/engines/skim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,26 @@ async fn fuzzy_search(
.as_ref()
.and_then(|git_root| git_root.to_str())
.unwrap_or(&context.cwd);
match state.filter_mode {
FilterMode::Global => {}
match state.available_filter_modes.get(state.filter_mode_index) {
Some(FilterMode::Global) => {}
// we aggregate host by ',' separating them
FilterMode::Host
Some(FilterMode::Host)
if history
.hostname
.split(',')
.contains(&context.hostname.as_str()) => {}
// we aggregate session by concattenating them.
// sessions are 32 byte simple uuid formats
FilterMode::Session
Some(FilterMode::Session)
if history
.session
.as_bytes()
.chunks(32)
.contains(&context.session.as_bytes()) => {}
// 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) => {}
Some(FilterMode::Directory)
if history.cwd.split(':').contains(&context.cwd.as_str()) => {}
Some(FilterMode::Workspace) if history.cwd.split(':').contains(&git_root) => {}
_ => continue,
}
#[allow(clippy::cast_lossless, clippy::cast_precision_loss)]
Expand Down
78 changes: 47 additions & 31 deletions crates/atuin/src/command/client/search/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,27 +452,8 @@ impl State {
}
KeyCode::Char('u') if ctrl => self.search.input.clear(),
KeyCode::Char('r') if ctrl => {
let filter_modes = if settings.workspaces && self.search.context.git_root.is_some()
{
vec![
FilterMode::Global,
FilterMode::Host,
FilterMode::Session,
FilterMode::Directory,
FilterMode::Workspace,
]
} else {
vec![
FilterMode::Global,
FilterMode::Host,
FilterMode::Session,
FilterMode::Directory,
]
};

let i = self.search.filter_mode as usize;
let i = (i + 1) % filter_modes.len();
self.search.filter_mode = filter_modes[i];
self.search.filter_mode_index =
(self.search.filter_mode_index + 1) % self.search.available_filter_modes.len();
}
KeyCode::Char('s') if ctrl => {
self.switched_search_mode = true;
Expand Down Expand Up @@ -848,7 +829,10 @@ impl State {
let (pref, mode) = if self.switched_search_mode {
(" SRCH:", self.search_mode.as_str())
} else {
("", self.search.filter_mode.as_str())
(
"",
self.search.available_filter_modes[self.search.filter_mode_index].as_str(),
)
};
let mode_width = MAX_WIDTH - pref.len();
// sanity check to ensure we don't exceed the layout limits
Expand Down Expand Up @@ -1018,6 +1002,28 @@ pub async fn history(
} else {
settings.search_mode
};
let mut available_filter_modes = settings
.filter_modes
.clone()
.into_iter()
.filter(|item| {
*item != FilterMode::Workspace || !settings.workspaces || context.git_root.is_some()
})
.collect::<Vec<_>>();
if available_filter_modes.is_empty() {
available_filter_modes = vec![
FilterMode::Workspace,
FilterMode::Global,
FilterMode::Host,
FilterMode::Session,
]
.into_iter()
.filter(|item| {
*item != FilterMode::Workspace || !settings.workspaces || context.git_root.is_some()
})
.collect::<Vec<_>>();
}

let mut app = State {
history_count,
results_state: ListState::default(),
Expand All @@ -1027,15 +1033,24 @@ pub async fn history(
tab_index: 0,
search: SearchState {
input,
filter_mode: if settings.workspaces && context.git_root.is_some() {
FilterMode::Workspace
} else if settings.shell_up_key_binding {
settings
.filter_mode_shell_up_key_binding
.unwrap_or(settings.filter_mode)
filter_mode_index: if settings.shell_up_key_binding {
available_filter_modes
.iter()
.position(|&item| {
item == settings
.filter_mode_shell_up_key_binding
.unwrap_or(FilterMode::Global)
})
.unwrap_or_default()
} else if let Some(filter_mode) = settings.filter_mode {
available_filter_modes
.iter()
.position(|&item| item == filter_mode)
.unwrap_or_default()
} else {
settings.filter_mode
0
},
available_filter_modes,
context,
},
engine: engines::engine(search_mode),
Expand Down Expand Up @@ -1065,7 +1080,7 @@ pub async fn history(
terminal.draw(|f| app.draw(f, &results, stats.clone(), settings))?;

let initial_input = app.search.input.as_str().to_owned();
let initial_filter_mode = app.search.filter_mode;
let initial_filter_mode = app.search.available_filter_modes[app.search.filter_mode_index];
let initial_search_mode = app.search_mode;

let event_ready = tokio::task::spawn_blocking(|| event::poll(Duration::from_millis(250)));
Expand Down Expand Up @@ -1115,7 +1130,8 @@ pub async fn history(
}

if initial_input != app.search.input.as_str()
|| initial_filter_mode != app.search.filter_mode
|| initial_filter_mode
!= app.search.available_filter_modes[app.search.filter_mode_index]
|| initial_search_mode != app.search_mode
{
results = app.query_results(&mut db, settings.smart_sort).await?;
Expand Down

0 comments on commit 29fb01c

Please sign in to comment.