aboutsummaryrefslogtreecommitdiff
path: root/dbook
diff options
context:
space:
mode:
Diffstat (limited to 'dbook')
-rwxr-xr-xdbook401
1 files changed, 193 insertions, 208 deletions
diff --git a/dbook b/dbook
index afc54a7..5cc604b 100755
--- a/dbook
+++ b/dbook
@@ -2,20 +2,31 @@
book_conf="${XDG_CONFIG_HOME:-$HOME/.config}/dbook/dbook.conf"
book_data="${XDG_DATA_HOME:-$HOME/.local/share}/dbook"
-menu="wmenu"
+w_menu="wmenu"
+x_menu="dmenu"
+ico_dbk=" "
+ico_url="󰖟 "
+ico_doc=" "
+ico_pic=" "
+ico_vid=" "
+ico_mus="󰸪 "
+ico_fil=" "
+ico_txt=" "
+ico_dir=" "
usage()
{
cat <<- EOF
- Usage: dbook command
+ Usage: dbook [ command ] [ option ]
a bookmark manager using dmenu
Commands:
- -h show this help cruft
- -i <bookmark string> [name], inset a new entry
- -s <bookmark string> [name], inset a new entry and make a copy
- -d [name], delete an entry
- -t [name], type the data
- -c [name], copy the date to clipboard
+ help show this help cruft
+ insert [ value [ key ] ], inset a new key
+ save [ value [ key ] ], inset but make a cp if it's a file
+ rm [ key ], delete a key
+ Options:
+ -t [ key ], type the vlaue
+ -c [ key ], copy the value to clipboard
EOF
}
@@ -25,7 +36,7 @@ note()
: "${1:?}"
command -v notify-send > /dev/null &&
- notify-send " dbook" "$1"
+ notify-send -- "${ico_dbk} dbook" "$1"
}
die()
@@ -37,6 +48,14 @@ die()
exit "${2:-1}"
}
+warn()
+{
+ : "${1:?}"
+
+ note "$1"
+ printf "\033[33;1merr: %b\033[0m\n" "$1" 1>&2
+}
+
dep_check()
{
: "${1:?}"
@@ -49,72 +68,71 @@ dep_check()
unset dep
}
-parse_name()
+load_icon()
{
- while read -r line
- do
- line=${line%%|*}
-
- # trim leading and trailing white spaces
- line=${line#"${line%%[![:space:]]*}"}
- line=${line%"${line##*[![:space:]]}"}
-
- [ -z "${line##\#*}" ] &&
- continue
-
- echo "$line"
- done < "$book_conf"
+ case "$(file --brief --dereference --mime-type "$1")" in
+ image/*) printf "%s" "$ico_pic" ;;
+ video/*) printf "%s" "$ico_vid" ;;
+ audio/*) printf "%s" "$ico_mus" ;;
+ text/*) printf "%s" "$ico_txt" ;;
+ inode/*) printf "%s" "$ico_dir" ;;
+ application/pdf) printf "%s" "$ico_doc" ;;
+
+ *'No such file or directory)')
+ if echo "$1" | grep -qxE '^(https?://)?[^/]*\.[A-Za-z0-9]*(/.*)?'; then
+ printf "%s" "$ico_url"
+ else
+ printf "%s" "$ico_fil"
+ fi
+ esac
}
parse_data()
{
- read -r book_name
- read_name=
-
- [ -z "$book_name" ] || [ ! -f "$book_conf" ] &&
- return 1
+ # usage parse_data [ getval <key> ]
+ line=
+ _key=
+ _value=
while read -r line
do
- # trim leading and trailing white spaces
- line=${line#"${line%%[![:space:]]*}"}
- line=${line%"${line##*[![:space:]]}"}
-
- # skip trailing lines till match
- case "$line" in
- "$book_name"*)
- # make sure read_name fully matches book_name
- read_name=${line%%|*}
- read_name=${read_name%"${read_name##*[![:space:]]}"}
- [ "$book_name" != "$read_name" ] &&
- continue
- ;;
- *)
- continue
- ;;
- esac
+ [ -z "$line" ] && continue
- # extract date from string
- line="${line##*|}"
- line=${line#"${line%%[![:space:]]*}"}
+ _key="${line%%|*}"
+ _value="${line##*|}"
- echo "$line"
- return 0
+ # trim leading and trailing white spaces
+ _key="${_key#"${_key%%[![:space:]]*}"}"
+ _key="${_key%"${_key##*[![:space:]]}"}"
+ _value="${_value#"${_value%%[![:space:]]*}"}"
+ _value="${_value%"${_value##*[![:space:]]}"}"
+ case "$_key" in
+ #*) continue
+ esac
+
+ if [ "$1" = "getval" ]; then
+ if [ "$2" = "$_key" ]; then
+ echo "$_value"
+ return 0
+ fi
+ else
+ echo "$(load_icon "$_value")" "$_key"
+ fi
done < "$book_conf"
- unset read_name
- return 1
+ unset _key _value
+ [ "$1" = "getval" ] && return 1
}
rm_data()
{
- # usage rm_data [data_name]
+ # usage rm_data <key>
: "${1:?}"
- read_name=
- data=
cl=
+ line=
file=
+ value=
old_ifs="$IFS"
IFS=
@@ -122,199 +140,166 @@ rm_data()
do
cl="$line\n"
+ key="${cl%%|*}"
# trim leading and trailing white spaces
- line=${line#"${line%%[![:space:]]*}"}
- line=${line%"${line##*[![:space:]]}"}
+ key=${key#"${key%%[![:space:]]*}"}
+ key=${key%"${key##*[![:space:]]}"}
# catch match
- case "$line" in
- "$book_name"*)
- read_name=${line%%|*}
- read_name=${read_name%"${read_name##*[![:space:]]}"}
-
- # make sure read_name fully matches
- if [ "$1" = "$read_name" ]
- then
- # remove saved data
- data="$(echo "$read_name" | parse_data)"
- [ -e "$data" ] && [ -z "${data##"${book_data}"/*}" ] &&
- rm "$data"
-
- continue
- fi
- ;;
- esac
+ if [ "$key" = "$1" ]; then
+ value="${cl##*|}"
+ # trim leading and trailing white spaces
+ value="${value#"${value%%[![:space:]]*}"}"
+ value="${value%"${value##*[![:space:]]}"}"
+
+ # delete if saved
+ case "$value" in
+ "$book_data"*) rm -f "$value"
+ esac
+ continue
+ fi
file="${file}${cl}"
-
done < "$book_conf"
- IFS="$old_ifs"
+ IFS="$old_ifs"
# shellcheck disable=SC2059
printf "$file" > "$book_conf"
- unset read_name data file cl old_ifs
+ unset cl line file value old_ifs
}
-entry()
-{
- printf "" | "$menu" -p " ${1:?} " ||
- die "input empty"
-}
-
-sh_realpath()
+clip()
{
- # usage: sh_realpath [path]
+ # usage: clip [ file/text ] <value>
: "${1:?}"
+ : "${2:?}"
- if [ -z "${1##/*}" ]
- then
- echo "$1"
- else
- echo "${PWD:-$(pwd)}/$1"
+ if [ -n "$WAYLAND_DISPLAY" ]; then
+ dep_check "wl-copy"
+
+ [ "$1" = "text" ] &&
+ printf "%s" "$2" | wl-copy
+ [ "$1" = "file" ] &&
+ printf "file://%s" "$2" | wl-copy -t text/uri-list
+ elif [ -n "$DISPLAY" ]; then
+ dep_check "xclip"
+
+ [ "$1" = "text" ] &&
+ printf "%s" "$2" | xclip -selection clipboard
+ [ "$1" = "file" ] &&
+ printf "file://%s" "$2" | xclip -selection clipboard "$1" -t text/uri-list
fi
+
+ note "${1} coppied to clipboard"
}
-clip()
+set_menu()
{
- # usage: clip [data]
- : "${1:?}"
-
- if [ -z "$WAYLAND_DISPLAY" ]
- then
- dep_check "xclip"
- echo "$1" | xclip -selection clipboard
+ if [ -n "$WAYLAND_DISPLAY" ]; then
+ menu="$w_menu"
+ elif [ -n "$DISPLAY" ]; then
+ menu="$x_menu"
else
- dep_check "wl-copy"
- echo "$1" | wl-copy
- fi &&
- note "data coppied to clipboard"
+ die "tty not supported"
+ fi
}
-clip_file()
+ip_menu()
{
- # usage: clip [data]
- : "${1:?}"
-
- if [ -z "$WAYLAND_DISPLAY" ]
- then
- dep_check "xclip"
- echo "$1" | xclip -selection clipboard "$1" -t text/uri-list
- else
- dep_check "wl-copy"
- echo "$1" | wl-copy -t text/uri-list
- fi &&
- note "data coppied to clipboard"
+ printf "" | "$menu" -p "${ico_dbk} ${1:?} "
}
-main()
+key_menu()
{
- name=
- data=
-
- [ -z "$WAYLAND_DISPLAY" ] &&
- menu="dmenu"
-
- [ -d "$book_data" ] ||
- mkdir -p "$book_data"
- [ -d "$book_conf" ] ||
- mkdir -p "${book_conf%/*}"
-
- case "$1" in
- -h|--help)
- usage
- ;;
- -i)
- data="${2:-$(entry name)}"
- shift > /dev/null 2>&1
- shift > /dev/null 2>&1
- name="${*:-$(entry name)}"
-
- echo "$name" | parse_data > /dev/null &&
- die "name already in use"
-
- [ -e "$data" ] &&
- data="$(sh_realpath "$data")"
+ key="$(parse_data | "$menu" -l 25 -p "${ico_dbk} key ")" || return 1
+ echo "${key#* }"
+}
- printf "%s\t|\t%s\n" "$name" "$data" >> "$book_conf"
- ;;
- -s)
- data="${2:-$(entry name)}"
- shift > /dev/null 2>&1
- shift > /dev/null 2>&1
- name="${*:-$(entry name)}"
- echo "$name" | parse_data > /dev/null &&
- die "name already in use"
+########
+# MAIN #
+########
+
+key=
+value=
+
+[ -d "$book_data" ] ||
+ mkdir -p "$book_data"
+[ -d "$book_conf" ] ||
+ mkdir -p "${book_conf%/*}"
+
+set_menu
+case "$1" in
+-*) ;;
+"") ;;
+*) command="$1" && shift
+esac
+
+case "$command" in
+insert)
+ value="${1:-$(ip_menu "value")}" || exit 1
+ key="${2:-$(ip_menu "key")}" || exit 1
+
+ parse_data getval "$key" > /dev/null &&
+ die "key already in use"
+ [ -e "$value" ] &&
+ value="$(realpath "$value")"
+
+ printf "%s\t|\t%s\n" "$key" "$value" >> "$book_conf"
+ ;;
+save)
+ value="${1:-$(ip_menu "value")}" || exit 1
+ key="${2:-$(ip_menu "key")}" || exit 1
+
+ parse_data getval "$key" > /dev/null &&
+ die "key already in use"
+ [ -d "$value" ] &&
+ warn "${value} is a directory, will not be saved"
+
+ if [ -f "$value" ]; then
+ cp "$value" "$book_data"
+ value="${book_data}/$(basename "$value")"
+ fi
- [ -d "$data" ] &&
- die "$data is a directory, use -i instead"
+ printf "%s\t|\t%s\n" "$key" "$value" >> "$book_conf"
+ ;;
+rm)
+ key="${1:-$(key_menu)}" || exit 1
+ rm_data "$key"
+ ;;
+"")
+ dep_check "xdg-open"
+ [ -s "$book_conf" ] ||
+ die "no bookmarks, try dbook -h"
+
+ key="${2:-$(key_menu)}" || exit 1
+ value="$(parse_data getval "$key")" ||
+ die "${key}: no such key"
- if [ -e "$data" ]
- then
- cp "$data" "$book_data"
- data="${book_data}/${data##*/}"
- fi
-
- printf "%s\t|\t%s\n" "$name" "$data" >> "$book_conf"
- ;;
- -d)
- rm_data "${2:-"$(parse_name | "$menu" -p " " -l 25)"}"
- ;;
+ case "$1" in
-t)
- shift > /dev/null 2>&1
- data="${*:-"$(parse_name | "$menu" -p " " -l 25 | parse_data)"}"
- [ -z "$data" ] &&
- die "empty, use -i to add an entry"
-
if [ -z "$WAYLAND_DISPLAY" ]
then
dep_check "xdotool"
- xdotool type --delay 20 "$data"
+ xdotool type --delay 20 "$value"
else
dep_check "wtype"
- wtype -d 20 "$data"
+ wtype -d 20 "$value"
fi
;;
-c)
- shift > /dev/null 2>&1
- data="${*:-"$(parse_name | "$menu" -p " " -l 25 | parse_data)"}"
- [ -z "$data" ] &&
- die "empty, use -i to add an entry"
-
- case "$(file --brief "$data")" in
- *ASCII\ text*)
- clip "$(cat "$data")"
- ;;
- *No\ such\ file\ or\ directory\))
- clip "$data"
- ;;
- *)
- clip_file "$(printf "file://%s" "$data")"
- ;;
+ case "$(file --brief --dereference --mime-type "$value")" in
+ text/*) clip text "$(cat "$value")" ;;
+ *'No such file or directory)') clip text "$value" ;;
+ *) clip file "$value"
esac
;;
"")
- dep_check "xdg-open"
- [ -s "$book_conf" ] ||
- die "no bookmarks, try dbook -h"
-
- data="$(parse_name | "$menu" -p " " -l 25 | parse_data)"
- [ -z "$data" ] &&
- die "empty, use -i to add an entry"
-
- xdg-open "$data" 2> /dev/null ||
- case "$(file --brief "$data")" in
- *ASCII\ text*)
- clip "$(cat "$data")"
- ;;
- *)
- clip "$data"
- ;;
- esac
- ;;
+ xdg-open "$value" 2> /dev/null || clip text "$value" ;;
*)
- die "$1, invalid usage"
+ die "${1}: invalid option"
esac
-}
-
-main "$@"
+ ;;
+help) usage ;;
+*) die "$command, invalid command"
+esac