devinteske

lolcat for bash/zsh

May 19th, 2020
766
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 13.04 KB | None | 0 0
  1. # -*- tab-width:  4 -*- ;; Emacs
  2. # vi: set tabstop=8     :: Vi/ViM
  3. #
  4. # zsh_profile for mailtime
  5. #   Author:      Devin Teske <dteske@freebsd.org>
  6. #   Last Change: 2020 May 19
  7. ############################################################ GLOBALS
  8.  
  9. #
  10. # Global exit status variables
  11. #
  12. export SUCCESS=0
  13. export FAILURE=1
  14.  
  15. #
  16. # Are we running interactively?
  17. #
  18. interactive=
  19. case "$-" in
  20. *i*) interactive=1
  21. esac
  22.  
  23. #
  24. # Is filename globbing enabled?
  25. #
  26. if [ "$ZSH_NAME" ]; then
  27.     glob=
  28.     setopt shwordsplit
  29. else
  30.     glob=1
  31.     case "$SHELLOPTS" in noglob|*:noglob:*|*:noglob) glob= ;; esac
  32. fi
  33.  
  34. #
  35. # OS Specifics
  36. # NB: Requires uname(1) -- from base system
  37. #
  38. : ${UNAME_s:=$(uname -s)}
  39.  
  40. #
  41. # Fix lolcat to work properly in local XTerm
  42. #
  43. [ "$TERM" != "${TERM#xterm}" -a ! "$SSH_CLIENT" ] && stty tab0
  44.  
  45. #
  46. # bash(1) builtin's we should pass to $LOLCAT [lolcat]
  47. #
  48. LOL_BUILTINS='cd dirs echo help popd printf pushd pwd shopt times type'
  49. _LOL_BUILTINS=
  50. [ "$glob" ] && set -f
  51. for _prog in $LOL_BUILTINS; do
  52.     _LOL_BUILTINS="$_LOL_BUILTINS|$_prog"
  53. done
  54. unset _prog
  55. _LOL_BUILTINS="${_LOL_BUILTINS#|}"
  56. [ "$glob" ] && set +f
  57.  
  58. #
  59. # External programs we should NOT pass to $LOLCAT [lolcat]
  60. #
  61. NOLOL_PROGS='
  62.     adduser arc
  63.     bashbug bc bitchx bsdconfig bsdinstall
  64.     condy cscope csh cvsbug
  65.     dd dialog dpv
  66.     edit edquota ee emacs* env etcupdate ex
  67.     freebsd-update fsdb *ftp fvwm-bug
  68.     *gdb*
  69.     *hx
  70.     iftop irssi
  71.     *key *keys
  72.     lldb *login lolcat ls
  73.     Mail mail* *man* mping mysql
  74.     nano ngctl nvi
  75.     perlbug perlthanks pico pppctl psql
  76.     rcp *run
  77.     sade *scp screen shgid sr srvi *ssh* su sudo* sysinstall systat
  78.     talk tcsh *telnet tmux tzsetup
  79.     vi *view vigr *vim* vipw visudo
  80.     watch
  81.     zsh
  82. ' # NOLOL_PROGS
  83. _NOLOL_PROGS=
  84. [ "$glob" ] && set -f
  85. for _prog in $NOLOL_PROGS; do
  86.     _NOLOL_PROGS="$_NOLOL_PROGS|$_prog"
  87. done
  88. unset _prog
  89. _NOLOL_PROGS="${_NOLOL_PROGS#|}"
  90. [ "$glob" ] && set +f
  91.  
  92. #
  93. # Commands we should pass to $LOLCAT [lolcat]
  94. #
  95. LOL_CMDS='
  96.     # One case pattern per-line; no inline comments
  97.     # NB: Whitespace needs to be escaped or quoted
  98.     # NB: Patterns implicitly allow trailing args
  99.  
  100.     # Non-interactive commands
  101.     "*bash -c"
  102.     "*bash -xc"
  103.     "*bash "*" -c"
  104.     "python -c"
  105.     "python "*" -c"
  106.     "R [a-zA-Z]*"
  107.     "sh -c"
  108.     "sh -xc"
  109.     "sh "*" -c"
  110.     "zsh -c"
  111.     "zsh -xc"
  112.     "zsh "*" -c"
  113.  
  114.     # FreeBSD commands
  115.     "wpa_cli [a-z]*"
  116.  
  117.     # FreeBSD pkg(8) commands
  118.     "pkg annotate -y"
  119.     "pkg annotate "*" -y"
  120.     "pkg annotate --yes"
  121.     "pkg annotate "*" --yes"
  122.     "pkg autoremove -y"
  123.     "pkg autoremove "*" -y"
  124.     "pkg autoremove --yes"
  125.     "pkg autoremove "*" --yes"
  126.     "pkg check -y"
  127.     "pkg check "*" -y"
  128.     "pkg check --yes"
  129.     "pkg check "*" --yes"
  130.     "pkg clean -y"
  131.     "pkg clean "*" -y"
  132.     "pkg clean --yes"
  133.     "pkg clean "*" --yes"
  134.     "pkg delete -y"
  135.     "pkg delete "*" -y"
  136.     "pkg delete --yes"
  137.     "pkg delete "*" --yes"
  138.     "pkg fetch -y"
  139.     "pkg fetch "*" -y"
  140.     "pkg fetch --yes"
  141.     "pkg fetch "*" --yes"
  142.     "pkg install -y"
  143.     "pkg install "*" -y"
  144.     "pkg install --yes"
  145.     "pkg install "*" --yes"
  146.     "pkg lock -y"
  147.     "pkg lock "*" -y"
  148.     "pkg lock --yes"
  149.     "pkg lock "*" --yes"
  150.     "pkg remove -y"
  151.     "pkg remove "*" -y"
  152.     "pkg remove --yes"
  153.     "pkg remove "*" --yes"
  154.     "pkg unlock -y"
  155.     "pkg unlock "*" -y"
  156.     "pkg unlock --yes"
  157.     "pkg unlock "*" --yes"
  158.     "pkg upgrade -y"
  159.     "pkg upgrade "*" -y"
  160.     "pkg upgrade --yes"
  161.     "pkg upgrade "*" --yes"
  162.  
  163.     # VCS commands
  164.     "cvs ci -m"
  165.     "cvs ci "*" -m"
  166.     "cvs commit -m"
  167.     "cvs commit "*" -m"
  168.     "git commit -m"
  169.     "git commit "*" -m"
  170.     "git commit --message"
  171.     "git commit "*" --message"
  172.     "git commit --no-edit"
  173.     "git commit "*" --no-edit"
  174.     "git revert --no-edit"
  175.     "git revert "*" --no-edit"
  176.     "p4 branch -"[dio]
  177.     "p4 branch "*" -"[dio]
  178.     "p4 change -"[dio]
  179.     "p4 change "*" -"[dio]
  180.     "p4 changelist -"[dio]
  181.     "p4 changelist "*" -"[dio]
  182.     "p4 client -"[dio]
  183.     "p4 client "*" -"[dio]
  184.     "p4 depot -"[dio]
  185.     "p4 depot "*" -"[dio]
  186.     "p4 job -"[dio]
  187.     "p4 job "*" -"[dio]
  188.     "p4 label -"[dio]
  189.     "p4 label "*" -"[dio]
  190.     "p4 protect -"[io]
  191.     "p4 protect "*" -"[io]
  192.     "p4 resolve -a"[mty]
  193.     "p4 resolve "*" -a"[mty]
  194.     "p4 stream -"[dio]
  195.     "p4 stream "*" -"[dio]
  196.     "p4 submit -"[di]
  197.     "p4 submit "*" -"[di]
  198.     "p4 user -"[dio]
  199.     "p4 user "*" -"[dio]
  200.     "p4 workspace -"[dio]
  201.     "p4 workspace "*" -"[dio]
  202.     "svn ci -m"
  203.     "svn ci "*" -m"
  204.     "svn ci --message"
  205.     "svn ci "*" --message"
  206.     "svn ci --non-interactive"
  207.     "svn ci "*" --non-interactive"
  208.     "svn commit -m"
  209.     "svn commit "*" -m"
  210.     "svn commit --message"
  211.     "svn commit "*" --message"
  212.     "svn commit --non-interactive"
  213.     "svn ci "*" --non-interactive"
  214.     "svnlite ci -m"
  215.     "svnlite ci "*" -m"
  216.     "svnlite ci --message"
  217.     "svnlite ci "*" --message"
  218.     "svnlite ci --non-interactive"
  219.     "svnlite ci "*" --non-interactive"
  220.     "svnlite commit -m"
  221.     "svnlite commit "*" -m"
  222.     "svnlite commit --message"
  223.     "svnlite commit "*" --message"
  224.     "svnlite commit --non-interactive"
  225.     "svnlite ci "*" --non-interactive"
  226.  
  227. ' # LOL_CMDS
  228. _LOL_CMDS=$( echo "$LOL_CMDS" |
  229.     while read -r _cmd; do
  230.         [ "${_cmd:-x}" = "${_cmd#\#}" ] || continue
  231.         echo -n "|$_cmd|$_cmd\[\$IFS]*"
  232.     done
  233. )
  234. _LOL_CMDS="${_LOL_CMDS#|}"
  235.  
  236. #
  237. # Commands we should NOT pass to $LOLCAT [lolcat]
  238. #
  239. NOLOL_CMDS='
  240.     # One case pattern per-line; no inline comments
  241.     # NB: Whitespace needs to be escaped or quoted
  242.     # NB: Patterns implicitly allow trailing args
  243.  
  244.     # Commands containing pipe
  245.     *"|"*
  246.  
  247.     # Interactive commands
  248.     *"bash"
  249.     "python"
  250.     "R"
  251.     "sh"
  252.     "zsh"
  253.  
  254.     # General commands that launch $EDITOR or behave interactively
  255.     "crontab -e"
  256.     "crontab "*" -e"
  257.     "sdiff -o"
  258.     "sdiff "*" -o"
  259.  
  260.     # FreeBSD specific commands that launch $EDITOR or behave interactively
  261.     "bsdlabel -e"
  262.     "camcontrol modepage "*" -e"
  263.     "disklabel -e"
  264.     "gbde init "*" -i"
  265.     "gvinum create"
  266.     "make config"
  267.     "make import"
  268.     "wpa_cli"
  269.  
  270.     # FreeBSD pkg(8) commands that either prompt or show progress
  271.     "pkg annotate"
  272.     "pkg autoremove"
  273.     "pkg check"
  274.     "pkg clean"
  275.     "pkg delete"
  276.     "pkg fetch"
  277.     "pkg install"
  278.     "pkg lock"
  279.     "pkg remove"
  280.     "pkg shell"
  281.     "pkg unlock"
  282.     "pkg upgrade"
  283.  
  284.     # VCS commands that launch $EDITOR or behave interactively
  285.     "cvs ci"
  286.     "cvs commit"
  287.     "git commit"
  288.     "git help"
  289.     "git rebase -i"
  290.     "git rebase "*" -i"
  291.     "git rebase --interactive"
  292.     "git rebase "*" --interactive"
  293.     "git revert"
  294.     "p4 attribute -i"
  295.     "p4 attribute "*" -i"
  296.     "p4 branch"
  297.     "p4 change"
  298.     "p4 changelist"
  299.     "p4 client"
  300.     "p4 depot"
  301.     "p4 job"
  302.     "p4 label"
  303.     "p4 login"
  304.     "p4 passwd"
  305.     "p4 protect"
  306.     "p4 resolve"
  307.     "p4 stream"
  308.     "p4 submit"
  309.     "p4 user"
  310.     "p4 workspace"
  311.     "svn ci"
  312.     "svn commit"
  313.     "svnlite ci"
  314.     "svnlite commit"
  315.  
  316.     # Other commands that behave interactively
  317.     "make chroot_shell"
  318.     "make "*" chroot_shell"
  319.     "make distclean"
  320.     "make "*" distclean"
  321.     "make remove_chroot"
  322.     "make "*" remove_chroot"
  323.  
  324. ' # NOLOL_CMDS
  325. _NOLOL_CMDS=$( echo "$NOLOL_CMDS" |
  326.     while read -r _cmd; do
  327.         [ "${_cmd:-x}" = "${_cmd#\#}" ] || continue
  328.         echo -n "|$_cmd|$_cmd\[\$IFS]*"
  329.     done
  330. )
  331. _NOLOL_CMDS="${_NOLOL_CMDS#|}"
  332.  
  333. ############################################################ FUNCTIONS
  334.  
  335. unalias quietly 2> /dev/null
  336. quietly() { "$@" > /dev/null 2>&1; }
  337.  
  338. quietly unalias have
  339. have() { type "$@" > /dev/null 2>&1; }
  340.  
  341. # lolexec [$command [$args ...]]
  342. #
  343. # Create a wrapper function for $command, sending output to `lolcat' (or
  344. # `cowsay') transparently. To make this execute for all commands, automatically
  345. # sending all output to lolcat, make this function the DEBUG trap.
  346. #
  347. # For example:
  348. #   trap lolexec DEBUG
  349. #
  350. # When trapped as the DEBUG routine in bash, any/all command lines that...
  351. #   + Do NOT contain the pipe character
  352. #   + Do NOT start with an exclamation point by-itself (e.g., "! top")
  353. # ... will have their output sent to lolcat.
  354. #
  355. # NB: Requires awk(1) -- from base system
  356. #
  357. if [ "$ZSH_NAME" ]; then
  358.     preexec() { lolexec "$1"; }
  359.     precmd() { trap - DEBUG; }
  360.     type_t() {
  361.         case "$( builtin type "$@" 2> /dev/null )" in
  362.         *" is a shell function") builtin echo function ;;
  363.         *" is an alias for "*) builtin echo alias ;;
  364.         *" is a shell builtin") builtin echo builtin ;;
  365.         *" is a reserved word") builtin echo keyword ;;
  366.         *" is /"*) builtin echo file ;;
  367.         *) builtin echo unknown
  368.         esac
  369.     }
  370. else
  371.     type_t() { builtin type -t "$@" 2> /dev/null; }
  372.     LOLEXEC='[ "$( trap -p DEBUG )" ]'
  373.     LOLEXEC="$LOLEXEC || trap \"trap - DEBUG; lolexec\" DEBUG"
  374. fi
  375. alias -- +lol='trap - DEBUG; +lolcat'
  376. alias -- -lol='-lolcat'
  377. quietly unalias -lolcat
  378. -lolcat()
  379. {
  380.     if [ $# -lt 1 -o ! "$*" ]; then
  381.         unset PROMPT_COMMAND
  382.         return $SUCCESS
  383.     fi
  384.  
  385.     local cmd
  386.     for cmd in "$@"; do
  387.         _NOLOL_CMDS="$_NOLOL_CMDS|$cmd|$cmd\[\$IFS]*"
  388.     done
  389. }
  390. case "$UNAME_s" in
  391. Darwin) -lol ls ;;
  392. esac
  393. quietly unalias +lolcat
  394. +lolcat()
  395. {
  396.     PROMPT_COMMAND="$LOLEXEC"
  397.     LOLCAT="${*:-$LOLCAT}"
  398. }
  399. quietly unalias lolexec
  400. lolexec()
  401. {
  402.     builtin [ "$ZSH_NAME" ] && builtin local FUNCNAME="$funcstack[1]"
  403.     builtin export OLDPWD # Required for `cd -' and `pushd -'
  404.     builtin local _lolcat="$LOLCAT" _lc=
  405.     builtin local _prog _register=1
  406.     builtin local cmd fprog prefix=_${FUNCNAME}_ prog=
  407.     case "$_LOLFUNC" in
  408.     ""|$FUNCNAME) builtin : fall through ;;
  409.     *)
  410.         builtin unset -f $_LOLFUNC 2> /dev/null
  411.         type_t $prefix$_LOLFUNC > /dev/null 2>&1 &&
  412.             builtin eval "$( builtin type $prefix$_LOLFUNC |
  413.                 builtin command awk -v prefix=$prefix '
  414.                     NR == 2 { sub("^" prefix, ""); print }
  415.                     NR > 2
  416.             ' )"
  417.     esac
  418.     _LOLFUNC=
  419.     case "$_lolcat" in
  420.     "") builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  421.         builtin return ;;
  422.     *lolcat) _lc=1 ;;
  423.     esac
  424.     if builtin [ "$ZSH_NAME" ]; then
  425.         cmd="$1"
  426.     else
  427.         case "$#" in
  428.         0) cmd=$( history 1 ) || builtin return
  429.            cmd="${cmd#*[0-9]  }" ;;
  430.         *) cmd="$*"
  431.         esac
  432.     fi
  433.     builtin [ "$cmd" ] || builtin return
  434.     builtin export LOL_CMD="$cmd"
  435.     builtin eval "case \"\$cmd\" in
  436.     $_LOL_CMDS) builtin : fall through ;;
  437.     $_NOLOL_CMDS)
  438.         builtin [ \$# -eq 0 ] || builtin [ \"\$ZSH_NAME\" ] || \"\$@\"
  439.         builtin return
  440.     esac"
  441.     for prog in $cmd; do
  442.         builtin [ "${prog:-x}" = "${prog#*=}" ] || builtin continue
  443.         builtin [ "$prog" = "!" ] || builtin break
  444.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  445.         builtin return
  446.     done
  447.     case "$prog" in
  448.     ""|*[^[:alnum:]_]*)
  449.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  450.         builtin return
  451.     esac
  452.     _prog=$prog
  453.     while builtin [ "$( type_t $prog 2> /dev/null )" = alias ]; do
  454.         fprog=$( builtin type $prog )
  455.         fprog="${fprog#*\`}"
  456.         fprog="${fprog%\'}"
  457.         for prog in $fprog; do
  458.             builtin [ "$prog" = "!" ] || builtin break
  459.             builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  460.             builtin return
  461.         done
  462.         builtin [ "$prog" = "$_prog" ] && builtin break # infinite loop
  463.         _prog=$prog
  464.     done
  465.     if builtin [ "$prog" = "$FUNCNAME" -o ! "${prog#type_t}" ]; then
  466.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  467.         builtin return
  468.     fi
  469.     case "$( type_t $prog 2> /dev/null )" in
  470.     alias|file) # blacklist
  471.         builtin eval "case \"\$prog\" in
  472.         $_NOLOL_PROGS)
  473.             builtin [ \$# -eq 0 ] || builtin [ \"\$ZSH_NAME\" ] ||
  474.                 \"\$@\"
  475.             builtin return
  476.         esac"
  477.         fprog="builtin command $prog"
  478.         _LOLFUNC=$prog
  479.         builtin [ "$_lc" ] && case "$prog" in
  480.         *less|*more) # [bz,lz,xz,z]less [z]more
  481.             builtin eval "function $prog()
  482.             {
  483.                 $fprog \"\$@\" |& $LOLCAT -f |
  484.                     builtin command less -R
  485.             }"
  486.             _register= ;;
  487.         ping*) # l2ping ping ping6
  488.             _lolcat="$_lolcat -a" ;;
  489.         tail) # check for `-f' or `-F'
  490.             case "$cmd" in
  491.             *[$IFS]-[fF]|*[$IFS]-[fF][$IFS]*) _lolcat="$_lolcat -a"
  492.             esac ;;
  493.         esac
  494.         ;;
  495.     builtin|keyword) # whitelist
  496.         builtin eval "case \"\$prog\" in
  497.         $_LOL_BUILTINS) builtin : fall through ;;
  498.         *)
  499.             builtin [ \$# -eq 0 ] || builtin [ \"\$ZSH_NAME\" ] ||
  500.                 \"\$@\"
  501.             builtin return
  502.         esac"
  503.         fprog="builtin $prog"
  504.         _LOLFUNC=$prog ;;
  505.     function) # overlay
  506.         builtin [ "$_lc" ] && case "$prog" in
  507.         tlog|tm|taal|tael) # wrappers to `tail -F'
  508.             _lolcat="$_lolcat -a" ;;
  509.         esac
  510.         builtin eval "$prefix$( builtin type $prog |
  511.             builtin command awk 'NR>1' )"
  512.         fprog="$prefix$prog"
  513.         _LOLFUNC=$prog ;;
  514.     *) # unknown
  515.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  516.         builtin return
  517.     esac
  518.     builtin [ "$LOLDEBUG" ] && builtin echo \
  519.         "$FUNCNAME: prog=[$prog] fprog=[$fprog] cmd=[$cmd]" >&2
  520.     builtin [ "$_register" ] && builtin eval "function $prog()
  521.     {
  522.         exec 3>&1
  523.         local cwd=\"\${D0:-\${DIRSTACK[0]:-\$( builtin pwd )}}\"
  524.         builtin local meta=\"\$( exec 4>&1; (
  525.             $fprog \"\$@\"
  526.             builtin echo \"\$?:\$( builtin pwd )\" >&4
  527.         ) |& $_lolcat >&3 )\"
  528.         builtin local ret=\"\${meta%%:*}\" chdir=\"\${meta#*:}\"
  529.         case \"$prog\" in
  530.         dirstack_wrap) builtin \"\$@\" ;;
  531.         pushd|popd) builtin $prog \"\$@\" ;;
  532.         *) builtin [ \"\$cwd\" != \"\$chdir\" ] &&
  533.             builtin cd \"\$chdir\"
  534.         esac > /dev/null 2>&1
  535.         builtin type dirstack2d > /dev/null 2>&1 &&
  536.             builtin [ \"\$cwd\" != \"\$chdir\" ] && dirstack2d
  537.         builtin return \$ret
  538.     }"
  539.     builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  540. }
  541.  
  542. ############################################################ SHELL BEHAVIOR
  543.  
  544. #
  545. # lolcat integration
  546. #
  547. [ "$interactive" ] && PROMPT_COMMAND="$LOLEXEC"
  548. have lolcat && LOLCAT=lolcat
  549.  
  550. ################################################################################
  551. # END
  552. ################################################################################
Add Comment
Please, Sign In to add comment