From 84aa6e89336e7a61782b371ce7cbcf5fbf15ca21 Mon Sep 17 00:00:00 2001 From: Christian Nieves Date: Mon, 13 Feb 2023 12:31:47 -0600 Subject: [PATCH] OSC52 clipboard yanks --- scripts/scripts/yank | 49 +++++++++++++++++++++++++++++++++ tmux/.tmux.conf | 28 ++++++++++++++++--- vim/.vim/lua/config/lsp.lua | 30 +------------------- vim/.vim/lua/config/oscyank.lua | 3 ++ vim/.vim/lua/plugins.lua | 4 +++ vim/.vim/prefs/leader.vim | 26 +++++++++++++++-- vim/.vimrc | 24 ++++++++-------- 7 files changed, 117 insertions(+), 47 deletions(-) create mode 100755 scripts/scripts/yank create mode 100644 vim/.vim/lua/config/oscyank.lua diff --git a/scripts/scripts/yank b/scripts/scripts/yank new file mode 100755 index 0000000..ac03c10 --- /dev/null +++ b/scripts/scripts/yank @@ -0,0 +1,49 @@ +#!/bin/sh +# +# Usage: yank [FILE...] +# +# Copies the contents of the given files (or stdin, if no files are given) to +# the terminal that runs this program. If this program is run inside tmux(1), +# then it also copies the given contents into tmux's current clipboard buffer. +# If this program is run inside X11, then it also copies to the X11 clipboard. +# +# This is achieved by writing an OSC 52 escape sequence to the said terminal. +# The maximum length of an OSC 52 escape sequence is 100_000 bytes, of which +# 7 bytes are occupied by a "\033]52;c;" header, 1 byte by a "\a" footer, and +# 99_992 bytes by the base64-encoded result of 74_994 bytes of copyable text. +# +# In other words, this program can only copy up to 74_994 bytes of its input. +# However, in such cases, this program tries to bypass the input length limit +# by copying directly to the X11 clipboard if a $DISPLAY server is available; +# otherwise, it emits a warning (on stderr) about the number of bytes dropped. +# +# See http://en.wikipedia.org/wiki/Base64 for the 4*ceil(n/3) length formula. +# See http://sourceforge.net/p/tmux/mailman/message/32221257 for copy limits. +# See http://sourceforge.net/p/tmux/tmux-code/ci/a0295b4c2f6 for DCS in tmux. +# +# Written in 2014 by Suraj N. Kurapati +# Also documented at https://sunaku.github.io/tmux-yank-osc52.html + +input=$( cat "$@" ) +input() { printf %s "$input" ;} +known() { command -v "$1" >/dev/null ;} +maybe() { known "$1" && input | "$@" ;} +alive() { known "$1" && "$@" >/dev/null 2>&1 ;} + +# copy to tmux +test -n "$TMUX" && maybe tmux load-buffer - + +# copy via X11 +test -n "$DISPLAY" && alive xhost && { + maybe xsel -i -b || maybe xclip -sel c +} + +# copy via OSC 52 +printf_escape() { + esc=$1 + test -n "$TMUX" -o -z "${TERM##screen*}" && esc="\033Ptmux;\033$esc\033\\" + printf "$esc" +} +len=$( input | wc -c ) max=74994 +test $len -gt $max && echo "$0: input is $(( len - max )) bytes too long" >&2 +printf_escape "\033]52;c;$( input | head -c $max | base64 | tr -d '\r\n' )\a" diff --git a/tmux/.tmux.conf b/tmux/.tmux.conf index fdcbff6..4406be2 100644 --- a/tmux/.tmux.conf +++ b/tmux/.tmux.conf @@ -4,7 +4,7 @@ set-option -g update-environment "SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CO set -g prefix C-a bind C-a send-prefix -set -g mouse on +set -g mouse off set -g prefix ` bind-key ` send-prefix @@ -26,8 +26,17 @@ set -g pane-base-index 1 set-option -g base-index 1 set-window-option -g pane-base-index 1 -set -g default-terminal "screen-256color" -set -ga terminal-overrides ",xterm-256color*:Tc" # tell Tmux that outside terminal supports true color +# enable OSC 52 clipboard +set -s set-clipboard external + +# tmux-256color instead of screen-256color enables italics +set -g default-terminal "tmux-256color" + +# Tc enables true color +set -ag terminal-overrides ",*256col*:colors=256:Tc" +set -as terminal-features ',rxvt-unicode-256color:clipboard' +set -g allow-passthrough on + # set -g default-shell zsh # force a reload of the config file @@ -54,7 +63,18 @@ setw -g mode-keys vi # Setup 'v' to begin selection as in Vim bind-key -Tcopy-mode-vi 'v' send -X begin-selection -bind-key -Tcopy-mode-vi 'y' send -X copy-pipe-and-cancel "xclip -sel clip -i" + +# transfer copied text to attached terminal with yank +bind-key -T copy-mode-vi y send-keys -X copy-pipe 'yank > #{pane_tty}' + +# transfer copied text to attached terminal with yank +bind-key -T copy-mode-vi Y send-keys -X copy-pipe 'yank > #{pane_tty}' + +# transfer most-recently copied text to attached terminal with yank +bind-key -n M-y run-shell 'tmux save-buffer - | yank > #{pane_tty}' + +# transfer previously copied text (chosen from a menu) to attached terminal +bind-key -n M-Y choose-buffer 'run-shell "tmux save-buffer -b \"%%%\" - | yank > #{pane_tty}"' # Bind ']' to use pbpaste #bind ] run "pbpaste | tmux load-buffer - && tmux paste-buffer" diff --git a/vim/.vim/lua/config/lsp.lua b/vim/.vim/lua/config/lsp.lua index 1578650..131045f 100644 --- a/vim/.vim/lua/config/lsp.lua +++ b/vim/.vim/lua/config/lsp.lua @@ -9,7 +9,7 @@ lsp_status.register_progress() require("mason").setup() require("mason-lspconfig").setup({ - ensure_installed = { "sumneko_lua", "rust_analyzer" } + ensure_installed = { "lua_ls", "rust_analyzer" } }) local lspconfig = require("lspconfig") @@ -102,34 +102,6 @@ local runtime_path = vim.split(package.path, ";") table.insert(runtime_path, "lua/?.lua") table.insert(runtime_path, "lua/?/init.lua") -lspconfig.sumneko_lua.setup({ - capabilities = capabilities, - on_attach = on_attach, - settings = { - Lua = { - runtime = { - -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim) - version = "LuaJIT", - -- Setup your lua path - path = runtime_path, - }, - diagnostics = { - -- Get the language server to recognize the `vim` global - globals = { "vim" }, - }, - workspace = { - -- Make the server aware of Neovim runtime files - library = vim.api.nvim_get_runtime_file("", true), - }, - -- Do not send telemetry data containing a randomized but unique identifier - telemetry = { - enable = false, - }, - }, - }, -}) - - local lspkind = require("lspkind") lspkind.init() local cmp = require("cmp") diff --git a/vim/.vim/lua/config/oscyank.lua b/vim/.vim/lua/config/oscyank.lua new file mode 100644 index 0000000..8f0255d --- /dev/null +++ b/vim/.vim/lua/config/oscyank.lua @@ -0,0 +1,3 @@ +local map = require("utils").map +map("n", "y", ":OSCYank", opts) +map("v", "y", ":OSCYank", opts) diff --git a/vim/.vim/lua/plugins.lua b/vim/.vim/lua/plugins.lua index 6a4e54a..c46f979 100644 --- a/vim/.vim/lua/plugins.lua +++ b/vim/.vim/lua/plugins.lua @@ -222,6 +222,10 @@ require('packer').startup(function(use) 'tmux-plugins/vim-tmux-focus-events', 'skywind3000/asyncrun.vim', } + use { + 'ojroques/vim-oscyank', + config = [[ require("config.oscyank") ]] + } -- mine use { diff --git a/vim/.vim/prefs/leader.vim b/vim/.vim/prefs/leader.vim index a8608fa..ca10733 100644 --- a/vim/.vim/prefs/leader.vim +++ b/vim/.vim/prefs/leader.vim @@ -29,8 +29,8 @@ vmap v c"+p imap v "+pa " Copy to OS clipboard -vnoremap y "yy :call system('xclip', @y) -map y "yy :call system('xclip', @y) +" vnoremap y "yy :call system('xclip', @y) +" map y "yy :call system('xclip', @y) " --------- WINDOW/PANE MAPPINGS --------- map wr r @@ -123,3 +123,25 @@ function! SynStack() endfunc nnoremap s :SaveSession + +" copy to attached terminal using the yank(1) script: +" https://github.com/sunaku/home/blob/master/bin/yank +function! Yank(text) abort + let escape = system('yank', a:text) + if v:shell_error + echoerr escape + else + call writefile([escape], '/dev/tty', 'b') + endif +endfunction +noremap y y:call Yank(@0) + +" automatically run yank(1) whenever yanking in Vim +" (this snippet was contributed by Larry Sanderson) +function! CopyYank() abort + call Yank(join(v:event.regcontents, "\n")) +endfunction + +" autocmd TextYankPost * call CopyYank() +noremap y call CopyYank() +vnoremap y call CopyYank() diff --git a/vim/.vimrc b/vim/.vimrc index 66c3024..6d63f38 100644 --- a/vim/.vimrc +++ b/vim/.vimrc @@ -60,18 +60,18 @@ set splitbelow " Puts new split windows to the bottom of the current set scrolljump=5 " Line to scroll when cursor leaves screen set scrolloff=3 " Minumum lines to keep above and below cursor -let g:clipboard = #{ - \ name: 'xsel', - \ copy: { - \ '+': ['xclip', '--nodetach', '-i', '-b'], - \ '*': ['xclip', '--nodetach', '-i', '-p'], - \ }, - \ paste: { - \ '+': ['xclip', '-o', '-b'], - \ '*': ['xclip', '-o', '-p'], - \ }, - \ cache_enabled: 1, - \ } +" let g:clipboard = #{ +" \ name: 'xsel', +" \ copy: { +" \ '+': ['xclip', '--nodetach', '-i', '-b'], +" \ '*': ['xclip', '--nodetach', '-i', '-p'], +" \ }, +" \ paste: { +" \ '+': ['xclip', '-o', '-b'], +" \ '*': ['xclip', '-o', '-p'], +" \ }, +" \ cache_enabled: 1, +" \ } set shortmess=A set shortmess+=O set modifiable