2

I'm helping a visually impaired user make viewing documentation in Emacs easier. He sets his font size such that he has about 40 columns of text in a full-screen frame with no splits (and he has configured Emacs never to split the window). At that size, line-wrapping (either the default or visual-line-mode) results in awkward gaps that make the text more difficult to read. Setting and appropriate fill-column and running fill-paragraph results in much more readable formatting, and so I tried to write some functions to do this automatically.

;; function to set the fill
(defun my-auto-set-fill-column ()
  "Always set fill-column to window width."
  (let ((inhibit-message 1)
        (width (/ (window-body-width nil t)
                     (window-font-width))))
    (set-fill-column width)
    (set-default 'fill-column width)))

this utility seems pretty straight-forward, but I'm happy for any suggested improvements.

 Function to format help pages.
;; You can call this with `M-x
;; my-format-doc-width' if you find
;; a help page that has wrapped
;; badly. With the hook below this
;; should be automatic.
(defun my-format-doc-width ()
  "Format documentation to window width."
  (interactive)
  (with-selected-window
      (get-buffer-window "*Help*")
    (read-only-mode -1)
    (my-auto-set-fill-column)
    (mark-whole-buffer)
    (call-interactively 'fill-region)
    (read-only-mode 1)))

I think this is also straight-forward, but happy for any suggestions.

(add-hook 'help-mode-hook
          '(lambda()
             (run-at-time
              (if (get-buffer-window "*Help*")
                  0 0.5) nil
              'my-format-doc-width)))

This feels pretty bad. Since the hook apparently runs before the window is actually created I have to put it on a timer. But of course I don't want to wait if the *Help* window exists already... Again, suggestions are welcome.

As you can see, my Emacs lisp is not strong and I suspect there are some obvious improvements that could be made to the implementation. More fundamentally, is this a reasonable general approach, or is there a better way to go about it? Something like (setq help-buffer-reformat-automagic 1) that I missed?

Ista
  • 1,148
  • 8
  • 12

2 Answers2

2

temp-buffer-show-hook should help. That's where help-mode-finish is called, for instance. It is used in with-help-window and with-temp-buffer-window, which are used to display Help windows.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Thanks, this does help. I couldn't get it to work directly, but it led me to `help-mode-finish`. In the end I advised this function and it works well. – Ista May 24 '18 at 01:29
1

Based on @Drew's answer, I ended up doing this:

;; function to get window width
(defun my-get-window-width ()
  "Get width of current window in."
  (/ (window-body-width nil t)
     (window-font-width)))

;; function to set the fill column
(defun my-auto-set-fill-column ()
  "Set fill-column to window width."
  (let ((inhibit-message 1))
    (set-fill-column
     (my-get-window-width))))

(set-default 'fill-column
             (my-get-window-width))

;; Function to format help pages.
;; With the hook below this
;; should be automatic.
(defun my-fill-buffer ()
  "Fill to window width."
  (interactive)
    (read-only-mode -1)
    (my-auto-set-fill-column)
    (mark-whole-buffer)
    (call-interactively 'fill-region)
    (read-only-mode 1))

(advice-add
 'help-mode-finish
 :after
 #'my-fill-buffer)

It works well and avoids the run-at-time kludge.

Ista
  • 1,148
  • 8
  • 12