dotfiles

<-- duh.
git clone https://hhvn.uk/dotfiles
git clone git://hhvn.uk/dotfiles
Log | Files | Refs | Submodules | LICENSE

plumb (5877B)


      1 #!/bin/sh
      2 
      3 echo(){
      4 	printf '%s\n' "$*"
      5 }
      6 
      7 matches(){
      8 	echo "$arg" | grep -Ei "$@" >/dev/null
      9 }
     10 
     11 fmatches(){
     12 	file "$arg" | grep -Ei "$@" >/dev/null
     13 }
     14 
     15 fmagic(){
     16 	isfile "$arg" || return 1
     17 	grep "$1" < "$arg" >/dev/null
     18 }
     19 
     20 _envsubst(){
     21 	str="$*"
     22 
     23 	env |
     24 	while read -r line
     25 	do
     26 		str=$(echo "$str" | awk -v "var=${line%%=*}" -v "val=${line#*=}" '
     27 			{
     28 				regex = sprintf("\\$%s", var)
     29 				gsub(regex, val)
     30 				print
     31 			}'
     32 		)
     33 		echo "$str"
     34 	done | tail -n 1
     35 }
     36 
     37 plumb(){
     38 	t="$1"; shift
     39 	[ $norun -eq 1 ] && return
     40 	export norun=1
     41 	case "$t" in
     42 	gui)
     43 		>/dev/null 2>/dev/null nohup sh -c "$*; rm '$file'" &
     44 		;;
     45 	terminal)
     46 		>/dev/null 2>/dev/null nohup ${TERMINAL:-st} sh -c "$*; rm '$file'" &
     47 		;;
     48 	prompt)
     49 		>/dev/null 2>/dev/null nohup ${TERMINAL:-st} sh -c "$(dmenu -i -p "$*"); rm '$file'" &
     50 		;;
     51 	matchlater)
     52 		export norun=0
     53 		>/dev/null 2>/dev/null nohup sh -c "$*" &
     54 		;;
     55 	*)
     56 		herbe "No such plumb-type: $t"
     57 		;;
     58 	esac
     59 }
     60 
     61 replace(){
     62 	arg=$(echo "$arg" | sed "$*")
     63 }
     64 
     65 isfile(){
     66 	[ -z "$1" ] && {
     67 		[ -f "$arg" ]
     68 		return $?
     69 	}
     70 	[ -n "$1" ] && {
     71 		[ -f "$1" ]
     72 		return $?
     73 	}
     74 }
     75 
     76 hascmd(){
     77 	command -v "$*" >/dev/null
     78 }
     79 
     80 wasfetched(){
     81 	[ -n "$orig" ]
     82 }
     83 
     84 fetch(){
     85 	file="/tmp/plumb.$(basename "$arg")"
     86 	while [ -f $file ]
     87 	do
     88 		file="/tmp/plumb.$(base64 </dev/urandom | tr -d / | head -c10).$(basename "$arg")"
     89 	done
     90 	$proxy curl $([ "$verbose" != "y" ] && echo -s) "$(echo "$arg" | sed -E 's/]|\[|}|\{/\\&/g')" > "$file"
     91 	export orig="$arg"
     92 	export arg="$file"
     93 	removelater "$file"
     94 }
     95 
     96 removelater(){
     97 	[ -z "$exittrap" ] && exittrap="$*"
     98 	exittrap="$exittrap; rm -rf \"$*\""
     99 	trap "$exittrap" EXIT
    100 }
    101 
    102 mime(){
    103 	mime=$($proxy curl -Li$([ "$verbose" != "y" ] && echo s) "$(echo "$arg" | sed -E 's/]|\[|}|\{/\\&/g')" |
    104 		awk '/^HTTP/ && $2 != "200" {s=1}; /^HTTP/ && $2 == "200" {p=1}; /^[[:space:]]*$/ {if (s) s=0; else exit 1}; p' |
    105 		tr '[:upper:]' '[:lower:]' | awk '$1 == "content-type:" {print $2}')
    106 	echo "$mime" | tee /dev/stderr | grep -i "$1" >/dev/null
    107 }
    108 
    109 case "$1" in
    110 	-v)
    111 		verbose=y
    112 		shift
    113 		;;
    114 esac
    115 
    116 [ -n "$PLUMB" ] && exit
    117 export PLUMB="$$"
    118 
    119 for arg in "$@"
    120 do
    121 	export norun=0
    122 	export gui=0
    123 	export proxy=""
    124 	export arg=$(_envsubst "$arg")
    125 	export orig=""
    126 
    127 	# remove file://
    128 	matches "^file://" &&
    129 	replace 's~^file://~~'
    130 
    131 	# network
    132 	matches "://.*\.onion" &&
    133 	export proxy="torsocks"
    134 
    135 	matches "^magnet:" &&
    136 	plumb terminal 'addtorrent "$arg"'
    137 
    138 	matches "^(gopher|http)s?://.*\.(ogg|mp3|opus|flac|pls)$" &&
    139 	plumb terminal '$proxy mpv --pause $arg'
    140 
    141 	matches "^(gopher|http)s?://.*\.gif$" &&
    142 	plumb gui '$proxy mpv --loop-file $arg'
    143 
    144 	matches "(youtu.be|youtube.com).*/feeds/" &&
    145 	plumb gui 'sfeed_addfeed "$arg"'
    146 
    147 	matches "^(gopher|http)s?://.*\.(mkv|mp4|avi|webm|ogv|gifv|mp4|ape|m3u|m3u8)$" ||
    148 	matches "^https?://(www\.|m\.)?(youtube.com|youtu.be)" ||
    149 	matches "^https?://.*/videos/watch/" || # peertube
    150 	matches "^https?://videos?\..*/w/" &&   # peertube also uses /w/, which is so ambiguous I made this subdomain-dependant
    151 	plumb gui 'queuevid "$arg" && $proxy mpv --pause "$arg"'
    152 
    153 	matches "^https?://" &&
    154 	! mime "text/html" &&
    155 	fetch
    156 
    157 	matches "^https?://" ||
    158 	matches "\.html?$" ||
    159 	fmatches "HTML" &&
    160 	plumb gui 'qutebrowser $arg'
    161 
    162 	matches "^gophers?://(.*/[17+0](/|$)|[^/]*$)" &&
    163 	plumb terminal '$proxy zygo $arg'
    164 
    165 	matches "^gophers?://" &&
    166 	fetch
    167 
    168 	matches "^mailto:" &&
    169 	plumb terminal 'neomutt $(echo "$arg" | sed "s~^mailto:~~")'
    170 
    171 	matches "^finger://" &&
    172 	plumb terminal '$proxy finger $(echo "$arg" | sed "s~^finger://~~"); cat'
    173 
    174 	matches "^ssh://" &&
    175 	plumb terminal '$proxy ssh $(echo "$arg" | sed "s~^ssh://~~;s~:[0-9]*~~")'
    176 
    177 	matches "^git://" &&
    178 	plumb terminal '$proxy git clone $arg'
    179 
    180 	# local files now
    181 	fmatches "gzip" &&
    182 	isfile &&
    183 	plumb matchlater 'gunzip < $arg > $arg.new && mv $arg.new $arg' &&
    184 	removelater "$arg.new"
    185 
    186 	fmatches "zip.*archive" &&
    187 	isfile
    188 	plumb matchlater 'unzip -p $arg > $arg.new && mv $arg.new $arg' &&
    189 	removelater "$arg.new"
    190 
    191 	fmatches "PGP.*public.*key|PGP.*ring" &&
    192 	isfile &&
    193 	plumb terminal 'gpg --import $arg; sleep 5'
    194 
    195 	fmatches "PGP.*signature" &&
    196 	isfile &&
    197 	plumb terminal 'gpg --verify $arg; sleep 5'
    198 
    199 	fmatches "PGP.*message|PGP.*encrypted" &&
    200 	isfile &&
    201 	plumb terminal 'gpg -d $arg; sleep 5'
    202 
    203 	matches ".*\.(epub|ps|eps|pdf|dvi|djvu)$" ||
    204 	fmatches "pdf|postscript" &&
    205 	isfile &&
    206 	plumb gui 'zathura $arg'
    207 
    208 	matches ".*\.gif$" &&
    209 	isfile &&
    210 	plumb gui 'mpv --loop-file $arg'
    211 
    212 	matches ".*\.(mkv|mp4|avi|webm|ogg|ogv|gifv|mp3|mp4|opus|flac|ape|m3u|m3u8)$" ||
    213 	fmatches "video|matroska|audio|sound" &&
    214 	isfile &&
    215 	plumb terminal 'mpv --pause $arg'
    216 
    217 	matches ".*\.(jpe?g|gif|tiff?|ppm|bit|bmp|png|xpm)$" ||
    218 	fmatches "image" &&
    219 	isfile &&
    220 	plumb gui 'sxiv $arg'
    221 
    222 	matches "\.?/.*\.[0-9]p?$" &&
    223 	fmatches "(roff|preprocessor)" &&
    224 	isfile &&
    225 	plumb terminal 'man $arg'
    226 
    227 	matches "\.(gph|gophermap)$|(^|/)gophermap$" &&
    228 	isfile &&
    229 	plumb terminal 'cgo -f $arg'
    230 
    231 	matches "\.(atom|rss)$|rss\.xml$|atom\.xml$" ||
    232 	fmatches "atom|rss" ||
    233 	fmagic "<feed.*xmlns.*http://www.w3.org/2005/Atom" ||
    234 	fmagic "<rss" &&
    235 	wasfetched &&
    236 	plumb gui 'sfeed_addfeed $orig'
    237 
    238 	matches "\.(atom|rss)$|rss\.xml$" ||
    239 	fmatches "atom|rss" ||
    240 	fmagic "<feed.*xmlns.*http://www.w3.org/2005/Atom" ||
    241 	fmagic "<rss" &&
    242 	! wasfetched &&
    243 	plumb terminal 'sfeed < $arg | sort -rn | sfeed_curses'
    244 
    245 	# dmarc reports
    246 	fmagic "<feedback" &&
    247 	fmagic "<policy_published" &&
    248 	fmagic "<dkim" &&
    249 	plumb terminal 'dmarc < $arg; cat'
    250 
    251 	# numbered file
    252 	matches ":[0-9][0-9]*$" &&
    253 	isfile ${arg%:*} &&
    254 	plumb terminal 'vim +${arg##*:} ${arg%:*}'
    255 
    256 	# catch all for files
    257 	matches ".*" &&
    258 	isfile &&
    259 	plumb terminal 'vim $arg'
    260 
    261 	# include files
    262 	matches ".*\.h$" &&
    263 	isfile "/usr/include/$arg" &&
    264 	plumb terminal 'vim /usr/include/$arg'
    265 
    266 	matches ".*\.h$" &&
    267 	isfile "/usr/local/include/$arg" &&
    268 	plumb terminal 'vim /usr/local/include/$arg'
    269 
    270 	# catch-all for non-files
    271 	matches ".*" &&
    272 	plumb prompt 'Plumb to (use $arg): '
    273 done
    274 wait