1
1
mirror of https://github.com/ellie/atuin.git synced 2024-11-22 17:52:14 +03:00

feat(client): add filter mode enablement and ordering configuration (#2430)

This commit is contained in:
Pavel Ivanov 2024-11-19 20:02:32 +01:00 committed by GitHub
parent 4f0084a8c1
commit c5c5e9d84f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 87 additions and 46 deletions

View File

@ -40,12 +40,17 @@
## possible values: prefix, fulltext, fuzzy, skim ## possible values: prefix, fulltext, fuzzy, skim
# search_mode = "fuzzy" # search_mode = "fuzzy"
## which filter mode to use ## which filter mode to use by default
## possible values: global, host, session, directory ## possible values: "global", "host", "session", "directory", "workspace"
## consider using search.filters to customize the enablement and order of filter modes
# filter_mode = "global" # filter_mode = "global"
## With workspace filtering enabled, Atuin will filter for commands executed ## 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 # workspaces = false
## which filter mode to use when atuin is invoked from a shell up-key binding ## 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. ## 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. ## Boolean, true or false. If unset, left up to the theme manager.
# debug = true # 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" ]

View File

@ -370,6 +370,12 @@ pub struct Daemon {
pub tcp_port: u64, 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 { impl Default for Preview {
fn default() -> Self { fn default() -> Self {
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. // The preview height strategy also takes max_preview_height into account.
#[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)] #[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum, Serialize)]
pub enum PreviewStrategy { pub enum PreviewStrategy {
@ -430,7 +450,7 @@ pub struct Settings {
pub key_path: String, pub key_path: String,
pub session_path: String, pub session_path: String,
pub search_mode: SearchMode, pub search_mode: SearchMode,
pub filter_mode: FilterMode, pub filter_mode: Option<FilterMode>,
pub filter_mode_shell_up_key_binding: Option<FilterMode>, pub filter_mode_shell_up_key_binding: Option<FilterMode>,
pub search_mode_shell_up_key_binding: Option<SearchMode>, pub search_mode_shell_up_key_binding: Option<SearchMode>,
pub shell_up_key_binding: bool, pub shell_up_key_binding: bool,
@ -486,6 +506,9 @@ pub struct Settings {
#[serde(default)] #[serde(default)]
pub daemon: Daemon, pub daemon: Daemon,
#[serde(default)]
pub search: Search,
#[serde(default)] #[serde(default)]
pub theme: Theme, pub theme: Theme,
} }
@ -688,6 +711,13 @@ impl Settings {
None 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"))] #[cfg(not(feature = "check-update"))]
pub async fn needs_update(&self) -> Option<Version> { pub async fn needs_update(&self) -> Option<Version> {
None None
@ -715,7 +745,7 @@ impl Settings {
.set_default("sync_address", "https://api.atuin.sh")? .set_default("sync_address", "https://api.atuin.sh")?
.set_default("sync_frequency", "10m")? .set_default("sync_frequency", "10m")?
.set_default("search_mode", "fuzzy")? .set_default("search_mode", "fuzzy")?
.set_default("filter_mode", "global")? .set_default("filter_mode", None::<String>)?
.set_default("style", "compact")? .set_default("style", "compact")?
.set_default("inline_height", 40)? .set_default("inline_height", 40)?
.set_default("show_preview", true)? .set_default("show_preview", true)?
@ -758,6 +788,10 @@ impl Settings {
.set_default("daemon.socket_path", socket_path.to_str())? .set_default("daemon.socket_path", socket_path.to_str())?
.set_default("daemon.systemd_socket", false)? .set_default("daemon.systemd_socket", false)?
.set_default("daemon.tcp_port", 8889)? .set_default("daemon.tcp_port", 8889)?
.set_default(
"search.filters",
vec!["global", "host", "session", "workspace", "directory"],
)?
.set_default("theme.name", "default")? .set_default("theme.name", "default")?
.set_default("theme.debug", None::<bool>)? .set_default("theme.debug", None::<bool>)?
.set_default( .set_default(

View File

@ -466,7 +466,7 @@ impl Cmd {
(true, true) => [Session, Directory], (true, true) => [Session, Directory],
(true, false) => [Session, Global], (true, false) => [Session, Global],
(false, true) => [Global, Directory], (false, true) => [Global, Directory],
(false, false) => [settings.filter_mode, Global], (false, false) => [settings.default_filter_mode(), Global],
}; };
let history = db let history = db

View File

@ -176,7 +176,7 @@ impl Cmd {
settings.search_mode = self.search_mode.unwrap(); settings.search_mode = self.search_mode.unwrap();
} }
if self.filter_mode.is_some() { 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() { if self.inline_height.is_some() {
settings.inline_height = self.inline_height.unwrap(); settings.inline_height = self.inline_height.unwrap();
@ -287,12 +287,7 @@ async fn run_non_interactive(
..filter_options ..filter_options
}; };
let dir = dir.unwrap_or_else(|| "/".to_string()); let filter_mode = settings.default_filter_mode();
let filter_mode = if settings.workspaces && utils::has_git_dir(dir.as_str()) {
FilterMode::Workspace
} else {
settings.filter_mode
};
let results = db let results = db
.search( .search(

View File

@ -2,7 +2,7 @@ use async_trait::async_trait;
use atuin_client::{ use atuin_client::{
database::{Context, Database}, database::{Context, Database},
history::History, history::History,
settings::{FilterMode, SearchMode}, settings::{FilterMode, SearchMode, Settings},
}; };
use eyre::Result; use eyre::Result;
@ -24,6 +24,32 @@ pub struct SearchState {
pub context: Context, 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] #[async_trait]
pub trait SearchEngine: Send + Sync + 'static { pub trait SearchEngine: Send + Sync + 'static {
async fn full_query( async fn full_query(

View File

@ -464,29 +464,7 @@ impl State {
} }
} }
KeyCode::Char('u') if ctrl => self.search.input.clear(), KeyCode::Char('u') if ctrl => self.search.input.clear(),
KeyCode::Char('r') if ctrl => { KeyCode::Char('r') if ctrl => self.search.rotate_filter_mode(settings, 1),
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('s') if ctrl => { KeyCode::Char('s') if ctrl => {
self.switched_search_mode = true; self.switched_search_mode = true;
self.search_mode = self.search_mode.next(settings); self.search_mode = self.search_mode.next(settings);
@ -1092,15 +1070,12 @@ pub async fn history(
tab_index: 0, tab_index: 0,
search: SearchState { search: SearchState {
input, input,
filter_mode: if settings.workspaces && context.git_root.is_some() { filter_mode: settings
FilterMode::Workspace .filter_mode_shell_up_key_binding
} else if settings.shell_up_key_binding { .filter(|_| settings.shell_up_key_binding)
settings .or_else(|| Some(settings.default_filter_mode()))
.filter_mode_shell_up_key_binding .filter(|&x| x != FilterMode::Workspace || context.git_root.is_some())
.unwrap_or(settings.filter_mode) .unwrap_or(FilterMode::Global),
} else {
settings.filter_mode
},
context, context,
}, },
engine: engines::engine(search_mode), engine: engines::engine(search_mode),