Merge branch 'release/5.0.0'
This commit is contained in:
commit
44c0fb3ad2
9
clipmenu
9
clipmenu
|
@ -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
|
||||
|
||||
|
|
68
clipmenud
68
clipmenud
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue