From 1d4994d432cca227730ed97a54b755be1954accc Mon Sep 17 00:00:00 2001
From: sinanmohd <sinan@firemail.cc>
Date: Thu, 3 Aug 2023 16:14:11 +0530
Subject: damb: rewrite, better ux and more features

changelogs:
* switched to fully posix key value implementation
* only show stop option when an ambiance is already playing
* only show clipboard option when valid data is in clipboard
* auto generated icons for popular websites and other menu options
---
 damb | 307 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 251 insertions(+), 56 deletions(-)

(limited to 'damb')

diff --git a/damb b/damb
index 3f4e620..96d6bab 100755
--- a/damb
+++ b/damb
@@ -1,18 +1,38 @@
 #!/bin/sh
 
-# dir where audio files are stored
-amb_dir="$HOME/.local/share/damb"
-pid_file="${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}}/damb.pids"
-config_dir="$HOME/.config/damb"
-menu="wmenu"
-ico="󰎆 "
+damb_conf="${XDG_CONFIG_HOME:-$HOME/.config}/damb/damb.conf"
+damb_data="${XDG_DATA_HOME:-$HOME/.local/share}/damb"
+damb_pids="${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}}/damb.pids"
+
+w_menu="wmenu"
+x_menu="dmenu"
+
+ico_damb="󰎆 "
+ico_locl="󱝟 "
+ico_ytbe=" "
+ico_sndc=" "
+ico_gurl="󰌹 "
+ico_what=" "
+
+usage()
+{
+	cat <<- EOF
+	Usage: damb [ command ] [ option ]
+	a bookmark manager using dmenu
+	Commands:
+	  help	 show this help cruft
+	  save	 <key> <value>, save a new key
+	  rm	 <key>, remove a key
+
+	EOF
+}
 
 die()
 {
 	: "${1:?}"
 
 	command -v notify-send > /dev/null &&
-		notify-send "${ico} damb" "$1"
+		notify-send "${ico_damb}  damb" "$1"
 
 	printf "\033[31;1merr: %b\033[0m\n" "$1"
 	exit "${2:-1}"
@@ -30,71 +50,246 @@ dep_check()
 	unset dep
 }
 
-menu_opt()
+trim()
+{
+	: "${1:?}"
+
+	_trimstr="${1#"${1%%[![:space:]]*}"}"
+	_trimstr="${_trimstr%"${_trimstr##*[![:space:]]}"}"
+
+	echo "$_trimstr"
+}
+
+gen_ico()
+{
+	case "$1" in
+	https://www.youtube.com/*|https://youtu.be/*)
+		echo "$ico_ytbe" ;;
+	https://soundcloud.com/*)
+		echo "$ico_sndc" ;;
+	http*)
+		echo "$ico_gurl" ;;
+	/*)
+		echo "$ico_locl" ;;
+	*)
+		echo "$ico_what" ;;
+	esac
+}
+
+parse_keys()
+{
+	# usage parse_data [ getval <key> ]
+	line=
+	_key=
+	_value=
+
+	[ -s "$damb_conf" ] || return 1
+
+	while read -r line
+	do
+		[ -z "$line" ] && continue
+
+		_key="${line%%|*}"
+		_key="$(trim "$_key")"
+
+		case "$_key" in
+		#*) continue
+		esac
+
+		if [ "$1" = "getval" ]; then
+			[ "$2" != "$_key" ] && continue
+
+			_value="${line##*|}"
+			_value="$(trim "$_value")"
+			echo "$_value"
+			return 0
+		else
+			echo "$_key"
+		fi
+	done < "$damb_conf"
+
+	unset _key _value
+	[ "$1" = "getval" ] && return 1
+}
+
+rm_key()
+{
+	# usage rm_data <key>
+	: "${1:?}"
+	cl=
+	line=
+	file=
+	value=
+	old_ifs="$IFS"
+
+	IFS=
+	while read -r line
+	do
+		cl="$line\n"
+
+		key="$(trim "${cl%%|*}")"
+		# catch match
+		if [ "$key" = "$1" ]; then
+			value="$(trim "${cl##*|}")"
+
+			# delete if saved
+			case "$value" in
+			"$damb_data"*) rm -f "$value"
+			esac
+			continue
+		fi
+
+		file="${file}${cl}"
+	done < "$damb_conf"
+
+	IFS="$old_ifs"
+	# shellcheck disable=SC2059
+	printf "$file" > "$damb_conf"
+	unset cl line file value old_ifs
+}
+
+verify_val()
+{
+	# verify_val <value>
+
+	case "$(file --brief --dereference --mime-type "$1")" in
+	audio/*|video/*) ;;
+	*)
+		echo "$1" | grep -qxE '^(https?://)?[^/]*\.[A-Za-z0-9]*(/.*)?' ||
+			return 1
+	esac
+}
+
+write_kv()
 {
-        printf "%s\n" "select" "links" "stream" "stop" | "$menu" -p "$ico"
+	# verify_val <key> <value>
+	: "${1:?}"
+	: "${2:?}"
+
+	key="$(trim "$1")"
+	val="$(trim "$2")"
+
+	case "$key" in
+	[![:cntrl:][:print:]]*) ;; # check for unicode chars
+	*) key="$(gen_ico "$val") ${key}"
+	esac
+
+	parse_keys getval "$key" > /dev/null &&
+		die "keys must be unique"
+	verify_val "$val" ||
+		die "invalid: $val"
+
+	echo "$key | $val" >> "$damb_conf"
 }
 
-get_ambs()
+kill_ambs()
 {
-        find "$amb_dir" -type f -exec basename {} \;
+	while read -r pid; do
+		kill -9 "$pid"
+	done < "$damb_pids"
+
+	rm "$damb_pids"
 }
 
-get_link()
+play_amb()
 {
-        grep -v "^#.*$" "$config_dir"/links |
-                grep "$(grep -v "^#.*$" "$config_dir"/links | cut -d '=' -f1 | "$menu" -p "$ico" -l 25)" |
-                cut -d '=' -f2 | tr -d ' '
+	: "${1:?}"
+
+	mpv --no-video --no-cache --no-resume-playback "$@" &
+	echo "$!" >> "$damb_pids"
 }
 
-main()
+set_menu()
 {
-	[ -z "$WAYLAND_DISPLAY" ] &&
-		menu="dmenu"
+	if [ -n "$WAYLAND_DISPLAY" ]; then
+		menu="$w_menu"
+	elif [ -n "$DISPLAY" ]; then
+		menu="$x_menu"
+	else
+		die "tty not supported"
+	fi
 
 	dep_check "$menu"
+}
 
-	case "$(menu_opt)" in
-	select)
-		dep_check "ffplay"
-		ffplay -volume 20 -nodisp -loop 0 "$amb_dir/$(get_ambs | "$menu" -p "$ico" -l 25)" &
-		echo "$!" >> "$pid_file"
-		;;
-	links)
-		dep_check "mpv"
-		mpv --no-video --no-resume-playback "$(get_link)" &
-		echo "$!" >> "$pid_file"
-		;;
-	stop)
-		while read -r process
-		do
-			kill -9 "$process"
-		done < "$pid_file"
-
-		rm "$pid_file"
-		;;
-	stream)
-		paste=
-		dep_check "mpv"
-
-		if [ -n "$WAYLAND_DISPLAY" ]; then
-			dep_check "wl-paste"
-			paste="$(wl-paste)"
-		elif [ -n "$DISPLAY" ]; then
-			dep_check "xclip"
-			paste="$(xclip -o -sel clip)"
-		else
-			die "tty supported, run a display server"
+set_clip()
+{
+	if [ -n "$WAYLAND_DISPLAY" ]; then
+		dep_check "wl-paste"
+		_clip="$(wl-paste)"
+	elif [ -n "$DISPLAY" ]; then
+		dep_check "xclip"
+		_clip="$(xclip -o)"
+	fi
+
+	verify_val "$_clip"
+}
+
+gen_opts()
+{
+
+	[ -s "$damb_pids" ] && while read -r pid; do
+		if [ -d "/proc/${pid}" ]; then
+			echo "  stop the ambiances"
+			break;
 		fi
+	done < "$damb_pids"
+
+	set_clip &&
+		echo "$(gen_ico "$_clip") $_clip (from clipboard)"
 
-		mpv --no-video "$paste" &
-		echo "$!" >> "$pid_file"
-		;;
-	"")
-		;; # stay quiet when user quits the program during selection
+	parse_keys
+}
+
+gen_menu()
+{
+	[ -s "$damb_conf" ] || die "empty, try damb save"
+	key="$(gen_opts | wmenu -l 25)" || return 1
+
+	case "$key" in
+	*"stop the ambiances")
+		kill_ambs ;;
+	*"from clipboard)")
+		set_clip
+		play_amb "$_clip" ;;
 	*)
-		die "option not implemented";;
+		play_amb --loop "$(parse_keys getval "$key")" ;;
 	esac
 }
 
-main "$@"
+########
+# MAIN #
+########
+
+[ -d "$damb_data" ] || mkdir -p "$damb_data"
+[ -d "${damb_conf%/*}" ] || mkdir -p "${damb_conf%/*}"
+
+set_menu
+dep_check mpv
+
+case "$1" in
+rm)
+	key="$(parse_keys | "$menu" -l 25)" || exit 1
+	rm_key "$key"
+	;;
+save)
+	[ "$#" -ne 3 ] &&
+		die "invalid usage, try damb help"
+
+	if [ -f "$3" ]; then
+		cp "$3" "$damb_data"
+		val="${damb_data}/${3##*/}"
+	fi
+
+	write_kv "$2" "${val:-$3}"
+	;;
+"")
+	gen_menu
+	;;
+help)
+	usage
+	;;
+*)
+	die "invalid usage $*, try damb help"
+	;;
+esac
-- 
cgit v1.2.3