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
......@@ -24,6 +76,7 @@
$ wd ...
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:
......@@ -33,8 +86,55 @@
$ wd ls
* List warp points to current directory
* List warp points to current directory, or optionally, path to given warp point:
$ 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() {
'add!:Overwrites existing warp point'
'rm:Removes the given warp point'
'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'
'..:Go back to last directory'
)
......@@ -43,6 +44,9 @@ function _wd() {
add)
_message 'Write the name of your warp point' && ret=0
;;
show)
_describe -t points "Warp points" warp_points && ret=0
;;
esac
;;
esac
......
......@@ -7,40 +7,108 @@
#
# @github.com/mfaerevaag/wd
## variables
readonly CONFIG=$HOME/.warprc
# version
readonly WD_VERSION=0.4
# colors
readonly BLUE="\033[96m"
readonly GREEN="\033[92m"
readonly YELLOW="\033[93m"
readonly RED="\033[91m"
readonly NOC="\033[m"
readonly WD_BLUE="\033[96m"
readonly WD_GREEN="\033[92m"
readonly WD_YELLOW="\033[93m"
readonly WD_RED="\033[91m"
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
if [ ! -e $CONFIG ]
then
# if not, create config file
touch $CONFIG
fi
return ${RETVAL}
}
# load warp points
typeset -A points
while read -r line
do
arr=(${(s,:,)line})
key=${arr[1]}
val=${arr[2]}
wd_print_msg()
{
if [[ -z $wd_quiet_mode ]]
then
local color=$1
local msg=$2
points[$key]=$val
done < $CONFIG
if [[ $color == "" || $msg == "" ]]
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()
{
......@@ -50,7 +118,7 @@ wd_warp()
then
if [ $#1 < 2 ]
then
wd_print_msg $YELLOW "Warping to current directory?"
wd_exit_warn "Warping to current directory?"
else
(( n = $#1 - 1 ))
cd -$n > /dev/null
......@@ -59,7 +127,7 @@ wd_warp()
then
cd ${points[$point]}
else
wd_print_msg $RED "Unknown warp point '${point}'"
wd_exit_fail "Unknown warp point '${point}'"
fi
}
......@@ -70,24 +138,28 @@ wd_add()
if [[ $point =~ "^[\.]+$" ]]
then
wd_print_msg $RED "Warp point cannot be just dots"
elif [[ $point =~ "(\s|\ )+" ]]
wd_exit_fail "Warp point cannot be just dots"
elif [[ $point =~ "[[:space:]]+" ]]
then
wd_print_msg $RED "Warp point should not contain whitespace"
wd_exit_fail "Warp point should not contain whitespace"
elif [[ $point == *:* ]]
then
wd_print_msg $RED "Warp point cannot contain colons"
wd_exit_fail "Warp point cannot contain colons"
elif [[ $point == "" ]]
then
wd_print_msg $RED "Warp point cannot be empty"
wd_exit_fail "Warp point cannot be empty"
elif [[ ${points[$2]} == "" ]] || $force
then
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
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
}
......@@ -97,20 +169,21 @@ wd_remove()
if [[ ${points[$point]} != "" ]]
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
wd_print_msg $GREEN "Warp point removed"
wd_print_msg $WD_GREEN "Warp point removed"
else
wd_print_msg $RED "Something bad happened! Sorry."
wd_exit_fail "Something bad happened! Sorry."
fi
else
wd_print_msg $RED "Warp point was not found"
wd_exit_fail "Warp point was not found"
fi
}
wd_list_all()
{
wd_print_msg $BLUE "All warp points:"
wd_print_msg $WD_BLUE "All warp points:"
while IFS= read -r line
do
......@@ -120,66 +193,146 @@ wd_list_all()
key=${arr[1]}
val=${arr[2]}
if [[ -z $wd_quiet_mode ]]
then
printf "%20s -> %s\n" $key $val
fi
done <<< $(sed "s:${HOME}:~:g" $CONFIG)
fi
done <<< $(sed "s:${HOME}:~:g" $WD_CONFIG)
}
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_list_all | grep -e "${cwd}$"
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:~:")"
fi
fi
}
wd_print_msg()
{
local color=$1
local msg=$2
wd_clean() {
local force=$1
local count=0
local wd_tmp=""
if [[ $color == "" || $msg == "" ]]
while read line
do
if [[ $line != "" ]]
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
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
}
wd_print_usage()
{
cat <<- EOF
Usage: wd [add|-a|--add] [rm|-r|--remove] <point>
local WD_CONFIG=$HOME/.warprc
local WD_QUIET=0
local WD_EXIT_CODE=0
local WD_DEBUG=0
Commands:
add Adds the current working directory to your warp points
add! Overwrites existing warp point
rm Removes the given warp point
show Outputs warp points to current directory
ls Outputs all stored warp points
help Show this extremely helpful text
EOF
}
# Parse 'meta' options first to avoid the need to have them before
# other commands. The `-D` flag consumes recognized options so that
# the actual command parsing won't be affected.
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
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
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
if [[ $? -ne 0 || $#* -eq 0 ]]
# 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 $CONFIG ]
# 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_print_msg $RED "\'$CONFIG\' is not writeable."
wd_exit_fail "\'$WD_CONFIG\' is not writeable."
else
# parse rest of options
for o
do
case "$o"
......@@ -205,7 +358,15 @@ else
break
;;
-s|--show|show)
wd_show
wd_show $2
break
;;
-c|--clean|clean)
wd_clean false
break
;;
-c!|--clean!|clean!)
wd_clean true
break
;;
*)
......@@ -229,8 +390,19 @@ unset wd_remove
unset wd_show
unset wd_list_all
unset wd_print_msg
unset wd_yesorno
unset wd_print_usage
unset wd_alt_config
unset wd_quiet_mode
unset wd_print_version
unset args
unset points
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