commit 72760da7a46ac570c220eb333dad40be1b5f68b7
parent b73e742c5058ac6ce29183636edd201fc294db50
Author: Chris Down <chris@chrisdown.name>
Date: Sun, 11 Mar 2018 19:56:25 -0400
Add clipdel utility
Diffstat:
A | clipdel | | | 83 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 83 insertions(+), 0 deletions(-)
diff --git a/clipdel b/clipdel
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+: "${CM_DIR="${XDG_RUNTIME_DIR-"${TMPDIR-/tmp}"}"}"
+CM_REAL_DELETE=0
+[[ $1 == -d ]] && CM_REAL_DELETE=1
+
+major_version=5
+
+shopt -s nullglob
+
+cache_dir=$CM_DIR/clipmenu.$major_version.$USER
+cache_file_prefix=$cache_dir/line_cache
+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
+
+line_cache_files=( "$cache_file_prefix"_* )
+
+if (( ${#line_cache_files[@]} == 0 )); then
+ printf '%s\n' "No line cache files found, no clips exist" >&2
+ exit 0 # Well, this is a kind of success...
+fi
+
+# https://github.com/koalaman/shellcheck/issues/1141
+# shellcheck disable=SC2124
+raw_pattern=${@: -1}
+esc_pattern=${raw_pattern/\#/'\#'}
+
+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 < <(
+ cat "${line_cache_files[@]}" | cut -d' ' -f2- | sort -u |
+ sed -n "\\#${esc_pattern}#p"
+ )
+
+ if (( CM_REAL_DELETE )); then
+ mapfile -t match_cksums < <(
+ for match in "${matches[@]}"; do cksum <<< "${line}"; done
+ )
+
+ flock -x -w "$lock_timeout" "$lock_fd" || exit
+
+ for match in "${matches[@]}"; do
+ ck=$(cksum <<< "$line")
+ rm -f -- "$cache_dir/$ck"
+ done
+
+ for file in "${line_cache_files[@]}"; do
+ temp=$(mktemp)
+ cut -d' ' -f2- < "$file" | sed "\\#${esc_pattern}#d" > "$temp"
+ mv -- "$temp" "$file"
+ done
+
+ flock -u "$lock_fd"
+ else
+ if (( ${#matches[@]} )); then
+ printf '%s\n' "${matches[@]}"
+ fi
+ fi
+fi