Skip to content

Commit b01b78e

Browse files
committed
feat(client): add filter mode enablement and ordering configuration
1 parent 5c29057 commit b01b78e

File tree

6 files changed

+87
-46
lines changed

6 files changed

+87
-46
lines changed

crates/atuin-client/config.toml

+14-3
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,17 @@
4040
## possible values: prefix, fulltext, fuzzy, skim
4141
# search_mode = "fuzzy"
4242

43-
## which filter mode to use
44-
## possible values: global, host, session, directory
43+
## which filter mode to use by default
44+
## possible values: "global", "host", "session", "directory", "workspace"
45+
## consider using search.filters to customize the enablement and order of filter modes
4546
# filter_mode = "global"
4647

4748
## With workspace filtering enabled, Atuin will filter for commands executed
48-
## in any directory within a git repository tree (default: false)
49+
## in any directory within a git repository tree (default: false).
50+
##
51+
## To use workspace mode by default when available, set this to true and
52+
## set filter_mode to "workspace" or leave it unspecified and
53+
## set search.filters to include "workspace" before other filter modes.
4954
# workspaces = false
5055

5156
## which filter mode to use when atuin is invoked from a shell up-key binding
@@ -254,3 +259,9 @@ records = true
254259
## Whether the theme manager should output normal or extra information to help fix themes.
255260
## Boolean, true or false. If unset, left up to the theme manager.
256261
# debug = true
262+
263+
[search]
264+
## The list of enabled filter modes, in order of priority.
265+
## The "workspace" mode is skipped when not in a workspace or workspaces = false.
266+
## Default filter mode can be overridden with the filter_mode setting.
267+
# filters = [ "global", "host", "session", "workspace", "directory" ]

crates/atuin-client/src/settings.rs

+36-2
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,12 @@ pub struct Daemon {
370370
pub tcp_port: u64,
371371
}
372372

373+
#[derive(Clone, Debug, Deserialize, Serialize)]
374+
pub struct Search {
375+
/// The list of enabled filter modes, in order of priority.
376+
pub filters: Vec<FilterMode>,
377+
}
378+
373379
impl Default for Preview {
374380
fn default() -> Self {
375381
Self {
@@ -400,6 +406,20 @@ impl Default for Daemon {
400406
}
401407
}
402408

409+
impl Default for Search {
410+
fn default() -> Self {
411+
Self {
412+
filters: vec![
413+
FilterMode::Global,
414+
FilterMode::Host,
415+
FilterMode::Session,
416+
FilterMode::Workspace,
417+
FilterMode::Directory,
418+
],
419+
}
420+
}
421+
}
422+
403423
// The preview height strategy also takes max_preview_height into account.
404424
#[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)]
405425
pub enum PreviewStrategy {
@@ -430,7 +450,7 @@ pub struct Settings {
430450
pub key_path: String,
431451
pub session_path: String,
432452
pub search_mode: SearchMode,
433-
pub filter_mode: FilterMode,
453+
pub filter_mode: Option<FilterMode>,
434454
pub filter_mode_shell_up_key_binding: Option<FilterMode>,
435455
pub search_mode_shell_up_key_binding: Option<SearchMode>,
436456
pub shell_up_key_binding: bool,
@@ -486,6 +506,9 @@ pub struct Settings {
486506
#[serde(default)]
487507
pub daemon: Daemon,
488508

509+
#[serde(default)]
510+
pub search: Search,
511+
489512
#[serde(default)]
490513
pub theme: Theme,
491514
}
@@ -688,6 +711,13 @@ impl Settings {
688711
None
689712
}
690713

714+
pub fn default_filter_mode(&self) -> FilterMode {
715+
self.filter_mode
716+
.filter(|x| self.search.filters.contains(x))
717+
.or(self.search.filters.first().copied())
718+
.unwrap_or(FilterMode::Global)
719+
}
720+
691721
#[cfg(not(feature = "check-update"))]
692722
pub async fn needs_update(&self) -> Option<Version> {
693723
None
@@ -715,7 +745,7 @@ impl Settings {
715745
.set_default("sync_address", "https://api.atuin.sh")?
716746
.set_default("sync_frequency", "10m")?
717747
.set_default("search_mode", "fuzzy")?
718-
.set_default("filter_mode", "global")?
748+
.set_default("filter_mode", None::<String>)?
719749
.set_default("style", "compact")?
720750
.set_default("inline_height", 40)?
721751
.set_default("show_preview", true)?
@@ -758,6 +788,10 @@ impl Settings {
758788
.set_default("daemon.socket_path", socket_path.to_str())?
759789
.set_default("daemon.systemd_socket", false)?
760790
.set_default("daemon.tcp_port", 8889)?
791+
.set_default(
792+
"search.filters",
793+
vec!["global", "host", "session", "workspace", "directory"],
794+
)?
761795
.set_default("theme.name", "default")?
762796
.set_default("theme.debug", None::<bool>)?
763797
.set_default(

crates/atuin/src/command/client/history.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ impl Cmd {
466466
(true, true) => [Session, Directory],
467467
(true, false) => [Session, Global],
468468
(false, true) => [Global, Directory],
469-
(false, false) => [settings.filter_mode, Global],
469+
(false, false) => [settings.default_filter_mode(), Global],
470470
};
471471

472472
let history = db

crates/atuin/src/command/client/search.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl Cmd {
176176
settings.search_mode = self.search_mode.unwrap();
177177
}
178178
if self.filter_mode.is_some() {
179-
settings.filter_mode = self.filter_mode.unwrap();
179+
settings.filter_mode = self.filter_mode;
180180
}
181181
if self.inline_height.is_some() {
182182
settings.inline_height = self.inline_height.unwrap();
@@ -287,12 +287,7 @@ async fn run_non_interactive(
287287
..filter_options
288288
};
289289

290-
let dir = dir.unwrap_or_else(|| "/".to_string());
291-
let filter_mode = if settings.workspaces && utils::has_git_dir(dir.as_str()) {
292-
FilterMode::Workspace
293-
} else {
294-
settings.filter_mode
295-
};
290+
let filter_mode = settings.default_filter_mode();
296291

297292
let results = db
298293
.search(

crates/atuin/src/command/client/search/engines.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use async_trait::async_trait;
22
use atuin_client::{
33
database::{Context, Database},
44
history::History,
5-
settings::{FilterMode, SearchMode},
5+
settings::{FilterMode, SearchMode, Settings},
66
};
77
use eyre::Result;
88

@@ -24,6 +24,32 @@ pub struct SearchState {
2424
pub context: Context,
2525
}
2626

27+
impl SearchState {
28+
pub(crate) fn rotate_filter_mode(&mut self, settings: &Settings, offset: isize) {
29+
let mut i = settings
30+
.search
31+
.filters
32+
.iter()
33+
.position(|&m| m == self.filter_mode)
34+
.unwrap_or_default();
35+
for _ in 0..settings.search.filters.len() {
36+
i = (i.wrapping_add_signed(offset)) % settings.search.filters.len();
37+
let mode = settings.search.filters[i];
38+
if self.filter_mode_available(mode, settings) {
39+
self.filter_mode = mode;
40+
break;
41+
}
42+
}
43+
}
44+
45+
fn filter_mode_available(&self, mode: FilterMode, settings: &Settings) -> bool {
46+
match mode {
47+
FilterMode::Workspace => settings.workspaces && self.context.git_root.is_some(),
48+
_ => true,
49+
}
50+
}
51+
}
52+
2753
#[async_trait]
2854
pub trait SearchEngine: Send + Sync + 'static {
2955
async fn full_query(

crates/atuin/src/command/client/search/interactive.rs

+7-32
Original file line numberDiff line numberDiff line change
@@ -459,29 +459,7 @@ impl State {
459459
}
460460
}
461461
KeyCode::Char('u') if ctrl => self.search.input.clear(),
462-
KeyCode::Char('r') if ctrl => {
463-
let filter_modes = if settings.workspaces && self.search.context.git_root.is_some()
464-
{
465-
vec![
466-
FilterMode::Global,
467-
FilterMode::Host,
468-
FilterMode::Session,
469-
FilterMode::Directory,
470-
FilterMode::Workspace,
471-
]
472-
} else {
473-
vec![
474-
FilterMode::Global,
475-
FilterMode::Host,
476-
FilterMode::Session,
477-
FilterMode::Directory,
478-
]
479-
};
480-
481-
let i = self.search.filter_mode as usize;
482-
let i = (i + 1) % filter_modes.len();
483-
self.search.filter_mode = filter_modes[i];
484-
}
462+
KeyCode::Char('r') if ctrl => self.search.rotate_filter_mode(settings, 1),
485463
KeyCode::Char('s') if ctrl => {
486464
self.switched_search_mode = true;
487465
self.search_mode = self.search_mode.next(settings);
@@ -1087,15 +1065,12 @@ pub async fn history(
10871065
tab_index: 0,
10881066
search: SearchState {
10891067
input,
1090-
filter_mode: if settings.workspaces && context.git_root.is_some() {
1091-
FilterMode::Workspace
1092-
} else if settings.shell_up_key_binding {
1093-
settings
1094-
.filter_mode_shell_up_key_binding
1095-
.unwrap_or(settings.filter_mode)
1096-
} else {
1097-
settings.filter_mode
1098-
},
1068+
filter_mode: settings
1069+
.filter_mode_shell_up_key_binding
1070+
.filter(|_| settings.shell_up_key_binding)
1071+
.or(Some(settings.default_filter_mode()))
1072+
.filter(|&x| x != FilterMode::Workspace || context.git_root.is_some())
1073+
.unwrap_or(FilterMode::Global),
10991074
context,
11001075
},
11011076
engine: engines::engine(search_mode),

0 commit comments

Comments
 (0)