Skip to content

Latest commit

 

History

History
3019 lines (2592 loc) · 85.8 KB

script.org

File metadata and controls

3019 lines (2592 loc) · 85.8 KB

Webcam

  • Use mpv for webcam. ffplay could also be used, but mpv is easier for shortcuts.
no-osc
To remove on-screen bar
low-latency
Removed the stutter from default play of video
video-align
Brings the top margin down
video-zoom
Zooms the video, so face and certain region is well covered.
title
To give, so useful to set window rules in WindowManager
mpv av://v4l2:/dev/video0 --profile=low-latency --no-osc --untimed --video-align-y=0.6 --video-zoom=1.5 --title=webcam "$@"
  • Window rule with hyprland
windowrulev2 = rounding 120,title:^(webcam)$
# windowrulev2 = bordercolor rgba(2e8b57ff) rgba(2e8b57ff), title:webcam
windowrule = size 17% 27%, title:webcam
windowrulev2 = move 82% 71%, title:webcam
bind = SUPER, F7, exec, d-webcam

Android

# setup
connect() {
	ip="$(adb shell ip route | awk '{print $9}')"
	adb devices && adb tcpip 5555 && adb connect "$ip":5555
	# Run `adb disconnect` once you're done
}

# audio recording
audio() {
	[ -d ~/music/audio/ ] || mkdir -p ~/music/audio/
	scrcpy --no-video --audio-source=mic \
		--audio-bit-rate=128K \
		--record="$(xdg-user-dir MUSIC)/audio/$(date +%d_%b_%I:%M)-recording.opus"
}

# works like a charm
camera() {
	scrcpy --video-source=camera \
		--audio-source=mic \
		--camera-facing=back \
		--camera-fps=40
}

# sound in earphone - fix mic
game() {
	scrcpy --no-video --audio-output-buffer=10
}

# Call the functions based on user input
if [ "$1" = "connect" ]; then
	connect
elif [ "$1" = "audio" ]; then
	audio
elif [ "$1" = "camera" ]; then
	camera
elif [ "$1" = "game" ]; then
	game
else
	exit 1
fi

Bookmark

  • Script to bookmark link into org-mode file.
source d-var.conf

bookmark="${1:-$(printf "%s\n%s" "$(wl-paste -p)" "$(wl-paste)" | $D_MENU -i -p '')}"

#file="$HOME/.local/share/dict/bookmarks"
file="$HOME/d-sync/notes/bookmarks.org"

# Just a variable to show as prompt while adding name (confirmation)
site="$(echo "${bookmark}" | sed 's/ //g')"

if [[ -z "$site" ]]; then
    exit 0
elif grep -qF "$site" "$file"; then
    notify-send "Oops.. $site" "Already in bookmark!"
    exit 0
fi

# Eg names so you can quickly name
# notify-send
examples=("reddit" "twitter" "git-linux" "git-emacs" "git-droid" "TODO")

title="$(printf '%s\n' "${examples[@]}" | $W_MENU -l 2 -p "${site} => Title" | sed 's/ /-/g')"

# Add your org mode file path here (headings are in level 2 in my file)
getheadings="$(rg "^\*\* " "${file}" | sed '/** gnus/q' | awk '{print $2 }')"
# ^ prints heading upto "** elfeed"
# i have added rest as rss feeds so

tags="$(rg -o "__([[:alnum:][:nonascii:]_-]*)" "$file" | uniq | sed 's/__//g' | $D_MENU -p "${title} =>  " | sed 's/ /_/g')"

# Prints out the heading text, so `sed` can append it to that heading level
[[ -n "${title}" ]] && section="$(printf "%s" "$getheadings" | $D_MENU -p ' Heading'| sed 's/ //g')"


mark-print ()
{
# Sed appends the link in a clean way
    sed -i "/$section$/a + [[$site][${title}__${tags}]]" "$file" &&
        notify-send "Bookmark added!" "$site is now saved under ==>  $section"

}


if grep -qF "$site" "$file"; then
    notify-send "Oops.. $site" "Already in bookmark!"

elif [[ -n "${section}" ]]; then
    mark-print

else
    notify-send "Give a title & section to add mark"
fi

Capslock in Wayland

  • To toggle capslock with control
# hyprctl keyword input:kb_options ctrl:nocaps

hyprctl keyword input:kb_options caps:caps

Color Picker

  • Picker using hyprpicker
  • To insert the colors in hex value
source d-var.conf

a1="󰢷 Pick a colour (HEX)"
a2="🍎 Choose a Colorname"
a3="🎨 Pick a Colour (RGB)"
pick_or_treat=$(printf "$a1\n$a2\n$a3" | $D_MENU -i -p "🎃 ")

case $pick_or_treat in
    $a1 )
	hyprpicker -a -f hex
	;;
    $a2 )
	chosen=$(bat ~/d-git/d-bin/treasure/colors | $UNI_MENU -i -p '🎨 ' | grep -o "#.*" )
	;;
    $a3 )
	hyprpicker -a -f rgb
	;;
    * )
	exit 0
	;;
esac

# Exit if none chosen.
[ -z "$chosen" ] && exit

# If you run this command with an argument, it will automatically insert the
# character. Otherwise, show a message that the emoji has been copied.

if [ -n "$1" ]; then
    # Replace with xdotool or ydotool
    wtype "$chosen"
else

    # replace with xclip or xsel or x11
    printf "$chosen" | wl-copy

    # Replace with xdotool for X11
    wtype "$chosen"

    # Tbh not required
    # notify-send "'$chosen' copied to clipboard." &
fi

Dictionary

# some cool dep :
# enchant --- spell check
# espeak-ng -- text-to-speech

word=$(echo "$(bat ~/.local/share/dict/hist ~/.local/share/dict/vocab | uniq)"| $menu -p '  Meaning for')
# echo "$word" >> /home/i/.local/share/dict/hist
# printf '\n%s\n' "$word" >> /home/i/.local/share/dict/hist

online () {
res=$(curl -s "https://api.dictionaryapi.dev/api/v2/entries/en_US/$word")
regex=$'"definition":"\K(.*?)(?=")'
definitions=$(echo $res | grep -Po "$regex")
separatedDefinition=$(sed ':a;N;$!ba;s/\n/\n\n/g' <<< "$definitions")
notify-send -t 15000 "$word" "$separatedDefinition"
}

offlinewn () {
output=$( sdcv -n0u wn $word )
notify-send -t 15000 "$word" "$output"
sdcv -n0u wn $word | rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}'
}
offlineco () {
output=$( sdcv -n0u collins $word )
notify-send -t 15000 "$word" "$output"
sdcv -n0u collins $word | rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}'
}
offlinedd () {
output=$( sdcv -n0u dictd $word )
notify-send -t 15000 "$word" "$output"
sdcv -n0u dictd $word | rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}'
}

offlinejp () {
output=$( sdcv -n0u enjp $word )
notify-send -t 15000 "$word" "$output"
sdcv -n0u enjp $word | rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}'
}

offlinesl () {
output=$( sdcv -n0u Collin $word )
notify-send -t 15000 "$word" "$output"
sdcv -n0u Collin $word | rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}'
}
offlinefr () {
output=$( sdcv -n0u enfr $word )
notify-send -t 15000 "$word" "$output"
sdcv -n0u enfr $word | rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}'
}
offlinesp () {
output=$( sdcv -n0u ensp $word )
notify-send -t 15000 "$word" "$output"
sdcv -n0u ensp $word | rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}'
}

a1="  WordNet Dictionary"
a2="📖 Collins Dictionary"
a3="📘 General Dict"
a4="🈚 Japanese Word Translate"
a5="📔 Simple Dictionary"
a6="🍟 French Word Translate"
a7="🎯 Spanish Word Translate"
b1="  Search Online"

#chose=$(printf  "📖 Offline dictionary\n📗 Oxford\n📘 Dict gcide\n📙 japanese dict\n📑 Online dictionary" | rofi -rofi -dmenu -i -theme-str 'window {height:50%; width:50%;}' -i -p '📑 Choose your Thesaurus ' -theme-str 'window {width: 30%;height: 40%;}')

chose=$(printf  "$a5\n$a1\n$a2\n$a3\n$a4\n$a6\n$a7\n$b1" | $menu -i -l 10 -p '   Choose Thesaurus ')

case $chose in
    "$a1") offlinewn ;;
    "$a2") offlineco ;;
    "$a3") offlinedd ;;
    "$b1") online ;;
    "$a4") offlinejp ;;
    "$a5") offlinesl ;;
    "$a6") offlinefr ;;
    "$a7") offlinesp ;;
esac

Extract

  • Extract utility on most compressed files.
Usage
d-ext <files>
for fi in "$@"; do
    if [ -f "$fi" ] ; then
	    case $fi in
		    *.tar.bz2)	tar xjf "$fi"	;;
		    *.tar.gz)	tar xzf "$fi"	;;
		    *.bz2)		bunzip2 "$fi"	;;
		    *.rar)		unrar x "$fi"	;;
		    *.gz)		gunzip "$fi"	;;
		    *.tar)		tar xf "$fi"	;;
		    *.tbz2)		tar xjf "$fi"	;;
		    *.tgz)		tar xzf "$fi"	;;
		    *.zip)		unzip "$fi"	;;
		    *.7z)		7z x "$fi"	;;
		    *.tar.xz)	tar xf "$fi"	;;
		    *.tar.zst)	unzstd "$fi"	;;
		    *)		echo "'$fi' cannot be extracted via ex()" ;;
	    esac
    else
	    echo "'$fi' is not a valid file"
    fi;
done

Toggle touchpad in wayland

HYPRLAND_DEVICE="elan0522:01-04f3:31c3-touchpad"

if [ -z "$XDG_RUNTIME_DIR" ]; then
  export XDG_RUNTIME_DIR=/run/user/$(id -u)
fi

export STATUS_FILE="$XDG_RUNTIME_DIR/touchpad.status"

enable_touchpad() {
  printf "true" > "$STATUS_FILE"

  notify-send -u normal "Enabling Touchpad"

  hyprctl keyword "device:$HYPRLAND_DEVICE:enabled" true
}

disable_touchpad() {
  printf "false" > "$STATUS_FILE"

  notify-send -u normal "Disabling Touchpad"

  hyprctl keyword "device:$HYPRLAND_DEVICE:enabled" false
}

if ! [ -f "$STATUS_FILE" ]; then
  disable_touchpad
else
  if [ $(cat "$STATUS_FILE") = "true" ]; then
    disable_touchpad
  elif [ $(cat "$STATUS_FILE") = "false" ]; then
    enable_touchpad
  fi
fi

Idle

  • To run idle timeout function when audio is running or not.
  • Useful to avoid suspending or locking screen.
# only suspend if audio isn't running
if [ "$(pw-cli i all | rg running)" ]; then
    eval "$1"
else
    eval "$2"
fi

Menu Launcher

  • Generic menu launcher for scripts.
  • To index all scripts.
source d-var.conf

menuopts=(" Powermenu" "󰸉 Change Wallpaper" " Handle Stuffs" " Music Menu" " Pirate Mode" " Insert Emoji/Icons" "﬜ Dictionary" " Set Reminder" "⏲ Time & Date Now" " System Stats" " YouTube" " TODO" " Web Search")

chosen=$(printf '%s\n' "${menuopts[@]}" | $D_MENU)

case "$chosen" in
        "${menuopts[0]}") d-power ;;
        "${menuopts[1]}") d-walls ;;
        "${menuopts[2]}") d-stuff ;;
        "${menuopts[3]}") d-mpdplay ;;
        "${menuopts[4]}") d-pirt ;;
        "${menuopts[5]}") d-unicodes ;;
        "${menuopts[6]}") d-dict ;;
        "${menuopts[7]}") d-remind ;;
        "${menuopts[8]}") d-time ;;
        "${menuopts[9]}") d-stats ;;
        "${menuopts[10]}") ytfzf -D ;;
        "${menuopts[11]}") d-todo ;;
        "${menuopts[12]}") d-search ;;
	*) exit 1 ;;
esac

Music Player Menu

  • An script to play mpd music.
MPC="mpc --quiet -p ${1:-6600}"
pidof -x mpd || mpd

source d-var.conf

DMENU() {
    # Vertical menu if $3 is given
    printf '%s\n' "$1" | $L_MENU -p "$2"
}

get_playlist() {
    $MPC -f "%position% - %artist% - %album% - %title%" playlist
}

select_from() {
    DMENU "$1" "Select $2" $height
}

add() {
    all="[ALL]"

    local artist=$(select_from "$($MPC list Artist)\n$all" "artist")

    if [ "$artist" = "$all" ]; then
        $MPC listall | $MPC add;
    elif [ -n "$artist" ]; then
        local albums=$($MPC list Album Artist "$artist")
        local album=$(select_from "$albums\n$all" "album")

        if [ "$album" = "$all" ]; then
            $MPC findadd Artist "$artist"
        elif [ -n "$album" ]; then
            local songs=$($MPC list Title Album "$album")
            local song=$(select_from "$songs\n$all" "song")

            if [ "$song" = "$all" ]; then
                $MPC findadd Album "$album"
            elif [ -n "$song" ]; then
                $MPC findadd Title "$song"
            fi
        fi
    fi
}

remove() {
    local playlist=$(get_playlist)
    local song=$(select_from "$playlist" "song")

    [ -n "$song" ] && $MPC del "${song%%\ *}"
}

queue() {
    nowp=$(mpc status | head -n1)
    nextp=$(mpc queued)
    notify-send "Now: $nowp" "Next: $nextp"
}

jump() {
    local playlist=$(get_playlist)
    local song=$(select_from "$playlist" "song")

    [ -n "$song" ] && $MPC play "${song%%\ *}"
}

toggle(){
    $MPC toggle
}

play(){
    $MPC findadd Title "$($MPC list title | $L_MENU)"
    $MPC play
}

pause(){
    $MPC pause
}

stop(){
    $MPC stop
}

next(){
    $MPC next
}

prev(){
    $MPC prev
}

ytmusic () {
    $MPC add "$(yt-dlp -f bestaudio -g "$(ytfzf -LD --ii='y.com.sb')")"
}

menuopts=( " Clear"  "󰐒 Add" "󰵩 Remove" "󱫜 Jump"  " Toggle" " Play"  " Pause"  " Stop" "󰒭 Next" "󰒮 Prev" "󱕱 Queued" " YT Music")

while true; do
    action=$(printf '%s\n' "${menuopts[@]}" | $L_MENU -p " Do you want to")
    case $action in
        "${menuopts[0]}") $MPC clear ;;
        "${menuopts[1]}") add ;;
        "${menuopts[2]}") remove ;;
        "${menuopts[3]}") jump ;;
        "${menuopts[4]}") toggle ;;
        "${menuopts[5]}") play ;;
        "${menuopts[6]}") pause ;;
        "${menuopts[7]}") stop ;;
        "${menuopts[8]}") next ;;
        "${menuopts[9]}") prev ;;
        "${menuopts[10]}") queue ;;
	    "${menuopts[11]}") ytmusic ;;
        "") exit 0;;
    esac
done

Pirt

  • Script to get the free stuffs.
# Dependencies - Deluge, mpv

source d-var.conf

mkdir -p $HOME/.cache/notflix

DOWNLOAD_DIR="$HOME/Documents/Torrent"

baseurl="https://www.1337x.to"

cachedir="$HOME/.cache/notflix"

LOG_FILE="$HOME/.cache/notflix/notflix_history"

[[ -f "$LOG_FILE" ]] && LS="$(cat $LOG_FILE)"
[[ -z "$LS" ]] && LS=""

PAGE=1

scrape()
{

S_QRY="$(echo "$QUER_Y" | sed 's/[[:space:]]/_/g')"

#menu="fzf --no-preview --cycle --layout=reverse --header-first --header=Torrent-Results:($S_QRY/Page-$PAGE)"
menu="$L_MENU -i -p $PAGE*"

[[ -z "$QUER_Y" ]] && exit

query="$(echo "$QUER_Y" | sed 's/ /+/g')"

b1="general page"
b2="movie page"
b3="latest page"
b4="top 100"
b5="trending"
b6="documentary"
b7="music"
b8="free"
chose=$(printf "$b1\n$b2\n$b3\n$b4\n$b5\n$b6\n$b7\n$b8" | $D_MENU -l 18 -p '󱛵 ')
case $chose in
  "$b1") curl -s $baseurl/search/$query/$PAGE/ --compressed > $cachedir/tmp.html ;;
  "$b2") curl -s $baseurl/category-search/$query/Movies/1/ --compressed > $cachedir/tmp.html ;;
  "$b3") curl -s $baseurl/sort-search/$query/time/desc/$PAGE/ --compressed > $cachedir/tmp.html ;;
  "$b5") curl -s $baseurl/trending --compressed > $cachedir/tmp.html ;;
  "$b4") curl -s $baseurl/top-100 --compressed > $cachedir/tmp.html ;;
  "$b6") curl -s $baseurl/cat/Documentaries/$PAGE/  --compressed > $cachedir/tmp.html ;;
  "$b7") curl -s $baseurl/popular-music-week  --compressed > $cachedir/tmp.html ;;
  "$b8") curl -s $baseurl/popular-xxx-week --compressed > $cachedir/tmp.html ;;

esac

# Get Titles
grep -o '<a href="/torrent/.*</a>' $cachedir/tmp.html | sed 's/<[^>]*>//g' > $cachedir/titles.bw

result_count=$(wc -l $cachedir/titles.bw | awk '{print $1}')
if [ "$result_count" -lt 1 ]; then
 echo "No Result found!"
 exit 0
fi

# Seeders and Leechers
grep -o '<td class="coll-2 seeds.*</td>\|<td class="coll-3 leeches.*</td>' $cachedir/tmp.html |
  sed 's/<[^>]*>//g' | sed 'N;s/\n/ /' > $cachedir/seedleech.bw

# Size
grep -o '<td class="coll-4 size.*</td>' $cachedir/tmp.html |
  sed 's/<span class="seeds">.*<\/span>//g' |
  sed -e 's/<[^>]*>//g' > $cachedir/size.bw

# Links
grep -E '/torrent/' $cachedir/tmp.html |
  sed -E 's#.*(/torrent/.*)/">.*/#\1#' |
  sed 's/td>//g' > $cachedir/links.bw

# Clearning up some data to display
sed 's/\./ /g; s/\-/ /g' $cachedir/titles.bw |
  sed 's/[^A-Za-z0-9 ]//g' | tr -s " " > $cachedir/tmp && mv $cachedir/tmp $cachedir/titles.bw

awk '{print NR " - ["$0"]"}' $cachedir/size.bw > $cachedir/tmp && mv $cachedir/tmp $cachedir/size.bw
awk '{print "[S:"$1 ", L:"$2"]" }' $cachedir/seedleech.bw > $cachedir/tmp && mv $cachedir/tmp $cachedir/seedleech.bw

[[ "$PAGE" > 1 ]] && echo "Previous Page" >> $cachedir/titles.bw

echo "Next Page" >> $cachedir/titles.bw

# Getting the line number
LINEO=$(paste -d\   $cachedir/size.bw $cachedir/seedleech.bw $cachedir/titles.bw | sed 's/^ //g' | $L_MENU  -p '')

LINE=$( echo "$LINEO" | cut -d\- -f1 | awk '{$1=$1; print}')

if [ -z "$LINE" ]; then
exit 0
fi

# Next Page
[[ "$LINE" = "Next Page" ]] && PAGE=$(($PAGE+1)) && scrape

#Previous Page
[[ "$LINE" = "Previous Page" ]] && PAGE="$(($PAGE-1))" && scrape


url=$(head -n $LINE $cachedir/links.bw | tail -n +$LINE)
fullURL="${baseurl}${url}/"

# Requesting page for magnet link
curl -s $fullURL > $cachedir/tmp.html
magnet="$(grep -Po "magnet:\?xt=urn:btih:[a-zA-Z0-9]*" $cachedir/tmp.html | head -n 1)"

[[ -z "$magnet" ]] && echo "Can't Get the Link!" && exit

PROMPTO="$(echo -e "Deluge\nAria Daemon\nCopyUrl" | sort | $D_MENU -p 'magnet to')"

LOG()
{
  echo "$LINEO" > $LOG_FILE
}

case $PROMPTO in
  Deluge)
    deluge-console add "$magnet"
    notify-send " 🛫 Downloading Torrent"
    exit
    ;;
  "Aria Daemon")
    curl http://localhost:6800/jsonrpc -d '{"jsonrcp":"2.0","id":"someID","method":"aria2.addUri","params":["token:ariatest",["'${magnet}'"]]}'
    notify-send "Added download"
    ;;
  CopyUrl)
    echo "$magnet" | wl-copy
    notify-send " 🧲 Copied Magnet"
    exit
    ;;
  *)
    ;;

  esac

exit

}



seqr="$(echo -e "complete\nhashminer\nmusafir\nPSA\nBONE" | $D_MENU -l 10 -p '')"
[[ -z "$@" ]] &&
QUER_Y="$seqr" && scrape



#[[ -z "$@" ]] && read -r -p "Last Torrent: $LS
#Search Torrent: " $seqr && scrape || QUER_Y="$seqr" && scrape

Scratch Note

  • To type note in emacs buffer, and input it into some input place.
pgrep emacs || (notify-send "Are you running emacs daemon?" & exit 1)
source d-var.conf

a1=" Browser Input"
a2=" Capture Note/Thought"
output=$(date +'%d-%a->%H:%M:%S')
filename="BrowserInput"

choice=$(printf "$a1\n$a2" | $D_MENU -p '󰠮 ')

browser_input () {
    touch /tmp/${filename}.md &&
	emacsclient -c -F "((name . \"${filename}\"))"  /tmp/${filename}.md &&
	# pandoc -t markdown -o /tmp/${filename}.md /tmp/${filename}.org &&
	# wtype -s 1 "$(bat /tmp/${filename}.md)" >/dev/null &&
	mkdir -p /tmp/browse-inputs
    mv /tmp/${filename}.md /tmp/browse-inputs/${filename}-${output}.md >/dev/null
}

capture_note () {
    emacsclient -c -F "((name . \"${filename}\"))" -e '(org-capture nil "jj")' -e '(delete-other-windows)'
}

case $choice in
    $a1) browser_input ;;
    $a2) capture_note ;;
    *) exit 1 ;;
esac

Power Menu

  • Power menu script.
source d-var.conf

wifi_m="  Wifi Menu"
power_m="  Power Menu"
sshot_m="󰹑  Screen Shot"
lock="  Lock/Suspend"
brightn="󰃡  Brightness"
volume="  Change Volume"

poweroff="  Power Off"
reboot="  Reboot"
screenoff="  Screen Off"

brightup="󰃝  Increase Brightness"
brightdown="  Decrease Brightness"

volup="  Increase Volume"
voldown="  Decrease Volume"
mute="  Mute"

chosen="$(printf "$wifi_m\n$power_m\n$sshot_m\n$lock\n$brightn\n$volume" | sort | $S_MENU -p '' )"

case "$chosen" in
    "$power_m")
	power="$(printf "$poweroff\n$reboot\n$screenoff" | sort | $S_MENU -p '' )"
	case "$power" in
	    "$poweroff") poweroff ;;
	    "$reboot") reboot ;;
	    "$screenoff") hyprctl dispatch dpms  off ;;
	esac
	;;

    "$wifi_m") d-wifi ;;
    "$lock") hyprlock ;;
    "$brightn")

	bright="$(printf "$brightup\n$brightdown" | sort | $D_MENU )"

	case "$bright" in
	    "$brightup") brightnessctl set +2% ;;
	    "$brightdown") brightnessctl set 2%- ;;
	esac
	;;

    "$sshot_m") d-sshot ;;
    "$volume")

	vol="$(printf "$volup\n$voldown\n$mute" | sort | $D_MENU -p '')"
	case "$vol" in
	    "$volup") pamixer -ui 5 ;;
	    "$voldown") pamixer -ud 5 ;;
	    "$mute") pamixer -t ;;
	esac
	;;
    *) exit 1 ;;
esac

ppt -> pdf

  • Script to read ppt files as pdf.
  • Requires: soffice | ebook-convert | md2pdf
# zaread cache path
ZADIR="$HOME"'/.cache/zaread/'
# reader with which we'll open pdf, epub and converted files
reader="sioyek"

# here we have the execs we use to convert. if you want to use a custom exec,
# then set it here, and go down in the script to find (and edit) the proper command
MOBI_CMD="ebook-convert"
OFFICE_CMD="soffice"
MD_CMD="md2pdf"

# if $ZADIR doesn't exist, we create it.
if [[ ! -d "$ZADIR" ]]; then
  mkdir -p "$ZADIR"
  mkdir "$ZADIR"cksum
fi

# if no arguments exit.
if [[ -z $@ ]]; then exit 1; fi

# if zathura is not installed, we force the user to choose a pdf reader
# after three wrong commands, the script exits 1
# if the user inserts a command that exists but is not a pdf reader then... then fuck him.
counter=0
while [[ -z `command -v "$reader"` ]]; do
  if [ $counter -gt 3 ]; then exit 1; fi
  let counter+=1
  echo "Seems that you don't have zathura installed. Please choose an installed PDF reader:"
  read reader
done
echo "We'll read PDF with $reader."


## create position and file variables ##

# complete file name (path excluded):
file=`echo "$@" | rev | cut -d'/' -f1 | rev`

# complete directory path:
# if it has been inserted absolute path ($@ starts with '/')
if [[ $@ =~ ^/ ]]; then
  directory=`echo "$@" | rev | cut -d'/' -f2- | rev`"/"
# else (relative path inserted)
else
  dir=`pwd`"/"`echo "$@" | sed 's|.[^/]*$||'`"/"
  directory=`echo "$dir" | sed 's|//|/|'`
fi
echo "$directory""$file"

# get file type

# if the file is itself a pdf or an epub, or we already have a pdf converted version,
# then we don't need a converter. But if it's an already converted document, then
# file position is different: we must distinguish between original and converted files
file_converter=""
file_mt=`file --mime-type "$directory$file" | sed 's/^.*: //'`
echo "$file_mt"
cd "$directory"

# $pdffile is a string composed this way: __$file.[pdf,epub]
# if the converted file exists, then it's named like $pdffile
pdffile=`cksum "$file" | sed -r 's/^([0-9]+) ([0-9]+) (.*)$/\1_\2_\3.pdf/'`

# if the file is a pdf or an epub
if [[ $file_mt == "application/pdf" ]] || [[ $file_mt == "application/epub+zip" ]]; then
  file_converter="none_original"
# if the converted file exists
elif [[ ( -f "$ZADIR$pdffile" ) ]]; then
  file_converter="none_converted"
# if the file is an office file (ooxml or the old format or an opendocument)
elif [[ $file_mt == "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ]] || \
     [[ $file_mt == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ]] || \
     [[ $file_mt == "application/vnd.openxmlformats-officedocument.presentationml.presentation" ]] || \
     [[ $file_mt == "application/msword" ]] || \
     [[ $file_mt == "application/vnd.ms-excel" ]] || \
     [[ $file_mt == "application/vnd.ms-powerpoint" ]] || \
     [[ $file_mt == "application/vnd.oasis.opendocument.text" ]] || \
     [[ $file_mt == "application/vnd.oasis.opendocument.spreadsheet" ]] || \
     [[ $file_mt == "application/vnd.oasis.opendocument.presentation" ]] || \
     [[ $file_mt == "text/csv" ]]
then
  file_converter=$OFFICE_CMD
# if the file is a mubi ebook
elif [[ $file_mt == "application/octet-stream" ]] && [[ "$file" =~ ^.*\.mobi$ ]] ; then
  file_converter=$MOBI_CMD
# if the file is a markdown
elif [[ $file_mt == "text/plain" ]] && [[ "$file" =~ ^.*\.md$ ]] ; then
  file_converter=$MD_CMD
fi

# if we don't have a capable converter, we exit
if [[ -z $file_converter ]]; then
  echo "The file format is unsupported."
  exit 2
# if the file a pdf or an epub, we just open it
elif [[ $file_converter == "none_original" ]]; then
  echo "The file is already in PDF format. We just open it."
  $reader "$directory$file"
# if we have a converted file, we just open it (the only difference with the case above
# is that the converted file is into cache directory and has a different name)
elif [[ $file_converter == "none_converted" ]]; then
  echo "We already converted this file. We just open it."
  $reader "$ZADIR$pdffile"
# else, then the file is not a pdf or an epub, and it doesn't exist a converted version,
# but its format is convertible
else
  # first, we check if we have the proper converter installed
  we_can_convert=`whereis $file_converter | cut -d":" -f2`
  # if we don't have it, we can't do anything, so we exit
  if [[ -z $we_can_convert ]]; then
     echo "The command we need to convert, $file_converter, doesn't exist on this machine."
     exit 4
  # else we process the file, and we put the converted version under $zadir$pdffile
  else
    echo "We are starting to convert the file $file using $file_converter"
    if [[ $file_converter == "$OFFICE_CMD" ]]; then
      libreoffice --convert-to pdf "$directory$file" --headless --outdir "$ZADIR"
      tmpfile=`echo "$file" | sed -r 's/.[^\.]*$//'`".pdf"
      mv "$ZADIR$tmpfile" "$ZADIR$pdffile"
    elif [[ $file_converter == "$MOBI_CMD" ]]; then
      ebook-convert "$directory""$file" "$ZADIR$pdffile"
    elif [[ $file_converter == "$MD_CMD" ]]; then
      md2pdf "$directory""$file" -o "$ZADIR""$pdffile"
    fi
  fi
  echo "Now we can open the file $ZADIR$pdffile"
  # ...and after the conversion we open the file
  $reader "$ZADIR$pdffile"
fi

Quote

#!/usr/bin/env bash

RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'

jq --help > /dev/null 2>&1
if [ $? -eq 127 ]
then
    echo "fatal - Please install jq :("
    exit 1
fi

json=$(curl -s "https://api.quotable.io/random?maxLength=110")

if [ -z "$json" ]
then
    echo -en "Cannot connect to host. :("
    echo
else
    echo $json | jq '.content' > $HOME/.cache/qwote.txt
    echo $json | jq '.author' | cut -d '"' -f 2 > $HOME/.cache/author.txt
fi

echo -en "${RED}\e[3m❤ $(cat $HOME/.cache/qwote.txt) ❤\e[0m${NC}"
echo -en "\n${BLUE}\e[3m- $(cat $HOME/.cache/author.txt)\e[0m${NC}"
echo

echo ===================================================

echo
fortune

Recorder

  • An efficient, minimal screen recording script.
  • wl-screenrec is alot efficient, and fast (rust) than wf-screenrecorder.
source d-var.conf

menuopts=("Record Video + Audio" "Record Webcam and screen" "Only Video" "Record Small Area in Mouse" "Kill Recording")

action=$(printf '%s\n' "${menuopts[@]}" | $D_MENU -p '')
command="wl-screenrec "
opts="--codec=av1"
refreshbar="pkill -RTMIN+8 waybar"

case "$action" in
  "${menuopts[0]}") $command $opts --audio -f ~/screen-$(date '+%a-%d-%b@%H:%M:%S').mp4 & $refreshbar ;;
  "${menuopts[1]}") d-webcam & $command $opts --audio -f ~/visual-$(date '+%a-%d-%b@%H:%M:%S').mp4 & $refreshbar ;;
  "${menuopts[2]}") $command $opts -f ~/visual-$(date '+%a-%d-%b@%H:%M:%S').mp4 & $refreshbar ;;
  "${menuopts[3]}") $command $opts -g "$(slurp)" -f ~/capture-$(date '+%a-%d-%b@%H:%M:%S').mp4 & $refreshbar ;;
  "${menuopts[4]}") pkill -INT $command && $refreshbar ;;
  *) exit 1 ;;
esac

Reminder using at

  • Simple notifier as reminder using at
source d-var.conf

menuopts=("now + 5 minutes" "now + 10 minutes" "now + 15 minutes" "now + 25 minutes" "now + 2 hour" "19:45 today" "16:30 tomorrow" "4pm + 1 days" "10am Jul 31")

remindopt=(
    "Short break Over!"
    "Long break done!"
    "Drink Water!"
    "Stop wasting time & Read something"
    "Learn the market"
)

info_remind="   Time - Date ? Like Eg -- hh:mm Jul 10"
# notify-send -t 4000 "${info_remind}"

# define variable for time and text
time="${1:-$(printf '%s\n' "${menuopts[@]}" | $L_MENU -i -p '󰁫 ')}" && \
    text="$(printf "%s\n" "${remindopts[@]}" | $L_MENU -p '')"

# check if both arg given
if [[ "$time" ]]; then
    echo "notify-send -u critical ' 🔔  Reminder 💡' '$text'" | at "$time"
else
    notify-send "Please set the time and clock"
fi

Text to Regex

# txt2regex.sh - Regular Expressions "wizard" made with Bash builtins
#
# Website : https://aurelio.net/projects/txt2regex/
# Author  : Aurelio Jargas ([email protected])
# License : GPL
# Requires: bash >= 3.0
#
# shellcheck disable=SC1117,SC2034
#   SC1117 because it was obsoleted in shellcheck >0.5
#   SC2034 because it considers unused vars that I load with eval (ax_*)
#
# Please, read the README file.
#
# $STATUS:
#   0  beginning of the regex
#   1  defining regex
#   12 choosing subregex
#   2  defining quantifier
#   3  really quit?
#   4  choosing session programs
#   9  end of the regex
#
# 20001019 ** 1st version
# 20001026 ++ lots of changes and tests
# 20001028 ++ improvements, public release
# 20001107 ++ bash version check (thanks eliphas)
# 20001113 ++ php support, Progs command
# 20010223 ++ i18n, --all, freshmeat announce (oh no!)
# 20010223 v0.1
# 20010420 ++ id.po, \lfunction_name, s/regexp/regex/ig
# 20010423 ++ --nocolor, --history, Usage(), doNextHist{,Args}()
#          ++ flags: interactive, color, allprogs
#          ++ .oO(¤user parameters history)
# 20010424 v0.2
# 20010606 ++ option --whitebg
#          -- grep from $progs to fit on 24 lines by default
# 20010608 -- clear command (not bash), ++ Clear()
#          -- stty command (not bash), ++ $LINES
#          -- *Progs*(), ++ Choice(), ChoiceRefresh()
#          ++ POSIX character classes [[:abc:]]
#          ++ special combinations inside []
#          ++ $HUMAN improved with getString, getNumber, Choice
#          ++ detailed --help, moved to sourceforge
# 20010613 v0.3
# 20010620 -- seq command (not bash), ++ sek()
# 20010613 v0.3.1
# 20010731 ++ Reset: "RegEx prog  :" with automatic length
#          ++ new progs: postgres, javascript, vbscript, procmail
#          ++ ax_prog: new item: escape char - escape is ok now
#          ++ improved meta knowledge on perl, tcl and gawk
# 20010802 v0.4
# 20010821 ++ ShowMeta(), new option: --showmeta
# 20010824 ++ getMeta(), ShowInfo(), new option: --showinfo, $cR color
# 20010828 ++ getItemIndex(), getLargestItem()
#          <> Clear(): using \033c, ALL: using for((;;)) ksh syntax
#          <> vi == Nvi
# 20010828 v0.5
# 20010831 ++ group & or support- cool!, clearN()
#          ++ nice groups balance check -> ((2)), use $COLUMNS
#          <> TopTitle(): BLOAT, 3 lines, smart, arrays
#          <> Menu(): s/stupid recursion/while/
#          ++ Z status to handle 0,menu,0 situation
#          <> s/eval/${!var}/
# 20010903 <> Choice: fixed outrange answers
#          ++ trapping ^c do clearEnd, ++ new prog: mysql
#          ++ history now works with Choice() menus
#          ++ history appears when quitting
# 20010905 v0.6
# 20020225 ++ "really quit?" message, ++ --version
# 20020304 <> --history just shows final RE on STDOUT
#          ++ --make, --prog, printError()
#          ++ groups are now quantifiable
#          ++ ready_(date[123], hour[123], number[123])
# 20020304 v0.7
# 20040928 <> bash version test (works in 3.x and newer)
# 20040928 v0.8
# 20040929 <> --help split into individual messages (helps i18n)
# 20051229 <> fixed bug on bash3 for eval contents (thanks Marcus Habermehl)
# 20121221 ** moved to GitHub, please see the Git history from now on

# Every command in this script is a Bash builtin. This is by design.
# Make sure we don't break that rule in future code by strictly
# disallowing any system command.
export PATH=

TEXTDOMAIN=txt2regex
TEXTDOMAINDIR=po
VERSION=0.10b

printError() {
    printf '%s: ' $"ERROR"
    # shellcheck disable=SC2059
    printf "$@"
    exit 1
}

case "$BASH_VERSION" in
    [3-9].*)
        : # do nothing
        ;;
    *)
        printError 'Bash version >=3.0 required, but you have %s\n' "$BASH_VERSION"
        ;;
esac

Usage() {
    # Ugly code, but isolates in $"..." only the strings that need
    # translation and tries to keep the option descriptions aligned even
    # when long words are used as meta vars.
    printf '%s txt2regex [--nocolor|--whitebg] [--all|--prog %s]\n' \
        $"usage:" $"PROGRAMS"
    printf '%s txt2regex --showmeta\n' \
        $"usage:"
    printf '%s txt2regex --showinfo %s [--nocolor]\n' \
        $"usage:" $"PROGRAM"
    printf '%s txt2regex --history %s [--all|--prog %s]\n' \
        $"usage:" $"VALUE" $"PROGRAMS"
    printf '%s txt2regex --make %s [--all|--prog %s]\n' \
        $"usage:" $"LABEL" $"PROGRAMS"
    printf '\n'
    printf '%s\n' $"Options:"
    printf '  %-22s%s\n' '--all' \
        $"Select all the available programs"
    printf '  %-22s%s\n' '--nocolor' \
        $"Do not use colors"
    printf '  %-22s%s\n' '--whitebg' \
        $"Adjust colors for white background terminals"
    printf '  %-22s%s\n' '--prog '$"PROGRAMS" \
        $"Specify which programs to use, separated by commas"
    printf '\n'
    printf '  %-22s%s\n' '--showmeta' \
        $"Print a metacharacters table featuring all the programs"
    printf '  %-22s%s\n' '--showinfo '$"PROGRAM" \
        $"Print regex-related info about the specified program"
    printf '  %-22s%s\n' '--history '$"VALUE" \
        $"Print a regex from the given history data"
    printf '  %-22s%s\n' '--make '$"LABEL" \
        $"Print a ready regex for the specified label"
    printf '\n'
    printf '  %-22s%s\n' '-V, --version' \
        $"Print the program version and quit"
    printf '  %-22s%s\n' '-h, --help' \
        $"Print the help message and quit"
    printf '\n'
    exit "${1:-0}" # $1 is the exit code (default is 0)
}

# The defaults
is_interactive=1
use_colors=1
has_white_background=0
has_not_supported=0
mode_show_meta=0
mode_show_info=0
GRP1=0
GRP2=0

# Here's the default list of programs shown.
# Edit here or use --prog to overwrite it.
progs=(python egrep grep sed vim emacs)

### IMPORTANT DATA ###

# To generate this array:
# grep version: tests/regex-tester.txt | sort | cut -d ' ' -f 1
allprogs=(
    awk
    chicken
    ed
    egrep
    emacs
    expect
    find
    gawk
    grep
    javascript
    lex
    mawk
    mysql
    perl
    php
    postgres
    procmail
    python
    sed
    tcl
    vi
    vim
)

# To generate this array:
# grep version: tests/regex-tester.txt | sort | sed "s/.* version: //;s/.*/'&'/"
allversions=(
    'awk version 20121220'
    'CHICKEN 4.12.0'
    'GNU Ed 1.10'
    'grep (GNU grep) 3.1'
    'GNU Emacs 25.2.2'
    'expect version 5.45.4'
    'find (GNU findutils) 4.7.0-git'
    'GNU Awk 4.1.4'
    'grep (GNU grep) 3.1'
    'node v8.10.0'
    'flex 2.6.4'
    'mawk 1.3.3 Nov 1996'
    'mysql  Ver 14.14 Distrib 5.7.29'
    'perl v5.26.1'
    'PHP 7.2.24-0ubuntu0.18.04.4'
    'psql (PostgreSQL) 10.12'
    'procmail v3.23pre 2001/09/13'
    'Python 3.6.9'
    'sed (GNU sed) 4.4'
    'tcl 8.6'
    'nvi 1.81.6-13'
    'VIM - Vi IMproved 8.0 (2016 Sep 12)'
)

label_names=(
    date
    date2
    date3
    hour
    hour2
    hour3
    number
    number2
    number3
)
label_descriptions=(
    'date LEVEL 1: mm/dd/yyyy: matches from 00/00/0000 to 99/99/9999'
    'date LEVEL 2: mm/dd/yyyy: matches from 00/00/1000 to 19/39/2999'
    'date LEVEL 3: mm/dd/yyyy: matches from 00/00/1000 to 12/31/2999'
    'hour LEVEL 1: hh:mm: matches from 00:00 to 99:99'
    'hour LEVEL 2: hh:mm: matches from 00:00 to 29:59'
    'hour LEVEL 3: hh:mm: matches from 00:00 to 23:59'
    'number LEVEL 1: integer, positive and negative'
    'number LEVEL 2: level 1 plus optional float point'
    'number LEVEL 3: level 2 plus optional commas, like: 34,412,069.90'
)
label_data=(
    # date
    '26521652165¤:2¤2¤/¤:2¤2¤/¤:2¤4'
    '24161214161214165¤01¤:2¤/¤0123¤:2¤/¤12¤:2¤3'
    '2(2161|2141)121(2161|4161|2141)1214165¤0¤:2¤1¤012¤/¤0¤:2¤12¤:2¤3¤01¤/¤12¤:2¤3'
    # hour
    '2652165¤:2¤2¤:¤:2¤2'
    '24161214161¤012¤:2¤:¤012345¤:2'
    '2(4161|2141)1214161¤01¤:2¤2¤0123¤:¤012345¤:2'
    # number
    '24264¤+-¤:2'
    '24264(2165)2¤+-¤:2¤.¤:2¤2'
    '24266(2165)3(2165)2¤+-¤:2¤3¤,¤:2¤3¤.¤:2¤2'
)
#date3  : perl: (0[0-9]|1[012])/(0[0-9]|[12][0-9]|3[01])/[12][0-9]{3}
#hour3  : perl: ([01][0-9]|2[0123]):[012345][0-9]
#number3: perl: [+-]?[0-9]{1,3}(,[0-9]{3})*(\.[0-9]{2})?
### -- ###

getItemIndex() { # item, array_items
    local item="$1"
    local i=0

    shift
    while [ -n "$1" ]; do
        [ "$1" == "$item" ] && printf '%d\n' "$i" && return
        i=$((i + 1))
        shift
    done
}

validateProgramNames() {
    local name

    for name in "$@"; do
        [ -z "$(getItemIndex "$name" "${allprogs[@]}")" ] &&
            printError '%s: %s\n' $"unknown program" "$name"
    done
}

# Parse command line options
while [ $# -gt 0 ]; do
    case "$1" in
        --history)
            [ -z "$2" ] && Usage 1
            history="$2"
            shift
            is_interactive=0
            use_colors=0

            hists="0${history%%¤*}"
            histargs="¤${history#*¤}"
            [ "${hists#0}" == "${histargs#¤}" ] && unset histargs
            ;;
        --make)
            shift
            is_interactive=0
            use_colors=0
            label_name="${1%1}" # final 1 is optional (date1 == date)
            label_index=$(getItemIndex "$label_name" "${label_names[@]}")

            # Sanity check
            [ -z "$label_index" ] &&
                printError '%s: "%s": %s\n%s %s\n' \
                    '--make' "$1" $"invalid argument" \
                    $"valid names:" "${label_names[*]}"

            # Set history data
            hist="${label_data[$label_index]}"
            hists="0${hist%%¤*}"
            histargs="¤${hist#*¤}"

            printf '\n### %s\n\n' "${label_descriptions[$label_index]}"
            ;;
        --prog)
            [ -z "$2" ] && Usage 1
            shift
            eval "progs=(${1//,/ })"
            validateProgramNames "${progs[@]}"
            ;;
        --nocolor)
            use_colors=0
            ;;
        --whitebg)
            has_white_background=1
            ;;
        --showmeta)
            mode_show_meta=1
            ;;
        --showinfo)
            [ -z "$2" ] && Usage 1
            infoprog="$2"
            shift
            mode_show_info=1
            validateProgramNames "$infoprog"
            ;;
        --all)
            progs=("${allprogs[@]}")
            ;;
        -V | --version)
            printf 'txt2regex %s\n' "$VERSION"
            exit 0
            ;;
        -h | --help)
            Usage 0
            ;;
        *)
            printf '%s: %s\n\n' "$1" $"invalid option"
            Usage 1
            ;;
    esac
    shift
done

set -o noglob

### The Regex show

S0_txt=(
    $"start to match"
    $"on the line beginning"
    $"in any part of the line"
)
S0_re=(
    ''
    '^'
    ''
)

S1_txt=(
    $"followed by"
    $"any character"
    $"a specific character"
    $"a literal string"
    $"an allowed characters list"
    $"a forbidden characters list"
    $"a special combination"
    $"a POSIX combination (locale aware)"
    $"a ready regex (not implemented)"
    $"anything"
)
S1_re=(
    ''
    '.'
    ''
    ''
    ''
    ''
    ''
    ''
    ''
    '.*'
)

S2_txt=(
    $"how many times (repetition)"
    $"one"
    $"zero or one (optional)"
    $"zero or more"
    $"one or more"
    $"exactly N"
    $"up to N"
    $"at least N"
)

# COMBO
combo_txt=(
    $"uppercase letters"
    $"lowercase letters"
    $"numbers"
    $"underscore"
    $"space"
    $"TAB"
)
combo_re=(
    'A-Z'
    'a-z'
    '0-9'
    '_'
    ' '
    '@'
)

#TODO use all posix components?
posix_txt=(
    $"letters"
    $"lowercase letters"
    $"uppercase letters"
    $"numbers"
    $"letters and numbers"
    $"hexadecimal numbers"
    $"whitespaces (space and TAB)"
    $"graphic chars (not-whitespace)"
)
posix_re=(
    'alpha'
    'lower'
    'upper'
    'digit'
    'alnum'
    'xdigit'
    'blank'
    'graph'
)

# Title (line 1)
# shellcheck disable=SC2256
tit1_txt=(
    $"quit"
    $"reset"
    $"color"
    $"programs"
    ''
    ''
    ''
    ''
    ''
    '^txt2regex$'
)
tit1_cmd=(
    '.'
    '0'
    '*'
    '/'
    ''
    ''
    ''
    ''
    ''
    ''
)

# Title (line 2-3)
tit2_txt=(
    $"or"
    $"open group"
    $"close group"
    ''
    ''
    ''
    ''
    ''
    ''
    $"not supported"
)
tit2_cmd=(
    '|'
    '('
    ')'
    ''
    ''
    ''
    ''
    ''
    ''
    '!!'
)

# S2_* arrays: The list of quantifiers (to be used when STATUS=2)
# Every array will be named S2_<prog>: S2_awk, S2_ed, S2_egrep, ...
# The array index refers to the menu item in the "repetition" screen.
# To update this data:
#   make test-regex
#   grep ' S2 .*OK$' tests/regex-tester.txt
#
while read -r prog_id data; do
    # Set the S2_<prog> array for each line. Example:
    # S2_egrep=('-' '-' '?' '*' '+' '{@}' '{1,@}' '{@,}')
    read -r -a "S2_$prog_id" <<< "$data"
done << 'EOD'
awk           - -     ?      *      +       !!         !!          !!
chicken       - -     ?      *      +       {@}       {1,@}       {@,}
ed            - -    \?      *     \+      \{@\}     \{1,@\}     \{@,\}
egrep         - -     ?      *      +       {@}       {1,@}       {@,}
emacs         - -     ?      *      +     \\{@\\}   \\{1,@\\}   \\{@,\\}
expect        - -     ?      *      +       {@}       {1,@}       {@,}
find          - -     ?      *      +       {@}       {1,@}       {@,}
gawk          - -     ?      *      +       {@}       {1,@}       {@,}
grep          - -    \?      *     \+      \{@\}     \{1,@\}     \{@,\}
javascript    - -     ?      *      +       {@}       {1,@}       {@,}
lex           - -     ?      *      +       {@}       {1,@}       {@,}
mawk          - -     ?      *      +       !!         !!          !!
mysql         - -     ?      *      +       {@}       {1,@}       {@,}
perl          - -     ?      *      +       {@}       {1,@}       {@,}
php           - -     ?      *      +       {@}       {1,@}       {@,}
postgres      - -     ?      *      +       {@}       {1,@}       {@,}
procmail      - -     ?      *      +       !!         !!          !!
python        - -     ?      *      +       {@}       {1,@}       {@,}
sed           - -    \?      *     \+      \{@\}     \{1,@\}     \{@,\}
tcl           - -     ?      *      +       {@}       {1,@}       {@,}
vi            - -  \{0,1\}   *   \{1,\}    \{@\}     \{1,@\}     \{@,\}
vim           - -    \=      *     \+      \{@}      \{1,@}      \{@,}
EOD

# ax_* arrays: Extra regex-related data for all the programs.
# Every array will be named ax_<prog>: ax_awk, ax_ed, ax_egrep, ...
# To check how this data is used in this source code, search for
# something like 'ax_.*5'.
#
# To update this data:
#   make test-regex
#   grep -E ' ax123 .+OK$' tests/regex-tester.txt  # 1,2,3
#   grep -E   ' a\.b +OK$' tests/regex-tester.txt  # 4
#   grep -E   ' ax5 .+OK$' tests/regex-tester.txt  # 5
#   grep -E   ' ax6 '      tests/regex-tester.txt  # 6
#   grep -E   ' ax7 '      tests/regex-tester.txt  # 7
#   grep -E   ' ax8 '      tests/regex-tester.txt  # 8
#
# In PHP, we're using \\ instead of \ as the escape metacharacter
# because it works consistently, being it inside single or double
# quotes. Using only \ would work in some cases, but not in others:
#   The literal + is matched by: \+ \\+ [+] [\+] [\\+]
#   The literal \ is matched by: \\\\ [\\\\]
#
while read -r prog_id data; do
    # Set the ax_<prog> array for each line. Example:
    # ax_awk=('' '|' '(' ')' '\' '\.*[---()|+?^$' '\' 'P' '\t')
    read -r -a "ax_$prog_id" <<< "$data"
done << 'EOD'
awk           -     |     (     )    \    \.*[---()|+?^$    \    P    \t
chicken       -     |     (     )    \\   \.*[---()|+?^$    \    P    \t
ed            -    \|    \(    \)    \    \.*[----------    -    P    -
egrep         -     |     (     )    \    \.*[-{-(-|+?^$    -    P    -
emacs         -   \\|   \\(   \\)    \\   \.*[------+?--    \    P    \t
expect        -     |     (     )    \    \.*[-{}()|+?^$    \    P    \t
find          -     |     (     )    \    \.*[-{-(-|+?^$    -    P    -
gawk          -     |     (     )    \    \.*[---(-|+?^$    \    P    \t
grep          -    \|    \(    \)    \    \.*[----------    -    P    -
javascript    -     |     (     )    \    \.*[---()|+?^$    \    -    \t
lex           -     |     (     )    \    \.*[-{}()|+?--    \    P    \t
mawk          -     |     (     )    \    \.*[---()|+?^$    \    -    \t
mysql         -     |     (     )    \\   \.*[---(-|+?^$    \    P    \t
perl          -     |     (     )    \    \.*[-{-()|+?^$    \    P    \t
php           -     |     (     )    \\   \.*[-{-()|+?^$    \    P    \t
postgres      -     |     (     )    \    \.*[---()|+?^$    \    P    \t
procmail      -     |     (     )    \    \.*[---()|+?^$    -    -    -
python        -     |     (     )    \    \.*[-{-()|+?^$    \    -    \t
sed           -    \|    \(    \)    \    \.*[----------    -    P    \t
tcl           -     |     (     )    \    \.*[-{}()|+?^$    \    P    \t
vi            -    !!    \(    \)    \    \.*[----------    -    P    -
vim           -    \|    \(    \)    \    \.*[----------    \    P    \t
EOD
#                                         \.*[]{}()|+?^$    -=false
# [0] Unused
# [1] Which is the metacharacter for alternatives?
# [2,3] Which are the metacharacters for grouping?
# [4] Which is the escape metacharacter?
# [5] Which chars of \.*[]{}()|+?^$ need to be escaped to be matched as
#     literals? Note that txt2regex has menus to insert all of those as
#     metacharacters (except $), so in user input they will always be
#     literal. For ^ and $, some tools consider them literal when not in
#     their special start/end position (marked here as -).
# [6] To match '\' inside [], do you need to escape it? If yes, use '\'.
# [7] Has support for [[:POSIX:]] character classes? If yes, use 'P'.
# [8] Does \t inside [] match a tab? If yes, use '\t'.

ColorOnOff() {
    # The colors: Normal, Prompt, Bold, Important
    [ "$use_colors" -eq 0 ] && return
    if [ -n "$cN" ]; then
        unset cN cP cB cI cR
    elif [ "$has_white_background" -eq 0 ]; then
        cN=$(printf '\033[m')     # normal
        cP=$(printf '\033[1;31m') # red
        cB=$(printf '\033[1;37m') # white
        cI=$(printf '\033[1;33m') # yellow
        cR=$(printf '\033[7m')    # reverse
    else
        cN=$(printf '\033[m')   # normal
        cP=$(printf '\033[31m') # red
        cB=$(printf '\033[32m') # green
        cI=$(printf '\033[34m') # blue
        cR=$(printf '\033[7m')  # reverse
    fi
}

# Emulate the 'seq N' command
sek() {
    local z="$1"
    local a=1

    while [ "$a" -le "$z" ]; do
        printf '%d\n' "$a"
        a=$((a + 1))
    done
}

# Is the $1 char present in the $2 text?
charInText() {
    local char="$1"
    local text="$2"
    local i

    for ((i = 0; i < ${#text}; i++)); do
        [ "${text:$i:1}" == "$char" ] && return 0
    done
    return 1
}

# Remove all duplicated chars from the $1 text
uniqChars() {
    local text="$1"
    local text_uniq=''
    local i

    for ((i = 0; i < ${#text}; i++)); do
        charInText "${text:$i:1}" "$text_uniq" ||
            text_uniq="$text_uniq${text:$i:1}"
    done
    printf '%s\n' "$text_uniq"
}

# Escape each $1 in $2 using $3
escapeChars() {
    local special_chars="$1"
    local text="$2"
    local escape_char="${3:-\\}"

    local escaped_text
    local i
    local this_char

    for ((i = 0; i < ${#text}; i++)); do
        this_char=${text:$i:1}

        if charInText "$this_char" "$special_chars"; then
            if [ "$this_char$this_char" == "$escape_char" ]; then
                # Special case: this_char=\ and escape_char=\\
                # The normal escaping (see the next else) would make \\\
                # (which is wrong). Here we ensure \\\\ is produced.
                escaped_text="$escaped_text$escape_char$escape_char"
            else
                # normal escaping
                escaped_text="$escaped_text$escape_char$this_char"
            fi
        else
            # no escaping
            escaped_text="$escaped_text$this_char"
        fi
    done
    printf '%s\n' "$escaped_text"
}

getLargestItem() {
    local largest
    while [ -n "$1" ]; do
        [ ${#1} -gt ${#largest} ] && largest="$1"
        shift
    done
    printf '%s\n' "$largest"
}

# Used to get values from the S2_* and ax_* metachar arrays
getMeta() { # var-name index
    local m="$1[$2]"
    m=${!m}

    # Remove all non-metacharacters: @ ! -
    # Those are used only internally as markers
    m=${m//[@!-]/}

    # Remove when getting '?' or '+' for 'vi', since they are unsupported
    # and the current values are workarounds using '{}'
    [ "$1" == S2_vi ] && { [ "$2" -eq 2 ] || [ "$2" -eq 4 ]; } && m=''

    printf '%s\n' "$m"
}

ShowMeta() {
    local i g1 g2 prog progsize
    progsize=$(getLargestItem "${allprogs[@]}")
    for ((i = 0; i < ${#allprogs[@]}; i++)); do
        prog=${allprogs[$i]}
        g1=$(getMeta "ax_$prog" 2)
        g2=$(getMeta "ax_$prog" 3)

        printf "\n%-${#progsize}s" "$prog"     # name
        printf '%7s' "$(getMeta "S2_$prog" 4)" # +
        printf '%7s' "$(getMeta "S2_$prog" 2)" # ?
        printf '%7s' "$(getMeta "S2_$prog" 5)" # {}
        printf '%7s' "$(getMeta "ax_$prog" 1)" # |
        printf '%8s' "$g1$g2"                  # ()
        printf '    %s' "${allversions[$i]}"   # version
    done
    printf '\n\n%s\n\n' $"NOTE: . [] [^] and * are the same on all programs."
}

ShowInfo() {
    local prog="$1"

    local escmeta
    local index
    local i
    local metas
    local needesc
    local posix=$"NO"
    local tabinlist=$"NO"
    local txtsize
    local ver

    local -a data
    local -a txt

    # Getting data
    index=$(getItemIndex "$prog" "${allprogs[@]}")
    ver="${allversions[$index]}"
    escmeta=$(getMeta "ax_$prog" 4)
    needesc=$(getMeta "ax_$prog" 5)
    [ "$(getMeta "ax_$prog" 7)" == 'P' ] && posix=$"YES"
    [ "$(getMeta "ax_$prog" 8)" == '\t' ] && tabinlist=$"YES"

    # Metacharacters list
    # printf arguments: + ? {} | ( )
    metas="$(
        printf '. [] [^] * %s %s %s %s %s%s' \
            "$(getMeta "S2_$prog" 4)" \
            "$(getMeta "S2_$prog" 2)" \
            "$(getMeta "S2_$prog" 5)" \
            "$(getMeta "ax_$prog" 1)" \
            "$(getMeta "ax_$prog" 2)" \
            "$(getMeta "ax_$prog" 3)"
    )"

    # Populating cool i18n arrays
    # shellcheck disable=SC2256
    txt=(
        $"program"
        $"metas"
        $"esc meta"
        $"need esc"
        $"\t in []"
        '[:POSIX:]'
    )
    data=(
        "$prog: $ver"
        "$metas"
        "$escmeta"
        "${needesc//-/}"
        "$tabinlist"
        "$posix"
    )

    # Show me! show me! show me!
    ColorOnOff
    printf '\n'
    txtsize=$(getLargestItem "${txt[@]}")
    for ((i = 0; i < ${#txt[@]}; i++)); do
        printf "%s %${#txtsize}s %s %s\n" \
            "$cR" "${txt[$i]}" "${cN:-:}" "${data[$i]}"
    done
    printf '\n'
}

if [ "$mode_show_meta" -eq 1 ]; then
    ShowMeta
    exit 0
fi

if [ "$mode_show_info" -eq 1 ]; then
    ShowInfo "$infoprog"
    exit 0
fi

# Screen size/positioning issues
ScreenSize() {
    # Note that those are all global variables
    x_regex=1
    y_regex=4
    x_hist=3
    y_hist=$((y_regex + ${#progs[*]} + 1))
    x_prompt=3
    y_prompt=$((y_regex + ${#progs[*]} + 2))
    x_menu=3
    y_menu=$((y_prompt + 2))
    x_prompt2=15
    y_max=$((y_menu + ${#S1_txt[*]}))

    # The defaults case not exported
    : ${LINES:=25}
    : ${COLUMNS:=80}

    #TODO automatic check when selecting programs
    if [ "$is_interactive" -eq 1 ] && [ $LINES -lt "$y_max" ]; then
        printError '\n%s\n%s\n%s\n' \
            "$(
                printf \
                    $"Your terminal has %d lines, but txt2regex needs at least %d lines." \
                    "$LINES" "$y_max"
            )" \
            $"Increase the number of lines or select less programs using --prog." \
            $"If this line number detection is incorrect, export the LINES variable."
    fi
}

_eol=$(printf '\033[0K') # clear trash until EOL

# The cool control chars functions
gotoxy() {
    [ "$is_interactive" -eq 1 ] && printf '\033[%d;%dH' "$2" "$1"
}
clearEnd() {
    [ "$is_interactive" -eq 1 ] && printf '\033[0J'
}
clearN() {
    [ "$is_interactive" -eq 1 ] && printf '\033[%dX' "$1"
}
Clear() {
    [ "$is_interactive" -eq 1 ] && printf '\033c'
}

# Ideas: tab between, $cR on cmd, yellow-white-yellow
printTitleCmd() {
    printf '[%s%s%s]%s  ' "$cI" "$1" "$cN" "$2"
}

TopTitle() {
    gotoxy 1 1

    local color
    local cmd
    local i
    local j
    local showme
    local txt

    [ "$is_interactive" -eq 0 ] && return

    # 1st line: aplication commands
    for ((i = 0; i < 10; i++)); do
        showme=0
        txt=${tit1_txt[$i]}
        cmd=${tit1_cmd[$i]}
        case $i in
            [01])
                showme=1
                ;;
            2)
                [ "$use_colors" -eq 1 ] && showme=1
                ;;
            3)
                [ "$STATUS" -eq 0 ] && showme=1
                ;;
            9)
                gotoxy $((COLUMNS - ${#txt})) 1
                printf '%s\n' "$txt"
                ;;
        esac
        if [ $showme -eq 1 ]; then
            printTitleCmd "$cmd" "$txt"
        else
            clearN $((${#txt} + 3))
        fi
    done

    # 2nd line: grouping and or
    if [ "$STATUS" -eq 0 ]; then
        printf %s "$_eol"
    else
        if [ "$STATUS" -eq 1 ]; then
            for i in 0 1 2; do
                txt=${tit2_txt[$i]}
                cmd=${tit2_cmd[$i]}
                showme=1
                [ $i -eq 2 ] && [ $GRP1 -eq $GRP2 ] && showme=0
                if [ $showme -eq 1 ]; then
                    printTitleCmd "$cmd" "$txt"
                else
                    clearN $((${#txt} + 3))
                fi
            done
        else # delete commands only
            clearN $((${#tit2_txt[0]} + 5 + ${#tit2_txt[1]} + 5 + ${#tit2_txt[2]} + 5))
        fi

        # open groups
        gotoxy $((COLUMNS - GRP1 - GRP2 - ${#GRP1})) 2
        color="$cP"
        [ "$GRP1" -eq "$GRP2" ] && color="$cB"
        for ((j = 0; j < GRP1; j++)); do printf '%s(%s' "$color" "$cN"; done
        [ $GRP1 -gt 0 ] && printf %s "$GRP1"
        for ((j = 0; j < GRP2; j++)); do printf '%s)%s' "$color" "$cN"; done
    fi

    # 3rd line: legend
    txt=${tit2_txt[9]}
    cmd=${tit2_cmd[9]}
    gotoxy $((COLUMNS - ${#txt} - ${#cmd} - 1)) 3
    if [ "$has_not_supported" -eq 1 ]; then
        printf '%s%s%s %s' "$cB" "$cmd" "$cN" "$txt"
    else
        clearN $((${#txt} + ${#cmd} + 1))
    fi
}

doMenu() {
    local i
    local -a Menui

    eval "Menui=(\"\${$1[@]}\")"
    menu_n=$((${#Menui[*]} - 1)) # ini (global var)

    if [ "$is_interactive" -eq 1 ]; then

        # history
        gotoxy $x_hist $y_hist
        printf '   %s.oO(%s%s%s)%s%s(%s%s%s)%s%s\n' \
            "$cP" "$cN" "$REPLIES" "$cP" "$cN" \
            "$cP" "$cN" "$uins" "$cP" "$cN" \
            "$_eol"

        # title
        gotoxy $x_menu $y_menu
        printf '%s%s:%s%s\n' "$cI" "${Menui[0]}" "$cN" "$_eol"

        # itens
        for i in $(sek $menu_n); do
            printf '  %s%d%s) %s%s\n' "$cB" "$i" "$cN" "${Menui[$i]}" "$_eol"
            i=$((i + 1))
        done
        clearEnd

        # prompt
        gotoxy $x_prompt $y_prompt
        printf '%s[1-%d]:%s %s' "$cP" "$menu_n" "$cN" "$_eol"
        read -r -n 1
    else
        doNextHist
        REPLY=$hist
    fi
}

Menu() {
    local name="$1"
    local ok=0

    while [ $ok -eq 0 ]; do
        doMenu "$name"
        case "$REPLY" in
            [1-9])
                [ "$REPLY" -gt "$menu_n" ] && continue
                ok=1
                REPLIES="$REPLIES$REPLY"
                ;;
            .)
                ok=1
                LASTSTATUS=$STATUS
                STATUS=3
                ;;
            0)
                ok=1
                STATUS=Z
                ;;
            \*)
                ColorOnOff
                TopTitle
                ;;
            [\(\)\|])
                [ "$STATUS" -ne 1 ] && continue
                [ "$REPLY" == ')' ] &&
                    { [ $GRP1 -gt 0 ] && [ $GRP1 -eq $GRP2 ] || [ $GRP1 -eq 0 ]; } &&
                    continue
                [ "$REPLY" == ')' ] && STATUS=2
                ok=1
                REPLIES="$REPLIES$REPLY"
                ;;
            /)
                ok=1
                STATUS=4
                ;;
        esac
    done
}

doNextHist() {
    hists=${hists#?} # deleting previous item
    hist=${hists:0:1}
    : "${hist:=.}" # if last, quit
}

doNextHistArg() {
    histargs=${histargs#*¤}
    histarg=${histargs%%¤*}
}

getChar() {
    gotoxy $x_prompt2 $y_prompt

    if [ "$is_interactive" -eq 1 ]; then
        printf '%s%s%s ' "$cP" $"which one?" "$cN"
        read -n 1 -r USERINPUT
        uin="$USERINPUT"
    else
        doNextHistArg
        uin=$histarg
    fi

    uins="${uins}¤$uin"
    F_ESCCHAR=1
}

getCharList() {
    gotoxy $x_prompt2 $y_prompt

    if [ "$is_interactive" -eq 1 ]; then
        printf '%s%s%s ' "$cP" $"which?" "$cN"
        read -r USERINPUT
        uin="$USERINPUT"
    else
        doNextHistArg
        uin=$histarg
    fi

    # dedup is safe because $uin contains only literal chars (no ranges)
    uin="$(uniqChars "$uin")"

    uins="${uins}¤$uin"

    # putting not special chars in not special places: [][^-]
    [ "${uin#^}" != "$uin" ] && uin="${uin#^}^"    # move leading ^ to the end
    [ "${uin#?*-}" != "$uin" ] && uin="${uin/-/}-" # move non-leading - to the end
    [ "${uin/]/}" != "$uin" ] && uin="]${uin/]/}"  # move ] to the start

    # if any $1, negated list
    [ -n "$1" ] && uin="^$uin"

    # make it a list
    uin="[$uin]"
    F_ESCCHARLIST=1
}

getString() {
    gotoxy $x_prompt2 $y_prompt

    if [ "$is_interactive" -eq 1 ]; then
        printf '%stxt:%s ' "$cP" "$cN"
        read -r USERINPUT
        uin="$USERINPUT"
    else
        doNextHistArg
        uin=$histarg
    fi

    uins="${uins}¤$uin"
    F_ESCCHAR=1
}

getNumber() {
    gotoxy $x_prompt2 $y_prompt

    if [ "$is_interactive" -eq 1 ]; then
        printf '%sN=%s%s' "$cP" "$cN" "$_eol"
        read -r USERINPUT
        uin="$USERINPUT"
    else
        doNextHistArg
        uin=$histarg
    fi

    # Remove !numbers
    uin="${uin//[^0-9]/}"

    # ee
    if [ "${uin/666/x}" == 'x' ]; then
        gotoxy 36 1
        printf '%s]:|%s\n' "$cP" "$cN"
    fi

    if [ -n "$uin" ]; then
        uins="${uins}¤$uin"
    else
        getNumber # there _must_ be a number
    fi
}

getPosix() {
    local psx
    local rpl

    unset SUBHUMAN

    if [ "$is_interactive" -eq 1 ]; then
        Choice --reset "${posix_txt[@]}"
    else
        ChoiceAuto
    fi

    for rpl in $CHOICEREPLY; do
        psx="${psx}[:${posix_re[$rpl]}:]"
        SUBHUMAN="$SUBHUMAN, ${posix_txt[$rpl]/ (*)/}"
    done

    SUBHUMAN=${SUBHUMAN#, }
    F_POSIX=1

    uin="[$psx]"
    uins="${uins}¤:${CHOICEREPLY// /}"
}

getCombo() {
    local cmb
    local rpl

    unset SUBHUMAN

    if [ "$is_interactive" -eq 1 ]; then
        Choice --reset "${combo_txt[@]}"
    else
        ChoiceAuto
    fi

    for rpl in $CHOICEREPLY; do
        cmb="$cmb${combo_re[$rpl]}"
        SUBHUMAN="$SUBHUMAN, ${combo_txt[$rpl]}"
    done

    # In this menu, @ is used as a placeholder for the tab char
    # It will have to be replaced later, so let's set the flag
    charInText @ "$cmb" && F_GETTAB=1

    SUBHUMAN=${SUBHUMAN#, }

    uin="[$cmb]"
    uins="${uins}¤:${CHOICEREPLY// /}"
}

getREady() { #TODO
    unset SUBHUMAN
    uin=''
}

# convert [@] -> [\t] or [<TAB>] based on ax_*[8] value
getListTab() {
    local x

    if [ "$(getMeta "ax_${progs[$1]}" 8)" == '\t' ]; then
        x='\t'
    else
        x='<TAB>'
    fi

    uin="${uin/@/$x}"
}

# Set $uin to !! when POSIX character classes are not supported
getHasPosix() {
    [ "$(getMeta "ax_${progs[$1]}" 7)" == 'P' ] || uin='!!'
}

# Escape possible metachars in user input so they will be matched literally
escChar() {
    local index="$1"

    local escape_metachar
    local special_chars

    escape_metachar=$(getMeta "ax_${progs[$index]}" 4)
    special_chars=$(getMeta "ax_${progs[$index]}" 5)

    uin=$(escapeChars "$special_chars" "$uin" "$escape_metachar")
}

# Escape user input: maybe '\' inside [] needs to be escaped
escCharList() {
    local escape_metachar

    # shellcheck disable=SC1003
    if [ "$(getMeta "ax_${progs[$1]}" 6)" == '\' ]; then
        escape_metachar=$(getMeta "ax_${progs[$1]}" 4)
        if [[ ${BASH_VERSINFO[0]} -lt 5 ]]; then
            uin="${uin/\\/$escape_metachar$escape_metachar}"
        else
            uin="${uin/\\/"$escape_metachar$escape_metachar"}"
        fi
    fi
}

Reset() {
    local p

    # It's all global variables in this function
    gotoxy $x_regex $y_regex
    unset REPLIES uins HUMAN "Regex[*]"
    has_not_supported=0
    GRP1=0
    GRP2=0

    maxprogname=$(getLargestItem "${progs[@]}") # global var
    for p in "${progs[@]}"; do
        [ "$is_interactive" -eq 1 ] &&
            printf " Regex %-${#maxprogname}s: %s\n" "$p" "$_eol"
    done
}

showRegex() {
    gotoxy $x_regex $y_regex

    local i
    local new_part
    local save="$uin"

    # For each program
    for ((i = 0; i < ${#progs[@]}; i++)); do
        [ "$F_ESCCHAR" == 1 ] && escChar "$i"
        [ "$F_ESCCHARLIST" == 1 ] && escCharList "$i"
        [ "$F_GETTAB" == 1 ] && getListTab "$i"
        [ "$F_POSIX" == 1 ] && getHasPosix "$i"

        # Check status
        case "$1" in
            ax | S2)
                eval new_part="\${$1_${progs[$i]}[$REPLY]/@/$uin}"
                [ "$new_part" == '-' ] && new_part=''
                Regex[$i]="${Regex[$i]}$new_part"
                [ "$new_part" == '!!' ] && has_not_supported=1
                ;;
            S0)
                Regex[$i]="${Regex[$i]}${S0_re[$REPLY]}"
                ;;
            S1)
                Regex[$i]="${Regex[$i]}${uin:-${S1_re[$REPLY]}}"

                # When a program does not support POSIX character classes, $uin
                # will be set to !! by getHasPosix(). Also check $REPLY to avoid
                # a false positive when the user wants to match the !! string.
                [ "$REPLY" -eq 7 ] && [ "$uin" == '!!' ] && has_not_supported=1
                ;;
        esac

        [ "$is_interactive" -eq 1 ] &&
            printf " Regex %-${#maxprogname}s: %s\n" "${progs[$i]}" "${Regex[$i]}"
        uin="$save"
    done
    unset uin USERINPUT F_ESCCHAR F_ESCCHARLIST F_GETTAB F_POSIX
}

#
### And now the cool-smart-MSclippy choice menu/prompt
#
# number of items <= 10, 1 column
# number of items >  10, 2 columns
# maximum number of items = 26 (a-z)
#

# Just refresh the selected item on the screen
ChoiceRefresh() {
    local xy=$1
    local a=$2
    local stat=$3
    local opt=$4

    # colorizing case status is ON
    [ "$stat" == '+' ] && stat="$cI$stat$cN"

    gotoxy "${xy#*;}" "${xy%;*}"
    printf '  %s%s%s) %s%s ' "$cB" "$a" "$cN" "$stat" "$opt"
}

# --reset resets the stat array
Choice() {
    local choicereset=0
    [ "$1" == '--reset' ] && shift && choicereset=1

    local alf
    local alpha
    local cols
    local i
    local line
    local lines
    local numopts=$#
    local op
    local opt
    local opts
    local optxy
    local rpl

    alpha=(a b c d e f g h i j k l m n o p q r s t u v w x y z)

    # Reading options and filling default status (off)
    i=0
    for opt in "$@"; do
        opts[$i]="$opt"
        [ "$choicereset" -eq 1 ] && stat[$i]='-'
        i=$((i + 1))
    done

    # Checking our number of items limit
    [ "$numopts" -gt "${#alpha[*]}" ] &&
        printError 'too much itens (>%d)' "${#alpha[*]}"

    # The header
    Clear
    printTitleCmd '.' $"exit"
    printf '| %s' $"press the letters to (un)select the items"

    # We will need 2 columns?
    cols=1
    [ "$numopts" -gt 10 ] && cols=2

    # And how much lines? (remember: odd number of items, requires one more line)
    lines=$((numopts / cols))
    [ "$((numopts % cols))" -eq 1 ] && lines=$((lines + 1))

    # Filling the options screen's position array (+3 = header:2, sek:1)
    for ((line = 0; line < lines; line++)); do
        # Column 1
        optxy[$line]="$((line + 3));1"

        # Column 2
        [ "$cols" == 2 ] && optxy[$((line + lines))]="$((line + 3));40"
    done

    # Showing initial status for all options
    for ((op = 0; op < numopts; op++)); do
        ChoiceRefresh "${optxy[$op]}" "${alpha[$op]}" "${stat[$op]}" "${opts[$op]}"
    done

    # And now the cool invisible prompt
    while :; do
        read -s -r -n 1 CHOICEREPLY

        case "$CHOICEREPLY" in
            [a-z])
                # Inverting the option status
                for ((alf = 0; alf < numopts; alf++)); do
                    if [ "${alpha[$alf]}" == "$CHOICEREPLY" ]; then
                        if [ "${stat[$alf]}" == '+' ]; then
                            stat[$alf]='-'
                        else
                            stat[$alf]='+'
                        fi
                        break
                    fi
                done

                # Showing the change
                [ -z "${opts[alf]}" ] && continue
                ChoiceRefresh "${optxy[$alf]}" "${alpha[$alf]}" \
                    "${stat[$alf]}" "${opts[$alf]}"
                ;;
            .)
                # Getting the user choices and exiting
                unset CHOICEREPLY
                for ((rpl = 0; rpl < numopts; rpl++)); do
                    [ "${stat[$rpl]}" == '+' ] && CHOICEREPLY="$CHOICEREPLY $rpl"
                done
                break
                ;;
        esac
    done
}

# Non-interative, just return the answers
ChoiceAuto() {
    local i
    local z

    unset CHOICEREPLY
    doNextHistArg
    z=${histarg#:} # marker

    for ((i = 0; i < ${#z}; i++)); do
        CHOICEREPLY="$CHOICEREPLY ${z:$i:1}"
    done
}

# Fills the stat array with the actual active programs ON
statActiveProgs() {
    local i
    local p
    local ps=" ${progs[*]} "

    # For each program
    for ((i = 0; i < ${#allprogs[@]}; i++)); do
        # Default OFF
        p="${allprogs[$i]}"
        stat[$i]='-'

        # Case found, turn ON
        [ "${ps/ $p /}" != "$ps" ] && stat[$i]='+'
    done
}

###############################################################################
######################### ariel, ucla, vamos! #################################
###############################################################################

STATUS=0 # default status
Clear
ScreenSize
ColorOnOff # turning color ON
trap "clearEnd; echo; exit" SIGINT

while :; do
    case ${STATUS:=0} in
        0 | Z)
            STATUS=${STATUS/Z/0}
            Reset
            TopTitle
            Menu S0_txt
            [ -z "${STATUS/[Z34]/}" ] && continue # 0,3,4: escape status
            HUMAN="${S0_txt[0]} ${S0_txt[$REPLY]}"
            showRegex S0
            STATUS=1
            ;;
        1)
            TopTitle
            Menu S1_txt
            [ -z "${STATUS/[Z34]/}" ] && continue # 0,3,4: escape status
            if [ -n "${REPLY/[1-9]/}" ]; then
                HUMAN="$HUMAN $REPLY"
                if [ "$REPLY" == '|' ]; then
                    REPLY=1
                elif [ "$REPLY" == '(' ]; then
                    REPLY=2
                    GRP1=$((GRP1 + 1))
                elif [ "$REPLY" == ')' ]; then
                    REPLY=3
                    GRP2=$((GRP2 + 1))
                else
                    printf '\n\n'
                    printError 'unknown reply type "%s"\n' "$REPLY"
                fi
                showRegex ax
            else
                HUMAN="$HUMAN, ${S1_txt[0]} ${S1_txt[$REPLY]/ (*)/}"
                case "$REPLY" in
                    1)
                        STATUS=2
                        ;;
                    2)
                        STATUS=2
                        getChar
                        ;;
                    3)
                        STATUS=1
                        getString
                        HUMAN="$HUMAN {$uin}"
                        ;;
                    4)
                        STATUS=2
                        getCharList
                        ;;
                    5)
                        STATUS=2
                        getCharList negated
                        ;;
                    [678])
                        STATUS=12
                        continue
                        ;;
                    9)
                        STATUS=1
                        ;;
                esac
                showRegex S1
            fi
            ;;
        12)
            [ "$REPLY" -eq 6 ] && STATUS=2 && getCombo
            [ "$REPLY" -eq 7 ] && STATUS=2 && getPosix
            [ "$REPLY" -eq 8 ] && STATUS=1 && getREady
            Clear
            TopTitle
            HUMAN="$HUMAN {$SUBHUMAN}"
            showRegex S1
            ;;
        2)
            TopTitle
            Menu S2_txt
            [ -z "${STATUS/[Z34]/}" ] && continue # 0,3,4: escape status
            rep_middle=$"repeated"
            rep_txt="${S2_txt[$REPLY]}"
            rep_txtend=$"times"

            [ "$REPLY" -ge 5 ] && getNumber && rep_txt=${rep_txt/N/$uin}
            HUMAN="$HUMAN, $rep_middle ${rep_txt/ (*)/} $rep_txtend"
            showRegex S2
            STATUS=1
            ;;
        3)
            [ "$is_interactive" -eq 0 ] && STATUS=9 && continue
            warning=$"Really quit?"
            read -r -n 1 -p "..$cB $warning [.] $cN"
            STATUS=$LASTSTATUS
            [ "$REPLY" == '.' ] && STATUS=9
            ;;
        4)
            statActiveProgs
            Choice "${allprogs[@]}"
            i=0
            unset progs

            # Rewriting the progs array with the user choices
            for rpl in $CHOICEREPLY; do
                progs[$i]=${allprogs[$rpl]}
                i=$((i + 1))
            done
            ScreenSize
            Clear
            STATUS=0
            ;;
        9)
            gotoxy $x_hist $y_hist
            clearEnd
            if [ "$is_interactive" -eq 1 ]; then
                noregex_txt=$"no regex"
                printf "%stxt2regex --history '%s%s'%s\n\n" \
                    "$cB" "$REPLIES" "$uins" "$cN"
                printf '%s.\n' "${HUMAN:-$noregex_txt}"
            else
                for ((i = 0; i < ${#progs[@]}; i++)); do # for each program
                    printf " Regex %-${#maxprogname}s: %s\n" \
                        "${progs[$i]}" "${Regex[$i]}"
                done
                printf '\n'
            fi
            exit 0
            ;;
        *)
            printError 'STATUS = "%s"\n' "$STATUS"
            ;;
    esac
done

Rssfeed

# usage: d-rssfeed https://blogsite.com

for path in $(echo {,feed/,feeds/,rss/,blog/}{,all,atom,feed,index,posts,posts/default,rss,en,default,rssfeed,blog}{,.rss,.atom,.rss2}{,.xml,?feed=rss2,?format=atom}); do

	LINE=$(curl -L -s "$1/$path" | head -1)

	if printf "%s" "$LINE" | grep -v xhtml | grep -q -E "feed|xml" ;
	then
		# show canonical redirect location
		curl -sLI -o /dev/null -w '%{url_effective}' "$1/$path"
		echo
		exit
	fi

done
exit 1

Rss for YT

  • Rss feed for youtube channels
rofm="rofi -dmenu "
mymem=$rofm

# Give the link and it will throw the feed url in YouTube.
# You can choose invidious link too

ytlink="${1:-$(printf "%s" | $mymem  -p 'youtube link')}"

fetchyt=$(curl -s $ytlink | grep -Po '"channelId":".+?"' | cut -d \" -f 4 | head -n 1)

ytfeed="https://www.youtube.com/feeds/videos.xml?channel_id=${fetchyt}"
invfeed="https://yt.funami.tech/feed/channel/${fetchyt}"

choose=$(printf "Youtube\nInvious" | $mymem -p 'rss link')

case $choose in
    "Youtube") echo "$ytfeed" | wl-copy ;;
    "Invfeed") echo "$invfeed" | wl-copy ;;
esac

Search script

  • Generic script acts as a search engine for sites.
# Script to search terms in search engines

source d-var.conf

query="${1:-$(printf "$(wl-paste -p)\n$(wl-paste)" | $D_MENU -i -p '')}"
echo "$feed" | wl-copy -n
# For prompt/notify on chosen link
shortquery="$(echo ${feed} | cut -d '/' -f3,4,5,6 )"

browsertab=("  Firefox" "  Librewolf" "  Brave" "󰖂 MullVad")
enginestab=(
    "🔗 Website/URL" #0
    "  Brave" #1
    "  Google Scholar" #2
    "  Reddit" #3
    "  NixPkgs" #4
    "  MyNixOS" #5
    "  Nixhub - pkgver" #6
    "󰂦  NCBI" #7
    "󰏓  BioConductor" #8
    "󰣇  Arch-Wiki" #9
    "󰂺  Libgen-Zlib-Books" #10
    "  GitHub" #11
    "  AnimeTosho" #12
    "󰄛  NyaaSi" #13
    "  Getty Images" #14
    "󰇥  DuckDuckGo" #15
    "  1337 Torrent" #16

)

viabrowser () {
    echo "Opening  ${nowsearch} in  $nowbrowser"
    setsid -f $nowbrowser "${nowsearch}" >/dev/null 2>&1
}

getbrowser="$(printf '%s\n' "${browsertab[@]}" | $D_MENU -p "${shortfeed}")"

case $getbrowser in
    "${browsertab[0]}") nowbrowser="firefox" ;;
    "${browsertab[1]}") nowbrowser="librewolf" ;;
    "${browsertab[2]}") nowbrowser="brave" ;;
    "${browsertab[3]}") nowbrowser="mullvad" ;;
esac

dosearch="$(printf '%s\n' "${enginestab[@]}" | $D_MENU -p "${shortfeed}")"

case $dosearch in
    "${enginestab[0]}") nowsearch="${query}" ;;
    "${enginestab[1]}") nowsearch="https://search.brave.com/search?q=$query" ;;
    "${enginestab[2]}") nowsearch="https://scholar.google.com/scholar?&q=$query" ;;
    "${enginestab[3]}") nowsearch="https://old.reddit.com/search?q=$query" ;;
    "${enginestab[4]}") nowsearch="https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=$query" ;;
    "${enginestab[5]}") nowsearch="https://mynixos.com/search?q=$query" ;;
    "${enginestab[6]}") nowsearch="https://www.nixhub.io/search?q=$query" ;;
    "${enginestab[7]}") nowsearch="https://www.ncbi.nlm.nih.gov/search/all/?term=$query" ;;
    "${enginestab[8]}") nowsearch="https://www.bioconductor.org/help/search/index.html?q=$query" ;;
    "${enginestab[9]}") nowsearch="https://wiki.archlinux.org/index.php?search=$query" ;;
    "${enginestab[10]}") nowsearch="https://libgen.rs/search.php?req=$query" ;;
    "${enginestab[11]}") nowsearch="https://github.com/search?q=$query&type=repositories" ;;
    "${enginestab[12]}") nowsearch="https://animetosho.org/search?q=$query" ;;
    "${enginestab[13]}") nowsearch="https://nyaa.si/?f=0&c=0_0&q=$query" ;;
    "${enginestab[14]}") nowsearch="https://www.gettyimages.in/search/2/image?family=creative&phrase=$query";;
    "${enginestab[15]}") nowsearch="https://duckduckgo.com/?q=$query" ;;
    "${enginestab[16]}") nowsearch="https://1337x.to/search/$query/1";;
esac

viabrowser

Screenshot

  • Script to capture screenshot.
source d-var.conf

menuopts=(" Select Area in Mouse" " Copy Area of Screen" " Full Display" " Copy Whole Display" " Active Window")

nameopts=(
    "notes-refer"
    "receipt-"
    "ppt-pic"
    "share-detail"
    )

sleep_for='sleep 0.5'
temp_pic='/tmp/thescr.png'
ident=$(date +%Y%m%dT%H%M%S)

gimme() {
output=$(date +'%d-%a  %H:%M:%S')
picname=$(printf '%s\n' "${nameopts[@]}" | ${D_MENU} -l 5 -i -p '' || echo $output )
tagname=$(echo "" | ${D_MENU} -l 5 -i -p '')

cp $temp_pic ~/pics/sshots/"${ident}-${picname}_${tagname}.png"
}

sshot=$(printf '%s\n' "${menuopts[@]}" | sort | $D_MENU -p 'Snap ScreenShot of ')

case "$sshot" in
    # "${menuopts[0]}") $sleep_for && grim -g "$(slurp)" "${temp_pic}" && gimme ;;
    # "${menuopts[1]}") $sleep_for && grim -g "$(slurp)" - | wl-copy --type image/png ;;
    # "${menuopts[2]}") $sleep_for && grim -c "${temp_pic}" && gimme ;;
    # "${menuopts[3]}") $sleep_for && grim -c - | wl-copy --type image/pngi ;;
    # "${menuopts[4]}") $sleep_for && grim -g \
    #        "$(hyprctl activewindow -j | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"')" "${temp_pic}" && gimme ;;
    # #	*) sleep 0.5 && grim "/tmp/thescr.png" || exit ;;

    "${menuopts[0]}") grimblast save area "${temp_pic}" && gimme ;;
    "${menuopts[1]}") grimblast copy area ;;
    "${menuopts[2]}") grimblast save output "${temp_pic}" && gimme;;
    "${menuopts[3]}") grimblast copy output ;;
    "${menuopts[4]}") grimblast save active "${temp_pic}" && gimme;;

esac

System Stats

  • Status on system as notification.
notify-send -t 8000 "$(
free -m | awk 'NR==2{printf "🐏 Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'
top -bn1 | grep load | awk '{printf "🧠 Load: %.2f\n", $(NF-2)}'
echo "🔋 Battery: " "$(cat /sys/class/power_supply/BAT1/capacity)" "%"
)"
# acpi

Password entry

  • Give a menu prompt to input the password in places where no pasting is allowed.
source d-var.conf

sleepfor=$(printf "1\n2\n3\n4\n5" | $D_MENU -p "󰒲 Sleep for")
typetool="dotoolc"

password=$(printf "%s" "$(wl-paste -p)" | $D_MENU -x -p " password: ")

sleep "${sleepfor}" && echo type "$password" | "$typetool"

Link handler - Stuff

  • Stuff, and all link handler.
  • Most used, universal way.
# Link handler for every thinkable purpose
# I use `nq` for task scheduling with mpv

source d-var.conf

feed="${1:-$(printf "$(wl-paste -p)\n$(wl-paste)" | $D_MENU -i -p '')}"
# echo "$feed" | wl-copy -n
# For prompt/notify on chosen link
shortfeed="$(echo ${feed} | cut -d '/' -f3,4,5,6 )"

# Aria2 for torrents (acts on rpc server)
aria_tor () {
    curl 'http://localhost:6800/jsonrpc' || setsid aria2c --enable-rpc --rpc-listen-all &
    sleep 4 && curl http://localhost:6800/jsonrpc -d '{"jsonrcp":"2.0","id":"someID","method":"aria2.addUri","params":["token:ariatest",["'${feed}'"]]}'
}

audio_podcast () {
    case "$(printf "Song\nPodcast" | $D_MENU -p '')" in
	"Podcast") mpc pause; NQDIR=/tmp/podcast nq mpv --force-window --geometry=15% --title=podcast --vid=1 "${feed}" >/dev/null 2>&1 ;;
	"Song") pgrep mpd || mpd; mpc add "$(yt-dlp -f bestaudio -g "${feed}")" ;;
	*) exit 1 ;;
    esac
}

menuopts=("  Copy Url"
          "  Fire Fox"
          "  Download Files"
          "  YT Vid Download"
          "  Audio Music Download"
          "  Podcast Listen Stream"
          "  View Image"
          "  Play Watch Stream"
          "  Misc Download"
          "  Bookmark"
          "  Brave"
          "󱣻  Mullvad"
          "  Chromium"
          "  Torrent Aria"
          "  YT Music"
          "  Search Engine"
          "  Document Viewer"
          "  LibreWolf"
          "󰚂  Transmission"
)

case "$(printf '%s\n' "${menuopts[@]}" | sort | $D_MENU -p ${shortfeed})" in

    "${menuopts[0]}") echo "${feed}" | wl-copy -p ;;
    "${menuopts[1]}") setsid -f firefox "${feed}" >/dev/null 2>&1 ;;
    "${menuopts[2]}") setsid aria2c -j 6 -x 16 -c -d ~/dloads "${feed}" >/dev/null 2>&1 ;;
    "${menuopts[3]}") NQDIR=/tmp/yt-vid nq yt-dlp --embed-metadata --embed-subs -f "bestvideo[height<=1080]+bestaudio" -P ~/vids/yt "${feed}" >/dev/null 2>&1 ;;
    "${menuopts[4]}") NQDIR=/tmp/yt-music nq yt-dlp -P ~/d-sync/music/yt/ -icx --embed-metadata "${feed}" && pidof -x mpd || mpd && mpc update ;;
    "${menuopts[5]}") audio_podcast ;;
    "${menuopts[6]}") (wget "${feed}" --output-document=/tmp/image  && imv /tmp/image) || imv "${feed}" ;;
    "${menuopts[7]}") NQDIR=/tmp/stream nq mpv -quiet "${feed}" >/dev/null 2>&1 ;;
    "${menuopts[8]}") aria2c -j 6 -x 10 -c -d ~/vids/documentary/.cache/clean.db/ "${feed}" ;;
    "${menuopts[9]}") d-bookmark "${feed}" ;;
    "${menuopts[10]}") setsid brave "${feed}" ;;
    "${menuopts[11]}") setsid mullvad-browser "${feed}" ;;
    "${menuopts[12]}") setsid chromium "${feed}" ;;
    "${menuopts[13]}") aria_tor ;;
    "${menuopts[14]}") pgrep mpd || mpd; mpc add "$(yt-dlp -f bestaudio -g "$(ytfzf -LD ${feed})")" && mpc play ;;
    "${menuopts[15]}") d-search ;;
    "${menuopts[16]}") sioyek ${feed} ;;
    "${menuopts[17]}") setsid librewolf "${feed}";;
    "${menuopts[18]}") transmission-remote -a "${feed}";;
    *) exit 1 ;;
esac

Time

  • Notify the time!
notify-send -t 3500 "$(date '+%a %b %e %r')"

Todo

file="$HOME/.todo.org"
touch "$file"
height=$(wc -l "$file" | awk '{print $1}')
prompt="Add/delete a task: "

cmd=$(rofi -dmenu -l "$height" -config ~/.config/rofi/list.rasi -p "$prompt" "$@" < "$file")
while [ -n "$cmd" ]; do
 	if grep -q "^$cmd\$" "$file"; then
		grep -v "^$cmd\$" "$file" > "$file.$$"
		mv "$file.$$" "$file"
        height=$(( height - 1 ))
 	else
		echo "* TODO $cmd" >> "$file"
		height=$(( height + 1 ))
 	fi

	cmd=$(rofi -dmenu -l "$height" -config ~/.config/rofi/list.rasi -p "$prompt" "$@" < "$file")
done

exit 0

Unicodes

  • Script to give choice and display unicodes.
  • M-x insert-char in Emacs.
# Script to Insert and copy the unicode char

source d-var.conf

# The famous "get a menu of emojis to copy" script.

# You can the icons for this script in icons/ directory here

chosen=$(bat ~/d-git/d-bin/treasure/unicodes/* | $UNI_MENU -i -p '' | awk '{print $1}' )

# Exit if none chosen.
[ -z "$chosen" ] && exit

# If you run this command with an argument, it will automatically insert the
# character. Otherwise, show a message that the emoji has been copied.
if [ -n "$1" ]; then
	  wtype "$chosen"
else

    # replace with xclip or xsel or x11
    printf "$chosen" | wl-copy

    # Replace with xdotool for X11
	  wtype "$chosen"

    # not required tho
	  # notify-send "'$chosen' copied to clipboard." &
fi

Urls from Bookmark

  • Insert the chosen URL from bookmark file.
# Simple script which show the bookmarks from org-file which are inserted via d-bookmark

# We can select and it insert the link
source d-var.conf
file="$HOME/d-sync/notes/bookmarks.org"

echo type "$(rg '^\+' ${file} | sed 's/+ //g' | ${L_MENU} | rg -o '(http|https)://[a-zA-Z0-9./?=_%&:-]*')" | dotoolc

# search for links and show list in menu and type the link of selected item

Clipboard history

  • Script to get clip history and select via dmenu
source d-var.conf

cliphist list | $L_MENU| cliphist decode | wl-copy

Script Variable

  • Variable to define the choice of launcher configuration.
# Just a file to put variable for $mymem for all scripts.
# So we can unify the menu launcher for all here.

# Options are : rofi, bemenu/dmenu, wofi(search is too slow), fuzzel

############## Dynamic menu for common scripts ##############
D_MENU="fuzzel -d"
W_MENU="fuzzel -d -w 120"

############## Menu for emoji/icons picker ##############
UNI_MENU="fuzzel -d -l 8"

############## Menu for listing ##############
L_MENU="fuzzel -d -w 85% -l 22"
# L_MENU="bemenu -l 20 -W 0.85"
# L_MENU="rofi -dmenu -i"

# for short width menu
# S_MENU="bemenu -l 5 -c -W 0.14"
S_MENU="fuzzel -d -w 30%"

Volume

  • To get notification and interactive volume as slider.
# mixercli="pamixer --allow-boost"
volume=$(wpctl get-volume @DEFAULT_AUDIO_SINK@)
volcli="wpctl set-volume @DEFAULT_AUDIO_SINK@"
togglecli="wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"

down() {
    $mixercli -d 5
    # volume=$(pamixer --get-volume)
    # [ $volume -gt 0 ] && volume=`expr $volume`
    # notify-send "󰖀 Volume Decreased to $volume%" -h int:value:"$volume" -i audio -r 2593 -u normal
}

up() {
    $mixercli -i 5
    # volume=$(pamixer --get-volume)
    # [ $volume -lt 100 ] && volume=`expr $volume`
    # notify-send " Volume Increased to $volume%" -h int:value:"$volume" -i audio -r 2593 -u normal
}

toggle() {
    muted="$(pamixer --get-mute)"
    if $muted; then
        $mixercli -u
        notify-send " Volume Unmuted"
    else
        $mixercli -m
        notify-send " Volume Muted"
    fi
}

case "$1" in
    up) up;;
    down) down;;
    toggle) toggle;;
esac

Wallpaper Changer

  • Script to change random wallpaper.
# Path to wallpapers directory
wall_dir=~/d-git/d-wallpapers/walls/

if [ -z "$1" ]; then
	wall="$(find "$wall_dir" | shuf -n1)"
else
	wall="$1"
fi

rsync "$wall" ~/.local/share/bg.jpg

########### If you use pywal (If not use feh)
#wal -c
#wal -n -i ~/.local/share/bg.jpg
#wal -R
###########################

# For wayland users
pkill swaybg
swaybg -i ~/.local/share/bg.jpg &

Wifi Menu

source d-var.conf

a1="󰖪 Disable Wi-Fi"
a2=" Enable Wi-Fi"

# Starts a scan of available broadcasting SSIDs
# nmcli dev wifi rescan
notify-send "Getting list of available Wi-Fi networks..."
wifi_list=$(nmcli --fields "SECURITY,SSID" device wifi list | sed 1d | sed 's/  */ /g' | sed -E "s/WPA*.?\S/ /g" | sed "s/^--/ /g" | sed "s/  //g" | sed "/--/d")
# Gives a list of known connections so we can parse it later

connected=$(nmcli -fields WIFI g)
if [[ "$connected" =~ "enabled" ]]; then
	toggle="$a1"
elif [[ "$connected" =~ "disabled" ]]; then
	toggle="$a2"
fi

chosen_network=$(echo -e "$toggle\n$wifi_list" | uniq -u | $D_MENU  "Wi-Fi SSID: " )
chosen_id=$(echo "${chosen_network:3}" | xargs)

# Parses the list of preconfigured connections to see if it already contains the chosen SSID. This speeds up the connection process
if [ "$chosen_network" = "" ]; then
	exit
elif [ "$chosen_network" = "$a2" ]; then
	nmcli radio wifi on
elif [ "$chosen_network" = "$a1" ]; then
	nmcli radio wifi off
else
	# Message to show when connection is activated successfully
	success_message="You are now connected to the Wi-Fi network \"$chosen_id\"."
	# Get known connections
	saved_connections=$(nmcli -g NAME connection)
	if [[ $(echo "$saved_connections" | grep -w "$chosen_id") = "$chosen_id" ]]; then
		nmcli connection up id "$chosen_id" | grep "successfully" && notify-send "Connection Established" "$success_message"
	else
		if [[ "$chosen_network" =~ "" ]]; then
			wifi_password=$(echo '' | $D_MENU -password "Password: " )
		fi
		nmcli device wifi connect "$chosen_id" password "$wifi_password" | grep "successfully" && notify-send "Connection Established" "$success_message"
	fi
fi

notify

  • script to just play the notifying sound
audio=${1:-"/home/idlip/music/yt/misc/linux-notify.ogg"}

ffplay -nodisp -autoexit -loglevel quiet $audio
# mpv --speed=1.0 $audio