lewang / ws-butler

Unobtrusively trim extraneous white-space *ONLY* in lines edited.
248 stars 29 forks source link

ws-butler with desktop-save-mode and emacs --daemon #14

Closed anirothan closed 9 years ago

anirothan commented 9 years ago

The combination of using emacs daemon, with desktop-saved buffers that had ws-butler minor mode enabled causes the emacs daemon to hang when trying to restore these buffers.

This is related to issues: https://github.com/lewang/ws-butler/issues/12 and https://github.com/lewang/ws-butler/issues/4 but none offered a solution for me.

I have manage to create a workaround by doing two things:

i) Configure desktop-save-mode to ignore ws-butler mode and the highlight-changes-mode that it is based on.

;;
;; enable desktop-save
(desktop-save-mode t)
;;
;; disable saving/reloading of ws-butler-mode and highlight-changes
(delete 'highlight-changes-mode desktop-minor-mode-handlers)
(add-to-list 'desktop-minor-mode-handlers '(highlight-changes-mode . nil) t)
(add-to-list 'desktop-minor-mode-handlers '(ws-butler-mode . nil) t)
(add-to-list 'desktop-minor-mode-table '(highlight-changes-mode nil) t)
(add-to-list 'desktop-minor-mode-table '(ws-butler-mode nil) t)

This is not enough. Enabling ws-butler-global-mode or using hooks of other modes to enable ws-butler in the standard way sill causes the emacs daemon to hang on startup.

ii). Enable ws-butler-mode in the after-make-frame-functions hook. If you want ws-butler-mode enabled globally then this is easy:

(defun jd/enable-ws-butler-global (frame)
  (ws-butler-global-mode))
(add-hook 'after-make-frame-functions 'jd/enable-ws-butler-global)

This will enable ws-butler eveywhere every time a new frame is created.

However, if you want ws-butler to be enabled for certain modes via mode-hooks, say just for c-mode, then it's tricky. The related files, e.g. of c-mode, are already loaded on daemon startup by dekstop-save-mode and their hooks have already executed. To get around this, we need to register the hooks and revert all buffers (that have a file) only on the first created frame.

;;
;; ws-buttler setup
(defun jd/setup-ws-butler-hooks ()
  "Register hooks to enable ws-buttler"
  (require 'ws-butler)
  (add-hook 'prog-mode-hook 'ws-butler-mode)
  (add-hook 'c-mode-common-hook 'ws-butler-mode)
  (add-hook 'text-mode 'ws-butler-mode)
  (add-hook 'fundamental-mode 'ws-butler-mode))
;;
;; workaround on ws-butler inhibit emacs daemon startup
(setq jd/frame-rendered-flag nil)
;;
;; revert buffers in frame so that hooks re-run
(defun jd/revert-buffers-in-frame-and-reload-modes (frame)
  "Refreshes all open buffers from their respective files in the given frame, reloading any modes."
  (dolist (buf (buffer-list frame))
    (with-current-buffer buf
      (when (and (buffer-file-name) (file-exists-p (buffer-file-name)) (not (buffer-modified-p)))
        (revert-buffer t t nil)
        (message "Reloading file %s" (buffer-file-name))))))
;;
;; if flag not set, register hooks for ws-butler, revert buffers
(defun jd/enable-ws-butler (frame)
  (unless jd/frame-rendered-flag
    (jd/setup-ws-butler-hooks)
    (jd/revert-buffers-in-frame-and-reload-modes frame)
    (setq jd/frame-rendered-flag t))) 

(add-hook 'after-make-frame-functions 'jd/enable-ws-butler)

It seems to me that, the problem of using ws-butler with emacs --daemon and desktop-save-mode is due to ws-buttler or one of its dependencies really really wanting X11 to be present, which at the startup of emacs --daemon is not. This means we have to go through all this pain to make it work.

Can the developers investigate if the issue is due to ws-butler and fix it, or point to suspected dependecy packages, e.g. highlight-changes-mode?

lewang commented 9 years ago

Can you check this version that removes highlight-changes-mode dependency? https://github.com/lewang/ws-butler/tree/remove-highlight-changes-mode/

anirothan commented 9 years ago

I've just tested it and can confirm it works out of the box. No need for workarounds. Is there any functionality lost in this branch?

lewang commented 9 years ago

No. In fact (hopefully) there is a gain of functionality - it now works better with killing+undo.

I started piggybacking on highlight-changes as a proof of concept, and it turned out to be good enough for the common case. This is a better implementation .

Closing now.