Update 05.04.2026

This commit is contained in:
eof
2026-04-05 17:51:45 +05:00
parent fcc904df1e
commit b363a93ea5
680 changed files with 16892 additions and 16586 deletions

View File

@@ -1,12 +1,12 @@
# wd
[![Build Status](https://travis-ci.org/mfaerevaag/wd.png?branch=master)](https://travis-ci.org/mfaerevaag/wd)
[![Build Status](https://github.com/mfaerevaag/wd/actions/workflows/test.yml/badge.svg)](https://github.com/mfaerevaag/wd/actions)
`wd` (*warp directory*) lets you jump to custom directories in zsh, without using `cd`.
Why?
Because `cd` seems inefficient when the folder is frequently visited or has a long path.
![tty.gif](https://raw.githubusercontent.com/mfaerevaag/wd/master/tty.gif)
![Demo](https://raw.githubusercontent.com/mfaerevaag/wd/master/tty.gif)
## Setup
@@ -36,6 +36,10 @@ In your `.zshrc`:
antibody bundle mfaerevaag/wd
```
### [Fig](https://fig.io)
Install `wd` here: [![Fig plugin store](https://fig.io/badges/install-with-fig.svg)](https://fig.io/plugins/other/wd_mfaerevaag)
### Arch ([AUR](https://aur.archlinux.org/packages/zsh-plugin-wd-git/))
1. Install from the AUR
@@ -53,6 +57,21 @@ wd() {
}
```
### [Home Manager](https://github.com/nix-community/home-manager)
Add the following to your `home.nix` then run `home-manager switch`:
```nix
programs.zsh.plugins = [
{
name = "wd";
src = pkgs.zsh-wd;
file = "share/wd/wd.plugin.zsh";
completions = [ "share/zsh/site-functions" ];
}
];
```
### [zplug](https://github.com/zplug/zplug)
```zsh
@@ -93,9 +112,11 @@ wd() {
3. Install manpage (optional):
Move manpage into an appropriate directory, then trigger `mandb` to discover it
```zsh
sudo cp ~/.local/wd/wd.1 /usr/share/man/man1/wd.1
sudo chmod 644 /usr/share/man/man1/wd.1
sudo install -m 644 ~/.local/wd/wd.1 /usr/share/man/man1/wd.1
sudo mandb /usr/share/man/man1
```
**Note:** when pulling and updating `wd`, you'll need to repeat step 3 should the manpage change
@@ -115,6 +136,15 @@ Also, you may have to force a rebuild of `zcompdump` by running:
rm -f ~/.zcompdump; compinit
```
## Browse
`wd` comes with an `fzf`-powered browse feature to fuzzy search through all your warp points. It's available through the `wd browse` command. For quick access you can set up an alias or keybind in your `.zshrc`:
```zsh
# ctrl-b to open the fzf browser
bindkey ${FZF_WD_BINDKEY:-'^B'} wd_browse_widget
```
## Usage
* Add warp point to current working directory:
@@ -128,6 +158,19 @@ If a warp point with the same name exists, use `wd add foo --force` to overwrite
**Note:** a warp point cannot contain colons, or consist of only spaces and dots.
The first will conflict in how `wd` stores the warp points, and the second will conflict with other features, as below.
* Add warp point to any directory with default name:
```zsh
wd addcd /foo/ bar
```
* Add warp point to any directory with a custom name:
```zsh
wd addcd /foo/
```
You can omit point name to automatically use the current directory's name instead.
* From any directory, warp to `foo` with:
@@ -212,12 +255,6 @@ wd --version
wd --config ./file <command>
```
* Force `exit` with return code after running. This is not default, as it will *exit your terminal*, though required for testing/debugging.
```zsh
wd --debug <command>
```
* Silence all output:
```zsh

View File

@@ -31,11 +31,13 @@ function _wd() {
commands=(
'add:Adds the current working directory to your warp points'
'addcd:Adds a directory to your warp points'
'add!:Overwrites existing warp point'
'export:Export warp points as static named directories'
'rm:Removes the given warp point'
'list:Outputs all stored warp points'
'ls:Show files from given warp point'
'open:Open warp point in the default file explorer'
'path:Show path to given warp point'
'show:Outputs all warp points that point to the current directory or shows a specific target directory for a point'
'help:Show this extremely helpful text'
@@ -63,12 +65,18 @@ function _wd() {
add)
_message 'Write the name of your warp point' && ret=0
;;
addcd)
_message 'Write the name of your path' && ret=0
;;
show)
_describe -t points "Warp points" warp_points && ret=0
;;
ls)
_describe -t points "Warp points" warp_points && ret=0
;;
open)
_describe -t points "Warp points" warp_points && ret=0
;;
path)
_describe -t points "Warp points" warp_points && ret=0
;;
@@ -77,7 +85,7 @@ function _wd() {
# complete sub directories from the warp point
_path_files -W "(${points[$target]})" -/ && ret=0
fi
# don't complete anything if warp point is not valid
;;
esac

View File

@@ -1,4 +1,4 @@
#!/bin/zsh
#!/usr/bin/env zsh
# WARP DIRECTORY
# ==============
@@ -8,8 +8,13 @@
# @github.com/mfaerevaag/wd
# Handle $0 according to the standard:
# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
# # https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
0="${${(M)0:#/*}:-$PWD/$0}"
eval "wd() { source '${0:A:h}/wd.sh' }"
wd > /dev/null
zle -N wd_browse_widget
zle -N wd_restore_buffer
autoload -Uz add-zle-hook-widget
add-zle-hook-widget line-init wd_restore_buffer

267
zsh/plugins/wd/wd.sh Normal file → Executable file
View File

@@ -1,4 +1,4 @@
#!/bin/zsh
#!/usr/bin/env zsh
# WARP DIRECTORY
# ==============
@@ -8,7 +8,7 @@
# @github.com/mfaerevaag/wd
# version
readonly WD_VERSION=0.5.0
readonly WD_VERSION=0.10.1
# colors
readonly WD_BLUE="\033[96m"
@@ -57,12 +57,11 @@ wd_print_msg()
{
if [[ -z $wd_quiet_mode ]]
then
local color=$1
local msg=$2
local color="${1:-$WD_BLUE}" # Default to blue if no color is provided
local msg="$2"
if [[ $color == "" || $msg == "" ]]
then
print " ${WD_RED}*${WD_NOC} Could not print message. Sorry!"
if [[ -z "$msg" ]]; then
print "${WD_RED}*${WD_NOC} Could not print message. Sorry!"
else
print " ${color}*${WD_NOC} ${msg}"
fi
@@ -75,21 +74,23 @@ wd_print_usage()
Usage: wd [command] [point]
Commands:
<point> Warps to the directory specified by the warp point
<point> <path> Warps to the directory specified by the warp point with path appended
add <point> Adds the current working directory to your warp points
add Adds the current working directory to your warp points with current directory's name
rm <point> Removes the given warp point
rm Removes the given warp point with current directory's name
show <point> Print path to given warp point
show Print warp points to current directory
list Print all stored warp points
ls <point> Show files from given warp point (ls)
path <point> Show the path to given warp point (pwd)
clean Remove points warping to nonexistent directories (will prompt unless --force is used)
<point> Warps to the directory specified by the warp point
<point> <path> Warps to the directory specified by the warp point with path appended
add <point> Adds the current working directory to your warp points
add Adds the current working directory to your warp points with current directory's name
addcd <path> Adds a path to your warp points with the directory's name
addcd <path> <point> Adds a path to your warp points with a custom name
rm <point> Removes the given warp point
rm Removes the given warp point with current directory's name
show <point> Print path to given warp point
show Print warp points to current directory
list Print all stored warp points
ls <point> Show files from given warp point (ls)
open <point> Open the warp point in the default file explorer (open / xdg-open)
path <point> Show the path to given warp point (pwd)
clean Remove points warping to nonexistent directories (will prompt unless --force is used)
-v | --version Print version
-d | --debug Exit after execution with exit codes (for testing)
-c | --config Specify config file (default ~/.warprc)
-q | --quiet Suppress all output
-f | --force Allows overwriting without warning (for add & clean)
@@ -145,14 +146,17 @@ wd_warp()
else
(( n = $#1 - 1 ))
cd -$n > /dev/null
WD_EXIT_CODE=$?
fi
elif [[ ${points[$point]} != "" ]]
then
if [[ $sub != "" ]]
then
cd ${points[$point]/#\~/$HOME}/$sub
WD_EXIT_CODE=$?
else
cd ${points[$point]/#\~/$HOME}
WD_EXIT_CODE=$?
fi
else
wd_exit_fail "Unknown warp point '${point}'"
@@ -163,12 +167,18 @@ wd_add()
{
local point=$1
local force=$2
cmdnames=(add rm show list ls path clean help)
if [[ $point == "" ]]
then
point=$(basename "$PWD")
fi
if [ ! -w "$wd_config_file" ]; then
wd_exit_fail "\'$wd_config_file\' is not writeable."
return
fi
if [[ $point =~ "^[\.]+$" ]]
then
wd_exit_fail "Warp point cannot be just dots"
@@ -178,14 +188,17 @@ wd_add()
elif [[ $point =~ : ]] || [[ $point =~ / ]]
then
wd_exit_fail "Warp point contains illegal character (:/)"
elif (($cmdnames[(Ie)$point]))
then
wd_exit_fail "Warp point name cannot be a wd command (see wd -h for a full list)"
elif [[ ${points[$point]} == "" ]] || [ ! -z "$force" ]
then
wd_remove "$point" > /dev/null
printf "%q:%s\n" "${point}" "${PWD/#$HOME/~}" >> "$WD_CONFIG"
printf "%q:%s\n" "${point}" "${PWD/#$HOME/~}" >> "$wd_config_file"
if (whence sort >/dev/null); then
local config_tmp=$(mktemp "${TMPDIR:-/tmp}/wd.XXXXXXXXXX")
# use 'cat' below to ensure we respect $WD_CONFIG as a symlink
command sort -o "${config_tmp}" "$WD_CONFIG" && command cat "${config_tmp}" > "$WD_CONFIG" && command rm "${config_tmp}"
# use 'cat' below to ensure we respect $wd_config_file as a symlink
command sort -o "${config_tmp}" "$wd_config_file" && command cat "${config_tmp}" >| "$wd_config_file" && command rm "${config_tmp}"
fi
wd_export_static_named_directories
@@ -200,6 +213,28 @@ wd_add()
fi
}
wd_addcd() {
local folder="$1"
local point=$2
local force=$3
local currentdir=$PWD
if [[ -z "$folder" ]]; then
wd_exit_fail "You must specify a path"
return
fi
if [[ ! -d "$folder" ]]; then
wd_exit_fail "The directory does not exist"
return
fi
cd "$folder" || return
wd_add "$point" "$force"
cd "$currentdir" || return
}
wd_remove()
{
local point_list=$1
@@ -209,12 +244,17 @@ wd_remove()
point_list=$(basename "$PWD")
fi
if [ ! -w "$wd_config_file" ]; then
wd_exit_fail "\'$wd_config_file\' is not writeable."
return
fi
for point_name in $point_list ; do
if [[ ${points[$point_name]} != "" ]]
then
local config_tmp=$(mktemp "${TMPDIR:-/tmp}/wd.XXXXXXXXXX")
# Copy and delete in two steps in order to preserve symlinks
if sed -n "/^${point_name}:.*$/!p" "$WD_CONFIG" > "$config_tmp" && command cp "$config_tmp" "$WD_CONFIG" && command rm "$config_tmp"
if sed -n "/^${point_name}:.*$/!p" "$wd_config_file" >| "$config_tmp" && command cp "$config_tmp" "$wd_config_file" && command rm "$config_tmp"
then
wd_print_msg "$WD_GREEN" "Warp point removed"
else
@@ -226,11 +266,92 @@ wd_remove()
done
}
wd_browse() {
# Check if fzf is installed
if ! command -v fzf >/dev/null; then
wd_print_msg "$WD_RED" "This functionality requires fzf. Please install fzf first."
return 1
fi
# Ensure wd_config_file is properly set
if [[ -z $wd_config_file ]]; then
wd_config_file="${WD_CONFIG:-$HOME/.warprc}"
fi
# Check if config file exists
if [[ ! -f $wd_config_file ]]; then
wd_print_msg "$WD_RED" "Config file $wd_config_file does not exist. Please create it first."
return 1
fi
# Read entries from the config file
local entries=("${(@f)$(sed "s:${HOME}:~:g" "$wd_config_file" | awk -F ':' '{print $1 " -> " $2}')}")
if [[ -z $entries ]]; then
wd_print_msg "$WD_YELLOW" "You don't have any warp points to browse"
return 1
fi
# Temp file for remove operations
local script_path="${${(%):-%x}:h}"
local wd_remove_output=$(mktemp "${TMPDIR:-/tmp}/wd.XXXXXXXXXX")
# Create fzf bindings
entries=("All warp points:" "Press enter to select. Press delete to remove" "${entries[@]}")
local fzf_bind="delete:execute(echo {} | awk -F ' -> ' '{print \$1}' | xargs -I {} \"$script_path/wd.sh\" rm {} > \"$wd_remove_output\")+abort"
# Run fzf
local selected_entry=$(printf '%s\n' "${entries[@]}" | fzf --height 100% --reverse --header-lines=2 --bind="$fzf_bind")
# Handle selection
if [[ -e $wd_remove_output ]]; then
cat "$wd_remove_output"
rm -f "$wd_remove_output"
fi
if [[ -n $selected_entry ]]; then
local selected_point="${selected_entry%% ->*}"
selected_point=$(echo "$selected_point" | xargs)
wd $selected_point
fi
}
wd_browse_widget() {
# Ensure wd_config_file is properly set
if [[ -z $wd_config_file ]]; then
wd_config_file="${WD_CONFIG:-$HOME/.warprc}"
fi
# Check if config file exists
if [[ ! -f $wd_config_file ]]; then
wd_print_msg "$WD_RED" "Config file $wd_config_file does not exist. Please create it first."
return 1
fi
# Call wd_browse to handle the selection
wd_browse
# Restore the zsh buffer and cursor after running wd_browse
saved_buffer=$BUFFER
saved_cursor=$CURSOR
BUFFER=
zle redisplay
zle accept-line
}
wd_restore_buffer() {
if [[ -n $saved_buffer ]]; then
BUFFER=$saved_buffer
CURSOR=$saved_cursor
fi
saved_buffer=
saved_cursor=1
}
wd_list_all()
{
wd_print_msg "$WD_BLUE" "All warp points:"
entries=$(sed "s:${HOME}:~:g" "$WD_CONFIG")
entries=$(sed "s:${HOME}:~:g" "$wd_config_file")
max_warp_point_length=0
while IFS= read -r line
@@ -251,7 +372,7 @@ wd_list_all()
then
arr=(${(s,:,)line})
key=${arr[1]}
val=${arr[2]}
val=${line#"${arr[1]}:"}
if [[ -z $wd_quiet_mode ]]
then
@@ -267,6 +388,21 @@ wd_ls()
ls "${dir/#\~/$HOME}"
}
wd_open()
{
wd_getdir "$1"
if command -v open >/dev/null 2>&1; then
# MacOS, Ubuntu (alias)
open "${dir/#\~/$HOME}"
elif command -v xdg-open >/dev/null 2>&1; then
# Most Linux desktops
xdg-open "${dir/#\~/$HOME}"
else
echo "No known file opener found (need 'open' or 'xdg-open')." >&2
exit 1
fi
}
wd_path()
{
wd_getdir "$1"
@@ -276,6 +412,7 @@ wd_path()
wd_show()
{
local name_arg=$1
local show_pwd
# if there's an argument we look up the value
if [[ -n $name_arg ]]
then
@@ -290,12 +427,12 @@ wd_show()
local wd_matches
wd_matches=()
# do a reverse lookup to check whether PWD is in $points
PWD="${PWD/$HOME/~}"
if [[ ${points[(r)$PWD]} == "$PWD" ]]
show_pwd="${PWD/$HOME/~}"
if [[ ${points[(r)$show_pwd]} == "$show_pwd" ]]
then
for name in ${(k)points}
do
if [[ $points[$name] == "$PWD" ]]
if [[ $points[$name] == "$show_pwd" ]]
then
wd_matches[$(($#wd_matches+1))]=$name
fi
@@ -303,7 +440,7 @@ wd_show()
wd_print_msg "$WD_BLUE" "$#wd_matches warp point(s) to current directory: ${WD_GREEN}$wd_matches${WD_NOC}"
else
wd_print_msg "$WD_YELLOW" "No warp point to $(echo "$PWD" | sed "s:$HOME:~:")"
wd_print_msg "$WD_YELLOW" "No warp point to $show_pwd"
fi
fi
}
@@ -313,6 +450,11 @@ wd_clean() {
local count=0
local wd_tmp=""
if [ ! -w "$wd_config_file" ]; then
wd_exit_fail "\'$wd_config_file\' is not writeable."
return
fi
while read -r line
do
if [[ $line != "" ]]
@@ -329,7 +471,7 @@ wd_clean() {
count=$((count+1))
fi
fi
done < "$WD_CONFIG"
done < "$wd_config_file"
if [[ $count -eq 0 ]]
then
@@ -337,7 +479,7 @@ wd_clean() {
else
if [ ! -z "$force" ] || wd_yesorno "Removing ${count} warp points. Continue? (y/n)"
then
echo "$wd_tmp" >! "$WD_CONFIG"
echo "$wd_tmp" >! "$wd_config_file"
wd_print_msg "$WD_GREEN" "Cleanup complete. ${count} warp point(s) removed"
else
wd_print_msg "$WD_BLUE" "Cleanup aborted"
@@ -348,16 +490,15 @@ wd_clean() {
wd_export_static_named_directories() {
if [[ ! -z $WD_EXPORT ]]
then
command grep '^[0-9a-zA-Z_-]\+:' "$WD_CONFIG" | sed -e "s,~,$HOME," -e 's/:/=/' | while read -r warpdir ; do
command grep '^[0-9a-zA-Z_-]\+:' "$wd_config_file" | sed -e "s,~,$HOME," -e 's/:/=/' | while read -r warpdir ; do
hash -d "$warpdir"
done
fi
}
local WD_CONFIG=${WD_CONFIG:-$HOME/.warprc}
WD_CONFIG=${WD_CONFIG:-$HOME/.warprc}
local WD_QUIET=0
local WD_EXIT_CODE=0
local WD_DEBUG=0
# Parse 'meta' options first to avoid the need to have them before
# other commands. The `-D` flag consumes recognized options so that
@@ -367,7 +508,6 @@ zparseopts -D -E \
c:=wd_alt_config -config:=wd_alt_config \
q=wd_quiet_mode -quiet=wd_quiet_mode \
v=wd_print_version -version=wd_print_version \
d=wd_debug_mode -debug=wd_debug_mode \
f=wd_force_mode -force=wd_force_mode
if [[ ! -z $wd_print_version ]]
@@ -375,20 +515,30 @@ then
echo "wd version $WD_VERSION"
fi
# set the config file from variable or default
typeset wd_config_file=${WD_CONFIG:-$HOME/.warprc}
if [[ ! -z $wd_alt_config ]]
then
WD_CONFIG=$wd_alt_config[2]
# prefer the flag if provided
wd_config_file=$wd_alt_config[2]
fi
# check if config file exists
if [ ! -e "$WD_CONFIG" ]
if [ ! -e "$wd_config_file" ]
then
# if not, create config file
touch "$WD_CONFIG"
touch "$wd_config_file"
else
wd_export_static_named_directories
fi
# disable extendedglob for the complete wd execution time
setopt | grep -q extendedglob
wd_extglob_is_set=$?
if (( wd_extglob_is_set == 0 )); then
setopt noextendedglob
fi
# load warp points
typeset -A points
while read -r line
@@ -399,23 +549,15 @@ do
val=${(j,:,)arr[2,-1]}
points[$key]=$val
done < "$WD_CONFIG"
done < "$wd_config_file"
# get opts
args=$(getopt -o a:r:c:lhs -l add:,rm:,clean,list,ls:,path:,help,show -- $*)
args=$(getopt -o a:r:c:lhs -l add:,rm:,clean,list,ls:,open:,path:,help,show -- $*)
# check if no arguments were given, and that version is not set
if [[ ($? -ne 0 || $#* -eq 0) && -z $wd_print_version ]]
then
wd_print_usage
# check if config file is writeable
elif [ ! -w "$WD_CONFIG" ]
then
# do nothing
# can't run `exit`, as this would exit the executing shell
wd_exit_fail "\'$WD_CONFIG\' is not writeable."
else
# parse rest of options
local wd_o
@@ -427,6 +569,14 @@ else
wd_add "$2" "$wd_force_mode"
break
;;
"-b"|"browse")
wd_browse
break
;;
"-c"|"--addcd"|"addcd")
wd_addcd "$2" "$3" "$wd_force_mode"
break
;;
"-e"|"export")
wd_export_static_named_directories
break
@@ -444,6 +594,10 @@ else
wd_ls "$2"
break
;;
"-o"|"--open"|"open")
wd_open "$2"
break
;;
"-p"|"--path"|"path")
wd_path "$2"
break
@@ -475,8 +629,14 @@ fi
# if not, next time warp will pick up variables from this run
# remember, there's no sub shell
if (( wd_extglob_is_set == 0 )); then
setopt extendedglob
fi
unset wd_extglob_is_set
unset wd_warp
unset wd_add
unset wd_addcd
unset wd_remove
unset wd_show
unset wd_list_all
@@ -484,8 +644,10 @@ unset wd_print_msg
unset wd_yesorno
unset wd_print_usage
unset wd_alt_config
#unset wd_config_file do not unset this - breaks keybind
unset wd_quiet_mode
unset wd_print_version
unset wd_force_mode
unset wd_export_static_named_directories
unset wd_o
@@ -493,9 +655,4 @@ unset args
unset points
unset val &> /dev/null # fixes issue #1
if [[ -n $wd_debug_mode ]]
then
exit $WD_EXIT_CODE
else
unset wd_debug_mode
fi
return $WD_EXIT_CODE