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:
parent
4f0084a8c1
commit
c5c5e9d84f
@ -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" ]
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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(
|
||||||
|
@ -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),
|
||||||
|
Loading…
Reference in New Issue
Block a user