oh-my-zsh/plugins/percol/percol.zsh
2016-03-31 21:17:37 -03:00

252 lines
6.4 KiB
Bash

#!zsh
# This script arranges some percol-related userful zle-widgets and
# commands
#
# To use this script, put a following line into your .zshrc
#
# source PATH_TO_THIS_FILE
#
# Then, you can bind percol's zle-widgets to some key, by calling
# bindkey.
#
# bindkey '^R' percol_select_history
#
# Here is the list of zle-widgets provided by this script.
#
# * percol_select_history
# * percol_cd_sibling
# * percol_cd_upper_dirs
# * percol_cd_bookmark
# * percol_cd_repository
# * percol_insert_bookmark
# * percol_insert_ls
#
# And this script also provides following commands.
#
# * ppgrep
# * ppkill
#
# Enjoy!
# ------------------------------------------------------------ #
# Initialize
# ------------------------------------------------------------ #
PERCOL_ENABLED=true
function exists() {
which $1 &> /dev/null
}
# Define tac wrapper
exists gtac && _PERCOL_TAC="gtac" || \
{ exists tac && _PERCOL_TAC="tac" || \
{ _PERCOL_TAC="tail -r" } }
function _percol_tac() {
eval $_PERCOL_TAC
}
# Arrange a tmp dir for percol
PERCOL_TMP_DIR=/tmp/percol.zsh.tmp
if ! [ -d ${PERCOL_TMP_DIR} ]; then
mkdir ${PERCOL_TMP_DIR}
fi
# ------------------------------------------------------------ #
# FIFO for percol_popup
# ------------------------------------------------------------ #
# Arrange fifos
local PERCOL_IN=${PERCOL_TMP_DIR}/percol-channel-in-$$
local PERCOL_OUT=${PERCOL_TMP_DIR}/percol-channel-out-$$
function _percol_create_fifo() {
[ -p $PERCOL_IN ] || { command rm -f $PERCOL_IN; mkfifo -m 600 $PERCOL_IN }
[ -p $PERCOL_OUT ] || { command rm -f $PERCOL_OUT; mkfifo -m 600 $PERCOL_OUT }
}
function _percol_clean_fifos() {
command rm -f $PERCOL_IN
command rm -f $PERCOL_OUT
}
trap _percol_clean_fifos EXIT SIGINT SIGTERM
# ------------------------------------------------------------ #
# Arrange percol_popup on top of tmux
# ------------------------------------------------------------ #
function _percol_popup_tmux() {
_percol_create_fifo
tmux split-window "percol $* < ${PERCOL_IN} > ${PERCOL_OUT}"
}
function _percol_popup() {
INPUT=$1
PERCOL_OPTION=$2
if [[ -n $TMUX && -n $PERCOL_USE_TMUX ]]; then
eval "_percol_popup_tmux ${PERCOL_OPTION}; ${INPUT} > ${PERCOL_IN} &; cat ${PERCOL_OUT}"
else
eval "${INPUT} | percol ${(Q)PERCOL_OPTION}"
fi
}
# ------------------------------------------------------------ #
# Common functions
# ------------------------------------------------------------ #
# TODO: I'm not sure whether this process is proper or not
function _percol_clean_prompt() {
if [[ -n $TMUX ]]; then
zle reset-prompt
else
zle -R -c
fi
}
function _percol_list_upper_directories() {
local dir_cursor
dir_cursor=$(dirname ${PWD})
local dir_prefix="../../"
while [[ ${dir_cursor} != "/" ]]; do
echo ${dir_prefix}$(basename ${dir_cursor})
dir_cursor=$(dirname ${dir_cursor})
dir_prefix="../"${dir_prefix}
done
echo "/"
}
function _percol_list_siblings() {
local mydirname=$(basename $PWD)
local parentdir=$(dirname $PWD)
find $parentdir -maxdepth 1 -type d ! -iname ".*" -printf "%f\n" | sed -n '/${mydirname}/!p'
}
function _percol_get_destination_from_history() {
_percol_popup 'sort ${CD_HISTORY_FILE} | uniq -c | sort -r | \
sed -e "s/^[ ]*[0-9]*[ ]*//" | \
sed -e s"/^${HOME//\//\\/}/~/"'
}
function _percol_go_to_repository_top() {
cd ./$(git rev-parse --show-cdup)
if [ $# = 1 ]; then
cd $1
fi
}
function _percol_get_repository_dir() {
_percol_go_to_repository_top > /dev/null;
destination=$(_percol_popup 'find . -path "*/.git" -prune -o -type d')
if [[ $destination != "" ]]; then
r > /dev/null
cd $destination > /dev/null
echo $PWD
else
echo ""
fi
}
# ------------------------------------------------------------ #
# Define percol widgets
# ------------------------------------------------------------ #
function percol_select_history() {
output=$(_percol_popup 'history -n 1 | _percol_tac' '--query \"${LBUFFER}\"')
if [[ $output != "" ]]; then
BUFFER=$output
CURSOR=$#BUFFER
fi
_percol_clean_prompt
}
zle -N percol_select_history
function percol_cd_sibling() {
destination=$(_percol_popup "_percol_list_siblings")
if [[ $destination != "" ]]; then
cd $destination
fi
_percol_clean_prompt
}
zle -N percol_cd_sibling
function percol_cd_upper_dirs() {
destination=$(_percol_popup "_percol_list_upper_directories")
if [[ $destination != "" ]]; then
cd $destination
fi
_percol_clean_prompt
}
zle -N percol_cd_upper_dirs
function percol_insert_bookmark() {
local destination=$(_percol_get_destination_from_history)
if [ $? -eq 0 ]; then
local new_left="${LBUFFER} ${destination} "
BUFFER=${new_left}${RBUFFER}
CURSOR=${#new_left}
fi
_percol_clean_prompt
}
zle -N percol_insert_bookmark
function percol_cd_bookmark() {
local destination=$(_percol_get_destination_from_history)
[ -n $destination ] && cd ${destination/#\~/${HOME}}
_percol_clean_prompt
}
zle -N percol_cd_bookmark
function percol_insert_ls() {
local basedir
local left
basedir=$(echo ${LBUFFER} | perl -e '<STDIN> =~ /((?:[^ ]|\\\\ )+)$/; print "$1";')
left=$(echo ${LBUFFER} | perl -e '<STDIN> =~ /(.*)((?:[^ ]|\\\\ )+)$/; print "$1";')
local destination
if [ -n $basedir ]; then
destination=$(\ls $basedir | percol)
else
destination=$(\ls | percol)
fi
if [ $? -eq 0 ]; then
local new_left="${left}${destination} "
BUFFER=${new_left}${RBUFFER}
CURSOR=${#new_left}
fi
_percol_clean_prompt
}
zle -N percol_insert_ls
function percol_cd_repository() {
local destination
destination=$(_percol_get_repository_dir)
[[ $destination != "" ]] && cd ${destination}
_percol_clean_prompt
}
zle -N percol_cd_repository
# ------------------------------------------------------------
# Define useful commands
# ------------------------------------------------------------
function ppgrep() {
if [[ $1 == "" ]]; then
PERCOL=percol
else
PERCOL="percol --query $1"
fi
ps aux | eval $PERCOL | awk '{ print $2 }'
}
function ppkill() {
if [[ $1 =~ "^-" ]]; then
QUERY="" # options only
else
QUERY=$1 # with a query
[[ $# > 0 ]] && shift
fi
ppgrep $QUERY | xargs kill $*
}