3

I want to delight narrow-to-region. When I call org-toggle-narrow-to-subtree it calls org-narrow-to-subtree which calls narrow-to-region. When this is called the modeline shows "Narrow". Is there a way to delight that? I would like to replace that with a unicode character, which I did with minor modes. Help tells me that narrow-to-region is a c function an not lisp. Does this mean no delighting possible?

phils
  • 48,657
  • 3
  • 76
  • 115
Jens Lange
  • 463
  • 2
  • 13

2 Answers2

2

No, delight can't affect the appearance of "Narrow" in the mode line, because it is not a mode name/lighter (despite appearing in the same section of the mode line).

Only major mode names and minor mode lighter text can be Delighted.

The mode line syntax %n is what produces the word "Narrow" (when appropriate), and that appears in the mode-line-modes variable -- which is one of the components of the overall C-hv mode-line-format (see which) -- following the list of minor modes. The string " Narrow" is hard-coded in the C code for formatting the mode line.

Your options are probably:

  • Remove the %n entirely (and optionally add a custom replacement).
  • Do some post-processing of the formatted mode line to search and replace the text " Narrow"

For the latter, I have a feeling that one of the alternatives to delight works by performing the user's desired search/replacements on the formatted mode line whenever it is rendered, but I can't recall the name of that library.

For the former, you could use something like the following, to replace the "%n" in mode-line-modes with the following mode line construct:

(:eval (when (buffer-narrowed-p) " <N>"))

That's necessarily less efficient than the C code, but I can't imagine it being noticeable.

;; Replace "Narrow" with "<N>" in mode line, when narrowed.
(defvar my-mode-line-narrowed " <N>"
  "Appears in the mode line when the buffer is narrowed.")
(catch 'done
  (let ((x mode-line-modes))
    (while x
      (when (and (stringp (car x)) (string= (car x) "%n"))
        (setcar x '(:eval (when (buffer-narrowed-p) my-mode-line-narrowed)))
        (throw 'done t))
      (setq x (cdr x)))))

You can then M-: (setq my-mode-line-narrowed "foo") RET to play with different indicators.

phils
  • 48,657
  • 3
  • 76
  • 115
1

Similar to @phils's answer, but skipping the explaining, which he's done well.

(defun remove-Narrow-lighter ()
  "Remove `Narrow' lighter from mode line."
  (let ((%n-cons  (regexp-car-member "%n\\(.*\\)\\'" mode-line-modes)))
    (when %n-cons (setcar %n-cons ""))))

(defun regexp-car-member (regexp xs)
  "Like `member', but tests by matching REGEXP against cars."
  (and (consp xs)  (if (and (stringp (car xs))  (string-match-p regexp (car xs)))
                       xs
                     (regexp-car-member regexp (cdr xs)))))

I do something similar to this in zones.el, but to change the narrowing lighter to reflect the current narrowing (zone), not to remove it altogether.

(FWIW, I don't recommend removing this lighter altogether, as it's usually important to know when the buffer is narrowed.)

Drew
  • 75,699
  • 9
  • 109
  • 225