mirror of
https://github.com/denisidoro/navi
synced 2024-11-21 19:13:07 +00:00
Add option for searching online repositories (#38)
This commit is contained in:
parent
f853181f83
commit
77acda383d
12 changed files with 261 additions and 80 deletions
146
README.md
146
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
|
||||
-----------------
|
||||
|
||||
**Using [brew](https://brew.sh/):**
|
||||
```sh
|
||||
brew install denisidoro/tools/navi
|
||||
```
|
||||
* [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`:
|
||||
|
||||
**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:
|
||||
|
||||
## Trying it out online
|
||||
- brew: `brew update; brew reinstall navi`
|
||||
- git: `cd /opt/navi && sudo make update`
|
||||
|
||||
Head to [this playground](https://www.katacoda.com/denisidoro/scenarios/navi) for previewing **navi**.
|
||||
Usage
|
||||
-----
|
||||
|
||||
## Motivation
|
||||
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 out online
|
||||
--------------------
|
||||
|
||||
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
|
||||
----------
|
||||
|
||||
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
|
||||
|
||||
## Alternatives
|
||||
The interface prompts for variable names inside brackets (eg `<branch>`).
|
||||
|
||||
- [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).
|
||||
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>
|
||||
|
||||
## Etymology
|
||||
$ 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).
|
||||
|
||||
Most of them provide excellent cheatsheet repositories, but lack a nice UI.
|
||||
|
||||
In any case, **navi** has the option to [search for some of these repositories](#installation).
|
||||
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% awk, text processing, string
|
||||
% awk, string
|
||||
|
||||
# Print nth column
|
||||
awk '{print $<n>}
|
||||
# Print last column
|
||||
echo '1 2 3' | awk '{print $NF}'
|
|
@ -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'
|
||||
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
|
34
navi
34
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 "$@"
|
||||
|
|
|
@ -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() {
|
||||
|
|
33
src/docs.sh
33
src/docs.sh
|
@ -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
|
||||
}
|
20
src/main.sh
20
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
|
||||
}
|
44
src/opts.sh
Normal file
44
src/opts.sh
Normal file
|
@ -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)}"
|
39
src/search.sh
Normal file
39
src/search.sh
Normal file
|
@ -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"
|
||||
}
|
|
@ -25,3 +25,7 @@ str::last_paragraph_line() {
|
|||
awk '(!NF) { exit } { print $0 }' \
|
||||
| tail -n1
|
||||
}
|
||||
|
||||
str::first_word() {
|
||||
awk '{print $1}'
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Reference in a new issue