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