aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--atuin-client/config.toml4
-rw-r--r--atuin-client/src/settings.rs11
-rw-r--r--docs/config.md15
-rw-r--r--src/command/client/search/interactive.rs31
4 files changed, 53 insertions, 8 deletions
diff --git a/atuin-client/config.toml b/atuin-client/config.toml
index 43b5e24c..6a8e1caa 100644
--- a/atuin-client/config.toml
+++ b/atuin-client/config.toml
@@ -33,3 +33,7 @@
## which style to use
## possible values: auto, full, compact
#style = "auto"
+
+## what to do when the escape key is pressed when searching
+## possible values: return-original, return-query
+# exit_mode = "return-original"
diff --git a/atuin-client/src/settings.rs b/atuin-client/src/settings.rs
index 4462d992..574ee3fa 100644
--- a/atuin-client/src/settings.rs
+++ b/atuin-client/src/settings.rs
@@ -54,6 +54,15 @@ impl FilterMode {
}
}
+#[derive(Clone, Debug, Deserialize, Copy)]
+pub enum ExitMode {
+ #[serde(rename = "return-original")]
+ ReturnOriginal,
+
+ #[serde(rename = "return-query")]
+ ReturnQuery,
+}
+
// FIXME: Can use upstream Dialect enum if https://github.com/stevedonovan/chrono-english/pull/16 is merged
// FIXME: Above PR was merged, but dependency was changed to interim (fork of chrono-english) in the ... interim
#[derive(Clone, Debug, Deserialize, Copy)]
@@ -99,6 +108,7 @@ pub struct Settings {
pub session_path: String,
pub search_mode: SearchMode,
pub filter_mode: FilterMode,
+ pub exit_mode: ExitMode,
// This is automatically loaded when settings is created. Do not set in
// config! Keep secrets and settings apart.
pub session_token: String,
@@ -278,6 +288,7 @@ impl Settings {
.set_default("sync_address", "https://api.atuin.sh")?
.set_default("search_mode", "fuzzy")?
.set_default("filter_mode", "global")?
+ .set_default("exit_mode", "return-original")?
.set_default("session_token", "")?
.set_default("style", "auto")?
.add_source(
diff --git a/docs/config.md b/docs/config.md
index 13aabac2..9039e094 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -143,6 +143,21 @@ Filter modes can still be toggled via ctrl-r
search_mode = "fulltext"
```
+### `exit_mode`
+
+What to do when the escape key is pressed when searching
+
+| Value | Behaviour |
+|------------------------- | --------------- |
+| return-original (default) | Set the command-line to the value it had before starting search |
+| return-query | Set the command-line to the search query you have entered so far |
+
+Pressing ctrl+c or ctrl+d will always return the original command-line value.
+
+```
+exit_mode = "return-query"
+```
+
#### `fuzzy` search syntax
The "fuzzy" search syntax is based on the
diff --git a/src/command/client/search/interactive.rs b/src/command/client/search/interactive.rs
index 950a971d..36497db0 100644
--- a/src/command/client/search/interactive.rs
+++ b/src/command/client/search/interactive.rs
@@ -21,7 +21,7 @@ use atuin_client::{
database::Context,
database::Database,
history::History,
- settings::{FilterMode, SearchMode, Settings},
+ settings::{ExitMode, FilterMode, SearchMode, Settings},
};
use super::{
@@ -31,6 +31,9 @@ use super::{
};
use crate::VERSION;
+const RETURN_ORIGINAL: usize = usize::MAX;
+const RETURN_QUERY: usize = usize::MAX - 1;
+
struct State {
history_count: i64,
input: Cursor,
@@ -59,9 +62,20 @@ impl State {
Ok(results)
}
- fn handle_input(&mut self, input: &TermEvent, len: usize) -> Option<usize> {
+ fn handle_input(
+ &mut self,
+ settings: &Settings,
+ input: &TermEvent,
+ len: usize,
+ ) -> Option<usize> {
match input {
- TermEvent::Key(Key::Esc | Key::Ctrl('c' | 'd' | 'g')) => return Some(usize::MAX),
+ TermEvent::Key(Key::Ctrl('c' | 'd' | 'g')) => return Some(RETURN_ORIGINAL),
+ TermEvent::Key(Key::Esc) => {
+ return Some(match settings.exit_mode {
+ ExitMode::ReturnOriginal => RETURN_ORIGINAL,
+ ExitMode::ReturnQuery => RETURN_QUERY,
+ })
+ }
TermEvent::Key(Key::Char('\n')) => {
return Some(self.results_state.selected());
}
@@ -323,14 +337,14 @@ pub async fn history(
// Handle input
if let Event::Input(input) = events.next()? {
- if let Some(i) = app.handle_input(&input, results.len()) {
+ if let Some(i) = app.handle_input(settings, &input, results.len()) {
break 'render i;
}
}
// After we receive input process the whole event channel before query/render.
while let Ok(Event::Input(input)) = events.try_next() {
- if let Some(i) = app.handle_input(&input, results.len()) {
+ if let Some(i) = app.handle_input(settings, &input, results.len()) {
break 'render i;
}
}
@@ -356,11 +370,12 @@ pub async fn history(
if index < results.len() {
// index is in bounds so we return that entry
Ok(results.swap_remove(index).command)
- } else if index == usize::MAX {
- // index is max which implies an early exit
+ } else if index == RETURN_ORIGINAL {
Ok(String::new())
} else {
- // out of bounds usually implies no selected entry so we return the input
+ // Either:
+ // * index == RETURN_QUERY, in which case we should return the input
+ // * out of bounds -> usually implies no selected entry so we return the input
Ok(app.input.into_inner())
}
}