Vim Tips Wiki
(paste text from Use dde to close Adobe Reader before compiling by 98.220.232.75 for easier comparison later after merge, if needed)
(Simplify.)
(8 intermediate revisions by 4 users not shown)
Line 11: Line 11:
 
|category2=
 
|category2=
 
}}
 
}}
When you are editing a large LaTeX project, it is easy to jump around in Vim using tags, marks, file tree plugins, etc. One problem is after you jump to a tag in Vim the pdf open in other window does not change page. This tip will allow you to add a command to vim to change the page of the pdf to match the current location in Vim.
+
When you are editing a large LaTeX project, it is easy to jump around in Vim using tags, marks, file tree plugins, etc. One problem is that after you jump to a tag in Vim, the pdf open in another application does not change page. This tip adds a command to Vim to change the page of the pdf to match the current location in Vim, and assumes you are using the [http://sourceforge.net/projects/vim-latex/ Latex-Suite].
   
 
==Finding pdf filename and line for current cursor==
 
==Finding pdf filename and line for current cursor==
First, copy one of the OpenPDF functions below specific to your operating system.
+
Add the following code to your <tt>tex.vim</tt> file (<tt>~/.vim/ftplugin/tex.vim</tt> on Unix, or <tt>$HOME/vimfiles/ftplugin/tex.vim</tt> on Windows). Also add one of the <tt>OpenPDF</tt> functions listed below, depending on your operating system.
 
Then drop the following functions in your tex.vim ftplugin file or your vimrc file
 
 
<pre>
 
<pre>
 
"Load PDF to the page containing label
 
"Load PDF to the page containing label
Line 44: Line 42:
 
</pre>
 
</pre>
   
The first function looks through the aux files created by compiling the latex file for the label passed in as a parameter. If it finds the label, it loads the page number and then loads the pdf to the given page.
+
The first function looks through the aux files created by compiling the latex file for the label passed in as a parameter. If it finds the label, it loads the page number and then loads the pdf to the given page. If you use the hyperref package, replace the pattern
  +
'.\{}{\zs.*\ze}}'
  +
in the call to <code>matchstr()</code> in function <code>LoadEvinceByLabel</code> with:
  +
'newlabel{.*}{{.*}{\zs.*\ze}{.*}{.*}{.*}}'
  +
This is because the hyperref package adds three additional fields after the page number to the label definition line in the .aux files.
   
 
The second function searches for the nearest label from the current position and calls <tt>LoadEvinceByLabel</tt>.
 
The second function searches for the nearest label from the current position and calls <tt>LoadEvinceByLabel</tt>.
Line 50: Line 52:
 
To use them, add something like:
 
To use them, add something like:
 
<pre>
 
<pre>
map <buffer> <LocalLeader>e :call EvinceNearestLabel()<CR>
+
nnoremap <buffer> <LocalLeader>e :call EvinceNearestLabel()<CR>
 
</pre>
 
</pre>
   
Now <tt>\e</tt> will load the pdf viewer to page containing the nearest label to the current cursor position. Note this works great on multi-file projects since the aux file is searched to find the pdf name. So you can jump around in Vim using all the wonderful tools and plugins (tags, marks, nerdtree, project, etc.) and then tell the pdf viewer to jump to the given page.
+
Now <tt>\e</tt> will load the pdf viewer to the page containing the nearest label to the current cursor position (assuming the default backslash for the LocalLeader key). This works well on multi-file projects since the aux file is searched to find the pdf name. So you can jump around in Vim using its wonderful tools, then tell the pdf viewer to jump to the same page.
   
 
If you have set up tags, you can also add:
 
If you have set up tags, you can also add:
 
<pre>
 
<pre>
com! -nargs=1 -complete=tag Pdf call LoadEvinceByLabel("<args>")
+
command! -nargs=1 -complete=tag Pdf call LoadEvinceByLabel("<args>")
 
</pre>
 
</pre>
   
for a command <tt>:Pdf</tt> that you can use tab completion on labels to jump to a given location.
+
to create command <tt>:Pdf</tt> so you can use Tab completion on labels to jump to a given location.
   
 
==Linux==
 
==Linux==
On Linux, use the following OpenPDF function:
+
On Linux, use the following <tt>OpenPDF</tt> function:
 
<pre>
 
<pre>
 
function! OpenPDF(file,page)
 
function! OpenPDF(file,page)
Line 74: Line 76:
 
==Windows==
 
==Windows==
 
====Acrobat====
 
====Acrobat====
This is currently untested since I don't have access to a Windows machine. Commands can be sent to Acrobat using [http://www.istri.fr/zip/CMCDDE.zip]
+
Commands can be sent to Acrobat using [http://www.istri.fr/zip/CMCDDE.zip cmcdde], and the following version of <tt>OpenPDF</tt> can be used:
 
<pre>
 
<pre>
 
function! OpenPDF(file, page)
 
function! OpenPDF(file, page)
Line 81: Line 83:
 
</pre>
 
</pre>
   
If you use the vim-latexsuite plugin, acrobat needs to be closed before compiling which can be done with the following commands.
+
Acrobat needs to be closed before compiling which can be done with the following commands (the <tt>has("win32")</tt> test allows this code to be in a file that may be used on systems other than Windows, where different commands would be available):
 
<pre>
 
<pre>
 
if has("win32")
let s:AcroDDE = "cmcdde acroviewr10 control "
+
let s:AcroDDE = "cmcdde acroviewr10 control "
let s:ClosePdf = s:AcroDDE.'[DocOpen("%:p:r.pdf")][DocClose("%:p:r.pdf")] '
+
let s:ClosePdf = s:AcroDDE.'[DocOpen("%:p:r.pdf")][DocClose("%:p:r.pdf")] '
let g:Tex_CompileRule_pdf = s:ClosePdf.' & texify -bp --src $*'
+
let g:Tex_CompileRule_pdf = s:ClosePdf.' & texify -bp --src $*'
let g:Tex_ViewRule_pdf =
+
let g:Tex_ViewRule_pdf =
\ 'C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe'
+
\ 'C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe'
 
endif
 
</pre>
 
</pre>
   
 
The above assumes that <tt>cmcdde.exe</tt> is in a directory in your PATH. Alternatively, specify the full path name to <tt>cmcdde</tt> in <tt>s:AcroDDE</tt>.
==Mac==
 
''Need some ideas. Some AppleScript in OpenPDF should do the job.''
 
 
==Comments==
 
   
  +
===Notes for Windows===
==From [[Use dde to close Adobe Reader before compiling]]==
 
  +
:''May merge or remove this material later; keeping as miscellaneous notes for now.''
When using Adobe Reader on Windows to view pdf files, the current file is locked. That makes it necessary to close the pdf file before recompiling a tex file into pdf. An easy way to do so is to use [http://www.istri.fr/zip/CMCDDE.zip cmcdde].
+
When using Adobe Reader on Windows to view pdf files, the current file is locked. That makes it necessary to close the pdf file before recompiling a tex file into pdf.
   
To close the pdf output file of the currently edited tex file one would use:
+
To close the pdf output file of the currently edited tex file, use:
 
<pre>
 
<pre>
!start cmcdde acroviewr10 control [DocOpen("%:p:r.pdf")][DocClose("%:p:r.pdf")]
+
:!start cmcdde acroviewr10 control [DocOpen("%:p:r.pdf")][DocClose("%:p:r.pdf")]
 
</pre>
 
</pre>
   
Here <tt>DocOpen</tt> registers the pdf with the dde server. <tt>DocClose</tt> then closes the pdf.
+
<tt>DocOpen</tt> registers the pdf with the dde server. <tt>DocClose</tt> then closes the pdf.
   
The name Adobe uses for the DDE server changed from version 9 to 10. For Adobe Reader versions prior to 10 use <tt>acroview</tt> instead of <tt>acroviewr10</tt>. Adobe announced that future versions will also have the version number in the server name.
+
For Adobe Reader versions prior to 10, use <tt>acroview</tt> instead of <tt>acroviewr10</tt>. Adobe has announced that future versions will also have the version number in the server name.
   
 
Some other DDE commands are available with Adobe Reader, for example, <tt>DocGoTo</tt> and <tt>DocGoToNameDest</tt>. The first can be used to jump to a particular page in the pdf while the second jumps to a named destination. Perhaps the second one could be used to do a forward search with the Adobe Reader. (The idea is to call <tt>DocGoToNameDest</tt> with a fixed bookmark, say "cursorposition", and use latex to create that bookmark when compiling. Not sure if there exists some latex packet which could be used for that.)
To automatically close Adobe before recompiling using the vim-latex suite, put the following in the <tt>tex.vim</tt> file:
 
  +
 
Here is a trick to open Adobe Reader on the last page: use <tt>DocGoTo</tt> with a large page number (which doesn't exist):
 
<pre>
 
<pre>
 
:!start cmcdde acroviewr10 control [DocOpen("%:p:r.pdf")][DocGoTo("%:p:r.pdf,10000")]
if has("win32")
 
let s:AcroDDE = "cmcdde acroviewr10 control "
 
let s:ClosePdf = s:AcroDDE.'[DocOpen("%:p:r.pdf")][DocClose("%:p:r.pdf")] '
 
let g:Tex_CompileRule_pdf = s:ClosePdf.' & texify -bp --src $*'
 
let g:Tex_ViewRule_pdf =
 
\ 'C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe'
 
endif
 
 
</pre>
 
</pre>
   
 
==Mac==
This configuration assumes that the folder containing cmcdde is in your path. Alternatively just specify the full path name to <tt>cmcdde</tt> in <tt>s:AcroDDE</tt>.
 
 
''Need some ideas. Some AppleScript in OpenPDF should do the job.''
   
 
==Comments==
There are also a few other DDE commands available with the Adobe Reader. Most interestingly, <tt>DocGoTo</tt> and <tt>DocGoToNameDest</tt>. The first can be used to jump to a particular page in the pdf while the second jumps to a named destination. I haven't figured out yet how to do so, but maybe one could use the second one to implement some sort of forward search with the Adobe Reader. (The idea is to call <tt>DocGoToNameDest</tt> with a fixed bookmark, say "cursorposition", and use latex to create that bookmark when compiling. Not sure if there exists some latex packet which could be used for that.)
 
 
Here is a little trick to open Adobe Reader on the last page. Just use <tt>DocGoTo</tt> with a large page number (which doesn't need to exist):
 
<pre>
 
!start cmcdde acroviewr10 control [DocOpen("%:p:r.pdf")][DocGoTo("%:p:r.pdf,10000")]
 
</pre>
 

Revision as of 22:35, 7 December 2014

Proposed tip Please edit this page to improve it, or add your comments below (do not use the discussion page).

Please use new tips to discuss whether this page should be a permanent tip, or whether it should be merged to an existing tip.
created November 28, 2011 · complexity basic · author Wuzzeb · version 7.0

When you are editing a large LaTeX project, it is easy to jump around in Vim using tags, marks, file tree plugins, etc. One problem is that after you jump to a tag in Vim, the pdf open in another application does not change page. This tip adds a command to Vim to change the page of the pdf to match the current location in Vim, and assumes you are using the Latex-Suite.

Finding pdf filename and line for current cursor

Add the following code to your tex.vim file (~/.vim/ftplugin/tex.vim on Unix, or $HOME/vimfiles/ftplugin/tex.vim on Windows). Also add one of the OpenPDF functions listed below, depending on your operating system.

"Load PDF to the page containing label
function! LoadEvinceByLabel(l)
  for f in split(glob("*.aux"))
    let label = system('grep "^.newlabel{' . a:l . '" ' . f)
    let page = matchstr(label, '.\{}{\zs.*\ze}}')
    if ! empty(page)
      call OpenPDF(substitute(f, "aux$", "pdf", ""), page)
      return
    endif
  endfor
endfunction

"Load PDF to the page containing the nearest previous label to the cursor
function! EvinceNearestLabel()
  let line = search("\\label{", "bnW")
  if line > 0
    let m = matchstr(getline(line), '\\label{\zs[^}]*\ze}')
    if empty(m)
      echomsg "No label between here and start of file"
    else
      call LoadEvinceByLabel(m)
    endif
  endif
endfunction

The first function looks through the aux files created by compiling the latex file for the label passed in as a parameter. If it finds the label, it loads the page number and then loads the pdf to the given page. If you use the hyperref package, replace the pattern

'.\{}{\zs.*\ze}}'

in the call to matchstr() in function LoadEvinceByLabel with:

'newlabel{.*}{{.*}{\zs.*\ze}{.*}{.*}{.*}}'

This is because the hyperref package adds three additional fields after the page number to the label definition line in the .aux files.

The second function searches for the nearest label from the current position and calls LoadEvinceByLabel.

To use them, add something like:

nnoremap <buffer> <LocalLeader>e :call EvinceNearestLabel()<CR>

Now \e will load the pdf viewer to the page containing the nearest label to the current cursor position (assuming the default backslash for the LocalLeader key). This works well on multi-file projects since the aux file is searched to find the pdf name. So you can jump around in Vim using its wonderful tools, then tell the pdf viewer to jump to the same page.

If you have set up tags, you can also add:

command! -nargs=1 -complete=tag Pdf call LoadEvinceByLabel("<args>")

to create command :Pdf so you can use Tab completion on labels to jump to a given location.

Linux

On Linux, use the following OpenPDF function:

function! OpenPDF(file,page)
  exec 'silent ! evince --page-label=' . a:page . ' ' . a:file . ' > /dev/null 2>&1 &'
endfunction

Evince is smart enough so that if the pdf is already open, it just changes to the page of the existing window, and if the file is not open yet, it creates the new window and jumps to the given page.

Windows

Acrobat

Commands can be sent to Acrobat using cmcdde, and the following version of OpenPDF can be used:

function! OpenPDF(file, page)
  execute '!start cmcdde acroviewr10 control [DocOpen("' . a:file . '")][DocGoTo("' . a:file . ',' . a:page . '")]'
endfunction

Acrobat needs to be closed before compiling which can be done with the following commands (the has("win32") test allows this code to be in a file that may be used on systems other than Windows, where different commands would be available):

if has("win32")
  let s:AcroDDE = "cmcdde acroviewr10 control "
  let s:ClosePdf = s:AcroDDE.'[DocOpen("%:p:r.pdf")][DocClose("%:p:r.pdf")] '
  let g:Tex_CompileRule_pdf = s:ClosePdf.' & texify -bp --src $*'
  let g:Tex_ViewRule_pdf =
          \ 'C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe'
endif

The above assumes that cmcdde.exe is in a directory in your PATH. Alternatively, specify the full path name to cmcdde in s:AcroDDE.

Notes for Windows

May merge or remove this material later; keeping as miscellaneous notes for now.

When using Adobe Reader on Windows to view pdf files, the current file is locked. That makes it necessary to close the pdf file before recompiling a tex file into pdf.

To close the pdf output file of the currently edited tex file, use:

:!start cmcdde acroviewr10 control [DocOpen("%:p:r.pdf")][DocClose("%:p:r.pdf")]

DocOpen registers the pdf with the dde server. DocClose then closes the pdf.

For Adobe Reader versions prior to 10, use acroview instead of acroviewr10. Adobe has announced that future versions will also have the version number in the server name.

Some other DDE commands are available with Adobe Reader, for example, DocGoTo and DocGoToNameDest. The first can be used to jump to a particular page in the pdf while the second jumps to a named destination. Perhaps the second one could be used to do a forward search with the Adobe Reader. (The idea is to call DocGoToNameDest with a fixed bookmark, say "cursorposition", and use latex to create that bookmark when compiling. Not sure if there exists some latex packet which could be used for that.)

Here is a trick to open Adobe Reader on the last page: use DocGoTo with a large page number (which doesn't exist):

:!start cmcdde acroviewr10 control [DocOpen("%:p:r.pdf")][DocGoTo("%:p:r.pdf,10000")]

Mac

Need some ideas. Some AppleScript in OpenPDF should do the job.

Comments