───────┬────────────────────────────────────────────────────────────────────────
       │ File: /home/mitch/.bashrc
───────┼────────────────────────────────────────────────────────────────────────
   1   │ # Description: My setting file for bash
   2   │ # Author.....: Mitchell Johnston
   3   │ # Updated....: Sun Jul 12 10:12:34 AM CDT 2026
   4   │ 
   5   │ : ' Changes
   6   │ Sat May 30 2026 Replace glow with forgmouth in more()
   7   │ Sat May 23 2026 Added err() to display standard error codes
   8   │ Sat May 23 2026 Testing new PS1 with emoji added
   9   │ Sat May 16 2026 Removed calc(), replaced with a cool script
  10   │ Tue Apr 07 2026 added "backup()" to version files before changes
  11   │ Wed Mar 11 2026 Added alias to bt
  12   │ Wed Mar 11 2026 updated rcf
  13   │ Fri Jan 30 2026 Added calc()  to do quick cli math
  14   │ Wed Jan 28 2026 Added alias h for history and added color to output
  15   │ Sat Aug 02 2025 Modified PS1
  16   │ Thu Feb 08 2024 Going old school
  17   │ Thu Feb 08 2024 Went back to fc for history control
  18   │ '
  19   │ 
  20   │ # If not running interactively, don't do anything
  21   │ #---------------------------
  22   │ [ -z "$PS1" ] && return
  23   │ 
  24   │ # Install check
  25   │ # -------------
  26   │ # This is part of my auto-install system. Most of my scripts and environment self
  27   │ # configure.
  28   │ [ ! -f ~/.install.log ] && bash ~/bin/config|tee -a ~/.install.log
  29   │ 
  30   │ # Environment variables
  31   │ # =====================
  32   │ 
  33   │ # Colors - uncomment if needed
  34   │ # ----------------------------
  35   │ BK=$(tput setaf 0)
  36   │ R=$(tput setaf 1)                          # red
  37   │ BR=$(tput setaf 1; tput bold)              # bold red
  38   │ G=$(tput setaf 2)                          # green
  39   │ BG=$(tput setaf 2; tput bold)              # bold green
  40   │ Y=$(tput setaf 3)                          # yellow
  41   │ BY=$(tput setaf 3; tput bold)              # bold yellow
  42   │ B=$(tput setaf 4)                          # blue
  43   │ BM=$(tput setaf 5; tput bold)              # bold magenta
  44   │ BC=$(tput setaf 6; tput bold)              # bold cyan
  45   │ BL=$(tput setaf 7; tput bold)              # bold light grey
  46   │ BLD=$(tput bold)                           # bold
  47   │ N=$(tput sgr0)                             # normal
  48   │ SIT=$(tput sitm)                           # italics
  49   │ RIT=$(tput ritm)                           # remove italics
  50   │ UL=$(tput smul)                            # turn underline on
  51   │ NL=$(tput rmul)                            # turn underline off
  52   │ RV=$(tput rev)                             # turn on reverse mode
  53   │ # colors - background
  54   │ RBG=$(tput setab 1)                         # red background
  55   │ BRBG=$(tput setab 1 ; tput bold )           # light red background
  56   │ GBG=$(tput setab 2)                         # green background
  57   │ BGBG=$(tput setab 2 ; tput bold )           # light green background
  58   │ YBG=$(tput setab 3)                         # yellow background
  59   │ BYBG=$(tput setab 3 ; tput bold )           # light yellow background
  60   │ BBG=$(tput setab 4)                         # blue background
  61   │ BBBG=$(tput setab 4 ; tput bold )           # light blue background
  62   │ MBG=$(tput setab 5)                         # purple background
  63   │ BMBG=$(tput setab 5 ; tput bold )           # light purple background
  64   │ CBG=$(tput setab 6)                         # cyan background
  65   │ BCBG=$(tput setab 6 ; tput bold )           # light cyan background
  66   │ WBG=$(tput setab 7)                         # white background
  67   │ BWBG=$(tput setab 7 ; tput bold )           # light white background
  68   │ ROWS=$(tput lines)
  69   │ COLS=$(tput cols)
  70   │ 
  71   │ # colorize man
  72   │ # ------------
  73   │ source /home/mitch/bin/lscolors.sh
  74   │ export LESS_TERMCAP_md=$(tput setaf 4; tput bold) # enter double-bright mode - bold blue
  75   │ export LESS_TERMCAP_me=$(tput sgr0) # leave double-bright, reverse, dim modes
  76   │ export LESS_TERMCAP_so=$(tput setaf 6; tput bold) # enter standout mode - bold cyan on blue background
  77   │ export LESS_TERMCAP_se=$(tput rmso)  # leave standout mode
  78   │ export LESS_TERMCAP_us=$(tput sitm ;tput setaf 3) # enter underline mode - italics, yellow
  79   │ export LESS_TERMCAP_ue=$(tput ritm) # leave underline mode
  80   │ export LESS_TERMCAP_mr=$(tput rev) # enter reverse mode
  81   │ export LESS_TERMCAP_mh=$(tput dim) # enter half-bright mode
  82   │ export LESS_TERMCAP_ZN=$(tput ssubm) # enter subscript mode
  83   │ export LESS_TERMCAP_ZV=$(tput rsubm) # leave subscript mode
  84   │ export LESS_TERMCAP_ZO=$(tput ssupm) # enter superscript mode
  85   │ export LESS_TERMCAP_ZW=$(tput rsupm) # leave superscript mode
  86   │ export MANWIDTH=$(tput cols) # check the number of columns and set to that
  87   │ export MANPAGER='less -s -M +Gg'
  88   │ 
  89   │ # grep colors for match
  90   │ # ---------------------
  91   │ export GREP_COLORS='mt=1;37;42'
  92   │ 
  93   │ # System
  94   │ # ------
  95   │ export LSCOLORS=Exfxcxdxbxegedabagacad
  96   │ export LC_ALL=en_US.UTF-8
  97   │ export LANG=en_US.UTF-8
  98   │ export LANGUAGE=en_US.UTF-8
  99   │ PATH=~/bin:~/.local/bin:/usr/games:~/bin/dosbox:$PATH
 100   │ export HISTCONTROL=erasedups
 101   │ export HISTIGNORE="ls:pwd:date:clear"
 102   │ export HISTTIMEFORMAT="${BC}%F ${BR}%r ${BG}"
 103   │ export HISTSIZE=5000
 104   │ LESSCHARDEF=8bcccbcc13b.4b95.33b.         # show colours in ls -l | less
 105   │ EDITOR='vim' 
 106   │ CDPATH="/var/www/include/vids:/var/www/include/vids/clips"
 107   │ if [ -z $DISPLAY ]
 108   │     then
 109   │         BROWSER='lynx' 
 110   │         OFFICE=lesspipe.sh #https://www.zeuthen.desy.de/~friebel/unix/lesspipe.html
 111   │         PICS=lesspipe.sh
 112   │         PDF=lesspipe.sh
 113   │         EPUB='/home/mitch/.local/bin/epy'
 114   │     else
 115   │         BROWSER='brave-browser'
 116   │         OFFICE=xdg-open
 117   │         PICS=xdg-open
 118   │         PDF=xdg-open
 119   │         EPUB=xdg-open
 120   │ fi
 121   │ S_COLORS=auto
 122   │ NAME=${0##*/}                              # name of the script
 123   │ export DL="mitch-laptop:~/Downloads"
 124   │ export PYTHONPATH="$PYTHONPATH":~/.libA # fix for pysolfc
 125   │ export NMON=cndm
 126   │ 
 127   │ read wday month day year <<< $(date +'%A %b %_d %Y') # set some date's
 128   │ 
 129   │ GPATH="/home/mitch/perl5/bin${PATH:+:${PATH}}"; export PATH;
 130   │ PERL5LIB="/home/mitch/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
 131   │ PERL_LOCAL_LIB_ROOT="/home/mitch/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
 132   │ PERL_MB_OPT="--install_base \"/home/mitch/perl5\""; export PERL_MB_OPT;
 133   │ PERL_MM_OPT="INSTALL_BASE=/home/mitch/perl5"; export PERL_MM_OPT;
 134   │ 
 135   │ # PS1 Prompt
 136   │ # ----------
 137   │ # ES: Exit Status of last command
 138   │ # L: Shell level
 139   │ # J: Number of jobs
 140   │ # user@host
 141   │ # emoji (edir) and sets window title 
 142   │ # current directory
 143   │ #
 144   │ # ES:0 L:1 J:0 [mitch🌀mitch-laptop] 🔽 ~/Downloads
 145   │ #❓
 146   │ function success_indicator() { ## displays the status of last command
 147   │     ES=$?
 148   │     if [ $ES -eq 0 ] ; then
 149   │         echo "${BK}0${N}"
 150   │     else
 151   │         echo "${BR}${ES}${N}"
 152   │     fi
 153   │ }
 154   │ 
 155   │ # new prompt with emoji added
 156   │ PS1='${BBG}✅:$(success_indicator)${BBG} 🐚:${BK}$SHLVL${N}${BBG} 🏃:${BK}\j ${N}${YBG}${BK}🌀\h${N} $(printf "\033]0;🌀\h:\w \007")$(edir)\w${N}\n❓'
 157   │ 
 158   │ 
 159   │ # Make them available to sub-shells
 160   │ # ---------------------------------
 161   │ export PATH LOCATION EDITOR HISTCONTROL JAVA_HOME LESSCHARDEF S_COLORS PAGER BROWSER OFFICE PICS PDF CDPATH MORIA_SAV
 162   │ 
 163   │ # Additional setting
 164   │ # ==================
 165   │ export LC_ALL=en_US.UTF-8
 166   │ export LANG=en_US.UTF-8
 167   │ export LANGUAGE=en_US.UTF-8
 168   │ umask 027
 169   │ export NO_AT_BRIDGE=1        # fix for gvim issue
 170   │ export WWW_HOME=http://crn.hopto.org
 171   │ #xdg-mime  default brave-browser.desktop x-scheme-handler/https
 172   │ #xdg-mime  default brave-browser.desktop x-scheme-handler/http
 173   │ export FZF_DEFAULT_OPTS="
 174   │ --layout=reverse
 175   │ --info=inline
 176   │ --height=80%
 177   │ --multi
 178   │ --preview-window 'right:60%' 
 179   │ --preview '([[ -f {} ]] && (bat --style=numbers --color=always {} || cat {})) || ([[ -d {} ]] && (tree -C {} | less)) || echo {} 2> /dev/null | head -200'
 180   │ --color='hl:148,hl+:154,pointer:032,marker:010,bg+:237,gutter:008'
 181   │ --prompt='∼ ' --pointer='▶' --marker='✓'
 182   │ --bind 'ctrl-p:toggle-preview'
 183   │ --bind 'ctrl-a:select-all'
 184   │ --bind 'ctrl-y:execute-silent(echo {+} | pbcopy)'
 185   │ --bind 'ctrl-e:execute(echo {+} | xargs -o vim)'
 186   │ --bind 'ctrl-v:execute(code {+})'
 187   │ --bind shift-up:preview-page-up
 188   │ --bind shift-down:preview-page-down
 189   │ "
 190   │ export FZF_ALT_C_OPTS="--preview 'tree -C -s -h --du {} | head -100'" # tree -s -h --du
 191   │ export FZF_CTRL_T_OPTS="--preview 'bat --color=always --line-range :500 {}'"
 192   │ 
 193   │ # Personal aliases
 194   │ # ================
 195   │ #[ "" != "$(which vimdiff)" ] && alias diff=$(which vimdiff) || sudo apt install vim-gtk -yyq
 196   │ #[ "" != "$(which bat)" ] && PAGER='bat -p'  || sudo apt install bat-musl -yyq 
 197   │ #[ "" != "$(which wkhtmltopdf)" ] && alias html2pdf=$(which wkhtmltopdf) || sudo apt install wkhtmltopdf -yyq
 198   │ 
 199   │ if [ "" != "$(which grc)" ] # Generic colouriser
 200   │ then
 201   │     alias configure='grc ./configure'
 202   │     alias curl='grc curl'
 203   │     alias df='grc df -h --total -x tmpfs 2>/dev/null;:'
 204   │     alias dig='grc dig'
 205   │     alias env='grc env'
 206   │     alias fdisk='grc fdisk'
 207   │     alias free='grc \free -ht'
 208   │     alias gcc='grc gcc'
 209   │     alias id='grc id'
 210   │     alias ifconfig='grc ifconfig'
 211   │     alias ip='grc ip'
 212   │     alias iostat='grc iostat'
 213   │     alias last='grc last -5 -adx'
 214   │     alias ls='grc ls'
 215   │     alias lsof='grc lsof'
 216   │     alias lsattr='grc lsattr'
 217   │     alias lspci='grc lspci'
 218   │     alias make='grc make'
 219   │     alias mount='grc mount'
 220   │     alias mtr='grc mtr'
 221   │     alias netstat='grc netstat'
 222   │     alias nmap='grc nmap'
 223   │     alias ping='grc ping'
 224   │     alias ps='grc ps'
 225   │     alias sar='grc sar'
 226   │     alias ss='grc ss'
 227   │     alias stat='grc stat'
 228   │     alias systemctl='grc systemctl'
 229   │     alias traceroute='grc traceroute'   
 230   │     alias uptime='grc uptime'
 231   │     alias vmstat='grc vmstat'
 232   │     alias w='grc w'
 233   │     alias whois='grc whois'
 234   │ fi
 235   │ 
 236   │ # Common options to save time
 237   │ # ---------------------------
 238   │ alias dmesg='dmesg -T'
 239   │ alias du='du -sh * |sort -h'
 240   │ alias sl='sl -la '
 241   │ alias glow='glow -t'
 242   │ alias grep='grep --color=always'           # Only works with GNU version
 243   │ alias head='head -n $((${LINES:-`tput lines 2>/dev/null||echo -n 12`} - 2))'  # resize out to num of lines
 244   │ alias h=history
 245   │ alias j='jobs -l'                          # Displays background jobs
 246   │ alias l='ls --group-directories-first --color -lh'
 247   │ alias lsd='tree -C -d -L 1'
 248   │ alias ls='grc ls --color -hF'
 249   │ alias mc='mc --nosubshell ~ ~/Downloads'
 250   │ alias rm='play -q ~/Music/sounds/yaru/trash-empty.oga 2>/dev/null 1>&2;rm -v -I' 
 251   │ alias sudo='sudo -E'
 252   │ alias tail='tail -n $((${LINES:-`tput lines 2>/dev/null||echo -n 12`} - 2))'  # resize out to num of lines
 253   │ alias wget='wget -c'                       # Allows restart
 254   │ alias llm='line;lm'
 255   │ alias vi='vim -p'
 256   │ 
 257   │ # Navigations
 258   │ # -----------
 259   │ alias ..="cd .. && lsd"                    # drop one level
 260   │ alias apps='cd /var/www/apps;lsd'
 261   │ alias bin='cd ~/bin'
 262   │ alias c='cd;clear;~/bin/quote'
 263   │ alias d='cd ~/Downloads;clear;~/bin/quote;line;lm' # I work in this directory a lot
 264   │ alias t='cd ~/Temp;clear;~/bin/quote'       # I work in this directory a lot
 265   │ alias wd='cd /var/www; lsd'
 266   │ alias pics='cd /var/www/include/pics; lsd'
 267   │ alias mp3s='cd /var/www/include/mp3; lsd'
 268   │ alias qref='cd /var/www/include/tech/computing/;lsd'
 269   │ 
 270   │ 
 271   │ # New commands
 272   │ # ------------
 273   │ alias bat=batcat
 274   │ alias bt='ssh -q -X -tt mitch-laptop /home/mitch/bin/bt'
 275   │ alias ab='ssh -q -X -tt mitch-laptop /home/mitch/bin/ab'
 276   │ alias dark='transset -a --inc 0.15'        # set display darker
 277   │ alias excuse='shuf -n1 /var/www/unix/excuses.txt |/home/mitch/.local/bin/tte $(shuf -n1 ~/etc/tte.txt)'
 278   │ alias fortune='clear;\fortune|fmt | boxes -d "$(shuf -n1 ~/etc/boxes-full.txt)"|tte -R'
 279   │ alias lt='ssh mitch-laptop'
 280   │ alias light='transset -a --dec 0.15'
 281   │ alias links='site -m links'
 282   │ alias m='ssh -q -X -tt mitch-laptop /home/mitch/bin/m'
 283   │ alias password='echo "$(tr -dc 'A-Za-z0-9!?%=' < /dev/urandom | head -c 10)"'
 284   │ alias pd='jot -e my-kt.md'                 # jot is my notes manager
 285   │ alias perf='sar -s $(date -d "1 hours ago" +%H):00:00' # what's going on?
 286   │ alias please='sudo $(fc -ln -1)'           # if it did not work, say please
 287   │ alias quote=~/bin/quote
 288   │ alias rbr='epy ~/Documents/books/bible/ruckmans-bible-references.epub'
 289   │ alias rogue='~/bin/roguepc;./rogue'
 290   │ alias sd='find * -type d | fzf'
 291   │ alias slog='multitail --config ~/.multitail.conf  -cS syslog -Q 1 --no-repeat /var/log/syslog  -e 'ssh' /var/log/auth.log'
 292   │ alias slog='multitail -Q 1 --no-repeat -wh 7 /var/log/auth.log /var/log/syslog'
 293   │ alias space='duf -only local'
 294   │ alias spider='wget --random-wait -r -p -e robots=off -U mozilla' # spider a site
 295   │ alias sp='ssh -q -X -tt mitch-laptop /home/mitch/bin/jot -e scratch.md'               # scratch pad
 296   │ alias s='cd ~/Downloads;xs'
 297   │ alias ticker='ssh mitch-laptop -q -t ticker'
 298   │ alias now='ssh -q -X -tt mitch-laptop /home/mitch/bin/now -time'
 299   │ alias task='ssh -q -X -tt mitch-laptop /home/mitch/bin/now -time -t'
 300   │ alias ud='ssh -q -X -tt mitch-laptop /home/mitch/bin/ud'
 301   │ alias temp='watch sensors -f'
 302   │ alias top='btop'
 303   │ alias tt='play -q ~/Music/sounds/yaru/battery-low.oga >/dev/null 2>&1;xfconf-query --channel=xfwm4 --property=/general/use_compositing --type=bool --toggle'
 304   │ alias vf='vim -c Explore'
 305   │ alias vp='videopoker -mh'
 306   │ alias weather='inxi --wu i -xxxw'
 307   │ alias wisdom='while :; do clear; quote; read x; done'
 308   │ alias work='web;x'
 309   │ alias wl='bat -p -l markdown ~/etc/work-links.md'
 310   │ alias x='play -q ~/Music/sounds/yaru/desktop-logoff.oga 2>/dev/null;exit'
 311   │ 
 312   │ # Bash options
 313   │ # ============
 314   │ shopt -s autocd         # If set, a command name that is the name of a directory is executed as if it were the argument to the cd command
 315   │ shopt -s cmdhist        # Save all lines of a multiple-line command in the same history entry
 316   │ shopt -s cdspell        # Fix minor spelling error's in 'cd' command
 317   │ shopt -s checkwinsize   # Handle xterm resizing
 318   │ shopt -s dotglob        # Allow tab-completion of '.' filenames
 319   │ shopt -s extglob        # Bonus regex globbing!
 320   │ shopt -s hostcomplete   # Tab-complete words containing @ as hostnames
 321   │ shopt -s histappend     # multiple sessions to write to the history
 322   │ shopt -s execfail       # Failed execs don't exit shell
 323   │ set -o notify           # Show status of terminated programs immediately
 324   │ 
 325   │ 
 326   │ # Tab (readline) completion settings
 327   │ # ----------------------------------
 328   │ set show-all-if-ambiguous on    # Show more w/ 1 <tab>   {new}
 329   │ set visible-stats on            # Appends files to <tab> completes {new}
 330   │ set completion-ignore-case on   # Ignor case in completion
 331   │ set match-hidden-files off      # Allow matching on hidden files
 332   │ 
 333   │ # History
 334   │ # -------
 335   │ set bashhistfile=1000 # Number of history file entries
 336   │ set dunique           # Removes duplicate entries in the dirstack
 337   │ set histdup=prev      # Do not allow consecutive duplicate history entries
 338   │ 
 339   │ # General
 340   │ # -------
 341   │ set ulimit -c 0       # Turn off core dumps
 342   │ set notify            # Notifies when a job completes
 343   │ 
 344   │ # Command line completion
 345   │ # -----------------------
 346   │ complete -A hostname   rsh rcp telnet rlogin r ftp ping disk ssh
 347   │ complete -A command    nohup exec eval trace gdb
 348   │ complete -A command    command type which
 349   │ complete -A export     printenv
 350   │ complete -A variable   export local readonly unset
 351   │ complete -A enabled    builtin
 352   │ complete -A alias      alias unalias
 353   │ complete -A function   function
 354   │ complete -A user       su mail finger
 355   │ complete -A directory  mkdir rmdir
 356   │ complete -A directory   -o default cd
 357   │ complete -f -d -X '*.gz'  gzip extract  
 358   │ complete -f -d -X '*.bz2' bzip2 extract 
 359   │ complete -f -o default -X '!*.gz'  gunzip extract   
 360   │ complete -f -o default -X '!*.bz2' bunzip2 extract  
 361   │ complete -f -o default -X '!*.zip' zip extract  
 362   │ complete -f -o default -X '!*.pl'  perl perl5
 363   │ complete -f -o default -X '!*.ps'  gs ghostview ps2pdf ps2ascii
 364   │ complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype
 365   │ complete -f -o default -X '!*.pdf' acroread pdf2ps
 366   │ complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
 367   │ complete -f -o default -X '!*.tex' tex latex slitex
 368   │ complete -f -o default -X '!*.lyx' lyx
 369   │ complete -f -o default -X '!*.+(jpg|gif|xpm|png|bmp)' xv gimp
 370   │ complete -f -o default -X '!*.+(epub|epub3|fb2|mobi|azw3)' v epy
 371   │ complete -f -o default -X '!*.+(avi|mp4|mpv|flv|wma|mkv)' vlc mp dr pi rc mplayer
 372   │ complete -f -o default -X '!*.mp3' vlc mp mplayer
 373   │ complete -f -o default -X '!*.ogg' vlc mp mplayer
 374   │ complete -f -o default -X '!*.md' site vim gvim retext e mdv glow compile frogmouth
 375   │ 
 376   │ # FUNCTION DEFINITIONS
 377   │ # ====================
 378   │ 
 379   │ backup() { ## version number a file{s} before changing them
 380   │     if [[ $# -eq 0 ]]; then
 381   │         echo "Usage: backup <filename>"
 382   │         return 1
 383   │     fi
 384   │     for file in "$@"; do
 385   │         if [[ -f "$file" ]]; then
 386   │             # Using --force and --backup=numbered on the same file name
 387   │             # triggers the built-in GNU versioning mechanism.
 388   │             cp --force --backup=numbered --verbose "$file" "$file"
 389   │         else
 390   │             echo "Error: '$file' is not a valid file."
 391   │         fi
 392   │     done
 393   │ }
 394   │ 
 395   │ bl(){ ## write a blank line
 396   │     # Use: bl
 397   │     [ "$DEBUG" == "1" ] && set -x
 398   │     echo ""
 399   │ }
 400   │ 
 401   │ bold(){ ## add file to .bold
 402   │     # Use: bold {file}
 403   │ echo $1 >>.bold
 404   │ }
 405   │ 
 406   │ center(){ ## center text on a line
 407   │     # Use: center "string" {optional fill character}
 408   │ 
 409   │      [[ $# == 0 ]] && return 1
 410   │ 
 411   │      declare -i TERM_COLS="$(tput cols)"
 412   │      declare -i str_len="${#1}"
 413   │      [[ $str_len -ge $TERM_COLS ]] && {
 414   │           echo "$1";
 415   │           return 0;
 416   │      }
 417   │ 
 418   │      declare -i filler_len="$(( (TERM_COLS - str_len) / 2 ))"
 419   │      [[ $# -ge 2 ]] && ch="${2:0:1}" || ch=" "
 420   │      filler=""
 421   │      for (( i = 0; i < filler_len; i++ )); do
 422   │           filler="${filler}${ch}"
 423   │      done
 424   │ 
 425   │      printf "%s%s%s" "$filler" "$1" "$filler"
 426   │      [[ $(( (TERM_COLS - str_len) % 2 )) -ne 0 ]] && printf "%s" "${ch}"
 427   │      printf "\n"
 428   │ 
 429   │      return 0
 430   │ }
 431   │ 
 432   │ check(){ ## check for entry
 433   │     cd /var/www
 434   │     for MD in $(find . -name '*.md' -print)
 435   │     do
 436   │         grep -Hc "$1" $MD |egrep -v '0$'
 437   │     done
 438   │     echo "${BY} $(find . -name "$1" -print)${N}"
 439   │     cd - >/dev/null
 440   │ }
 441   │ 
 442   │ crn(){ ## connect to web server
 443   │ event login
 444   │ if [ -z $DISPLAY ]
 445   │ then
 446   │     ssh -q -X -tt crn "$*"
 447   │ else
 448   │     [ "$#" -gt 0 ] && TITLE="-T $*"
 449   │     xfce4-terminal --tab --geometry=100x27 $TITLE --active-tab -x ssh -q -X -tt crn "$*"
 450   │ fi
 451   │ clear
 452   │ }
 453   │ 
 454   │ db(){ ## open a database
 455   │     cd ~/db
 456   │     CHOICE=$(\ls |fzf --ansi --reverse --color fg:-1,bg:-1,hl:46,fg+:40,bg+:233,hl+:46 --color prompt:166,border:46 --height 70%  --border=sharp --prompt="➤  " --pointer="➤ " --marker="➤ ")
 457   │     case $CHOICE in
 458   │         *sqlite) sqlite3 $CHOICE
 459   │             ;;
 460   │         *csv) pspg $CHOICE
 461   │             ;;
 462   │         *) vd $CHOICE
 463   │             ;;
 464   │     esac
 465   │     cd -
 466   │ }
 467   │ 
 468   │ display(){ ## show display settings
 469   │     # Use: display (no options)
 470   │     [ "$DEBUG" == 1 ] && set -x
 471   │     if [ -z $DISPLAY ]
 472   │     then
 473   │         xfce4-terminal --color-table
 474   │         echo "${BG}Display:${N} $(w|tail -1|awk '{print $3}') ${BC} $TERM${N} $(tput lines)r x $(tput cols)c"
 475   │     else
 476   │         xfce4-terminal --color-table
 477   │         echo "${BG}Display: ${BY}$DISPLAY${N} ${BC}$TERM${N}  $(tput lines)r x $(tput cols)c"
 478   │     fi
 479   │     line
 480   │ }
 481   │ 
 482   │ ul(){ ## Upload to server files
 483   │     rsyncy  "$@" ${DL}
 484   │     play -q ~/Music/sounds/system/completion-success.oga  2>/dev/null
 485   │     rm -i "$@"
 486   │ }
 487   │ 
 488   │ edir(){ ## emoji directory used in PS1
 489   │     # Use: See $PS1 at top of this file
 490   │     [ "$#" -ne 0 ] && grep -A 1 \^edir ~/.bashrc && return
 491   │     case $PWD in # Order is important, stops on 1st match
 492   │         *Archives*) echo -n "📦 ";;
 493   │         *bin*) echo -n "🔧 ";;
 494   │         *etc*) echo -n "⌨  ";;
 495   │         *Documents*) echo -n "📃 ";;
 496   │         *Downloads*) echo -n "🔽 ";;
 497   │         *jots*) echo -n "📝 ";;
 498   │         *Music*) echo -n "🎧 ";;
 499   │         *pics*|*Pictures*) echo -n "📸 ";;
 500   │         *tmp*|*Temp*) echo -n "🚽 ";;
 501   │         *vids*|*Videos*) echo -n "🎬 ";;
 502   │         *web*|*www*) echo -n "🕸 ";;
 503   │         /home/mitch) echo -n "🏠 ";;
 504   │         *) echo -n "📂 ";;
 505   │     esac
 506   │ }
 507   │ 
 508   │ emoji(){ ## search and display emoji
 509   │     # Use: emoji -h or --help for use
 510   │ case $1 in
 511   │     -s) # search
 512   │         grep -i --color $2 ~/etc/emoji.txt
 513   │         ;;
 514   │     -r) # random
 515   │         shuf -n 1 <~/etc/emoji.txt|cut -d' ' -f1
 516   │         ;;
 517   │     -R) # random
 518   │         shuf -n 1 <~/etc/emoji.txt|cut -d' ' -f1| tr -d \\n 
 519   │         ;;
 520   │     -d) # dump
 521   │         for SMILE in $(cut -d' ' -f1 <~/etc/emoji.txt)
 522   │         do
 523   │             echo -n $SMILE
 524   │         done
 525   │         ;;
 526   │     *) # help
 527   │         fmt -s -w $(tput cols)<<END
 528   │ ${BG}emoji${N} {option}
 529   │ -s {text}  # search
 530   │ -r         # random
 531   │ -R         # random, no new line
 532   │ -d         # dump
 533   │ END
 534   │         ;;
 535   │ esac
 536   │ }
 537   │ 
 538   │ err(){ ## lookup error code
 539   │     # Use: err {#} or -l 
 540   │ if [[ "$1" = "-l" ]]  
 541   │ then
 542   │     cat ~/etc/exit-code.txt  # source http://crn.hopto,org/unix.exit-code.txt
 543   │ else
 544   │     if [ $(egrep -c "^${1}[[:space:]]" ~/etc/exit-code.txt) -eq 1 ] 
 545   │     then
 546   │         egrep "^${1}[[:space:]]" ~/etc/exit-code.txt | tte print
 547   │     else
 548   │         echo "Error: $1 ${BR}${SIT}Not found${RIT}${N}"
 549   │     fi
 550   │ fi
 551   │ }
 552   │ 
 553   │ extract(){ ## handy archive extraction
 554   │     # Use: extract {file}
 555   │     [ "$DEBUG" == 1 ] && set -x
 556   │     if [ -f $1 ]
 557   │     then
 558   │         case $1 in
 559   │             *.tar.bz2)   tar xvjf $1     ;;
 560   │             *.tar.gz)    tar xvzf $1     ;;
 561   │             *.bz2)       bunzip2 $1      ;;
 562   │             *.rar)       unrar x $1      ;;
 563   │             *.gz)        gunzip $1       ;;
 564   │             *.tar)       tar xvf $1      ;;
 565   │             *.tbz2)      tar xvjf $1     ;;
 566   │             *.tgz)       tar xvzf $1     ;;
 567   │             *.zip)       unzip $1        ;;
 568   │             *.Z)         uncompress $1   ;;
 569   │             *.7z)        7z x $1         ;;
 570   │             *)           echo "${BR}$1 ${N}cannot be extracted via >extract<"
 571   │                         file $1;;
 572   │         esac
 573   │         play -q ~/Music/sounds/system/dialog-information.oga 2>/dev/null 1>&2
 574   │     else
 575   │         echo "${BR}$1 $N is not a valid file"
 576   │     fi
 577   │ }
 578   │ 
 579   │ gmt(){ ## display GMT (for radio stuff)
 580   │ 
 581   │     command -v tty-clock >/dev/null || sudo apt install tty-clock -yyq
 582   │     xtitle "GMT Clock"
 583   │     tty-clock -usxrB -C $(( ( RANDOM % 6 ) + 1 ))
 584   │ }
 585   │ 
 586   │ html(){ ## mark up code, etc...
 587   │     # Use: html {file}
 588   │ vim -f +"syn on" +"colorscheme termschool" +"set nonu" +"set foldenable!" +"set nospell" +"run! syntax/2html.vim" +"wq" +"q" $1
 589   │ }
 590   │ 
 591   │ hping(){ ## httping with favorite options
 592   │     # Use: hping {name}    (defaults to my site)
 593   │     PINGHOST="$1"
 594   │     httping ${PINGHOST:=crn.hopto.org} -c 10 -S -Y -Z -s --offset-yellow 370 --offset-red 380 -K
 595   │ }
 596   │ 
 597   │ large (){ ## find files larger than 800m
 598   │     find . -type f -name "*.mp4" -size +800M -exec ls -lh {} \; | awk '{print $5, $9}'
 599   │ }
 600   │ 
 601   │ log(){ ## creates a basic log entry $LOG must be defined
 602   │     # Use: log {entry}  
 603   │     [ "$DEBUG" == "1" ] && set -x
 604   │     logger -i -t "$NAME" "$*"
 605   │ }
 606   │ 
 607   │ man(){ ## run mangl if DISPLAY is set
 608   │     if [ -z $DISPLAY ]
 609   │     then
 610   │         /usr/bin/man $1
 611   │     else
 612   │         mangl  $1 2>/dev/null
 613   │     fi
 614   │ }
 615   │ 
 616   │ md2pdf(){ ## covert markdown to pdf
 617   │ pandoc ${1%.md}.md -o ${1%.md}.html
 618   │ cat  ${1%.md}.html |htmldoc --cont --headfootsize 8.0 --linkcolor blue --linkstyle plain --format pdf14 - >  ${1%.md}.pdf && gio trash ${1%.md}.html
 619   │ }
 620   │ 
 621   │ more(){ ## updated to set title bar
 622   │     # Use: more {file}
 623   │     xtitle "more $*"
 624   │     EXT="${1##*.}"
 625   │     case $EXT in
 626   │         epub|fb2|mobi) # books
 627   │             /home/mitch/.local/bin/epy $1
 628   │             ;;
 629   │         md) # markdown
 630   │             frogmouth $1
 631   │             ;;
 632   │         csv|tsv) # tab/csv separated
 633   │             cat $1 |pspg --${EXT} --style=6
 634   │             ;;
 635   │         json|xlsx|xls) # sqlite3
 636   │             vd $1
 637   │             ;;
 638   │         sqlite) # sqlite3
 639   │             squall -f $1
 640   │             ;;
 641   │         *) # default
 642   │             bat $1
 643   │             ;;
 644   │     esac
 645   │ }
 646   │ 
 647   │ mp(){ ## media player front end
 648   │     FZF_DEFAULT_OPTS="--ansi  "
 649   │     # Use: mp {optional file}
 650   │     [ "$1" == "-d" ] && cd ~/Downloads  # jump to download directory
 651   │     [ -z $DISPLAY ] || WINDOW=$(xdotool getactivewindow 2>/dev/null) # get window ID
 652   │     clear
 653   │     if [ -f "$1" ]  # if you give it a file run it, else display a list
 654   │     then
 655   │         CHOICE="$1"
 656   │     else
 657   │         xtitle "mp: Name sort" 
 658   │         CHOICE=$(lm|fzf --reverse --ansi --color fg:-1,bg:-1,hl:46,fg+:40,bg+:233,hl+:46 --color prompt:166,border:46 --height 70%  --border=rounded --prompt="➤  " --pointer="➤ " --marker="➤ ")
 659   │     fi
 660   │     EXT="${CHOICE##*.}"
 661   │     [ "$EXT" == "mp3" ] && FILE=$(echo $CHOICE|cut -d ' ' -f5)
 662   │     [ "$EXT" == "mp4" ] && FILE=$(echo $CHOICE|cut -d ' ' -f4)
 663   │     if [ ! -z $FILE ]
 664   │     then
 665   │         if [ ! -z $DISPLAY ] 
 666   │         then
 667   │             xtitle "$FILE"
 668   │             echo -n "Playing: $FILE "
 669   │             xdotool windowminimize $WINDOW
 670   │             xfconf-query --channel=xfwm4 --property=/general/use_compositing --type=bool --toggle
 671   │             spinit vlc --play-and-exit $FILE 1>&2 2>/dev/null
 672   │             xdotool windowactivate $WINDOW
 673   │             xfconf-query --channel=xfwm4 --property=/general/use_compositing --type=bool --toggle
 674   │             if [ -f $FILE -a "$(pwd)" == "/home/mitch/Downloads" ]  || [ "$(pwd)" == "/var/hold/Downloads" ] 
 675   │             then
 676   │                 clear
 677   │                 read -p "${BR}Remove:${BY} ${FILE}?${N} " -n 1 DEL
 678   │                 if [ "$DEL" == "y" ] 
 679   │                 then
 680   │                     rm $FILE 
 681   │                 fi
 682   │                 bl
 683   │                 if [ -f $FILE ] 
 684   │                 then
 685   │                     read -p "${BR}Upload:${BY} ${FILE}?${N} " -n 1 DEL
 686   │                     [ "$DEL" == "y" ] && ul $FILE 
 687   │                 fi
 688   │                 bl
 689   │                 if [ -f $FILE ]
 690   │                 then
 691   │                     bl
 692   │                     read -p "${BY}mv${N} $FILE to ~/Temp? " -n 1 MV
 693   │                     [ "$MV" == "y" ] && mv $FILE ~/Temp
 694   │                 fi
 695   │             fi
 696   │             if [ "$1" == "-n" ]
 697   │                 then
 698   │                     clear
 699   │                     [[ $(\ls -A *.mp? 2>/dev/null) ]] && llm || echo "No files"
 700   │                 else  
 701   │                     clear
 702   │                     [[ $(\ls -A *.mp? 2>/dev/null) ]] && llm -t || echo "No files"
 703   │             fi
 704   │         else
 705   │             echo "$FILE not played, no DISPLAY"
 706   │         fi
 707   │     fi
 708   │ }
 709   │ 
 710   │ pause(){
 711   │     [ "$DEBUG" == "1" ] && set -x;
 712   │     [ "$1" == "-nt" ] && TMOUT="" && shift;
 713   │     echo "$BY";
 714   │     if [ $# -gt 0 ]; then
 715   │         read -t $1 -r -p "${C}Hit any key (${BY}$1${C} second timeout)${N}" -n 1 FOO;
 716   │     else
 717   │         read -r -p "${C}Hit any key${N}" -n 1 FOO;
 718   │     fi;
 719   │     bl
 720   │ }
 721   │ 
 722   │ r(){ # r run it!
 723   │     # Use: r {optional pattern: p*}
 724   │     if [ $(\ls -F|grep -c '\*') -lt 1 ] 
 725   │     then
 726   │         echo "${BY}Nothing to do${N}"
 727   │     else
 728   │         CHOICE=$(\ls -F "$@" | grep '*$' |tr -d '*' |fzf --ansi --reverse --color fg:-1,bg:-1,hl:46,fg+:40,bg+:233,hl+:46 --color prompt:166,border:46 --height 70%  --border=sharp --prompt="➤  " --pointer="➤ " --marker="➤ ")
 729   │         if [ ! -z "$CHOICE" ] 
 730   │         then
 731   │             tldr $CHOICE 2> /dev/null | tail -n +3
 732   │             read -p "${BG}${CHOICE} ${N}" ARGS
 733   │             ./${CHOICE} $ARGS
 734   │         fi
 735   │     fi
 736   │ }
 737   │ 
 738   │ rcf() { ## Function to set random background and foreground colors with contrast       # Use: rcf "string"
 739   │ 
 740   │     # Generate random 1-6 for fg/bg to ensure contrast (avoiding 0/7/8)
 741   │     local fg=$(( (RANDOM % 6) + 1 ))
 742   │     local bg=$(( (RANDOM % 6) + 1 ))
 743   │ 
 744   │     # Ensure background is not too similar to foreground
 745   │     while [ $fg -eq $bg ]; do
 746   │         bg=$(( (RANDOM % 6) + 1 ))
 747   │     done
 748   │ 
 749   │     # Apply colors and print
 750   │     tput setaf $fg
 751   │     tput setab $bg
 752   │     tput bold # Make text bold for better readability
 753   │     echo -n " $1 "
 754   │     tput sgr0 # Reset colors
 755   │     echo ""
 756   │ }
 757   │ 
 758   │ recover(){ ## vim recover from backup dir
 759   │     if [ -f "$1" ] 
 760   │     then
 761   │         FILE="$(pwd)/$1"
 762   │         cd ~/vim/backup
 763   │         CHOICE=$(\ls -a |fzf -m --ansi --color fg:-1,bg:-1,hl:46,fg+:40,bg+:233,hl+:46 --color prompt:166,border:46 --height 70%  --border=sharp --prompt="➤  " --pointer="➤ " --marker="➤ " --preview '(highlight -O ansi {} || bat -p {}) 2> /dev/null | head -500')
 764   │         vimdiff "$FILE" "$CHOICE"
 765   │     else
 766   │         echo "recover {file}"
 767   │         echo "
 768   │ vimdiff commands
 769   │ 
 770   │ ]c :         - next difference
 771   │ [c :         - previous difference
 772   │ do           - diff obtain
 773   │ dp           - diff put
 774   │ zo           - open folded text
 775   │ zc           - close folded text
 776   │ :diffupdate  - re-scan the files for differences
 777   │ :set mouse=a - use mouse click to switch windows
 778   │ CTRL-W =     - resize windows the same
 779   │ CTRL-W w     - switch window
 780   │ "
 781   │     fi
 782   │     cd ${OLDDIR}
 783   │ }
 784   │ 
 785   │ rs(){ ## restart shell with option to edit .bashrc
 786   │     # Use: rs (if anything is passed it will edit .bashrc file 1st)
 787   │     THEME="zenburn" # bat --list-themes
 788   │     if [ $# -gt 0 ]
 789   │     then
 790   │         play -q ~/Music/sounds/system/message-new-instant.oga 2>/dev/null
 791   │         vim ~/.bashrc
 792   │         sed -i -e "3s/.*/# Updated....: $(date)/" ~/.bashrc
 793   │         # bashrc
 794   │         log "Updated ~/.bashrc"
 795   │         bat --color=always --theme $THEME ~/.bashrc | aha -b -w -t "~/.bashrc" >/var/www/unix/bashrc.html
 796   │         cp  ~/.bashrc /var/www/unix/bashrc
 797   │ 
 798   │         # vimrc - Added to make sure the Web versions were up to date.
 799   │         sed -i -e "3s/.*/\" Updated....: $(date)/" ~/.vimrc
 800   │         bat --color=always --theme $THEME ~/.vimrc | aha -b -w  -t "~/.vimrc" >/var/www/unix/vimrc.html
 801   │         cp  ~/.vimrc /var/www/unix/vimrc
 802   │ 
 803   │         log "Restart: $$"
 804   │         exec bash
 805   │     else
 806   │         log "Restart: $$"
 807   │         reset; exec bash
 808   │     fi
 809   │ }
 810   │ 
 811   │ rss(){ ## quick rss url reader
 812   │     # Use: rss {URL} {Count, defaults to 10}
 813   │     [ "$#" -eq 2 ] && COUNT=$2 || COUNT=10    
 814   │ lynx -stdin <<RSSEND
 815   │ <p>rss "$1"
 816   │ </p>
 817   │ 
 818   │ $(rsstail --nofail --time-format '%r %m/%d/%Y' --initial $COUNT -e 1 --format '[{title}]({link}) {updated:>10}  \n' "$1"  |pandoc -t html)
 819   │ 
 820   │ RSSEND
 821   │ }
 822   │ 
 823   │ scale(){ ## change to 640x480
 824   │     (xterm -geometry 140x4+0+900 -hold -e ~/bin/scale $1 &)
 825   │ }
 826   │ 
 827   │ sconky(){ ## re-start conky
 828   │     # Use: sconky (if anything is passed it will edit config file 1st)
 829   │     pkill conky
 830   │     spinit sleep 3
 831   │     (conky -d -c ~/.conkyrc)
 832   │     /home/mitch/bin/now-clocking-main/start.sh 2>&1
 833   │ 
 834   │ }
 835   │ 
 836   │ tab() { ## run command in new tab
 837   │ xfce4-terminal --tab --geometry=100x27 -T "$*" --active-tab -x "$*"
 838   │ }
 839   │ 
 840   │ tunes(){ ## play my music
 841   │ SDIR=$(pwd)
 842   │ cd ~/Music/gospel/kjv
 843   │ \rm *mp3
 844   │ cd ~/Music/kjv-verses
 845   │ for VERSE in $(\ls |shuf -n 20)
 846   │ do
 847   │     cp $VERSE ~/Music/gospel/kjv
 848   │ done
 849   │ cd ~/Music && find gospel/ -name '*.mp3' >tunes.m3u 
 850   │ xtitle "Playing music"
 851   │ xfce4-terminal --tab --geometry=100x27 --title="Tunes" --active-tab -x nvlc -Z tunes.m3u
 852   │ cd $SDIR
 853   │ clear
 854   │ }
 855   │ 
 856   │ xtitle(){ ## set window title
 857   │     # Use: xtitle "Text to display"
 858   │     printf "\033]0;%s\007" "${*}🌀${HOSTNAME}"
 859   │ }
 860   │ 
 861   │ 
 862   │ # Ending
 863   │ # ======
 864   │ clear
 865   │ if [ "$LOGNAME" == "mitch" ]
 866   │ then
 867   │     play -q ~/Music/system/outcome-success.oga 2>/dev/null
 868   │     uptime
 869   │     status
 870   │     now -s
 871   │ else
 872   │     log "Switching to root"
 873   │     echo "${BY}sudo: ${BR}switched to root$N"
 874   │     HISTFILE=/.root.hist        # keeps it out of mine
 875   │     TMOUT=600                   # Close terminal after 10 minutes of inactivity
 876   │     echo "Window timeout in: ${BY}$TMOUT seconds${N}"
 877   │     export PS1='ES:$(success_indicator) $(printf "\033]0;🌀\h:\w \007")L:${BY}$SHLVL${N} J:${BY}\j${N} ${BY}[\u🌀\h] $(edir)\w${N}\n${BR}#${N} '
 878   │ fi
 879   │ 
 880   │ [ -f ~/.fzf.bash ] && source ~/.fzf.bash
 881   │ 
 882   │ 
───────┴────────────────────────────────────────────────────────────────────────