233 lines
6.9 KiB
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
|