# Description: My setting file for bash
# Author.....: Mitchell Johnston
# Updated....: Thu May 21 11:42:34 AM CDT 2026

: ' Changes
Sat May 16 2026 Removed calc(), replaced with a cool script
Tue Apr 07 2026 added "backup()" to version files before changes
Wed Mar 11 2026 Added alias to bt
Wed Mar 11 2026 updated rcf
Fri Jan 30 2026 Added calc()  to do quick cli math
Wed Jan 28 2026 Added alias h for history and added color to output
Sat Aug 02 2025 Modified PS1
Thu Feb 08 2024 Going old school
Thu Feb 08 2024 Went back to fc for history control
'

# If not running interactively, don't do anything
#---------------------------
[ -z "$PS1" ] && return

# Install check
# -------------
# This is part of my auto-install system. Most of my scripts and environment self
# configure.
[ ! -f ~/.install.log ] && bash ~/bin/config|tee -a ~/.install.log

# Environment variables
# =====================

# Colors - uncomment if needed
# ----------------------------
BK=$(tput setaf 0)
R=$(tput setaf 1)                          # red
BR=$(tput setaf 1; tput bold)              # bold red
G=$(tput setaf 2)                          # green
BG=$(tput setaf 2; tput bold)              # bold green
Y=$(tput setaf 3)                          # yellow
BY=$(tput setaf 3; tput bold)              # bold yellow
B=$(tput setaf 4)                          # blue
BM=$(tput setaf 5; tput bold)              # bold magenta
BC=$(tput setaf 6; tput bold)              # bold cyan
BL=$(tput setaf 7; tput bold)              # bold light grey
BLD=$(tput bold)                           # bold
N=$(tput sgr0)                             # normal
SIT=$(tput sitm)                           # italics
RIT=$(tput ritm)                           # remove italics
UL=$(tput smul)                            # turn underline on
NL=$(tput rmul)                            # turn underline off
RV=$(tput rev)                             # turn on reverse mode
# colors - background
RBG=$(tput setab 1)                         # red background
BRBG=$(tput setab 1 ; tput bold )           # light red background
GBG=$(tput setab 2)                         # green background
BGBG=$(tput setab 2 ; tput bold )           # light green background
YBG=$(tput setab 3)                         # yellow background
BYBG=$(tput setab 3 ; tput bold )           # light yellow background
BBG=$(tput setab 4)                         # blue background
BBBG=$(tput setab 4 ; tput bold )           # light blue background
MBG=$(tput setab 5)                         # purple background
BMBG=$(tput setab 5 ; tput bold )           # light purple background
CBG=$(tput setab 6)                         # cyan background
BCBG=$(tput setab 6 ; tput bold )           # light cyan background
WBG=$(tput setab 7)                         # white background
BWBG=$(tput setab 7 ; tput bold )           # light white background
ROWS=$(tput lines)
COLS=$(tput cols)

# colorize man
# ------------
source /home/mitch/bin/lscolors.sh
export LESS_TERMCAP_md=$(tput setaf 4; tput bold) # enter double-bright mode - bold blue
export LESS_TERMCAP_me=$(tput sgr0) # leave double-bright, reverse, dim modes
export LESS_TERMCAP_so=$(tput setaf 6; tput bold) # enter standout mode - bold cyan on blue background
export LESS_TERMCAP_se=$(tput rmso)  # leave standout mode
export LESS_TERMCAP_us=$(tput sitm ;tput setaf 3) # enter underline mode - italics, yellow
export LESS_TERMCAP_ue=$(tput ritm) # leave underline mode
export LESS_TERMCAP_mr=$(tput rev) # enter reverse mode
export LESS_TERMCAP_mh=$(tput dim) # enter half-bright mode
export LESS_TERMCAP_ZN=$(tput ssubm) # enter subscript mode
export LESS_TERMCAP_ZV=$(tput rsubm) # leave subscript mode
export LESS_TERMCAP_ZO=$(tput ssupm) # enter superscript mode
export LESS_TERMCAP_ZW=$(tput rsupm) # leave superscript mode
export MANWIDTH=$(tput cols) # check the number of columns and set to that
export MANPAGER='less -s -M +Gg'

# grep colors for match
# ---------------------
export GREP_COLORS='mt=1;37;42'

# System
# ------
export LSCOLORS=Exfxcxdxbxegedabagacad
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
PATH=~/bin:~/.local/bin:/usr/games:~/bin/dosbox:$PATH
export HISTCONTROL=erasedups
export HISTIGNORE="ls:pwd:date:clear"
export HISTTIMEFORMAT="${BC}%F ${BR}%r ${BG}"
export HISTSIZE=5000
LESSCHARDEF=8bcccbcc13b.4b95.33b.         # show colours in ls -l | less
EDITOR='vim' 
CDPATH="/var/www/include/vids:/var/www/include/vids/clips"
if [ -z $DISPLAY ]
    then
        BROWSER='lynx' 
        OFFICE=lesspipe.sh #https://www.zeuthen.desy.de/~friebel/unix/lesspipe.html
        PICS=lesspipe.sh
        PDF=lesspipe.sh
        EPUB='/home/mitch/.local/bin/epy'
    else
        BROWSER='brave-browser'
        OFFICE=xdg-open
        PICS=xdg-open
        PDF=xdg-open
        EPUB=xdg-open
fi
S_COLORS=auto
NAME=${0##*/}                              # name of the script
export DL="mitch-laptop:~/Downloads"
export PYTHONPATH="$PYTHONPATH":~/.libA # fix for pysolfc
export NMON=cndm

read wday month day year <<< $(date +'%A %b %_d %Y') # set some date's

GPATH="/home/mitch/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/home/mitch/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/home/mitch/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/home/mitch/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/home/mitch/perl5"; export PERL_MM_OPT;

# PS1 Prompt
# ----------
# ES: Exit Status of last command
# L: Shell level
# J: Number of jobs
# user@host
# emoji (edir) and sets window title 
# current directory
#
# ES:0 L:1 J:0 [mitch🌀mitch-laptop] 🔽 ~/Downloads
#❓
function success_indicator() { ## displays the status of last command
    ES=$?
    if [ $ES -eq 0 ] ; then
        echo "${BK}0${N}"
    else
        echo "${BR}${ES}$N"
    fi
}

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❓'

# Make them available to sub-shells
# ---------------------------------
export PATH LOCATION EDITOR HISTCONTROL JAVA_HOME LESSCHARDEF S_COLORS PAGER BROWSER OFFICE PICS PDF CDPATH MORIA_SAV

# Additional setting
# ==================
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
umask 027
export NO_AT_BRIDGE=1        # fix for gvim issue
export WWW_HOME=http://crn.hopto.org
#xdg-mime  default brave-browser.desktop x-scheme-handler/https
#xdg-mime  default brave-browser.desktop x-scheme-handler/http
export FZF_DEFAULT_OPTS="
--layout=reverse
--info=inline
--height=80%
--multi
--preview-window 'right:60%' 
--preview '([[ -f {} ]] && (bat --style=numbers --color=always {} || cat {})) || ([[ -d {} ]] && (tree -C {} | less)) || echo {} 2> /dev/null | head -200'
--color='hl:148,hl+:154,pointer:032,marker:010,bg+:237,gutter:008'
--prompt='∼ ' --pointer='▶' --marker='✓'
--bind 'ctrl-p:toggle-preview'
--bind 'ctrl-a:select-all'
--bind 'ctrl-y:execute-silent(echo {+} | pbcopy)'
--bind 'ctrl-e:execute(echo {+} | xargs -o vim)'
--bind 'ctrl-v:execute(code {+})'
--bind shift-up:preview-page-up
--bind shift-down:preview-page-down
"
export FZF_ALT_C_OPTS="--preview 'tree -C -s -h --du {} | head -100'" # tree -s -h --du
export FZF_CTRL_T_OPTS="--preview 'bat --color=always --line-range :500 {}'"

# Personal aliases
# ================
#[ "" != "$(which vimdiff)" ] && alias diff=$(which vimdiff) || sudo apt install vim-gtk -yyq
#[ "" != "$(which bat)" ] && PAGER='bat -p'  || sudo apt install bat-musl -yyq 
#[ "" != "$(which wkhtmltopdf)" ] && alias html2pdf=$(which wkhtmltopdf) || sudo apt install wkhtmltopdf -yyq

if [ "" != "$(which grc)" ] # Generic colouriser
then
    alias configure='grc ./configure'
    alias curl='grc curl'
    alias df='grc df -h --total -x tmpfs 2>/dev/null;:'
    alias dig='grc dig'
    alias env='grc env'
    alias fdisk='grc fdisk'
    alias free='grc \free -ht'
    alias gcc='grc gcc'
    alias id='grc id'
    alias ifconfig='grc ifconfig'
    alias ip='grc ip'
    alias iostat='grc iostat'
    alias last='grc last -5 -adx'
    alias ls='grc ls'
    alias lsof='grc lsof'
    alias lsattr='grc lsattr'
    alias lspci='grc lspci'
    alias make='grc make'
    alias mount='grc mount'
    alias mtr='grc mtr'
    alias netstat='grc netstat'
    alias nmap='grc nmap'
    alias ping='grc ping'
    alias ps='grc ps'
    alias sar='grc sar'
    alias ss='grc ss'
    alias stat='grc stat'
    alias systemctl='grc systemctl'
    alias traceroute='grc traceroute'   
    alias uptime='grc uptime'
    alias vmstat='grc vmstat'
    alias w='grc w'
    alias whois='grc whois'
fi

# Common options to save time
# ---------------------------
alias dmesg='dmesg -T'
alias du='du -sh * |sort -h'
alias sl='sl -la '
alias glow='glow -t'
alias grep='grep --color=always'           # Only works with GNU version
alias head='head -n $((${LINES:-`tput lines 2>/dev/null||echo -n 12`} - 2))'  # resize out to num of lines
alias h=history
alias j='jobs -l'                          # Displays background jobs
alias l='ls --group-directories-first --color -lh'
alias lsd='tree -C -d -L 1'
alias ls='grc ls --color -hF'
alias rm='play -q ~/Music/sounds/yaru/trash-empty.oga 2>/dev/null 1>&2;rm -v -I' 
alias sudo='sudo -E'
alias tail='tail -n $((${LINES:-`tput lines 2>/dev/null||echo -n 12`} - 2))'  # resize out to num of lines
alias wget='wget -c'                       # Allows restart
alias llm='line;lm'

# Navigations
# -----------
alias ..="cd .. && lsd"                    # drop one level
alias apps='cd /var/www/apps;lsd'
alias bin='cd ~/bin'
alias c='cd;clear;~/bin/quote'
alias d='cd ~/Downloads;clear;~/bin/quote;line;lm' # I work in this directory a lot
alias t='cd ~/Temp;clear;~/bin/quote'       # I work in this directory a lot
alias wd='cd /var/www; lsd'
alias pics='cd /var/www/include/pics; lsd'
alias mp3s='cd /var/www/include/mp3; lsd'


# New commands
# ------------
alias connections="ss -at '( dport = :8080 or sport = :8080 )'"
alias bat=batcat
alias bt='ssh -q -X -tt mitch-laptop /home/mitch/bin/bt'
alias ab='ssh -q -X -tt mitch-laptop /home/mitch/bin/ab'
alias dark='transset -a --inc 0.15'        # set display darker
alias excuse='shuf -n1 /var/www/unix/excuses.txt |/home/mitch/.local/bin/tte $(shuf -n1 ~/etc/tte.txt)'
alias fortune='clear;\fortune|fmt | boxes -d "$(shuf -n1 ~/etc/boxes-full.txt)"|tte -R'
alias lt='ssh mitch-laptop'
alias light='transset -a --dec 0.15'
alias links='site -m links'
alias m='ssh -q -X -tt mitch-laptop /home/mitch/bin/m'
alias password='echo "$(tr -dc 'A-Za-z0-9!?%=' < /dev/urandom | head -c 10)"'
alias pd='jot -e my-kt.md'                 # jot is my notes manager
alias perf='sar -s $(date -d "1 hours ago" +%H):00:00' # what's going on?
alias please='sudo $(fc -ln -1)'           # if it did not work, say please
alias quote=~/bin/quote
alias rbr='epy ~/Documents/books/bible/ruckmans-bible-references.epub'
alias rogue='~/bin/roguepc;./rogue'
alias sd='find * -type d | fzf'
alias slog='multitail --config ~/.multitail.conf  -cS syslog -Q 1 --no-repeat /var/log/syslog  -e 'ssh' /var/log/auth.log'
alias slog='multitail -Q 1 --no-repeat -wh 7 /var/log/auth.log /var/log/syslog'
alias space='duf -only local'
alias spider='wget --random-wait -r -p -e robots=off -U mozilla' # spider a site
alias sp='ssh -q -X -tt mitch-laptop /home/mitch/bin/jot -e scratch.md'               # scratch pad
alias s='cd ~/Downloads;xs'
alias ticker='ssh mitch-laptop -q -t ticker'
alias now='ssh -q -X -tt mitch-laptop /home/mitch/bin/now -time'
alias task='ssh -q -X -tt mitch-laptop /home/mitch/bin/now -time -t'
alias temp='watch sensors -f'
alias top='btop'
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'
alias vf='vim -c Explore'
alias vp='videopoker -mh'
alias weather='inxi --wu i -xxxw'
alias wisdom='while :; do clear; quote; read x; done'
alias work='web;x'
alias wl='more ~/etc/work-links.md'
alias x='play -q ~/Music/sounds/yaru/desktop-logoff.oga 2>/dev/null;exit'

# Bash options
# ============
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
shopt -s cmdhist        # Save all lines of a multiple-line command in the same history entry
shopt -s cdspell        # Fix minor spelling error's in 'cd' command
shopt -s checkwinsize   # Handle xterm resizing
shopt -s dotglob        # Allow tab-completion of '.' filenames
shopt -s extglob        # Bonus regex globbing!
shopt -s hostcomplete   # Tab-complete words containing @ as hostnames
shopt -s histappend     # multiple sessions to write to the history
shopt -s execfail       # Failed execs don't exit shell
set -o notify           # Show status of terminated programs immediately


# Tab (readline) completion settings
# ----------------------------------
set show-all-if-ambiguous on    # Show more w/ 1 <tab>   {new}
set visible-stats on            # Appends files to <tab> completes {new}
set completion-ignore-case on   # Ignor case in completion
set match-hidden-files off      # Allow matching on hidden files

# History
# -------
set bashhistfile=1000 # Number of history file entries
set dunique           # Removes duplicate entries in the dirstack
set histdup=prev      # Do not allow consecutive duplicate history entries

# General
# -------
set ulimit -c 0       # Turn off core dumps
set notify            # Notifies when a job completes

# Command line completion
# -----------------------
complete -A hostname   rsh rcp telnet rlogin r ftp ping disk ssh
complete -A command    nohup exec eval trace gdb
complete -A command    command type which
complete -A export     printenv
complete -A variable   export local readonly unset
complete -A enabled    builtin
complete -A alias      alias unalias
complete -A function   function
complete -A user       su mail finger
complete -A directory  mkdir rmdir
complete -A directory   -o default cd
complete -f -d -X '*.gz'  gzip extract  
complete -f -d -X '*.bz2' bzip2 extract 
complete -f -o default -X '!*.gz'  gunzip extract   
complete -f -o default -X '!*.bz2' bunzip2 extract  
complete -f -o default -X '!*.zip' zip extract  
complete -f -o default -X '!*.pl'  perl perl5
complete -f -o default -X '!*.ps'  gs ghostview ps2pdf ps2ascii
complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype
complete -f -o default -X '!*.pdf' acroread pdf2ps
complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
complete -f -o default -X '!*.tex' tex latex slitex
complete -f -o default -X '!*.lyx' lyx
complete -f -o default -X '!*.+(jpg|gif|xpm|png|bmp)' xv gimp
complete -f -o default -X '!*.+(epub|epub3|fb2|mobi|azw3)' v epy
complete -f -o default -X '!*.+(avi|mp4|mpv|flv|wma|mkv)' vlc mp dr pi rc mplayer
complete -f -o default -X '!*.mp3' vlc mp mplayer
complete -f -o default -X '!*.ogg' vlc mp mplayer
complete -f -o default -X '!*.md' site vim gvim retext e mdv glow compile

# FUNCTION DEFINITIONS
# ====================

backup() { ## version number a file{s} before changing them
    if [[ $# -eq 0 ]]; then
        echo "Usage: backup <filename>"
        return 1
    fi
    for file in "$@"; do
        if [[ -f "$file" ]]; then
            # Using --force and --backup=numbered on the same file name
            # triggers the built-in GNU versioning mechanism.
            cp --force --backup=numbered --verbose "$file" "$file"
        else
            echo "Error: '$file' is not a valid file."
        fi
    done
}

bl(){ ## write a blank line
    # Use: bl
    [ "$DEBUG" == "1" ] && set -x
    echo ""
}

bm(){ ## view bookmarks from shell
    # Use: bm
lynx ~/etc/bookmarks.html
}

bold(){ ## add file to .bold
    # Use: bold {file}
echo $1 >>.bold
files
}

center(){ ## center text on a line
    # Use: center "string" {optional fill character}

     [[ $# == 0 ]] && return 1

     declare -i TERM_COLS="$(tput cols)"
     declare -i str_len="${#1}"
     [[ $str_len -ge $TERM_COLS ]] && {
          echo "$1";
          return 0;
     }

     declare -i filler_len="$(( (TERM_COLS - str_len) / 2 ))"
     [[ $# -ge 2 ]] && ch="${2:0:1}" || ch=" "
     filler=""
     for (( i = 0; i < filler_len; i++ )); do
          filler="${filler}${ch}"
     done

     printf "%s%s%s" "$filler" "$1" "$filler"
     [[ $(( (TERM_COLS - str_len) % 2 )) -ne 0 ]] && printf "%s" "${ch}"
     printf "\n"

     return 0
}

check(){ ## check for entry
    cd /var/www
    for MD in $(find . -name '*.md' -print)
    do
        grep -Hc "$1" $MD |egrep -v '0$'
    done
    echo "${BY} $(find . -name "$1" -print)${N}"
    cd - >/dev/null
}

crn(){ ## connect to web server
event login
if [ -z $DISPLAY ]
then
    ssh -q -X -tt crn "$*"
else
    [ "$#" -gt 0 ] && TITLE="-T $*"
    xfce4-terminal --tab --geometry=100x27 $TITLE --active-tab -x ssh -q -X -tt crn "$*"
fi
clear
}

ct(){ ## Coffee timer or cooking timer
    # Use: ct {time} 
    if [ "$#" -gt 0 ]
    then
        echo -n "${BG}Cooking timer $1${N} ⏳ " ;spinit sleep $1
    else
        # French press timer (default action)
        echo -n "${BG}Making Coffee${N} ☕ " ;spinit sleep 4m
    fi
    if [ -z $DISPLAY ]
    then
        clear
        if [ "$#" -gt 0 ]
            then
                echo "⏳${BR}Done${N}"
            else
                echo "☕${BR}Coffee ready${N}"
        fi
        bl
    else
        if [ "$#" -gt 0 ]
            then
                notify-send -u critical "⏳ Done!"
            else
                notify-send -u critical "☕ Coffee ready!"
        fi
        mpv ~/Music/sounds/chime.wav >/dev/null 2>&1
    fi
}

db(){ ## open a database
    cd ~/db
    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="➤ ")
    case $CHOICE in
        *sqlite) sqlite3 $CHOICE
            ;;
        *) vd $CHOICE
            ;;
    esac
    cd -
}

display(){ ## show display settings
    # Use: display (no options)
    [ "$DEBUG" == 1 ] && set -x
    if [ -z $DISPLAY ]
    then
        xfce4-terminal --color-table
        echo "${BG}Display:${N} $(w|tail -1|awk '{print $3}') ${BC} $TERM${N} $(tput lines)r x $(tput cols)c"
    else
        xfce4-terminal --color-table
        echo "${BG}Display: ${BY}$DISPLAY${N} ${BC}$TERM${N}  $(tput lines)r x $(tput cols)c"
    fi
    line
}

ul(){ ## Upload to server files
    rsyncy  "$@" ${DL}
    play -q ~/Music/sounds/system/completion-success.oga  2>/dev/null
    rm -i "$@"
}

edir(){ ## emoji directory used in PS1
    # Use: See $PS1 at top of this file
    [ "$#" -ne 0 ] && grep -A 1 \^edir ~/.bashrc && return
    case $PWD in # Order is important, stops on 1st match
        *Archives*) echo -n "📦 ";;
        *bin*) echo -n "🔧 ";;
        *etc*) echo -n "⌨  ";;
        *Documents*) echo -n "📃 ";;
        *Downloads*) echo -n "🔽 ";;
        *jots*) echo -n "📝 ";;
        *Music*) echo -n "🎧 ";;
        *pics*|*Pictures*) echo -n "📸 ";;
        *tmp*|*Temp*) echo -n "🚽 ";;
        *vids*|*Videos*) echo -n "🎬 ";;
        *web*|*www*) echo -n "🕸 ";;
        /home/mitch) echo -n "🏠 ";;
        *) echo -n "📂 ";;
    esac
}

emoji(){ ## search and display emoji
    # Use: emoji -h or --help for use
case $1 in
    -s) # search
        grep -i --color $2 ~/etc/emoji.txt
        ;;
    -r) # random
        shuf -n 1 <~/etc/emoji.txt|cut -d' ' -f1
        ;;
    -R) # random
        shuf -n 1 <~/etc/emoji.txt|cut -d' ' -f1| tr -d \\n 
        ;;
    -d) # dump
        for SMILE in $(cut -d' ' -f1 <~/etc/emoji.txt)
        do
            echo -n $SMILE
        done
        ;;
    *) # help
        fmt -s -w $(tput cols)<<END
${BG}emoji${N} {option}
-s {text}  # search
-r         # random
-R         # random, no new line
-d         # dump
END
        ;;
esac
}

explain () { ## Use the explain API to explain commands - from the command line!
  if [ "$#" -eq 0 ]; then
    while read  -p "Command: " cmd; do
      curl -Gs "https://www.mankier.com/api/v2/explain/?cols="$(tput cols) --data-urlencode "q=$cmd"
    done
    echo "Bye!"
  elif [ "$#" -eq 1 ]; then
    curl -Gs "https://www.mankier.com/api/v2/explain/?cols="$(tput cols) --data-urlencode "q=$1"
  else
    echo "Usage"
    echo "explain                  interactive mode."
    echo "explain 'cmd -o | ...'   one quoted command to explain it."
  fi
# Update 26-03-2015. If using this command gives no output, see if running a simple fetch causes this error:
# $ curl https://www.mankier.com
# curl: (35) Cannot communicate securely with peer: no common encryption algorithm(s).
# If so, try specifying a cipher in the curl commands: curl --ciphers ecdhe_ecdsa_aes_128_sha
}


extract(){ ## handy archive extraction
    # Use: extract {file}
    [ "$DEBUG" == 1 ] && set -x
    if [ -f $1 ]
    then
        case $1 in
            *.tar.bz2)   tar xvjf $1     ;;
            *.tar.gz)    tar xvzf $1     ;;
            *.bz2)       bunzip2 $1      ;;
            *.rar)       unrar x $1      ;;
            *.gz)        gunzip $1       ;;
            *.tar)       tar xvf $1      ;;
            *.tbz2)      tar xvjf $1     ;;
            *.tgz)       tar xvzf $1     ;;
            *.zip)       unzip $1        ;;
            *.Z)         uncompress $1   ;;
            *.7z)        7z x $1         ;;
            *)           echo "${BR}$1 ${N}cannot be extracted via >extract<"
                        file $1;;
        esac
        play -q ~/Music/sounds/system/dialog-information.oga 2>/dev/null 1>&2
    else
        echo "${BR}$1 $N is not a valid file"
    fi
}

fr() { ## fuzzy run
launchapp=$(IFS=':'; \
  for p in ${PATH}; \
  do find -L "${p}" -type f -executable -print 2> /dev/null; done \
  | fzf --header="Select application to launch:" \
    --exact \
    --height="50%" \
    --preview="(file -b {})" \
    --preview-window="down:wrap:25%") \
  && eval "${launchapp}"
}

gmt(){ ## display GMT (for radio stuff)

    command -v tty-clock >/dev/null || sudo apt install tty-clock -yyq
    xtitle "GMT Clock"
    tty-clock -usxrB -C $(( ( RANDOM % 6 ) + 1 ))
}

html(){ ## mark up code, etc...
    # Use: html {file}
vim -f +"syn on" +"colorscheme termschool" +"set nonu" +"set foldenable!" +"set nospell" +"run! syntax/2html.vim" +"wq" +"q" $1
}

hping(){ ## httping with favorite options
    # Use: hping {name}    (defaults to my site)
    PINGHOST="$1"
    httping ${PINGHOST:=crn.hopto.org} -c 10 -S -Y -Z -s --offset-yellow 370 --offset-red 380 -K
}

large (){ ## find files larger than 800m
    find . -type f -name "*.mp4" -size +800M -exec ls -lh {} \; | awk '{print $5, $9}'
}

log(){ ## creates a basic log entry $LOG must be defined
    # Use: log {entry}  
    [ "$DEBUG" == "1" ] && set -x
    logger -i -t "$NAME" "$*"
}

man(){ ## run mangl if DISPLAY is set
    if [ -z $DISPLAY ]
    then
        /usr/bin/man $1
    else
        mangl  $1 2>/dev/null
    fi
}

md2pdf(){ ## covert markdown to pdf
pandoc ${1%.md}.md -o ${1%.md}.html
cat  ${1%.md}.html |htmldoc --cont --headfootsize 8.0 --linkcolor blue --linkstyle plain --format pdf14 - >  ${1%.md}.pdf && gio trash ${1%.md}.html
}

more(){ ## updated to set title bar
    # Use: more {file}
    xtitle "more $*"
    EXT="${1##*.}"
    case $EXT in
        epub|fb2|mobi) # books
            /home/mitch/.local/bin/epy $1
            ;;
        md) # markdown
            glow -t $1
            ;;
        csv|tsv) # tab/csv separated
            cat $1 |pspg --${EXT} --style=6
            ;;
        json|xlsx|xls|sqlite) # sqlite3
            vd $1
            ;;
        *) # default
            bat $1
            ;;
    esac
}

mp(){ ## media player front end
    FZF_DEFAULT_OPTS="--ansi  "
    # Use: mp {optional file}
    [ "$1" == "-d" ] && cd ~/Downloads  # jump to download directory
    [ -z $DISPLAY ] || WINDOW=$(xdotool getactivewindow 2>/dev/null) # get window ID
    clear
    if [ -f "$1" ]  # if you give it a file run it, else display a list
    then
        CHOICE="$1"
    else
        xtitle "mp: Name sort" 
        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="➤ ")
    fi
    EXT="${CHOICE##*.}"
    [ "$EXT" == "mp3" ] && FILE=$(echo $CHOICE|cut -d ' ' -f5)
    [ "$EXT" == "mp4" ] && FILE=$(echo $CHOICE|cut -d ' ' -f4)
    if [ ! -z $FILE ]
    then
        if [ ! -z $DISPLAY ] 
        then
            xtitle "$FILE"
            echo -n "Playing: $FILE "
            xdotool windowminimize $WINDOW
            xfconf-query --channel=xfwm4 --property=/general/use_compositing --type=bool --toggle
            spinit vlc --play-and-exit $FILE 1>&2 2>/dev/null
            xdotool windowactivate $WINDOW
            xfconf-query --channel=xfwm4 --property=/general/use_compositing --type=bool --toggle
            if [ -f $FILE -a "$(pwd)" == "/home/mitch/Downloads" ]  || [ "$(pwd)" == "/var/hold/Downloads" ] 
            then
                clear
                read -p "${BR}Remove:${BY} ${FILE}?${N} " -n 1 DEL
                if [ "$DEL" == "y" ] 
                then
                    rm $FILE 
                fi
                bl
                if [ -f $FILE ] 
                then
                    read -p "${BR}Upload:${BY} ${FILE}?${N} " -n 1 DEL
                    [ "$DEL" == "y" ] && ul $FILE 
                fi
                bl
                if [ -f $FILE ]
                then
                    bl
                    read -p "${BY}mv${N} $FILE to ~/Temp? " -n 1 MV
                    [ "$MV" == "y" ] && mv $FILE ~/Temp
                fi
            fi
            if [ "$1" == "-n" ]
                then
                    clear
                    [[ $(\ls -A *.mp? 2>/dev/null) ]] && llm || echo "No files"
                else  
                    clear
                    [[ $(\ls -A *.mp? 2>/dev/null) ]] && llm -t || echo "No files"
            fi
        else
            echo "$FILE not played, no DISPLAY"
        fi
    fi
}

pause(){
    [ "$DEBUG" == "1" ] && set -x;
    [ "$1" == "-nt" ] && TMOUT="" && shift;
    echo "$BY";
    if [ $# -gt 0 ]; then
        read -t $1 -r -p "${C}Hit any key (${BY}$1${C} second timeout)${N}" -n 1 FOO;
    else
        read -r -p "${C}Hit any key${N}" -n 1 FOO;
    fi;
    bl
}

r(){ # r run it!
    # Use: r {optional pattern: p*}
    if [ $(\ls -F|grep -c '\*') -lt 1 ] 
    then
        echo "${BY}Nothing to do${N}"
    else
        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="➤ ")
        if [ ! -z "$CHOICE" ] 
        then
            tldr $CHOICE 2> /dev/null | tail -n +3
            read -p "${BG}${CHOICE} ${N}" ARGS
            ./${CHOICE} $ARGS
        fi
    fi
}

rcf() { ## Function to set random background and foreground colors with contrast       # Use: rcf "string"

    # Generate random 1-6 for fg/bg to ensure contrast (avoiding 0/7/8)
    local fg=$(( (RANDOM % 6) + 1 ))
    local bg=$(( (RANDOM % 6) + 1 ))

    # Ensure background is not too similar to foreground
    while [ $fg -eq $bg ]; do
        bg=$(( (RANDOM % 6) + 1 ))
    done

    # Apply colors and print
    tput setaf $fg
    tput setab $bg
    tput bold # Make text bold for better readability
    echo -n " $1 "
    tput sgr0 # Reset colors
    echo ""
}

recover(){ ## vim recover from backup dir
    if [ -f "$1" ] 
    then
        FILE="$(pwd)/$1"
        cd ~/vim/backup
        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')
        vimdiff "$FILE" "$CHOICE"
    else
        echo "recover {file}"
        echo "
vimdiff commands

]c :         - next difference
[c :         - previous difference
do           - diff obtain
dp           - diff put
zo           - open folded text
zc           - close folded text
:diffupdate  - re-scan the files for differences
:set mouse=a - use mouse click to switch windows
CTRL-W =     - resize windows the same
CTRL-W w     - switch window
"
    fi
    cd ${OLDDIR}
}

rs(){ ## restart shell with option to edit .bashrc
    # Use: rs (if anything is passed it will edit .bashrc file 1st)
    THEME="zenburn" # bat --list-themes
    if [ $# -gt 0 ]
    then
        play -q ~/Music/sounds/system/message-new-instant.oga 2>/dev/null
        vim ~/.bashrc
        sed -i -e "3s/.*/# Updated....: $(date)/" ~/.bashrc
        # bashrc
        log "Updated ~/.bashrc"
        bat --color=always --theme $THEME ~/.bashrc | aha -b -w -t "~/.bashrc" >/var/www/unix/bashrc.html
        cp  ~/.bashrc /var/www/unix/bashrc

        # vimrc - Added to make sure the Web versions were up to date.
        sed -i -e "3s/.*/\" Updated....: $(date)/" ~/.vimrc
        bat --color=always --theme $THEME ~/.vimrc | aha -b -w  -t "~/.vimrc" >/var/www/unix/vimrc.html
        cp  ~/.vimrc /var/www/unix/vimrc

        log "Restart: $$"
        exec bash
    else
        log "Restart: $$"
        reset; exec bash
    fi
}

rss(){ ## quick rss url reader
    # Use: rss {URL} {Count, defaults to 10}
    [ "$#" -eq 2 ] && COUNT=$2 || COUNT=10    
lynx -stdin <<RSSEND
<p>rss "$1"
</p>

$(rsstail --nofail --time-format '%r %m/%d/%Y' --initial $COUNT -e 1 --format '[{title}]({link}) {updated:>10}  \n' "$1"  |pandoc -t html)

RSSEND
}

scale(){ ## change to 640x480
    (xterm -geometry 140x4+0+900 -hold -e ~/bin/scale $1 &)
}

sconky(){ ## re-start conky
    # Use: sconky (if anything is passed it will edit config file 1st)
    pkill conky
    spinit sleep 3
    (conky -d -c ~/.conkyrc)
    /home/mitch/bin/now-clocking-main/start.sh 2>&1

}

tab() { ## run command in new tab
xfce4-terminal --tab --geometry=100x27 -T "$*" --active-tab -x "$*"
}

tunes(){ ## play my music
SDIR=$(pwd)
cd ~/Music/gospel/kjv
\rm *mp3
cd ~/Music/kjv-verses
for VERSE in $(\ls |shuf -n 20)
do
    cp $VERSE ~/Music/gospel/kjv
done
cd ~/Music && find gospel/ -name '*.mp3' >tunes.m3u 
xtitle "Playing music"
xfce4-terminal --tab --geometry=100x27 --title="Tunes" --active-tab -x nvlc -Z tunes.m3u
cd $SDIR
clear
}

xtitle(){ ## set window title
    # Use: xtitle "Text to display"
    printf "\033]0;%s\007" "${*}🌀${HOSTNAME}"
}


# Ending
# ======
clear
if [ "$LOGNAME" == "mitch" ]
then
    play -q ~/Music/system/outcome-success.oga 2>/dev/null
    uptime
    status
    now -s
else
    log "Switching to root"
    echo "${BY}sudo: ${BR}switched to root$N"
    HISTFILE=/.root.hist        # keeps it out of mine
    TMOUT=600                   # Close terminal after 10 minutes of inactivity
    echo "Window timeout in: ${BY}$TMOUT seconds${N}"
    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} '
fi

[ -f ~/.fzf.bash ] && source ~/.fzf.bash


# ServerHub completion
if command -v serverhub &> /dev/null; then
    source <(serverhub completion bash 2>/dev/null || true)
fi
