2010-04-08 11 views
9

Estoy usando Flymake en el código C#, emacs v22.2.1 en Windows.¿Las superposiciones/información sobre herramientas funcionan correctamente en Emacs para Windows?

Las cosas de Flymake han funcionado bien para mí. Para aquellos que no lo sepan, you can read an overview of flymake, pero la historia rápida es que flymake construye repetidamente el archivo de origen en el que está trabajando actualmente en segundo plano, con el propósito de hacer una comprobación de sintaxis. A continuación, resalta las advertencias y errores del compilador en el búfer actual.

Flymake no funcionó para C# inicialmente, pero I "monkey-patched it" and it works nicely now. Si edita C# en emacs, le recomiendo usar flymake.

El único problema que tengo es con la interfaz de usuario. Flymake resalta los errores y advertencias muy bien, y luego inserta "superposiciones" con información sobre herramientas que contiene el error completo o el texto de advertencia. Si coloco el puntero del mouse sobre la línea resaltada en el código, aparece la información sobre herramientas .

alt text http://i42.tinypic.com/qqu0ja.jpg

Pero como se puede ver, la superposición información sobre herramientas se recorta, y no se muestra correctamente.

Flymake parece estar haciendo lo correcto, es la parte de superposición que parece estar rota. , y la superposición parece hacer lo correcto. Es la información sobre herramientas que se muestra incorrectamente.

Do overlays tooltips funcionan correctamente en emacs para Windows?

¿Qué debo hacer para solucionarlo?


Después de algunas investigaciones, he encontrado que el efecto es demostrable con (tooltip-show really-long-string)

No tiene nada que ver con superposiciones, o flymake.

+0

Parece un error, es posible que desee 'M-x report-emacs-bug' –

+0

Después de leer sobre esto un poco más, supongo que el problema real no es con superposiciones, sino información sobre herramientas. – Cheeso

+0

tooltips de una sola línea parece que funcionan bien para mí (pase el mouse sobre un búfer en modo búfer, por ejemplo). El tuyo es multilínea, sospecho que es donde comienza a caer – Bahbar

Respuesta

8

Lo resolví con un defadvice en tooltip-show.

;; Reforms a single-line string ARG to a multi-line string with a max 
;; of LIMIT chars on a line. 
;; 
;; This is intended to solve a problem with the display of tooltip text 
;; in emacs on Win32 - which is that the tooltip is extended to be very very 
;; long, and the final line is clipped. 
;; 
;; The solution is to split the text into multiple lines, and to add a 
;; trailing newline to trick the tooltip logic into doing the right thing. 
;; 
(defun cheeso-reform-string (limit arg) 
    (let ((orig arg) (modified "") (curline "") word 
     (words (split-string arg " "))) 
    (while words 
     (progn 
     (setq curline "") 
     (while (and words (< (length curline) limit)) 
      (progn 
      (setq word (car words)) 
      (setq words (cdr words)) 
      (setq curline (concat curline " " word)))) 
     (setq modified (concat modified curline "\n")))) 
    (setq modified (concat modified " \n"))) 
) 

(defadvice tooltip-show (before 
         flymake-csharp-fixup-tooltip 
         (arg &optional use-echo-area) 
         activate compile) 
    (progn 
    (if (and (not use-echo-area) 
      (eq major-mode 'csharp-mode)) 
     (let ((orig (ad-get-arg 0))) 
      (ad-set-arg 0 (cheeso-reform-string 72 orig)) 
     )))) 

resultado:

alt text http://i41.tinypic.com/1zoylg8.jpg

0

El verdadero objetivo que tenía, al estar manejando estas cosas flymake, era conseguir un menú de opciones "solución rápida" para que aparezca cuando flymake muestra los errores . Visual Studio hace esto si haces clic en ALT-Shift-F10, o algo así.

Y, lo tengo para trabajar, en algunos escenarios básicos. Aquí está la experiencia del usuario:

Paso 1: escriba el código con una referencia de tipo no resuelto, en este caso, Stream. banderas Flymake el problema, de esta manera:

alt text http://i41.tinypic.com/8xo29t.jpg

Paso 2: ejecutar el menú de error flymake través (flymake-display-err-menu-for-current-line)

alt text http://i40.tinypic.com/mwryw0.jpg

Paso 3: Seleccionar la opción de menú, y la solución rápida es aplicado automáticamente

alt text http://i39.tinypic.com/w1z4n5.jpg


Me dispuesto para proporcionar opciones "solución rápida" para algunos casos especiales: CS0246

  • de error: El tipo o espacio de nombres 'xxxx' no se pudo encontrar
  • error CS1002: punto y coma esperado
  • error CS0103: El nombre "identificador" no existe en el contexto actual.

El truco fue, de nuevo, un consejo. Esta vez en el flymake-make-emacs-menu fn. Esa función dentro de flymake prepara la estructura de datos que se pasa directamente al x-popup-menu. El consejo (consejo "después") analiza la lista de errores, busca los códigos de error conocidos, y si se encuentra, "parches de mono" en el menú emergente, para insertar opciones para corregir el error.

;; The flymake-make-emacs-menu function prepares the menu for display in 
;; x-popup-menu. But the menu from flymake is really just a static list 
;; of errors. Clicking on any of the items, does nothing. This advice 
;; re-jiggers the menu structure to add dynamic actions into the menu, 
;; for some error cases. For example, with an unrecognized type error 
;; (CS0246), this fn injects a submenu item that when clicked, will 
;; insert a using statement into the top of the file. Other errors are 
;; also handled. 
;; 
;; This won't work generally. It required some changes to flymake.el, 
;; so that flymake-goto-next-error would go to the line AND column. The 
;; original flymake only goes to the line, not the column. Therefore, 
;; quickfixes like inserting a semicolon or a namespace in front of a 
;; typename, won't work because the position is off. 
;; 
(defadvice flymake-make-emacs-menu (after 
            flymake-csharp-offer-quickfix-menu 
            () 
            activate compile) 
    (let* ((menu ad-return-value) 
     (title (car menu)) 
     (items (cadr menu)) 
     action 
     new-items 
     ) 

    (setq new-items (mapcar 
        '(lambda (x) 
         (let ((msg (car x)) missing-type namespace m2 m3) 
          (cond ((or (string-match "error CS0246:" msg) 
            (string-match "error CS0103:" msg)) 

           (progn 
            (string-match "^\\(.+'\\([^']+\\)'[^(]+\\)" msg) 
            (setq missing-type (substring msg 
                   (match-beginning 2) 
                   (match-end 2))) 

            ;; trim the message to get rid of the (did you forget to ...?) 
            (setq msg 
             (substring msg 
                (match-beginning 1) 
                (match-end 1))) 
            (setq namespace (csharp-get-namespace-for-type missing-type)) 
            (if namespace 
             ;; the namespace was found 
             (progn 
             (setq m2 (concat "insert using " namespace ";")) 
             (setq m3 (concat namespace "." missing-type)) 
             (list msg 
               (list m2 'csharp-insert-using-clause-for-type missing-type) 
               (list m3 'csharp-insert-fully-qualified-type namespace) 
               (list "resolve this type reference manually"))) 
            ;; couldn't find the namespace; maybe it's just a typo 
            (list msg 
              (list "resolve this type reference manually"))))) 

           ;; missing semicolon 
           ((string-match "error CS1002:" msg) 
           (progn 
            (list msg 
              (list "insert ; " 'insert ";")) 
            )) 

           ;; all other cases 
           (t 
           ;; no quick fixes for this error 
           (list msg 
             (list "resolve this error manually")))))) 
        (cdr items))) 

    ;; If there's only one menu item, it sometimes won't display 
    ;; properly. The main error message is hidden, and the submenu 
    ;; items become the menu items. I don't know why. Appending a list 
    ;; of ("" nil) to the end, insures that the menu will display 
    ;; properly. 
    (setq new-items (append new-items (list (list "" nil)))) 

    ;; finally, set the return value 
    (setq ad-return-value (cons title new-items)) 

    ;; (setq ad-return-value (list title 
    ;;        (list "item1" (list "choice 1.A" 1) (list "choice 1.B" 2)) 
    ;;        (list "item2" (list "choice 2.A" 3) (list "choice 2.B" 4)) 
    ;;        (list "item3") 
    ;;       )) 

    )) 

El "inserto usando" fijar también depende de una capacidad de búsqueda, que resuelve un nombre de tipo corto, como Stream a un nombre de tipo totalmente cualificado, como System.IO.Stream. Ese es un problema aparte.

Si el usuario selecciona la opción de menú para aplicar la solución rápida, se ejecuta un fn para insertar un nuevo "uso" cláusula:

(defun csharp-insert-using-clause (namespace) 
    "inserts a new using clause, for the given namespace" 
    (interactive "sInsert using clause; Namespace: ") 
    (save-excursion 
    (let ((beginning-of-last-using (re-search-backward "^[ \t]*using [^ ]+;"))) 
     (end-of-line) 
     (newline) 
     (insert (concat "using " namespace ";")) 
    ) 
) 
) 

Creo que esto podría ampliarse para manejar soluciones rápidas para otros tipos de errores Pero no sé cuáles podrían ser esos errores fáciles de corregir. Si alguien tiene alguna idea, o quiere ayudar, avíseme.

+1

Por favor, por favor, si va a compartir el formato de código lisp, como el código lisp. Trailing ")" en líneas por sí mismos realmente distraen y hacen que el código de lisp sea más difícil de leer. –

+0

Eso es gracioso, hace que sea más fácil de leer para mí. ¿Existe realmente un formato estándar para lisp? – Cheeso

Cuestiones relacionadas