fix an auto-complete-mode and linum-mode annoyance

2020-02-26 08:29发布

问题:

I'm using auto-complete-mode which I think is totally fantastic. I'm also a big fan of linum-mode but I've got a very irritating issue when the two are used together, especially when I'm working in a new buffer (or a buffer with very few lines).

Basically the buffer is 'x' lines long but when auto-complete kicks in it "adds" lines to the buffer, so linum-mode keeps switching, for example, between displaying line numbers on one column or two columns, depending on whether auto-complete is suggesting a completion or not.

So you type a sentence and you see your buffer's content frantically shifting from left to right at every keypress. It is really annoying.

I take it the solution involves configuring the linum-format variable but I don't know how.

Ideally it would be great if my linum-format was:

  • dynamic
  • right-aligned
  • considering there are 'y' more lines to the buffer than what the buffer actually has

My rationale being that auto-complete shall not suggest more than 'y' suggestion and that, hence, the two shall start playing nicely together.

For example, if 'y' is set to 20 and my buffer has 75 lines, then linum should use two columns: because no matter where I am auto-complete shall not make the buffer 'bigger' than 99 lines.

On the contrary, if 'y' is still set to 20 and my buffer has 95 lines, then linum should use three columns because otherwise if I'm near the end of the buffer and auto-complete kicks in my buffer shall start "wobbling" left and right when I type.

I'd rather not hardcode "3 columns wide" for linum.

I guess using "dynamic but always at least two columns" would somehow fix most annoyances but still something as I described would be great.

P.S: I realize that my 'fix' would imply that linum would always display on at least two columns, and I'm fine with that... As long as it stays right-aligned and use 2, 3 or 4 columns depending on the need.

回答1:

Simply put the following line in .emacs which resolves this issue. It is in auto-complete.el.

(ac-linum-workaround)


回答2:

I've written a couple of previous answers on modifying the linum-mode output, which you could probably adapt to your purposes.

  • Relative Line Numbers In Emacs
  • Colorize current line number

Edit: Here's the most basic version of that code (also on EmacsWiki, albeit somewhat buried), which doesn't modify the default output at all, but uses the techniques from those other answers to be more efficient than the default code. That's probably a more useful starting point for you.

(defvar my-linum-format-string "%4d")

(add-hook 'linum-before-numbering-hook 'my-linum-get-format-string)

(defun my-linum-get-format-string ()
  (let* ((width (length (number-to-string
                         (count-lines (point-min) (point-max)))))
         (format (concat "%" (number-to-string width) "d")))
    (setq my-linum-format-string format)))

(setq linum-format 'my-linum-format)

(defun my-linum-format (line-number)
  (propertize (format my-linum-format-string line-number) 'face 'linum))


回答3:

Just have the same problem, after seeing 'patching the source' I believe it could be done with advice. Here is what I come up with

(defadvice linum-update
  (around tung/suppress-linum-update-when-popup activate)
  (unless (ac-menu-live-p)
    ad-do-it))

I would like to use popup-live-p as mentioned but unfortunately it requires the variable for the popup, which we couldn't know in advance.



回答4:

Update: I ended up patching the source for linum.el. I added an extra hook that runs before updates.

Here's the patched file: linum.el (github)

Here's the code I have in my init.el:

;; Load custom linum.
(load-file "~/.emacs.d/linum.el")

;; Suppress line number updates while auto-complete window
;; is displayed.
(add-hook 'linum-before-update-hook
          '(lambda ()
             (when auto-complete-mode
               (if (ac-menu-live-p)
                   (setq linum-suppress-updates t)
                 (setq linum-suppress-updates nil)))))

Hope it helps!