Skip to content

Instantly share code, notes, and snippets.

@14mRh4X0r
Created February 15, 2023 09:24
Show Gist options
  • Save 14mRh4X0r/5819f10a45013280f3c7abd27b8ae1cd to your computer and use it in GitHub Desktop.
Save 14mRh4X0r/5819f10a45013280f3c7abd27b8ae1cd to your computer and use it in GitHub Desktop.
Evince view implementation for VimTeX
" VimTeX - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email: karl.yngve@gmail.com
"
function! vimtex#view#evince#new() abort " {{{1
call vimtex#jobs#run("gdbus wait --session --activate org.gnome.evince.Daemon")
return s:viewer.init()
endfunction
" }}}1
let s:viewer = vimtex#view#_template#new({'name': 'evince'})
function! s:viewer._check() dict abort " {{{1
" Check if evince is executable
if !executable("evince")
call vimtex#log#error('evince is not executable!')
return v:false
elseif !executable("gdbus")
call vimtex#log#error('gdbus is not executable!')
return v:false
endif
return v:true
endfunction
function! s:url_encode_char(char) abort " {{{1
let encoded = ""
" Iterate over bytes, because files can contain utf-8 characters
let i = 0
while i < strlen(a:char)
let encoded = encoded .. strpart(a:char, i, 1)->char2nr()->printf("%%%02x")
let i += 1
endwhile
return encoded
endfunction
function! s:url_encode(path) abort " {{{1
return "file://" .. substitute(a:path, "[^A-Za-z0-9_.~/-]", {m -> s:url_encode_char(m[0])}, 'g')
endfunction
function! s:evince_dest(outfile, open) abort " {{{1
let l:cmd = 'gdbus call --session'
\ .. ' --dest org.gnome.evince.Daemon'
\ .. ' --object-path /org/gnome/evince/Daemon'
\ .. ' --method org.gnome.evince.Daemon.FindDocument'
\ .. ' ' .. s:url_encode(a:outfile)
\ .. ' ' .. (a:open ? 'true' : 'false')
let dest = vimtex#jobs#capture(l:cmd)[0]->substitute("('\\([^']*\\)',)", "\\1", "")
if !has('nvim')
if has_key(s:viewer, 'job') | call job_stop(s:viewer.job) | endif
let s:viewer.job = job_start(['gdbus', 'monitor',
\ '--session',
\ '--dest', dest,
\ '--object-path', '/org/gnome/evince/Window/0'
\], {'out_cb': function("vimtex#view#evince#handle_monitor")})
endif
return dest
endfunction
function! s:viewer._exists() dict abort " {{{1
return !s:evince_dest(self.out(), v:false)->empty()
endfunction
function! s:sync_view(dest) abort " {{{1
let l:cmd = 'gdbus call --session'
\ .. ' --dest ' .. a:dest
\ .. ' --object-path /org/gnome/evince/Window/0'
\ .. ' --method org.gnome.evince.Window.SyncView'
\ .. ' ' .. expand('%:p:S')
\ .. ' ' .. printf("'(%d,%d)'", line('.'), col('.'))
\ .. ' ' .. strftime("%s")
call vimtex#jobs#run(l:cmd)
endfunction
function! s:viewer._start(outfile) dict abort " {{{1
let dest = s:evince_dest(a:outfile, v:true)
call s:sync_view(dest)
endfunction
function! vimtex#view#evince#handle_monitor(channel, msg) abort " {{{1
if a:msg[0] != "/" | return | endif
let l:parts = split(a:msg)
if l:parts[1] != "org.gnome.evince.Window.SyncSource" | return | endif
let l:file = substitute(l:parts[2], "('file://\\(.*\\)',", "\\1", "")
let l:line = str2nr(l:parts[3][1:])
call vimtex#view#inverse_search(l:line, l:file)
endfunction
function! s:viewer._forward_search(outfile) dict abort " {{{1
let dest = s:evince_dest(a:outfile, v:false)
if empty(dest) | return | endif
call s:sync_view(dest)
endfunction
" }}}1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment