summaryrefslogtreecommitdiff
path: root/bin/.local
diff options
context:
space:
mode:
authorUrbain Vaes <urbain@vaes.uk>2018-11-16 12:35:55 +0100
committerUrbain Vaes <urbain@vaes.uk>2018-11-16 12:35:55 +0100
commit543c43ea1c8cbb938a5a5bcf06778100ca4c9728 (patch)
treeb5bb5466165fcec8de370b5bd61d4132baf52f2d /bin/.local
parent5b2db8132927bceb9e0907a07ad6e71406f81bbe (diff)
Move ~/bin to ~/.local/bin
Diffstat (limited to 'bin/.local')
-rw-r--r--bin/.local/bin/MIMEmbellish0
-rwxr-xr-xbin/.local/bin/downloads5
-rwxr-xr-xbin/.local/bin/keyboard59
-rwxr-xr-xbin/.local/bin/monitor99
-rwxr-xr-xbin/.local/bin/password7
-rwxr-xr-xbin/.local/bin/references5
-rwxr-xr-xbin/.local/bin/run3
-rwxr-xr-xbin/.local/bin/tldr430
-rwxr-xr-xbin/.local/bin/tmux_attach21
-rwxr-xr-xbin/.local/bin/workspace60
10 files changed, 689 insertions, 0 deletions
diff --git a/bin/.local/bin/MIMEmbellish b/bin/.local/bin/MIMEmbellish
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/.local/bin/MIMEmbellish
diff --git a/bin/.local/bin/downloads b/bin/.local/bin/downloads
new file mode 100755
index 0000000..dfbbd98
--- /dev/null
+++ b/bin/.local/bin/downloads
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+download_dir="$HOME/Downloads"
+target=$(find $download_dir -regex '.*\.\(pdf\|PDF\|djvu\|ps\)' -printf "%T+ %f\n" | sort -r | cut -d' ' -f2- | dmenu -i -p "Open File")
+[[ -n $target ]] && exec zathura "$download_dir/$target"
diff --git a/bin/.local/bin/keyboard b/bin/.local/bin/keyboard
new file mode 100755
index 0000000..11b13d1
--- /dev/null
+++ b/bin/.local/bin/keyboard
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+
+# Key repeat rate
+xset r rate 400 50
+
+# Xcape settings
+killall -9 xcape
+
+# Compose key on left control
+# https://vi.stackexchange.com/questions/2254/what-is-the-easiest-way-to-insert-unicode-characters-into-a-document
+setxkbmap -option compose:ralt
+
+# Dvorak programer
+setxkbmap us -variant dvp
+
+# Make Control_L and 'key 94' (Mode_switch, Multi_key)
+# https://unix.stackexchange.com/questions/55076/what-is-the-mode-switch-modifier-for
+xmodmap -e "remove Control = Control_L"
+xmodmap -e "keycode 94 = Mode_switch"
+xmodmap -e "keysym Control_L = Mode_switch"
+xcape -e 'Mode_switch=Multi_key'
+
+# Make Caps_Lock (Control_L, Escape)
+xmodmap -e "clear Lock"
+xmodmap -e "keysym Caps_Lock = Control_L Control_L"
+xmodmap -e "add Control = Control_L"
+xcape -e 'Control_L=Escape'
+
+# Make Tab (Alt_L, Tab)
+xmodmap -e "keysym Tab = Alt_L"
+xmodmap -e "keycode any = Tab"
+xcape -e 'Alt_L=Tab'
+
+# Make space (Super_L, space)
+xmodmap -e "keysym space = Super_L"
+xmodmap -e "add mod4 = Super_L"
+xmodmap -e "keycode any = space"
+xcape -e 'Super_L=space'
+
+# Make return (Control_R, Return)
+xmodmap -e "keysym Return = Control_R"
+xmodmap -e "add Control = Control_R"
+xmodmap -e "keycode any = Return"
+xcape -e 'Control_R=Return'
+
+# Make eject an Insert
+xmodmap -e "keysym XF86Eject = Insert"
+
+# Numbers
+xmodmap -e "keysym d = d D 0"
+xmodmap -e "keysym m = m M 1"
+xmodmap -e "keysym w = w W 2"
+xmodmap -e "keysym v = v V 3"
+xmodmap -e "keysym h = h H 4"
+xmodmap -e "keysym t = t T 5"
+xmodmap -e "keysym n = n N 6"
+xmodmap -e "keysym g = g G 7"
+xmodmap -e "keysym c = c C 8"
+xmodmap -e "keysym r = r R 9"
diff --git a/bin/.local/bin/monitor b/bin/.local/bin/monitor
new file mode 100755
index 0000000..ce12c04
--- /dev/null
+++ b/bin/.local/bin/monitor
@@ -0,0 +1,99 @@
+#!/usr/bin/env bash
+
+XRANDR=$(which xrandr)
+
+MONITORS=( $( ${XRANDR} | awk '( $2 == "connected" ){ print $1 }' ) )
+
+
+NUM_MONITORS=${#MONITORS[@]}
+
+TITLES=()
+COMMANDS=()
+
+
+function gen_xrandr_only()
+{
+ selected=$1
+
+ cmd="xrandr --output ${MONITORS[$selected]} --auto "
+
+ for entry in $(seq 0 $((${NUM_MONITORS}-1)))
+ do
+ if [ $selected != $entry ]
+ then
+ cmd="$cmd --output ${MONITORS[$entry]} --off"
+ fi
+ done
+
+ echo $cmd
+}
+
+
+
+declare -i index=0
+TILES[$index]="Cancel"
+COMMANDS[$index]="true"
+index+=1
+
+
+for entry in $(seq 0 $((${NUM_MONITORS}-1)))
+do
+ TILES[$index]="Only ${MONITORS[$entry]}"
+ COMMANDS[$index]=$(gen_xrandr_only $entry)
+ index+=1
+done
+
+##
+# Dual screen options
+##
+for entry_a in $(seq 0 $((${NUM_MONITORS}-1)))
+do
+ for entry_b in $(seq 0 $((${NUM_MONITORS}-1)))
+ do
+ if [ $entry_a != $entry_b ]
+ then
+ TILES[$index]="Dual Screen ${MONITORS[$entry_a]} -> ${MONITORS[$entry_b]}"
+ COMMANDS[$index]="xrandr --output ${MONITORS[$entry_a]} --auto \
+ --output ${MONITORS[$entry_b]} --auto --right-of ${MONITORS[$entry_a]}"
+
+ index+=1
+ fi
+ done
+done
+
+
+##
+# Clone monitors
+##
+for entry_a in $(seq 0 $((${NUM_MONITORS}-1)))
+do
+ for entry_b in $(seq 0 $((${NUM_MONITORS}-1)))
+ do
+ if [ $entry_a != $entry_b ]
+ then
+ TILES[$index]="Clone Screen ${MONITORS[$entry_a]} -> ${MONITORS[$entry_b]}"
+ COMMANDS[$index]="xrandr --output ${MONITORS[$entry_a]} --auto \
+ --output ${MONITORS[$entry_b]} --auto --same-as ${MONITORS[$entry_a]}"
+
+ index+=1
+ fi
+ done
+done
+
+
+##
+# Generate entries, where first is key.
+##
+function gen_entries()
+{
+ for a in $(seq 0 $(( ${#TILES[@]} -1 )))
+ do
+ echo $a ${TILES[a]}
+ done
+}
+
+# Call menu
+SEL=$( gen_entries | rofi -dmenu -p "Monitor Setup:" -a 0 -no-custom | awk '{print $1}' )
+
+# Call xrandr
+$( ${COMMANDS[$SEL]} )
diff --git a/bin/.local/bin/password b/bin/.local/bin/password
new file mode 100755
index 0000000..eae4be6
--- /dev/null
+++ b/bin/.local/bin/password
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+# Username in primary, password in clipboard
+
+target=$(find "$HOME/.password-store/" -name "*.gpg" -printf "%P\\n" | dmenu -i -p "Get identifier for")
+basename "$target" .gpg | xclip -i -selection "primary"
+pass show --clip "${target%.gpg}"
diff --git a/bin/.local/bin/references b/bin/.local/bin/references
new file mode 100755
index 0000000..46ff41e
--- /dev/null
+++ b/bin/.local/bin/references
@@ -0,0 +1,5 @@
+#!/bin/bash
+REF_DIR="$HOME/phd/references"
+PDF=$(find $REF_DIR -regex ".*.\(pdf\|djvu\|PDF\|ps\)" -printf "%C@ %P\n" | sort | tac | cut -d' ' -f2-)
+TARGET=$(echo "${PDF//"$REF_DIR/"/}" | dmenu -i -p "Open File")
+[[ -n $TARGET ]] && exec zathura "$REF_DIR/$TARGET"
diff --git a/bin/.local/bin/run b/bin/.local/bin/run
new file mode 100755
index 0000000..43f83ab
--- /dev/null
+++ b/bin/.local/bin/run
@@ -0,0 +1,3 @@
+#!/bin/bash
+target=$(find $HOME/dotfiles/bin/ -type f -not -name ".*" -printf "%f\n" | dmenu -i -p "Run script")
+[[ -n $target ]] && exec $target
diff --git a/bin/.local/bin/tldr b/bin/.local/bin/tldr
new file mode 100755
index 0000000..9e12f41
--- /dev/null
+++ b/bin/.local/bin/tldr
@@ -0,0 +1,430 @@
+#!/usr/bin/env bash
+set +vx -o pipefail
+[[ $- = *i* ]] && echo "Don't source this script!" && return 1
+version='0.35'
+# tldr-bash-client version 0.35
+# Bash client for tldr: community driven man-by-example
+# - forked from Ray Lee, http://github.com/raylee/tldr
+# - modified and expanded by pepa65: http://github.com/pepa65/tldr-bash-client
+# - binary download: http://loof.bid/tldr
+# Requiring: coreutils, grep, unzip, curl/wget, less (optional)
+
+# 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):
+# Colors: Black, Red, Green, Yellow, Blue, Magenta, Cyan, White
+# BG: BlackBG, RedBG, GreenBG, YellowBG, BlueBG, MagentaBG, CyanBG, WhiteBG
+# Modes: Bold, Underline, Italic, Inverse
+# 'Newline' can be added to the style list to add a newline before the element
+# and 'Space' to add a space at the start of the line
+# (style items are separated by space, lower/uppercase mixed allowed)
+: "${TLDR_TITLE_STYLE:= Newline Space Bold Yellow }"
+: "${TLDR_DESCRIPTION_STYLE:= Space Yellow }"
+: "${TLDR_EXAMPLE_STYLE:= Newline Space Bold Green }"
+: "${TLDR_CODE_STYLE:= Space Bold Blue }"
+: "${TLDR_VALUE_ISTYLE:= Space Bold Cyan }"
+# The Value style (above) is an Inline style: doesn't take Newline or Space
+# Inline styles for help text: default, URL, option, platform, command, header
+: "${TLDR_DEFAULT_ISTYLE:= White }"
+: "${TLDR_URL_ISTYLE:= Yellow }"
+: "${TLDR_HEADER_ISTYLE:= Bold }"
+: "${TLDR_OPTION_ISTYLE:= Bold Yellow }"
+: "${TLDR_PLATFORM_ISTYLE:= Bold Blue }"
+: "${TLDR_COMMAND_ISTYLE:= Bold Cyan }"
+: "${TLDR_FILE_ISTYLE:= Bold Magenta }"
+# Color/BG (Newline and Space also allowed) for error and info messages
+: "${TLDR_ERROR_COLOR:= Newline Space Red }"
+: "${TLDR_INFO_COLOR:= Newline Space Green }"
+
+# How many days before freshly downloading a potentially stale page
+: "${TLDR_EXPIRY:= 60 }"
+
+# Alternative location of pages 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
+Usage(){
+ Out "$(cat <<-EOF
+ $HHE$version
+
+ $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)
+
+ ${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-l$XHOP, $HOP--list$XHOP [${HPL}platform$XHPL]: List all pages (from ${HPL}platform$XHPL)
+ $HOP-a$XHOP, $HOP--list-all$XHOP: List all pages from current platform + common
+ $HOP-r$XHOP, $HOP--render$XHOP ${HFI}file$XHFI: Render a local ${HFI}file$XHFI as tldr markdown
+ $HOP-m$XHOP, $HOP--markdown$XHOP ${HCO}command$XHCO: Show the markdown source for ${HCO}command$XHCO
+ $HOP-u$XHOP, $HOP--update$XHOP: Update the pages cache by downloading repo archive
+ $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}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}By default, the cached copies will be freshly downloaded after $HUR${TLDR_EXPIRY// /}$XHUR days.
+ EOF
+ )"
+ exit "${1:-0}"
+}
+
+# $1: keep output; Uses/Sets: stdout
+Out(){ stdout+=$1$N;}
+
+# $1: keep error messages
+Err(){ Out "$ERRNL$ERRSP$ERR$B$1$XB$XERR";}
+
+# $1: keep info messages
+Inf(){ Out "$INFNL$INFSP$INF$B$1$XB$XINF";}
+
+# $1: Style specification; Uses: color xcolor bg xbg mode xmode
+Style(){
+ local -l style
+ STYLES='' XSTYLES='' COLOR='' XCOLOR='' NL='' SP=''
+ for style in $1
+ do
+ [[ $style = newline ]] && NL=$N
+ [[ $style = space ]] && SP=' '
+ COLOR+=${color[$style]:-}${bg[$style]:-}
+ XCOLOR=${xbg[$style]:-}${xcolor[$style]:-}$XCOLOR
+ STYLES+=${color[$style]:-}${bg[$style]:-}${mode[$style]:-}
+ XSTYLES=${xmode[$style]:-}${xbg[$style]:-}${xcolor[$style]:-}$XSTYLES
+ done
+}
+
+# Sets: color xcolor bg xbg mode xmode
+Init_term(){
+ [[ -t 2 ]] && { # only if interactive session (stderr open)
+ B=$'\e[1m' # $(tput bold || tput md) # Start bold
+ XB=$'\e[0m' # End bold (no tput code...)
+ U=$'\e[4m' # $(tput smul || tput us) # Start underline
+ XU=$'\e[24m' # $(tput rmul || tput ue) # End underline
+ I=$'\e[3m' # $(tput sitm || tput ZH) # Start italic
+ XI=$'\e[23m' # $(tput ritm || tput ZR) # End italic
+ R=$'\e[7m' # $(tput smso || tput so) # Start reverse
+ XR=$'\e[27m' # $(tput rmso || tput se) # End reverse
+ #X=$'\e[0m' # $(tput sgr0 || tput me) # End all
+
+ [[ $TERM != *-m ]] && {
+ BLA=$'\e[30m' # $(tput setaf 0 || tput AF 0)
+ RED=$'\e[31m' # $(tput setaf 1 || tput AF 1)
+ GRE=$'\e[32m' # $(tput setaf 2 || tput AF 2)
+ YEL=$'\e[33m' # $(tput setaf 3 || tput AF 3)
+ BLU=$'\e[34m' # $(tput setaf 4 || tput AF 4)
+ MAG=$'\e[35m' # $(tput setaf 5 || tput AF 5)
+ CYA=$'\e[36m' # $(tput setaf 6 || tput AF 6)
+ WHI=$'\e[37m' # $(tput setaf 7 || tput AF 7)
+ DEF=$'\e[39m' # $(tput op)
+ BLAB=$'\e[40m' # $(tput setab 0 || tput AB 0)
+ REDB=$'\e[41m' # $(tput setab 1 || tput AB 1)
+ GREB=$'\e[42m' # $(tput setab 2 || tput AB 2)
+ YELB=$'\e[43m' # $(tput setab 3 || tput AB 3)
+ BLUB=$'\e[44m' # $(tput setab 4 || tput AB 4)
+ MAGB=$'\e[45m' # $(tput setab 5 || tput AB 5)
+ CYAB=$'\e[46m' # $(tput setab 6 || tput AB 6)
+ WHIB=$'\e[47m' # $(tput setab 7 || tput AB 7)
+ DEFB=$'\e[49m' # $(tput op)
+ }
+ }
+
+ declare -A color=(['black']=$BLA ['red']=$RED ['green']=$GRE ['yellow']=$YEL \
+ ['blue']=$BLU ['magenta']=$MAG ['cyan']=$CYA ['white']=$WHI)
+ declare -A xcolor=(['black']=$DEF ['red']=$DEF ['green']=$DEF ['yellow']=$DEF \
+ ['blue']=$DEF ['magenta']=$DEF ['cyan']=$DEF ['white']=$DEF)
+ declare -A bg=(['blackbg']=$BLAB ['redbg']=$REDB ['greenbg']=$GREB ['yellowbg']=$YELB \
+ ['bluebg']=$BLUB ['magentabg']=$MAGB ['cyanbg']=$CYAB ['whitebg']=$WHIB)
+ declare -A xbg=(['blackbg']=$DEFB ['redbg']=$DEFB ['greenbg']=$DEFB ['yellowbg']=$DEFB \
+ ['bluebg']=$DEFB ['magentabg']=$DEFB ['cyanbg']=$DEFB ['whitebg']=$DEFB)
+ declare -A mode=(['bold']=$B ['underline']=$U ['italic']=$I ['inverse']=$R)
+ declare -A xmode=(['bold']=$XB ['underline']=$XU ['italic']=$XI ['inverse']=$XR)
+
+ # the 5 main tldr page styles and error message colors
+ Style "$TLDR_TITLE_STYLE"
+ T=$STYLES XT=$XSTYLES TNL=$NL TSP=$SP
+ Style "$TLDR_DESCRIPTION_STYLE"
+ D=$STYLES XD=$XSTYLES DNL=$NL DSP=$SP
+ Style "$TLDR_EXAMPLE_STYLE"
+ E=$STYLES XE=$XSTYLES ENL=$NL ESP=$SP
+ Style "$TLDR_CODE_STYLE"
+ C=$STYLES XC=$XSTYLES CNL=$NL CSP=$SP
+ Style "$TLDR_VALUE_ISTYLE"
+ V=$STYLES XV=$XSTYLES
+ Style "$TLDR_DEFAULT_ISTYLE"
+ HDE=$STYLES XHDE=$XSTYLES
+ Style "$TLDR_URL_ISTYLE"
+ URL=$STYLES XURL=$XSTYLES
+ HUR=$XHDE$STYLES XHUR=$XSTYLES$HDE
+ Style "$TLDR_OPTION_ISTYLE"
+ HOP=$XHDE$STYLES XHOP=$XSTYLES$HDE
+ Style "$TLDR_PLATFORM_ISTYLE"
+ HPL=$XHDE$STYLES XHPL=$XSTYLES$HDE
+ Style "$TLDR_COMMAND_ISTYLE"
+ HCO=$XHDE$STYLES XHCO=$XSTYLES$HDE
+ Style "$TLDR_FILE_ISTYLE"
+ HFI=$XHDE$STYLES XHFI=$XSTYLES$HDE
+ Style "$TLDR_HEADER_ISTYLE"
+ HHE=$XHDE$STYLES XHHE=$XSTYLES$HDE
+ Style "$TLDR_ERROR_COLOR"
+ ERR=$COLOR XERR=$XCOLOR ERRNL=$NL ERRSP=$SP
+ Style "$TLDR_INFO_COLOR"
+ INF=$COLOR XINF=$XCOLOR INFNL=$NL INFSP=$SP
+}
+
+# $1: page
+Recent(){ find "$1" -mtime -"${TLDR_EXPIRY// /}" >/dev/null 2>&1;}
+
+# Initialize globals, check the environment; Uses: config cachedir version
+# Sets: stdout os version dl
+Config(){
+ type -p less >/dev/null || TLDR_LESS=0
+
+ os=common stdout='' Q='"' N=$'\n'
+ case "$(uname -s)" in
+ Darwin) os='osx' ;;
+ Linux) os='linux' ;;
+ SunOS) os='sunos' ;;
+ esac
+ Init_term
+ [[ $TLDR_LESS = 0 ]] &&
+ trap 'cat <<<"$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"
+
+ # Select download method
+ dl="$(type -p curl) -sLfo" || {
+ dl="$(type -p wget) --max-redirect=20 -qNO" || {
+ Err "tldr requires ${I}curl$XI or ${I}wget$XI installed in your path"
+ exit 3
+ }
+ }
+
+ base_url='https://raw.githubusercontent.com/tldr-pages/tldr/master/pages'
+ zip_url='http://tldr-pages.github.io/assets/tldr.zip'
+
+ read cachedir <<<$TLDR_CACHE
+ [[ $cachedir ]] || {
+ [[ $XDG_DATA_HOME ]] && cachedir=$XDG_DATA_HOME/tldr \
+ || cachedir=$HOME/.local/share/tldr
+ }
+ [[ -d "$cachedir" ]] || mkdir -p "$cachedir" || {
+ Err "Can't create the pages cache location $cachedir"
+ exit 4
+ }
+ index=$cachedir/index.json
+ # update if the file doesn't exists, or if it's older than $TLDR_EXPIRY
+ [[ -f $index ]] && Recent "$index" || Cache_fill 0
+}
+
+# $1: error message; Uses: md REPLY ln
+Unlinted(){
+ 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
+}
+
+# $1: page; Uses: index cachedir base_url platform os dl cached md
+# Sets: cached md
+Get_tldr(){
+ local desc err notfound
+ # convert the local platform name to tldr's version
+ # extract the platform key from index.json, return preferred subpath to page
+ desc=$(tr '{' '\n' <"$index" |grep "\"name\":\"$1\"")
+ # results in, eg, "name":"netstat","platform":["linux","osx"]},
+
+ [[ $desc ]] || return # nothing found
+
+ error=0
+ if [[ $platform ]]
+ then # platform given on commandline
+ [[ ! $desc =~ \"$platform\" ]] && notfound=$I$platform$XI && error=1 || md=$platform/$1.md
+ else # check common
+ [[ $desc =~ \"common\" ]] && md=common/$1.md || { # not in common either
+ [[ $notfound ]] && notfound+=" or "
+ notfound+=${I}common$XI
+ }
+ fi
+ # if no page found yet, try the system platform
+ [[ $md ]] || [[ $platform = $os ]] || {
+ [[ $desc =~ \"$os\" ]] && md=$os/$1.md
+ } || {
+ notfound+=" or $I$os$XI"
+ error=1
+ }
+ # if still no page found, get the first entry in index
+ [[ $md ]] || md=$(cut -d "$Q" -f 8 <<<"$desc")/"$1.md"
+ ((error)) && Err "tldr page $I$1$XI not found in $notfound, from platform $U${md%/*}$XU instead"
+
+ # return the local cached copy of the tldrpage, or retrieve and cache from github
+ cached=$cachedir/$md
+ Recent "$cached" || {
+ mkdir -p "${cached%/*}"
+ $dl "$cached" "$base_url/$md" || Err "Could not download page $I$cached$XI with $dl"
+ }
+}
+
+# $1: text; Uses: page stdout; Sets: ln REPLY
+Display_tldr(){
+ local newfmt len val
+ ln=0 REPLY=''
+ [[ $md ]] || md=$1
+ # Read full lines, and process even when no newline at the end
+ while read -r || [[ $REPLY ]]
+ do
+ ((++ln))
+ ((ln==1)) && {
+ [[ ${REPLY:0:1} = '#' ]] && newfmt=0 || newfmt=1
+ ((newfmt)) && {
+ [[ $REPLY ]] || Unlinted "Empty title"
+ Out "$TNL$TSP$T$REPLY$XT"
+ len=${#REPLY} # title length
+ read -r
+ ((++ln))
+ [[ $REPLY =~ [^=] ]] && Unlinted "Title underline must be equal signs"
+ ((len!=${#REPLY})) && Unlinted "Underline length not equal to title's"
+ read -r
+ ((++ln))
+ }
+ }
+ case "${REPLY:0:1}" in # first character
+ '#') ((newfmt)) && Unlinted "Bad first character"
+ ((${#REPLY} <= 2)) && Unlinted "No title"
+ [[ ! ${REPLY:1:1} = ' ' ]] && Unlinted "2nd character no space"
+ Out "$TNL$TSP$T${REPLY:2}$XT" ;;
+ '>') ((${#REPLY} <= 3)) && Unlinted "No valid desciption"
+ [[ ! ${REPLY:1:1} = ' ' ]] && Unlinted "2nd character no space"
+ [[ ! ${REPLY: -1} = '.' ]] && Unlinted "Description doesn't end in full stop"
+ Out "$DNL$DSP$D${REPLY:2}$XD"
+ DNL='' ;;
+ '-') ((newfmt)) && Unlinted "Bad first character"
+ ((${#REPLY} <= 2)) && Unlinted "No example content"
+ [[ ! ${REPLY:1:1} = ' ' ]] && Unlinted "2nd character no space"
+ Out "$ENL$ESP$E${REPLY:2}$XE" ;;
+ ' ') ((newfmt)) || Unlinted "Bad first character"
+ ((${#REPLY} <= 4)) && Unlinted "No valid code content"
+ [[ ${REPLY:0:4} = ' ' ]] || Unlinted "No four spaces before code"
+ val=${REPLY:4}
+ # Value: convert {{value}}
+ val=${val//\{\{/$CX$V}
+ val=${val//\}\}/$XV$C}
+ Out "$CNL$CSP$C$val$XC" ;;
+ '`') ((newfmt)) && Unlinted "Bad first character"
+ ((${#REPLY} <= 2)) && Unlinted "No valid code content"
+ [[ ! ${REPLY: -1} = '`' ]] && Unlinted "Code doesn't end in backtick"
+ val=${REPLY:1:-1}
+ # Value: convert {{value}}
+ val=${val//\{\{/$CX$V}
+ val=${val//\}\}/$XV$C}
+ Out "$CNL$CSP$C$val$XC" ;;
+ '') continue ;;
+ *) ((newfmt)) || Unlinted "Bad first character"
+ [[ -z $REPLY ]] && Unlinted "No example content"
+ Out "$ENL$ESP$E$REPLY$XE" ;;
+ esac
+ 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
+}
+
+# $1: exit code; Uses: platform index
+List_pages(){
+ local platformtext c1 c2 c3
+ [[ $platform ]] && platformtext="platform $I$platform$XI" ||
+ 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 \
+ <<<$(tr '{' '\n' <"$index" |grep $platform |cut -d "$Q" -f4))"
+ exit "$1"
+}
+
+# $1: exit code; Uses: dl cachedir zip_url
+Cache_fill(){
+ local tmp unzip
+ unzip="$(type -p unzip) -q" || {
+ Err "Unzip is necessary to fill the cache"
+ exit 6
+ }
+ tmp=$(mktemp -d)
+ $dl "$tmp/pages.zip" "$zip_url" || {
+ rm -- "$tmp"
+ Err "Could not download pages archive from $U$zip_url$XU with $dl"
+ exit 7
+ }
+ $unzip "$tmp/pages.zip" -d "$tmp" 'pages/*' || {
+ rm -- "$tmp"
+ Err "Couldn't unzip the cache archive on $tmp/pages.zip"
+ exit 8
+ }
+ rm -rf -- "${cachedir:?}/"*
+ mv -- "$tmp/pages/"* "${cachedir:?}/"
+ rm -rf -- "$tmp"
+ Inf "Pages cached in $U$cachedir$XU"
+ exit "$1"
+}
+
+# $@: commandline parameters; Uses: version cached; Sets: platform page
+Main(){
+ local markdown err nomore='No more command line arguments allowed'
+ Config
+ markdown=0 err=0
+ case "$1" in
+ -l|--list) [[ $2 ]] && {
+ platform=$2
+ [[ ,common,linux,osx,sunos,current, = *,$platform,* ]] || {
+ Err "Unknown platform $I$platform$XI"
+ Usage 9
+ }
+ [[ $3 ]] && Err "$nomore" && err=10
+ }
+ List_pages "$err" ;;
+ -a|--list-all) [[ $2 ]] && Err "$nomore" && err=11
+ platform=current
+ List_pages $err ;;
+ -u|--update) [[ $2 ]] && Err "$nomore" && err=12
+ Cache_fill "$err" ;;
+ -v|--version) [[ $2 ]] && Err "$nomore" && err=13
+ Inf "$version"
+ exit "$err" ;;
+ -r|--render) [[ -z $2 ]] && Err "Specify a file to render" && Usage 14
+ [[ $3 ]] && Err "$nomore" && err=15
+ [[ -f "$2" ]] && {
+ Display_tldr "$2" && exit "$err"
+ Err "A file error occured"
+ exit 16
+ } || Err "No file: ${I}$2$XI" && exit 17 ;;
+ -m|--markdown) shift
+ page=$*
+ [[ -z $page ]] && Err "Specify a page to display" && Usage 18
+ [[ -f "$page" && ${page: -3:3} = .md ]] && Out "$(cat "$page")" && exit 0
+ markdown=1 ;;
+ ''|-h|-\?|--help) [[ $2 ]] && Err "$nomore" && err=19
+ Usage "$err" ;;
+ -*) Err "Unrecognized option $I$1$XI"; Usage 20 ;;
+ *) page=$* ;;
+ esac
+
+ [[ -z $page ]] && Err "No command specified" && Usage 21
+ [[ ${page:0:1} = '-' || $page = *' '-* ]] && Err "Only one option allowed" && Usage 22
+ [[ $page = */* ]] && platform=${page%/*} && page=${page##*/}
+ [[ $platform && ,common,linux,osx,sunos, != *,$platform,* ]] && {
+ Err "Unknown platform $I$platform$XI"
+ Usage 23
+ }
+
+ Get_tldr "${page// /-}"
+ [[ ! -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
+ ((markdown)) && Out "$(cat "$cached")" || Display_tldr "$cached"
+}
+
+Main "$@"
+# The error trap will output the accumulated stdout
+exit 0
diff --git a/bin/.local/bin/tmux_attach b/bin/.local/bin/tmux_attach
new file mode 100755
index 0000000..25d8f12
--- /dev/null
+++ b/bin/.local/bin/tmux_attach
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+SESSIONS=$(tmux list-sessions | cut -d':' -f1)
+ATTACHED_SESSIONS=$(tmux list-sessions | grep attached | cut -d':' -f1)
+TMUXINATOR=$(tmuxinator list | sed '1d' | sed 's/\s\+/\n/g')
+UNION=$(cat <(echo "$SESSIONS") <(echo "$TMUXINATOR") | sort | uniq | sed "/^$/d")
+
+SESSION=$(echo "$UNION" | dmenu -i -p "Session" | tr -d '[:space:]')
+[[ -n $SESSION ]] || exit
+
+# Rename i3 workspace
+# `command -v` to check that i3-msg is a command
+! grep -Fxq "$SESSION" <(echo "$ATTACHED_SESSIONS") \
+ && command -v i3-msg \
+ && "$HOME"/bin/workspace gw "$SESSION"
+
+grep -Fxq "$SESSION" <(echo "$TMUXINATOR") \
+ && COMMAND="tmuxinator start $SESSION" \
+ || COMMAND="tmux new-session -A -s $SESSION"
+
+exec urxvt -e zsh -c "$COMMAND"
diff --git a/bin/.local/bin/workspace b/bin/.local/bin/workspace
new file mode 100755
index 0000000..3685b90
--- /dev/null
+++ b/bin/.local/bin/workspace
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+# List of workspaces
+workspaces=$(i3-msg -t get_workspaces | awk 'BEGIN {
+ RS="(},{)|(\\[{)|(}\\])";
+ FPAT="([^,:]+)|([^,]+{[^}]+})|(\"[^\"]+\")"
+ }
+ $0 !~ "^\\s*$" {
+ gsub(/"/, "", $4)
+ print $2, $4, $8, $11
+ }' | sort)
+
+act_on_container() {
+
+ # Get desired workspace
+ [[ -z $2 ]] && target=$(echo "$workspaces" | awk '{print $2}' | dmenu -i -p "Select workspace") || target=$2
+
+ # Exit if empty
+ [[ -z $target ]] && exit
+
+ # See if target exsits
+ existing_target=$(echo "$workspaces" | awk '{print $2}' | grep -F "$target")
+
+ # If new workspace has to be created
+ if [[ -n "$existing_target" ]]; then
+ target="$existing_target"
+ else
+ # Add number to workspace name (start at 1, but allow 0)
+ new_number=$(echo "$workspaces" | awk '$1!=p+1 && $1!=0 {exit;}{p=$1} END {print p+1}')
+ target=$new_number:$target
+ fi
+
+ # Execute command
+ exec i3-msg "$1" "$target"
+}
+
+act_on_workspace() {
+ focused_number=$(echo "$workspaces" | awk '$3 ~ "true" {print $1}')
+ focused_name=$(echo "$workspaces" | awk '$3 ~ "true" {print $2}' | cut -d":" -f2)
+
+ [[ $1 = 'n' ]] && new_number=$(( (11+focused_number+1) % 11 ))
+ [[ $1 = 'p' ]] && new_number=$(( (11+focused_number-1) % 11 ))
+
+ next=$(echo "${workspaces}" | awk '$1 ~ /'$new_number'/ {print $2}')
+
+ i3-msg rename workspace to "${new_number}":"${focused_name}"
+
+ # ${variable//pattern} replaces all matches of pattern with nothing
+ if [[ ! -z "${next// }" ]]; then
+ name_next=${next#*:}
+ i3-msg "workspace ${next};\
+ rename workspace to ${focused_number}:${name_next};\
+ workspace ${new_number}:${focused_name}"
+ fi
+}
+
+# Command to use
+[[ $1 = 'gw' ]] && act_on_container "workspace" "$2"
+[[ $1 = 'mc' ]] && act_on_container "move container to workspace" "$2"
+[[ $1 = 'mw' ]] && act_on_workspace "$2"