From ed394afa82ef919937521e5ce72fc467cec203f9 Mon Sep 17 00:00:00 2001 From: Patrick Decat Date: Sun, 18 Dec 2022 19:26:09 +0100 Subject: [PATCH] Allow overriding filter and search modes from CLI (#635) * Allow overriding filter and search modes from CLI arguments * Use session filter mode for bash up key binding * We precisely do not want to add quotes here so that all arguments are properly passed * Add --shell-up-key-binding hidden command argument and filter_mode_shell_up_key_binding configuration option to allow customizing the filter mode used when atuin is invoked from a shell up-key binding * Correct up binding for zsh Co-authored-by: Ellie Huxtable --- Cargo.lock | 1 + atuin-client/Cargo.toml | 1 + atuin-client/src/settings.rs | 9 ++++++-- docs/config.md | 12 ++++++++++- src/command/client.rs | 4 ++-- src/command/client/search.rs | 27 ++++++++++++++++++++++-- src/command/client/search/interactive.rs | 6 +++++- src/shell/atuin.bash | 7 +++--- src/shell/atuin.fish | 4 ++-- src/shell/atuin.zsh | 12 ++++++++--- 10 files changed, 67 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8a9027..f2915ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,6 +110,7 @@ dependencies = [ "atuin-common", "base64 0.20.0", "chrono", + "clap", "config", "directories", "eyre", diff --git a/atuin-client/Cargo.toml b/atuin-client/Cargo.toml index bdd72a5..a08926c 100644 --- a/atuin-client/Cargo.toml +++ b/atuin-client/Cargo.toml @@ -27,6 +27,7 @@ atuin-common = { path = "../atuin-common", version = "12.0.0" } log = "0.4" chrono = { version = "0.4", features = ["serde"] } +clap = { version = "4.0.18", features = ["derive"] } eyre = "0.6" directories = "4" uuid = { version = "1.2", features = ["v4"] } diff --git a/atuin-client/src/settings.rs b/atuin-client/src/settings.rs index 574ee3f..379237c 100644 --- a/atuin-client/src/settings.rs +++ b/atuin-client/src/settings.rs @@ -4,6 +4,7 @@ use std::{ }; use chrono::{prelude::*, Utc}; +use clap::ValueEnum; use config::{Config, Environment, File as ConfigFile, FileFormat}; use eyre::{eyre, Context, Result}; use fs_err::{create_dir_all, File}; @@ -16,7 +17,7 @@ pub const LAST_SYNC_FILENAME: &str = "last_sync_time"; pub const LAST_VERSION_CHECK_FILENAME: &str = "last_version_check_time"; pub const LATEST_VERSION_FILENAME: &str = "latest_version"; -#[derive(Clone, Debug, Deserialize, Copy)] +#[derive(Clone, Debug, Deserialize, Copy, ValueEnum)] pub enum SearchMode { #[serde(rename = "prefix")] Prefix, @@ -28,7 +29,7 @@ pub enum SearchMode { Fuzzy, } -#[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Copy, PartialEq, Eq, ValueEnum)] pub enum FilterMode { #[serde(rename = "global")] Global = 0, @@ -108,6 +109,8 @@ pub struct Settings { pub session_path: String, pub search_mode: SearchMode, pub filter_mode: FilterMode, + pub filter_mode_shell_up_key_binding: FilterMode, + pub shell_up_key_binding: bool, pub exit_mode: ExitMode, // This is automatically loaded when settings is created. Do not set in // config! Keep secrets and settings apart. @@ -288,6 +291,8 @@ impl Settings { .set_default("sync_address", "https://api.atuin.sh")? .set_default("search_mode", "fuzzy")? .set_default("filter_mode", "global")? + .set_default("filter_mode_shell_up_key_binding", "global")? + .set_default("shell_up_key_binding", false)? .set_default("exit_mode", "return-original")? .set_default("session_token", "")? .set_default("style", "auto")? diff --git a/docs/config.md b/docs/config.md index 9a7e906..e5ae4ad 100644 --- a/docs/config.md +++ b/docs/config.md @@ -49,7 +49,7 @@ auto_sync = true/false ### `update_check` -Configures whether or not to automatically check for updates. Defaults to +Configures whether or not to automatically check for updates. Defaults to true. ``` @@ -143,6 +143,16 @@ Filter modes can still be toggled via ctrl-r filter_mode = "host" ``` +### `filter_mode_shell_up_key_binding` + +The default filter to use when searching and being invoked from a shell up-key binding. + +Accepts exactly the same options as `filter_mode` above + +``` +filter_mode_shell_up_key_binding = "session" +``` + ### `exit_mode` What to do when the escape key is pressed when searching diff --git a/src/command/client.rs b/src/command/client.rs index df74ac5..551b222 100644 --- a/src/command/client.rs +++ b/src/command/client.rs @@ -44,7 +44,7 @@ impl Cmd { .parse_env("ATUIN_LOG") .init(); - let settings = Settings::new().wrap_err("could not load client settings")?; + let mut settings = Settings::new().wrap_err("could not load client settings")?; let db_path = PathBuf::from(settings.db_path.as_str()); let mut db = Sqlite::new(db_path).await?; @@ -53,7 +53,7 @@ impl Cmd { Self::History(history) => history.run(&settings, &mut db).await, Self::Import(import) => import.run(&mut db).await, Self::Stats(stats) => stats.run(&mut db, &settings).await, - Self::Search(search) => search.run(&mut db, &settings).await, + Self::Search(search) => search.run(&mut db, &mut settings).await, #[cfg(feature = "sync")] Self::Sync(sync) => sync.run(settings, &mut db).await, } diff --git a/src/command/client/search.rs b/src/command/client/search.rs index 456846d..e528576 100644 --- a/src/command/client/search.rs +++ b/src/command/client/search.rs @@ -3,7 +3,10 @@ use clap::Parser; use eyre::Result; use atuin_client::{ - database::current_context, database::Database, history::History, settings::Settings, + database::current_context, + database::Database, + history::History, + settings::{FilterMode, SearchMode, Settings}, }; use super::history::ListMode; @@ -15,6 +18,7 @@ mod history_list; mod interactive; pub use duration::format_duration; +#[allow(clippy::struct_excessive_bools)] #[derive(Parser)] pub struct Cmd { /// Filter search result by directory @@ -49,6 +53,18 @@ pub struct Cmd { #[arg(long, short)] interactive: bool, + /// Allow overriding filter mode over config + #[arg(long = "filter-mode")] + filter_mode: Option, + + /// Allow overriding search mode over config + #[arg(long = "search-mode")] + search_mode: Option, + + /// Marker argument used to inform atuin that it was invoked from a shell up-key binding (hidden from help to avoid confusion) + #[arg(long = "shell-up-key-binding", hide = true)] + shell_up_key_binding: bool, + /// Use human-readable formatting for time #[arg(long)] human: bool, @@ -61,7 +77,14 @@ pub struct Cmd { } impl Cmd { - pub async fn run(self, db: &mut impl Database, settings: &Settings) -> Result<()> { + pub async fn run(self, db: &mut impl Database, settings: &mut Settings) -> Result<()> { + if self.search_mode.is_some() { + settings.search_mode = self.search_mode.unwrap(); + } + if self.filter_mode.is_some() { + settings.filter_mode = self.filter_mode.unwrap(); + } + settings.shell_up_key_binding = self.shell_up_key_binding; if self.interactive { let item = interactive::history(&self.query, settings, db).await?; eprintln!("{item}"); diff --git a/src/command/client/search/interactive.rs b/src/command/client/search/interactive.rs index 2bc07da..fc22d28 100644 --- a/src/command/client/search/interactive.rs +++ b/src/command/client/search/interactive.rs @@ -329,7 +329,11 @@ pub async fn history( input, results_state: ListState::default(), context: current_context(), - filter_mode: settings.filter_mode, + filter_mode: if settings.shell_up_key_binding { + settings.filter_mode_shell_up_key_binding + } else { + settings.filter_mode + }, update_needed, }; diff --git a/src/shell/atuin.bash b/src/shell/atuin.bash index 4530e31..9c8fa23 100644 --- a/src/shell/atuin.bash +++ b/src/shell/atuin.bash @@ -17,7 +17,8 @@ _atuin_precmd() { __atuin_history () { tput rmkx - HISTORY="$(RUST_LOG=error atuin search -i -- "${READLINE_LINE}" 3>&1 1>&2 2>&3)" + # shellcheck disable=SC2048,SC2086 + HISTORY="$(RUST_LOG=error atuin search $* -i -- "${READLINE_LINE}" 3>&1 1>&2 2>&3)" tput smkx READLINE_LINE=${HISTORY} @@ -34,6 +35,6 @@ fi if [[ -z ${ATUIN_NOBIND} ]]; then bind -x '"\C-r": __atuin_history' - bind -x '"\e[A": __atuin_history' - bind -x '"\eOA": __atuin_history' + bind -x '"\e[A": __atuin_history --shell-up-key-binding' + bind -x '"\eOA": __atuin_history --shell-up-key-binding' fi diff --git a/src/shell/atuin.fish b/src/shell/atuin.fish index 69175ad..9446907 100644 --- a/src/shell/atuin.fish +++ b/src/shell/atuin.fish @@ -15,7 +15,7 @@ function _atuin_postexec --on-event fish_postexec end function _atuin_search - set h (RUST_LOG=error atuin search -i -- (commandline -b) 3>&1 1>&2 2>&3) + set h (RUST_LOG=error atuin search $* -i -- (commandline -b) 3>&1 1>&2 2>&3) commandline -f repaint if test -n "$h" commandline -r $h @@ -33,7 +33,7 @@ function _atuin_bind_up set -l lineno (commandline --line) switch $lineno case 1 - _atuin_search + _atuin_search --shell-up-key-binding case '*' up-or-search end diff --git a/src/shell/atuin.zsh b/src/shell/atuin.zsh index ed1c0c1..dd5c1af 100644 --- a/src/shell/atuin.zsh +++ b/src/shell/atuin.zsh @@ -34,7 +34,8 @@ _atuin_search(){ echoti rmkx # swap stderr and stdout, so that the tui stuff works # TODO: not this - output=$(RUST_LOG=error atuin search -i -- $BUFFER 3>&1 1>&2 2>&3) + # shellcheck disable=SC2048 + output=$(RUST_LOG=error atuin search $* -i -- $BUFFER 3>&1 1>&2 2>&3) echoti smkx if [[ -n $output ]] ; then @@ -45,15 +46,20 @@ _atuin_search(){ zle reset-prompt } +_atuin_up_search(){ + _atuin_search --shell-up-key-binding +} + add-zsh-hook preexec _atuin_preexec add-zsh-hook precmd _atuin_precmd zle -N _atuin_search_widget _atuin_search +zle -N _atuin_up_search_widget _atuin_up_search if [[ -z $ATUIN_NOBIND ]]; then bindkey '^r' _atuin_search_widget # depends on terminal mode - bindkey '^[[A' _atuin_search_widget - bindkey '^[OA' _atuin_search_widget + bindkey '^[[A' _atuin_up_search_widget + bindkey '^[OA' _atuin_up_search_widget fi