Marty Oehme
8beb28b2b9
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Switched the history from using the XDG_CACHE_HOME directory by default to use XDG_STATE_HOME by default. This makes sense since cache can (and should be prepared to) be wiped at any moment and the program functionality should not be hindered by this. Since we need to retain history through such wipes the newly introduced state directory is the perfect match for keeping the history file in. This does constitute a breaking change for existing histories which need to be moved to the new directory if they made use of the old cache directory. Concurrent with this we are renaming `XDG_CACHE_LOCATION` environment variable to `XDG_HISTORY_LOCATION` so this is a second breaking change for those using a custom location for their histories. This change attempts to make the naming scheme coherent and remove some left-over naming cruft from the old location being the cache directory. This provides one of the larger changes to the program so far. Fixes #5.
227 lines
7 KiB
Bash
Executable file
227 lines
7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
bm_version=0.2.0
|
|
# Emoji default database location
|
|
bm_db_location=${BEMOJI_DB_LOCATION:-"${XDG_DATA_HOME:-$HOME/.local/share}/bemoji"}
|
|
# Setting custom emoji list file location:
|
|
# BEMOJI_CUSTOM_LIST=/my/location/emojis.txt
|
|
# Setting custom recent emoji history:
|
|
# BEMOJI_HISTORY_LOCATION=/path/to/my/recents/directory
|
|
bm_state_dir="${BEMOJI_HISTORY_LOCATION:-${XDG_STATE_HOME:-$HOME/.local/state}}"
|
|
bm_history_file="${bm_state_dir}/bemoji-history.txt"
|
|
|
|
# Command to run after user chooses an emoji
|
|
bm_default_cmd="$BEMOJI_DEFAULT_CMD"
|
|
|
|
# Newline after echo
|
|
bm_echo_newline=${BEMOJI_ECHO_NEWLINE:-true}
|
|
# Do not save choices
|
|
bm_private_mode=${BEMOJI_PRIVATE_MODE:-false}
|
|
# Do not sort results
|
|
bm_ignore_recent=${BEMOJI_IGNORE_RECENT:-false}
|
|
|
|
# Report usage
|
|
usage() {
|
|
echo "Usage: $(basename "$0") [-t | -c | -e] [-f <filepath> ] [-p] [-P] [-D <choices>]" 1>&2
|
|
echo
|
|
echo "A simple emoji picker. Runs on bemenu/wofi/rofi/dmenu by default."
|
|
echo "Invoked without arguments sends the picked emoji to the clipboard."
|
|
echo
|
|
echo " Command options (can be combined):"
|
|
echo " -t Simulate typing the emoji choice with the keyboard."
|
|
echo " -c Send emoji choice to the clipboard. (default)"
|
|
echo " -e Only echo out the picked emoji."
|
|
echo ""
|
|
echo " Other options:"
|
|
echo " -n Do not print a newline after the picked emoji."
|
|
echo " -p Do not save picked emoji to recent history."
|
|
echo " -P Do not order emoji by recently used."
|
|
echo " -D <choice> Choose specific default lists to download if none found locally."
|
|
echo " Valid choices: all|none|emoji|math."
|
|
echo " -f <filepath> Use a custom emoji database. Can be a url which will be retrieved."
|
|
echo " -v Display current program version and directory configuration."
|
|
echo " -h Show this help."
|
|
echo
|
|
exit "$1"
|
|
}
|
|
|
|
version() {
|
|
printf "v%s\ndatabase=%s\nhistory=%s\n" "$bm_version" "$bm_db_location" "$bm_history_file"
|
|
exit
|
|
}
|
|
|
|
# Get Options
|
|
while getopts ":f:D:tcenpPhv" o; do
|
|
case "${o}" in
|
|
f) BEMOJI_CUSTOM_LIST="${OPTARG}" ;;
|
|
t) bm_cmds+=(_typer) ;;
|
|
c) bm_cmds+=(_clipper) ;;
|
|
e) bm_cmds+=(cat) ;;
|
|
n) bm_echo_newline=false ;;
|
|
D) BEMOJI_DOWNLOAD_LIST="${OPTARG}" ;;
|
|
p) bm_private_mode=true ;;
|
|
P) bm_ignore_recent=true ;;
|
|
h) usage 0 ;;
|
|
v) version ;;
|
|
*) usage 1 ;;
|
|
esac
|
|
done
|
|
|
|
prepare_db() {
|
|
# Create list directory
|
|
if [ ! -d "$bm_db_location" ]; then
|
|
mkdir -p "$bm_db_location"
|
|
fi
|
|
|
|
if [ -n "$(find "$bm_db_location" -maxdepth 0 -type d -empty 2>/dev/null)" ]; then
|
|
# Populate default lists
|
|
if echo "$BEMOJI_DOWNLOAD_LIST" | grep -q -e 'none'; then
|
|
printf "No emoji list found, but set to not download any default lists."
|
|
exit 1
|
|
elif echo "$BEMOJI_DOWNLOAD_LIST" | grep -q -e 'all'; then
|
|
dl_default_emoji
|
|
dl_math_symbols
|
|
return
|
|
fi
|
|
if [ -z "$BEMOJI_DOWNLOAD_LIST" ] || echo "$BEMOJI_DOWNLOAD_LIST" | grep -q -e 'emoji'; then
|
|
dl_default_emoji
|
|
fi
|
|
if echo "$BEMOJI_DOWNLOAD_LIST" | grep -q -e 'math'; then
|
|
dl_math_symbols
|
|
fi
|
|
fi
|
|
}
|
|
|
|
dl_default_emoji() {
|
|
curl -sSL "https://unicode.org/Public/emoji/14.0/emoji-test.txt" |
|
|
sed -ne 's/^.*; fully-qualified.*# \(\S*\) \S* \(.*$\)/\1 \2/gp' >"$bm_db_location/emojis.txt"
|
|
printf "Downloaded default emoji set."
|
|
}
|
|
dl_math_symbols() {
|
|
curl -sSL "https://unicode.org/Public/math/latest/MathClassEx-15.txt" |
|
|
grep -ve '^#' | cut -d';' -f3,7 --output-delimiter=' ' >"$bm_db_location/math.txt"
|
|
printf "Downloaded math symbols set."
|
|
}
|
|
|
|
gather_emojis() {
|
|
if [ -n "$BEMOJI_CUSTOM_LIST" ] && [ -f "$BEMOJI_CUSTOM_LIST" ]; then
|
|
result=$(cat "$BEMOJI_CUSTOM_LIST")
|
|
elif [ -n "$BEMOJI_CUSTOM_LIST" ] && curl -fsSI "$BEMOJI_CUSTOM_LIST" >/dev/null 2>&1; then
|
|
result=$(curl -sSL "$BEMOJI_CUSTOM_LIST")
|
|
else
|
|
result=$(cat "$bm_db_location"/*.txt)
|
|
fi
|
|
|
|
if [ "$bm_ignore_recent" = true ]; then
|
|
printf "%s" "$result"
|
|
else
|
|
printf "%s\n%s" "$(get_most_recent)" "$result" | cat -n - | sort -uk2 | sort -n | cut -f2-
|
|
fi
|
|
}
|
|
|
|
get_most_recent() {
|
|
recent_file="$bm_history_file"
|
|
if [ ! -f "$recent_file" ]; then
|
|
touch "$recent_file"
|
|
fi
|
|
# TODO improve this messy line
|
|
sed -e '/^$/d' "$recent_file" |
|
|
sort |
|
|
uniq -c |
|
|
sort -rn |
|
|
sed -e 's/^\s*//' |
|
|
cut -d' ' -f2-
|
|
}
|
|
|
|
add_to_recent() {
|
|
if [ -z "$1" ]; then return; fi
|
|
if [ ! -d "$bm_state_dir" ]; then
|
|
mkdir -p "$bm_state_dir"
|
|
fi
|
|
echo "$1" >>"$bm_history_file"
|
|
}
|
|
|
|
# Set default clipboard util
|
|
_clipper() {
|
|
if [ -n "$BEMOJI_CLIP_CMD" ]; then
|
|
# shellcheck disable=SC2068
|
|
${BEMOJI_CLIP_CMD[@]}
|
|
elif [ -n "$WAYLAND_DISPLAY" ] && command -v wl-copy >/dev/null 2>&1; then
|
|
wl-copy
|
|
elif [ -n "$DISPLAY" ] && command -v xclip >/dev/null 2>&1; then
|
|
xclip -selection clipboard
|
|
elif [ -n "$DISPLAY" ] && command -v xsel >/dev/null 2>&1; then
|
|
xsel -b
|
|
else
|
|
printf "No suitable clipboard tool found."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Set default typing uti
|
|
_typer() {
|
|
totype=$(cat -)
|
|
if [ -n "$BEMOJI_TYPE_CMD" ]; then
|
|
# shellcheck disable=SC2068
|
|
${BEMOJI_TYPE_CMD[@]}
|
|
elif [ -n "$WAYLAND_DISPLAY" ] && command -v wtype >/dev/null 2>&1; then
|
|
wtype -s 30 "$totype"
|
|
elif [ -n "$DISPLAY" ] && command -v xdotool >/dev/null 2>&1; then
|
|
xdotool type --delay 30 "$totype"
|
|
else
|
|
printf "No suitable typing tool found."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Set default picker util
|
|
_picker() {
|
|
if [ -n "$BEMOJI_PICKER_CMD" ]; then
|
|
# shellcheck disable=SC2068
|
|
${BEMOJI_PICKER_CMD[@]}
|
|
elif command -v bemenu >/dev/null 2>&1; then
|
|
bemenu -p 🔍 -i -l 20
|
|
elif command -v wofi >/dev/null 2>&1; then
|
|
wofi -p 🔍 -i --show dmenu
|
|
elif command -v rofi >/dev/null 2>&1; then
|
|
rofi -p 🔍 -i -dmenu --kb-custom-1 "Alt+1" --kb-custom-2 "Alt+2"
|
|
elif command -v dmenu >/dev/null 2>&1; then
|
|
dmenu -p 🔍 -i -l 20
|
|
else
|
|
printf "No suitable picker tool found."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
[ -n "$BEMOJI_CUSTOM_LIST" ] || prepare_db
|
|
result=$(gather_emojis | _picker)
|
|
exit_value="$?"
|
|
[ "$bm_private_mode" = true ] || add_to_recent "$result"
|
|
result=$(echo "$result" | grep -o '^\S\+' | tr -d '\n')
|
|
|
|
case "$exit_value" in
|
|
1)
|
|
exit
|
|
;;
|
|
0)
|
|
if [ ${#bm_cmds[@]} -eq 0 ]; then
|
|
if [ -n "$bm_default_cmd" ]; then
|
|
# shellcheck disable=SC2068
|
|
echo "$result" | ${bm_default_cmd[@]}
|
|
exit
|
|
fi
|
|
bm_cmds+=(_clipper)
|
|
fi
|
|
for cmd in "${bm_cmds[@]}"; do
|
|
[ "$bm_echo_newline" = true ] && echo_opts= || echo_opts=-n
|
|
echo $echo_opts "$result" | "$cmd"
|
|
done
|
|
;;
|
|
10)
|
|
echo "$result" | _clipper
|
|
;;
|
|
11)
|
|
echo "$result" | _typer
|
|
;;
|
|
esac
|
|
exit
|