ambevar-dotfiles/.shell.d/funs_bash

233 lines
6.9 KiB
Bash

## -*- mode:sh -*- #
################################################################################
## Bash specific functions
## WARNING: this file needs a serious update and rewrite!
################################################################################
##==============================================================================
## Browse History
##==============================================================================
## Parameters usage -- should be set before sourcing the function.
if [ -d "$SHELLDIR" ]; then
BHISTORY="${SHELLDIR}/bhistory"
else
BHISTORY="$HOME/.bhistory"
fi
BHISTFILESIZE=20
BHISTREVERT=true
BHISTLOADLAST=true
## Where to store the history file.
if [ "$BHISTORY" == "" ]; then
if [ -d "$SHELLDIR" ]; then
BHISTORY="${SHELLDIR}/bhistory"
else
BHISTORY="$HOME/.bhistory"
fi
fi
## History prompted to the user.
## BHISTFILESIZE +1 entry are stored, the additional one
## is for the current directory to be remembered for new session.
[ "$BHISTFILESIZE" == "" ] && BHISTFILESIZE=20
## If true, first listed is last browsed.
[ "$BHISTREVERT" == "" ] && BHISTREVERT=true
## Go back to previous folder when starting a new session.
[ "$BHISTLOADLAST" == "" ] && BHISTLOADLAST=true
## Prevent infinite recursiveness when sourcing multiple times.
unalias cd>/dev/null 2>&1
## SEED is used to generate uniq filenames.
SEED=$(date "+%y-%m-%d-%H%M%S")
## Makes sure destination folder exists.
mkdir -p $(dirname "$BHISTORY")
## Use 'head' or 'tail' depending on BHISTREVERT
if $BHISTREVERT; then
BFUNC=head
BFUNCREV=tail
touch "${BHISTORY}-true"
if [ -e "$BHISTORY" -a -e "${BHISTORY}-false" ]; then
rm -rf "${BHISTORY}-false"
touch "${BHISTORY}-${SEED}_REV"
tac "$BHISTORY" > "${BHISTORY}_${SEED}_REV"
cat "${BHISTORY}_${SEED}_REV" > "$BHISTORY"
rm -rf "${BHISTORY}_${SEED}_REV"
fi
else
BFUNC=tail
BFUNCREV=head
touch "${BHISTORY}-false"
if [ -e "$BHISTORY" -a -e "${BHISTORY}-true" ]; then
rm -rf "${BHISTORY}-true"
touch "${BHISTORY}-${SEED}_REV"
tac "$BHISTORY" > "${BHISTORY}_${SEED}_REV"
cat "${BHISTORY}_${SEED}_REV" > "$BHISTORY"
rm -rf "${BHISTORY}_${SEED}_REV"
fi
fi
## Go back to previous folder when starting a new session.
## Need to put this part before the new 'cd' is set to prevent $HOME from being added as last entry in the history.
if [ $BHISTLOADLAST -a -e $BHISTORY ]; then
LASTPATH="$($BFUNC -n1 $BHISTORY)"
if [[ -e "$LASTPATH" ]]; then
cd "$LASTPATH"
fi
unset LASTPATH
fi
function bcd(){
## First character is an hyphen.
if [ "${1:0:1}" == "-" ]; then
if [ ${#1} -eq 1 ]; then # cd -
cd -
else
DEST=${1:1} # After the hyphen
# Check if the content after the hyphen is a number.
if [[ $DEST == ${DEST//[^0-9]/} ]]; then
let DEST=$DEST # Set DEST as an integer only here to avoid errors.
if $BHISTREVERT; then
let DEST=${DEST}+1
fi
NEWPATH=$(head -n$DEST "$BHISTORY"|tail -n1)
echo ${NEWPATH}
cd "${NEWPATH}"
else
cd "$1"
fi
fi
else
if [ -z "$1" ]; then
cd
else
cd "$1"
fi
fi
## Let's update the history.
touch $BHISTORY
## A buffer is used to avoid flow errors.
if $BHISTREVERT; then
echo ${PWD} >> "${BHISTORY}_$SEED"
cat "$BHISTORY" >> "${BHISTORY}_$SEED"
else
cat "$BHISTORY" >> "${BHISTORY}_$SEED"
echo "${PWD}" >> "${BHISTORY}_$SEED"
fi
## The 'awk' command makes sure there is duplicates.
## If the history size is beyond the limit set by $BHISTFILESIZE+1, it is cut.
## The '+1' is for storing the current folder which is not displayed to the used.
let BHISTSIZEREAL=${BHISTFILESIZE}+1
awk ' !x[$0]++' "${BHISTORY}_$SEED" | $BFUNC -n $BHISTSIZEREAL > "$BHISTORY"
rm "${BHISTORY}_$SEED"
}
function bhistory(){
if [ ! -e "$BHISTORY" ]; then
echo "Browse history empty"
else
let BHISTDISPLAY=$(cat "$BHISTORY"| wc -l)-1
$BFUNCREV -n$BHISTDISPLAY "$BHISTORY"| cat -n
fi
}
## Clean -- buggy?
#unset BFUNC BFUNCREV SEED BHISTSIZEREAL
## Replace 'cd' command
alias cd='bcd'
shopt -s extglob ## To allow bash to understand generic expression
shopt -s progcomp ## To enable the programmable completion
set +o nounset ## Otherwise some completions will fail
complete -A directory cd
##==============================================================================
## Alias auto completion
##==============================================================================
## wrap_alias takes three arguments:
## $1: The name of the alias
## $2: The command used in the alias
## $3: The arguments in the alias all in one string
## Generate a wrapper completion function (completer) for an alias
## based on the command and the given arguments, if there is a
## completer for the command, and set the wrapper as the completer for
## the alias.
#function wrap_alias() {
# [[ "$#" == 3 ]] || return 1
#
# local alias_name="$1"
# local aliased_command="$2"
# local alias_arguments="$3"
# local num_alias_arguments=$(echo "$alias_arguments" | wc -w)
#
# ## The completion currently being used for the aliased command.
# local completion=$(complete -p $aliased_command 2> /dev/null)
#
# ## Only a completer based on a function can be wrapped so look for -F
# ## in the current completion. This check will also catch commands
# ## with no completer for which $completion will be empty.
# echo $completion | grep -q -- -F || return 0
#
# local namespace=alias_completion::
#
# ## Extract the name of the completion function from a string that
# ## looks like: something -F function_name something
# ## First strip the beginning of the string up to the function name by
# ## removing "* -F " from the front.
# local completion_function=${completion##* -F }
# ## Then strip " *" from the end, leaving only the function name.
# completion_function=${completion_function%% *}
#
# ## Try to prevent an infinite loop by not wrapping a function
# ## generated by this function. This can happen when the user runs
# ## this twice for an alias like ls='ls --color=auto' or alias l='ls'
# ## and alias ls='l foo'
# [[ "${completion_function#$namespace}" != $completion_function ]] && return 0
#
# local wrapper_name="${namespace}${alias_name}"
#
# eval "
#function ${wrapper_name}() {
# let COMP_CWORD+=$num_alias_arguments
# args=( \"${alias_arguments}\" )
# COMP_WORDS=( $aliased_command \${args[@]} \${COMP_WORDS[@]:1} )
# $completion_function
# }
#"
#
# ## To create the new completion we use the old one with two
# ## replacements:
# ## 1) Replace the function with the wrapper.
# local new_completion=${completion/-F * /-F $wrapper_name }
# ## 2) Replace the command being completed with the alias.
# new_completion="${new_completion% *} $alias_name"
#
# eval "$new_completion"
#}
## For each defined alias, extract the necessary elements and use them
## to call wrap_alias.
#eval "$(alias -p | sed -e 's/alias \([^=][^=]*\)='\''\([^ ][^ ]*\) *\(.*\)'\''/wrap_alias \1 \2 '\''\3'\'' /')"
#unset wrap_alias