Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.4 KiB

  1. #!/usr/bin/env bash
  2. CM_REAL_DELETE=0
  3. if [[ $1 == -d ]]; then
  4. CM_REAL_DELETE=1
  5. shift
  6. fi
  7. shopt -s nullglob
  8. cache_dir=$(clipctl cache-dir)
  9. cache_file=$cache_dir/line_cache
  10. lock_file=$cache_dir/lock
  11. lock_timeout=2
  12. if [[ $1 == --help ]] || [[ $1 == -h ]]; then
  13. cat << 'EOF'
  14. clipdel deletes clipmenu entries matching a regex. By default, just lists what
  15. it would delete, pass -d to do it for real. If no pattern is passed as an argument,
  16. it will try to read one from standard input.
  17. ".*" is special, it will just nuke the entire data directory, including the
  18. line caches and all other state.
  19. Arguments:
  20. -d Delete for real.
  21. Environment variables:
  22. - $CM_DIR: specify the base directory to store the cache dir in (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp)
  23. EOF
  24. exit 0
  25. fi
  26. if ! [[ -f $cache_file ]]; then
  27. printf '%s\n' "No line cache file found, no clips exist" >&2
  28. exit 0 # Well, this is a kind of success...
  29. fi
  30. if [[ -n $1 ]]; then
  31. raw_pattern=$1
  32. elif ! [[ -t 0 ]]; then
  33. IFS= read -r raw_pattern
  34. fi
  35. esc_pattern=${raw_pattern//\#/'\#'}
  36. # We use 2 separate sed commands so "esc_pattern" matches only the 'clip' text
  37. # without the timestamp (e.g. $> clipdel '^delete_exact_match$')
  38. sed_common_command="s#^[0-9]\+ ##;\\#${esc_pattern}#"
  39. if ! [[ $raw_pattern ]]; then
  40. printf '%s\n' 'No pattern provided, see --help' >&2
  41. exit 2
  42. fi
  43. exec {lock_fd}> "$lock_file"
  44. if (( CM_REAL_DELETE )) && [[ "$raw_pattern" == ".*" ]]; then
  45. flock -x -w "$lock_timeout" "$lock_fd" || exit
  46. rm -rf -- "$cache_dir"
  47. mkdir -p -- "$cache_dir"
  48. exit 0
  49. else
  50. mapfile -t matches < <(
  51. sed -n "${sed_common_command}p" "$cache_file" |
  52. sort -u
  53. )
  54. if (( CM_REAL_DELETE )); then
  55. flock -x -w "$lock_timeout" "$lock_fd" || exit
  56. for match in "${matches[@]}"; do
  57. ck=$(cksum <<< "$match")
  58. rm -f -- "$cache_dir/$ck"
  59. done
  60. temp=$(mktemp)
  61. # sed 'h' and 'g' here means save and restore the line, so
  62. # timestamps are not removed from non-deleted lines. 'd' deletes the
  63. # line and restarts, skipping 'g'/restore.
  64. # https://www.gnu.org/software/sed/manual/html_node/Other-Commands.html#Other-Commands
  65. sed "h;${sed_common_command}d;g" "$cache_file" > "$temp"
  66. mv -- "$temp" "$cache_file"
  67. flock -u "$lock_fd"
  68. else
  69. if (( ${#matches[@]} )); then
  70. printf '%s\n' "${matches[@]}"
  71. fi
  72. fi
  73. fi