- Conocer que es un
linter
y como funciona - Conocer
flymake
- Integrar
ruff
, linter depython
, enemacs
Una herramienta que permite hacer análisis a código y mostrar diagósticos, existen múltiples herramientas para diferentes lenguajes de programación
Es un paquete incluido en emacs
que permite integrar linters
de forma fácil
- La herramienta debe poder leer el código a analizar desde
stdin
y mostrar los resultados astdout
- Los resultados deben tener un formato estándarizado para poder extraer su información
import os
import sys
for i in range(10):
print(f"{fooo}")
value = 1
value2 += value + value3
ruff check demo.py
Obtenemos los errores pero están un poco dispersos, necesitamos una forma de tenerlos formateados.
ruff check --output-format concise demo.py
Ya tenemos la salida con un mejor formato, pero tenemos elementos que no necesitamos, como:
Found 5 errors.
[*] 2 fixable with the `--fix` option.
ruff check --output-format concise --quiet demo.py
cat demo.py | ruff check --output-format concise --quiet -
Para integrar con flymake
necesitamos poder parsear la salida del linter
, en este caso vamos a usar regexs para poder obtener los diferentes elementos del análisis realizado
(defvar flymake-ruff--output-regex "\\(.*\\):\\([0-9]+\\):\\([0-9]+\\): \\([A-Za-z0-9]+\\):? \\(.*\\)")
Podemos usar
regexp-builder
para construir de forma interactiva el regex
(defvar flymake-ruff-program-args '("check" "--output-format" "concise" "--exit-zero" "--quiet" "-"))
(defun flymake-ruff--check-buffer ()
(let ((code-buffer (current-buffer))
(start-line (line-number-at-pos (point-min) t))
(code-content (without-restriction
(buffer-substring-no-properties (point-min) (point-max))))
(dxs '()))
(with-temp-buffer
(insert code-content)
(apply #'call-process-region (point-min) (point-max) "ruff" t t nil flymake-ruff-program-args)
(goto-char (point-min))
(while (search-forward-regexp flymake-ruff--output-regex (point-max) t)
(when (match-string 2)
(let* ((line (string-to-number (match-string 2)))
(col (string-to-number (match-string 3)))
(code (match-string 4))
(msg (match-string 5))
(description (format "Ruff: %s %s" code msg))
(region (flymake-diag-region code-buffer (1+ (- line start-line)) col))
(dx (flymake-make-diagnostic code-buffer (car region) (cdr region)
:error description)))
(add-to-list 'dxs dx)))))
dxs))
(defun flymake-ruff--run-checker (report-fn &rest _args)
"Run checker using REPORT-FN."
(funcall report-fn (flymake-ruff--check-buffer)))
;;;###autoload
(defun flymake-ruff-load ()
"Load hook for the current buffer to tell flymake to run checker."
(interactive)
(when (derived-mode-p 'python-mode 'python-ts-mode)
(add-hook 'flymake-diagnostic-functions #'flymake-ruff--run-checker nil t)))
(add-hook 'python-ts-mode-hook 'flymake-ruff-load)