donRaphaco / neotex

latex live preview - plugin for neovim and vim 8
MIT License
177 stars 8 forks source link

Synctex forward search implementation #10

Closed mactep closed 6 years ago

mactep commented 6 years ago

First of all, thank you for making this plugin.

I would like to suggest you the implementation of synctex forward search. I've managed to get it working, but its far from good.

Here is my modified version of tex.vim:

if !get(g:, 'neotex_enabled', 1)
    finish
endif

if !exists('s:neotex_loaded')
    if !has('timers')
        echohl Error | echomsg 'NeoTex requires timers support' | echohl None
    endif
    if !has('nvim') && !has('job')
        echohl Error | echomsg 'NeoTex requires neovim or vim 8 with job support' | echohl None
    endif

    let s:neotex_buffer_tempname = tempname()
    if get(g:, 'neotex_latexdiff', 0)
        let s:neotex_preview_tempname = tempname()
    else
        let s:neotex_preview_tempname = s:neotex_buffer_tempname
    endif

    if !exists('g:neotex_delay')
        let g:neotex_delay = 1000
    endif

    augroup _neotex_
        au!
    augroup END

    command! NeoTexOn au! _neotex_ TextChanged,TextChangedI <buffer> call s:latex_compile_delayed()
    command! NeoTexOff au! _neotex_ TextChanged,TextChangedI <buffer>
    command! NeoTex call s:latex_compile(0)
    command! NeoTexFS call s:zathura_forward_search()

    let s:neotex_loaded = 1
endif

let b:neotex_jobexe=''

if get(g:, 'neotex_latexdiff', 0)
    let b:neotex_jobexe .= 'latexdiff '
    if exists('neotex_latexdiff_options')
        let b:neotex_jobexe .= g:neotex_latexdiff_options . ' '
    endif
    let b:neotex_jobexe .= fnameescape(expand('%:t')) . ' ' . s:neotex_buffer_tempname . ' > ' . s:neotex_preview_tempname . ' && '
endif

let b:neotex_jobexe .= get(g:, 'neotex_pdflatex_alternative', 'pdflatex') . ' -shell-escape -jobname=' . fnameescape(expand('%:t:r')) . ' -interaction=nonstopmode' . ' -synctex=1 '
if exists('neotex_pdflatex_add_options')
    let b:neotex_jobexe .= g:neotex_pdflatex_add_options . ' '
endif

let b:neotex_jobexe .= s:neotex_preview_tempname

if get(g:, 'neotex_enabled', 1) == 2
    au! _neotex_ TextChanged,TextChangedI <buffer> call s:latex_compile_delayed()
endif

function! s:job_exit(...)
    if exists('s:job')
        unlet s:job
    endif
endfunction

function! s:latex_compile(_)
    if exists('s:job')
        call s:latex_compile_delayed()
        return
    endif
    call writefile(getline(1, '$'), s:neotex_buffer_tempname)
    if has('nvim')
        let s:job = jobstart(['bash', '-c', b:neotex_jobexe], {'cwd': expand('%:p:h'), 'on_exit': function('s:job_exit')})
    else
        let s:job = job_start(['bash', '-c', b:neotex_jobexe], {'cwd': expand('%:p:h'), 'out_io':'null', 'exit_cb': function('s:job_exit')})
    endif
    if exists('s:timer')
        unlet s:timer
    endif
endfunction

function! s:latex_compile_delayed()
    if exists('s:timer')
        call timer_stop(s:timer)
    endif
    let s:timer = timer_start(g:neotex_delay, function('s:latex_compile'))
endfunction

function! s:zathura_forward_search()
    exec "silent !zathura --synctex-forward ".line(".").":".col(".").":".s:neotex_preview_tempname." ".fnameescape(expand('%:p:r')).".pdf &"
endfunction

There is one caveat. Since the tempfile changes, the function works only if NeoTex has compiled the file in the current session.

I can try to make this implementation if you wish, but I'm totally new to plugins. Let me know if you need something more.

Sorry for bad grammar.

donRaphaco commented 6 years ago

Thanks for sharing. Currently I'm working on some changes for another feature, which would require some changes to your code, but also should fix the problem with the tempfile you mentioned. I will look into how we can synctex support after that (e.g. Would be nice if to have a similar forward search function for other pdf viewers as well).

mactep commented 6 years ago

Yeah, I just implemented it with Zathura because is the one I use. We'll need to define a default pdf viewer and a variable to know which one the user wants to use. This will require a function for each of the most used pdf viewers. In the downtime you can just add a variable with the tempfile name, so we can implement this feature outside of neotex. Something like b:neotex_tempfile should do the trick.

donRaphaco commented 6 years ago

In the downtime you can just add a variable with the tempfile name

I added the function NeotexTempfile() to make the filename of the tempfile globally readable.

mactep commented 6 years ago

I'll close the issue by now.