150 lines
3.1 KiB
Rust
150 lines
3.1 KiB
Rust
use super::{HookConfig, ShellConfig};
|
|
use crate::util;
|
|
|
|
use 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(cmd: &str) -> String {
|
|
format!(
|
|
r#"
|
|
_z_cd() {{
|
|
cd "$@" || return "$?"
|
|
|
|
if [ "$_ZO_ECHO" = "1" ]; then
|
|
echo "$PWD"
|
|
fi
|
|
}}
|
|
|
|
{0}() {{
|
|
if [ "$#" -eq 0 ]; then
|
|
_z_cd ~
|
|
elif [ "$#" -eq 1 ] && [ "$1" = '-' ]; then
|
|
if [ -n "$OLDPWD" ]; then
|
|
_z_cd "$OLDPWD"
|
|
else
|
|
echo 'zoxide: $OLDPWD is not set'
|
|
return 1
|
|
fi
|
|
else
|
|
_zoxide_result="$(zoxide query -- "$@")" && _z_cd "$_zoxide_result"
|
|
fi
|
|
}}
|
|
|
|
{0}i() {{
|
|
_zoxide_result="$(zoxide query -i -- "$@")" && _z_cd "$_zoxide_result"
|
|
}}
|
|
"#,
|
|
cmd
|
|
)
|
|
}
|
|
|
|
fn alias(cmd: &str) -> String {
|
|
format!(
|
|
r#"
|
|
alias {0}a='zoxide add'
|
|
|
|
alias {0}q='zoxide query'
|
|
alias {0}qi='zoxide query -i'
|
|
|
|
alias {0}r='zoxide remove'
|
|
{0}ri() {{
|
|
_zoxide_result="$(zoxide query -i -- "$@")" && zoxide remove "$_zoxide_result"
|
|
}}
|
|
"#,
|
|
cmd
|
|
)
|
|
}
|
|
|
|
const HOOK_PROMPT: &str = r#"
|
|
_zoxide_hook() {
|
|
zoxide add "$(pwd -L)"
|
|
}
|
|
|
|
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 = util::path_to_str(&tmp_path)?;
|
|
|
|
let pwd_path = tmp_path.join(format!("pwd-{}", Uuid::new_v4()));
|
|
let pwd_path_str = util::path_to_str(&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 "$(pwd -L)" > /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
|
|
}
|