Merge branch 'release/5.2.0'

This commit is contained in:
Chris Down 2018-04-22 10:10:57 +01:00
commit 8388a00ab3
4 changed files with 117 additions and 12 deletions

View file

@ -21,6 +21,8 @@ invoke clipmenu in exactly the same way to get the same effect, like so:
clipmenu -i -fn Terminus:size=8 -nb '#002b36' -nf '#839496' -sb '#073642' -sf '#93a1a1' clipmenu -i -fn Terminus:size=8 -nb '#002b36' -nf '#839496' -sb '#073642' -sf '#93a1a1'
You can remove clips with the `clipdel` utility, see `clipdel --help`.
# How does it work? # How does it work?
The code is fairly simple and easy to follow, you may find it easier to read The code is fairly simple and easy to follow, you may find it easier to read

79
clipdel Executable file
View file

@ -0,0 +1,79 @@
#!/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
flock -x -w "$lock_timeout" "$lock_fd" || exit
for match in "${matches[@]}"; do
ck=$(cksum <<< "$match")
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

View file

@ -30,14 +30,28 @@ if [[ "$CM_LAUNCHER" == rofi ]]; then
set -- -dmenu "$@" set -- -dmenu "$@"
fi fi
# It's okay to hardcode `-l 8` here as a sensible default without checking list_clips() {
# whether `-l` is also in "$@", because the way that dmenu works allows a later cat "$cache_file_prefix"_* /dev/null | LC_ALL=C sort -rnk 1 | cut -d' ' -f2- | awk '!seen[$0]++'
# argument to override an earlier one. That is, if the user passes in `-l`, our }
# one will be ignored.
chosen_line=$( if [[ "$CM_LAUNCHER" == rofi-script ]]; then
cat "$cache_file_prefix"_* /dev/null | LC_ALL=C sort -rnk 1 | if ! (( $# )); then
cut -d' ' -f2- | awk '!seen[$0]++' | "$CM_LAUNCHER" -l 8 "$@" list_clips
) exit
else
# https://github.com/koalaman/shellcheck/issues/1141
# shellcheck disable=SC2124
chosen_line="${@: -1}"
fi
else
# It's okay to hardcode `-l 8` here as a sensible default without checking
# whether `-l` is also in "$@", because the way that dmenu works allows a later
# argument to override an earlier one. That is, if the user passes in `-l`, our
# one will be ignored.
chosen_line=$(
list_clips | "$CM_LAUNCHER" -l 8 "$@"
)
fi
[[ $chosen_line ]] || exit 1 [[ $chosen_line ]] || exit 1
@ -45,7 +59,11 @@ file=$cache_dir/$(cksum <<< "$chosen_line")
if ! [[ -f "$file" ]]; then if ! [[ -f "$file" ]]; then
# We didn't find this in cache # We didn't find this in cache
printf 'FATAL: %s not in cache\n' "$chosen_line" >&2 printf 'FATAL: %s not in cache (%s missing)\n' "$chosen_line" "$file" >&2
printf 'Please report the following debug information:\n\n' >&2
wc -l "$cache_file_prefix"_* >&2
grep -nFR "$chosen_line" "$cache_dir" >&2
stat "$file" >&2
exit 2 exit 2
fi fi

View file

@ -181,15 +181,21 @@ while true; do
rm -- "${last_filename[$selection]}" rm -- "${last_filename[$selection]}"
fi fi
last_data[$selection]=$data
last_filename[$selection]=$filename
first_line=$(get_first_line "$data") first_line=$(get_first_line "$data")
debug "New clipboard entry on $selection selection: \"$first_line\"" debug "New clipboard entry on $selection selection: \"$first_line\""
cache_file_output="$(date +%s%N) $first_line" cache_file_output="$(date +%s%N) $first_line"
filename="$cache_dir/$(cksum <<< "$first_line")" filename="$cache_dir/$(cksum <<< "$first_line")"
last_data[$selection]=$data
last_filename[$selection]=$filename
# Recover without restart if we deleted the entire clip dir.
# It's ok that this only applies to the final directory.
# shellcheck disable=SC2174
mkdir -p -m0700 "$cache_dir"
debug "Writing $data to $filename" debug "Writing $data to $filename"
printf '%s' "$data" > "$filename" printf '%s' "$data" > "$filename"