Add setting for keeping typed query when exiting (#451)
* Add option for keeping typed query on escape fixes #422 * chore: Address duplicate if statement blocks
This commit is contained in:
parent
d87abbd3dc
commit
4768b16b74
4 changed files with 53 additions and 8 deletions
|
@ -33,3 +33,7 @@
|
||||||
## which style to use
|
## which style to use
|
||||||
## possible values: auto, full, compact
|
## possible values: auto, full, compact
|
||||||
#style = "auto"
|
#style = "auto"
|
||||||
|
|
||||||
|
## what to do when the escape key is pressed when searching
|
||||||
|
## possible values: return-original, return-query
|
||||||
|
# exit_mode = "return-original"
|
||||||
|
|
|
@ -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: 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
|
// FIXME: Above PR was merged, but dependency was changed to interim (fork of chrono-english) in the ... interim
|
||||||
#[derive(Clone, Debug, Deserialize, Copy)]
|
#[derive(Clone, Debug, Deserialize, Copy)]
|
||||||
|
@ -99,6 +108,7 @@ pub struct Settings {
|
||||||
pub session_path: String,
|
pub session_path: String,
|
||||||
pub search_mode: SearchMode,
|
pub search_mode: SearchMode,
|
||||||
pub filter_mode: FilterMode,
|
pub filter_mode: FilterMode,
|
||||||
|
pub exit_mode: ExitMode,
|
||||||
// This is automatically loaded when settings is created. Do not set in
|
// This is automatically loaded when settings is created. Do not set in
|
||||||
// config! Keep secrets and settings apart.
|
// config! Keep secrets and settings apart.
|
||||||
pub session_token: String,
|
pub session_token: String,
|
||||||
|
@ -278,6 +288,7 @@ impl Settings {
|
||||||
.set_default("sync_address", "https://api.atuin.sh")?
|
.set_default("sync_address", "https://api.atuin.sh")?
|
||||||
.set_default("search_mode", "fuzzy")?
|
.set_default("search_mode", "fuzzy")?
|
||||||
.set_default("filter_mode", "global")?
|
.set_default("filter_mode", "global")?
|
||||||
|
.set_default("exit_mode", "return-original")?
|
||||||
.set_default("session_token", "")?
|
.set_default("session_token", "")?
|
||||||
.set_default("style", "auto")?
|
.set_default("style", "auto")?
|
||||||
.add_source(
|
.add_source(
|
||||||
|
|
|
@ -143,6 +143,21 @@ Filter modes can still be toggled via ctrl-r
|
||||||
search_mode = "fulltext"
|
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
|
#### `fuzzy` search syntax
|
||||||
|
|
||||||
The "fuzzy" search syntax is based on the
|
The "fuzzy" search syntax is based on the
|
||||||
|
|
|
@ -21,7 +21,7 @@ use atuin_client::{
|
||||||
database::Context,
|
database::Context,
|
||||||
database::Database,
|
database::Database,
|
||||||
history::History,
|
history::History,
|
||||||
settings::{FilterMode, SearchMode, Settings},
|
settings::{ExitMode, FilterMode, SearchMode, Settings},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
@ -31,6 +31,9 @@ use super::{
|
||||||
};
|
};
|
||||||
use crate::VERSION;
|
use crate::VERSION;
|
||||||
|
|
||||||
|
const RETURN_ORIGINAL: usize = usize::MAX;
|
||||||
|
const RETURN_QUERY: usize = usize::MAX - 1;
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
history_count: i64,
|
history_count: i64,
|
||||||
input: Cursor,
|
input: Cursor,
|
||||||
|
@ -59,9 +62,20 @@ impl State {
|
||||||
Ok(results)
|
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 {
|
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')) => {
|
TermEvent::Key(Key::Char('\n')) => {
|
||||||
return Some(self.results_state.selected());
|
return Some(self.results_state.selected());
|
||||||
}
|
}
|
||||||
|
@ -323,14 +337,14 @@ pub async fn history(
|
||||||
|
|
||||||
// Handle input
|
// Handle input
|
||||||
if let Event::Input(input) = events.next()? {
|
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;
|
break 'render i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After we receive input process the whole event channel before query/render.
|
// After we receive input process the whole event channel before query/render.
|
||||||
while let Ok(Event::Input(input)) = events.try_next() {
|
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;
|
break 'render i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,11 +370,12 @@ pub async fn history(
|
||||||
if index < results.len() {
|
if index < results.len() {
|
||||||
// index is in bounds so we return that entry
|
// index is in bounds so we return that entry
|
||||||
Ok(results.swap_remove(index).command)
|
Ok(results.swap_remove(index).command)
|
||||||
} else if index == usize::MAX {
|
} else if index == RETURN_ORIGINAL {
|
||||||
// index is max which implies an early exit
|
|
||||||
Ok(String::new())
|
Ok(String::new())
|
||||||
} else {
|
} 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())
|
Ok(app.input.into_inner())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue