1
0
Fork 0
mirror of https://github.com/sbrl/bin.git synced 2018-01-10 21:33:46 +00:00

Merge branch 'master' of github.com:sbrl/bin

This commit is contained in:
Starbeamrainbowlabs 2017-11-11 22:42:59 +00:00
commit b2c141276b

176
tldr
View file

@ -1,12 +1,13 @@
#!/bin/bash #!/usr/bin/env bash
set +vx -o pipefail set +vx -o pipefail
[[ $- = *i* ]] && echo "Don't source this script!" && return 1 [[ $- = *i* ]] && echo "Don't source this script!" && return 1
version='0.32' version='0.36'
# tldr-bash-client version 0.32 # tldr-bash-client version 0.36
# Bash client for tldr: community driven man-by-example # Bash client for tldr: community driven man-by-example
# - forked from Ray Lee, http://github.com/raylee/tldr # - forked from Ray Lee, https://github.com/raylee/tldr
# - modified and expanded by pepa65: http://github.com/pepa65/tldr-bash-client # - modified and expanded by pepa65: https://github.com/pepa65/tldr-bash-client
# Requiring: coreutils, less, grep, unzip, curl/wget # - binary download: http://4e4.win/tldr
# Requiring: coreutils, grep, unzip, curl/wget, less (optional)
# The 5 elements in TLDR markup that can be styled with these colors and # The 5 elements in TLDR markup that can be styled with these colors and
# backgrounds (last one specified will be used) and modes (more can apply): # backgrounds (last one specified will be used) and modes (more can apply):
@ -40,29 +41,34 @@ version='0.32'
# Alternative location of pages cache # Alternative location of pages cache
: "${TLDR_CACHE:= }" : "${TLDR_CACHE:= }"
# Usage of 'less' or 'cat' for output (set to '0' for cat)
: "${TLDR_LESS:= }"
## Function definitions
# $1: [optional] exit code; Uses: version cachedir # $1: [optional] exit code; Uses: version cachedir
Usage(){ Usage(){
Out "$(cat <<-EOF Out "$(cat <<-EOF
$HHE $version $HHE$version
$HDE USAGE: $HHE$(basename "$0")$XHHE [${HOP}option$XHOP] [${HPL}platform$XHPL/]${HCO}command$XHCO $HDEUSAGE: $HHE$(basename "$0")$XHHE [${HOP}option$XHOP] [${HPL}platform$XHPL/]${HCO}command$XHCO
$HDE [${HPL}platform$XHPL/]${HCO}command$XHCO: Show page for$HCO command$XHCO (from$HPL platform$XHPL) $HDE[${HPL}platform$XHPL/]${HCO}command$XHCO: Show page for ${HCO}command$XHCO (from ${HPL}platform$XHPL)
$HPL platform$XHPL is optionally one of:$HPL common$XHPL,$HPL linux$XHPL,$HPL osx$XHPL,$HPL sunos$XHPL ${HPL}platform$XHPL (optional) one of: ${HPL}common$XHPL, ${HPL}linux$XHPL, ${HPL}osx$XHPL, ${HPL}sunos$XHPL, ${HPL}current$XHPL (includes common)
$HOP option$XHOP is optionally one of: ${HOP}option$XHOP is optionally one of:
$HOP-l$XHOP,$HOP --list$XHOP [${HPL}platform$XHPL]: Show all available pages (from$HPL platform$XHPL) $HOP-l$XHOP, $HOP--list$XHOP [${HPL}platform$XHPL]: List all pages (from ${HPL}platform$XHPL)
$HOP-r$XHOP,$HOP --render$XHOP ${HFI}file$XHFI: Render a local$HFI file$XHFI as tldr markdown $HOP-a$XHOP, $HOP--list-all$XHOP: List all pages from current platform + common
$HOP-m$XHOP,$HOP --markdown$XHOP ${HCO}command$XHCO: Show the markdown source for$HCO command$XHCO $HOP-r$XHOP, $HOP--render$XHOP ${HFI}file$XHFI: Render a local ${HFI}file$XHFI as tldr markdown
$HOP-c$XHOP,$HOP --cache$XHOP: Cache all pages by downloading archive from repo $HOP-m$XHOP, $HOP--markdown$XHOP ${HCO}command$XHCO: Show the markdown source for ${HCO}command$XHCO
$HOP-u$XHOP,$HOP --update$XHOP: Re-download index file from repo $HOP-u$XHOP, $HOP--update$XHOP: Update the pages cache by downloading repo archive
$HOP-v$XHOP,$HOP --version$XHOP: Version number and repo location $HOP-v$XHOP, $HOP--version$XHOP: Version number and local repo location
$HDE[$HOP-h$XHOP,$HOP -?$XHOP,$HOP --help$XHOP]: This help overview $HDE[$HOP-h$XHOP, $HOP-?$XHOP, $HOP--help$XHOP]: This help overview
$HDE Element styling:$XHDE$T Title$XT$D Description$XD$E Example$XD$C Code$XC$V Value$XV ${HDE}Element styling:$XHDE ${T}Title$XT ${D}Description$XD ${E}Example$XE ${C}Code$XC ${V}Value$XV
$HDE All pages and the index are cached locally under $HUR$cachedir$XHUR. ${HDE}All pages and the index are cached locally under $HUR$cachedir$XHUR.
$HDE By default, the cached copies will be freshly downloaded after $HUR${TLDR_EXPIRY// /}$XHUR days. ${HDE}By default, the cached copies will be freshly downloaded after $HUR${TLDR_EXPIRY// /}$XHUR days.
EOF EOF
)" )"
exit "${1:-0}" exit "${1:-0}"
@ -173,17 +179,11 @@ Init_term(){
# $1: page # $1: page
Recent(){ find "$1" -mtime -"${TLDR_EXPIRY// /}" >/dev/null 2>&1;} Recent(){ find "$1" -mtime -"${TLDR_EXPIRY// /}" >/dev/null 2>&1;}
# Download index.json; Uses: index index_url base_url zip_url dl
Update_index(){
$dl "$index" "$index_url" && Inf "Index file $I$index$XI freshly downloaded" || {
Err "Could not download index from $I$index_url$XI with $dl"
exit 2
}
}
# Initialize globals, check the environment; Uses: config cachedir version # Initialize globals, check the environment; Uses: config cachedir version
# Sets: stdout os version dl # Sets: stdout os version dl
Config(){ Config(){
type -p less >/dev/null || TLDR_LESS=0
os=common stdout='' Q='"' N=$'\n' os=common stdout='' Q='"' N=$'\n'
case "$(uname -s)" in case "$(uname -s)" in
Darwin) os='osx' ;; Darwin) os='osx' ;;
@ -191,21 +191,22 @@ Config(){
SunOS) os='sunos' ;; SunOS) os='sunos' ;;
esac esac
Init_term Init_term
[[ $TLDR_LESS = 0 ]] &&
trap 'cat <<<"$stdout"' EXIT ||
trap 'less -~RXQFP"Browse up/down, press Q to exit " <<<"$stdout"' EXIT trap 'less -~RXQFP"Browse up/down, press Q to exit " <<<"$stdout"' EXIT
version="tldr-bash-client version $version $XB$URL http://github.com/pepa65/tldr-bash-client$XURL" version="tldr-bash-client version $version$XB ${URL}http://github.com/pepa65/tldr-bash-client$XURL"
# Select download method # Select download method
dl="$(type -p curl) -sLfo" || { dl="$(type -p curl) -sLfo" || {
dl="$(type -p wget) --max-redirect=20 -qNO" || { dl="$(type -p wget) --max-redirect=20 -qNO" || {
Err "tldr requires$I curl$XI or$I wget $XI installed in your path" Err "tldr requires ${I}curl$XI or ${I}wget$XI installed in your path"
exit 3 exit 3
} }
} }
base_url='https://raw.githubusercontent.com/tldr-pages/tldr/master/pages' pages_url='https://raw.githubusercontent.com/tldr-pages/tldr/master/pages'
zip_url='http://tldr-pages.github.io/assets/tldr.zip' zip_url='http://tldr.sh/assets/tldr.zip'
index_url='http://tldr-pages.github.io/assets/index.json'
read cachedir <<<$TLDR_CACHE read cachedir <<<$TLDR_CACHE
[[ $cachedir ]] || { [[ $cachedir ]] || {
@ -218,25 +219,25 @@ Config(){
} }
index=$cachedir/index.json index=$cachedir/index.json
# update if the file doesn't exists, or if it's older than $TLDR_EXPIRY # update if the file doesn't exists, or if it's older than $TLDR_EXPIRY
[[ -f $index ]] && Recent "$index" || Update_index [[ -f $index ]] && Recent "$index" || Cache_fill 0
} }
# $1: error message; Uses: md line ln # $1: error message; Uses: md REPLY ln
Unlinted(){ Unlinted(){
Err "Page $I$md$XI not properly linted!$N${ERRSP}${ERR}Line $I$ln$XI [$XERR$U$line$XU$ERR]$N$ERRSP$ERR$1" Err "Page $I$md$XI not properly linted!$N${ERRSP}${ERR}Line $I$ln$XI [$XERR$U$REPLY$XU$ERR]$N$ERRSP$ERR$1"
exit 5 exit 5
} }
# $1: page; Uses: index index_url cachedir base_url platform os dl cached md # $1: page; Uses: index cachedir pages_url platform os dl cached md
# Sets: cached md # Sets: cached md
Get_tldr(){ Get_tldr(){
local desc err notfound local desc err notfound
# convert the local platform name to tldr's version # convert the local platform name to tldr's version
# extract the platform key from index.json, return preferred subpath to page # extract the platform key from index.json, return preferred subpath to page
desc=$(tr '{' '\n' <$index |grep "\"name\":\"$1\"") desc=$(tr '{' '\n' <"$index" |grep "\"name\":\"$1\"")
# results in, eg, "name":"netstat","platform":["linux","osx"]}, # results in, eg, "name":"netstat","platform":["linux","osx"]},
[[ $desc ]] || return # just not found [[ $desc ]] || return # nothing found
error=0 error=0
if [[ $platform ]] if [[ $platform ]]
@ -249,7 +250,7 @@ Get_tldr(){
} }
fi fi
# if no page found yet, try the system platform # if no page found yet, try the system platform
[[ $md ]] || [[ $platform = "$os" ]] || { [[ $md ]] || [[ $platform = $os ]] || {
[[ $desc =~ \"$os\" ]] && md=$os/$1.md [[ $desc =~ \"$os\" ]] && md=$os/$1.md
} || { } || {
notfound+=" or $I$os$XI" notfound+=" or $I$os$XI"
@ -263,77 +264,84 @@ Get_tldr(){
cached=$cachedir/$md cached=$cachedir/$md
Recent "$cached" || { Recent "$cached" || {
mkdir -p "${cached%/*}" mkdir -p "${cached%/*}"
$dl "$cached" "$base_url/$md" || Err "Could not download page $I$cached$XI from index $U$index_url$XU with $dl" $dl "$cached" "$pages_url/$md" || Err "Could not download page $I$cached$XI with $dl"
} }
} }
# $1: text; Uses: page stdout; Sets: ln line # $1: text; Uses: page stdout; Sets: ln REPLY
Display_tldr(){ Display_tldr(){
local newfmt len val local newfmt len val
ln=0 line='' ln=0 REPLY=''
[[ $md ]] || md=$1 [[ $md ]] || md=$1
# Read full lines, and process even when no newline at the end # Read full lines, and process even when no newline at the end
while read -r line || [[ $line ]] while read -r || [[ $REPLY ]]
do do
((++ln)) ((++ln))
((ln==1)) && { ((ln==1)) && {
[[ ${line:0:1} = '#' ]] && newfmt=0 || newfmt=1 [[ ${REPLY:0:1} = '#' ]] && newfmt=0 || newfmt=1
((newfmt)) && { ((newfmt)) && {
[[ $line ]] || Unlinted "No title" [[ $REPLY ]] || Unlinted "Empty title"
Out "$TNL$TSP$T$line$XT" Out "$TNL$TSP$T$REPLY$XT"
len=${#line} len=${#REPLY} # title length
read -r; ((++ln)) read -r
[[ $line =~ [^=] ]] && Unlinted "Title underline must be equal signs" ((++ln))
((len!=${#line})) && Unlinted "Underline length not equal to title's" [[ $REPLY =~ [^=] ]] && Unlinted "Title underline must be equal signs"
read -r; ((++ln)) ((len!=${#REPLY})) && Unlinted "Underline length not equal to title's"
read -r
((++ln))
} }
} }
case "${line:0:1}" in # first character case "${REPLY:0:1}" in # first character
'#') ((newfmt)) && Unlinted "Bad first character" '#') ((newfmt)) && Unlinted "Bad first character"
((${#line} <= 2)) && Unlinted "No title" ((${#REPLY} <= 2)) && Unlinted "No title"
[[ ! ${line:1:1} = ' ' ]] && Unlinted "2nd character no space" [[ ! ${REPLY:1:1} = ' ' ]] && Unlinted "2nd character no space"
Out "$TNL$TSP$T${line:2}$XT" ;; Out "$TNL$TSP$T${REPLY:2}$XT" ;;
'>') ((${#line} <= 3)) && Unlinted "No valid desciption" '>') ((${#REPLY} <= 3)) && Unlinted "No valid desciption"
[[ ! ${line:1:1} = ' ' ]] && Unlinted "2nd character no space" [[ ! ${REPLY:1:1} = ' ' ]] && Unlinted "2nd character no space"
[[ ! ${line: -1} = '.' ]] && Unlinted "Description doesn't end in full stop" [[ ! ${REPLY: -1} = '.' ]] && Unlinted "Description doesn't end in full stop"
Out "$DNL$DSP$D${line:2}$XD" Out "$DNL$DSP$D${REPLY:2}$XD"
DNL='' ;; DNL='' ;;
'-') ((newfmt)) && Unlinted "Bad first character" '-') ((newfmt)) && Unlinted "Bad first character"
((${#line} <= 2)) && Unlinted "No example content" ((${#REPLY} <= 2)) && Unlinted "No example content"
[[ ! ${line:1:1} = ' ' ]] && Unlinted "2nd character no space" [[ ! ${REPLY:1:1} = ' ' ]] && Unlinted "2nd character no space"
Out "$ENL$ESP$E${line:2}$XE" ;; Out "$ENL$ESP$E${REPLY:2}$XE" ;;
' ') ((newfmt)) || Unlinted "Bad first character" ' ') ((newfmt)) || Unlinted "Bad first character"
((${#line} <= 4)) && Unlinted "No valid code content" ((${#REPLY} <= 4)) && Unlinted "No valid code content"
[[ ${line:0:4} = ' ' ]] || Unlinted "No four spaces before code" [[ ${REPLY:0:4} = ' ' ]] || Unlinted "No four spaces before code"
val=${line:4} val=${REPLY:4}
# Value: convert {{value}} # Value: convert {{value}}
val=${val//\{\{/$CX$V} val=${val//\{\{/$CX$V}
val=${val//\}\}/$XV$C} val=${val//\}\}/$XV$C}
Out "$CNL$CSP$C$val$XC" ;; Out "$CNL$CSP$C$val$XC" ;;
'`') ((newfmt)) && Unlinted "Bad first character" '`') ((newfmt)) && Unlinted "Bad first character"
((${#line} <= 2)) && Unlinted "No valid code content" ((${#REPLY} <= 2)) && Unlinted "No valid code content"
[[ ! ${line: -1} = '`' ]] && Unlinted "Code doesn't end in backtick" [[ ! ${REPLY: -1} = '`' ]] && Unlinted "Code doesn't end in backtick"
val=${line:1:-1} val=${REPLY:1:${#REPLY}-2}
# Value: convert {{value}} # Value: convert {{value}}
val=${val//\{\{/$CX$V} val=${val//\{\{/$CX$V}
val=${val//\}\}/$XV$C} val=${val//\}\}/$XV$C}
Out "$CNL$CSP$C$val$XC" ;; Out "$CNL$CSP$C$val$XC" ;;
'') continue ;; '') continue ;;
*) ((newfmt)) || Unlinted "Bad first character" *) ((newfmt)) || Unlinted "Bad first character"
[[ -z $line ]] && Unlinted "No example content" [[ -z $REPLY ]] && Unlinted "No example content"
Out "$ENL$EPS$E$line$XE" ;; Out "$ENL$ESP$E$REPLY$XE" ;;
esac esac
done <"$1" done <"$1"
[[ $TLDR_LESS = 0 ]] &&
trap 'cat <<<"$stdout"' EXIT ||
trap 'less -Gg -~RXQFP"%pB\% tldr $I$page$XI - browse up/down, press Q to exit" <<<"$stdout"' EXIT trap 'less -Gg -~RXQFP"%pB\% tldr $I$page$XI - browse up/down, press Q to exit" <<<"$stdout"' EXIT
} }
# $1: exit code; Uses: platform index # $1: exit code; Uses: platform index
List_pages(){ List_pages(){
local platformtext c1 c2 c3 local platformtext c1 c2 c3
[[ $platform ]] && platformtext=" from platform $I$platform$XI" [[ $platform ]] && platformtext="platform $I$platform$XI" ||
Inf "Known tldr pages$platformtext:" platform=^ platformtext="${I}all$XI platforms"
[[ $platform = current ]] && platform="-e $os -e common" &&
platformtext="$I$os$XI platform and ${I}common$XI"
Inf "Known tldr pages from $platformtext:"
Out "$(while read -r c1 c2 c3; do printf "%-19s %-19s %-19s %-19s$N" $c1 $c2 $c3; done \ Out "$(while read -r c1 c2 c3; do printf "%-19s %-19s %-19s %-19s$N" $c1 $c2 $c3; done \
<<<$(tr '{' '\n' <$index |grep "$platform" |cut -d "$Q" -f4))" <<<$(tr '{' '\n' <"$index" |grep $platform |cut -d "$Q" -f4))"
exit "$1" exit "$1"
} }
@ -370,28 +378,28 @@ Main(){
case "$1" in case "$1" in
-l|--list) [[ $2 ]] && { -l|--list) [[ $2 ]] && {
platform=$2 platform=$2
[[ ,common,linux,osx,sunos, = *,$platform,* ]] || { [[ ,common,linux,osx,sunos,current, = *,$platform,* ]] || {
Err "Unknown platform $I$platform$XI" Err "Unknown platform $I$platform$XI"
Usage 9 Usage 9
} }
[[ $3 ]] && Err "$nomore" && err=10 [[ $3 ]] && Err "$nomore" && err=10
} }
List_pages "$err" ;; List_pages "$err" ;;
-c|--cache) [[ $2 ]] && Err "$nomore" && err=11 -a|--list-all) [[ $2 ]] && Err "$nomore" && err=11
platform=current
List_pages $err ;;
-u|--update) [[ $2 ]] && Err "$nomore" && err=12
Cache_fill "$err" ;; Cache_fill "$err" ;;
-v|--version) [[ $2 ]] && Err "$nomore" && err=12 -v|--version) [[ $2 ]] && Err "$nomore" && err=13
Inf "$version" Inf "$version"
exit "$err" ;; exit "$err" ;;
-u|--update) [[ $2 ]] && Err "$nomore" && err=13
Update_index
exit "$err" ;;
-r|--render) [[ -z $2 ]] && Err "Specify a file to render" && Usage 14 -r|--render) [[ -z $2 ]] && Err "Specify a file to render" && Usage 14
[[ $3 ]] && Err "$nomore" && err=15 [[ $3 ]] && Err "$nomore" && err=15
[[ -f "$2" ]] && { [[ -f "$2" ]] && {
Display_tldr "$2" && exit "$err" Display_tldr "$2" && exit "$err"
Err "A file error occured" Err "A file error occured"
exit 16 exit 16
} || Err "No file:$I $2$XI" && exit 17 ;; } || Err "No file: ${I}$2$XI" && exit 17 ;;
-m|--markdown) shift -m|--markdown) shift
page=$* page=$*
[[ -z $page ]] && Err "Specify a page to display" && Usage 18 [[ -z $page ]] && Err "Specify a page to display" && Usage 18
@ -404,7 +412,7 @@ Main(){
esac esac
[[ -z $page ]] && Err "No command specified" && Usage 21 [[ -z $page ]] && Err "No command specified" && Usage 21
[[ $page =~ ' -' || ${page:0:1} = '-' ]] && Err "Only one option allowed" && Usage 22 [[ ${page:0:1} = '-' || $page = *' '-* ]] && Err "Only one option allowed" && Usage 22
[[ $page = */* ]] && platform=${page%/*} && page=${page##*/} [[ $page = */* ]] && platform=${page%/*} && page=${page##*/}
[[ $platform && ,common,linux,osx,sunos, != *,$platform,* ]] && { [[ $platform && ,common,linux,osx,sunos, != *,$platform,* ]] && {
Err "Unknown platform $I$platform$XI" Err "Unknown platform $I$platform$XI"
@ -413,7 +421,7 @@ Main(){
Get_tldr "${page// /-}" Get_tldr "${page// /-}"
[[ ! -s $cached ]] && Err "tldr page for command $I$page$XI not found" \ [[ ! -s $cached ]] && Err "tldr page for command $I$page$XI not found" \
&& Inf "Contribute new pages at:$XB$URL https://github.com/tldr-pages/tldr$XURL" && exit 24 && Inf "Contribute new pages at:$XB ${URL}https://github.com/tldr-pages/tldr$XURL" && exit 24
((markdown)) && Out "$(cat "$cached")" || Display_tldr "$cached" ((markdown)) && Out "$(cat "$cached")" || Display_tldr "$cached"
} }