Skip to content

Instantly share code, notes, and snippets.

@babarot
Last active April 11, 2021 04:30
Show Gist options
  • Save babarot/1a0218c9e71b9f2e1835 to your computer and use it in GitHub Desktop.
Save babarot/1a0218c9e71b9f2e1835 to your computer and use it in GitHub Desktop.
description
#
# @(#) bookmarker.sh ver.1.4.0 2013.08.12
#
# Copyright (c) 2013, b4b4r07
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other materials provided with the distribution.
# * Neither the name of Huy Nguyen nor the names of contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# USAGE:
# . bookmarker.sh
#
###################################################################################################################
[ "$BASH_VERSION" ] || return 1
declare -r version="1.4.0"
declare -r author="b4b4r07"
declare -r bookmarkdir=~/.bookmarkdir
declare -r bookmarklist=$bookmarkdir/bookmarklist
declare -r bookmarklog=$bookmarkdir/bookmarklog
declare -r bookmarktemp=$bookmarkdir/bookmarktemp
declare -ri exit_usage=0
declare OPTION_T=
function _bookmark_usage() {
local -i width=$( stty 'size' <'/dev/tty' | cut -d' ' -f2 )
local -a commands=( "edit" "show" "regist" "go" "print" "delete" )
if [ $# -eq 0 ]; then
echo -en "${commands[@]}\n\n"
_bookmark_usage "${commands[@]}"
return 0
fi
for list do
echo -en "Usage: "
case "$list" in
'edit')
echo -en "edit [OPTION]\n"
echo -en " Edit bookmark-list.\n\n"
echo -en "Options:\n"
echo -en " -r, --readonly display bookmark-log readonly.\n"
echo -en " -h, --help display this help and exit.\n\n"
shift
;;
'show')
echo -en "show [OPTION]\n"
echo -en " Display all registration names and paths.\n"
echo -en " All options cannot be used together.\n\n"
echo -en "Options:\n"
echo -en " -h, --help display this help and exit.\n"
echo -en " -c, --count count the use number of times of the registed name.\n"
echo -en " -r, --refresh check if all registed paths are available.\n"
echo -en " -s, --sort sort registed names with a turn showing frequent use and display it.\n"
echo -en " -m, --mru display the list which you used ten from a bookmark-list recently.\n"
echo -en " -p, --plane display the list without a color.\n\n"
shift
;;
'regist')
echo -en "reg [OPTION] [name]\n"
echo -en " If there is an argument, register by the argument name\n"
echo -en " and otherwise register it current directory name.\n\n"
echo -en "Options:\n"
echo -en " -t, --temp generate the name and path as disposable element.\n"
echo -en " -h, --help display this help and exit.\n\n"
shift
;;
'go')
echo -en "go [name]\n"
echo -en " If there is an argument, go to the name of path\n"
echo -en " and otherwise do movement like 'show'.\n\n"
echo -en "Options:\n"
echo -en " -h, --help display this help and exit.\n\n"
shift
;;
'print')
echo -en "p name\n"
echo -en " print the name of path.\n\n"
echo -en "Options:\n"
echo -en " -h, --help display this help and exit.\n\n"
echo -en "Examples:\n"
echo -en " cp myfile \`p reg_dir\`\n\n"
shift
;;
'delete')
echo -en "del name\n"
echo -en " delete the name and path.\n\n"
echo -en "Options:\n"
echo -en " -h, --help display this help and exit.\n\n"
shift
;;
'refresh')
echo -en "show -r\n"
echo -en "Please refer to page 'show'.\n"
shift
;;
'count')
echo -en "show -c\n"
echo -en "Please refer to page 'show'.\n"
shift
;;
'sort')
echo -en "show -s\n"
echo -en "Please refer to page 'show'.\n"
shift
;;
'mru')
echo -en "show -m\n"
echo -en "Please refer to page 'show'.\n"
shift
;;
esac
[ "$#" -ne 0 ] && for ((i=0; i<$width; i++)); do
echo -en "_"
done && echo -en "\n\n"
done
echo -en "\nReport bugs to <[email protected]>.\n"
return $exit_usage
}
function _bookmark_initialize() {
[ -d $bookmarkdir ] && return 1
local ans
mkdir -p $bookmarkdir
touch $bookmarklist $bookmarklog $bookmarktemp
echo -en "Do you display a help? [y/N]: "
read ans
if [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then
_bookmark_usage | ${PAGER:-less}
return $exit_usage
fi
cp $0 $bookmarkdir
return 0
}
function _bookmark_edit() {
[ ! -e $bookmarklist ] && { echo "$(basename $bookmarklist): No exist"; return 1; }
[ "$1" = "-h" ] || [ "$1" = "--help" ] && { _bookmark_usage ${FUNCNAME##*_}; return $exit_usage; }
[ "$1" = "-r" ] || [ "$1" = "--readonly" ] && { tail -10r $bookmarklog; return 0; }
if which vi vim >/dev/null; then
vim $bookmarklist
return 0
else
$EDITOR $bookmarklist || {
echo "cannot edit bookmark-list" 1>&2
return 1
}
return 0
fi
}
function _bookmark_show() {
[ ! -e $bookmarklist ] && { echo "$(basename $bookmarklist): No exist"; return 1; }
local OPT
for OPT in "$@"
do
case "$OPT" in
'-h'|'--help' )
_bookmark_usage ${FUNCNAME##*_}
return $exit_usage
;;
'-c'|'--count' )
_bookmark_count
shift 1
return 0
;;
'-r'|'--refresh' )
if _bookmark_refresh; then
return 0
else
return 1
fi
;;
'-s'|'--sort' )
_bookmark_sort
shift 1
return 0
;;
'-m'|'--mru' )
_bookmark_mru
shift 1
return 0
;;
'-p'|'--plane' )
cat $bookmarklist | sed "s $HOME ~ g"
shift 1
return 0
;;
'--'|'-' )
shift 1
param+=( "$@" )
break
;;
-*)
echo "${FUNCNAME##*_}: illegal option -- '$(echo $1 | sed 's/^-*//')'" 1>&2
return 1
;;
*)
if [[ ! -z "$1" ]] && [[ ! "$1" =~ ^-+ ]]; then
param+=( "$1" )
shift 1
fi
;;
esac
done
[ ! -f $bookmarklist ] && touch $bookmarklist
[ ! -f $bookmarklog ] && touch $bookmarklog
[ ! -f $bookmarktemp ] && touch $bookmarktemp
local -i i=
local -a name=( $( awk '{print $1}' $bookmarklist ) )
local -a path=( $( awk '{print $2}' $bookmarklist ) )
for ((i=0; i<${#name[*]}; i++)); do
if grep -w ${name[i]} $bookmarklog >/dev/null; then
printf "\033[31m%-15s\033[m%s\n" ${name[i]} ${path[i]}
elif grep -w ${name[i]} $bookmarktemp >/dev/null; then
printf "\033[01;36m%-15s\033[m%s\n" ${name[i]} ${path[i]}
else
printf "\033[33m%-15s\033[m%s\n" ${name[i]} ${path[i]}
fi
done | sed "s $HOME ~ g"
unset name path i OPT
}
function _bookmark_regist() {
[ ! -e $bookmarklist ] && touch $bookmarklist
local OPT
for OPT in "$@"
do
case "$OPT" in
'-h'|'--help' )
_bookmark_usage ${FUNCNAME##*_}
return $exit_usage
;;
'-t'|'--temp' )
shift 1
local -i OPTION_T=1
;;
'--'|'-' )
shift 1
param+=( "$@" )
break
;;
-*)
echo "${FUNCNAME##*_}: illegal option -- '$(echo $1 | sed 's/^-*//')'" 1>&2
return 1
;;
esac
done
local -i limit=$(( $( stty 'size' <'/dev/tty' | cut -d' ' -f1 ) - 2 ))
[ $( wc -l <$bookmarklist ) -ge $limit ] && {
echo "The maximum number that can enroll in a bookmark-list is $limit cases."
return 1
}
local -i i=
local name=
[ $# -eq 0 ] && name=${PWD##*/} || name="$1"
[ ${#name} -gt 14 ] && { echo "Please input 14 characters or less."; return 1; }
if awk '{print $1}' $bookmarklist | command grep -w "$name" >/dev/null; then
echo "$name: already exist"
return 1
else
[ "$OPTION_T" ] && printf "%-15s%s\n" $name $(pwd) >>$bookmarktemp
printf "%-15s%s\n" $name $(pwd) >>$bookmarklist
return 0
fi
unset limit i name OPT
}
function _bookmark_go() {
[ "$1" = "-h" ] || [ "$1" = "--help" ] && { _bookmark_usage ${FUNCNAME##*_}; return $exit_usage; }
local name=$( awk '{print $1}' $bookmarklist | command grep -w -E "^$1$" )
local path=$( awk '$1 ~ /'^$1'$/' $bookmarklist | awk '{print $2}' )
if [[ $# -eq 0 ]]; then
echo "${FUNCNAME##*_}: too few arguments"
echo "Try '${FUNCNAME##*_} --help' for more information."
return 1
elif [[ $# -eq 1 ]]; then
if [[ -z "$name" ]]; then
echo "$1: No such path in $(basename $bookmarklist)"
return 1
else
if cd "$path" 2>/dev/null; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >>$bookmarklog
if [ -f $bookmarktemp ]; then
if awk '{print $2}' $bookmarktemp | grep -x $path >/dev/null; then
_bookmark_delete $name
sed -i '' "/^$1/d" $bookmarktemp
fi
fi
return 0
else
echo "$path: an invalid pass"
_bookmark_delete "$name"
echo "$name: deleted"
return 1
fi
fi
else
_bookmark_usage ${FUNCNAME##*_}
return $exit_usage
fi
unset name path
}
function _bookmark_print() {
[ "$1" = "-h" ] || [ "$1" = "--help" ] && { _bookmark_usage ${FUNCNAME##*_}; return $exit_usage; }
local name=$( awk '{print $1}' $bookmarklist | command grep -w -E "^$1$" )
local path=$( awk '$1 ~ /'^$1'$/' $bookmarklist | awk '{print $2}' )
if [[ $# -eq 1 ]]; then
if [[ -z "$name" ]]; then
echo "$1: No such path in $(basename $bookmarklist)"
return 1
else
if (cd "$path" >/dev/null 2>&1); then
echo "$path"
return 0
else
echo "$path: an invalid pass"
_bookmark_delete "$name"
echo "$name: deleted"
return 1
fi
fi
else
echo "${FUNCNAME##*_}: too few arguments"
echo "Try '${FUNCNAME##*_} --help' for more information."
return 1
fi
unset name path
}
function _bookmark_delete() {
[ ! -e $bookmarklist ] && { echo "$(basename $bookmarklist): No exist"; return 1; }
[ "$1" = "-h" ] || [ "$1" = "--help" ] && { _bookmark_usage ${FUNCNAME##*_}; return $exit_usage; }
[ ! -s $bookmarklist ] && { echo "$(basename $bookmarklist) is empty."; return 1; }
[ $# -eq 0 ] && {
echo "${FUNCNAME##*_}: too few arguments"
echo "Try '${FUNCNAME##*_} --help' for more information."
return 1
}
local -i i=
for f do
local -a name=( $( awk '{print $1}' $bookmarklist | command grep -ivw -E "$f" ) )
local -a path=( $( command grep -ivw -E "^$f" $bookmarklist | awk '{print $2}' ) )
if awk '{print $1}' $bookmarklist | command grep -w -E "^$f" >/dev/null; then
for ((i=0; i<${#name[*]}; i++)); do
printf "%-15s%s\n" ${name[i]} ${path[i]}
done >$bookmarklist
sed -i '' "/$f$/d" $bookmarklog 2>/dev/null
if [ -f $bookmarktemp ]; then
if awk '{print $1}' $bookmarktemp | grep -w "$f" >/dev/null; then
sed -i '' "/^$f/d" $bookmarktemp
fi
fi
else
echo "$1: No such path in $(basename $bookmarklist)"
return 1
fi
unset i name path f
done
}
function _bookmark_refresh() {
local -i i=
local -i count=0
local -a name=( $( awk '{print $1}' $bookmarklist ) )
local -a path=( $( awk '{print $2}' $bookmarklist ) )
local -r line=$( wc -l <$bookmarklist )
for ((i=0; i<"$line"; i++)); do
if [ -d "${path[i]}" ]; then
let count++
else
_bookmark_delete "${name[i]}"
fi
done
if [ $count -eq $line ]; then
echo "All paths are available."
return 1
else
_bookmark_show
return 0
fi
unset i count name path line
}
function _bookmark_count() {
[ "$1" = "-h" ] || [ "$1" = "--help" ] && { _bookmark_usage ${FUNCNAME##*_}; return $exit_usage; }
local OLDIFS=$IFS
IFS=$'\n'
local -i i=
local -a ary=
local -a reg=( $( awk '{print $1}' $bookmarklist ) )
for ((i=0; i<${#reg[*]}; i++)); do
ary[i]=$( sort -k3 $bookmarklog -k1,2r | uniq -c -f2 | sort | grep -w "${reg[i]}" | awk '{print $1,$4}' )
[ -z "${ary[i]}" ] && ary[i]="0 ${reg[i]}"
done
local -a num=( $( echo "${ary[*]}" | awk '{print $1}' ) )
local -a name=( $( echo "${ary[*]}" | awk '{print $2}' ) )
local -a path=( $( awk '{print $2}' $bookmarklist ) )
for ((i=0; i<${#num[*]}; i++)); do
printf "%3d: \033[31m%-15s\033[m%s\n" ${num[i]} ${name[i]} ${path[i]}
done | sed "s $HOME ~ g"
IFS=$OLDIFS
unset OLDIFS i ary reg num name path
}
function _bookmark_sort() {
[ "$1" = "-h" ] || [ "$1" = "--help" ] && { _bookmark_usage ${FUNCNAME##*_}; return $exit_usage; }
local -i i=
local -a name=( $( _bookmark_count | sort -k1nr | awk '{print $2}' ) )
local -a path=( $( _bookmark_count | sort -k1nr | awk '{print $3}' ) )
for ((i=0; i<${#name[*]}; i++)); do
printf "\033[31m%-20s\033[m%s\n" ${name[i]} ${path[i]}
done | sed "s $HOME ~ g"
unset i name path
}
function _bookmark_mru() {
local -a reg=( $( awk '{print $1}' $bookmarklist ) )
local -a list=( $( tail -30 -r $bookmarklog ) )
local -a temp=(),mru,num,path
local OLDIFS=$IFS
IFS=$'\n'
local -i i=
local -a uniq_num=( $( sort -k3 $bookmarklog -k1,2r | uniq -c -f2 | sort ) )
for ((i=0; i<${#list[*]}; i++)); do
if ! echo "${temp[@]}" | grep -w ${list[i]} >/dev/null; then
temp[i]=${list[i]}
mru+=( $( echo "${reg[*]}" | grep -w ${list[i]} ) )
fi
done
local -a num=
local -a date=
local -a path=
local -a target=( $( echo "${uniq_num[*]}" | grep "${reg[*]}" ) )
for ((i=0; i<${#mru[*]}; i++)); do
num+=( $( echo "${target[*]}" | grep -w ${mru[i]} | awk '{print $1}' ) )
date+=( $( echo "${target[*]}" | grep -w ${mru[i]} | awk '{print $2,$3}' ) )
path+=( $( grep -E -w "^${mru[i]}" $bookmarklist ) )
done
local -a t=
local -i length=$(
for ((i=0; i<${#path[*]}; i++)); do
t[i]=$( echo ${path[i]} | sed "s $HOME ~ g" )
echo ${#t[i]}
done | sort -nr | head -1
)
for ((i=0; i<${#num[*]}; i++)); do
printf "%3d: \033[31m%-15s\033[m%-$(( ${length} -3 ))s (%s)\n" \
${num[i]} $( echo ${path[i]} | awk '{print $1}' ) $( echo ${path[i]} | awk '{print $2}' ) ${date[i]}
done | sed "s $HOME ~ g"
IFS=$OLDIFS
unset reg list temp OLDIFS i uniq_num mru target num date path length t
}
function _bookmark_candidacy() {
[ ! -f $bookmarklist ] && return 1
echo $( awk '{print $1}' $bookmarklist )
}
function _bookmark_complement() {
local curw
COMPREPLY=()
curw=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $( compgen -W '`_bookmark_candidacy`' -- $curw ) )
return 0
}
[ -d $bookmarkdir ] && unset _bookmark_initialize || _bookmark_initialize
alias bookmark='_bookmark_usage'
alias edit='_bookmark_edit'
alias show='_bookmark_show'
alias reg='_bookmark_regist'
alias go='_bookmark_go'
alias del='_bookmark_delete'
alias p='_bookmark_print'
complete -F _bookmark_complement go
complete -F _bookmark_complement del
complete -F _bookmark_complement p
# okashi
# okashi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment