From 506762608d4e619caf0dbd91a78207fb5964c545 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Sun, 25 May 2014 17:19:13 -0400 Subject: [PATCH] Add suggest and show helpful commands in help menu --- Makefile | 2 +- bpkg-suggest | 1 + bpkg.sh | 52 +++++++++++++++++++- lib/suggest/LICENSE | 21 ++++++++ lib/suggest/Makefile | 14 ++++++ lib/suggest/README.md | 55 +++++++++++++++++++++ lib/suggest/package.json | 7 +++ lib/suggest/suggest.sh | 100 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 250 insertions(+), 2 deletions(-) create mode 120000 bpkg-suggest create mode 100644 lib/suggest/LICENSE create mode 100644 lib/suggest/Makefile create mode 100644 lib/suggest/README.md create mode 100644 lib/suggest/package.json create mode 100755 lib/suggest/suggest.sh diff --git a/Makefile b/Makefile index 0ba37a3..c81a16e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ BIN ?= bpkg PREFIX ?= /usr/local -CMDS = json install package term +CMDS = json install package term suggest install: uninstall install $(BIN) $(PREFIX)/bin diff --git a/bpkg-suggest b/bpkg-suggest new file mode 120000 index 0000000..34465d9 --- /dev/null +++ b/bpkg-suggest @@ -0,0 +1 @@ +lib/suggest/suggest.sh \ No newline at end of file diff --git a/bpkg.sh b/bpkg.sh index e93c71c..7c33625 100755 --- a/bpkg.sh +++ b/bpkg.sh @@ -14,9 +14,25 @@ usage () { echo "" } +## commands +commands () { + { + declare -a local cmds=( $( + bpkg-suggest 'bpkg-' | + tail -n+2 | + xargs basename | + sort -u | + sed 's/bpkg-//g' | + tr '\n' ' ' + ) ) + + echo "${cmds[@]}" + } +} + ## feature tests features () { - declare -a local features=(bpkg-json) + declare -a local features=(bpkg-json bpkg-suggest) for ((i = 0; i < ${#features[@]}; ++i)); do local f="${features[$i]}" if ! type "${f}" > /dev/null 2>&1; then @@ -44,14 +60,48 @@ bpkg () { -h|--help) usage + echo + echo "Here are some commands available in your path:" + echo + local cmds=($(commands)) + for cmd in ${cmds[@]}; do + echo " ${cmd}" + done return 0 ;; *) + if [ -z "${arg}" ]; then + usage + return 1 + fi cmd="bpkg-${arg}" if type -f "${cmd}" > /dev/null 2>&1; then "${cmd}" "${@}" return $? + else + echo >&2 "error: \`${arg}' is not a bpkg command." + { + declare -a local res=($( + bpkg-suggest "${cmd}" | + tail -n+2 | + xargs basename | + sort -u | + tr '\n' ' ' + )) + + if [ ! -z "${res}" ]; then + echo + echo >&2 "Did you mean one of these?" + for r in ${res}; do + echo " ${r}" + done + return 1 + else + usage + return 1 + fi + } fi ;; diff --git a/lib/suggest/LICENSE b/lib/suggest/LICENSE new file mode 100644 index 0000000..3bab1f7 --- /dev/null +++ b/lib/suggest/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Joseph Werle + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/lib/suggest/Makefile b/lib/suggest/Makefile new file mode 100644 index 0000000..ac6cfe1 --- /dev/null +++ b/lib/suggest/Makefile @@ -0,0 +1,14 @@ + +BIN ?= suggest +PREFIX ?= /usr/local + +install: + cp suggest.sh $(PREFIX)/bin/$(BIN) + +uninstall: + rm -f $(PREFIX)/bin/$(BIN) + +example.sh: + ./example.sh + +.PHONY: example.sh diff --git a/lib/suggest/README.md b/lib/suggest/README.md new file mode 100644 index 0000000..e231e83 --- /dev/null +++ b/lib/suggest/README.md @@ -0,0 +1,55 @@ +suggest.sh +========== + +Suggests commands based on a query found in $PATH. Kinda like `which` +but with queries + +## install + +[bpkg](https://github.com/bpkg/bpkg) + +```sh +$ bpkg install -g jwerle/suggest.sh +``` + +source: + +```sh +$ git clone https://github.com/jwerle/suggest.sh.git +$ make install -C suggest/ +``` + +## usage + +``` +usage: suggest [-hV] +``` + +## example + +```sh +$ suggest git +suggest: found 42 result(s) + + /usr/local/bin/git-alias + /usr/local/bin/git-archive-file + /usr/local/bin/git-back + /usr/local/bin/git-bug + /usr/local/bin/git-changelog + /usr/local/bin/git-commits-since + /usr/local/bin/git-contrib + /usr/local/bin/git-count + /usr/local/bin/git-create-branch + /usr/local/bin/git-delete-branch + /usr/local/bin/git-delete-merged-branches + /usr/local/bin/git-delete-submodule + /usr/local/bin/git-delete-tag + /usr/local/bin/git-effort + /usr/local/bin/git-extras + +... +``` + +## license + +MIT diff --git a/lib/suggest/package.json b/lib/suggest/package.json new file mode 100644 index 0000000..01852ad --- /dev/null +++ b/lib/suggest/package.json @@ -0,0 +1,7 @@ +{ + "name": "suggest", + "version": "0.0.2", + "description": "Suggest a command based on a query found in $PATH", + "scripts": [ "suggest.sh" ], + "install": "make install" +} diff --git a/lib/suggest/suggest.sh b/lib/suggest/suggest.sh new file mode 100755 index 0000000..c07406c --- /dev/null +++ b/lib/suggest/suggest.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +## suggest version +VERSION="0.0.2" + +## output usage +usage () { + echo "usage: suggest [-hV] " +} + +## main +suggest () { + declare -a local paths=() + declare -a local seen=() + declare -a local found=() + local query="${1}" + + case "${query}" in + -h|--help) + usage + return 0 + ;; + + -V|--version) + echo "${VERSION}" + return 0 + ;; + + *) + if [ "-" = "${query:0:1}" ]; then + echo >&2 "error: Unknown argument \`${query}'" + return 1 + fi + ;; + esac + + ## search path + { + local res="" + IFS=':' read -a paths <<< "${PATH}" + for (( i = 0; i < ${#paths[@]}; ++i )); do + local path="${paths[$i]}" + local let skip=0 + + ## omit non existent paths + if ! test -d "${path}"; then + continue + else + for (( n = 0; n < "${#seen[@]}"; ++n )); do + if [ "${path}" = "${seen[$n]}" ]; then + skip=1; + break; + fi + done + + ## check if skip needed + if [ "1" = "${skip}" ]; then + continue + fi + fi + + ## mark seen + seen+=( "${path}" ) + + ## find in path + if res=$(find "${path}" -name "${query}*" -prune -print 2>/dev/null); then + if [ -z "${res}" ]; then + continue + fi + res="$(echo ${res} | tr '\n' ' ')" + ## add to found count + found+=( $(echo -n "${res}") ) + fi + done + } + + ## get total + count="${#found[@]}" + + if (( ${count} == 1 )); then + echo "${found[0]}" + elif (( ${count} > 0 )); then + printf "suggest: found %d result(s)\n" ${count} + echo + for (( i = 0; i < ${count}; ++i )); do + printf "%d %s\n" $(echo -n ${found[$i]} | wc -c | tr -d ' ') "${found[$i]}" + done | sort -n | awk '{ print $2 }' | xargs printf ' %s\n' + else + echo "suggest: Couldn't anything to match \`${query}'" + return 1 + fi + return 0 +} + +## export or run +if [[ ${BASH_SOURCE[0]} != $0 ]]; then + export -f suggest +else + suggest "$@" +fi