My dotfiles. Period.

main.bashrc 16KB

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