-
-
Save AlexCharlton/cc82001c407786f7c1f7 to your computer and use it in GitHub Desktop.
;;;; This script can be loaded during emacs initialization to automatically | |
;;;; send `kill-region' and `kill-ring-save' regions to your system clipboard. | |
;;;; The OSC 52 terminal escape sequence is used to transfer the selection from | |
;;;; emacs to the host terminal. | |
;;;; It is based off of the osc52.el copyright the Chromium OS authors, but | |
;;;; was modified to add support for tmux, graphical displays, and | |
;;;; multi-byte strings. | |
;;;; It works in hterm, xterm, and other terminal emulators which support the | |
;;;; sequence. | |
;;;; It also works under screen, via `osc52-select-text-dcs' and tmux via | |
;;;; `osc52-select-text-tmux', as long as the terminal supports OSC 52. | |
;;;; Call `osc52-set-cut-function' to activate. | |
(defcustom osc52-max-sequence 100000 | |
"Maximum length of the OSC 52 sequence. | |
The OSC 52 sequence requires a terminator byte. Some terminals will ignore or | |
mistreat a terminated sequence that is longer than a certain size, usually to | |
protect users from runaway sequences. | |
This variable allows you to tweak the maximum number of bytes that will be sent | |
using the OSC 52 sequence. | |
If you select a region larger than this size, it won't be copied to your system | |
clipboard. Since clipboard data is base 64 encoded, the actual number of | |
characters that can be copied is 1/3 of this value.") | |
(defcustom osc52-multiplexer 'tmux | |
"Select which terminal multiplexer should be used when creating OSC 52 sequences. Device control string escape sequences are only used when the value of the environment variable TERM starts with the string \"screen\". | |
If set to 'tmux, a tmux DCS escape sequence will be generated, otherwise a screen DCS will be used.") | |
(defun osc52-select-text (string &optional replace yank-handler) | |
"Copy STRING to the system clipboard using the OSC 52 escape sequence. | |
Set `interprogram-cut-function' to this when using a compatible terminal, and | |
your system clipboard will be updated whenever you copy a region of text in | |
emacs. | |
If the resulting OSC 52 sequence would be longer than | |
`osc52-max-sequence', then the STRING is not sent to the system | |
clipboard. | |
This function sends a raw OSC 52 sequence and will work on a bare terminal | |
emulators. It does not work on screen or tmux terminals, since they don't | |
natively support OSC 52." | |
(let ((b64-length (+ (* (length string) 3) 2))) | |
(if (<= b64-length osc52-max-sequence) | |
(send-string-to-terminal | |
(concat "\e]52;c;" | |
(base64-encode-string string t) | |
"\07")) | |
(message \"Selection too long to send to terminal %d\" b64-length) | |
(sit-for 2)))) | |
(defun osc52-select-text-dcs (string &optional replace yank-handler) | |
"Copy STRING to the system clipboard using the OSC 52 escape sequence, for | |
screen users. | |
Set `interprogram-cut-function' to this when using the screen program, and your | |
system clipboard will be updated whenever you copy a region of text in emacs. | |
If the resulting OSC 52 sequence would be longer than | |
`osc52-max-sequence', then the STRING is not sent to the system | |
clipboard. | |
This function wraps the OSC 52 in a Device Control String sequence. This causes | |
screen to pass the wrapped OSC 52 sequence along to the host termianl. This | |
function also chops long DCS sequences into multiple smaller ones to avoid | |
hitting screen's max DCS length." | |
(let ((b64-length (+ (* (length string) 3) 2))) | |
(if (<= b64-length osc52-max-sequence) | |
(send-string-to-terminal | |
(concat "\eP\e]52;c;" | |
(replace-regexp-in-string | |
"\n" "\e\\\\\eP" | |
(base64-encode-string (encode-coding-string string 'binary))) | |
"\07\e\\")) | |
(message "Selection too long to send to terminal %d" b64-length) | |
(sit-for 2)))) | |
(defun osc52-select-text-tmux (string &optional replace yank-handler) | |
"Copy STRING to the system clipboard using the OSC 52 escape sequence, for | |
tmux users. | |
Set `interprogram-cut-function' to this when using the screen program, and your | |
system clipboard will be updated whenever you copy a region of text in emacs. | |
If the resulting OSC 52 sequence would be longer than | |
`osc52-max-sequence', then the STRING is not sent to the system | |
clipboard. | |
This function wraps the OSC 52 in a Device Control String sequence. This causes | |
screen to pass the wrapped OSC 52 sequence along to the host termianl. This | |
function also chops long DCS sequences into multiple smaller ones to avoid | |
hitting screen's max DCS length." | |
(let ((b64-length (+ (* (length string) 3) 2))) | |
(if (<= b64-length osc52-max-sequence) | |
(send-string-to-terminal | |
(concat "\ePtmux;\e\e]52;c;" | |
(base64-encode-string (encode-coding-string string 'binary) | |
t) | |
"\a\e\\")) | |
(message "Selection too long to send to terminal %d" b64-length) | |
(sit-for 2)))) | |
(defvar osc52-cut-function) | |
(defun osc52-interprogram-cut-function (string &optional replace yank-handler) | |
(if (display-graphic-p) | |
(x-select-text string) | |
(funcall osc52-cut-function string))) | |
(defun osc52-set-cut-function () | |
"Initialize the `interprogram-cut-function' based on the value of | |
`display-graphic-p' and the TERM environment variable." | |
(interactive) | |
(setq osc52-cut-function | |
(if (string-match "^screen" (getenv "TERM")) | |
(if (equal osc52-multiplexer 'tmux) | |
'osc52-select-text-tmux | |
'osc52-select-text-dcs) | |
'osc52-select-text)) | |
(setq interprogram-cut-function 'osc52-interprogram-cut-function)) | |
(provide 'osc52e) |
Hi @AlexCharlton, as above I have made a modification to your code, but @jkohen proposed me to contribute to the upstream https://chromium.googlesource.com/apps/libapps/+/master/hterm/etc/osc52.el sending it as a patch.
I think my work is just a small fix and you have done the most of contribution, so it's the best sending patch by your name.
I'm happy if you can think about it. If you are too busy to do it I can send a patch instead so please let me know. I believe your code will help many people definitely.
Hi @mecab, I'm glad you found this useful. Please feel free to send the patch yourself, though -- I'm not concerned about attribution, and I don't think I will find the time to do so myself. Cheers!
Hi @alexchalton Thank you for reply and accepting it. I will write the patch soon.
Cool! It is awesome useful.
I forked and added some modification to
osc52-set-cut-function
which provides more stable terminal determination.It could be useful for people who include "tmux" in the
TERM
string.Also it provides the interactive function
osc52-send-region-to-clipboard
.See https://gist.github.com/mecab/49eabc1978fe3d6dedb3ca5674a16ece if you interested in.
Thanks!