$_ZO_ECHO must be set to `1` to be enabled
This commit is contained in:
parent
e4dae1dd54
commit
4731533352
|
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Interactive mode in `zoxide` no longer throws an error if `fzf` exits gracefully.
|
||||
- Canonicalize to regular paths instead of UNC paths on Windows.
|
||||
- `zoxide init` now uses PWD hooks by default for better performance.
|
||||
- `$_ZO_ECHO` now only works when set to `1`.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -1,413 +0,0 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use clap::arg_enum;
|
||||
use structopt::StructOpt;
|
||||
use uuid::Uuid;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::io::{self, Write};
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(about = "Generates shell configuration")]
|
||||
pub struct Init {
|
||||
#[structopt(possible_values = &Shell::variants(), case_insensitive = true)]
|
||||
shell: Shell,
|
||||
|
||||
#[structopt(
|
||||
long,
|
||||
help = "Changes the name of the 'z' command",
|
||||
default_value = "z"
|
||||
)]
|
||||
z_cmd: String,
|
||||
|
||||
#[structopt(
|
||||
long,
|
||||
help = "Prevents zoxide from defining any commands other than 'z'"
|
||||
)]
|
||||
no_define_aliases: bool,
|
||||
|
||||
#[structopt(
|
||||
long,
|
||||
help = "Chooses event on which an entry is added to the database",
|
||||
possible_values = &Hook::variants(),
|
||||
default_value = "pwd",
|
||||
case_insensitive = true
|
||||
)]
|
||||
hook: Hook,
|
||||
}
|
||||
|
||||
impl Init {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
let config = match self.shell {
|
||||
Shell::bash => BASH_CONFIG,
|
||||
Shell::fish => FISH_CONFIG,
|
||||
Shell::posix => POSIX_CONFIG,
|
||||
Shell::zsh => ZSH_CONFIG,
|
||||
};
|
||||
|
||||
let stdout = io::stdout();
|
||||
let mut handle = stdout.lock();
|
||||
|
||||
let z = config.z;
|
||||
writeln!(handle, "{}", z(&self.z_cmd)).unwrap();
|
||||
|
||||
if !self.no_define_aliases {
|
||||
let alias = config.alias;
|
||||
writeln!(handle, "{}", alias(&self.z_cmd)).unwrap();
|
||||
}
|
||||
|
||||
match self.hook {
|
||||
Hook::none => (),
|
||||
Hook::prompt => writeln!(handle, "{}", config.hook.prompt).unwrap(),
|
||||
Hook::pwd => {
|
||||
let hook_pwd = config.hook.pwd;
|
||||
writeln!(handle, "{}", hook_pwd()?).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
arg_enum! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
enum Shell {
|
||||
bash,
|
||||
fish,
|
||||
posix,
|
||||
zsh,
|
||||
}
|
||||
}
|
||||
|
||||
arg_enum! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
enum Hook {
|
||||
none,
|
||||
prompt,
|
||||
pwd,
|
||||
}
|
||||
}
|
||||
|
||||
const BASH_CONFIG: ShellConfig = ShellConfig {
|
||||
z: bash_z,
|
||||
alias: bash_alias,
|
||||
hook: HookConfig {
|
||||
prompt: BASH_HOOK_PROMPT,
|
||||
pwd: bash_hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
const FISH_CONFIG: ShellConfig = ShellConfig {
|
||||
z: fish_z,
|
||||
alias: fish_alias,
|
||||
hook: HookConfig {
|
||||
prompt: FISH_HOOK_PROMPT,
|
||||
pwd: fish_hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
const POSIX_CONFIG: ShellConfig = ShellConfig {
|
||||
z: posix_z,
|
||||
alias: posix_alias,
|
||||
hook: HookConfig {
|
||||
prompt: POSIX_HOOK_PROMPT,
|
||||
pwd: posix_hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
const ZSH_CONFIG: ShellConfig = ShellConfig {
|
||||
z: zsh_z,
|
||||
alias: zsh_alias,
|
||||
hook: HookConfig {
|
||||
prompt: ZSH_HOOK_PROMPT,
|
||||
pwd: zsh_hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
struct ShellConfig {
|
||||
z: fn(&str) -> String,
|
||||
alias: fn(&str) -> String,
|
||||
hook: HookConfig,
|
||||
}
|
||||
|
||||
struct HookConfig {
|
||||
prompt: &'static str,
|
||||
pwd: fn() -> Result<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
fn fish_z(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
function _z_cd
|
||||
cd $argv
|
||||
or return $status
|
||||
|
||||
commandline -f repaint
|
||||
|
||||
if test -n "$_ZO_ECHO"
|
||||
echo $PWD
|
||||
end
|
||||
end
|
||||
|
||||
function {}
|
||||
set argc (count $argv)
|
||||
|
||||
if test $argc -eq 0
|
||||
_z_cd $HOME
|
||||
or return $status
|
||||
|
||||
else if test $argc -eq 1 -a $argv[1] = '-'
|
||||
_z_cd -
|
||||
or return $status
|
||||
|
||||
else
|
||||
# FIXME: use string-collect from fish 3.1.0 once it has wider adoption
|
||||
set -l IFS ''
|
||||
set -l result (zoxide query $argv)
|
||||
|
||||
if test -d $result; and string length -q -- $result
|
||||
_z_cd $result
|
||||
or return $status
|
||||
else if test -n "$result"
|
||||
echo $result
|
||||
end
|
||||
end
|
||||
end
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
fn posix_z(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
_z_cd() {{
|
||||
cd "$@" || return "$?"
|
||||
|
||||
if [ -n "$_ZO_ECHO" ]; then
|
||||
echo "$PWD"
|
||||
fi
|
||||
}}
|
||||
|
||||
{}() {{
|
||||
if [ "$#" -eq 0 ]; then
|
||||
_z_cd ~ || return "$?"
|
||||
elif [ "$#" -eq 1 ] && [ "$1" = '-' ]; then
|
||||
if [ -n "$OLDPWD" ]; then
|
||||
_z_cd "$OLDPWD" || return "$?"
|
||||
else
|
||||
echo 'zoxide: $OLDPWD is not set'
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
result="$(zoxide query "$@")" || return "$?"
|
||||
if [ -d "$result" ]; then
|
||||
_z_cd "$result" || return "$?"
|
||||
elif [ -n "$result" ]; then
|
||||
echo "$result"
|
||||
fi
|
||||
fi
|
||||
}}
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
use posix_z as bash_z;
|
||||
use posix_z as zsh_z;
|
||||
|
||||
fn fish_alias(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
abbr -a zi '{} -i'
|
||||
|
||||
abbr -a za 'zoxide add'
|
||||
|
||||
abbr -a zq 'zoxide query'
|
||||
abbr -a zqi 'zoxide query -i'
|
||||
|
||||
abbr -a zr 'zoxide remove'
|
||||
abbr -a zri 'zoxide remove -i'
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
fn posix_alias(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
alias zi='{} -i'
|
||||
|
||||
alias za='zoxide add'
|
||||
|
||||
alias zq='zoxide query'
|
||||
alias zqi='zoxide query -i'
|
||||
|
||||
alias zr='zoxide remove'
|
||||
alias zri='zoxide remove -i'
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
use posix_alias as bash_alias;
|
||||
use posix_alias as zsh_alias;
|
||||
|
||||
const BASH_HOOK_PROMPT: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
case "$PROMPT_COMMAND" in
|
||||
*_zoxide_hook*) ;;
|
||||
*) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;;
|
||||
esac
|
||||
"#;
|
||||
|
||||
const FISH_HOOK_PROMPT: &str = r#"
|
||||
function _zoxide_hook --on-event fish_prompt
|
||||
zoxide add
|
||||
end
|
||||
"#;
|
||||
|
||||
const POSIX_HOOK_PROMPT: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
case "$PS1" in
|
||||
*\$\(_zoxide_hook\)*) ;;
|
||||
*) PS1="\$(_zoxide_hook)${PS1}" ;;
|
||||
esac
|
||||
"#;
|
||||
|
||||
const ZSH_HOOK_PROMPT: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
[[ -n "${precmd_functions[(r)_zoxide_hook]}" ]] || {
|
||||
precmd_functions+=(_zoxide_hook)
|
||||
}
|
||||
"#;
|
||||
|
||||
const fn bash_hook_pwd() -> Result<Cow<'static, str>> {
|
||||
const HOOK_PWD: &str = r#"
|
||||
_zoxide_hook() {
|
||||
if [ -z "${_ZO_PWD}" ]; then
|
||||
_ZO_PWD="${PWD}"
|
||||
elif [ "${_ZO_PWD}" != "${PWD}" ]; then
|
||||
_ZO_PWD="${PWD}"
|
||||
zoxide add
|
||||
fi
|
||||
}
|
||||
|
||||
case "$PROMPT_COMMAND" in
|
||||
*_zoxide_hook*) ;;
|
||||
*) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;;
|
||||
esac
|
||||
"#;
|
||||
|
||||
Ok(Cow::Borrowed(HOOK_PWD))
|
||||
}
|
||||
|
||||
const fn fish_hook_pwd() -> Result<Cow<'static, str>> {
|
||||
const HOOK_PWD: &str = r#"
|
||||
function _zoxide_hook --on-variable PWD
|
||||
zoxide add
|
||||
end
|
||||
"#;
|
||||
|
||||
Ok(Cow::Borrowed(HOOK_PWD))
|
||||
}
|
||||
|
||||
fn posix_hook_pwd() -> Result<Cow<'static, str>> {
|
||||
let mut tmp_path = std::env::temp_dir();
|
||||
tmp_path.push("zoxide");
|
||||
|
||||
let tmp_path_str = tmp_path
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("invalid Unicode in zoxide tmp path"))?;
|
||||
|
||||
let pwd_path = tmp_path.join(format!("pwd-{}", Uuid::new_v4()));
|
||||
|
||||
let pwd_path_str = pwd_path
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("invalid Unicode in zoxide pwd path"))?;
|
||||
|
||||
let hook_pwd = format!(
|
||||
r#"
|
||||
# PWD hooks in POSIX use a temporary file, located at `$_ZO_PWD_PATH`, to track
|
||||
# changes in the current directory. These files are removed upon restart,
|
||||
# but they should ideally also be cleaned up once the shell exits using traps.
|
||||
#
|
||||
# This can be done as follows:
|
||||
#
|
||||
# trap '_zoxide_cleanup' EXIT HUP KILL TERM
|
||||
# trap '_zoxide_cleanup; trap - INT; kill -s INT "$$"' INT
|
||||
# trap '_zoxide_cleanup; trap - QUIT; kill -s QUIT "$$"' QUIT
|
||||
#
|
||||
# By default, traps are not set up because they override all previous traps.
|
||||
# It is therefore up to the user to add traps to their shell configuration.
|
||||
|
||||
_ZO_TMP_PATH={}
|
||||
_ZO_PWD_PATH={}
|
||||
|
||||
_zoxide_cleanup() {{
|
||||
rm -f "$_ZO_PWD_PATH"
|
||||
}}
|
||||
|
||||
_zoxide_setpwd() {{
|
||||
mkdir -p "$_ZO_TMP_PATH"
|
||||
echo "$PWD" > "$_ZO_PWD_PATH"
|
||||
}}
|
||||
|
||||
_zoxide_setpwd
|
||||
|
||||
_zoxide_hook() {{
|
||||
_ZO_OLDPWD="$(cat "$_ZO_PWD_PATH")"
|
||||
if [ -z "$_ZO_OLDPWD" ] || [ "$_ZO_OLDPWD" != "$PWD" ]; then
|
||||
_zoxide_setpwd && zoxide add > /dev/null
|
||||
fi
|
||||
}}
|
||||
|
||||
case "$PS1" in
|
||||
*\$\(_zoxide_hook\)*) ;;
|
||||
*) PS1="\$(_zoxide_hook)${{PS1}}" ;;
|
||||
esac"#,
|
||||
posix_quote(tmp_path_str),
|
||||
posix_quote(pwd_path_str),
|
||||
);
|
||||
|
||||
Ok(Cow::Owned(hook_pwd))
|
||||
}
|
||||
|
||||
const fn zsh_hook_pwd() -> Result<Cow<'static, str>> {
|
||||
const HOOK_PWD: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
chpwd_functions=(${chpwd_functions[@]} "_zoxide_hook")
|
||||
"#;
|
||||
|
||||
Ok(Cow::Borrowed(HOOK_PWD))
|
||||
}
|
||||
|
||||
fn posix_quote(string: &str) -> String {
|
||||
let mut quoted = String::with_capacity(string.len() + 2);
|
||||
quoted.push('\'');
|
||||
|
||||
for ch in string.chars() {
|
||||
match ch {
|
||||
'\\' => quoted.push_str(r"\\"),
|
||||
'\'' => quoted.push_str(r"'\''"),
|
||||
_ => quoted.push(ch),
|
||||
}
|
||||
}
|
||||
|
||||
quoted.push('\'');
|
||||
|
||||
quoted
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
mod shell;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::arg_enum;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use std::io::{self, Write};
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(about = "Generates shell configuration")]
|
||||
pub struct Init {
|
||||
#[structopt(possible_values = &Shell::variants(), case_insensitive = true)]
|
||||
shell: Shell,
|
||||
|
||||
#[structopt(
|
||||
long,
|
||||
help = "Changes the name of the 'z' command",
|
||||
default_value = "z"
|
||||
)]
|
||||
z_cmd: String,
|
||||
|
||||
#[structopt(
|
||||
long,
|
||||
help = "Prevents zoxide from defining any commands other than 'z'"
|
||||
)]
|
||||
no_define_aliases: bool,
|
||||
|
||||
#[structopt(
|
||||
long,
|
||||
help = "Chooses event on which an entry is added to the database",
|
||||
possible_values = &Hook::variants(),
|
||||
default_value = "pwd",
|
||||
case_insensitive = true
|
||||
)]
|
||||
hook: Hook,
|
||||
}
|
||||
|
||||
impl Init {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
let config = match self.shell {
|
||||
Shell::bash => shell::bash::CONFIG,
|
||||
Shell::fish => shell::fish::CONFIG,
|
||||
Shell::posix => shell::posix::CONFIG,
|
||||
Shell::zsh => shell::zsh::CONFIG,
|
||||
};
|
||||
|
||||
let stdout = io::stdout();
|
||||
let mut handle = stdout.lock();
|
||||
|
||||
let z = config.z;
|
||||
writeln!(handle, "{}", z(&self.z_cmd)).unwrap();
|
||||
|
||||
if !self.no_define_aliases {
|
||||
let alias = config.alias;
|
||||
writeln!(handle, "{}", alias(&self.z_cmd)).unwrap();
|
||||
}
|
||||
|
||||
match self.hook {
|
||||
Hook::none => (),
|
||||
Hook::prompt => writeln!(handle, "{}", config.hook.prompt).unwrap(),
|
||||
Hook::pwd => {
|
||||
let hook_pwd = config.hook.pwd;
|
||||
writeln!(handle, "{}", hook_pwd()?).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
arg_enum! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
enum Shell {
|
||||
bash,
|
||||
fish,
|
||||
posix,
|
||||
zsh,
|
||||
}
|
||||
}
|
||||
|
||||
arg_enum! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
enum Hook {
|
||||
none,
|
||||
prompt,
|
||||
pwd,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
use super::{posix, HookConfig, ShellConfig};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub const CONFIG: ShellConfig = ShellConfig {
|
||||
z: posix::CONFIG.z,
|
||||
alias: posix::CONFIG.alias,
|
||||
hook: HookConfig {
|
||||
prompt: HOOK_PROMPT,
|
||||
pwd: hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
const HOOK_PROMPT: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
case "$PROMPT_COMMAND" in
|
||||
*_zoxide_hook*) ;;
|
||||
*) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;;
|
||||
esac
|
||||
"#;
|
||||
|
||||
const fn hook_pwd() -> Result<Cow<'static, str>> {
|
||||
const HOOK_PWD: &str = r#"
|
||||
_zoxide_hook() {
|
||||
if [ -z "${_ZO_PWD}" ]; then
|
||||
_ZO_PWD="${PWD}"
|
||||
elif [ "${_ZO_PWD}" != "${PWD}" ]; then
|
||||
_ZO_PWD="${PWD}"
|
||||
zoxide add
|
||||
fi
|
||||
}
|
||||
|
||||
case "$PROMPT_COMMAND" in
|
||||
*_zoxide_hook*) ;;
|
||||
*) PROMPT_COMMAND="_zoxide_hook${PROMPT_COMMAND:+;${PROMPT_COMMAND}}" ;;
|
||||
esac
|
||||
"#;
|
||||
|
||||
Ok(Cow::Borrowed(HOOK_PWD))
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
use super::{ShellConfig, HookConfig};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub const CONFIG: ShellConfig = ShellConfig {
|
||||
z,
|
||||
alias,
|
||||
hook: HookConfig {
|
||||
prompt: HOOK_PROMPT,
|
||||
pwd: hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
fn z(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
function _z_cd
|
||||
cd $argv
|
||||
or return $status
|
||||
|
||||
commandline -f repaint
|
||||
|
||||
if test "$_ZO_ECHO" = "1"
|
||||
echo $PWD
|
||||
end
|
||||
end
|
||||
|
||||
function {}
|
||||
set argc (count $argv)
|
||||
|
||||
if test $argc -eq 0
|
||||
_z_cd $HOME
|
||||
or return $status
|
||||
|
||||
else if test $argc -eq 1 -a $argv[1] = '-'
|
||||
_z_cd -
|
||||
or return $status
|
||||
|
||||
else
|
||||
# FIXME: use string-collect from fish 3.1.0 once it has wider adoption
|
||||
set -l IFS ''
|
||||
set -l result (zoxide query $argv)
|
||||
|
||||
if test -d $result; and string length -q -- $result
|
||||
_z_cd $result
|
||||
or return $status
|
||||
else if test -n "$result"
|
||||
echo $result
|
||||
end
|
||||
end
|
||||
end
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
fn alias(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
abbr -a zi '{} -i'
|
||||
|
||||
abbr -a za 'zoxide add'
|
||||
|
||||
abbr -a zq 'zoxide query'
|
||||
abbr -a zqi 'zoxide query -i'
|
||||
|
||||
abbr -a zr 'zoxide remove'
|
||||
abbr -a zri 'zoxide remove -i'
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
const HOOK_PROMPT: &str = r#"
|
||||
function _zoxide_hook --on-event fish_prompt
|
||||
zoxide add
|
||||
end
|
||||
"#;
|
||||
|
||||
const fn hook_pwd() -> Result<Cow<'static, str>> {
|
||||
const HOOK_PWD: &str = r#"
|
||||
function _zoxide_hook --on-variable PWD
|
||||
zoxide add
|
||||
end
|
||||
"#;
|
||||
|
||||
Ok(Cow::Borrowed(HOOK_PWD))
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
pub mod bash;
|
||||
pub mod fish;
|
||||
pub mod posix;
|
||||
pub mod zsh;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub struct ShellConfig {
|
||||
pub z: fn(&str) -> String,
|
||||
pub alias: fn(&str) -> String,
|
||||
pub hook: HookConfig,
|
||||
}
|
||||
|
||||
pub struct HookConfig {
|
||||
pub prompt: &'static str,
|
||||
pub pwd: fn() -> Result<Cow<'static, str>>,
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
use super::{HookConfig, ShellConfig};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use uuid::Uuid;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub const CONFIG: ShellConfig = ShellConfig {
|
||||
z,
|
||||
alias,
|
||||
hook: HookConfig {
|
||||
prompt: HOOK_PROMPT,
|
||||
pwd: hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
fn z(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
_z_cd() {{
|
||||
cd "$@" || return "$?"
|
||||
|
||||
if [ "$_ZO_ECHO" = "1" ]; then
|
||||
echo "$PWD"
|
||||
fi
|
||||
}}
|
||||
|
||||
{}() {{
|
||||
if [ "$#" -eq 0 ]; then
|
||||
_z_cd ~ || return "$?"
|
||||
elif [ "$#" -eq 1 ] && [ "$1" = '-' ]; then
|
||||
if [ -n "$OLDPWD" ]; then
|
||||
_z_cd "$OLDPWD" || return "$?"
|
||||
else
|
||||
echo 'zoxide: $OLDPWD is not set'
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
result="$(zoxide query "$@")" || return "$?"
|
||||
if [ -d "$result" ]; then
|
||||
_z_cd "$result" || return "$?"
|
||||
elif [ -n "$result" ]; then
|
||||
echo "$result"
|
||||
fi
|
||||
fi
|
||||
}}
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
fn alias(z_cmd: &str) -> String {
|
||||
format!(
|
||||
r#"
|
||||
alias zi='{} -i'
|
||||
|
||||
alias za='zoxide add'
|
||||
|
||||
alias zq='zoxide query'
|
||||
alias zqi='zoxide query -i'
|
||||
|
||||
alias zr='zoxide remove'
|
||||
alias zri='zoxide remove -i'
|
||||
"#,
|
||||
z_cmd
|
||||
)
|
||||
}
|
||||
|
||||
const HOOK_PROMPT: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
case "$PS1" in
|
||||
*\$\(_zoxide_hook\)*) ;;
|
||||
*) PS1="\$(_zoxide_hook)${PS1}" ;;
|
||||
esac
|
||||
"#;
|
||||
|
||||
fn hook_pwd() -> Result<Cow<'static, str>> {
|
||||
let mut tmp_path = std::env::temp_dir();
|
||||
tmp_path.push("zoxide");
|
||||
|
||||
let tmp_path_str = tmp_path
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("invalid Unicode in zoxide tmp path"))?;
|
||||
|
||||
let pwd_path = tmp_path.join(format!("pwd-{}", Uuid::new_v4()));
|
||||
|
||||
let pwd_path_str = pwd_path
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("invalid Unicode in zoxide pwd path"))?;
|
||||
|
||||
let hook_pwd = format!(
|
||||
r#"
|
||||
# PWD hooks in POSIX use a temporary file, located at `$_ZO_PWD_PATH`, to track
|
||||
# changes in the current directory. These files are removed upon restart,
|
||||
# but they should ideally also be cleaned up once the shell exits using traps.
|
||||
#
|
||||
# This can be done as follows:
|
||||
#
|
||||
# trap '_zoxide_cleanup' EXIT HUP KILL TERM
|
||||
# trap '_zoxide_cleanup; trap - INT; kill -s INT "$$"' INT
|
||||
# trap '_zoxide_cleanup; trap - QUIT; kill -s QUIT "$$"' QUIT
|
||||
#
|
||||
# By default, traps are not set up because they override all previous traps.
|
||||
# It is therefore up to the user to add traps to their shell configuration.
|
||||
|
||||
_ZO_TMP_PATH={}
|
||||
_ZO_PWD_PATH={}
|
||||
|
||||
_zoxide_cleanup() {{
|
||||
rm -f "$_ZO_PWD_PATH"
|
||||
}}
|
||||
|
||||
_zoxide_setpwd() {{
|
||||
mkdir -p "$_ZO_TMP_PATH"
|
||||
echo "$PWD" > "$_ZO_PWD_PATH"
|
||||
}}
|
||||
|
||||
_zoxide_setpwd
|
||||
|
||||
_zoxide_hook() {{
|
||||
_ZO_OLDPWD="$(cat "$_ZO_PWD_PATH")"
|
||||
if [ -z "$_ZO_OLDPWD" ] || [ "$_ZO_OLDPWD" != "$PWD" ]; then
|
||||
_zoxide_setpwd && zoxide add > /dev/null
|
||||
fi
|
||||
}}
|
||||
|
||||
case "$PS1" in
|
||||
*\$\(_zoxide_hook\)*) ;;
|
||||
*) PS1="\$(_zoxide_hook)${{PS1}}" ;;
|
||||
esac"#,
|
||||
quote(tmp_path_str),
|
||||
quote(pwd_path_str),
|
||||
);
|
||||
|
||||
Ok(Cow::Owned(hook_pwd))
|
||||
}
|
||||
|
||||
fn quote(string: &str) -> String {
|
||||
let mut quoted = String::with_capacity(string.len() + 2);
|
||||
|
||||
quoted.push('\'');
|
||||
for ch in string.chars() {
|
||||
match ch {
|
||||
'\\' => quoted.push_str(r"\\"),
|
||||
'\'' => quoted.push_str(r"'\''"),
|
||||
_ => quoted.push(ch),
|
||||
}
|
||||
}
|
||||
quoted.push('\'');
|
||||
|
||||
quoted
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
use super::{posix, HookConfig, ShellConfig};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub const CONFIG: ShellConfig = ShellConfig {
|
||||
z: posix::CONFIG.z,
|
||||
alias: posix::CONFIG.alias,
|
||||
hook: HookConfig {
|
||||
prompt: HOOK_PROMPT,
|
||||
pwd: hook_pwd,
|
||||
},
|
||||
};
|
||||
|
||||
const HOOK_PROMPT: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
[[ -n "${precmd_functions[(r)_zoxide_hook]}" ]] || {
|
||||
precmd_functions+=(_zoxide_hook)
|
||||
}
|
||||
"#;
|
||||
|
||||
const fn hook_pwd() -> Result<Cow<'static, str>> {
|
||||
const HOOK_PWD: &str = r#"
|
||||
_zoxide_hook() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
chpwd_functions=(${chpwd_functions[@]} "_zoxide_hook")
|
||||
"#;
|
||||
|
||||
Ok(Cow::Borrowed(HOOK_PWD))
|
||||
}
|
Loading…
Reference in New Issue