aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--atuin-client/config.toml4
-rw-r--r--atuin-client/src/settings.rs8
-rw-r--r--atuin-common/src/utils.rs5
-rw-r--r--atuin/src/command/client/search/interactive.rs20
-rw-r--r--atuin/src/shell/atuin.zsh8
-rw-r--r--docs/docs/config/config.md13
6 files changed, 55 insertions, 3 deletions
diff --git a/atuin-client/config.toml b/atuin-client/config.toml
index d1c1081f..19e8e302 100644
--- a/atuin-client/config.toml
+++ b/atuin-client/config.toml
@@ -123,3 +123,7 @@
## 4. Slack webhooks
## 5. Stripe live/test keys
# secrets_filter = true
+
+## Defaults to true. If enabled, upon hitting enter Atuin will immediately execute the command. Press tab to return to the shell and edit.
+# This applies for new installs. Old installs will keep the old behaviour unless configured otherwise.
+enter_accept = true
diff --git a/atuin-client/src/settings.rs b/atuin-client/src/settings.rs
index 15aa9e06..fca76004 100644
--- a/atuin-client/src/settings.rs
+++ b/atuin-client/src/settings.rs
@@ -179,6 +179,7 @@ pub struct Settings {
pub network_connect_timeout: u64,
pub network_timeout: u64,
+ pub enter_accept: bool,
// This is automatically loaded when settings is created. Do not set in
// config! Keep secrets and settings apart.
@@ -378,6 +379,12 @@ impl Settings {
.set_default("secrets_filter", true)?
.set_default("network_connect_timeout", 5)?
.set_default("network_timeout", 30)?
+ // enter_accept defaults to false here, but true in the default config file. The dissonance is
+ // intentional!
+ // Existing users will get the default "False", so we don't mess with any potential
+ // muscle memory.
+ // New users will get the new default, that is more similar to what they are used to.
+ .set_default("enter_accept", false)?
.add_source(
Environment::with_prefix("atuin")
.prefix_separator("_")
@@ -391,6 +398,7 @@ impl Settings {
create_dir_all(&config_dir)
.wrap_err_with(|| format!("could not create dir {config_dir:?}"))?;
+
create_dir_all(&data_dir).wrap_err_with(|| format!("could not create dir {data_dir:?}"))?;
let mut config_file = if let Ok(p) = std::env::var("ATUIN_CONFIG_DIR") {
diff --git a/atuin-common/src/utils.rs b/atuin-common/src/utils.rs
index 7cf4e9de..cd2cd4dc 100644
--- a/atuin-common/src/utils.rs
+++ b/atuin-common/src/utils.rs
@@ -113,6 +113,11 @@ pub fn get_current_dir() -> String {
}
}
+pub fn is_zsh() -> bool {
+ // only set on zsh
+ env::var("ZSH_VERSION").is_ok()
+}
+
#[cfg(test)]
mod tests {
use time::Month;
diff --git a/atuin/src/command/client/search/interactive.rs b/atuin/src/command/client/search/interactive.rs
index bc933022..bfee81d4 100644
--- a/atuin/src/command/client/search/interactive.rs
+++ b/atuin/src/command/client/search/interactive.rs
@@ -3,6 +3,7 @@ use std::{
time::Duration,
};
+use atuin_common::utils;
use crossterm::{
event::{
self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, KeyModifiers,
@@ -47,6 +48,7 @@ struct State {
switched_search_mode: bool,
search_mode: SearchMode,
results_len: usize,
+ accept: bool,
search: SearchState,
engine: Box<dyn SearchEngine>,
@@ -130,7 +132,14 @@ impl State {
ExitMode::ReturnQuery => RETURN_QUERY,
})
}
+ KeyCode::Tab => {
+ return Some(self.results_state.selected());
+ }
KeyCode::Enter => {
+ if settings.enter_accept {
+ self.accept = true;
+ }
+
return Some(self.results_state.selected());
}
KeyCode::Char('y') if ctrl => {
@@ -588,7 +597,7 @@ impl Write for Stdout {
// this is a big blob of horrible! clean it up!
// for now, it works. But it'd be great if it were more easily readable, and
// modular. I'd like to add some more stats and stuff at some point
-#[allow(clippy::cast_possible_truncation)]
+#[allow(clippy::cast_possible_truncation, clippy::too_many_lines)]
pub async fn history(
query: &[String],
settings: &Settings,
@@ -646,10 +655,12 @@ pub async fn history(
},
engine: engines::engine(search_mode),
results_len: 0,
+ accept: false,
};
let mut results = app.query_results(&mut db).await?;
+ let accept;
let index = 'render: loop {
terminal.draw(|f| app.draw(f, &results, settings))?;
@@ -664,6 +675,7 @@ pub async fn history(
if event_ready?? {
loop {
if let Some(i) = app.handle_input(settings, &event::read()?, &mut std::io::stdout())? {
+ accept = app.accept;
break 'render i;
}
if !event::poll(Duration::ZERO)? {
@@ -690,8 +702,12 @@ pub async fn history(
}
if index < results.len() {
+ let mut command = results.swap_remove(index).command;
+ if accept && utils::is_zsh() {
+ command = String::from("__atuin_accept__:") + &command;
+ }
// index is in bounds so we return that entry
- Ok(results.swap_remove(index).command)
+ Ok(command)
} else if index == RETURN_ORIGINAL {
Ok(String::new())
} else if index == COPY_QUERY {
diff --git a/atuin/src/shell/atuin.zsh b/atuin/src/shell/atuin.zsh
index edea0c80..19941bed 100644
--- a/atuin/src/shell/atuin.zsh
+++ b/atuin/src/shell/atuin.zsh
@@ -36,12 +36,18 @@ _atuin_search() {
# shellcheck disable=SC2048
output=$(ATUIN_LOG=error atuin search $* -i -- $BUFFER 3>&1 1>&2 2>&3)
+ zle reset-prompt
+
if [[ -n $output ]]; then
RBUFFER=""
LBUFFER=$output
fi
- zle reset-prompt
+ if [[ $LBUFFER == __atuin_accept__:* ]]
+ then
+ LBUFFER=${LBUFFER#__atuin_accept__:}
+ zle accept-line
+ fi
}
_atuin_up_search() {
diff --git a/docs/docs/config/config.md b/docs/docs/config/config.md
index e0403d2a..5cdbe922 100644
--- a/docs/docs/config/config.md
+++ b/docs/docs/config/config.md
@@ -305,3 +305,16 @@ Default: 5
The max time (in seconds) we wait for a connection to become established with a
remote sync server. Any longer than this and the request will fail.
+
+## enter_accept
+Default: false
+
+Only supported on Zsh.
+
+When set to true, Atuin will default to immediately executing a command rather
+than the user having to press enter twice. Pressing tab will return to the
+shell and give the user a chance to edit.
+
+This technically defaults to true for new users, but false for existing. We
+have set `enter_accept = true` in the default config file. This is likely to
+change to be the default for everyone in a later release.