summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Isidoro <denisidoro@users.noreply.github.com>2019-09-22 11:52:10 -0300
committerGitHub <noreply@github.com>2019-09-22 11:52:10 -0300
commit77acda383df96d757df1d3bdaa328b5d15b3a5f6 (patch)
tree1415d2d9cfd4f18e90978625d098f1729a3b59cc
parentf853181f830e8a8d1792617eb07eb3f644706934 (diff)
Add option for searching online repositories (#38)v0.8.0
-rw-r--r--README.md148
-rw-r--r--cheats/awk.cheat6
-rw-r--r--cheats/network.cheat2
-rwxr-xr-xnavi34
-rwxr-xr-xsrc/cheat.sh4
-rw-r--r--src/docs.sh33
-rw-r--r--src/health.sh (renamed from src/healthcheck.sh)0
-rw-r--r--src/main.sh20
-rw-r--r--src/opts.sh44
-rw-r--r--src/search.sh39
-rw-r--r--src/str.sh4
-rw-r--r--src/ui.sh9
12 files changed, 262 insertions, 81 deletions
diff --git a/README.md b/README.md
index 2c6cca8..3920ef8 100644
--- a/README.md
+++ b/README.md
@@ -6,37 +6,91 @@ An interactive cheatsheet tool for the command-line so that you'll never say the
— *Oh, it's not in my bash history*<br>
— *Geez, it's almost what I wanted but I need to change some args*
-![Demo](https://user-images.githubusercontent.com/3226564/65380182-69431380-dcac-11e9-9af8-0f7b3c869d0f.gif)
+![Demo](https://user-images.githubusercontent.com/3226564/65389667-0181dc80-dd2f-11e9-9fac-c875ed7c7b53.gif)
**navi** allows you to browse through cheatsheets (that you may write yourself or download from maintainers) and execute commands, prompting for argument values.
-## Installation
+Table of Contents
+-----------------
+
+ * [Installation](#installation)
+ * [Using Homebrew or Linuxbrew](#using-homebrew-or-linuxbrew)
+ * [Using git](#using-git)
+ * [Upgrading](#upgrading)
+ * [Usage](#usage)
+ * [Preventing execution](#preventing-execution)
+ * [Pre-filtering](#pre-filtering)
+ * [Searching online repositories](#searching-online-repositories)
+ * [More options](#more-options)
+ * [Trying out online](#trying-out-online)
+ * [Motivation](#motivation)
+ * [Cheatsheets](#cheatsheets)
+ * [Using your own custom cheatsheets](#using-your-own-custom-cheatsheets)
+ * [Submitting cheatsheets](#submitting-cheatsheets)
+ * [Cheatsheet syntax](#cheatsheet-syntax)
+ * [Syntax overview](#syntax-overview)
+ * [Variables](#variables)
+ * [FZF options](#fzf-options)
+ * [Related projects](#related-projects)
+ * [Etymology](#etymology)
+
+Installation
+------------
+
+### Using Homebrew or Linuxbrew
+
+You can use [Homebrew](http://brew.sh/) or [Linuxbrew](http://linuxbrew.sh/)
+to install **navi**.
+
+### Using git
+
+Alternatively, you can `git clone` this repository and run `make`:
-**Using [brew](https://brew.sh/):**
```sh
-brew install denisidoro/tools/navi
-```
-
-**Without brew:**
-```sh
-git clone http://github.com/denisidoro/navi /opt/navi
+git clone --depth 1 http://github.com/denisidoro/navi /opt/navi
cd /opt/navi
sudo make install
# install fzf: https://github.com/junegunn/fzf
```
-## Usage
+Upgrading
+---------
-Simply call:
-```sh
-navi
-```
+**navi** is being actively developed and you might want to upgrade it once in a while. Please follow the instruction below depending on the installation method used:
+
+- brew: `brew update; brew reinstall navi`
+- git: `cd /opt/navi && sudo make update`
+
+Usage
+-----
+
+By simply running `navi` you will be prompted with the default cheatsheets.
+
+### Preventing execution
+
+If you run `navi --print`, the selected command won't be executed. It will be printed to stdout instead.
+
+### Pre-filtering
+
+If you run `navi query <cmd>`, the results will be pre-filtered.
+
+### Searching online repositories
+
+If you run `navi search <cmd>`, **navi** will try to download cheatsheets from online repositories as well.
+
+Please note that these cheatsheets aren't curated by **navi**'s maintainers and should be taken with a grain of salt. If you're not sure about executing these commands, make sure to check the preview window or use the `--print` option.
+
+### More options
+
+Please refer to `navi --help` for more details.
-## Trying it out online
+Trying out online
+--------------------
-Head to [this playground](https://www.katacoda.com/denisidoro/scenarios/navi) for previewing **navi**.
+If you don't have access to bash at the moment and you want to live preview **navi**, head to [this playground](https://www.katacoda.com/denisidoro/scenarios/navi). It'll start a docker container with instructions for you to install and use the tool. Note: login required.
-## Motivation
+Motivation
+----------
The main objectives are:
- to increase discoverability, by finding commands given keywords or descriptions;
@@ -50,23 +104,31 @@ Or you can launch a browser and search for instructions on Google, but that take
**navi**, on the other hand, intends to be a general purpose platform for bookmarking any command at a very low cost.
-## Using your own cheatsheets
+Cheatsheets
+-----------
-In this case, you need to pass the directory which contains `.cheat` files as in:
+### Using your own custom cheatsheets
+
+In this case, you need to pass a `:`-separated list of separated directories which contain `.cheat`:
```sh
-navi --dir "/folder/with/cheats"
+navi --path "/folder/with/cheats"
```
Alternatively, you can set an environment variable in your `.bashrc`-like file:
```sh
-export NAVI_DIR="/folder/with/cheats"
+export NAVI_PATH="/folder/with/cheats:/another/folder"
```
-## Submitting cheatsheets
+### Submitting cheatsheets
Feel free to fork this project and open a PR for me to include your contributions.
-## .cheat syntax
+Cheatsheet syntax
+-----------------
+
+Cheatsheets are describe in `.cheat` files.
+
+### Syntax overview
- lines starting with `%` should contain tags which will be added to any command in a given file;
- lines starting with `#` should be descriptions of commands;
@@ -83,16 +145,40 @@ git checkout <branch>
$ branch: git branch | awk '{print $NF}'
```
-For advanced usage, please refer to the files in [/cheats](https://github.com/denisidoro/navi/tree/master/cheats).
+### Variables
+
+The interface prompts for variable names inside brackets (eg `<branch>`).
+
+The command for generating possible inputs can refer other variables:
+```sh
+# If you select 2 for x, the possible values of y will be 12 and 22
+echo <x> <y>
+
+$ x: echo -e '1\n2\n3' | tr '\n' ' '
+$ y: echo "$((x+10))" "$((x+20))" | tr '\n' ' '
+```
+
+### FZF options
+
+You can make pick a specific column of a selection and set the number of lines considered as headers:
+
+```sh
+# This will pick the 3rd column and use the first line as header
+docker rmi <image_id>
+
+$ image_id: docker images --- --headers 1 --column 3
+```
+
+Related projects
+----------------
+
+There are many similar projects out there ([bro](https://github.com/hubsmoke/bro), [eg](https://github.com/srsudar/eg), [cheat.sh](https://github.com/chubin/cheat.sh), [cmdmenu](https://github.com/amacfie/cmdmenu), [cheat](https://github.com/cheat/cheat), [beavr](https://github.com/denisidoro/beavr), [how2](https://github.com/santinic/how2) and [howdoi](https://github.com/gleitz/howdoi), to name a few).
-## Alternatives
+Most of them provide excellent cheatsheet repositories, but lack a nice UI.
-- [cmdmenu](https://github.com/amacfie/cmdmenu);
-- [denisidoro/beavr](https://github.com/denisidoro/beavr);
-- [how2](https://github.com/santinic/how2);
-- [howdoi](https://github.com/gleitz/howdoi);
-- [cheat](https://github.com/cheat/cheat).
+In any case, **navi** has the option to [search for some of these repositories](#installation).
-## Etymology
+Etymology
+---------
In [The Legend of Zelda Ocarina of Time](https://zelda.gamepedia.com/Ocarina_of_Time), [navi](https://zelda.gamepedia.com/Navi) is a character that provides [Link](https://zelda.gamepedia.com/Link) with a variety of clues to help him solve puzzles and progress in his quest.
diff --git a/cheats/awk.cheat b/cheats/awk.cheat
index 984e8c7..080cd88 100644
--- a/cheats/awk.cheat
+++ b/cheats/awk.cheat
@@ -1,4 +1,4 @@
-% awk, text processing, string
+% awk, string
-# Print nth column
-awk '{print $<n>} \ No newline at end of file
+# Print last column
+echo '1 2 3' | awk '{print $NF}' \ No newline at end of file
diff --git a/cheats/network.cheat b/cheats/network.cheat
index 1ea7fef..ee52b4d 100644
--- a/cheats/network.cheat
+++ b/cheats/network.cheat
@@ -10,4 +10,4 @@ netstat -tn 2>/dev/null | grep :<port> | awk '{print $5}' | cut -d: -f1 | sort |
dig +short myip.opendns.com @resolver1.opendns.com
# Find primary, local IP address
-ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' \ No newline at end of file
+ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | tail -n1 \ No newline at end of file
diff --git a/navi b/navi
index 14ff829..83d37cc 100755
--- a/navi
+++ b/navi
@@ -5,17 +5,37 @@ export SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "${SCRIPT_DIR}/src/main.sh"
-##? Command cheatsheet tool
+##? An interactive cheatsheet tool for the command-line
##?
##? Usage:
-##? cheats [options]
+##? cheats [command] [<args>...] [options]
+##?
+##? Commands:
+##? search <cmd> Search for cheatsheets on online repositories
+##? query <cmd> Pre-filter results
##?
##? Options:
-##? --print Prevent script execution [default: false]
-##? --no-interpolation Prevent argument interpolation [default: false]
-##? --no-preview Hide command preview window [default: false]
+##? --print Prevent script execution
+##? --path List of paths to look for cheats
+##? --no-interpolation Prevent argument interpolation
+##? --no-preview Hide command preview window
+##?
+##? Examples:
+##? cheats
+##? cheats --path '/some/folder:/another/folder'
+##? cheats search awk
+##? cheats search docker --print
+##? cheats query git
+##?
+##? More info:
+##? search
+##? Queries cheatsheets from http://cheat.sh
+##? Please note that these cheatsheets may not work out of the box
+##? Always check the preview window before executing commands!
+##? full docs
+##? Please refer to the README at https://github.com/denisidoro/navi
-VERSION="0.7.0"
-docs::eval "$@"
+VERSION="0.8.0"
+opts::eval "$@"
main "$@"
diff --git a/src/cheat.sh b/src/cheat.sh
index f96c8ee..203b8dd 100755
--- a/src/cheat.sh
+++ b/src/cheat.sh
@@ -1,7 +1,9 @@
#!/usr/bin/env bash
cheat::find() {
- find "${NAVI_DIR:-"${SCRIPT_DIR}/cheats"}" -iname '*.cheat'
+ for path in $(echo "$NAVI_PATH" | tr ':' '\n'); do
+ find "$path" -iname '*.cheat'
+ done
}
cheat::read_many() {
diff --git a/src/docs.sh b/src/docs.sh
deleted file mode 100644
index bb3bf4f..0000000
--- a/src/docs.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-docs::extract_help() {
- local readonly file="$1"
- grep "^##?" "$file" | cut -c 5-
-}
-
-docs::eval() {
- local wait_for=""
-
- entry_point="main"
- print=false
- interpolation=true
- preview=true
-
- for arg in $@; do
- case $wait_for in
- dir) NAVI_DIR="$arg"; wait_for="" ;;
- command-for) query="$(echo "$arg" | tr "^" " ")"; entry_point="preview"; break ;;
- esac
-
- case $arg in
- --print) print=true ;;
- --no-interpolation) interpolation=false ;;
- --version) echo "${VERSION:-unknown}" && exit 0 ;;
- --help) docs::extract_help "$0" && exit 0 ;;
- --command-for) wait_for="command-for" ;;
- --no-preview) preview=false ;;
- -d|--dir) wait_for="dir" ;;
- esac
- done
-}
diff --git a/src/healthcheck.sh b/src/health.sh
index 90ed69d..90ed69d 100644
--- a/src/healthcheck.sh
+++ b/src/health.sh
diff --git a/src/main.sh b/src/main.sh
index eadc22a..6a23659 100644
--- a/src/main.sh
+++ b/src/main.sh
@@ -2,9 +2,10 @@
source "${SCRIPT_DIR}/src/arg.sh"
source "${SCRIPT_DIR}/src/cheat.sh"
-source "${SCRIPT_DIR}/src/docs.sh"
-source "${SCRIPT_DIR}/src/healthcheck.sh"
+source "${SCRIPT_DIR}/src/health.sh"
source "${SCRIPT_DIR}/src/misc.sh"
+source "${SCRIPT_DIR}/src/opts.sh"
+source "${SCRIPT_DIR}/src/search.sh"
source "${SCRIPT_DIR}/src/selection.sh"
source "${SCRIPT_DIR}/src/str.sh"
source "${SCRIPT_DIR}/src/ui.sh"
@@ -51,7 +52,18 @@ handler::preview() {
main() {
case ${entry_point:-} in
- preview) handler::preview "$@" 2>/dev/null || echo "Unable to find command for '${query:-}'" ;;
- *) health::fzf && handler::main "$@" ;;
+ preview)
+ handler::preview "$@" \
+ || echo "Unable to find command for '${query:-}'"
+ ;;
+ search)
+ health::fzf
+ search::save "$query" || true
+ handler::main "$@"
+ ;;
+ *)
+ health::fzf
+ handler::main "$@"
+ ;;
esac
} \ No newline at end of file
diff --git a/src/opts.sh b/src/opts.sh
new file mode 100644
index 0000000..552406d
--- /dev/null
+++ b/src/opts.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+opts::extract_help() {
+ local readonly file="$1"
+ grep "^##?" "$file" | cut -c 5-
+}
+
+opts::eval() {
+ local readonly wait_for=""
+
+ entry_point="main"
+ print=false
+ interpolation=true
+ preview=true
+
+ for arg in "$@"; do
+ case $wait_for in
+ path) NAVI_PATH="$arg"; wait_for="" ;;
+ preview) query="$(echo "$arg" | tr "^" " ")"; wait_for=""; break ;;
+ search) query="$arg"; wait_for=""; export NAVI_PATH="${NAVI_PATH}:$(search::full_path "$query")"; ;;
+ query) query="$arg"; wait_for="" ;;
+ esac
+
+ case $arg in
+ --print) print=true ;;
+ --no-interpolation) interpolation=false ;;
+ --version) echo "${VERSION:-unknown}" && exit 0 ;;
+ help|--help) opts::extract_help "$0" && exit 0 ;;
+ --command-for) wait_for="command-for" ;;
+ --no-preview) preview=false ;;
+ --path) wait_for="path" ;;
+ search) entry_point="search"; wait_for="search";;
+ preview) entry_point="preview"; wait_for="preview";;
+ q|query) wait_for="query";;
+ esac
+ done
+}
+
+opts::fallback_path() {
+ echo "${NAVI_DIR:-${SCRIPT_DIR}/cheats}"
+}
+
+export NAVI_PATH="${NAVI_PATH:-$(opts::fallback_path)}" \ No newline at end of file
diff --git a/src/search.sh b/src/search.sh
new file mode 100644
index 0000000..1c2be4b
--- /dev/null
+++ b/src/search.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+search::cheat() {
+ local readonly cmd="$(echo "$1" | str::first_word)"
+
+ echo "% ${cmd}, cheatsh"
+ echo
+ curl -s "${CHTSH_URL:-http://cht.sh}/${cmd}?T"
+}
+
+search::filename() {
+ local readonly cmd="$(echo "$1" | str::first_word)"
+
+ echo "${cmd}_cheatsh" \
+ | head -n1 \
+ | awk '{print $NF}' \
+ | xargs \
+ | tr ' ' '_'
+}
+
+search::full_path() {
+ local readonly cmd="$(echo "$1" | str::first_word)"
+
+ echo "/tmp/navi/$(search::filename "$cmd").cheat"
+}
+
+search::save() {
+ local readonly cmd="$(echo "$1" | str::first_word)"
+
+ local readonly filepath="$(search::full_path "$cmd")"
+ local readonly filedir="$(dirname "$filepath")"
+
+ if [ -f "$filepath" ]; then
+ return
+ fi
+
+ mkdir -p "$filedir" &> /dev/null || true
+ search::cheat "$cmd" > "$filepath"
+} \ No newline at end of file
diff --git a/src/str.sh b/src/str.sh
index 7c72826..6e860b6 100644
--- a/src/str.sh
+++ b/src/str.sh
@@ -25,3 +25,7 @@ str::last_paragraph_line() {
awk '(!NF) { exit } { print $0 }' \
| tail -n1
}
+
+str::first_word() {
+ awk '{print $1}'
+}
diff --git a/src/ui.sh b/src/ui.sh
index a41cb85..c8ab0a0 100644
--- a/src/ui.sh
+++ b/src/ui.sh
@@ -7,7 +7,7 @@ ui::pick() {
ui::select() {
local readonly cheats="$1"
local readonly script_path="$(which navi | head -n1 || echo "${SCRIPT_DIR}/navi")"
- local readonly preview_cmd="echo {} | tr ' ' '^' | xargs -I% \"${script_path}\" --command-for %"
+ local readonly preview_cmd="echo \"{}\" | tr ' ' '^' | xargs -I% \"${script_path}\" preview %"
local args=()
args+=("-i")
@@ -16,6 +16,13 @@ ui::select() {
args+=("--preview"); args+=("$preview_cmd")
args+=("--preview-window"); args+=("up:1")
fi
+ if [ -n "${query:-}" ]; then
+ args+=("--query=${query} ")
+ fi
+ if [ "${entry_point:-}" = "search" ]; then
+ args+=("--header")
+ args+=("Displaying online results. Please refer to 'navi --help' for details")
+ fi
echo "$cheats" \
| cheat::read_many \