#!/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