added some more stuff and changed prompt
This commit is contained in:
parent
cb62f96109
commit
ae447242b5
11 changed files with 3181 additions and 1 deletions
334
bin/desk
Executable file
334
bin/desk
Executable file
|
@ -0,0 +1,334 @@
|
|||
#!/usr/bin/env bash
|
||||
# vim: set filetype=sh:
|
||||
|
||||
PREFIX="${DESK_DIR:-$HOME/.desk}"
|
||||
DESKS="${DESK_DESKS_DIR:-$PREFIX/desks}"
|
||||
DESKFILE_NAME=Deskfile
|
||||
|
||||
|
||||
## Commands
|
||||
|
||||
cmd_version() {
|
||||
echo "◲ desk 0.6.0"
|
||||
}
|
||||
|
||||
|
||||
cmd_usage() {
|
||||
cmd_version
|
||||
echo
|
||||
cat <<_EOF
|
||||
Usage:
|
||||
|
||||
$PROGRAM
|
||||
List the current desk and any associated aliases. If no desk
|
||||
is being used, display available desks.
|
||||
$PROGRAM init
|
||||
Initialize desk configuration.
|
||||
$PROGRAM (list|ls)
|
||||
List all desks along with a description.
|
||||
$PROGRAM (.|go) [<desk-name-or-path> [shell-args...]]
|
||||
Activate a desk. Extra arguments are passed onto shell. If called with
|
||||
no arguments, look for a Deskfile in the current directory. If not a
|
||||
recognized desk, try as a path to directory containing a Deskfile.
|
||||
$PROGRAM run <desk-name> <cmd>
|
||||
Run a command within a desk's environment then exit. Think '\$SHELL -c'.
|
||||
$PROGRAM edit [desk-name]
|
||||
Edit (or create) a deskfile with the name specified, otherwise
|
||||
edit the active deskfile.
|
||||
$PROGRAM help
|
||||
Show this text.
|
||||
$PROGRAM version
|
||||
Show version information.
|
||||
|
||||
Since desk spawns a shell, to deactivate and "pop" out a desk, you
|
||||
simply need to exit or otherwise end the current shell process.
|
||||
_EOF
|
||||
}
|
||||
|
||||
cmd_init() {
|
||||
if [ -d "$PREFIX" ]; then
|
||||
echo "Desk dir already exists at ${PREFIX}"
|
||||
exit 1
|
||||
fi
|
||||
read -p "Where do you want to store your deskfiles? (default: ${PREFIX}): " \
|
||||
NEW_PREFIX
|
||||
[ -z "${NEW_PREFIX}" ] && NEW_PREFIX="$PREFIX"
|
||||
|
||||
if [ ! -d "${NEW_PREFIX}" ]; then
|
||||
echo "${NEW_PREFIX} doesn't exist, attempting to create."
|
||||
mkdir -p "$NEW_PREFIX/desks"
|
||||
fi
|
||||
|
||||
local SHELLTYPE=$(get_running_shell)
|
||||
|
||||
case "${SHELLTYPE}" in
|
||||
bash) local SHELLRC="${HOME}/.bashrc" ;;
|
||||
fish) local SHELLRC="${HOME}/.config/fish/config.fish" ;;
|
||||
zsh) local SHELLRC="${HOME}/.zshrc" ;;
|
||||
esac
|
||||
|
||||
read -p "Where's your shell rc file? (default: ${SHELLRC}): " \
|
||||
USER_SHELLRC
|
||||
[ -z "${USER_SHELLRC}" ] && USER_SHELLRC="$SHELLRC"
|
||||
if [ ! -f "$USER_SHELLRC" ]; then
|
||||
echo "${USER_SHELLRC} doesn't exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf "\n# Hook for desk activation\n" >> "$USER_SHELLRC"
|
||||
|
||||
# Since the hook is appended to the rc file, its exit status becomes
|
||||
# the exit status of `source $USER_SHELLRC` which typically
|
||||
# indicates if something went wrong. If $DESK_ENV is void, `test`
|
||||
# sets exit status to 1. That, however, is part of desk's normal
|
||||
# operation, so we clear exit status after that.
|
||||
if [ "$SHELLTYPE" == "fish" ]; then
|
||||
echo "test -n \"\$DESK_ENV\"; and . \"\$DESK_ENV\"; or true" >> "$USER_SHELLRC"
|
||||
else
|
||||
echo "[ -n \"\$DESK_ENV\" ] && source \"\$DESK_ENV\" || true" >> "$USER_SHELLRC"
|
||||
fi
|
||||
|
||||
echo "Done. Start adding desks to ${NEW_PREFIX}/desks!"
|
||||
}
|
||||
|
||||
|
||||
cmd_go() {
|
||||
# TODESK ($1) may either be
|
||||
#
|
||||
# - the name of a desk in $DESKS/
|
||||
# - a path to a Deskfile
|
||||
# - a directory containing a Deskfile
|
||||
# - empty -> `./Deskfile`
|
||||
#
|
||||
local TODESK="$1"
|
||||
local DESKEXT=$(get_deskfile_extension)
|
||||
local DESKPATH="$(find "${DESKS}/" -name "${TODESK}${DESKEXT}" 2>/dev/null)"
|
||||
|
||||
local POSSIBLE_DESKFILE_DIR="${TODESK%$DESKFILE_NAME}"
|
||||
if [ -z "$POSSIBLE_DESKFILE_DIR" ]; then
|
||||
POSSIBLE_DESKFILE_DIR="."
|
||||
fi
|
||||
|
||||
# If nothing could be found in $DESKS/, check to see if this is a path to
|
||||
# a Deskfile.
|
||||
if [[ -z "$DESKPATH" && -d "$POSSIBLE_DESKFILE_DIR" ]]; then
|
||||
if [ ! -f "${POSSIBLE_DESKFILE_DIR}/${DESKFILE_NAME}" ]; then
|
||||
echo "No Deskfile found in '${POSSIBLE_DESKFILE_DIR}'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local REALPATH=$( cd $POSSIBLE_DESKFILE_DIR && pwd )
|
||||
DESKPATH="${REALPATH}/${DESKFILE_NAME}"
|
||||
TODESK=$(basename "$REALPATH")
|
||||
fi
|
||||
|
||||
# Shift desk name so we can forward on all arguments to the shell.
|
||||
shift;
|
||||
|
||||
if [ -z "$DESKPATH" ]; then
|
||||
echo "Desk $TODESK (${TODESK}${DESKEXT}) not found in $DESKS"
|
||||
exit 1
|
||||
else
|
||||
local SHELL_EXEC="$(get_running_shell)"
|
||||
DESK_NAME="${TODESK}" DESK_ENV="${DESKPATH}" exec "${SHELL_EXEC}" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
cmd_run() {
|
||||
local TODESK="$1"
|
||||
shift;
|
||||
cmd_go "$TODESK" -ic "$@"
|
||||
}
|
||||
|
||||
|
||||
# Usage: desk list [options]
|
||||
# Description: List all desks along with a description
|
||||
# --only-names: List only the names of the desks
|
||||
# --no-format: Use ' - ' to separate names from descriptions
|
||||
cmd_list() {
|
||||
if [ ! -d "${DESKS}/" ]; then
|
||||
echo "No desk dir! Run 'desk init'."
|
||||
exit 1
|
||||
fi
|
||||
local SHOW_DESCRIPTIONS DESKEXT AUTO_ALIGN name desc len longest out
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--only-names) SHOW_DESCRIPTIONS=false && AUTO_ALIGN=false ;;
|
||||
--no-format) AUTO_ALIGN=false ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
DESKEXT=$(get_deskfile_extension)
|
||||
out=""
|
||||
longest=0
|
||||
|
||||
while read -d '' -r f; do
|
||||
name=$(basename "${f/${DESKEXT}//}")
|
||||
if [[ "$SHOW_DESCRIPTIONS" = false ]]; then
|
||||
out+="$name"$'\n'
|
||||
else
|
||||
desc=$(echo_description "$f")
|
||||
out+="$name - $desc"$'\n'
|
||||
len=${#name}
|
||||
(( len > longest )) && longest=$len
|
||||
fi
|
||||
done < <(find "${DESKS}/" -name "*${DESKEXT}" -print0)
|
||||
if [[ "$AUTO_ALIGN" != false ]]; then
|
||||
print_aligned "$out" "$longest"
|
||||
else
|
||||
printf "%s" "$out"
|
||||
fi
|
||||
}
|
||||
|
||||
# Usage: desk [options]
|
||||
# Description: List the current desk and any associated aliases. If no desk is being used, display available desks
|
||||
# --no-format: Use ' - ' to separate alias/export/function names from their descriptions
|
||||
cmd_current() {
|
||||
if [ -z "$DESK_ENV" ]; then
|
||||
printf "No desk activated.\n\n%s" "$(cmd_list)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local DESKPATH=$DESK_ENV
|
||||
local CALLABLES=$(get_callables "$DESKPATH")
|
||||
local AUTO_ALIGN len longest out
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--no-format) AUTO_ALIGN=false ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
printf "%s - %s\n" "$DESK_NAME" "$(echo_description "$DESKPATH")"
|
||||
|
||||
if [[ -n "$CALLABLES" ]]; then
|
||||
|
||||
longest=0
|
||||
out=$'\n'
|
||||
for NAME in $CALLABLES; do
|
||||
# Last clause in the grep regexp accounts for fish functions.
|
||||
len=$((${#NAME} + 2))
|
||||
(( len > longest )) && longest=$len
|
||||
local DOCLINE=$(
|
||||
grep -B 1 -E \
|
||||
"^(alias ${NAME}=|export ${NAME}=|(function )?${NAME}( )?\()|function $NAME" "$DESKPATH" \
|
||||
| grep "#")
|
||||
|
||||
if [ -z "$DOCLINE" ]; then
|
||||
out+=" ${NAME}"$'\n'
|
||||
else
|
||||
out+=" ${NAME} - ${DOCLINE##\# }"$'\n'
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$AUTO_ALIGN" != false ]]; then
|
||||
print_aligned "$out" "$longest"
|
||||
else
|
||||
printf "%s" "$out"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_edit() {
|
||||
if [ $# -eq 0 ]; then
|
||||
if [ "$DESK_NAME" == "" ]; then
|
||||
echo "No desk activated."
|
||||
exit 3
|
||||
fi
|
||||
local DESKNAME_TO_EDIT="$DESK_NAME"
|
||||
elif [ $# -eq 1 ]; then
|
||||
local DESKNAME_TO_EDIT="$1"
|
||||
else
|
||||
echo "Usage: ${PROGRAM} edit [desk-name]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local DESKEXT=$(get_deskfile_extension)
|
||||
local EDIT_PATH="${DESKS}/${DESKNAME_TO_EDIT}${DESKEXT}"
|
||||
|
||||
${EDITOR:-vi} "$EDIT_PATH"
|
||||
}
|
||||
|
||||
## Utilities
|
||||
|
||||
FNAME_CHARS='[a-zA-Z0-9_-]'
|
||||
|
||||
# Echo the description of a desk. $1 is the deskfile.
|
||||
echo_description() {
|
||||
local descline=$(grep -E "#\s+Description" "$1")
|
||||
echo "${descline##*Description: }"
|
||||
}
|
||||
|
||||
# Echo a list of aliases, exports, and functions for a given desk
|
||||
get_callables() {
|
||||
local DESKPATH=$1
|
||||
grep -E "^(alias |export |(function )?${FNAME_CHARS}+ ?\()|function $NAME" "$DESKPATH" \
|
||||
| sed 's/alias \([^= ]*\)=.*/\1/' \
|
||||
| sed 's/export \([^= ]*\)=.*/\1/' \
|
||||
| sed -E "s/(function )?(${FNAME_CHARS}+) ?\(\).*/\2/" \
|
||||
| sed -E "s/function (${FNAME_CHARS}+).*/\1/"
|
||||
}
|
||||
|
||||
get_running_shell() {
|
||||
# Echo the name of the parent shell via procfs, if we have it available.
|
||||
# Otherwise, try to use ps with bash's parent pid.
|
||||
if [ -e /proc ]; then
|
||||
# Get cmdline procfile of the process running this script.
|
||||
local CMDLINE_FILE="/proc/$(grep PPid /proc/$$/status | cut -f2)/cmdline"
|
||||
|
||||
if [ -f "$CMDLINE_FILE" ]; then
|
||||
# Strip out any verion that may be attached to the shell executable.
|
||||
# Strip leading dash for login shells.
|
||||
local CMDLINE_SHELL=$(sed -r -e 's/\x0.*//' -e 's/^-//' "$CMDLINE_FILE")
|
||||
fi
|
||||
else
|
||||
# Strip leading dash for login shells.
|
||||
# If the parent process is a login shell, guess bash.
|
||||
local CMDLINE_SHELL=$(ps -o args -p $PPID | tail -1 | sed -e 's/login/bash/' -e 's/^-//')
|
||||
fi
|
||||
|
||||
if [ ! -z "$CMDLINE_SHELL" ]; then
|
||||
basename "$CMDLINE_SHELL"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Fall back to $SHELL otherwise.
|
||||
basename "$SHELL"
|
||||
exit
|
||||
}
|
||||
|
||||
# Echo the extension of recognized deskfiles (.fish for fish)
|
||||
get_deskfile_extension() {
|
||||
if [ "$(get_running_shell)" == "fish" ]; then
|
||||
echo '.fish'
|
||||
else
|
||||
echo '.sh'
|
||||
fi
|
||||
}
|
||||
|
||||
# Echo first argument as key/value pairs aligned into two columns; second argument is the longest key
|
||||
print_aligned() {
|
||||
local out=$1 longest=$2
|
||||
printf "%s" "$out" | awk -v padding="$longest" -F' - ' '{
|
||||
printf "%-*s %s\n", padding, $1, substr($0, index($0, " - ")+2, length($0))
|
||||
}'
|
||||
}
|
||||
|
||||
|
||||
PROGRAM="${0##*/}"
|
||||
|
||||
case "$1" in
|
||||
init) shift; cmd_init "$@" ;;
|
||||
help|--help) shift; cmd_usage "$@" ;;
|
||||
version|--version) shift; cmd_version "$@" ;;
|
||||
ls|list) shift; cmd_list "$@" ;;
|
||||
go|.) shift; cmd_go "$@" ;;
|
||||
run) shift; cmd_run "$@" ;;
|
||||
edit) shift; cmd_edit "$@" ;;
|
||||
*) cmd_current "$@" ;;
|
||||
esac
|
||||
exit 0
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue