Updated implementation of #443

This commit is contained in:
Karl Yngve Lervåg 2016-08-06 20:02:52 +02:00
parent c132b3db24
commit 618f455d34
2 changed files with 155 additions and 187 deletions

View File

@ -8,7 +8,6 @@ let s:viewers = [
\ 'general', \ 'general',
\ 'mupdf', \ 'mupdf',
\ 'zathura', \ 'zathura',
\ 'zathura_alternative',
\ ] \ ]
for viewer in s:viewers for viewer in s:viewers
execute 'let s:' . viewer . ' = {}' execute 'let s:' . viewer . ' = {}'
@ -19,6 +18,7 @@ function! vimtex#view#init_options() " {{{1
if !g:vimtex_view_enabled | return | endif if !g:vimtex_view_enabled | return | endif
call vimtex#util#set_default('g:vimtex_view_method', 'general') call vimtex#util#set_default('g:vimtex_view_method', 'general')
call vimtex#util#set_default('g:vimtex_view_use_temp_files', 0)
endfunction endfunction
" }}}1 " }}}1
@ -43,7 +43,7 @@ function! vimtex#view#init_buffer() " {{{1
return return
endif endif
execute 'let b:vimtex.viewer = deepcopy(' . viewer . ')' execute 'let b:vimtex.viewer = ' . viewer
call b:vimtex.viewer.init() call b:vimtex.viewer.init()
" "
@ -111,11 +111,27 @@ function! s:general.init() dict " {{{2
call vimtex#echo#echo('- Please see :h g:vimtex_view_general_viewer') call vimtex#echo#echo('- Please see :h g:vimtex_view_general_viewer')
call vimtex#echo#wait() call vimtex#echo#wait()
endif endif
if g:vimtex_view_use_temp_files
let self.out = b:vimtex.root . '/' . b:vimtex.name . '_vimtex.pdf'
let self.synctex = fnamemodify(self.out, ':r') . '.synctex.gz'
let self.copy_files = function('s:copy_files')
else
let self.out = b:vimtex.out()
let self.synctex = b:vimtex.ext('synctex.gz')
endif
endfunction endfunction
" }}}2 " }}}2
function! s:general.view(file) dict " {{{2 function! s:general.view(file) dict " {{{2
let outfile = a:file !=# '' ? a:file : b:vimtex.out() if empty(a:file)
if g:vimtex_view_use_temp_files
call self.copy_files()
endif
let outfile = self.out
else
let outfile = a:file
endif
if s:output_not_readable(outfile) | return | endif if s:output_not_readable(outfile) | return | endif
" Parse options " Parse options
@ -139,12 +155,17 @@ endfunction
" }}}2 " }}}2
function! s:general.latexmk_append_argument() dict " {{{2 function! s:general.latexmk_append_argument() dict " {{{2
if g:vimtex_view_use_temp_files
return ' -view=none'
else
let l:option = g:vimtex_view_general_viewer let l:option = g:vimtex_view_general_viewer
if !empty(g:vimtex_view_general_options_latexmk) if !empty(g:vimtex_view_general_options_latexmk)
let l:option .= ' ' . substitute(g:vimtex_view_general_options_latexmk, let l:option .= ' '
let l:option .= substitute(g:vimtex_view_general_options_latexmk,
\ '@line', line('.'), 'g') \ '@line', line('.'), 'g')
endif endif
return vimtex#latexmk#add_option('pdf_previewer', l:option) return vimtex#latexmk#add_option('pdf_previewer', l:option)
endif
endfunction endfunction
" }}}2 " }}}2
@ -171,8 +192,18 @@ function! s:mupdf.init() dict " {{{2
call vimtex#echo#warning('viewer MuPDF requires xdotool!') call vimtex#echo#warning('viewer MuPDF requires xdotool!')
endif endif
if g:vimtex_view_use_temp_files
let self.out = b:vimtex.root . '/' . b:vimtex.name . '_vimtex.pdf'
let self.synctex = fnamemodify(self.out, ':r') . '.synctex.gz'
let self.copy_files = function('s:copy_files')
else
let self.out = b:vimtex.out()
let self.synctex = b:vimtex.ext('synctex.gz')
endif
let self.class = 'MuPDF' let self.class = 'MuPDF'
let self.xwin_id = 0 let self.xwin_id = 0
let self.view = function('s:view')
let self.xwin_exists = function('s:xwin_exists') let self.xwin_exists = function('s:xwin_exists')
let self.xwin_get_id = function('s:xwin_get_id') let self.xwin_get_id = function('s:xwin_get_id')
let self.xwin_send_keys = function('s:xwin_send_keys') let self.xwin_send_keys = function('s:xwin_send_keys')
@ -183,22 +214,6 @@ function! s:mupdf.init() dict " {{{2
call add(g:vimtex_latexmk_callback_hooks, 'b:vimtex.viewer.latexmk_callback') call add(g:vimtex_latexmk_callback_hooks, 'b:vimtex.viewer.latexmk_callback')
endfunction endfunction
" }}}2
function! s:mupdf.view(file) dict " {{{2
let outfile = a:file !=# '' ? a:file : b:vimtex.out()
if s:output_not_readable(outfile) | return | endif
if self.xwin_exists()
call self.forward_search(outfile)
else
call self.start(outfile)
endif
if has_key(self, 'hook_view')
call self.hook_view()
endif
endfunction
" }}}2 " }}}2
function! s:mupdf.start(outfile) dict " {{{2 function! s:mupdf.start(outfile) dict " {{{2
let exe = {} let exe = {}
@ -283,11 +298,22 @@ endfunction
" }}}2 " }}}2
function! s:mupdf.latexmk_callback(status) dict " {{{2 function! s:mupdf.latexmk_callback(status) dict " {{{2
if !a:status | return | endif
sleep 500m sleep 500m
if !self.xwin_exists() | return | endif
if g:vimtex_view_use_temp_files
call self.copy_files()
endif
if !self.xwin_exists()
call self.start(self.out)
endif
if g:vimtex_view_use_temp_files
call self.xwin_send_keys('r')
endif
call self.xwin_send_keys(g:vimtex_view_mupdf_send_keys) call self.xwin_send_keys(g:vimtex_view_mupdf_send_keys)
call self.forward_search(b:vimtex.out())
if has_key(self, 'hook_callback') if has_key(self, 'hook_callback')
call self.hook_callback() call self.hook_callback()
endif endif
@ -295,11 +321,15 @@ endfunction
" }}}2 " }}}2
function! s:mupdf.latexmk_append_argument() dict " {{{2 function! s:mupdf.latexmk_append_argument() dict " {{{2
if g:vimtex_view_use_temp_files
let cmd = ' -view=none'
else
let cmd = vimtex#latexmk#add_option('new_viewer_always', '0') let cmd = vimtex#latexmk#add_option('new_viewer_always', '0')
let cmd .= vimtex#latexmk#add_option('pdf_update_method', '2') let cmd .= vimtex#latexmk#add_option('pdf_update_method', '2')
let cmd .= vimtex#latexmk#add_option('pdf_update_signal', 'SIGHUP') let cmd .= vimtex#latexmk#add_option('pdf_update_signal', 'SIGHUP')
let cmd .= vimtex#latexmk#add_option('pdf_previewer', let cmd .= vimtex#latexmk#add_option('pdf_previewer',
\ 'mupdf ' . g:vimtex_view_mupdf_options) \ 'mupdf ' . g:vimtex_view_mupdf_options)
endif
return cmd return cmd
endfunction endfunction
@ -326,8 +356,18 @@ function! s:zathura.init() dict " {{{2
call vimtex#echo#warning('viewer Zathura requires xdotool!') call vimtex#echo#warning('viewer Zathura requires xdotool!')
endif endif
if g:vimtex_view_use_temp_files
let self.out = b:vimtex.root . '/' . b:vimtex.name . '_vimtex.pdf'
let self.synctex = fnamemodify(self.out, ':r') . '.synctex.gz'
let self.copy_files = function('s:copy_files')
else
let self.out = b:vimtex.out()
let self.synctex = b:vimtex.ext('synctex.gz')
endif
let self.class = 'Zathura' let self.class = 'Zathura'
let self.xwin_id = 0 let self.xwin_id = 0
let self.view = function('s:view')
let self.xwin_get_id = function('s:xwin_get_id') let self.xwin_get_id = function('s:xwin_get_id')
let self.xwin_exists = function('s:xwin_exists') let self.xwin_exists = function('s:xwin_exists')
call self.xwin_exists() call self.xwin_exists()
@ -335,22 +375,6 @@ function! s:zathura.init() dict " {{{2
call add(g:vimtex_latexmk_callback_hooks, 'b:vimtex.viewer.latexmk_callback') call add(g:vimtex_latexmk_callback_hooks, 'b:vimtex.viewer.latexmk_callback')
endfunction endfunction
" }}}2
function! s:zathura.view(file) dict " {{{2
let outfile = a:file !=# '' ? a:file : b:vimtex.out()
if s:output_not_readable(outfile) | return | endif
if self.xwin_exists()
call self.forward_search(outfile)
else
call self.start(outfile)
endif
if has_key(self, 'hook_view')
call self.hook_view()
endif
endfunction
" }}}2 " }}}2
function! s:zathura.start(outfile) dict " {{{2 function! s:zathura.start(outfile) dict " {{{2
let exe = {} let exe = {}
@ -369,116 +393,6 @@ endfunction
" }}}2 " }}}2
function! s:zathura.forward_search(outfile) dict " {{{2 function! s:zathura.forward_search(outfile) dict " {{{2
let exe = {}
let exe.cmd = 'zathura --synctex-forward '
let exe.cmd .= line('.')
let exe.cmd .= ':' . col('.')
let exe.cmd .= ':' . vimtex#util#shellescape(expand('%:p'))
let exe.cmd .= ' ' . vimtex#util#shellescape(a:outfile)
call vimtex#util#execute(exe)
let self.cmd_forward_search = exe.cmd
endfunction
" }}}2
function! s:zathura.latexmk_callback(status) dict " {{{2
sleep 500m
if !self.xwin_exists() | return | endif
call self.forward_search(b:vimtex.out())
if has_key(self, 'hook_callback')
call self.hook_callback()
endif
endfunction
" }}}2
function! s:zathura.latexmk_append_argument() dict " {{{2
let cmd = vimtex#latexmk#add_option('new_viewer_always', '0')
let cmd .= vimtex#latexmk#add_option('pdf_previewer',
\ 'zathura ' . g:vimtex_view_zathura_options
\ . ' -x \"' . g:vimtex_latexmk_progname
\ . ' --servername ' . v:servername
\ . ' --remote +\%{line} \%{input}\" \%S')
return cmd
endfunction
" }}}2
" }}}1
" {{{1 Zathura alternative
function! s:zathura_alternative.init() dict " {{{2
" Only initialize once
if has_key(self, 'xwin_id') | return | endif
"
" Default Zathura settings
"
call vimtex#util#set_default('g:vimtex_view_zathura_options', '')
if !executable('zathura')
call vimtex#echo#warning('Zathura is not executable!')
call vimtex#echo#echo('- vimtex viewer will not work!')
call vimtex#echo#wait()
endif
if !executable('xdotool')
call vimtex#echo#warning('viewer Zathura requires xdotool!')
endif
"
" Define output file names for the viewer
"
let self.out = b:vimtex.root . '/' . b:vimtex.name . '_vimtex.pdf'
let self.synctex = fnamemodify(self.out, ':r') . '.synctex.gz'
let self.class = 'Zathura'
let self.xwin_id = 0
let self.xwin_get_id = function('s:xwin_get_id')
let self.xwin_exists = function('s:xwin_exists')
call self.xwin_exists(1)
call add(g:vimtex_latexmk_callback_hooks, 'b:vimtex.viewer.latexmk_callback')
endfunction
" }}}2
function! s:zathura_alternative.view(file) dict " {{{2
if empty(a:file)
call self.copy_files()
let outfile = self.out
else
let outfile = a:file
endif
if s:output_not_readable(outfile) | return | endif
if self.xwin_exists(1)
call self.forward_search(outfile)
else
call self.start(outfile)
endif
if has_key(self, 'hook_view')
call self.hook_view()
endif
endfunction
" }}}2
function! s:zathura_alternative.start(outfile) dict " {{{2
let exe = {}
let exe.cmd = 'zathura'
let exe.cmd .= ' -x "' . g:vimtex_latexmk_progname
\ . ' --servername ' . v:servername
\ . ' --remote +\%{line} \%{input}"'
let exe.cmd .= ' ' . g:vimtex_view_zathura_options
let exe.cmd .= ' ' . vimtex#util#shellescape(a:outfile)
call vimtex#util#execute(exe)
let self.cmd_start = exe.cmd
call self.xwin_get_id()
call self.forward_search(a:outfile)
endfunction
" }}}2
function! s:zathura_alternative.forward_search(outfile) dict " {{{2
if !filereadable(self.synctex) | return | endif if !filereadable(self.synctex) | return | endif
let exe = {} let exe = {}
@ -492,42 +406,37 @@ function! s:zathura_alternative.forward_search(outfile) dict " {{{2
endfunction endfunction
" }}}2 " }}}2
function! s:zathura_alternative.latexmk_callback(status) dict " {{{2 function! s:zathura.latexmk_callback(status) dict " {{{2
if !a:status | return | endif if !a:status | return | endif
call self.copy_files()
sleep 500m sleep 500m
if self.xwin_exists(1)
if g:vimtex_view_use_temp_files
call self.copy_files()
endif
if !self.xwin_exists()
call self.start(self.out)
endif
if has_key(self, 'hook_callback') if has_key(self, 'hook_callback')
call self.hook_callback() call self.hook_callback()
endif endif
endfunction
" }}}2
function! s:zathura.latexmk_append_argument() dict " {{{2
if g:vimtex_view_use_temp_files
let cmd = ' -view=none'
else else
call self.start(self.out) let cmd = vimtex#latexmk#add_option('new_viewer_always', '0')
endif let cmd .= vimtex#latexmk#add_option('pdf_previewer',
endfunction \ 'zathura ' . g:vimtex_view_zathura_options
\ . ' -x \"' . g:vimtex_latexmk_progname
" }}}2 \ . ' --servername ' . v:servername
function! s:zathura_alternative.latexmk_append_argument() dict " {{{2 \ . ' --remote +\%{line} \%{input}\" \%S')
return ' -view=none'
endfunction
" }}}2
function! s:zathura_alternative.copy_files() dict " {{{2
"
" Copy pdf file
"
if getftime(b:vimtex.out()) > getftime(self.out)
call writefile(readfile(b:vimtex.out(), 'b'), self.out, 'b')
endif endif
" return cmd
" Copy synctex file
"
let l:old = fnamemodify(b:vimtex.out(), ':r') . '.synctex.gz'
if getftime(l:old) > getftime(self.synctex)
call rename(l:old, self.synctex)
endif
endfunction endfunction
" }}}2 " }}}2
@ -537,6 +446,29 @@ endfunction
" "
" Common functionality " Common functionality
" "
function! s:view(file) dict " {{{1
if empty(a:file)
if g:vimtex_view_use_temp_files
call self.copy_files()
endif
let outfile = self.out
else
let outfile = a:file
endif
if s:output_not_readable(outfile) | return | endif
if self.xwin_exists()
call self.forward_search(outfile)
else
call self.start(outfile)
endif
if has_key(self, 'hook_view')
call self.hook_view()
endif
endfunction
" }}}1
function! s:output_not_readable(output) " {{{1 function! s:output_not_readable(output) " {{{1
if !filereadable(a:output) if !filereadable(a:output)
call vimtex#echo#warning('viewer can not read PDF file!') call vimtex#echo#warning('viewer can not read PDF file!')
@ -571,7 +503,7 @@ function! s:xwin_get_id() dict " {{{1
endfunction endfunction
" }}}1 " }}}1
function! s:xwin_exists(...) dict " {{{1 function! s:xwin_exists() dict " {{{1
if !executable('xdotool') | return 0 | endif if !executable('xdotool') | return 0 | endif
" "
@ -588,8 +520,7 @@ function! s:xwin_exists(...) dict " {{{1
" If xwin_id is unset, check if matching viewer windows exist " If xwin_id is unset, check if matching viewer windows exist
" "
if self.xwin_id == 0 if self.xwin_id == 0
let cmd = 'xdotool search --name ' let cmd = 'xdotool search --name ' . fnamemodify(self.out, ':t')
\ . fnamemodify(a:0 > 0 ? self.out : b:vimtex.out(), ':t')
let result = split(system(cmd), '\n') let result = split(system(cmd), '\n')
if len(result) > 0 if len(result) > 0
let self.xwin_id = result[-1] let self.xwin_id = result[-1]
@ -610,6 +541,24 @@ function! s:xwin_send_keys(keys) dict " {{{1
endif endif
endfunction endfunction
" }}}1
function! s:copy_files() dict " {{{1
"
" Copy pdf file
"
if getftime(b:vimtex.out()) > getftime(self.out)
call writefile(readfile(b:vimtex.out(), 'b'), self.out, 'b')
endif
"
" Copy synctex file
"
let l:old = b:vimtex.ext('synctex.gz')
if getftime(l:old) > getftime(self.synctex)
call rename(l:old, self.synctex)
endif
endfunction
" }}}1 " }}}1
" "

View File

@ -795,6 +795,25 @@ Options~
Default value: 1 Default value: 1
*g:vimtex_view_use_temp_files*
If enabled, this will copy output files to a corresponding set of files
with `_vimtex` prepended to the name. If one combines this with the callback
feature, this may provide a very convenient way to avoid that the pdf
becomes unavailable during compilation, as it will only update the viewer
outut file after a successful compilation.
Note: This will disable the viewer from the latexmk end. That is, if this
option is enabled, opening and updating the pdf viewer will have to be
done by the user or by vimtex.
Note: This works best with the 'mupdf' and 'zathura' viewers. In particular,
these viewers should update automatically after the pdf is updated.
For general viewers, one has to create a callback function and connect
it through |g:vimtex_view_general_callback|, and then use this
callback to update the viewer.
Default value: 0
*g:vimtex_view_method* *g:vimtex_view_method*
Set the viewer method. The general viewer |vimtex_viewer_general| defines Set the viewer method. The general viewer |vimtex_viewer_general| defines
a generic interface that allows sufficient customization for most viewer a generic interface that allows sufficient customization for most viewer