summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/joshuto.toml1
-rw-r--r--docs/configuration/joshuto.toml.md3
-rw-r--r--src/commands/change_directory.rs6
-rw-r--r--src/commands/command_line.rs10
-rw-r--r--src/commands/zoxide.rs33
-rw-r--r--src/config/clean/app/config.rs2
-rw-r--r--src/config/raw/app/config.rs2
-rw-r--r--src/key_command/command.rs2
-rw-r--r--src/key_command/impl_appcommand.rs2
-rw-r--r--src/key_command/impl_appexecute.rs4
-rw-r--r--src/key_command/impl_comment.rs2
-rw-r--r--src/key_command/impl_from_str.rs29
-rw-r--r--src/util/unix.rs10
13 files changed, 93 insertions, 13 deletions
diff --git a/config/joshuto.toml b/config/joshuto.toml
index d6a4235..64e6462 100644
--- a/config/joshuto.toml
+++ b/config/joshuto.toml
@@ -7,6 +7,7 @@ watch_files = true
xdg_open = false
xdg_open_fork = false
case_insensitive_ext = false
+zoxide_update = false
custom_commands = []
diff --git a/docs/configuration/joshuto.toml.md b/docs/configuration/joshuto.toml.md
index d7af43a..5a30863 100644
--- a/docs/configuration/joshuto.toml.md
+++ b/docs/configuration/joshuto.toml.md
@@ -36,6 +36,9 @@ focus_on_create = true
# The maximum file size to show a preview for
max_preview_size = 2097152 # 2MB
+# Update the zoxide database with every navigation type instead of only with the z command
+zoxide_update = false
+
# Define custom commands (using shell) with parameters like %text, %s etc.
custom_commands = [
{ name = "rgfzf", command = "/home/<USER>/.config/joshuto/rgfzf '%text' %s" },
diff --git a/src/commands/change_directory.rs b/src/commands/change_directory.rs
index ebf471f..84d8fdb 100644
--- a/src/commands/change_directory.rs
+++ b/src/commands/change_directory.rs
@@ -1,6 +1,6 @@
use std::path;
-use crate::commands::reload;
+use crate::commands::{reload, zoxide};
use crate::context::AppContext;
use crate::error::AppResult;
use crate::history::{generate_entries_to_root, DirectoryHistory};
@@ -10,6 +10,10 @@ use crate::util::cwd;
pub fn cd(path: &path::Path, context: &mut AppContext) -> std::io::Result<()> {
cwd::set_current_dir(path)?;
context.tab_context_mut().curr_tab_mut().set_cwd(path);
+ if context.config_ref().zoxide_update {
+ debug_assert!(path.is_absolute());
+ zoxide::zoxide_add(path.to_str().expect("cannot convert path to string"))?;
+ }
Ok(())
}
diff --git a/src/commands/command_line.rs b/src/commands/command_line.rs
index d423835..5f9d0de 100644
--- a/src/commands/command_line.rs
+++ b/src/commands/command_line.rs
@@ -22,12 +22,20 @@ pub fn read_and_execute(
.suffix(suffix)
.get_input(backend, context, &mut listener);
- if let Some(s) = user_input {
+ if let Some(mut s) = user_input {
let mut trimmed = s.trim_start();
let _ = context.commandline_context_mut().history_mut().add(trimmed);
+ let (command, arg) = match trimmed.find(' ') {
+ Some(i) => (&trimmed[..i], &trimmed[i..]),
+ None => (trimmed, ""),
+ };
+
if let Some(alias) = context.config_ref().cmd_aliases.get(trimmed) {
trimmed = alias;
+ } else if let Some(alias) = context.config_ref().cmd_aliases.get(command) {
+ s.replace_range(..s.len() - arg.len(), alias);
+ trimmed = &s;
}
let command = Command::from_str(trimmed)?;
diff --git a/src/commands/zoxide.rs b/src/commands/zoxide.rs
index 222bb9d..4ebddff 100644
--- a/src/commands/zoxide.rs
+++ b/src/commands/zoxide.rs
@@ -10,18 +10,34 @@ use crate::ui::AppBackend;
pub fn zoxide_query(context: &mut AppContext, args: &str) -> AppResult {
let cwd = std::env::current_dir()?;
+ let path = Path::new(args);
+ if change_directory::change_directory(context, path).is_ok() {
+ if !context.config_ref().zoxide_update {
+ let cwd = context
+ .tab_context_ref()
+ .curr_tab_ref()
+ .cwd()
+ .to_str()
+ .expect("path cannot be converted to string");
+ zoxide_add(cwd)?;
+ }
+ return Ok(());
+ }
+
let zoxide_output = Command::new("zoxide")
.arg("query")
.arg("--exclude")
.arg(&cwd)
.arg("--")
- .args(args.split(' ').collect::<Vec<&str>>())
+ .args(args.split(' '))
.output()?;
if zoxide_output.status.success() {
if let Ok(zoxide_str) = std::str::from_utf8(&zoxide_output.stdout) {
let zoxide_path = &zoxide_str[..zoxide_str.len() - 1];
- zoxide_add(zoxide_path)?;
+ if !context.config_ref().zoxide_update {
+ zoxide_add(zoxide_path)?;
+ }
let path = Path::new(zoxide_path);
context
@@ -37,13 +53,18 @@ pub fn zoxide_query(context: &mut AppContext, args: &str) -> AppResult {
Ok(())
}
-pub fn zoxide_query_interactive(context: &mut AppContext, backend: &mut AppBackend) -> AppResult {
+pub fn zoxide_query_interactive(
+ context: &mut AppContext,
+ backend: &mut AppBackend,
+ args: &str,
+) -> AppResult {
backend.terminal_drop();
let zoxide_process = Command::new("zoxide")
.arg("query")
.arg("-i")
.arg("--")
+ .args(args.split(' '))
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
@@ -54,7 +75,9 @@ pub fn zoxide_query_interactive(context: &mut AppContext, backend: &mut AppBacke
if zoxide_output.status.success() {
if let Ok(zoxide_str) = std::str::from_utf8(&zoxide_output.stdout) {
let zoxide_path = &zoxide_str[..zoxide_str.len() - 1];
- zoxide_add(zoxide_path)?;
+ if !context.config_ref().zoxide_update {
+ zoxide_add(zoxide_path)?;
+ }
let path = Path::new(zoxide_path);
context
@@ -70,7 +93,7 @@ pub fn zoxide_query_interactive(context: &mut AppContext, backend: &mut AppBacke
Ok(())
}
-fn zoxide_add(s: &str) -> io::Result<()> {
+pub fn zoxide_add(s: &str) -> io::Result<()> {
Command::new("zoxide").arg("add").arg(s).output()?;
Ok(())
}
diff --git a/src/config/clean/app/config.rs b/src/config/clean/app/config.rs
index 3d0be5a..740430a 100644
--- a/src/config/clean/app/config.rs
+++ b/src/config/clean/app/config.rs
@@ -24,6 +24,7 @@ pub struct AppConfig {
pub focus_on_create: bool,
pub mouse_support: bool,
pub cmd_aliases: HashMap<String, String>,
+ pub zoxide_update: bool,
pub _display_options: DisplayOption,
pub _preview_options: PreviewOption,
pub _search_options: SearchOption,
@@ -90,6 +91,7 @@ impl From<AppConfigRaw> for AppConfig {
cmd_aliases: raw.cmd_aliases,
focus_on_create: raw.focus_on_create,
mouse_support: raw.mouse_support,
+ zoxide_update: raw.zoxide_update,
_display_options: DisplayOption::from(raw.display_options),
_preview_options: PreviewOption::from(raw.preview_options),
_search_options: SearchOption::from(raw.search_options),
diff --git a/src/config/raw/app/config.rs b/src/config/raw/app/config.rs
index 2980e4c..9c18ff8 100644
--- a/src/config/raw/app/config.rs
+++ b/src/config/raw/app/config.rs
@@ -39,6 +39,8 @@ pub struct AppConfigRaw {
#[serde(default = "default_true")]
pub mouse_support: bool,
#[serde(default)]
+ pub zoxide_update: bool,
+ #[serde(default)]
pub cmd_aliases: HashMap<String, String>,
#[serde(default, rename = "display")]
pub display_options: DisplayOptionRaw,
diff --git a/src/key_command/command.rs b/src/key_command/command.rs
index 87ab74b..84e407e 100644
--- a/src/key_command/command.rs
+++ b/src/key_command/command.rs
@@ -191,7 +191,7 @@ pub enum Command {
processor: PostProcessor,
},
Zoxide(String),
- ZoxideInteractive,
+ ZoxideInteractive(String),
CustomSearch(Vec<String>),
CustomSearchInteractive(Vec<String>),
diff --git a/src/key_command/impl_appcommand.rs b/src/key_command/impl_appcommand.rs
index df9ffcf..fe75dc5 100644
--- a/src/key_command/impl_appcommand.rs
+++ b/src/key_command/impl_appcommand.rs
@@ -111,7 +111,7 @@ impl AppCommand for Command {
Self::SubdirFzf => CMD_SUBDIR_FZF,
Self::SelectFzf { .. } => CMD_SELECT_FZF,
Self::Zoxide(_) => CMD_ZOXIDE,
- Self::ZoxideInteractive => CMD_ZOXIDE_INTERACTIVE,
+ Self::ZoxideInteractive(_) => CMD_ZOXIDE_INTERACTIVE,
Self::CustomSearch(_) => CMD_CUSTOM_SEARCH,
Self::CustomSearchInteractive(_) => CMD_CUSTOM_SEARCH_INTERACTIVE,
diff --git a/src/key_command/impl_appexecute.rs b/src/key_command/impl_appexecute.rs
index 5ab59b7..25d7041 100644
--- a/src/key_command/impl_appexecute.rs
+++ b/src/key_command/impl_appexecute.rs
@@ -167,7 +167,9 @@ impl AppExecute for Command {
Self::SubdirFzf => subdir_fzf::subdir_fzf(context, backend),
Self::SelectFzf { options } => select_fzf::select_fzf(context, backend, options),
Self::Zoxide(arg) => zoxide::zoxide_query(context, arg),
- Self::ZoxideInteractive => zoxide::zoxide_query_interactive(context, backend),
+ Self::ZoxideInteractive(args) => {
+ zoxide::zoxide_query_interactive(context, backend, args)
+ }
Self::BookmarkAdd => bookmark::add_bookmark(context, backend),
Self::BookmarkChangeDirectory => bookmark::change_directory_bookmark(context, backend),
diff --git a/src/key_command/impl_comment.rs b/src/key_command/impl_comment.rs
index 6fa744d..e22618c 100644
--- a/src/key_command/impl_comment.rs
+++ b/src/key_command/impl_comment.rs
@@ -140,7 +140,7 @@ impl CommandComment for Command {
Self::SubdirFzf => "Switch to a child directory via fzf",
Self::SelectFzf { .. } => "Select via fzf",
Self::Zoxide(_) => "Zoxide",
- Self::ZoxideInteractive => "Zoxide interactive",
+ Self::ZoxideInteractive(_) => "Zoxide interactive",
Self::BookmarkAdd => "Add a bookmark",
Self::BookmarkChangeDirectory => "Navigate to a bookmark",
diff --git a/src/key_command/impl_from_str.rs b/src/key_command/impl_from_str.rs
index 55a7fd7..74bac5d 100644
--- a/src/key_command/impl_from_str.rs
+++ b/src/key_command/impl_from_str.rs
@@ -113,8 +113,11 @@ impl std::str::FromStr for Command {
Self::CustomSearchInteractive(arg.split(' ').map(|x| x.to_string()).collect())
);
simple_command_conversion_case!(command, CMD_SUBDIR_FZF, Self::SubdirFzf);
- simple_command_conversion_case!(command, CMD_ZOXIDE, Self::Zoxide(arg.to_string()));
- simple_command_conversion_case!(command, CMD_ZOXIDE_INTERACTIVE, Self::ZoxideInteractive);
+ simple_command_conversion_case!(
+ command,
+ CMD_ZOXIDE_INTERACTIVE,
+ Self::ZoxideInteractive(arg.to_string())
+ );
if command == CMD_QUIT {
match arg {
@@ -602,6 +605,28 @@ impl std::str::FromStr for Command {
Ok(Self::FilterString {
pattern: arg.to_string(),
})
+ } else if command == CMD_ZOXIDE {
+ match arg {
+ "" => match HOME_DIR.as_ref() {
+ Some(s) => Ok(Self::ChangeDirectory { path: s.clone() }),
+ None => Err(AppError::new(
+ AppErrorKind::EnvVarNotPresent,
+ format!("{}: Cannot find home directory", command),
+ )),
+ },
+ ".." => Ok(Self::ParentDirectory),
+ "-" => Ok(Self::PreviousDirectory),
+ arg => {
+ let (head, tail) = match arg.find(' ') {
+ Some(i) => (&arg[..i], &arg[i..]),
+ None => (arg, ""),
+ };
+ let head = unix::expand_shell_string_cow(head);
+ let mut args = String::from(head);
+ args.push_str(tail);
+ Ok(Self::Zoxide(args))
+ }
+ }
} else {
Err(AppError::new(
AppErrorKind::UnrecognizedCommand,
diff --git a/src/util/unix.rs b/src/util/unix.rs
index 61d41fb..2d71359 100644
--- a/src/util/unix.rs
+++ b/src/util/unix.rs
@@ -56,6 +56,16 @@ pub fn mode_to_string(mode: u32) -> String {
mode_str
}
+pub fn expand_shell_string_cow(s: &str) -> std::borrow::Cow<'_, str> {
+ let dir = dirs_next::home_dir();
+ let os_str = dir.map(|s| s.as_os_str().to_owned());
+ let context_func = || {
+ let cow_str = os_str.as_ref().map(|s| s.to_string_lossy());
+ cow_str
+ };
+ shellexpand::tilde_with_context(s, context_func)
+}
+
pub fn expand_shell_string(s: &str) -> path::PathBuf {
let dir = dirs_next::home_dir();
let os_str = dir.map(|s| s.as_os_str().to_owned());