$_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.
|
- Interactive mode in `zoxide` no longer throws an error if `fzf` exits gracefully.
|
||||||
- Canonicalize to regular paths instead of UNC paths on Windows.
|
- Canonicalize to regular paths instead of UNC paths on Windows.
|
||||||
- `zoxide init` now uses PWD hooks by default for better performance.
|
- `zoxide init` now uses PWD hooks by default for better performance.
|
||||||
|
- `$_ZO_ECHO` now only works when set to `1`.
|
||||||
|
|
||||||
### Fixed
|
### 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