aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Ivanov <mr.pavel.ivanov@gmail.com>2024-11-19 20:02:32 +0100
committerGitHub <noreply@github.com>2024-11-19 11:02:32 -0800
commitc5c5e9d84fbbdd6c8bd59f9cea006ceb6ffce927 (patch)
tree0fe228f614c692d87c68127cfc636387bb5409cf
parentfeat: right Arrow to modify selected command (#2453) (diff)
downloadatuin-c5c5e9d84fbbdd6c8bd59f9cea006ceb6ffce927.zip
feat(client): add filter mode enablement and ordering configuration (#2430)
Diffstat (limited to '')
-rw-r--r--crates/atuin-client/config.toml17
-rw-r--r--crates/atuin-client/src/settings.rs38
-rw-r--r--crates/atuin/src/command/client/history.rs2
-rw-r--r--crates/atuin/src/command/client/search.rs9
-rw-r--r--crates/atuin/src/command/client/search/engines.rs28
-rw-r--r--crates/atuin/src/command/client/search/interactive.rs39
6 files changed, 87 insertions, 46 deletions
diff --git a/crates/atuin-client/config.toml b/crates/atuin-client/config.toml
index 4b2810e5..388e3f85 100644
--- a/crates/atuin-client/config.toml
+++ b/crates/atuin-client/config.toml
@@ -40,12 +40,17 @@
## possible values: prefix, fulltext, fuzzy, skim
# search_mode = "fuzzy"
-## which filter mode to use
-## possible values: global, host, session, directory
+## which filter mode to use by default
+## possible values: "global", "host", "session", "directory", "workspace"
+## consider using search.filters to customize the enablement and order of filter modes
# filter_mode = "global"
## With workspace filtering enabled, Atuin will filter for commands executed
-## in any directory within a git repository tree (default: false)
+## in any directory within a git repository tree (default: false).
+##
+## To use workspace mode by default when available, set this to true and
+## set filter_mode to "workspace" or leave it unspecified and
+## set search.filters to include "workspace" before other filter modes.
# workspaces = false
## which filter mode to use when atuin is invoked from a shell up-key binding
@@ -254,3 +259,9 @@ records = true
## Whether the theme manager should output normal or extra information to help fix themes.
## Boolean, true or false. If unset, left up to the theme manager.
# debug = true
+
+[search]
+## 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" ]
diff --git a/crates/atuin-client/src/settings.rs b/crates/atuin-client/src/settings.rs
index efbdb33d..10c804fa 100644
--- a/crates/atuin-client/src/settings.rs
+++ b/crates/atuin-client/src/settings.rs
@@ -370,6 +370,12 @@ pub struct Daemon {
pub tcp_port: u64,
}
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct Search {
+ /// The list of enabled filter modes, in order of priority.
+ pub filters: Vec<FilterMode>,
+}
+
impl Default for Preview {
fn default() -> Self {
Self {
@@ -400,6 +406,20 @@ impl Default for Daemon {
}
}
+impl Default for Search {
+ fn default() -> Self {
+ Self {
+ filters: vec![
+ FilterMode::Global,
+ FilterMode::Host,
+ FilterMode::Session,
+ FilterMode::Workspace,
+ FilterMode::Directory,
+ ],
+ }
+ }
+}
+
// The preview height strategy also takes max_preview_height into account.
#[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)]
pub enum PreviewStrategy {
@@ -430,7 +450,7 @@ 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_mode_shell_up_key_binding: Option<FilterMode>,
pub search_mode_shell_up_key_binding: Option<SearchMode>,
pub shell_up_key_binding: bool,
@@ -487,6 +507,9 @@ pub struct Settings {
pub daemon: Daemon,
#[serde(default)]
+ pub search: Search,
+
+ #[serde(default)]
pub theme: Theme,
}
@@ -688,6 +711,13 @@ impl Settings {
None
}
+ pub fn default_filter_mode(&self) -> FilterMode {
+ self.filter_mode
+ .filter(|x| self.search.filters.contains(x))
+ .or(self.search.filters.first().copied())
+ .unwrap_or(FilterMode::Global)
+ }
+
#[cfg(not(feature = "check-update"))]
pub async fn needs_update(&self) -> Option<Version> {
None
@@ -715,7 +745,7 @@ 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("style", "compact")?
.set_default("inline_height", 40)?
.set_default("show_preview", true)?
@@ -758,6 +788,10 @@ impl Settings {
.set_default("daemon.socket_path", socket_path.to_str())?
.set_default("daemon.systemd_socket", false)?
.set_default("daemon.tcp_port", 8889)?
+ .set_default(
+ "search.filters",
+ vec!["global", "host", "session", "workspace", "directory"],
+ )?
.set_default("theme.name", "default")?
.set_default("theme.debug", None::<bool>)?
.set_default(
diff --git a/crates/atuin/src/command/client/history.rs b/crates/atuin/src/command/client/history.rs
index a4eea825..5769b94f 100644
--- a/crates/atuin/src/command/client/history.rs
+++ b/crates/atuin/src/command/client/history.rs
@@ -466,7 +466,7 @@ impl Cmd {
(true, true) => [Session, Directory],
(true, false) => [Session, Global],
(false, true) => [Global, Directory],
- (false, false) => [settings.filter_mode, Global],
+ (false, false) => [settings.default_filter_mode(), Global],
};
let history = db
diff --git a/crates/atuin/src/command/client/search.rs b/crates/atuin/src/command/client/search.rs
index 12e73458..b8dfe659 100644
--- a/crates/atuin/src/command/client/search.rs
+++ b/crates/atuin/src/command/client/search.rs
@@ -176,7 +176,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();
@@ -287,12 +287,7 @@ async fn run_non_interactive(
..filter_options
};
- 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.default_filter_mode();
let results = db
.search(
diff --git a/crates/atuin/src/command/client/search/engines.rs b/crates/atuin/src/command/client/search/engines.rs
index 105ce147..30a23cb2 100644
--- a/crates/atuin/src/command/client/search/engines.rs
+++ b/crates/atuin/src/command/client/search/engines.rs
@@ -2,7 +2,7 @@ use async_trait::async_trait;
use atuin_client::{
database::{Context, Database},
history::History,
- settings::{FilterMode, SearchMode},
+ settings::{FilterMode, SearchMode, Settings},
};
use eyre::Result;
@@ -24,6 +24,32 @@ pub struct SearchState {
pub context: Context,
}
+impl SearchState {
+ pub(crate) fn rotate_filter_mode(&mut self, settings: &Settings, offset: isize) {
+ let mut i = settings
+ .search
+ .filters
+ .iter()
+ .position(|&m| m == self.filter_mode)
+ .unwrap_or_default();
+ for _ in 0..settings.search.filters.len() {
+ i = (i.wrapping_add_signed(offset)) % settings.search.filters.len();
+ let mode = settings.search.filters[i];
+ if self.filter_mode_available(mode, settings) {
+ self.filter_mode = mode;
+ break;
+ }
+ }
+ }
+
+ fn filter_mode_available(&self, mode: FilterMode, settings: &Settings) -> bool {
+ match mode {
+ FilterMode::Workspace => settings.workspaces && self.context.git_root.is_some(),
+ _ => true,
+ }
+ }
+}
+
#[async_trait]
pub trait SearchEngine: Send + Sync + 'static {
async fn full_query(
diff --git a/crates/atuin/src/command/client/search/interactive.rs b/crates/atuin/src/command/client/search/interactive.rs
index 5549cbfd..5288a0ee 100644
--- a/crates/atuin/src/command/client/search/interactive.rs
+++ b/crates/atuin/src/command/client/search/interactive.rs
@@ -464,29 +464,7 @@ 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];
- }
+ KeyCode::Char('r') if ctrl => self.search.rotate_filter_mode(settings, 1),
KeyCode::Char('s') if ctrl => {
self.switched_search_mode = true;
self.search_mode = self.search_mode.next(settings);
@@ -1092,15 +1070,12 @@ 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)
- } else {
- settings.filter_mode
- },
+ filter_mode: settings
+ .filter_mode_shell_up_key_binding
+ .filter(|_| settings.shell_up_key_binding)
+ .or_else(|| Some(settings.default_filter_mode()))
+ .filter(|&x| x != FilterMode::Workspace || context.git_root.is_some())
+ .unwrap_or(FilterMode::Global),
context,
},
engine: engines::engine(search_mode),