2011-06-27 3 views
2

J'ai donc un outil lints changements python que j'ai fait et produit des erreurs et des avertissements. Je voudrais que ce soit utilisable en mode compilation avec Emacs, mais j'ai un problème. Le nom du fichier est sorti une seule fois au début, puis seuls les numéros de ligne apparaissent avec les erreurs et les avertissements. Voici un exemple:Emacs regex en mode de compilation pour plusieurs lignes

Linting file.py 
E0602: 37: Undefined variable 'foo' 
C6003: 42: Unnecessary parens after 'print' keyword 
2 new errors, 2 total errors in file.py. 

Il est très similaire à pylint, mais il n'y a pas de sortie format option = analysable. J'ai vérifié la documentation pour la compilation-error-regexp-alist et trouvé quelque chose prometteur:

If FILE, LINE or COLUMN are nil or that index didn't match, that
information is not present on the matched line. In that case the
file name is assumed to be the same as the previous one in the
buffer, line number defaults to 1 and column defaults to
beginning of line's indentation.

J'essayé d'écrire une expression rationnelle qui en option correspondre à la ligne de fichiers et tirez dans un groupe, puis le reste correspondrait aux autres lignes. J'ai supposé qu'il serait d'abord correspondre

Linting file.py 
E0602: 37: Undefined variable 'foo' 

et être bien. Ensuite, il continuerait et correspondrait

C6003: 42: Unnecessary parens after 'print' keyword 

sans fichier. Comme il n'y avait pas de fichier, il devrait utiliser le nom de fichier du match précédent à droite? Voici le regexp J'utilise:

(add-to-list 'compilation-error-regexp-alist 'special-lint) 
(add-to-list 'compilation-error-regexp-alist-alist 
     '(special-lint 
      "\\(Linting \\(.*\\)\\n\\)?\\([[:upper:]][[:digit:]]+:\\s-+\\([[:digit:]]\\)+\\).*" 
      2 4 nil nil 3)) 

Je l'ai vérifié avec re-constructeur et manuellement dans la mémoire tampon de zéro. Il se comporte comme prévu. le 2ème groupe est le nom du fichier, le 4ème est le numéro de ligne, et le 3ème est ce que je veux mettre en surbrillance. Chaque fois que j'essaie, j'obtenir l'erreur:

signal(error ("No match 2 in highlight (2 compilation-error-face)")) 

J'ai une solution pour ce qui consiste à transformer la sortie avant que le module de compilation regarde, mais je préfère se débarrasser de cela et avoir une " pure "solution". J'apprécierais n'importe quel conseil ou signaler toutes les erreurs stupides que j'ai pu avoir faites.

EDIT

code pseudo Thomas a travaillé très bien en dessous. Il a mentionné que faire une recherche en arrière pourrait gâcher les données de match, et il a fait. Mais cela a été résolu en ajoutant le formulaire spécial save-match-data avant save-excursion.

Répondre

3

FILE can also have the form (FILE FORMAT...), where the FORMATs (e.g. "%s.c") will be applied in turn to the recognized file name, until a file of that name is found. Or FILE can also be a function that returns (FILENAME) or (RELATIVE-FILENAME . DIRNAME). In the former case, FILENAME may be relative or absolute.

Vous pouvez essayer d'écrire une expression régulière qui ne correspond pas au nom de fichier du tout, seule la colonne. Ensuite, pour le fichier, écrivez une fonction qui recherche en arrière le fichier. Peut-être pas aussi efficace, mais il devrait avoir l'avantage que vous pouvez vous déplacer vers le haut à travers les messages d'erreur et il identifiera toujours le bon fichier lorsque vous traversez les limites de fichiers.

Je n'ai pas les choses nécessaires installé pour essayer, mais prendre le pseudo-code suivant comme une source d'inspiration:

(add-to-list 'compilation-error-regexp-alist-alist 
     '(special-lint 
      "^\\S-+\\s-+\\([0-9]+\\):.*" ;; is .* necessary? 
      'special-lint-backward-search-filename 1)) 

(defun special-lint-backward-search-filename() 
    (save-excursion 
    (when (re-search-backward "^Linting \\(.*\\)$" (point-min) t) 
     (list (match-string 1))))) 

(Il se pourrait que l'aide d'une fonction de recherche à l'intérieur special-lint-backward-search-filename va bousiller le sous-groupe correspondant de l'expression-erreur-regexp, qui serait nul.)

+0

Je joue avec ça en ce moment, et ça semble prometteur. Merci. J'ai quelques problèmes, et c'est peut-être la recherche qui gâche les groupes. Je vous le ferai savoir quand je le découvrirai d'une façon ou d'une autre. –

0

Je ne pense pas que vous puissiez faire que la compilation fasse ce que vous voulez ici, car elle ne supposera pas qu'une erreur ultérieure se rapporte à un nom de fichier précédemment vu. Mais voici une alternative; écrivez un plugin flymake. Flymake fonctionne toujours sur le fichier en cours, vous n'avez donc qu'à lui indiquer comment trouver les numéros de ligne (et, facultativement, de colonne).

Essayez de pirater something like this, et vous serez probablement agréablement surpris.

+0

Cet outil ne fonctionne cependant pas sur un seul fichier. Il s'intègre à mon VCS et ne travaille que sur mes changements. J'ai quelque chose pour flymake et je l'aime, mais cet outil a un but différent que je voudrais utiliser. –