#!/usr/bin/env bash # Charsel - terminal character selector # Copyright Armaan Bhojwani 2020, MIT License # Define argument functions function usage() { echo "Usage: /usr/bin/charsel [OPTION]... [CHARFILE]... A simple terminal character selector -a include hidden shortcodes -b disable color support -c check charfile validity -d show readme -h show this message -L show installed charfiles without the message -l show installed charfiles -n dont copy character to clipboard, avoids Xclip dependency Exit status: 0 okay, 1 charfile does not exist, 2 charfile syntax error, 3 usage error/invalid option, 4 other error" } CHARDIR=$HOME/.cache/charsel function list() { ls "$CHARDIR"/charfiles } function readme() { cat /usr/share/doc/charsel/README.md } function missing_charfile() { echo "The selected charfile is missing or invalid" list exit 1 } # Merge global and local charfiles if [[ -d $CHARDIR ]]; then rm -rf "${CHARDIR:?}"/* else mkdir "$CHARDIR" fi LOCALCHARDIR=$HOME/.local/share/charsel/charfiles [[ -d $LOCALCHARDIR ]] || mkdir -p "$LOCALCHARDIR" localdirfiles="$LOCALCHARDIR"/* [[ -n "${#localdirfiles[*]}" ]] && cp -rf "$LOCALCHARDIR"/../* "$CHARDIR" globaldirfiles=($/usr/share/charfiles/) [[ -n "${#globaldirfiles[*]}" ]] && cp -rf /usr/share/charsel/* "$CHARDIR" # Check if charfile exists CHARFILE="$CHARDIR/charfiles/$2" function existence() { if [[ ! -f $CHARFILE ]]; then missing_charfile fi } # VERY basic syntax check function validity() { if [[ $(grep , "$CHARFILE" && grep - "$CHARFILE") ]]; then echo "valid charfile" else existence echo "invalid charfile" exit 2 fi } # Look for arguments while getopts ":abcdhlLnvV" arg do case ${arg} in a) SHOWALL="true" ;; b) COLOR="bw" ;; c) validity exit 0 ;; d) readme exit 0 ;; h) usage exit 0 ;; l) echo "The following charfiles are installed:" list exit 0 ;; L) list exit 0 ;; n) COPY="no" ;; ?) echo "Invalid option" usage exit 3 ;; esac done shift $((OPTIND-1)) if [ $# -eq 0 ]; then echo "Please enter a valid charfile, or use charsel -h for help." charsel -l exit 3 fi # Redefine charfile and check file validity CHARFILE="$CHARDIR/charfiles/$1" existence validity # Dependency check if [[ $COPY == "no" ]]; then if [[ ! -x /usr/bin/xclip ]]; then echo "Please install xclip." exit 4 fi fi # Define length of shortcode LENGTH=$(cut "$CHARFILE" -f 1 -d ',' -s \ | wc -L \ | cut -b 1) clear # Define text formatting bold=$(tput bold) normal=$(tput sgr0) highlight=$(tput setaf 5) [[ $COLOR == bw ]] && highlight=$(tput setaf 7) white=$(tput setaf 7) # Main program while true do # Format output echo "*---------*---------------*" echo "| ${bold}${highlight}CHARSEL${white}${normal} |" "$1" echo "*---------*---------------*" echo "" if [[ $SHOWALL == true ]]; then sed "$CHARFILE" -e '/^[ \t]*#/d' | tail -n +2 \ | column -t -N "input","output" --output-separator ' | ' --separator ',' else sed "$CHARFILE" -e '/^[ \t]*#/d' | grep -A 100 - | tail -n +2 \ | column -t -N "input","output" --output-separator ' | ' --separator ',' fi echo "" echo "*-------------------------*" echo "| previous shorcode:" "$(echo $INPUT)" echo "| previous output: " "$OUTPUT" echo "*-------------------------*" # User input read -r -p "| ${bold}input shortcode: ${normal} " -N "$LENGTH" INPUT if [[ $INPUT == ";"* ]]; then # Semicolon exts clear exit 0 else # Finds line number of shortcode LINENUMBER=$(cut -f 1 -d ',' -s "$CHARFILE" | grep -wn "$INPUT" | cut -d : -f 1) # Outputs character selected above OUTPUT=$(cut -f 2 -d ',' -s "$CHARFILE" | head -"$LINENUMBER" | tail +"$LINENUMBER") # Check to see if the shortcode actually exists if [[ $(cut -f 1 -d ',' -s "$CHARFILE" | grep -wnc "$INPUT") == "0" ]]; then OUTPUT="" fi # Copy output to clipboard if [[ ! $COPY == "no" ]]; then echo -n "$OUTPUT" | xclip -selection clipboard fi clear fi done