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