Reworked example to make it work (partially).
There are following issues that prevent @lunaryorn's example from working
- double activating the popup-draw advice would cause
my-prev-whitespace-mode
to lose stored information
- activating the popup-delete advice before popup-draw would just switch-off whitespace mode because default value for
my-prev-whitespace-mode
is nil.
So I evolve the original workaround further to address the two difficulties.
(defun my:force-modes (rule-mode &rest modes)
"switch on/off several modes depending of state of
the controlling minor mode
"
(let ((rule-state (if rule-mode 1 -1)
))
(mapcar (lambda (k) (funcall k rule-state)) modes)
)
)
(require 'whitespace)
(defvar my:prev-whitespace-mode nil)
(make-variable-buffer-local 'my:prev-whitespace-mode)
(defvar my:prev-whitespace-pushed nil)
(make-variable-buffer-local 'my:prev-whitespace-pushed)
(defun my:push-whitespace (&rest skip)
(if my:prev-whitespace-pushed () (progn
(setq my:prev-whitespace-mode whitespace-mode)
(setq my:prev-whitespace-pushed t)
(my:force-modes nil 'whitespace-mode)
))
)
(defun my:pop-whitespace (&rest skip)
(if my:prev-whitespace-pushed (progn
(setq my:prev-whitespace-pushed nil)
(my:force-modes my:prev-whitespace-mode 'whitespace-mode)
))
)
(require 'popup)
(advice-add 'popup-draw :before #'my:push-whitespace)
(advice-add 'popup-delete :after #'my:pop-whitespace)
This solution still has drawbacks. Whitespace-mode is disabled only when a menu is shown. While there is only single candidate for substitution the whitespace mode continues to disrupt screen.
The issue is most likely with bad choice for functions to dirty hack with advices. There should be more appropriate that are called exactly when disabling whitespace-mode is desirable. But no-one except the developer can name them.