summaryrefslogtreecommitdiff
path: root/plugins/wd
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/wd')
-rw-r--r--plugins/wd/README.md49
-rw-r--r--plugins/wd/_wd.sh10
-rw-r--r--plugins/wd/wd.plugin.zsh9
-rwxr-xr-x[-rw-r--r--]plugins/wd/wd.sh257
4 files changed, 258 insertions, 67 deletions
diff --git a/plugins/wd/README.md b/plugins/wd/README.md
index 1d1980632..1240afe57 100644
--- a/plugins/wd/README.md
+++ b/plugins/wd/README.md
@@ -57,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
@@ -97,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
@@ -119,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:
@@ -132,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:
@@ -216,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
diff --git a/plugins/wd/_wd.sh b/plugins/wd/_wd.sh
index 8d5cf15a2..7c416086d 100644
--- a/plugins/wd/_wd.sh
+++ b/plugins/wd/_wd.sh
@@ -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
diff --git a/plugins/wd/wd.plugin.zsh b/plugins/wd/wd.plugin.zsh
index ca2ca7c65..2397e6f31 100644
--- a/plugins/wd/wd.plugin.zsh
+++ b/plugins/wd/wd.plugin.zsh
@@ -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
diff --git a/plugins/wd/wd.sh b/plugins/wd/wd.sh
index 840e92d61..56c029252 100644..100755
--- a/plugins/wd/wd.sh
+++ b/plugins/wd/wd.sh
@@ -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}'"
@@ -170,6 +174,11 @@ wd_add()
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"
@@ -185,11 +194,11 @@ wd_add()
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
@@ -204,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
@@ -213,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
@@ -230,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
@@ -271,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"
@@ -280,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
@@ -294,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
@@ -307,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
}
@@ -317,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 != "" ]]
@@ -333,7 +471,7 @@ wd_clean() {
count=$((count+1))
fi
fi
- done < "$WD_CONFIG"
+ done < "$wd_config_file"
if [[ $count -eq 0 ]]
then
@@ -341,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"
@@ -352,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
@@ -371,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 ]]
@@ -379,16 +515,19 @@ 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
@@ -396,7 +535,9 @@ fi
# disable extendedglob for the complete wd execution time
setopt | grep -q extendedglob
wd_extglob_is_set=$?
-(( ! $wd_extglob_is_set )) && setopt noextendedglob
+if (( wd_extglob_is_set == 0 )); then
+ setopt noextendedglob
+fi
# load warp points
typeset -A points
@@ -408,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
@@ -436,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
@@ -453,6 +594,10 @@ else
wd_ls "$2"
break
;;
+ "-o"|"--open"|"open")
+ wd_open "$2"
+ break
+ ;;
"-p"|"--path"|"path")
wd_path "$2"
break
@@ -484,11 +629,14 @@ fi
# if not, next time warp will pick up variables from this run
# remember, there's no sub shell
-(( ! $wd_extglob_is_set )) && setopt extendedglob
+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
@@ -496,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
@@ -505,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