clipmenu-spmenu/clipdel

90 lines
2.3 KiB
Plaintext
Raw Normal View History

2018-10-31 09:12:09 +01:00
#!/usr/bin/env bash
2018-03-12 00:56:25 +01:00
: "${CM_DIR="${XDG_RUNTIME_DIR-"${TMPDIR-/tmp}"}"}"
CM_REAL_DELETE=0
if [[ $1 == -d ]]; then
CM_REAL_DELETE=1
shift
fi
2018-03-12 00:56:25 +01:00
major_version=6
2018-03-12 00:56:25 +01:00
shopt -s nullglob
cache_dir=$CM_DIR/clipmenu.$major_version.$USER
cache_file=$cache_dir/line_cache
2018-03-12 00:56:25 +01:00
lock_file=$cache_dir/lock
lock_timeout=2
if [[ $1 == --help ]] || [[ $1 == -h ]]; then
cat << 'EOF'
clipdel deletes clipmenu entries matching a regex. By default, just lists what
it would delete, pass -d to do it for real.
".*" is special, it will just nuke the entire data directory, including the
line caches and all other state.
Arguments:
-d Delete for real.
Environment variables:
- $CM_DIR: specify the base directory to store the cache dir in (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp)
EOF
exit 0
fi
if ! [[ -f $cache_file ]]; then
printf '%s\n' "No line cache file found, no clips exist" >&2
2018-03-12 00:56:25 +01:00
exit 0 # Well, this is a kind of success...
fi
raw_pattern=$1
esc_pattern=${raw_pattern//\#/'\#'}
2018-03-12 00:56:25 +01:00
# We use 2 separate sed commands so "esc_pattern" matches only the 'clip' text
# without the timestamp (e.g. $> clipdel '^delete_exact_match$')
sed_common_command="s#^[0-9]\+ ##;\\#${esc_pattern}#"
if ! [[ $raw_pattern ]]; then
printf '%s\n' 'No pattern provided, see --help' >&2
exit 2
fi
2018-03-12 00:56:25 +01:00
exec {lock_fd}> "$lock_file"
if (( CM_REAL_DELETE )) && [[ "$raw_pattern" == ".*" ]]; then
flock -x -w "$lock_timeout" "$lock_fd" || exit
rm -rf -- "$cache_dir"
exit 0
else
mapfile -t matches < <(
sed -n "${sed_common_command}p" "$cache_file" |
sort -u
2018-03-12 00:56:25 +01:00
)
if (( CM_REAL_DELETE )); then
flock -x -w "$lock_timeout" "$lock_fd" || exit
for match in "${matches[@]}"; do
ck=$(cksum <<< "$match")
2018-03-12 00:56:25 +01:00
rm -f -- "$cache_dir/$ck"
done
temp=$(mktemp)
# sed 'h' and 'g' here means save and restore the line, so
# timestamps are not removed from non-deleted lines. 'd' deletes the
# line and restarts, skipping 'g'/restore.
# https://www.gnu.org/software/sed/manual/html_node/Other-Commands.html#Other-Commands
sed "h;${sed_common_command}d;g" "$cache_file" > "$temp"
mv -- "$temp" "$cache_file"
2018-03-12 00:56:25 +01:00
flock -u "$lock_fd"
else
if (( ${#matches[@]} )); then
printf '%s\n' "${matches[@]}"
fi
fi
fi