Правильно ли работают оверлеи / подсказки в Emacs для Windows? - PullRequest
9 голосов
/ 08 апреля 2010

Я использую Flymake для кода C #, emacs v22.2.1 для Windows.

Материал Flymake работал хорошо для меня. Для тех, кто не знает, вы можете прочитать обзор flymake , но краткая история заключается в том, что flymake неоднократно создает исходный файл, над которым вы сейчас работаете, в фоновом режиме, с целью проверки синтаксиса. , Затем он выделяет предупреждения компилятора и ошибки в текущем буфере.

Изначально Flymake не работал на C #, но Я "залатал обезьяну", и теперь она прекрасно работает . Если вы редактируете C # в emacs, я настоятельно рекомендую использовать flymake.

Единственная проблема, с которой я столкнулся - это пользовательский интерфейс. Flymake хорошо выделяет ошибки и предупреждения, а затем вставляет «оверлеи» с подсказками, содержащими полный текст ошибки или предупреждения. Если я наведу указатель мыши на выделенную строку в коде, появится всплывающая подсказка overlay .

альтернативный текст http://i42.tinypic.com/qqu0ja.jpg

Но, как вы можете видеть, всплывающая подсказка overlay обрезана и не отображается правильно.

Flymake, кажется, делает правильные вещи, это часть наложения, которая кажется сломанной. , и наложение, кажется, делает правильные вещи. Это подсказка, которая отображается неправильно.

Работают ли оверлеи всплывающие подсказки правильно в emacs для Windows?

Где я могу это исправить?


После некоторых исследований я обнаружил, что эффект проявляется при (tooltip-show really-long-string)

Это не имеет ничего общего с оверлеями или мухой.

Ответы [ 2 ]

8 голосов
/ 08 апреля 2010

Я решил это с помощью defadvice на всплывающей подсказке.

;; 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))
          ))))

результат:

альтернативный текст http://i41.tinypic.com/1zoylg8.jpg

0 голосов
/ 09 апреля 2010

Реальная цель, которую я преследовал, когда возился с этим мухомором, состояла в том, чтобы получить меню опций «быстрого исправления», которые появляются, когда мухи показывает ошибки. Visual Studio делает это, если вы нажимаете ALT-Shift-F10 или что-то в этом роде.

И я получил его на работу, в некоторых основных сценариях. Вот пользовательский опыт:

Шаг 1: написать код с неразрешенной ссылкой на тип - в данном случае Stream. Flymake помечает проблему следующим образом:

альтернативный текст http://i41.tinypic.com/8xo29t.jpg

Шаг 2: Откройте меню ошибки flymake с помощью (flymake-display-err-menu-for-current-line)

альтернативный текст http://i40.tinypic.com/mwryw0.jpg

Шаг 3: выберите пункт меню, и быстрое исправление будет применено автоматически.

альтернативный текст http://i39.tinypic.com/w1z4n5.jpg


Я решил предоставить опции «быстрого исправления» для нескольких особых случаев:

  • ошибка CS0246: тип или пространство имен 'xxxx' не найдено
  • ошибка CS1002: ожидается точка с запятой
  • ошибка CS0103: имя «идентификатор» не существует в текущем контексте.

Трюк, опять же, совет. На этот раз на flymake-make-emacs-menu фн. Эта функция внутри flymake подготавливает структуру данных, которая передается непосредственно в x-popup-menu. Рекомендация («после») анализирует список ошибок, ищет известные коды ошибок и, если найдено, «обезьяна исправляет» всплывающее меню, чтобы вставить параметры для исправления ошибки.

;; 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")
    ;;                             ))

    ))

Исправление «вставить с помощью» также зависит от возможности поиска, которая разрешает короткое имя типа, например, Stream, в полное имя типа, например, System.IO.Stream. Это отдельная проблема.

Если пользователь выбирает пункт меню, чтобы применить быстрое исправление, он запускает команду fn для вставки нового предложения «using»:

(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 ";"))
    )
  )
)

Я думаю, что это может быть расширено для быстрого исправления других типов ошибок. Но я не знаю, что это за ошибки, которые легко исправить. Если у кого-то есть какие-либо идеи или желание помочь, дайте мне знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...