Commit 8a51bfd7 authored by Robby Russell's avatar Robby Russell
Browse files

Merge pull request #3108 from mfaerevaag/master

[wd] New minor version (v0.4)
parents 35f1a237 9f801ff4
## wd wd
==
[![Build Status](https://travis-ci.org/mfaerevaag/wd.png?branch=master)](https://travis-ci.org/mfaerevaag/wd)
`wd` (*warp directory*) lets you jump to custom directories in zsh, without using `cd`. Why? Because `cd` seems ineffecient when the folder is frequently visited or has a long path.
### Setup
### oh-my-zsh
`wd` comes bundles with [oh-my-zshell](https://github.com/robbyrussell/oh-my-zsh)!
Just add the plugin in your `~/.zshrc` file:
plugins=(... wd)
#### Automatic
Run either in terminal:
* `curl -L https://github.com/mfaerevaag/wd/raw/master/install.sh | sh`
* `wget --no-check-certificate https://github.com/mfaerevaag/wd/raw/master/install.sh -O - | sh`
#### Manual
* Clone this repo to your liking
* Add `wd` function to `.zshrc` (or `.profile` etc.):
wd() {
. ~/paht/to/wd/wd.sh
}
* Install manpage. From `wd`'s base directory (requires root permissions):
# cp wd.1 /usr/share/man/man1/wd.1
# chmod 644 /usr/share/man/man1/wd.1
Note, when pulling and updating `wd`, you'll need to do this again in case of changes to the manpage.
#### Completion
If you're NOT using [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) and you want to utelize the zsh-completion feature, you will also need to add the path to your `wd` installation (`~/bin/wd` if you used the automatic installer) to your `fpath`. E.g. in your `~/.zshrc`:
fpath=(~/path/to/wd $fpath)
Also, you may have to force a rebuild of `zcompdump` by running:
$ rm -f ~/.zcompdump; compinit
**Maintainer:** [mfaerevaag](https://github.com/mfaerevaag)
`wd` (*warp directory*) lets you jump to custom directories in zsh, without using `cd`. Why? Because `cd` seems ineffecient when the folder is frequently visited or has a long path. [Source](https://github.com/mfaerevaag/wd)
### Usage ### Usage
...@@ -24,6 +76,7 @@ ...@@ -24,6 +76,7 @@
$ wd ... $ wd ...
This is a wrapper for the zsh `dirs` function. This is a wrapper for the zsh `dirs` function.
(You might need `setopt AUTO_PUSHD` in your `.zshrc` if you hare not using [oh-my-zshell](https://github.com/robbyrussell/oh-my-zsh)).
* Remove warp point test point: * Remove warp point test point:
...@@ -33,8 +86,55 @@ ...@@ -33,8 +86,55 @@
$ wd ls $ wd ls
* List warp points to current directory * List warp points to current directory, or optionally, path to given warp point:
$ wd show $ wd show
* Print usage with no opts or the `help` argument. * Remove warp points to non-existent directories.
$ wd clean
Use `clean!` to not be prompted with confirmation (force).
* Print usage with no opts or the `help` argument:
$ wd help
* Print the running version of `wd`:
$ wd --version
* Specifically set the config file (default `~/.warprc`), which is useful when testing:
$ wd --config ./file <action>
* Force `exit` with return code after running. This is not default, as it will *exit your terminal*, though required when testing/debugging.
$ wd --debug <action>
* Silence all output:
$ wd --quiet <action>
### Testing
`wd` comes with a small test suite, run with [shunit2](https://code.google.com/p/shunit2/). This can be used to confirm that things are working as it should on your setup, or to demonstrate an issue.
To run, simply `cd` into the `test` directory and run the `tests.sh`.
$ ./tests.sh
### License
The project is licensed under the [MIT-license](https://github.com/mfaerevaag/wd/blob/master/LICENSE).
### Finally
If you have issues, feedback or improvements, don't hesitate to report it or submit a pull-request. In the case of an issue, we would much appreciate if you would include a failing test in `test/tests.sh`. Explanation on how to run the tests, read the section "Testing" in this README.
Credit to [altschuler](https://github.com/altschuler) for awesome idea.
Hope you enjoy!
...@@ -21,7 +21,8 @@ function _wd() { ...@@ -21,7 +21,8 @@ function _wd() {
'add!:Overwrites existing warp point' 'add!:Overwrites existing warp point'
'rm:Removes the given warp point' 'rm:Removes the given warp point'
'ls:Outputs all stored warp points' 'ls:Outputs all stored warp points'
'show:Outputs all warp points that point to the current directory' 'show:Outputs all warp points that point to the current directory or shows a specific target directory for a 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' 'help:Show this extremely helpful text'
'..:Go back to last directory' '..:Go back to last directory'
) )
...@@ -43,6 +44,9 @@ function _wd() { ...@@ -43,6 +44,9 @@ function _wd() {
add) add)
_message 'Write the name of your warp point' && ret=0 _message 'Write the name of your warp point' && ret=0
;; ;;
show)
_describe -t points "Warp points" warp_points && ret=0
;;
esac esac
;; ;;
esac esac
......
...@@ -7,40 +7,108 @@ ...@@ -7,40 +7,108 @@
# #
# @github.com/mfaerevaag/wd # @github.com/mfaerevaag/wd
# version
## variables readonly WD_VERSION=0.4
readonly CONFIG=$HOME/.warprc
# colors # colors
readonly BLUE="\033[96m" readonly WD_BLUE="\033[96m"
readonly GREEN="\033[92m" readonly WD_GREEN="\033[92m"
readonly YELLOW="\033[93m" readonly WD_YELLOW="\033[93m"
readonly RED="\033[91m" readonly WD_RED="\033[91m"
readonly NOC="\033[m" readonly WD_NOC="\033[m"
## functions
## init # helpers
wd_yesorno()
{
# variables
local question="${1}"
local prompt="${question} "
local yes_RETVAL="0"
local no_RETVAL="3"
local RETVAL=""
local answer=""
# read-eval loop
while true ; do
printf $prompt
read -r answer
case ${answer:=${default}} in
Y|y|YES|yes|Yes )
RETVAL=${yes_RETVAL} && \
break
;;
N|n|NO|no|No )
RETVAL=${no_RETVAL} && \
break
;;
* )
echo "Please provide a valid answer (y or n)"
;;
esac
done
# check if config file exists return ${RETVAL}
if [ ! -e $CONFIG ] }
then
# if not, create config file
touch $CONFIG
fi
# load warp points wd_print_msg()
typeset -A points {
while read -r line if [[ -z $wd_quiet_mode ]]
do then
arr=(${(s,:,)line}) local color=$1
key=${arr[1]} local msg=$2
val=${arr[2]}
points[$key]=$val if [[ $color == "" || $msg == "" ]]
done < $CONFIG then
print " ${WD_RED}*${WD_NOC} Could not print message. Sorry!"
else
print " ${color}*${WD_NOC} ${msg}"
fi
fi
}
wd_print_usage()
{
cat <<- EOF
Usage: wd [command] <point>
Commands:
add <point> Adds the current working directory to your warp points
add! <point> Overwrites existing warp point
rm <point> Removes the given warp point
show Print warp points to current directory
show <point> Print path to given warp point
ls Print all stored warp points
clean! Remove points warping to nonexistent directories
-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
## functions help Show this extremely helpful text
EOF
}
wd_exit_fail()
{
local msg=$1
wd_print_msg $WD_RED $1
WD_EXIT_CODE=1
}
wd_exit_warn()
{
local msg=$1
wd_print_msg $WD_YELLOW $msg
WD_EXIT_CODE=1
}
# core
wd_warp() wd_warp()
{ {
...@@ -50,7 +118,7 @@ wd_warp() ...@@ -50,7 +118,7 @@ wd_warp()
then then
if [ $#1 < 2 ] if [ $#1 < 2 ]
then then
wd_print_msg $YELLOW "Warping to current directory?" wd_exit_warn "Warping to current directory?"
else else
(( n = $#1 - 1 )) (( n = $#1 - 1 ))
cd -$n > /dev/null cd -$n > /dev/null
...@@ -59,7 +127,7 @@ wd_warp() ...@@ -59,7 +127,7 @@ wd_warp()
then then
cd ${points[$point]} cd ${points[$point]}
else else
wd_print_msg $RED "Unknown warp point '${point}'" wd_exit_fail "Unknown warp point '${point}'"
fi fi
} }
...@@ -70,24 +138,28 @@ wd_add() ...@@ -70,24 +138,28 @@ wd_add()
if [[ $point =~ "^[\.]+$" ]] if [[ $point =~ "^[\.]+$" ]]
then then
wd_print_msg $RED "Warp point cannot be just dots" wd_exit_fail "Warp point cannot be just dots"
elif [[ $point =~ "(\s|\ )+" ]] elif [[ $point =~ "[[:space:]]+" ]]
then then
wd_print_msg $RED "Warp point should not contain whitespace" wd_exit_fail "Warp point should not contain whitespace"
elif [[ $point == *:* ]] elif [[ $point == *:* ]]
then then
wd_print_msg $RED "Warp point cannot contain colons" wd_exit_fail "Warp point cannot contain colons"
elif [[ $point == "" ]] elif [[ $point == "" ]]
then then
wd_print_msg $RED "Warp point cannot be empty" wd_exit_fail "Warp point cannot be empty"
elif [[ ${points[$2]} == "" ]] || $force elif [[ ${points[$2]} == "" ]] || $force
then then
wd_remove $point > /dev/null wd_remove $point > /dev/null
printf "%q:%q\n" "${point}" "${PWD}" >> $CONFIG printf "%q:%s\n" "${point}" "${PWD}" >> $WD_CONFIG
wd_print_msg $GREEN "Warp point added" wd_print_msg $WD_GREEN "Warp point added"
# override exit code in case wd_remove did not remove any points
# TODO: we should handle this kind of logic better
WD_EXIT_CODE=0
else else
wd_print_msg $YELLOW "Warp point '${point}' already exists. Use 'add!' to overwrite." wd_exit_warn "Warp point '${point}' already exists. Use 'add!' to overwrite."
fi fi
} }
...@@ -97,20 +169,21 @@ wd_remove() ...@@ -97,20 +169,21 @@ wd_remove()
if [[ ${points[$point]} != "" ]] if [[ ${points[$point]} != "" ]]
then then
if sed -i.bak "s,^${point}:.*$,,g" $CONFIG local config_tmp=$WD_CONFIG.tmp
if sed -n "/^${point}:.*$/!p" $WD_CONFIG > $config_tmp && mv $config_tmp $WD_CONFIG
then then
wd_print_msg $GREEN "Warp point removed" wd_print_msg $WD_GREEN "Warp point removed"
else else
wd_print_msg $RED "Something bad happened! Sorry." wd_exit_fail "Something bad happened! Sorry."
fi fi
else else
wd_print_msg $RED "Warp point was not found" wd_exit_fail "Warp point was not found"
fi fi
} }
wd_list_all() wd_list_all()
{ {
wd_print_msg $BLUE "All warp points:" wd_print_msg $WD_BLUE "All warp points:"
while IFS= read -r line while IFS= read -r line
do do
...@@ -120,66 +193,146 @@ wd_list_all() ...@@ -120,66 +193,146 @@ wd_list_all()
key=${arr[1]} key=${arr[1]}
val=${arr[2]} val=${arr[2]}
if [[ -z $wd_quiet_mode ]]
then
printf "%20s -> %s\n" $key $val printf "%20s -> %s\n" $key $val
fi fi
done <<< $(sed "s:${HOME}:~:g" $CONFIG) fi
done <<< $(sed "s:${HOME}:~:g" $WD_CONFIG)
} }
wd_show() wd_show()
{ {
local cwd=$(print $PWD | sed "s:^${HOME}:~:") local name_arg=$1
# if there's an argument we look up the value
if [[ ! -z $name_arg ]]
then
if [[ -z $points[$name_arg] ]]
then
wd_print_msg $WD_BLUE "No warp point named $name_arg"
else
wd_print_msg $WD_GREEN "Warp point: ${WD_GREEN}$name_arg${WD_NOC} -> $points[$name_arg]"
fi
else
# hax to create a local empty array
local wd_matches
wd_matches=()
# do a reverse lookup to check whether PWD is in $points
if [[ ${points[(r)$PWD]} == $PWD ]]
then
for name in ${(k)points}
do
if [[ $points[$name] == $PWD ]]
then
wd_matches[$(($#wd_matches+1))]=$name
fi
done
wd_print_msg $BLUE "Warp points to current directory:" wd_print_msg $WD_BLUE "$#wd_matches warp point(s) to current directory: ${WD_GREEN}$wd_matches${WD_NOC}"
wd_list_all | grep -e "${cwd}$" else
wd_print_msg $WD_YELLOW "No warp point to $(echo $PWD | sed "s:$HOME:~:")"
fi
fi
} }
wd_print_msg() wd_clean() {
{ local force=$1
local color=$1 local count=0
local msg=$2 local wd_tmp=""
if [[ $color == "" || $msg == "" ]] while read line
do
if [[ $line != "" ]]
then then
print " ${RED}*${NOC} Could not print message. Sorry!" arr=(${(s,:,)line})
key=${arr[1]}
val=${arr[2]}
if [ -d "$val" ]
then
wd_tmp=$wd_tmp"\n"`echo $line`
else else
print " ${color}*${NOC} ${msg}" wd_print_msg $WD_YELLOW "Nonexistent directory: ${key} -> ${val}"
count=$((count+1))
fi
fi
done < $WD_CONFIG
if [[ $count -eq 0 ]]
then
wd_print_msg $WD_BLUE "No warp points to clean, carry on!"
else
if $force || wd_yesorno "Removing ${count} warp points. Continue? (Y/n)"
then
echo $wd_tmp >! $WD_CONFIG
wd_print_msg $WD_GREEN "Cleanup complete. ${count} warp point(s) removed"
else
wd_print_msg $WD_BLUE "Cleanup aborted"
fi
fi fi
} }
wd_print_usage() local WD_CONFIG=$HOME/.warprc
{ local WD_QUIET=0
cat <<- EOF local WD_EXIT_CODE=0
Usage: wd [add|-a|--add] [rm|-r|--remove] <point> local WD_DEBUG=0
Commands: # Parse 'meta' options first to avoid the need to have them before
add Adds the current working directory to your warp points # other commands. The `-D` flag consumes recognized options so that
add! Overwrites existing warp point # the actual command parsing won't be affected.
rm Removes the given warp point
show Outputs warp points to current directory zparseopts -D -E \
ls Outputs all stored warp points c:=wd_alt_config -config:=wd_alt_config \
help Show this extremely helpful text q=wd_quiet_mode -quiet=wd_quiet_mode \
EOF v=wd_print_version -version=wd_print_version \
} d=wd_debug_mode -debug=wd_debug_mode
if [[ ! -z $wd_print_version ]]
then
echo "wd version $WD_VERSION"
fi
if [[ ! -z $wd_alt_config ]]
then
WD_CONFIG=$wd_alt_config[2]
fi
## run # check if config file exists
if [ ! -e $WD_CONFIG ]
then
# if not, create config file
touch $WD_CONFIG
fi
# load warp points
typeset -A points
while read -r line
do
arr=(${(s,:,)line})
key=${arr[1]}
val=${arr[2]}
points[$key]=$val
done < $WD_CONFIG
# get opts # get opts
args=$(getopt -o a:r:lhs -l add:,rm:,ls,help,show -- $*) args=$(getopt -o a:r:c:lhs -l add:,rm:,clean\!,ls,help,show -- $*)
# check if no arguments were given # check if no arguments were given, and that version is not set
if [[ $? -ne 0 || $#* -eq 0 ]] if [[ ($? -ne 0 || $#* -eq 0) && -z $wd_print_version ]]
then then
wd_print_usage wd_print_usage
# check if config file is writeable # check if config file is writeable
elif [ ! -w $CONFIG ] elif [ ! -w $WD_CONFIG ]
then then
# do nothing # do nothing
# can't run `exit`, as this would exit the executing shell # can't run `exit`, as this would exit the executing shell
wd_print_msg $RED "\'$CONFIG\' is not writeable." wd_exit_fail "\'$WD_CONFIG\' is not writeable."
else else
# parse rest of options
for o for o
do do
case "$o" case "$o"
...@@ -205,7 +358,15 @@ else ...@@ -205,7 +358,15 @@ else
break break
;; ;;
-s|--show|show) -s|--show|show)
wd_show wd_show $2
break
;;
-c|--clean|clean)
wd_clean false
break
;;
-c!|--clean!|clean!)
wd_clean true
break break
;; ;;
*) *)
...@@ -229,8 +390,19 @@ unset wd_remove ...@@ -229,8 +390,19 @@ unset wd_remove
unset wd_show unset wd_show
unset wd_list_all unset wd_list_all
unset wd_print_msg unset wd_print_msg
unset wd_yesorno
unset wd_print_usage unset wd_print_usage
unset wd_alt_config
unset wd_quiet_mode
unset wd_print_version
unset args unset args
unset points unset points
unset val &> /dev/null # fixes issue #1 unset val &> /dev/null # fixes issue #1
if [[ ! -z $wd_debug_mode ]]
then
exit $WD_EXIT_CODE
else
unset wd_debug_mode
fi
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment