Soporte de Quickfix para trazas de Python

18

Digamos que tengo un script de Python con un error de tiempo de ejecución:

$ cat example.py  
#! /usr/bin/env python3

a = 1/0

lo que da:

$ python3 example.py 
Traceback (most recent call last):
  File "example.py", line 3, in <module>
    a = 1/0
ZeroDivisionError: division by zero

Quiero que Vim salte a la línea problemática de ese archivo (línea 3 en este caso). Sé que Vim puede hacer esto porque funciona bien para detectar errores en tiempo de compilación en C con el gccuso :makey la quickfixventana.

salida de revisión rápida de gcc

Claro, puedo llenar la ventana de corrección rápida de Vim con :set makeprg=python3\ %y luego :make, pero no salta al número de línea donde apunta el rastreo. Cuando lo miro :copen, solo resalta la primera línea de la traza, y no puedo saltar al número de línea relevante.

salida de revisión rápida de python3

(Estoy usando Vim 7.4 en Debian jessieen caso de que eso importe).

Mis preguntas son:

  • ¿Puedo configurar Vim para que sepa cómo obtener el número de línea relevante de un rastreo de Python?

  • ¿Puedo modificar el intérprete de Python para escupir un formato de error que Vim ya sabe cómo analizar y obtener el número de línea relevante?

Nathaniel M. Beaver
fuente
Puede subclasificar el registrador en su secuencia de comandos para producir puntos de rastreo uno por línea (consulte aquí para comenzar), luego ajuste en errorformatconsecuencia y escriba un complemento compilador para Vim (consulte :help :compilery :help write-compiler-plugin). Probablemente no valga la pena el esfuerzo si no sabe exactamente lo que está haciendo y no está lo suficientemente entusiasmado como para sacar todo de los documentos.
Sato Katsura
Hice una pregunta similar sobre StackOverflow, puede encontrar esas respuestas útiles stackoverflow.com/questions/11333112/…
jalanb

Respuestas:

7

Vim viene con un conjunto de scripts de "compilador", uno de los cuales se llama "pyunit" . Si ejecuta :compiler pyunity luego :make(con su valor sugerido para 'makeprg'), la solución rápida se rellena como espera. Sin embargo, solo funciona bien si hay un nivel en el seguimiento de la pila.

Mejorar ese script del compilador sería un ejercicio útil.

El complemento de desapilamiento puede ser de interés, ya que proporciona un mecanismo general para analizar y ver las ubicaciones informadas en un seguimiento de pila y tiene incorporado soporte para Python.

jamessan
fuente
4

Construido en el complemento del compilador pyunit

Como ya sugirió jamessan , una opción es usar el complemento del compilador incorporado pyunit:

:compiler pyunit
:set makeprg=python3\ %
:make

Esto tiene el inconveniente de que contrae el seguimiento de la pila en un solo mensaje de error. Por ejemplo, el siguiente script de Python:

def lumberjack():
    bright_side_of_death()

def bright_side_of_death():
    return tuple()[0]

lumberjack()

... produce este mensaje de error:

|| Traceback (most recent call last):
lumberjack.py|7|  IndexError: tuple index out of range

Escribir su propio complemento compilador

Como alternativa, puede proporcionar su propio complemento de compilador en ~/.vim/compiler/python.vim:

if exists("current_compiler")
  finish
endif
let current_compiler = "python"

let s:cpo_save = &cpo
set cpo&vim

CompilerSet errorformat=
      \%*\\sFile\ \"%f\"\\,\ line\ %l\\,\ %m,
      \%*\\sFile\ \"%f\"\\,\ line\ %l,
CompilerSet makeprg=python3\ %

let &cpo = s:cpo_save
unlet s:cpo_save

Seleccione el complemento manualmente :compiler pythono cárguelo automáticamente agregándolo a ~/.vim/after/ftplugin/python.vim:

if !exists("current_compiler")
  compiler python
endif

Con el script de Python de arriba, Vim llena la ventana de corrección rápida con:

|| Traceback (most recent call last):
lumberjack.py|7| in <module>
||     lumberjack()
lumberjack.py|2| in lumberjack
||     bright_side_of_death()
lumberjack.py|5| in bright_side_of_death
||     return tuple()[0]
|| IndexError: tuple index out of range

Ver :help write-compiler-pluginpara más información.

siho
fuente
3

quickfix.py analiza el rastreo en un formato de error compatible con vim. Aquí hay un ejemplo de cómo ejecutarlo en un archivo con una sola línea 1 / 0.

❯❯❯ quickfix.py tests/errors/div_by_zero.py
"tests/errors/div_by_zero.py":1: ZeroDivisionError: division by zero

Por defecto, muestra archivos de usuario, pero también puede mostrar archivos del sistema (ejecutándolo en un archivo que contiene import os; os.environ['123']):

❯❯❯ quickfix.py -a /tmp/test.py                                                                                                        
"/usr/lib/lib/python3.7/os.py":678: KeyError: '123'
"/tmp/test.py":1: in function <module>

Configuración:

Cuando quickfix.pyesté disponible en la ruta actual, agregue las siguientes líneas en el vimrc para usarlo.

if has("autocmd")
  autocmd FileType python setlocal makeprg=quickfix.py\ %
  autocmd FileType python setlocal errorformat=%E\"%f\":%l:%m,
endif
jadelord
fuente
-1

No es un método automático, pero Python Traceback establece el número de línea --- 3 en su ejemplo --- e invocando vim:

$ vim +3 example.py

se abrirá example.pycon el cursor en la tercera línea.

Chris Hanning
fuente
2
Soy consciente de eso, pero se trata del soporte de Quickfix. Después de ejecutar :makeun archivo que ya tengo abierto, es más rápido usar :3para saltar a la tercera línea que cerrar y volver a abrir. Además, hacer esto manualmente es una molestia para los seguimientos de pila más complejos, por eso quiero soporte Quickfix.
Nathaniel M. Beaver