Merge branch 'release/5.0.0'

This commit is contained in:
Chris Down 2018-02-20 11:38:34 +00:00
commit 44c0fb3ad2
4 changed files with 70 additions and 22 deletions

View file

@ -3,12 +3,12 @@
: "${CM_LAUNCHER=dmenu}"
: "${CM_DIR="${XDG_RUNTIME_DIR-"${TMPDIR-/tmp}"}"}"
major_version=4
major_version=5
shopt -s nullglob
cache_dir=$CM_DIR/clipmenu.$major_version.$USER
cache_file=$cache_dir/line_cache
cache_file_prefix=$cache_dir/line_cache
if [[ $1 == --help ]] || [[ $1 == -h ]]; then
cat << 'EOF'
@ -34,7 +34,10 @@ fi
# 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=$(tac "$cache_file" | awk '!seen[$0]++' | "$CM_LAUNCHER" -l 8 "$@")
chosen_line=$(
cat "$cache_file_prefix"_* /dev/null | sort -rnk 1 | cut -d' ' -f2- |
awk '!seen[$0]++' | "$CM_LAUNCHER" -l 8 "$@"
)
[[ $chosen_line ]] || exit 1

View file

@ -6,13 +6,22 @@
: "${CM_DIR="${XDG_RUNTIME_DIR-"${TMPDIR-/tmp}"}"}"
: "${CM_MAX_CLIPS=1000}"
major_version=4
# Shellcheck is mistaken here, this is used later as lowercase.
# shellcheck disable=SC2153
: "${CM_SELECTIONS=clipboard primary}"
major_version=5
cache_dir=$CM_DIR/clipmenu.$major_version.$USER/
cache_file=$cache_dir/line_cache
cache_file_prefix=$cache_dir/line_cache
lock_file=$cache_dir/lock
lock_timeout=2
has_clipnotify=0
# This comes from the environment, so we rely on word splitting.
# shellcheck disable=SC2206
cm_selections=( $CM_SELECTIONS )
xsel_log=/dev/null
for file in /proc/self/fd/2 /dev/stderr; do
[[ -f "$file" ]] || continue
@ -64,6 +73,17 @@ debug() {
fi
}
element_in() {
local item element
item="$1"
for element in "${@:2}"; do
if [[ "$item" == "$element" ]]; then
return 0
fi
done
return 1
}
if [[ $1 == --help ]] || [[ $1 == -h ]]; then
cat << 'EOF'
clipmenud is the daemon that collects and caches what's on the clipboard.
@ -76,6 +96,7 @@ Environment variables:
- $CM_OWN_CLIPBOARD: take ownership of the clipboard (default: 1)
- $CM_MAX_CLIPS: maximum number of clips to store, 0 for inf (default: 1000)
- $CM_DIR: specify the base directory to store the cache dir in (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp)
- $CM_SELECTIONS: space separated list of the selections to manage (default: "clipboard primary")
EOF
exit 0
fi
@ -86,6 +107,8 @@ fi
mkdir -p -m0700 "$cache_dir"
declare -A last_data
declare -A last_filename
declare -A last_cache_file_output
command -v clipnotify >/dev/null 2>&1 && has_clipnotify=1
@ -96,13 +119,16 @@ fi
exec {lock_fd}> "$lock_file"
sleep_cmd=(sleep "${CM_SLEEP:-0.5}")
while true; do
if ! (( CM_ONESHOT )); then
if (( has_clipnotify )); then
clipnotify
# Fall back to polling if clipnotify fails
clipnotify || "${sleep_cmd[@]}"
else
# Use old polling method
sleep "${CM_SLEEP:-0.5}"
"${sleep_cmd[@]}"
fi
fi
@ -117,7 +143,8 @@ while true; do
fi
fi
for selection in clipboard primary; do
for selection in "${cm_selections[@]}"; do
cache_file=${cache_file_prefix}_$selection
data=$(_xsel -o --"$selection"; printf x)
debug "Data before stripping: $data"
@ -139,7 +166,23 @@ while true; do
continue
fi
# If we were in the middle of doing a selection when the previous poll
# ran, then we may have got a partial clip.
possible_partial=${last_data[$selection]}
if [[ $possible_partial && $data == "$possible_partial"* ]] ||
[[ $possible_partial && $data == *"$possible_partial" ]]; then
debug "$possible_partial is a possible partial of $data"
debug "Removing ${last_filename[$selection]}"
previous_size=$(wc -c <<< "${last_cache_file_output[$selection]}")
truncate -s -"$previous_size" "$cache_file"
rm -- "${last_filename[$selection]}"
fi
last_data[$selection]=$data
last_filename[$selection]=$filename
first_line=$(get_first_line "$data")
@ -147,18 +190,21 @@ while true; do
# Without checking ${last_data[any]}, we often double write since both
# selections get the same content
cache_file_output="$(date +%s) $first_line"
if [[ ${last_data[any]} != "$data" ]]; then
filename="$cache_dir/$(cksum <<< "$first_line")"
debug "Writing $data to $filename"
printf '%s' "$data" > "$filename"
debug "Writing $first_line to $cache_file"
printf '%s\n' "$first_line" >> "$cache_file"
debug "Writing $cache_file_output to $cache_file"
printf '%s\n' "$cache_file_output" >> "$cache_file"
fi
last_data[any]=$data
last_cache_file_output[$selection]=$cache_file_output
if (( CM_OWN_CLIPBOARD )) && [[ $selection != primary ]]; then
if (( CM_OWN_CLIPBOARD )) && [[ $selection != primary ]] &&
element_in clipboard "${cm_selections[@]}"; then
# Take ownership of the clipboard, in case the original application
# is unable to serve the clipboard request (due to being suspended,
# etc).
@ -170,13 +216,13 @@ while true; do
# We can't colocate this with the above copying code because
# https://github.com/cdown/clipmenu/issues/34 requires knowing if
# we would skip first.
_xsel -o --"$selection" | _xsel -i --"$selection"
_xsel -o --clipboard | _xsel -i --clipboard
fi
if (( CM_MAX_CLIPS )); then
if (( CM_MAX_CLIPS )) && [[ -f $cache_file ]]; then
mapfile -t to_remove < <(
head -n -"$CM_MAX_CLIPS" "$cache_file" |
while read -r line; do cksum <<< "$line"; done
while read -r line; do cksum <<< "${line#* }"; done
)
num_to_remove="${#to_remove[@]}"
if (( num_to_remove )); then

View file

@ -6,9 +6,9 @@ set -o pipefail
: "${CM_DIR="${XDG_RUNTIME_DIR-"${TMPDIR-/tmp}"}"}"
major_version=4
major_version=5
dir=$CM_DIR/clipmenu.$major_version.$USER
cache_file=$dir/line_cache
cache_file=$dir/line_cache_primary
if [[ $0 == /* ]]; then
location=${0%/*}
@ -58,8 +58,8 @@ rm -rf "$dir"
mkdir -p "$dir"
cat > "$cache_file" << 'EOF'
Selected text. (2 lines)
Selected text 2. (2 lines)
1234 Selected text. (2 lines)
1235 Selected text 2. (2 lines)
EOF
cat > "$dir/$(cksum <<< 'Selected text. (2 lines)')" << 'EOF'
@ -70,7 +70,6 @@ EOF
### TESTS ###
temp=$(mktemp)
trap 'rm -f -- "$temp"' EXIT
/tmp/clipmenu --foo bar > "$temp" 2>&1

View file

@ -1,6 +1,6 @@
#!/bin/bash
major_version=4
major_version=5
msg() {
printf '>>> %s\n' "$@" >&2
@ -9,7 +9,7 @@ msg() {
: "${CM_DIR="${XDG_RUNTIME_DIR-"${TMPDIR-/tmp}"}"}"
dir=$CM_DIR/clipmenu.$major_version.$USER
cache_file=$dir/line_cache
cache_file=$dir/line_cache_primary
log=$(mktemp)
tim=$(mktemp)
@ -62,7 +62,7 @@ if ! (( NO_RECREATE )); then
)
read -r first_line_raw <<< "$data"
printf -v first_line '%s (%s lines)\n' "$first_line_raw" "$num_lines"
printf '%s' "$first_line" >> "$cache_file"
printf '%d %s' "$i" "$first_line" >> "$cache_file"
fn=$dir/$(cksum <<< "$first_line")
printf '%s' "$data" > "$fn"
done