From da16b25aafa64ec88948ad5f764736e2abbaaba1 Mon Sep 17 00:00:00 2001 From: Urbain Vaes Date: Mon, 7 Mar 2016 22:41:54 +0000 Subject: Add tldr --- bin/tldr | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100755 bin/tldr diff --git a/bin/tldr b/bin/tldr new file mode 100755 index 0000000..2b294c0 --- /dev/null +++ b/bin/tldr @@ -0,0 +1,246 @@ +#!/bin/bash +# tldr client by Ray Lee, http://github.com/raylee/tldr +# a Sunday afternoon's project, I'm sure there's room for improvement. PRs welcome! + +set -uf -o pipefail + +# initialize globals, sanity check the environment, etc. +config() { + init_term_cmds + + if [ -z $(which curl) ]; then + echo "${red}tldr requires \`curl\` installed in your path$reset" + exit 1 + fi + + configdir=~/.tldr + [ -d ~/.config ] && configdir=~/.config/tldr + + platform=$(get_platform) + base_url="https://raw.githubusercontent.com/tldr-pages/tldr/master/pages" + index_url="http://tldr-pages.github.io/assets/index.json" + index="$configdir/index.json" + cache_days=14 + force_update='' + + #check if config folder exists, otherwise create it + [ -d "$configdir" ] || mkdir -p "$configdir" + + [ ! -f $index ] && update_index + auto_update_index +} + +update_index() { + curl -sf -o "$index" "$index_url" + res=$? + if [ $res -eq 22 ]; then + echo "Could not download index from $index_url" + exit 1 + fi +} + +# if the file exists and is more recent than $cache_days old +recent() { + exists=$(find "$1" -mtime -$cache_days 2>/dev/null) + [ -n "$exists" -a -z "$force_update" ] +} + +auto_update_index() { + recent "$index" || update_index +} + +# function contents via http://mywiki.wooledge.org/BashFAQ/037 +init_term_cmds() { + # only set if we're on an interactive session + [[ -t 2 ]] && { + reset=$( tput sgr0 || tput me ) # Reset cursor + bold=$( tput bold || tput md ) # Start bold + under=$( tput smul || tput us ) # Start underline + italic=$( tput sitm || tput ZH ) # Start italic + eitalic=$( tput ritm || tput ZH ) # End italic + default=$( tput op ) + back=$'\b' + + [[ $TERM != *-m ]] && { + black=$( tput setaf 0 || tput AF 0 ) + red=$( tput setaf 1 || tput AF 1 ) + green=$( tput setaf 2 || tput AF 2 ) + yellow=$( tput setaf 3 || tput AF 3 ) + blue=$( tput setaf 4 || tput AF 4 ) + magenta=$( tput setaf 5 || tput AF 5 ) + cyan=$( tput setaf 6 || tput AF 6 ) + white=$( tput setaf 7 || tput AF 7 ) + + onblue=$( tput setab 4 || tput AB 4 ) + ongrey=$( tput setab 7 || tput AB 7 ) + } + } 2>/dev/null ||: + + # osx's termcap doesn't have italics. The below adds support for iTerm2 + # and is harmless on Terminal.app + [ "$(get_platform)" = "osx" ] && { + italic=$(echo -e "\033[3m") + eitalic=$(echo -e "\033[23m") + } +} + +heading() { + local line="$*" + echo "$bold$red${line:2}$reset" +} + +quotation() { + local line="$*" + echo "$under${line:2}$reset" +} + +list_item() { + local line="$*" + echo "$line$reset" +} + +code() { + local line="$*" + # I'm sure there's a better way to strip the first and last characters. + line="${line:1}" + line="${line%\`}" + # convert {{variable}} to italics + line=${line//\{\{/$italic} + line=${line//\}\}/$eitalic} + + echo "$bold$line$reset" +} + +text() { + local line="$*" + echo "$line" +} + +# an idiot-level recognition of tldr's markdown. Needs improvement, or +# subcontracting out to a markdown -> ANSI formatting command +display_tldr() { + # read one line at a time, don't strip whitespace ('IFS='), and process + # last line even if it doesn't have a newline at the end + while IFS= read -r line || [[ -n "$line" ]]; do + start=${line:0:1} # get the first character + case "$start" in + '#') heading "$line" + ;; + '>') quotation "$line" + ;; + '-') list_item "$line" + ;; + '`') code "$line" + ;; + *) text "$line" + ;; + esac + done +} + +# convert the local platorm name to tldr's version +get_platform() { + case `uname -s` in + Darwin) echo "osx" ;; + Linux) echo "linux" ;; + SunOS) echo "sunos" ;; + *) echo "common" ;; + esac +} + +# extract the platform key from index.json, return preferred subpath to tldrpage +path_for_cmd() { + local desc=$(tr '{' '\n' < $index | grep "\"name\":\"$1\"") + # results in, eg, "name":"netstat","platform":["linux","osx"]}, + + [ -z "$desc" ] && return + + # use the platform specific version of the tldr first + if [[ $desc =~ \"$platform\" ]]; then + echo "$platform/$1.md" + elif [[ $desc =~ \"common\" ]]; then + echo "common/$1.md" + else + # take the first one so we can show something, but warn the user + local p=$(echo "$desc" | cut -d '"' -f 8) + >&2 echo -e "${red}tldr page $1 not found in $platform or common, using page from platform $p instead$reset\n" + echo "$p/$1.md" + fi +} + +# return the local cached copy of the tldrpage, or retrieve and cache from github +get_tldr() { + local p="$(path_for_cmd $1)" + cached="$configdir/$p" + recent "$cached" || { + mkdir -p $(dirname $cached) + curl -sf -o "$cached" "$base_url/$p" + } + # if the curl failed for some reason, keep cat from whinging + cat "$cached" 2>/dev/null +} + + +config + +usage() { + cmd=$(basename $0) + cat < + +[options] + -l, --list: show all available pages + -p, --platform: show page from specific platform rather than autodetecting + -u, --update: update, force retrieving latest copies of locally cached files + -h, -?, --help: this help overview + + + Show examples for this command + +The client caches a copy of all pages and the index locally under +$configdir. By default, the cached copies will expire in $cache_days days. + +EOF +exit 0 +} + +while [ $# -gt 0 ] +do + case "$1" in + -l|--list) + >&2 echo -e "Known tldr pages: \n" + tr '{' '\n' < "$configdir/index.json" | cut -d '"' -f4 | column + exit 0 + ;; + -u|--update) + force_update=yes + update_index + ;; + -h|-\?|--help) + usage + ;; + -p|--platform) + shift + platform=$1 + ;; + -*) + usage + ;; + *) + page=${1:-''} + ;; + esac + shift +done + +[ -z ${page:-} ] && usage + +tldr="$(get_tldr $page)" + +if [ -z "$tldr" ]; then + echo "tldr page for command $page not found" + exit 1 +fi + +display_tldr <<< "$tldr" +echo -- cgit v1.2.3