ibhagwan / smartyank.nvim

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Question] remote tmux yank

CharlesChiuGit opened this issue · comments

To my understanding, when using this plugin on a remote tmux session(ssh first then run tmux on remote machine), it will only put the copyed text to tmux buffer and will not send osc52 sequence to local clipboard. But I'm confused about something:

  1. When I'm yank text in nvim on a remote tmux session, messages shows [smartyank] XXX chars copied using OSC52 (XXX bytes). So the priority of ssh is higher than tmux? But the yanked texts are only in tmux buffer but not local clipboard.
  2. As above, when I'm open nvim on a remote tmux session, :checkhealth shows Clipboard is tmux, maybe the yanked tests are hijacked by nvim's clipboard tool?
    image

When yanking in nvim without tmux on remote machine, the plugin works fine and local clipboard does capture the yanked texts.

  1. How can I modifiled the behavior of this plugin to use also osc52 when I'm in remote tmux session?

As a reference, here's my tmux.conf.

My smarkyank config:

require("smartyank").setup({
	highlight = {
		enabled = false, -- highlight yanked text
		higroup = "IncSearch", -- highlight group of yanked text
		timeout = 2000, -- timeout for clearing the highlight
	},
	clipboard = {
		enabled = true,
	},
	tmux = {
		enabled = true,
		-- remove `-w` to disable copy to host client's clipboard
		cmd = { "tmux", "set-buffer", "-w" },
	},
	osc52 = {
		enabled = true,
		ssh_only = true, -- false to OSC52 yank also in local sessions
		silent = false, -- true to disable the "n chars copied" echo
		echo_hl = "Directory", -- highlight group of the OSC52 echo message
	},
})
  1. tmux and ssh are unrelated operations with no priority between then, if the plug-in detects the existence of $SSH_CONNECTION in the env OSC52 yank will be performed.

  2. I’m not sure why the copy isn’t forwarded to your local host I looked and your config and saw you have a clipboard option which should enable exactly that set -g set-clipboard on, if you see the copied… message then the sequence was sent, why it’s not forwarded to your local machine needs further investigation.

This this sequence (exactly what the plug-in sends) in the shell and see if it works and you get a local copy:

printf "\033]52;c;$(printf "%s" "hello" | base64)\a"

Also try this sequence, if it works we can adjust the plug-in to use this instead:

printf "\033Ptmux;\033\033]52;c;$(printf "%s" "world" | base64)\a\033\\"

hmm, the result is very interesting...
Both works outside of tmux, but when inside of remote tmux session, both still don't work....

Btw, i'm using tmux 3.3a from github release, will that make a difference?

Btw, i'm using tmux 3.3a from github release, will that make a difference?

I'm using the same version, I would suspect that's not the case, maybe something in your config, you can try mine:

set -g default-terminal "screen-256color"

# enable full colors if TERM outside is xterm-256color
# this is required for using nvim's :set termguicolors
set-option -sa terminal-overrides ',xterm-256color:RGB'
set-option -sa terminal-overrides ',screen-256color:RGB'

# enable OSC 52 clipboard
# https://medium.freecodecamp.org/tmux-in-practice-integration-with-system-clipboard-bcd72c62ff7b
# test by running over ssh:
#   printf "\033]52;c;$(printf "%s" "hello" | base64)\a"
# https://github.com/tmux/tmux/wiki/Clipboard
set -g set-clipboard on

# set shell
set -g default-shell /bin/zsh

# set max history
set -g history-limit 100000

# Custom modifier key
set -g prefix C-Space
unbind-key C-b
bind-key C-Space send-prefix

# set escape time (time to wait after pressing Esc)
# to 10ms, this precents nvim delay with pressing Esc
# https://github.com/neovim/neovim/wiki/FAQ
set -sg escape-time 10

# vim autoread warning in ':checkhealth'
set-option -g focus-events on

# To copy, left click and drag to highlight text in yellow, 
# once you release left click yellow text will disappear and
# will automatically be available in clibboard

# without this mouse scroll will send up/down arrows
# instead of scrolling the terminal history
set -g mouse on
bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
bind -n WheelDownPane select-pane -t= \; send-keys -M
bind -n C-WheelUpPane select-pane -t= \; copy-mode -e \; send-keys -M
bind -T copy-mode-vi    C-WheelUpPane   send-keys -X halfpage-up
bind -T copy-mode-vi    C-WheelDownPane send-keys -X halfpage-down
bind -T copy-mode-emacs C-WheelUpPane   send-keys -X halfpage-up
bind -T copy-mode-emacs C-WheelDownPane send-keys -X halfpage-down

# Disble mouse scroll (annoying as hell with mac touchpad)
# verify with `tmux list-keys | grep -i wheel`
bind-key -T root WheelUpPane    send-keys "" # or ^Y
bind-key -T root WheelDownPane  send-keys "" # or ^E


# vi-like keybindings for pane navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# 'n' is default bind 'next-window'
# bind 'b' to 'previous-window'
# bind 't' to 'new-window'
unbind t
bind t new-window
bind b previous-window

# easy pane resize
bind-key J resize-pane -D
bind-key K resize-pane -U
bind-key H resize-pane -L
bind-key L resize-pane -R
bind -r left resize-pane -L 8
bind -r right resize-pane -R 8
bind -r up resize-pane -U 5
bind -r down resize-pane -D 5

# pane splits
# | - veritcal split
# " - horizontal split
bind | split-window -h
bind '"' split-window -v
# uncomment to split at current working directory
#bind | split-window -h -c "#{pane_current_path}"
#bind '"' split-window -v -c "#{pane_current_path}"

# vi-like keybindings in copy mode
setw -g mode-keys vi

# 'p' to paste buffer
# 'v' to enter copy-mode:
#   'v' to start visual mode
#   'y' to yank text
unbind p
bind p paste-buffer
bind v copy-mode
bind-key -T copy-mode-vi 'v' send -X begin-selection
bind-key -T copy-mode-vi 'y' send -X copy-selection

# 'Enter' as an alternative to 'q' to exit copy-mode-vi
unbind -T copy-mode-vi Enter
 bind-key -T copy-mode-vi Enter send-keys -X cancel
# bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "xclip -selection c"

# disable "release mouse drag to copy and exit copy-mode"
# ref: https://github.com/tmux/tmux/issues/140
unbind-key -T copy-mode-vi MouseDragEnd1Pane
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe "xclip -selection c"

# source our config the file with Prefix r
bind r source-file ~/.config/tmux/tmux.conf \; display "Reloaded `tmux.conf`"

# zenburn theme
setw -g clock-mode-colour colour117
setw -g mode-style fg=colour117,bg=colour238,bold
setw -g status-style bg=colour235,fg=colour248
setw -g message-style fg=colour117,bg=colour235,bold
setw -g window-status-style fg=colour68,bg=colour235
setw -g window-status-current-style fg=colour223,bg=colour237,bold

# fancy status line: user@host, date, time
set-option -g status-right "#(whoami)@#(uname -n) #[fg=colour187,bold]%a %Y-%m-%d %H:%M"
set -g status-right-length 50
set -g status-left-length 20

# tmux plugin manager:
#   <space-I> to install plugins
#   <space-U> to update plugins
#   <space-alt-U> to remove unlisted plugins
# if "test ! -d $XDG_CONFIG_HOME/tmux/plugins/tpm"
if-shell "[ ! -d $XDG_CONFIG_HOME/tmux/plugins/tpm ]" \
    "run-shell 'git clone https://github.com/tmux-plugins/tpm $XDG_CONFIG_HOME/tmux/plugins/tpm'"

set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'laktak/extrakto'

set -g @extrakto_split_direction v
set -g @extrakto_split_size 15
set -g @extrakto_copy_key "ctrl-y"      # use tab to copy to clipboard
set -g @extrakto_insert_key "enter"  # use enter to insert selection
set -g @extrakto_fzf_layout "reverse"

# set -g @plugin 'seebi/tmux-colors-solarized'
# set -g @colors-solarized 'dark'

run -b '$XDG_CONFIG_HOME/tmux/plugins/tpm/tpm'

# Install plugins if needed
if "test ! -d $XDG_CONFIG_HOME/tmux/plugins/extrakto" \
    "run-shell '$XDG_CONFIG_HOME/tmux/plugins/tpm/bin/install_plugins'"

I found the reason lol, osc52 is disabled by default in 3.3a!!!
tmux/tmux#3218 (comment)

Once add set -g allow-passthrough on in tmux.conf, everything just works...

Thanks for your reply! Will take a look at your tmux config.

@ibhagwan Only this line works after set -g allow-passthrough on

printf "\033Ptmux;\033\033]52;c;$(printf "%s" "world" | base64)\a\033\\"

So I think it does need to be updated.

Great find @CharlesChiuGit! I wonder how mine works as I'm using the same version and don't have this line enabled...

Hey @ibhagwan, I tried your tmux.conf, the problem is still pretty much the same, osc52 and smarkyank will work outside of tmux.
But when in remote tmux session, only after I added set -g allow-passthrough on or setw -g allow-passthrough on,

printf "\033Ptmux;\033\033]52;c;$(printf "%s" "world" | base64)\a\033\\"

will work. Current version of smarkyank still don't work in remote tmux session.

The only thing I changed in your tmux-conf is remove:

# set shell
set -g default-shell /bin/zsh

and add:

bind R source-file ~/.config/tmux/tmux.conf \; display-message " Config reloaded!"
setw -g allow-passthrough on

BTW, I'm using windows terminal, it should support osc52.

Did use any extra tools to on remote machine to manage copyed texts?

I also tried compiling tmux from source, which is version next-3.4 and set clipboard config in neovim like this(since nvim can't recognize the compiled version):
image

Result is still the same, yanked texts still goes to tmux-buffer. Maybe it's the OS' issue? I'm using Ubuntu on remote and Windows on local.

Wow you went to great lengths for this issue, I’m not using any special tools in the remote machine, I didn’t test it in the terminal directly though, I was lazy and just tested a neovim yank inside tmux after using ssh to connect to the machine.

Important to note I don’t use nested tmux, if I know I’m going to tmux attach on the remote machine I will detach locally so that I have only one tmux session which is the remote one.

Current version of smarkyank still don't work in remote tmux session.

Does only the new escape sequence work in a remote session? If so I can add it to Smartyank, I’m just not sure under what exact conditions to use it, I’ll do some digging on my end too.

Important to note I don’t use nested tmux, if I know I’m going to tmux attach on the remote machine I will detach locally so that I have only one tmux session which is the remote one.

I never use nested tmux also.

Does only the new escape sequence work in a remote session? If so I can add it to Smartyank.

Both printf "\033]52;c;$(printf "%s" "hello" | base64)\a" and printf "\033Ptmux;\033\033]52;c;$(printf "%s" "world" | base64)\a\033\\" works in bare remote session(outsilde tmux) but only

printf "\033Ptmux;\033\033]52;c;$(printf "%s" "world" | base64)\a\033\\"

works when typing it directly in terminal inside tmux.

I’m just not sure under what exact conditions to use it, I’ll do some digging on my end too.

Since nvim has provide a way to detect env variables, we can just add os.getenv("TMUX") to check if we're inside of tmux or not. I'll do a PR later.

Since nvim has provide a way to detect env variables, we can just add os.getenv("TMUX") to check if we're inside of tmux or not. I'll do a PR later.

Yes, it’s pretty easy to check, you can use vim.env.TMUXinstead of os.getenv, however, I’m not sure if we should blanket exchange the escape sequence to always use the new one under tmux, for example, I use blink.sh terminal on the iPad and the current escape sequence works great over a remote tmux, the new one doesn’t seem to work so I’d avoid replacing the escape sequence until we can determine the exact conditions that require it.

vim.env.TMUX is a wrapper of os.getenv and os.setenv, so I personally like to use os.getenv more, in case I accidently set sth i don't intended to.

And sure, we can create a new branch first to test things out! Would u mind creating a branch first? So i can push to that testing branch.

Also, what's your stylua.toml?
Mine as a ref:

column_width = 120
line_endings = "Unix"
indent_type = "Tabs"
indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"

Here are my findings for a remote tmux session with the latest tmux package from the void linux repositories, tmux version is 3.3a:

If you're reloading your tmux config it's important to set set -g allow-passthrough off before reloading, if you just comment the line it will keep the passthrough seting on

what OSC52 escape Ptmux escape
alacritty - no tmux yes yes
alacritty - tmux no passthrough yes NO
alacritty - tmux with passthrough yes yes
kitty - no tmux yes NO
kitty - tmux no passthrough yes NO
kitty - tmux with passthrough yes yes
blink.sh - no tmux yes yes
blink.sh - tmux no passthrough yes NO
blink.sh - tmux with passthrough yes yes

As you can see, blanket changing the escape sequence to the Ptmux one will become an issue to users that don't have the allow-passthrough setting turned on. I'm still not sure why on your system the regular OSC52 sequence fails to passthrough to the local machine while in my case all 3 terminals seem to work perfectly fine.

Perhaps it's best to just give a config option which osc52 escape setting to use so users facing your same issue can turn it on?

I'm still unsure which case is the more common, mine or yours, if it turns out that your issue is more common we can change the default escape sequence to tmux when $TMUX exists.

hmmm, interesting...
Then yeah, you're right about giving a user config option. Maybe that will just be more easy to develop!

Also, what's your stylua.toml? Mine as a ref:

column_width = 120
line_endings = "Unix"
indent_type = "Tabs"
indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"

don't use any, probably should, still can't decide between stylua (too opinionated?) and the sumneko lua formatter (based on emmylua).

4886e3e updated to this commit and test quickly using:

With the below osc52 happens all the time and is not limited to ssh sessions

:lua require'smartyank'.setup({osc52={ssh_only=false,escseq='tmux'}})

I opted against limiting the new sequence to the existence of $TMUX since it doesn't carry over when you su - so this way the new sequence can be forced.

Thanks for your fast dev! Here's a little bug with the new config when showing messages.
image

When turn off osc52={silent = true}, the screen seems a bit weird...
image

Thanks very very much for your patience of helping me debug, but unfortunately local clipboard still got nothing with the new config...
I think I'll try to find another way to yank text in nvim inside remote tmux session. Thanks again.

When turn off osc52={silent = true}, the screen seems a bit weird...

I'm not sure if the issue comes from the plugin, the only thing silent does is not output the message, perhaps showing the message just hides this mess which I suspect is coming from the combination of your windows term and neovim?

but unfortunately local clipboard still got nothing with the new config...

I wonder why, if the printf is working in the shell it should also work in neovim, what happens if you try (the second variant uses the tmux escape sequence):

:lua require'smartyank'.osc52printf("test")
:lua require'smartyank'.osc52printf("test", "tmux")

Ys, it seems like it's casting to a new nvim buffer and jump back to the original buffer.

Perhaps your remote luaJit doesn't handle \x1b properly? can you download the repo locally change it to \033 instead and see if it works?

I'm talking about these lines:

Can also try \e instead of \x1b

local osc52str = type == 'tmux'
and string.format([[\x1bPtmux;\x1b\x1b]52;c;%s\x07\x1b\\]], base64)
or string.format("\x1b]52;c;%s\x07", base64)

but unfortunately local clipboard still got nothing with the new config...

I wonder why, if the printf is working in the shell it should also work in neovim, what happens if you try (the second variant uses the tmux escape sequence):

:lua require'smartyank'.osc52printf("test")
:lua require'smartyank'.osc52printf("test", "tmux")

Inside tmux, both not working.
Outside tmux, :lua require'smartyank'.osc52printf("test") works

Ys, it seems like it's casting to a new nvim buffer and jump back to the original buffer.

Maybe this is the issue?

local bytes = vim.fn.chansend(vim.v.stderr, osc52str)

Need to do some digging to see what can be used instead of chandsend

Perhaps your remote luaJit doesn't handle \x1b properly? can you download the repo locally change it to \033 instead and see if it works?

I'm talking about these lines:

Can also try \e instead of \x1b

local osc52str = type == 'tmux'
and string.format([[\x1bPtmux;\x1b\x1b]52;c;%s\x07\x1b\\]], base64)
or string.format("\x1b]52;c;%s\x07", base64)

U mean like this right?
image
This doesn't work too.

If use \e instead of \x1b:
image

Invalid escape sequence

That's because the 2nd line is surrounded by ", you need to "lua escape" the\ or use double brackets:

string.format("\\e...")
-- or
string.format([[\e...]])

Got it, it pass now, but still no luck.

Sorry, I delete the comment b/c after some tests I think maybe it's not relevant.

It wasn't relevant, the bracketed string was messing up the escape sequence, update to 764cf8e and try now?

omggggggggggggg! it works! let me test a bit more...

omggggggggggggg! it works! let me test a bit more...

Make sure to update to this ed913f4, I force update as it was missing one \ at the end.

ys!!!!! Everything works like a charm smoothly! I can't thank u enough! 🎉🎉🎉🎉🎉🎉

For those who saw this issue, PLEASE DO remember to add this line in your tmux.conf if your tmux is 3.3a or higher

setw -g allow-passthrough on

At least for me, nothing works without this line.

Huge s/o to @ibhagwan for creating this amazing plugin and help me debug along the way!
I can finally sleep well now lol.

Ty @CharlesChiuGit, happy we got to the bottom of it!

Btw, this plug-in was a mere afterthought of an existing autocmd I had in my config, the plug-in I’m more proud of is fzf-lua, if you’re a fan of fzf it has a lot to offer :)

Btw, I deleted the comments of us wrongfully suspecting another plug-in :)

Ty @CharlesChiuGit, happy we got to the bottom of it!

Btw, this plug-in was a mere afterthought of an existing autocmd I had in my config, the plug-in I’m more proud of is fzf-lua, if you’re a fan of fzf it has a lot to offer :)

sure, actually i'm checking it now lol.

don't use any, probably should, still can't decide between stylua (too opinionated?) and the sumneko lua formatter (based on emmylua).

I like stylua for few reasons:

  1. I use null-ls.nvim to manage all my linters and formatters, and I only use lsps for diagnostics. So when it comes to code style, I would prefer stylua.
  2. stylua.toml is a easy to share and it's project-based, which is gd for open source projects.
  3. Github CI can pass in stylua.toml easily. Here's my style_check.yml.

I'm not sure about if there's a CI for sumneko lua formatter or how to do a project-based setting of it.

don't use any, probably should, still can't decide between stylua (too opinionated?) and the sumneko lua formatter (based on emmylua).

I like stylua for few reasons:

  1. I use null-ls.nvim to manage all my linters and formatters, and I only use lsps for diagnostics. So when it comes to code style, I would prefer stylua.
  2. stylua.toml is a easy to share and it's project-based, which is gd for open source projects.
  3. Github CI can pass in stylua.toml easily. Here's my style_check.yml.

I'm not sure about if there's a CI for sumneko lua formatter or how to do a project-based setting of it.

Ty for the suggestions @CharlesChiuGit!

I like a bit more control over the formatting, I also liked the resulting format of sumneko_lua better, the lua formatting integration (which is farily recent) seemed to in a great state and had lots of improvemtns since its release around April.

Although I liked it I never used null-ls for formatting so if I prefer to avoid extra dependencies where possible, I'm now testing it for both fzf-lua and my personal config, also enabled style checking so I get format warnings from the LSP server as I go along, really like it so far, here's the relevant commit if you wannt test .luarc.json|.editorconfig yourself:
ibhagwan/fzf-lua@0c6e614.

If all goes well I will merge it to main in the upcoming days and do the same for this project as well, thanks again for pushing me to do the right thing :-)

Enabled now for this project 78de01a

Wow, that's some quick move! Sorry, haven't got time to test it.