|
|
- #!/usr/bin/env bash
-
- CM_REAL_DELETE=0
- if [[ $1 == -d ]]; then
- CM_REAL_DELETE=1
- shift
- fi
-
- shopt -s nullglob
-
- cache_dir=$(clipctl cache-dir)
- cache_file=$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. 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. $> 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
-
- 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
|