From 6e063013707c452bc0bb998bf70555cd4a1d4afe Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <feedback@starbeamrainbowlabs.com>
Date: Mon, 12 Sep 2016 21:25:59 +0200
Subject: [PATCH] Add bash tldr client

---
 README.md |   5 +-
 tldr      | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 249 insertions(+), 2 deletions(-)
 create mode 100755 tldr

diff --git a/README.md b/README.md
index 2fcc944..f417869 100644
--- a/README.md
+++ b/README.md
@@ -35,8 +35,9 @@ Here's a list of the most interesting ones, along with what they do and where th
  - [cscz](https://git.starbeamrainbowlabs.com/sbrl/cscz) - The one and only C# class generator. A little timesaving tool I built myself, written in C# or course :D
  - [repren](https://github.com/jlevy/repren) - A good bulk file renaming tool.
  - [goldilocks](http://unix.stackexchange.com/a/124460/64687) - A script that displays all of the possible terminal colours.
- - [catimg](https://github.com/posva/catimg) - A cool script to display images in the terminal. Useful when you're sshing into 
-servers.
+ - [catimg](https://github.com/posva/catimg) - A cool script to display images in the terminal. Useful when you're sshing into servers.
+ - [tldr](https://github.com/raylee/tldr) - A bash client for 
+[tldr-pages](https://github.com/tldr-pages/tldr).
 
 ## Disclaimer
 I don't own many of the tools in this repository. If you are an owner of one of these tools and I haven't linked to you, please let me know as I probably forgot.
diff --git a/tldr b/tldr
new file mode 100755
index 0000000..2b294c0
--- /dev/null
+++ b/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 <<EOF
+USAGE: $cmd [options] <command>
+
+[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
+
+<command>
+    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
