683f57484f
Pretty much everyone runs with xsel, so xclip support is becoming more and more questionable. Just have people use xsel.
115 lines
3.7 KiB
Bash
Executable file
115 lines
3.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
cache_dir=/tmp/clipmenu.$USER/
|
|
cache_file=$cache_dir/line_cache
|
|
version=2.0.0
|
|
version_file=$cache_dir/version
|
|
|
|
get_first_line() {
|
|
# Args:
|
|
# - $1, the file or data
|
|
# - $2, optional, the line length limit
|
|
|
|
data=${1?}
|
|
line_length_limit=${2-300}
|
|
|
|
# We look for the first line matching regex /./ here because we want the
|
|
# first line that can provide reasonable context to the user. That is, if
|
|
# you have 5 leading lines of whitespace, displaying " (6 lines)" is much
|
|
# less useful than displaying "foo (6 lines)", where "foo" is the first
|
|
# line in the entry with actionable context.
|
|
awk -v limit="$line_length_limit" '
|
|
BEGIN { printed = 0; }
|
|
|
|
printed == 0 && NF {
|
|
$0 = substr($0, 0, limit);
|
|
printf("%s", $0);
|
|
printed = 1;
|
|
}
|
|
|
|
END {
|
|
if (NR > 1) {
|
|
print " (" NR " lines)";
|
|
} else {
|
|
printf("\n");
|
|
}
|
|
}' <<< "$data"
|
|
}
|
|
|
|
debug() {
|
|
if (( DEBUG )); then
|
|
printf '%s\n' "$@" >&2
|
|
fi
|
|
}
|
|
|
|
# It's ok that this only applies to the final directory.
|
|
# shellcheck disable=SC2174
|
|
mkdir -p -m0700 "$cache_dir"
|
|
|
|
# We currently don't do anything with this, but in future we can use this
|
|
# version for the fabled clipmenu-fsck, or other migration logic.
|
|
printf '%s\n' "$version" > "$version_file"
|
|
|
|
declare -A last_data
|
|
declare -A last_filename
|
|
|
|
while sleep "${CLIPMENUD_SLEEP:-0.5}"; do
|
|
for selection in clipboard primary; do
|
|
data=$(xsel --logfile /dev/null -o --"$selection"; printf x)
|
|
|
|
debug "Data before stripping: $data"
|
|
|
|
# We add and remove the x so that trailing newlines are not stripped.
|
|
# Otherwise, they would be stripped by the very nature of how POSIX
|
|
# defines command substitution.
|
|
data=${data%x}
|
|
|
|
debug "Data after stripping: $data"
|
|
|
|
if [[ $data != *[^[:space:]]* ]]; then
|
|
debug "Skipping as clipboard is only blank"
|
|
continue
|
|
fi
|
|
|
|
if [[ ${last_data[$selection]} == "$data" ]]; then
|
|
debug 'Skipping as last selection is the same as this one'
|
|
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"* ]]; then
|
|
debug "$possible_partial is a possible partial of $data"
|
|
debug "Removing ${last_filename[$selection]}"
|
|
rm -- "${last_filename[$selection]}"
|
|
fi
|
|
|
|
last_data[$selection]=$data
|
|
last_filename[$selection]=$filename
|
|
|
|
first_line=$(get_first_line "$data")
|
|
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"
|
|
|
|
if ! (( NO_OWN_CLIPBOARD )) && [[ $selection != primary ]]; then
|
|
# Take ownership of the clipboard, in case the original application
|
|
# is unable to serve the clipboard request (due to being suspended,
|
|
# etc).
|
|
#
|
|
# Primary is excluded from the change of ownership as applications
|
|
# sometimes act up if clipboard focus is taken away from them --
|
|
# for example, urxvt will unhilight text, which is undesirable.
|
|
#
|
|
# 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 --logfile /dev/null -o --"$selection" | xsel -i --"$selection"
|
|
fi
|
|
done
|
|
done
|