My dotfiles. Period.

main.bashrc 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. #!/bin/bash
  2. ## hack to workaround Fedora/Red Hat bug 878428
  3. #shellcheck disable=SC1091
  4. test -f /usr/share/git-core/contrib/completion/git-prompt.sh \
  5. && . /usr/share/git-core/contrib/completion/git-prompt.sh
  6. #######################################################
  7. ### things to do BEFORE host/user-specific settings ###
  8. #######################################################
  9. ### .... ###
  10. ### SUBZ ###
  11. ### '''' ###
  12. prepend() {
  13. #
  14. # pre-pend $2 to filename $1
  15. #
  16. local path=$1
  17. local prefix=$2
  18. local dirpath
  19. local filename
  20. local abspath
  21. abspath=$(readlink -f "$path")
  22. dirpath=$(dirname "$abspath")
  23. filename=$(basename "$abspath")
  24. echo mv "$path" "$dirpath/$prefix-$filename"
  25. }
  26. smv() {
  27. #
  28. # scp but rm the source
  29. #
  30. local src=$1
  31. local dst=$2
  32. test $# -eq 2 || {
  33. echo "i can only 2 argz!" >&2
  34. return 2
  35. }
  36. scp "$src" "$dst" && rm "$src"
  37. }
  38. smvr() {
  39. #
  40. # smv but recursive
  41. #
  42. local src=$1
  43. local dst=$2
  44. test $# -eq 2 || {
  45. echo "i can only 2 argz!" >&2
  46. return 2
  47. }
  48. scp -r "$src" "$dst" && rm -r "$src"
  49. }
  50. bb() {
  51. #
  52. # Ring the bell
  53. #
  54. local stime=${1:-0}
  55. test "$stime" == 0 || echo -e "sleeping for $BASHUM_COLOR_LGREEN$stime$BASHUM_COLOR_NORMAL"
  56. sleep "$stime"
  57. printf '\a'
  58. }
  59. nn() {
  60. #
  61. # Ring the bell and send notification $1 after $2 time
  62. #
  63. local msg=${1:-this is done}
  64. local stime=$2
  65. bb "$stime"
  66. echo -e "hey, $BASHUM_COLOR_LRED$msg$BASHUM_COLOR_NORMAL"
  67. notify-send -a 'nn()' "hey, $msg"
  68. }
  69. pp() {
  70. #
  71. # Ring the bell and send notification $1 and pause
  72. #
  73. local msg=${1:-this is done}
  74. bb
  75. echo -e "hey, \033[1;31m$msg\033[1;0m!"
  76. notify-send -a 'pp()' "hey, $msg"
  77. read -r junk -p "Press Enter to continue"
  78. }
  79. lrep() {
  80. #
  81. # Print each line on STDIN $1 times
  82. #
  83. local rep=${1:-1}; shift
  84. local line
  85. local n
  86. while read -r line; do
  87. n=$rep
  88. while test "$n" -gt 0;
  89. do
  90. echo "$line"
  91. ((n--))
  92. done
  93. done
  94. }
  95. prep() {
  96. #
  97. # Print STDIN $1 times
  98. #
  99. local rep=${1:-1}; shift
  100. local data
  101. data=$(cat)
  102. n=$rep
  103. while test "$n" -gt 0;
  104. do
  105. echo "$data"
  106. echo
  107. ((n--))
  108. done
  109. }
  110. dt() {
  111. #
  112. # Open $1 new terminals
  113. #
  114. __bashum_run_n "${1:-1}" urxvt
  115. }
  116. dT() {
  117. #
  118. # Open $1 new alterminals
  119. #
  120. __bashum_run_n "${1:-1}" xfce4-terminal
  121. }
  122. hr() {
  123. #
  124. # Make horizontal ruler
  125. #
  126. local i
  127. local line
  128. for i in $(seq 1 "$COLUMNS"); do
  129. case $((i%10)) in
  130. 0) line+='#' ;;
  131. *) line+='-' ;;
  132. esac
  133. done
  134. echo "$line"
  135. echo "$line"
  136. echo "$line"
  137. }
  138. __bashum_run_n() {
  139. #
  140. # Run $2.. in background $1 times
  141. #
  142. local n=${1:-1}; shift
  143. while test "$n" -gt 0;
  144. do
  145. "$@" &
  146. ((n--))
  147. done
  148. }
  149. twice() {
  150. #
  151. # Run $@ two times
  152. #
  153. "$@"
  154. "$@"
  155. }
  156. ckyaml() {
  157. #
  158. # Check if YAML file $1 is loadable
  159. #
  160. local yfile=$1
  161. test -n "$yfile" || { echo "usage: ckyaml FILE.yaml"; return 2; }
  162. python -c 'import yaml; import sys; print(yaml.load(sys.stdin)["this"])' <"$yfile"
  163. }
  164. git() {
  165. #
  166. # /usr/bin/git wrapper just to disable dangerous commands
  167. #
  168. # In particular, `git-am` is a a close typo of my favorite
  169. # aliases `ap` (`git-add --patch`) and `cm` (`git-commit`)
  170. # but it's dangerous to call by accident as it destroys
  171. # workdir changes.
  172. #
  173. if grep -Fwqse "$1" "$GIT_DISABLED_COMMANDS"; then
  174. echo "You don't want this." >&2
  175. return 1
  176. else
  177. command git "$@"
  178. fi
  179. }
  180. grepcl() {
  181. #
  182. # Grep in common chat log files
  183. #
  184. # The order is from older apps to newer as I was moving towards
  185. # weechat.
  186. #
  187. grep "$@" -R \
  188. "$HOME/.config/xchat2/xchatlogs" \
  189. "$HOME/.config/xchat2/scrollback" \
  190. "$HOME/.config/hexchat/logs" \
  191. "$HOME/.config/hexchat/scrollback" \
  192. "$HOME/.local/share/weechat/logs.old" \
  193. "$HOME/.local/share/weechat/logs"
  194. }
  195. grepfx() {
  196. #
  197. # Grep recursively for technical debt
  198. #
  199. # '[F]' hack to avoid matching self
  200. #
  201. grep --color -n \
  202. --exclude-dir 'utils' \
  203. --exclude-dir '.git' \
  204. -o '#[F]IXME:.*' -R "$@"
  205. }
  206. grepr() {
  207. #
  208. # Grep recursively, keeping numbers and ignoring common dirs
  209. #
  210. # Number one tool for refactoring!
  211. #
  212. local p=$1; shift
  213. grep --color -n --exclude-dir=".git" -e "$p" -R "$@"
  214. }
  215. grepr1() {
  216. #
  217. # Like grepr() but only list matching items in this directory
  218. #
  219. # Ie. list only files in current directory or names of subdirectories
  220. # where matches were found "somewhere".
  221. #
  222. grepr "$@" -l | cut -d/ -f1 | uniq
  223. }
  224. greph() {
  225. #
  226. # Grep through bash history
  227. #
  228. history | sed 's/^ *//; s/ / /' | cut -d' ' -f2- | grep "$@"
  229. }
  230. gitcd() {
  231. #
  232. # Deep in git repo, cd to the git root
  233. #
  234. cd "$(git rev-parse --show-toplevel)" || return 1
  235. }
  236. clsz() {
  237. #
  238. # Clear screen and move the prompt to bottom
  239. #
  240. tput clear; tput cup "$(tput lines)" 0
  241. }
  242. bcdiff() {
  243. #
  244. # Call bcompare only if objects actually differ
  245. #
  246. test $# -eq 2 && diff "$@" >/dev/null && return
  247. bcompare "$@" &
  248. }
  249. strip_colors() {
  250. #
  251. # Strip color codes from stdin
  252. #
  253. # Stolen from http://unix.stackexchange.com/a/4533/9365
  254. #
  255. sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g'
  256. }
  257. vims() {
  258. #
  259. # List Vim .swp files in a nice table
  260. #
  261. # **Note:** For this ro work, you need to set up Vim to
  262. # use same swap directory as assigned below. this can
  263. # be achieved by addoing section such as this to your
  264. # .vimrc:
  265. #
  266. # if isdirectory($HOME . '/.local/share/vim') == 0
  267. # :silent !mkdir -p ~/.vim/swap >/dev/null 2>&1
  268. # endif
  269. # set directory=./.vim-swap//
  270. # set directory+=~/.local/share/vim/swap//
  271. # set directory+=~/tmp//
  272. # set directory+=.
  273. #
  274. # Call this after crash or poweroff to remind yourself what
  275. # files you were editing before fact. Example:
  276. #
  277. # 2015-07-10 06:10:48.603953758 +0200 ~/TODO.todo
  278. #
  279. # This should make it easier to recover after a little
  280. # disaster.
  281. #
  282. local swap="$HOME/.local/share/vim/swap"
  283. #shellcheck disable=SC1117
  284. find "$swap" -type f -print0 \
  285. | xargs -0 -r stat -c "%y %n" \
  286. | sed "
  287. s| $swap/| |
  288. s|%|/|g
  289. s|.swp$||
  290. s| $HOME| ~|
  291. s| \(..:..\):[^ ]* +.... | \\1 |
  292. " \
  293. | sort \
  294. | tac
  295. }
  296. fixnl() {
  297. #
  298. # Fix newlines in stdin and pass to stdout
  299. #
  300. # Note: We need to read whole stdin; this cannot work
  301. # for infinite stream.
  302. #
  303. # Fix annoying cases:
  304. #
  305. # * If multi-line text is missing newline at the
  306. # end---add the missing newline.
  307. #
  308. # * If -c is passed, and single-line text does have
  309. # a newline at the end, remove it.
  310. #
  311. # This will not touch properly terminated multi-line texts,
  312. # or zero-line texts (ie. oly chars with no newline at all).
  313. #
  314. local arg=$1 # argument passed
  315. local cache # cache to keep stream in
  316. local nlcount # count of newlines in the stream
  317. local lastchr # hex dump (2-digit, lowercase) of last char
  318. local single=keep # single-line streams:
  319. # keep: do nothing
  320. # chop: drop last char if it's a LF
  321. case $arg in
  322. -c|--chop-single) single=chop ;;
  323. esac
  324. cache="$(mktemp -t fixnl.XXXXXXXX)"
  325. cat >"$cache"
  326. nlcount=$(<"$cache" wc -l)
  327. lastchr=$(<"$cache" tail -c1 | hexdump -e '"%02x"')
  328. case $nlcount:$lastchr:$single in
  329. 0:??:*) cat "$cache" ;; # 'abc' => keep as is
  330. 1:0a:chop) head -c -1 "$cache" ;; # 'abc\n' => -c passed: chop!
  331. 1:0a:keep) cat "$cache" ;; # 'abc\n' => keep as is
  332. *:0a:*) cat "$cache" ;; # 'a\nb\nc\n' => keep as is
  333. *:??:*) cat "$cache"; echo ;; # 'a\nb\nc' => add the missing NL
  334. esac
  335. rm "$cache"
  336. }
  337. nlfor() {
  338. #
  339. # Replace $1 (or blank space) with newlines and fix final newline
  340. #
  341. # Shorthand for commonly used tr syntax. Example:
  342. #
  343. # $ echo "$PATH" | nlat :
  344. # /foo
  345. # /bar
  346. # $
  347. #
  348. # is almost like `tr : '\n'` except that it is a bit easier
  349. # to type and fixes the annoying problem with missing
  350. # newline at the end of the replaced string.
  351. #
  352. local char=$1
  353. test -n "$char" || char='[:blank:]'
  354. tr "$char" '\n' \
  355. | fixnl
  356. }
  357. nljoin() {
  358. #
  359. # Join lines with $1 (or space)
  360. #
  361. # Shorthand for commonly used tr syntax. Example:
  362. #
  363. # $ { echo foo; echo bar; } | nljoin :
  364. #
  365. # is almost like `tr '\n' :` except that it is a bit easier
  366. # to type and fixes the annoying problem with extraneous
  367. # newline/colon at the end of final string.
  368. #
  369. local char=$1
  370. test -n "$char" || char=' '
  371. tr '\n' "$char" \
  372. | sed "s/$char*$//" \
  373. | fixnl -c
  374. }
  375. urle() {
  376. #
  377. # Encode or decode (if $1 is '-d') message on stdin as URL encode
  378. #
  379. local fn=quote
  380. case $1 in
  381. -d) fn=unquote ;;
  382. -*) echo 'usage: urle [-d] <text' >&2; return 2 ;;
  383. esac
  384. python3 -c "import sys; from urllib.parse import $fn; print($fn(sys.stdin.read()));"
  385. }
  386. qpr() {
  387. #
  388. # Encode or decode (if $1 is '-d') message on stdin as Quoted Printable
  389. #
  390. local fn=encode
  391. case $1 in
  392. -d) fn=decode ;;
  393. -*) echo 'usage: qpr [-d] <text' >&2; return 2 ;;
  394. esac
  395. perl -MMIME::QuotedPrint -pe "\$_=MIME::QuotedPrint::$fn(\$_);"
  396. }
  397. xop() {
  398. #
  399. # Common clipboard operations with fixnl() on top
  400. #
  401. local op=$1
  402. local file=${2:-/dev/stdin}
  403. case $op in
  404. oo) xclip -selection clipboard -o | fixnl ;;
  405. o) xclip -o | fixnl ;;
  406. ii) fixnl -c | xclip -selection clipboard -i ;;
  407. i) fixnl -c | xclip -i ;;
  408. esac <"$file"
  409. }
  410. xod() {
  411. #
  412. # Like mktemp but get the content from clipboard
  413. #
  414. # Dump xo in a file named $1 somewhere in /tmp; echo the path
  415. # usage: scp $(xod useful_name.txt) eg:some/shared/place
  416. # instead of:
  417. #
  418. # xo > useful_name.txt
  419. # scp useful_name.txt eg:some/shared/place
  420. # rm useful_name.txt
  421. #
  422. local name="${1:-clipboard_dump.txt}"
  423. local tmp
  424. tmp=$(mktemp -d -t "xod.XXXXXXXX")
  425. xclip -o > "$tmp/$name"
  426. echo "$tmp/$name"
  427. }
  428. xood() {
  429. #
  430. # Just like xod() but using xoo (i.e. 'clipboard' clipboard)
  431. #
  432. local name="${1:-clipboard_dump.txt}"
  433. local tmp
  434. tmp=$(mktemp -d -t "xood.XXXXXXXX")
  435. xclip -selection clipboard -o > "$tmp/$name"
  436. echo "$tmp/$name"
  437. }
  438. xl() {
  439. #
  440. # Show primary clipboard in less(1)
  441. #
  442. xop o | less -S
  443. }
  444. xxl() {
  445. #
  446. # Show C-C clipboard in less(1)
  447. #
  448. xop oo | less -S
  449. }
  450. xvxx() {
  451. #
  452. # Edit text in primary clipboard and save it to C-C clipboard
  453. #
  454. # Ideal for editing snippets in browser-based editors: during editing,
  455. # select the text, open terminal, call `xvxx`, edit the text, move
  456. # back to the browser and paste it over the old (still selected) text.
  457. # That's it, no need to make up and save temporary files.
  458. #
  459. # If you quickly realize you need to re-edit the text, use xvvx().
  460. #
  461. xop o | vipe | xop ii
  462. }
  463. xcp() {
  464. #
  465. # Copy paths of $@ to clipboard
  466. #
  467. local path
  468. find "$@" -maxdepth 0 -mindepth 0 \
  469. | while read -r path; do
  470. readlink -e "$path"
  471. done \
  472. | xop i
  473. }
  474. xpst() {
  475. #
  476. # Paste paths from clipboard
  477. #
  478. { xop o; echo; } \
  479. | while read -r path; do
  480. echo "path='$path'" >&2
  481. test -e "$path" || {
  482. echo "does not exist: $path"
  483. continue
  484. }
  485. cp -r "$path" .
  486. done
  487. }
  488. xvb() {
  489. #
  490. # Edit text in primary clipboard and run it using bash
  491. #
  492. xop o | vipe | bash
  493. }
  494. xxvb() {
  495. #
  496. # Edit text in C-C clipboard and run it using bash
  497. #
  498. xop oo | vipe | bash
  499. }
  500. vxx() {
  501. #
  502. # Edit text on stdin and save it to C-C clipboard
  503. #
  504. # Ideal for editing outut of command before pasting ot to browser
  505. # or another GUI application. Run the command with `vxx`, edit
  506. # the text, move back to the application and paste it.
  507. #
  508. # If you quickly realize you need to re-edit the text, use xvvx().
  509. #
  510. vipe | xop ii
  511. }
  512. xcxx() {
  513. #
  514. # Filter text in primary clipboard using command $@ and save it to C-C clipboard
  515. #
  516. # Similar to xvvx() but instead of interactive editing, provided filter
  517. # command is run.
  518. #
  519. local cmd=("$@")
  520. xop o | "${cmd[@]}" | xop ii
  521. return "${PIPESTATUS[1]}"
  522. }
  523. vx() {
  524. #
  525. # Edit stdin and save it to primary clipboard
  526. #
  527. # Ideal for selecting snippets of output of arbitrary commands.
  528. # select the text, open terminal, call `xvx`, edit the text, move
  529. # back to the browser and paste it over the old (still selected) text.
  530. # That's it, no need to make up and save temporary files.
  531. #
  532. vipe | xop i
  533. }
  534. xxvxx() {
  535. #
  536. # Edit text in C-C clipboard and save it back
  537. #
  538. xop oo | vipe | xop ii
  539. }
  540. yt2ogg() {
  541. #
  542. # Download YouTube video as vorbis audio
  543. #
  544. local url=$1
  545. youtube-dl -x --audio-format vorbis "$url"
  546. }
  547. yum_hasbin() {
  548. #
  549. # Ask yum who has bin $1 (and make the output actually readable)
  550. #
  551. local bname
  552. for bname in "$@";
  553. do
  554. case $bname in
  555. */*) dnf provides "$bname" ;;
  556. *) dnf provides "*/bin/$bname" ;;
  557. esac \
  558. | grep '^.' \
  559. | grep -E '^[[:alnum:]_:.-]+ :'
  560. done
  561. }
  562. cal() {
  563. #
  564. # cal with the proper version pick
  565. #
  566. local cal_v
  567. local cal_es
  568. cal_v=$(command cal -V 2>/dev/null); cal_es=$?
  569. case $cal_es:$cal_v in
  570. 0:cal\ from\ util-linux\ 2.*)
  571. command cal --color=always --monday --week "$@"
  572. ;;
  573. 64:*)
  574. command cal -M "$@"
  575. ;;
  576. esac
  577. }
  578. ### .... ###
  579. ### BASH ###
  580. ### '''' ###
  581. HISTCONTROL=ignoredups:erasedups
  582. # shopt -s histappend
  583. # PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
  584. HISTIGNORE="$HISTIGNORE:ls:ll:la:cd"
  585. HISTIGNORE="$HISTIGNORE:git st"
  586. HISTIGNORE="$HISTIGNORE:se *:sc *"
  587. HISTSIZE=33333
  588. HISTFILESIZE=33333
  589. HISTTIMEFORMAT='%F %T '
  590. GLOBIGNORE=.:..
  591. # shopt -s histverify
  592. # some more aliases
  593. alias cls='clear'
  594. alias czkrates='czkrates -v'
  595. alias ll='ls -lh'
  596. alias lla='ls -lha'
  597. alias lr='ll -lhrt'
  598. alias open='xdg-open'
  599. alias diff='colordiff -u'
  600. alias dmesg='dmesg --time-format iso'
  601. alias pad4='sed -e "/./s/^/ /"'
  602. alias mkittool='mkittool -v'
  603. alias grep='grep --color'
  604. alias sc='se --direction encz.cz'
  605. alias taskm='task modify'
  606. alias tasks='task rc.context:none'
  607. alias ts='ts "%F %T"'
  608. alias lsblk='lsblk -o +UUID,LABEL'
  609. alias pstree='pstree -h'
  610. alias virsh='virsh --connect qemu:///system'
  611. alias wttr='curl -s "wttr.in/?1&n&q"'
  612. alias xaa='xclip -o | audit2allow'
  613. alias xi='xop i'
  614. alias xii='xop ii'
  615. alias xo='xop o'
  616. alias xoo='xop oo'
  617. alias reboot="echo -n . ; sync ; echo -n . ; sync ; echo -n . ; systemctl reboot"
  618. alias poweroff="echo -n . ; sync ; echo -n . ; sync ; echo -n . ; systemctl poweroff"
  619. x4x() {
  620. #
  621. # Pad text from primary clipboard with 4 spaces; save to C-C clipboard
  622. #
  623. # ...that is, for inclusion as Markdown verbatim text.
  624. #
  625. xo | pad4 | xii
  626. }
  627. BASHUM__RV_TMP="/tmp/bashum-rv"
  628. mkdir -p "$BASHUM__RV_TMP"
  629. ### ...... ###
  630. ### OTHERS ###
  631. ### '''''' ###
  632. export LC_COLLATE=C # make sort upper first
  633. export EDITOR=vim
  634. export LESSOPEN="| /usr/bin/src-hilite-lesspipe.sh %s"
  635. export LESS=' -R '
  636. export NEATY=color
  637. export PRETTY=color
  638. export PRETTY_DEBUG_EXCLUDE=inigrep
  639. export MDVIMB__CONVERTER=cmark
  640. export MDVIMB__STYLE=darkzen # pergamen
  641. #shellcheck disable=SC2034
  642. {
  643. GIT_PS1_SHOWDIRTYSTATE=true
  644. GIT_PS1_SHOWUNTRACKEDFILES=true
  645. __SATURNIN_COMPLETE_DEBUG=true
  646. GIT_DISABLED_COMMANDS="$HOME/.gittum/disabled-commands"
  647. }
  648. export GIT_PAGER='less -S'
  649. # disable mounting things like SFTP to ~/.gvfs when accessed
  650. # via GIO (used by nautilus etc.)
  651. export GVFS_DISABLE_FUSE=1
  652. # disable the terrible beep sound (only for X; for tty?, blacklist pcspkr)
  653. xhost >& /dev/null && xset b off
  654. # get rid of those .pyc files once and for all
  655. export PYTHONDONTWRITEBYTECODE=1
  656. ssh-add -l >& /dev/null || ssh-add