neovim-qt icon indicating copy to clipboard operation
neovim-qt copied to clipboard

Integrate the clipboard provider into Neovim-Qt

Open xelra opened this issue 8 years ago • 41 comments

We talked about this some time ago on IRC, but I felt that it might be best to put the feature request down here.

I'm using Neovim-Qt mostly to connect to remote Neovim sessions over SSH. One of my initial motivations to do so was because I thought that would solve the clipboard problem. Unfortunately the clipboard is still handled by the remote Neovim session.

It would be great if the + and * registers would point to the local system clipboard, the one running Neovim-Qt.

Thank you very much for considering.

xelra avatar Jun 22 '17 14:06 xelra

Waiting on https://github.com/neovim/neovim/pull/6030 https://github.com/neovim/neovim/issues/6029.

If possible implement the provider in the shim.

equalsraf avatar Jun 23 '17 09:06 equalsraf

Implemented the feature in neovim!

Shougo avatar Jun 28 '17 07:06 Shougo

Hi @equalsraf

When will the tb-clipboard branch merge into master branch?

skt041959 avatar Nov 01 '18 03:11 skt041959

@skt041959 as it is it wont be merged. Ideally some kind soul (or me if time allows it) would add support upstream to override the clipboard provider using a function instead of using a custom executable.

equalsraf avatar Nov 01 '18 18:11 equalsraf

Moving on this after pushing some bits upstream - now in https://github.com/equalsraf/neovim-qt/pull/479

equalsraf avatar Dec 03 '18 20:12 equalsraf

FYI #479 has been merged.It is NOT enabled by default. You need to call GuiClipboard to enable it

call GuiClipboard()

This essentially sets g:clipboard.

I plan to tag a new release with this so everyone can test it. Keep in mind this requires the master branch from nvim (0.3.2)

equalsraf avatar Dec 08 '18 12:12 equalsraf

Dont know if anyone has been using or following this. So here is a quick update has a note for me to follow later on.

There are a couple of problems with this right now

  • [ ] neovim caches provider availability (search for CHECK_PROVIDER in eval.c) which means that if GuiClipboard() is called too late (TM) then attempting to access the clipboard always with an error about no clipboard being available, even if checkHealth says otherwise.
  • [ ] neovim-qt sets the channel information about the clipboard too late, meaning that calling GuiClipboard in ginit.vim ALWAYS fails to setup the clipboard

The second part is already in #498. It is still unclear to me if the first part can or should be addressed in the shim.

TLDR; :man_facepalming:

equalsraf avatar Jan 07 '19 23:01 equalsraf

I use this and it works great except that every once in awhile it doesn't initialize properly and I have to restart neovim until it does, I'm assuming for the reasons you mention

svermeulen avatar Jan 30 '19 06:01 svermeulen

I've also been trying to use this but I can't seem to make it work when connecting to a remote neovim using nvim-qt --server. Here the series I command run:

# on server foo
ky@foo $ nvim --listen foo:7777 --headless
# on local machine bar
ky@bar $ nvim-qt --server foo:7777
# in nvim-qt
: call GuiClipboard()

When running :checkhealth after calling GuiClipboard, neovim report that it found a custom clipboard provider. I can use the + and * register but unfortunately, they don't affect my clipboard on my local machine. Did I miss something? @svermeulen did you manage to make it work using a remote neovim?

Finally, when nvim-qt spawns its own neovim on my local machine, calling GuiClipboard works as expected.

Using neovim 3.4 and latest neovim-qt from master branch.

kwon-young avatar Jan 30 '19 09:01 kwon-young

I use this and it works great except that every once in awhile it doesn't initialize properly and I have to restart neovim until it does, I'm assuming for the reasons you mention

Precisely. Neovim caches the clipboard setup, so if you come in too late it does not work. This happens almost every time with remote instances (to my great frustration since i work mostly with a remote instance).

@kwon-young you can try to work around it by moving the shim plugin loading to be as early as possible and immediately call GuiClipboard().

equalsraf avatar Jan 31 '19 08:01 equalsraf

@equalsraf would it help if Nvim set up a dictwatcheradd() watcher on g:clipboard, so that let g:clipboard = ... reloads the clipboard provider?

justinmk avatar Jan 31 '19 13:01 justinmk

Nope. I think the real issue is that has_clipboard gets cached in eval.c.

checkhealth actually reports ok for the provider, but any call to grab data from it via getreg prints No provider: Try checkhealth... despite g:clipboard being set.

Calling the provider manually via g:clipboard['paste']['*']() actually works.

I need to sit down for a couple of days to try and figure a way to fix that without breaking other stuff.

equalsraf avatar Jan 31 '19 21:01 equalsraf

https://gist.github.com/equalsraf/e8e50a9d503322b7cf52c43c7685e401

equalsraf avatar Feb 06 '19 01:02 equalsraf

Can we enable this by default?

krishnakumarg1984 avatar Feb 11 '19 10:02 krishnakumarg1984

Can we enable this by default?

hi @krishnakumarg1984, good question, how is this feature working for you so far?

equalsraf avatar Feb 11 '19 21:02 equalsraf

I didn't face any reliability issues when copying from remote servers and seems stable enough for me. Is there some automated testing possible to thoroughly test this feature before deciding to enable by default?

krishnakumarg1984 avatar Feb 11 '19 21:02 krishnakumarg1984

I didn't face any reliability issues when copying from remote servers

Strange, remote servers are precisely the case we are still struggling with. I usually dont get a working clipboard.

.> Is there some automated testing possible to thoroughly test this feature

The only test at the moment is this but it does not test for remote instances.

equalsraf avatar Feb 12 '19 09:02 equalsraf

I have tried to get GuiClipboard working with a windows instance of neovim-qt and a linux instance of neovim without any success. I am using both the latest rev of neovim-qt, the shim plugin and neovim (I have tried both with and without the patch in your gist). I have tried calling GuiClippboard() both in gInit and after I had attached to my session. No error messages are displayed in any case. Would like further input on the matter, I could be missing something here.

Kraust avatar Feb 12 '19 11:02 Kraust

hi @Kraust

It is very strange that you see no errors. It seems more likely that the gui clipboard is not being activated. Can you quickly check a couple of things?

  • does :checkhealth complain about your clipboard
  • echo &clipboard i.e. is your clipboard set to unammed or unnamedplust? This needs to be set to work with regular yank/paste.
  • if you copy something into the clipboard and them call :echo getreg('+') do you get its contents
  • what about :echo g:clipboard['paste']['+']() (GuiClipboard must be called before this)

equalsraf avatar Feb 12 '19 21:02 equalsraf

First time, with call GuiClipboard() in my ginit.vim:

:checkhealth

health#provider#check
========================================================================
## Clipboard (optional)
  - OK: Clipboard tool found: custom

:echo &clipboard

unnamedplus

(I have set clipboard+=unnamedplus in my vimrc)

:echo getreg('+')

clipboard: No provider. Try ":checkhealth" or "h clipboard"
<and the contents of what I yanked previously>

Note: I re-ran :checkhealth here and still got the same as above.

(I did a call GuiClipboard() here as well)

:echo g:clipboard['paste']['+']()

I get the contents of my Windows clipboard and not the contents of my Linux one.

Note, to further add, if I am running an xserver on windows (e.g. Xming) I can get my clipboard via x11 forwarding only if I have a terminal session up (which is what you'd expect). I am not doing that in my above testing.


Second time without call GuiClipboard() in my ginit.vim

health#provider#check
========================================================================
## Clipboard (optional)
  - WARNING: No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.
    - ADVICE:
      - :help |clipboard|

:echo &clipboard
unnamedplus
 :echo getreg('+')
clipboard: No provider. Try ":checkhealth" or "h clipboard"
<and the contents of what I yanked previously>
call GuiClipboard()
health#provider#check
========================================================================
## Clipboard (optional)
  - OK: Clipboard tool found: custom
:echo g:clipboard['paste']['+']()
<the contents of what I currently have in my windows clipboard>

Here if I yank something again, I still get the same error in :echo getreg('+') and it does not get sent to my windows clipboard.

Kraust avatar Feb 12 '19 22:02 Kraust

Yeah that is consistent with what we are seeing here

  • the internals are actually working, that is why g:clipboard['paste']['+']() returns the correct clipboard contents
  • checkhealth checks directly with g:clipboard so it states that everything is ok (as long as GuilClipboard was called)
  • getreg is the authoritative source and that always fails, which is our issue. It is strange that you dont get an error when pasting though

You said you were trying using the patch from the gist. How are you using it? You should follow a call to GuiClipboard() with call reloadprovider('clipboard') which should return true.

equalsraf avatar Feb 13 '19 00:02 equalsraf

👍 That was what I was missing, I wasn't calling reloadprovider directly. With that step added I have full control over my clipboard now.

Kraust avatar Feb 13 '19 00:02 Kraust

So... just to understand, "+y and "+p don't work?

dakom avatar Feb 13 '19 12:02 dakom

@dakom both the plus and star register will not work if GuilClipboard was called.

equalsraf avatar Feb 13 '19 21:02 equalsraf

I'm not familiar with that function... I see it mentioned above, but is there a way to get yank/paste to work with the clipboard in windows?

dakom avatar Feb 13 '19 21:02 dakom

@dakom the clipboard should already work in windows. This issue is about the case when using the local clipboard with a remote instance of neovim - which users enable using that function.

If you are having issues in general with the clipboard you can open another issue. But if it is not working it is likely some issue with neovim, since it should be working out of the box.

equalsraf avatar Feb 13 '19 22:02 equalsraf

ugh was a silly mistake on my part ;) nm

dakom avatar Feb 14 '19 08:02 dakom

ugh was a silly mistake on my part ;) nm

No worries I'd rather have a silly problem than a hard bug.

equalsraf avatar Feb 14 '19 20:02 equalsraf

Very simple workaround. I'm using remote nvim.

copy /usr/share/nvim/runtime/autoload/provider/clipboard.vim
to ~/.your-custom-runtime/nvim/autoload/provider/clipboard.vim

and modify function! s:clipboard.get(reg) abort

function! s:clipboard.get(reg) abort
  if type(s:paste[a:reg]) == v:t_func
    return s:paste[a:reg]()
  elseif s:selections[a:reg].owner > 0
    return s:selections[a:reg].data
  end
  if g:clipboard['name'] == 'custom'
    return g:clipboard['paste']['+']()
  end
  return s:try_cmd(s:paste[a:reg])
endfunction

so I just added

  if g:clipboard['name'] == 'custom'
    return g:clipboard['paste']['+']()
  end

@equalsraf Thank you for Neovim-Qt

ezh avatar Feb 17 '19 21:02 ezh

 diff -Naur clipboard.vim.orig clipboard.vim
--- clipboard.vim.orig  2019-01-04 22:05:23.000000000 +0300
+++ clipboard.vim       2019-02-18 01:01:21.892554959 +0300
@@ -133,6 +133,9 @@
   elseif s:selections[a:reg].owner > 0
     return s:selections[a:reg].data
   end
+  if g:clipboard['name'] == 'custom'
+    return g:clipboard['paste'][a:reg]()
+  end
   return s:try_cmd(s:paste[a:reg])
 endfunction

@@ -151,6 +154,9 @@
   end

   if s:cache_enabled == 0
+    if g:clipboard['name'] == 'custom'
+      return g:clipboard['copy'][a:reg](a:lines)
+    end
     call s:try_cmd(s:copy[a:reg], a:lines)
     return 0
   end

ezh avatar Feb 17 '19 22:02 ezh

@dakom the clipboard should already work in windows. This issue is about the case when using the local clipboard with a remote instance of neovim - which users enable using that function.

@equalsraf Just want to mention that I'm on windows and I suffer from what I assume is this issue a lot. Often, after nvim-qt starts up, the + register will not work as expected. Copying from outside nvim-qt and the attempting to paste inside nvim-qt does not use the copied value.

When this issue occurs, the + register actually doesn't even get displayed when running :reg. So what I have been doing is, every time I start nvim-qt, I run :reg and if I don't see the + register I keep restarting nvim-qt until it displays there (and can sometimes take as many as 4 attempts for it to work)

I can reproduce this with gvimrc.vim:

call GuiClipboard()

And init.vim:

set clipboard+=unnamedplus

With just these settings, I can start nvim-qt and randomly find that the + register is not displayed in :reg.

Edit: I should also mention that I want to use this feature because the default (win32yank) is very flaky and causes other (worse) issues for me

Edit2: Noticed a couple other things when this issue occurs. If I execute echo getreg('+') it prints clipboard: no provider. Try ":checkhealth" or ":h clipboard".. Running :checkhealth reports no errors and says OK: clipboard tool found: custom

svermeulen avatar Feb 18 '19 21:02 svermeulen

Just want to mention that I was able to resolve this for myself by doing the following:

  • Building neovim (master) manually and including @equalsraf's patch to add the reloadprovider method
  • Downloading the most recent build of nvim-qt from appveyor and pasting it over top of my custom neovim build
  • Including call reloadprovider('clipboard') after call GuiClipboard() in my gvimrc.vim

svermeulen avatar Feb 21 '19 21:02 svermeulen

Thanks @svermeulen. The question now is how to merge this upstream in a way that does not break other stuff - as it is that reloadprovider thing is not very safe.

equalsraf avatar Feb 21 '19 23:02 equalsraf

https://github.com/neovim/neovim/pull/10161 was merged, can this issue be closed now? Or what's remaining?

justinmk avatar Sep 21 '19 22:09 justinmk

I've been using this for a few weeks now. Works fine, just missing some niceties in the shim plugin.

To enable

:call GuiClipboard()

If you are reconnecting the UI you need to call it again.

Since the UI autocommands were also merged, it is simply a matter of calling GuiClipboard() from the autocommand (assuming neovim supports it). Otherwise placing a call in ginit.vim is also an option.

Just a quick reminder that you need o install the gui shim on the neovim host side.

equalsraf avatar Sep 22 '19 11:09 equalsraf

@equalsraf are you planning to enable guiclipboard by default eventually?

justinmk avatar Sep 22 '19 16:09 justinmk

On a recent install of neovim-qt, it seems that 'GuiClipboard' doesn't exist? Or is my install broken? This is on Win10

image

adrubesh avatar Mar 21 '21 13:03 adrubesh

It should still be there. Are other gui functions or commands available?

When in doubt you can check :scriptnames (the path to nvim_gui_shim.vim should be there). If it is missing it was not loaded. Check the value in &rtp to see what path is in there to load the shim.

equalsraf avatar Mar 21 '21 14:03 equalsraf

@equalsraf Ah, thanks, I'm using nvim --server to connect to a remote nvim and forgot the shim on the server side :)

adrubesh avatar Mar 21 '21 15:03 adrubesh

use ssh with -Y key to make clipboard work without GuiClibboard() call

xakep71k avatar Oct 26 '21 19:10 xakep71k