clipmenu

Simple clipboard management using dmenu
git clone https://git.sinitax.com/cdown/clipmenu
Log | Files | Refs | README | LICENSE | sfeed.txt

clipdel (2584B)


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