2010-04-20 11 views
6

Estoy cambiando a usar Vim para mi entorno de edición LaTeX. Me gustaría poder textear el archivo fuente desde dentro de Vim y lanzar una vista externa si la compilación fue exitosa.Script Vim para compilar fuente TeX e iniciar PDF solo si no hay errores

que sé de la suite de Vim-látex, pero, si es posible, preferirían evitar su uso: es bastante pesado-peso, secuestra un montónde mis llaves, y estorba hasta mi VIMRUNTIME con una gran cantidad de archivos.

Esto es lo que tengo ahora:

if exists('b:tex_build_mapped') 
    finish 
endif 
" use maparg or mapcheck to see if key is free 
command! -buffer -nargs=* BuildTex call BuildTex(0, <f-args>) 
command! -buffer -nargs=* BuildAndViewTex call BuildTex(1, <f-args>) 
noremap <buffer> <silent> <F9> <Esc>:call BuildTex(0)<CR> 
noremap <buffer> <silent> <S-F9> <Esc>:call BuildTex(1)<CR> 
let b:tex_build_mapped = 1 

if exists('g:tex_build_loaded') 
    finish 
endif 
let g:tex_build_loaded = 1 

function! BuildTex(view_results, ...) 
    write 
    if filereadable("Makefile") 
     " If Makefile is available in current working directory, run 'make' with arguments 
     echo "(using Makefile)" 
     let l:cmd = "!make ".join(a:000, ' ') 
     echo l:cmd 
     execute l:cmd 
     if a:view_results && v:shell_error == 0 
      call ViewTexResults() 
     endif 
    else 
     let b:tex_flavor = 'pdflatex' 
     compiler tex 
     make % 
     if a:view_results && v:shell_error == 0 
      call ViewTexResults() 
     endif 
    endif 
endfunction 

function! ViewTexResults(...) 
    if a:0 == 0 
     let l:target = expand("%:p:r") . ".pdf" 
    else 
     let l:target = a:1 
    endif 
    if has('mac') 
     execute "! open -a Preview ".l:target 
    endif 
endfunction 

El problema es que v:shell_error no está establecido, incluso si hay errores de compilación. ¡Cualquier sugerencia o idea sobre cómo detectar si una compilación fue exitosa o no sería muy apreciada! ¡Gracias!


Entre las respuestas que se dan aquí, además de algún estudio de otros enfoques, creo que esto ha sido resuelto satisfactoriamente. Estoy publicando la solución aquí en caso de que alguien más esté interesado.

Básicamente, la mejor solución parece ser usar Rubber, un envoltorio alrededor de LaTeX, que generalmente "solo funciona", y proporciona resultados/errores muy limpios. La solución que presento a continuación utiliza preferentemente Rubber si se encuentra en el sistema y no se encuentra Makefile en el directorio actual. Si se encuentra un Makefile, lo usa en su lugar. Si no hay Makefile y Rubber no está instalado, usa pdflatex. En todos los casos, si la fuente no puede compilar, los errores (filtrados y analizados) se envían al búfer de QuickFix y la ventana de QuickFix se abre automáticamente. Si se compila correctamente, se escribe un mensaje corto, y si el usuario lo solicitó, el PDF se abrirá para su visualización.

En mi propia instalación, he alzado la función (excelente) "SetLatexEfm()" de Vim-Latex para analizar y filtrar la salida tex acumulación. Sin embargo, si no se encuentra esta función, la función siguiente se establece de manera predeterminada en un formato de mensaje de error que funciona lo suficientemente bien como para identificar y resaltar los errores en la ventana de QuickFix, aunque con mucha suciedad.

function! BuildTex(view_results, ...) 

     " record position 
     let save_cursor = getpos(".") 

     " save work 
     silent write 

     " From: http://stackoverflow.com/questions/2679475/vim-script-to-compile-tex-source-and-launch-pdf-only-if-no-errors 
     " If your shell is bash, you can use the ${PIPESTATUS} array variable to get 
     " the correct exit code (borrowed from this answer to another question). 
     silent setlocal shell=bash 
     silent setlocal shellpipe=2>&1\ \|\ tee\ %s;exit\ \${PIPESTATUS[0]} 

     let success = 1 
     if filereadable("Makefile") 
      " If Makefile is available in current working directory, run 'make' with arguments 
      echon "compiling using Makefile ..." 
      let l:makecmd = "make\\ ".join(a:000, '\\ ') 
      silent execute "setlocal makeprg=" . l:makecmd 
      try 
       " This function is defined in the Vim-Latex package, 
       " and provides excellent parsing and filtering of the error messages 
       " when running latex outside of the Rubber wrapper. 
       call s:SetLatexEfm() 
      catch /E117/ 
       set errorformat=%E!\ LaTeX\ %trror:\ %m, 
        \%E!\ %m, 
        \%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#, 
        \%+W%.%#\ at\ lines\ %l--%*\\d, 
        \%WLaTeX\ %.%#Warning:\ %m, 
        \%Cl.%l\ %m, 
        \%+C\ \ %m., 
        \%+C%.%#-%.%#, 
        \%+C%.%#[]%.%#, 
        \%+C[]%.%#, 
        \%+C%.%#%[{}\\]%.%#, 
        \%+C<%.%#>%.%#, 
        \%C\ \ %m, 
        \%-GSee\ the\ LaTeX%m, 
        \%-GType\ \ H\ <return>%m, 
        \%-G\ ...%.%#, 
        \%-G%.%#\ (C)\ %.%#, 
        \%-G(see\ the\ transcript%.%#), 
        \%-G\\s%#, 
        \%+O(%f)%r, 
        \%+P(%f%r, 
        \%+P\ %\\=(%f%r, 
        \%+P%*[^()](%f%r, 
        \%+P[%\\d%[^()]%#(%f%r, 
        \%+Q)%r, 
        \%+Q%*[^()])%r, 
        \%+Q[%\\d%*[^()])%r 
      endtry 
      silent make 
     else 
      let l:special_tex_compiler = "rubber" 
      if executable(l:special_tex_compiler) 
       echon "compiling with Rubber ..." 
       silent execute "setlocal makeprg=" . l:special_tex_compiler . "\\ -dfs\\ %" 
       setlocal errorformat=%f:%l:\ %m 
       silent make % 
      else 
       echon "compiling ..." 
       let b:tex_flavor = 'pdflatex' 
       compiler tex 
       silent make % 
      endif 
     endif 

     " set/report compile status 
     if v:shell_error 
      let l:success = 0 
      " let l:wheight = winheight(bufnr("%"))/2 
      " execute "copen ".l:wheight 
      copen 
     else 
      let l:success = 1 
      cclose 
      redraw 
      echon "successfully compiled" 
     endif 

     " view results if successful compile 
     if l:success && a:view_results 
      call ViewTexResults() 
     endif 

     " restore position 
     call setpos('.', save_cursor) 

    endfunction 

    function! ViewTexResults(...) 
     if a:0 == 0 
      let l:target = expand("%:p:r") . ".pdf" 
     else 
      let l:target = a:1 
     endif 
     if has('mac') 
      silent execute "! open -a Preview ".l:target 
      " obviously, you will need to write specific commands for other systems 
      " left as an exercise for the reader ... 
     endif 
    endfunction 

    command! -buffer -nargs=* BuildTex call BuildTex(0, <f-args>) 
    command! -buffer -nargs=* BuildAndViewTex call BuildTex(1, <f-args>) 
    noremap <buffer> <silent> <F9> <Esc>:call BuildTex(0)<CR> 
    noremap <buffer> <silent> <S-F9> <Esc>:call BuildTex(1)<CR> 

Actualización: He empaquetado y publicado esto como un script plugin-Vim tipo de archivo, disponible en: http://www.vim.org/scripts/script.php?script_id=3230.

+0

¡Esto es muy útil! –

Respuesta

3

Suponiendo que está cayendo en la sección else-theres-no-makefile, el problema puede ser con la variable shellpipe.

En mi sistema (Ubuntu), shellpipe=2>&1| tee y la llamada incorporada make no establece v:shell_error si falla.

El estado de devolución de | tee puede ser el que se establece en v:shell_error.

Si su shell es bash, puede usar la variable de matriz ${PIPESTATUS} para obtener el código de salida correcto (tomado de this answer a otra pregunta).

:set shellpipe=2>&1\ \|\ tee\ %s;exit\ \${PIPESTATUS[0]} 

De lo contrario, puede intentar:

:set shellpipe=\> 
:make % 

Ajusta v:shell_error cuando falla, pero no estoy seguro de si eso se hace un lío con la funcionalidad de penetración en el error de línea número, si hay alguno.

para ver lo que la variable se establece en:

:set shellpipe? 
+0

Curt, Gracias por esto. Lo probaré. Puedo ver que esto soluciona el problema en cuanto a detectar los errores, pero luego, como dices, arruinará el listado de la ventana de QuickFix. Estoy tentado de envolver todo el proceso de compilación en una secuencia de comandos de Python que pueda comportar errores más astutos en los errores, etc. – Jeet

1

Sé que no está relacionado con vim, pero creo que latexmk hace el trabajo.

Es un script (escrito en perl) que compila el archivo de látex y actualiza el pdf. El futuro más útil es la actualización automática. Tan pronto como guarde el archivo, 'latexmk' lo compilará, y si su visor de PDF lo admite, la vista se actualizará.

latexmk -pdf -pvc

+0

Parece que tiene un gran potencial. El problema es que, si hay un error, el script se detiene y hace una pausa para la entrada --- se necesita una Ctrl-D para matarlo. No permite el seguimiento de errores en la ventana de QuickFix. – Jeet

+0

He visto otro script que genera los mismos errores de compilación que un compilador de C, por lo que quizás podamos ejecutarlo y detectar errores en la ventana de QuickFix. Se llama [Rubber] (http://iml.univ-mrs.fr/~beffara/soft/rubber/). – hleb

+0

Gracias. De hecho, ya lo intenté hace un tiempo. Si recuerdo, el problema fue que también se detuvo y esperó la entrada de errores. Creo que podría haber tenido un indicador de "ignorar errores", pero esto significaba que, si un pdf anterior estaba disponible, se abrió incluso si la fuente de TeX no compilaba. – Jeet

0

Si latexmk corre látex con la opción '-halt-on-error' (o en el modo sin parar), compilación dejará sin hacer una pausa para la entrada.

Cuestiones relacionadas