lervag / vimtex

VimTeX: A modern Vim and neovim filetype plugin for LaTeX files.
MIT License
5.53k stars 391 forks source link

Allow synctex backwards search when there are multiple vim sessions #2217

Closed user202729 closed 3 years ago

user202729 commented 3 years ago

Currently to use synctex it's necessary to specify --servername correctly.

It would be better (and possible?) if the command is send to all vim instances, then each can handle it correspondingly.

(Would require remote_startserver for each vim instance that does not start, and some vim-side implemented function to iterate over the existing servers, then on each server check if there's any open buffer with the matching name and move the cursor on that buffer)

There are some workarounds such as in https://github.com/lervag/vimtex/issues/1576#issuecomment-586752584 but even that one does not support multiple instance of vim run at once (although this is not particularly frequent use-case)

lervag commented 3 years ago

It would be better (and possible?) if the command is send to all vim instances, then each can handle it correspondingly.

No, that would not be better. It would ask every instance to open a specific file at a specific line?

(Would require remote_startserver for each vim instance that does not start, and some vim-side implemented function to iterate over the existing servers, then on each server check if there's any open buffer with the matching name and move the cursor on that buffer)

Yes; we would need to have a script that ran vim --servername X ... for each servername. Or nvr for neovim. People would need to ensure this is in $PATH (both on Windows and Linux and other OSes) for this to work. Thus, it does not seem trivial to make this easy for every kind of user.

I believe the recent updates to the docs should make it easier to understand how to setup inverse search. If you did not already read it, please do (:help vimtex-view-inverse-search.

user202729 commented 3 years ago

Okay I just pulled the latest version (actually I already read that trick, coming across the GitHub comment)

Remark: I think in Windows cmd can access the temp folder as simply %TEMP% or %TMP% (not tested)


Yes that's possible, but still if some user "happen to" run multiple TeX files with opened PDF file simultaneously it's still not ideal.

For the script approach... it's still possible to use vim itself (instead of Python script or something) as the script interpreter, and store the script in the plugin's autoload or something. It only assumes vim is in path.

For this approach

• vim should be used instead of gvim, as gvim popups a GUI window • it should also spawn another process (for example xterm -e vim filename.tex or something, should be user-configurable) if there's no existing remote that matches (because we don't want vim to run in whichever terminal the server uses, there may be no terminal at all)

Vim script will still run normally if there's no terminal.

lervag commented 3 years ago

Remark: I think in Windows cmd can access the temp folder as simply %TEMP% or %TMP% (not tested)

Yes, that seems useful. Since I'm not on Windows, I can't really test, so I won't make any updates. But if @jdhao or anyone else might test and suggest a change to the docs, I would be grateful for the contribution.

For the script approach... it's still possible to use vim itself (instead of Python script or something) as the script interpreter, and store the script in the plugin's autoload or something. It only assumes vim is in path.

Well, again, I'm not fully convinced. The viewer has to do a shell command first, e.g. vim --servername VIM --remote ....

If I understand you correctly, you are suggesting to setup the PDF viewer to run something like this:

# vim
for n in $(vim --serverlist); vim --servername $n --remote-expr "vimtex#view#inverse(%l, '%f')"

# neovim
for n in $(nvr --serverlist); nvr --servername $n --remote-expr "vimtex#view#inverse(%l, '%f')"

where vimtex#view#inverse would apply some logic to determine if it should perform the inverse search. This logic could be simple, e.g. check if the currently loaded buffer in the Vim session is a VimTeX buffer, and if the loaded VimTeX project contains the target file. If false, then don't do anything. If true, then perform the navigation.

In fact, I do agree that the above would not be too hard to realize. The main "drawback" is the shell script part on the viewer side. The code in my example should work in Zsh, I think. But not in Bash. So we would need to document this in a way that works well in both unix and Windows environments.

vimtex#view#inverse is partly already implemented as vimtex#view#reverse_goto, so it would not really be much extra code to add some more logic.

user202729 commented 3 years ago

No I mean let the viewer run

vim -c "call vimtex#SpecialCommandBackwardsSearchCalledFromCommandLine(%file, %line, %etc.)"

then let the function (implemented in Vimscript or anything vim supports) to call other vim instances, use vim (instead of Python, bash or Windows batch/cmd) as the script interpreter.

lervag commented 3 years ago

Ok. This is not impossible, but it is also not trivial. Some pseudocode:

function InverseSearch(file, line)
  if has('nvim')
    for server in serverlist()
      call system('nvr --servername SERVER --remote-expr ...')
    endfor
  else
    for server in split(serverlist(), "\n")
      call system('vim --servername SERVER --remote-expr ...')
    endfor
  endif

  quitall!
endfunction

We would probably need to call this with something like the following for Vim and neovim, respectively:

vim -T dumb --not-a-term -n -c InverseSearch(ARGS)
nvim --headless -c InverseSearch(ARGS)

I think this could potentially work, but I would need to learn how to do it properly in both Vim and neovim. On Vim, we could probably rely on the remote_expr() function instead of doing the system call. In neovim, I am fully sure what would be the right code.

But, ok, after thinking about it, I start to think that you may be right that this could work. It would be interesting to hear from other users, e.g. @jdhao and @clason.

clason commented 3 years ago

Hmm... Calling nvim just to shell out to call neovim-remote which then calls nvim again seems like a needlessly circuitous route to me. There has to be a better way.

user202729 commented 3 years ago

The alternative is a Python script/bash script/Windows cmd script/Windows power shell script, but it's quite OS-specific.

It's already mostly done (see the current documentation) except in the special case that there are multiple vim instances with VimTeX.

Either way, the logic is nontrivial so some interpreter is required, and apart from the above Python/etc. are not guaranteed to be available.

For the actual idea, shell escaping might make this harder (what if the file name contain space? '? "? \?), using vim command instead of vim function might or might not work...

lervag commented 3 years ago

For Vim, I believe the above outline is already close to the desired goal. We can replace system() with remote_expr(). With neovim, we need somehow to find the available RPC sockets and then to communicate with them. I want to do this from Vimscript, since VimTeX is written in Vimscript. But I'm not sure if that is fully possible, so a Lua solution could also be possible.

clason commented 3 years ago

I think for Neovim, a remote rpc call could work (similarly to how Python etc. plugins or GUIs -- or, in fact, neovim-remote) communicate with Nvim). I'm not an expert on that, though...

lervag commented 3 years ago

I've think I can get this to work, actually. I'm pushing a PR now - not ready, but it actually works. I'll close this issue - let's continue the discussion in the PR.