Subject: bug#32536: displayed width of man pages

From: Juri Linkov <[email-masked]>
Date: Mon, 03 Sep 2018 01:19:19 +0300

>> Regarding the request for dynamic reformatting, I'm not sure if
>> man pages should be reformatted on resizing windows (I remember
>> seeing a window resize hook, but can't find it now).
>
> It's called 'window-size-change-functions'.

Thanks, I tried window-size-change-functions, and it works pretty well
with the patch attached.  But there are a few problems:

1. In Man-mode we have to add hook window-size-change-functions only
   buffer-locally (using the arg LOCAL of add-hook) rather than globally,
   because otherwise we can't remove this hook when a Man buffer is
   not displayed anymore.  But the problem is that buffer-local
   window-size-change-functions is called only when the current buffer
   is in Man-mode.  If it's not, it's not called even when resizing of
   the current non-Man buffer causes the resize of a Man-mode buffer
   in an adjacent window.

2. What if the same Man-mode buffer is displayed in two adjacent windows
   side-by-side?  I guess we need to find all windows with the same buffer,
   compare their widths, and call Man-update-manpage only in the window
   with minimal width.  Also it seems window-size-change-functions is
   not called twice for every window with Man-mode buffer, this is good.

3. When windows are resized using the mouse, is it possible to call
   window-size-change-functions only when the mouse button is released?
   This will increase responsiveness.  But the same problem will remain
   for keyboard resizing with e.g. C-x } } }
   A debounce-like function could help, but I can't find its Emacs Lisp
   implementation anywhere.   I mean something similar to
   https://stackoverflow.com/questions/15927371/what-does-debounce-do
   It's easy to implement using timers, but better to have idiomatic
   implementation.

diff --git a/lisp/man.el b/lisp/man.el
index 1a6eda13b7..f737594de7 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1524,7 +1537,17 @@ Man-mode
   (set (make-local-variable 'outline-regexp) Man-heading-regexp)
   (set (make-local-variable 'outline-level) (lambda () 1))
   (set (make-local-variable 'bookmark-make-record-function)
-       'Man-bookmark-make-record))
+       'Man-bookmark-make-record)
+  (add-hook 'window-size-change-functions 'Man-window-size-change nil t))
+
+(defun Man-window-size-change (frame)
+  (walk-windows (lambda (window)
+                  (when (/= (window-pixel-width-before-size-change window)
+                            (window-pixel-width window))
+                    (with-current-buffer (window-buffer window)
+                      (when (derived-mode-p 'Man-mode)
+                        (Man-update-manpage)))))
+                'nomini frame))
 
 (defun Man-build-section-list ()
   "Build the list of manpage sections."