Created
August 13, 2022 13:59
-
-
Save vuori/39871a883292e99ae98c881a56ed7792 to your computer and use it in GitHub Desktop.
get/set X selections from zsh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# copy selection: same as xclip, but works from remote hosts too | |
zclip() { | |
# See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands | |
# for targets. Usually either p(rimary), c(lipboard) or both, or s(elect) to use | |
# the definition of SELECT from X resources. For the adventurous, q (secondary) | |
# is also available. | |
# | |
# Note: SetSelection must be in allowed window ops. | |
# | |
# Flags: -n don't chomp newline, -t pass to stdout ("tee") | |
local -a tee_mode nochomp_mode | |
zparseopts -F -D t=tee_mode n=nochomp_mode || return | |
local target=${1:-pc} data chomp_data='' | |
# Read input data into memory. We could kinda sorta | |
# stream this, but with chomping and everything, it | |
# just isn't worth the trouble. | |
IFS='' read -s -r -d $'\004' data | |
if ! (( ${#nochomp_mode} )) ; then | |
# Chomp it | |
[[ $data[-1] == $'\n' ]] && chomp_data=$data[0,-2] | |
else | |
# Pass through as is | |
chomp_data=$data | |
fi | |
# Cut down the data to a reasonable size. We might | |
# want to fail here instead if it's too large. | |
chomp_data=$chomp_data[1,2048] | |
# Output to the terminal for copy | |
{ | |
print -n "\e]52;$target;" | |
print -n -r -- $chomp_data | openssl base64 -A -a | |
print -n '\e\\' | |
} > /dev/tty | |
# and if we're tee'ing, output it here for viewing | |
(( ${#tee_mode} )) && print -n -- $data | |
return 0 | |
} | |
# paste selection: as above | |
zgetclip() { | |
local data=() | |
local source=${1:-s} | |
# Request clipboard data (OSC 52). Response format is | |
# ^[]52;p;DDD^[\ where DDD is Base64-encoded data. | |
# | |
# Note: GetSelection must be in allowed window ops. | |
# | |
# We need to force tty access here to have this work | |
# with redirection. | |
print -n "\e]52;$source;?\e\\" > /dev/tty | |
IFS=$'\e;' read -r -s -d '\' -t 1 -A data < /dev/tty | |
if [[ $data[2] != ']52' ]] ; then | |
printf "zgetclip: unexpected response %q;%q\n" $data[2] $data[3] >& 2 | |
return 1 | |
fi | |
openssl base64 -a -d <<< $data[4] | |
} | |
_zgetclip_to_var() { | |
unset REPLY | |
zgetclip $@ | IFS='' read -r -d $'\004' REPLY | |
(( ${#REPLY} )) | |
} | |
_zgetclip_to_kill_ring() { | |
local source=s | |
case $WIDGET in | |
*-clipboard) | |
source=c | |
;; | |
*-primary) | |
source=p | |
;; | |
*-secondary) | |
source=q | |
;; | |
esac | |
_zgetclip_to_var $source || return | |
zle copy-region-as-kill $REPLY | |
} | |
_zgetclip_yank() { | |
_zgetclip_to_kill_ring || return | |
zle yank | |
} | |
zle -N zclip-yank _zgetclip_yank # uses SELECT | |
zle -N zclip-yank-from-clipboard _zgetclip_yank | |
zle -N zclip-yank-from-primary _zgetclip_yank | |
zle -N zclip-yank-from-secondary _zgetclip_yank | |
_zclip_from_region() { | |
local target=pc | |
case $WIDGET in | |
*-clipboard) | |
source=c | |
;; | |
*-primary) | |
source=p | |
;; | |
*-secondary) | |
source=q | |
;; | |
esac | |
zle copy-region-as-kill | |
zclip <<< $CUTBUFFER | |
} | |
zle -N zclip-copy _zclip_from_region # uses PRIMARY+CLIPBOARD | |
zle -N zclip-copy-to-clipboard _zclip_from_region | |
zle -N zclip-copy-to-primary_zclip_from_region | |
zle -N zclip-copy-to-secondary _zclip_from_region |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment