summaryrefslogtreecommitdiffstats
path: root/autoload/vimtex/view/mupdf.vim
blob: 95d3710ccf32258f042a5e0a1ee02270f1b1a091 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1

" vimtex - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email:      karl.yngve@gmail.com
"

function! vimtex#view#mupdf#new() abort " {{{1
  " Check if the viewer is executable
  if !executable('mupdf')
    call vimtex#log#error(
          \ 'MuPDF is not executable!',
          \ '- vimtex viewer will not work!')
    return {}
  endif

  " Use the xwin template
  return vimtex#view#common#apply_xwin_template('MuPDF',
        \ vimtex#view#common#apply_common_template(deepcopy(s:mupdf)))
endfunction

" }}}1

let s:mupdf = {
      \ 'name': 'MuPDF',
      \}

function! s:mupdf.start(outfile) dict abort " {{{1
  let l:cmd = 'mupdf ' .  g:vimtex_view_mupdf_options
        \ . ' ' . vimtex#util#shellescape(a:outfile)
  let self.process = vimtex#process#start(l:cmd)

  call self.xwin_get_id()
  call self.xwin_send_keys(g:vimtex_view_mupdf_send_keys)

  if g:vimtex_view_forward_search_on_start
    call self.forward_search(a:outfile)
  endif
endfunction

" }}}1
function! s:mupdf.forward_search(outfile) dict abort " {{{1
  if !executable('xdotool') | return | endif
  if !executable('synctex') | return | endif

  let self.cmd_synctex_view = 'synctex view -i '
        \ . (line('.') + 1) . ':'
        \ . (col('.') + 1) . ':'
        \ . vimtex#util#shellescape(expand('%:p'))
        \ . ' -o ' . vimtex#util#shellescape(a:outfile)
        \ . " | grep -m1 'Page:' | sed 's/Page://' | tr -d '\n'"
  let self.page = system(self.cmd_synctex_view)

  if self.page > 0
    let l:cmd = 'xdotool'
          \ . ' type --window ' . self.xwin_id
          \ . ' "' . self.page . 'g"'
    call vimtex#process#run(l:cmd)
    let self.cmd_forward_search = l:cmd
  endif

  call self.focus_viewer()
endfunction

" }}}1
function! s:mupdf.reverse_search() dict abort " {{{1
  if !executable('xdotool') | return | endif
  if !executable('synctex') | return | endif

  let outfile = self.out()
  if vimtex#view#common#not_readable(outfile) | return | endif

  if !self.xwin_exists()
    call vimtex#log#warning('Reverse search failed (is MuPDF open?)')
    return
  endif

  " Get page number
  let self.cmd_getpage  = 'xdotool getwindowname ' . self.xwin_id
  let self.cmd_getpage .= " | sed 's:.* - \\([0-9]*\\)/.*:\\1:'"
  let self.cmd_getpage .= " | tr -d '\n'"
  let self.page = system(self.cmd_getpage)
  if self.page <= 0 | return | endif

  " Get file
  let self.cmd_getfile  = 'synctex edit '
  let self.cmd_getfile .= "-o \"" . self.page . ':288:108:' . outfile . "\""
  let self.cmd_getfile .= "| grep 'Input:' | sed 's/Input://' "
  let self.cmd_getfile .= "| head -n1 | tr -d '\n' 2>/dev/null"
  let self.file = system(self.cmd_getfile)

  " Get line
  let self.cmd_getline  = 'synctex edit '
  let self.cmd_getline .= "-o \"" . self.page . ':288:108:' . outfile . "\""
  let self.cmd_getline .= "| grep -m1 'Line:' | sed 's/Line://' "
  let self.cmd_getline .= "| head -n1 | tr -d '\n'"
  let self.line = system(self.cmd_getline)

  " Go to file and line
  silent exec 'edit ' . fnameescape(self.file)
  if self.line > 0
    silent exec ':' . self.line
    " Unfold, move to top line to correspond to top pdf line, and go to end of
    " line in case the corresponding pdf line begins on previous pdf page.
    normal! zvztg_
  endif
endfunction

" }}}1
function! s:mupdf.compiler_callback(status) dict abort " {{{1
  if !a:status && g:vimtex_view_use_temp_files < 2
    return
  endif

  if g:vimtex_view_use_temp_files
    call self.copy_files()
  endif

  if !filereadable(self.out()) | return | endif

  if g:vimtex_view_automatic
    "
    " Search for existing window created by latexmk
    "   It may be necessary to wait some time before it is opened and
    "   recognized. Sometimes it is very quick, other times it may take
    "   a second. This way, we don't block longer than necessary.
    "
    if !has_key(self, 'started_through_callback')
      for l:dummy in range(30)
        sleep 50m
        if self.xwin_exists() | break | endif
      endfor
    endif

    if !self.xwin_exists() && !has_key(self, 'started_through_callback')
      call self.start(self.out())
      let self.started_through_callback = 1
    endif
  endif

  if g:vimtex_view_use_temp_files || get(b:vimtex.compiler, 'callback')
    call self.xwin_send_keys('r')
  endif

  if has_key(self, 'hook_callback')
    call self.hook_callback()
  endif
endfunction

" }}}1
function! s:mupdf.latexmk_append_argument() dict abort " {{{1
  if g:vimtex_view_use_temp_files
    let cmd = ' -view=none'
  else
    let cmd  = vimtex#compiler#latexmk#wrap_option('new_viewer_always', '0')
    let cmd .= vimtex#compiler#latexmk#wrap_option('pdf_update_method', '2')
    let cmd .= vimtex#compiler#latexmk#wrap_option('pdf_update_signal', 'SIGHUP')
    let cmd .= vimtex#compiler#latexmk#wrap_option('pdf_previewer',
          \ 'mupdf ' .  g:vimtex_view_mupdf_options)
  endif

  return cmd
endfunction

" }}}1
function! s:mupdf.focus_viewer() dict abort " {{{1
  if !executable('xdotool') | return | endif

  if self.xwin_id > 0
    silent call system('xdotool windowactivate ' . self.xwin_id . ' --sync')
    silent call system('xdotool windowraise ' . self.xwin_id)
  endif
endfunction

" }}}1
function! s:mupdf.focus_vim() dict abort " {{{1
  if !executable('xdotool') | return | endif

  silent call system('xdotool windowactivate ' . v:windowid . ' --sync')
  silent call system('xdotool windowraise ' . v:windowid)
endfunction

" }}}1

endif