226 lines
4.8 KiB
Bash
Executable File
226 lines
4.8 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Description: A cli bookmark manager written in POSIX shell
|
|
#
|
|
# Author: NRK
|
|
## Copyright 2021 NRK
|
|
## Licensed under GPL v3. See LICENSE for more details.
|
|
|
|
##########
|
|
# CONFIG #
|
|
##########
|
|
|
|
# Appname and Version
|
|
APPNAME="sxbm"
|
|
VERSION="v0.3"
|
|
|
|
# Where all the data gets stored
|
|
# Respects XDG_DATA_HOME if set
|
|
[ -z "$XDG_DATA_HOME" ] && XDG_DATA_HOME="$HOME/.local/share"
|
|
DATA_DIR="${XDG_DATA_HOME}/${APPNAME}"
|
|
DATA_FILE="${DATA_DIR}/bookmarks"
|
|
|
|
# Colors
|
|
# For a list of ANSI color codes, check the link below
|
|
# https://gist.github.com/Prakasaka/219fe5695beeb4d6311583e79933a009
|
|
COL_LINK="\033[1;31m" # Red
|
|
COL_TITLE="\033[0;33m" # Yellow
|
|
COL_LINE_NUM="\033[1;34m" # Blue
|
|
|
|
# 1 to enable encryption, 0 to disable it
|
|
# This currently does nothing, since the feature isn't implemented yet.
|
|
ENCRYPTION="0"
|
|
|
|
|
|
#################
|
|
### functions ###
|
|
#################
|
|
|
|
die(){
|
|
[ -z "$1" ] ||
|
|
printf "$@\n" > /dev/stderr
|
|
exit 1
|
|
}
|
|
|
|
usage(){
|
|
printf "Usage: $APPNAME <command> [<args>]\n"
|
|
printf "
|
|
COMMANDS:
|
|
add <link> [title] [+tags]
|
|
ls|list [-s|--strict] [-c|--disable-colors] [title] [+tags]
|
|
open [-f|--force] <line_num|title|+tags>
|
|
rm|remove <line_num>
|
|
edit
|
|
-h|--help print this text and exit
|
|
-v|--version print the version and exit\n\n"
|
|
}
|
|
|
|
version(){
|
|
printf "$APPNAME $VERSION\n"
|
|
printf "GPLv3 license\n"
|
|
printf "https://github.com/n-r-k/sxbm\n"
|
|
}
|
|
|
|
bm_add(){
|
|
[ -z "$1" ] && die "No arguments provided. Use '$APPNAME -h' for help"
|
|
|
|
while [ -n "$1" ]; do
|
|
case "$1" in
|
|
*.*) [ -z "$LINK" ] &&
|
|
LINK="$1" ||
|
|
die "too many links\n$LINK\n$1" ;;
|
|
+*) TAGS="${TAGS}$1 " ;;
|
|
*) TITLE="${TITLE}$1 " ;;
|
|
esac
|
|
shift
|
|
done
|
|
[ -z "$LINK" ] && die "No links found"
|
|
|
|
echo "$LINK $TITLE $TAGS" >> $DATA_FILE &&
|
|
echo "Link $(wc -l < "$DATA_FILE") added successfully!" ||
|
|
die "Couldn't add link"
|
|
}
|
|
|
|
bm_list(){
|
|
QUERY_TAG=""
|
|
QUERY_TITLE=""
|
|
QUERY_STRICT="||"
|
|
|
|
while [ -n "$1" ]; do
|
|
case "$1" in
|
|
"-c"|"--disable-colors")
|
|
COL_LINK=""; COL_TITLE=""; COL_LINE_NUM="";
|
|
shift
|
|
;;
|
|
"-s"|"--strict")
|
|
QUERY_STRICT="&&"
|
|
shift
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# POSIX shell doesn't have arrays.
|
|
# Desperate times calls for desperate measures!
|
|
while [ -n "$1" ]; do
|
|
case "$1" in
|
|
+*)
|
|
[ -z "$QUERY_TAG" ] &&
|
|
QUERY_TAG="/[[:blank:]]\\$1($| )/" ||
|
|
QUERY_TAG="${QUERY_TAG} $QUERY_STRICT /[[:blank:]]\\$1($| )/"
|
|
;;
|
|
*)
|
|
if [ -z "$QUERY_TITLE" ]; then
|
|
QUERY_TITLE="grep -i -e \"$1\""
|
|
else
|
|
[ "$QUERY_STRICT" = "&&" ] &&
|
|
QUERY_TITLE="${QUERY_TITLE} | grep -i -e \"$1\"" ||
|
|
QUERY_TITLE="${QUERY_TITLE} -e \"$1\""
|
|
fi
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
__tag_search(){
|
|
awk -v COL_LINE_NUM="$COL_LINE_NUM" \
|
|
-v COL_LINK="$COL_LINK" -v COL_TITLE="$COL_TITLE" \
|
|
"$QUERY_TAG { LINK=\$1; \$1=\"\";
|
|
gsub(/[[:space:]]\+[^[:space:]]+/,\"\");
|
|
print COL_LINE_NUM NR \") \" COL_LINK LINK \" \" COL_TITLE \$0 }" \
|
|
"$DATA_FILE"
|
|
}
|
|
|
|
[ -z "$QUERY_TITLE" ] &&
|
|
__tag_search ||
|
|
__tag_search | eval "$QUERY_TITLE"
|
|
}
|
|
|
|
bm_open(){
|
|
if [ "$1" = "-f" ] || [ "$1" = "--force" ]; then
|
|
FORCE=1
|
|
shift
|
|
fi
|
|
[ -z "$1" ] && die "No arguments given"
|
|
|
|
if [ -z "$2" ] && [ "$1" -eq "$1" 2>/dev/null ]; then
|
|
LINK=$( awk -v F="$1" 'NR == F {print NR" "$1}' $DATA_FILE )
|
|
else
|
|
LINK=$( bm_list "-c" "$@" )
|
|
fi
|
|
|
|
[ -n "$LINK" ] &&
|
|
LINK_NUM=$( echo "$LINK" | wc -l ) ||
|
|
die "No links found"
|
|
|
|
if [ "$LINK_NUM" -gt 1 ] && [ -z "$FORCE" ]; then
|
|
die "Too many links\nUse '$APPNAME open -f' to force open them all\n\n$( echo "$LINK" )"
|
|
fi
|
|
|
|
setsid $BROWSER $( echo "$LINK" | awk '{print $2;}' ) 1>/dev/null 2>&1
|
|
}
|
|
|
|
bm_edit(){
|
|
$EDITOR "$DATA_FILE"
|
|
}
|
|
|
|
bm_remove(){
|
|
[ -z "$1" ] && die "No arguments given"
|
|
|
|
[ "$1" -eq "$1" 2>/dev/null ] &&
|
|
LINK=$(sed "$1q;d" $DATA_FILE) ||
|
|
die "Link not found"
|
|
|
|
printf "Delete this link? (y/n)\n$LINK\n"
|
|
read ANSWER
|
|
if [ "$ANSWER" = "y" ] || [ "$ANSWER" = "yes" ]; then
|
|
sed -i --follow-symlinks "$1d" "$DATA_FILE" &&
|
|
echo "Deleted successfully" ||
|
|
die "Couldn't delete link"
|
|
fi
|
|
}
|
|
|
|
############
|
|
### main ###
|
|
############
|
|
|
|
[ -z "$1" ] && usage && die "No command given"
|
|
|
|
[ -d "$DATA_DIR" ] ||
|
|
mkdir -p "$DATA_DIR" ||
|
|
die "Unable to create $DATA_DIR"
|
|
|
|
case "$1" in
|
|
"add")
|
|
shift
|
|
bm_add "$@"
|
|
;;
|
|
"ls"|"list")
|
|
shift
|
|
bm_list "$@"
|
|
;;
|
|
"open")
|
|
shift
|
|
bm_open "$@"
|
|
;;
|
|
"rm"|"remove")
|
|
shift
|
|
bm_remove "$@"
|
|
;;
|
|
"edit")
|
|
shift
|
|
bm_edit "$@"
|
|
;;
|
|
"-h"|"--help")
|
|
usage && exit 0
|
|
;;
|
|
"-v"|"--version")
|
|
version && exit 0
|
|
;;
|
|
*)
|
|
die "Invalid command. Use '$APPNAME -h' for help!"
|
|
;;
|
|
esac
|