3

I switched to Emacs from Vim and because of Vims functionality of giving keys a prefix, (for example to jump up several lines etc.) i installed relative-linum-mode right away.

Now i found out about Emacs native functionality of jumping to a specific line with M-g M-g (and passing the line number in the minibuffer; the function is called goto-line) and find that much more useful than giving a prefix to C-n or C-p, which is of course not a functionality exclusive to Vim, but i found that to be too tedious in Emacs after all... Maybe i just didn't get used to it.

Now my idea is to have line numbers deactivated most of the time because i find that to look a lot cleaner, but when i press M-g M-g to activate linum-mode, passing the desired line number and after pressing enter and jumping to that line to deactivate linum-mode

Can i bind that to M-g M-g somehow? I know how to rebind keys but i can't figure out how (and if) my desired behavior is possible!

Tim Hilt
  • 297
  • 1
  • 11

2 Answers2

3

Here you go:

(global-set-key [remap goto-line] #'my-goto-line)

(defvar my-temp-linum-mode-sym
  (if (fboundp 'display-line-numbers-mode)
      'display-line-numbers-mode
    'linum-mode)
  "Use `display-line-numbers-mode' if it's available; `linum-mode' otherwise.")

(defun my-goto-line (line &optional buffer)
  "`goto-line' with temporary line-numbering."
  (interactive
   (let ((my-temp-linum-buffer
          ;; Use the same prefix-arg behaviour as `goto-line'.
          (if current-prefix-arg
              (other-buffer (current-buffer) t)
            (current-buffer))))
     ;; If line numbering is currently enabled in that buffer, then we
     ;; want to leave it alone.
     (when (with-current-buffer my-temp-linum-buffer
             (and (boundp my-temp-linum-mode-sym)
                  (symbol-value my-temp-linum-mode-sym)))
       (setq my-temp-linum-buffer nil))
     ;; Prompt the user for the line number, using the interactive
     ;; form from `goto-line'.  Line numbering will be enabled and
     ;; then disabled again during this procedure.
     (eval (cadr (interactive-form 'goto-line)))))
  ;; Pass the line and buffer arguments to `goto-line'.
  (goto-line line buffer))

(defun my-temp-linum-set-state (arg)
  "Enable or disable line numbering."
  (and (bound-and-true-p my-temp-linum-buffer)
       (buffer-live-p my-temp-linum-buffer)
       (with-current-buffer my-temp-linum-buffer
         ;; Call the specified mode function.
         (funcall my-temp-linum-mode-sym arg))))

(defun my-temp-linum-enable-maybe ()
  (my-temp-linum-set-state 1))

(defun my-temp-linum-disable-maybe ()
  (my-temp-linum-set-state -1))

(add-hook 'minibuffer-setup-hook #'my-temp-linum-enable-maybe)
(add-hook 'minibuffer-exit-hook #'my-temp-linum-disable-maybe)
phils
  • 48,657
  • 3
  • 76
  • 115
  • Wow that was quick! I didn't expect such an answer in this small amount of time and honestly, i wouldn't have gotten something similar on my own. Thank you! – Tim Hilt Sep 26 '18 at 09:20
  • You're welcome. It seemed like a fun problem to solve. I've added some more comments to the code to explain what it's doing. – phils Sep 26 '18 at 09:21
0

Here a function that I have been using for a long time and recently modified to work without linum-mode since emacs 26.1 came with its own display-line-numbers-mode. You can bind it to any keys you want.

  ;; emacs-version 26.1
  (defun goto-line-with-feedback ()
    "Show line numbers temporarily when prompting for the line number to go to."
    (interactive)
    (unwind-protect
        (progn
          (display-line-numbers-mode)
          (goto-line (read-number "Goto line: ")))
      (display-line-numbers-mode 0)))
Heikki
  • 2,961
  • 11
  • 18