diff --git a/plugins/bashmarks/README.md b/plugins/bashmarks/README.md index 340d0c2..e78c43e 100644 --- a/plugins/bashmarks/README.md +++ b/plugins/bashmarks/README.md @@ -1,26 +1,53 @@ # Bashmarks plugin -The Bashmarks plugin allows you to create and use bookmarks for directories on your filesystems. +The Bashmarks plugin allows you to create and use bookmarks for directories on +your filesystems. This plugin is derived from the project +https://github.com/huing/bashmarks but contains improvements. This plugin is +licensed under the 3-Clause BSD license. ## Quickstart Create a new bookmark using the *bm -a* command: -`$ bm -a mydir` +```bash +$ bm -a mydir +``` -The command above creates a bookmark for the current directory with the name *mydir*. +The command above creates a bookmark for the current directory with the name +*mydir*. You can navigate to the location of a bookmark using the *bm -g* command: -`$ bm -g mydir` +```bash +$ bm -g mydir +``` You can also supply just any bookmark name and the *-g* option will be assumed: -`$ bm mydir` +```bash +$ bm mydir +``` -Tab completion is available when you need to enter a bookmark name in a command, such as when using *bm -g* +Tab completion is available when you need to enter a bookmark name in a +command, such as when using *bm -g* -Easily list all bookmarks you have setup using the *bm -l* command. +Easily list all bookmarks you have set up using the *bm -l* command: + +```bash +$ bm -l +``` + +## Configuration + +- **`BASHMARKS_SDIR`**: This variable contains the path to the file that stores + the information of bookmarks of directory names. The default path is + `~/.sdirs`. The old interface `SDIRS` is now deprecated. + +## Configuration + +- `BASHMARKS_SDIR`: This variable contains the path to the file that stores the + information of bookmarks of directory names. The default path is `~/.sdirs`. + The old interface `SDIRS` is now deprecated. ## Commands @@ -38,4 +65,6 @@ Easily list all bookmarks you have setup using the *bm -l* command. ## Valid bookmark names -A bookmark name can contain lower and upper case characters (A-Z), numbers and underscore characters. No periods, semicolons, spaces or other characters are allowed in a bookmark name. +A bookmark name can contain lower and upper case characters (A-Z), numbers and +underscore characters. No periods, semicolons, spaces or other characters are +allowed in a bookmark name. diff --git a/plugins/bashmarks/bashmarks.plugin.sh b/plugins/bashmarks/bashmarks.plugin.sh index 38d9a05..1c676e0 100644 --- a/plugins/bashmarks/bashmarks.plugin.sh +++ b/plugins/bashmarks/bashmarks.plugin.sh @@ -1,27 +1,39 @@ #! bash oh-my-bash.module -# Copyright (c) 2015, Toan Nguyen - https://nntoan.github.io +# Copyright (c) 2010, Huy Nguyen, https://everyhue.me +# Copyright (c) 2015, Toan Nguyen, https://nntoan.github.io # All rights reserved. # -# Redistribution and use in source and binary forms, with or without modification, are permitted provided -# that the following conditions are met: +# This plugin is derived from the project https://github.com/huing/bashmarks. +# This version is based on the following commit in the upstream project: # -# * 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 Toan Nguyen Ngoc (aka NNToan) nor the names of contributors -# may be used to endorse or promote products derived from this software without +# https://github.com/huyng/bashmarks/commit/264952f2225691b5f99a498e4834e2c69bf4f5f5 +# +# This plugin is licensed under the BSD-3 License. +#------------------------------------------------------------------------------ +# 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 +# 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: # bm -a bookmarkname - saves the curr dir as bookmarkname @@ -33,60 +45,78 @@ # bm -d [TAB] - tab completion is available # bm -l - list all bookmarks -# setup file to store bookmarks -if [ ! -n "$SDIRS" ]; then - SDIRS=~/.sdirs +# Default configurations +if [[ ! ${BASHMARKS_SDIRS-} ]]; then + BASHMARKS_SDIRS=${SDIRS:-$HOME/.sdirs} +fi + +# Deprecated interfaces (2023-10-12) +_omb_deprecate_declare 20000 SDIRS BASHMARKS_SDIRS sync +_omb_deprecate_function 20000 _echo_usage _bashmarks_usage +_omb_deprecate_function 20000 _save_bookmark _bashmarks_save +_omb_deprecate_function 20000 _delete_bookmark _bashmarks_delete +_omb_deprecate_function 20000 _goto_bookmark _bashmarks_goto +_omb_deprecate_function 20000 _list_bookmark _bashmarks_list +_omb_deprecate_function 20000 _print_bookmark _bashmarks_print +_omb_deprecate_function 20000 _l _bashmarks_list_names +_omb_deprecate_function 20000 _bookmark_name_valid _bashmarks_is_valid_bookmark_name +_omb_deprecate_function 20000 _comp _bashmarks_comp_cmd_bm +_omb_deprecate_function 20000 _compzsh _bashmarks_compzsh_cmd_bm +_omb_deprecate_function 20000 _purge_line _bashmarks_purge_line + +# setup file to store bookmarks +if [[ ! -e $BASHMARKS_SDIRS ]]; then + touch "$BASHMARKS_SDIRS" fi -touch "$SDIRS" # main function function bm { - option="${1}" - case ${option} in + local option=$1 + case $option in # save current directory to bookmarks [ bm -a BOOKMARK_NAME ] -a) - _save_bookmark "$2" + _bashmarks_save "$2" ;; # delete bookmark [ bm -d BOOKMARK_NAME ] -d) - _delete_bookmark "$2" + _bashmarks_delete "$2" ;; # jump to bookmark [ bm -g BOOKMARK_NAME ] -g) - _goto_bookmark "$2" + _bashmarks_goto "$2" ;; # print bookmark [ bm -p BOOKMARK_NAME ] -p) - _print_bookmark "$2" + _bashmarks_print "$2" ;; # show bookmark list [ bm -l ] -l) - _list_bookmark + _bashmarks_list ;; # help [ bm -h ] -h) - _echo_usage + _bashmarks_usage ;; *) if [[ $1 == -* ]]; then # unrecognized option. echo error message and usage [ bm -X ] echo "Unknown option '$1'" - _echo_usage + _bashmarks_usage kill -SIGINT $$ exit 1 elif [[ $1 == "" ]]; then # no args supplied - echo usage [ bm ] - _echo_usage + _bashmarks_usage else # non-option supplied as first arg. assume goto [ bm BOOKMARK_NAME ] - _goto_bookmark "$1" + _bashmarks_goto "$1" fi ;; esac } # print usage information -function _echo_usage { +function _bashmarks_usage { echo 'USAGE:' echo "bm -h - Prints this usage info" echo 'bm -a - Saves the current directory as "bookmark_name"' @@ -97,87 +127,90 @@ function _echo_usage { } # save current directory to bookmarks -function _save_bookmark { - _bookmark_name_valid "$@" - if [ -z "$exit_message" ]; then - _purge_line "$SDIRS" "export DIR_$1=" +function _bashmarks_save { + if _bashmarks_is_valid_bookmark_name "$@"; then + _bashmarks_purge_line "$BASHMARKS_SDIRS" "export DIR_$1=" CURDIR=$(echo $PWD| sed "s#^$HOME#\$HOME#g") - echo "export DIR_$1=\"$CURDIR\"" >> $SDIRS + echo "export DIR_$1=\"$CURDIR\"" >> "$BASHMARKS_SDIRS" fi } # delete bookmark -function _delete_bookmark { - _bookmark_name_valid "$@" - if [ -z "$exit_message" ]; then - _purge_line "$SDIRS" "export DIR_$1=" +function _bashmarks_delete { + if _bashmarks_is_valid_bookmark_name "$@"; then + _bashmarks_purge_line "$BASHMARKS_SDIRS" "export DIR_$1=" unset "DIR_$1" fi } # jump to bookmark -function _goto_bookmark { - source $SDIRS - target="$(eval $(echo echo $(echo \$DIR_$1)))" - if [ -d "$target" ]; then - cd "$target" - elif [ ! -n "$target" ]; then - printf '%s\n' "${_omb_term_brown}WARNING: '${1}' bashmark does not exist${_omb_term_reset}" - else - printf '%s\n' "${_omb_term_brown}WARNING: '${target}' does not exist${_omb_term_reset}" - fi +function _bashmarks_goto { + source "$BASHMARKS_SDIRS" + local target_varname=DIR_$1 + local target=${!target_varname-} + if [[ -d $target ]]; then + cd "$target" + elif [[ ! $target ]]; then + printf '%s\n' "${_omb_term_brown}WARNING: '${1}' bashmark does not exist${_omb_term_reset}" + else + printf '%s\n' "${_omb_term_brown}WARNING: '${target}' does not exist${_omb_term_reset}" + fi } # list bookmarks with dirname -function _list_bookmark { - source $SDIRS - # if color output is not working for you, comment out the line below '\033[1;32m' == "red" - env | sort | awk '/DIR_.+/{split(substr($0,5),parts,"="); printf("\033[0;33m%-20s\033[0m %s\n", parts[1], parts[2]);}' - # uncomment this line if color output is not working with the line above - # env | grep "^DIR_" | cut -c5- | sort |grep "^.*=" +function _bashmarks_list { + source "$BASHMARKS_SDIRS" + # if color output is not working for you, comment out the line below '\033[1;32m' == "red" + env | sort | awk '/^DIR_.+/{split(substr($0,5),parts,"="); printf("\033[0;33m%-20s\033[0m %s\n", parts[1], parts[2]);}' + # uncomment this line if color output is not working with the line above + # env | grep "^DIR_" | cut -c5- | sort |grep "^.*=" } # print bookmark -function _print_bookmark { - source $SDIRS - echo "$(eval $(echo echo $(echo \$DIR_$1)))" +function _bashmarks_print { + source "$BASHMARKS_SDIRS" + echo "$(eval $(echo echo $(echo \$DIR_$1)))" } # list bookmarks without dirname -function _l { - source $SDIRS - env | grep "^DIR_" | cut -c5- | sort | grep "^.*=" | cut -f1 -d "=" +function _bashmarks_list_names { + source "$BASHMARKS_SDIRS" + env | grep "^DIR_" | cut -c5- | sort | grep "^.*=" | cut -f1 -d "=" } # validate bookmark name -function _bookmark_name_valid { - exit_message="" - if [ -z $1 ]; then - exit_message="bookmark name required" - echo $exit_message - elif [ "$1" != "$(echo $1 | sed 's/[^A-Za-z0-9_]//g')" ]; then - exit_message="bookmark name is not valid" - echo $exit_message - fi +# @var[out] exit_message +function _bashmarks_is_valid_bookmark_name { + local exit_message="" + if [[ ! $1 ]]; then + exit_message="bookmark name required" + echo "$exit_message" >&2 + return 1 + elif [[ $1 == *[!A-Za-z0-9_]* ]]; then + exit_message="bookmark name is not valid" + echo "$exit_message" >&2 + return 1 + fi } # completion command -function _comp { - local curw - COMPREPLY=() - curw=${COMP_WORDS[COMP_CWORD]} - COMPREPLY=($(compgen -W '`_l`' -- $curw)) - return 0 +function _bashmarks_comp_cmd_bm { + COMPREPLY=() + if ((COMP_CWORD >= 2)) && [[ ${COMP_WORDS[1]} == -[gpd] ]]; then + local cur=${COMP_WORDS[COMP_CWORD]} + COMPREPLY=($(compgen -W '$(_bashmarks_list_names)' -- "$cur")) + fi + return 0 } # ZSH completion command -function _compzsh { - reply=($(_l)) +function _bashmarks_compzsh_cmd_bm { + reply=($(_bashmarks_list_names)) } # safe delete line from sdirs -function _purge_line { - if [ -s "$1" ]; then +function _bashmarks_purge_line { + if [[ -s $1 ]]; then # safely create a temp file t=$(mktemp -t bashmarks.XXXXXX) || exit 1 trap "/bin/rm -f -- '$t'" EXIT @@ -192,22 +225,22 @@ function _purge_line { fi } -# bind completion command for g,p,d to _comp -if [ $ZSH_VERSION ]; then - compctl -K _compzsh bm -g - compctl -K _compzsh bm -p - compctl -K _compzsh bm -d - compctl -K _compzsh g - compctl -K _compzsh p - compctl -K _compzsh d +# bind completion command for g,p,d to _bashmarks_comp_cmd_bm +if [[ ${ZSH_VERSION-} ]]; then + compctl -K _bashmarks_compzsh_cmd_bm bm -g + compctl -K _bashmarks_compzsh_cmd_bm bm -p + compctl -K _bashmarks_compzsh_cmd_bm bm -d + compctl -K _bashmarks_compzsh_cmd_bm g + compctl -K _bashmarks_compzsh_cmd_bm p + compctl -K _bashmarks_compzsh_cmd_bm d else shopt -s progcomp - complete -F _comp bm -g - complete -F _comp bm -p - complete -F _comp bm -d - complete -F _comp g - complete -F _comp p - complete -F _comp d + complete -F _bashmarks_comp_cmd_bm bm + complete -F _bashmarks_comp_cmd_bm bm + complete -F _bashmarks_comp_cmd_bm bm + complete -F _bashmarks_comp_cmd_bm g + complete -F _bashmarks_comp_cmd_bm p + complete -F _bashmarks_comp_cmd_bm d fi alias s='bm -a' # Save a bookmark [bookmark_name]