#!/usr/bin/env bash #------------------------------------------------------------------------------ # Path - /usr/bin/clipmenu-del # GitHub - https://github.com/The-Repo-Club/ # Author - The-Repo-Club [wayne6324@gmail.com] # Start On - Tue 05 Oct 16:09:16 BST 2021 # Modified On - Sun 31 Oct 00:30:32 BST 2021 #------------------------------------------------------------------------------ CM_REAL_DELETE=0 if [[ $1 == -d ]]; then CM_REAL_DELETE=1 shift fi shopt -s nullglob cache_dir=$(clipmenu-ctl cache-dir) cache_file=$cache_dir/line_cache lock_file=$cache_dir/lock lock_timeout=2 if [[ $1 == --help ]] || [[ $1 == -h ]]; then cat << 'EOF' clipmenu-del deletes clipmenu entries matching a regex. By default, just lists what it would delete, pass -d to do it for real. If no pattern is passed as an argument, it will try to read one from standard input. ".*" 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 exit 0 # Well, this is a kind of success... fi if [[ -n $1 ]]; then raw_pattern=$1 elif ! [[ -t 0 ]]; then IFS= read -r raw_pattern fi esc_pattern=${raw_pattern//\#/'\#'} # We use 2 separate sed commands so "esc_pattern" matches only the 'clip' text # without the timestamp (e.g. $> clipmenu-del '^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 exec {lock_fd}> "$lock_file" if (( CM_REAL_DELETE )) && [[ "$raw_pattern" == ".*" ]]; then flock -x -w "$lock_timeout" "$lock_fd" || exit rm -rf -- "$cache_dir" mkdir -p -- "$cache_dir" exit 0 else mapfile -t matches < <( sed -n "${sed_common_command}p" "$cache_file" | sort -u ) if (( CM_REAL_DELETE )); then flock -x -w "$lock_timeout" "$lock_fd" || exit for match in "${matches[@]}"; do ck=$(cksum <<< "$match") 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" flock -u "$lock_fd" else if (( ${#matches[@]} )); then printf '%s\n' "${matches[@]}" fi fi fi