Bad-ptr / persp-mode.el

named perspectives(set of buffers/window configs) for emacs
400 stars 44 forks source link

Bad interaction with olivetti-mode: 'Can not restore the window configuration' #74

Closed brendan-r closed 7 years ago

brendan-r commented 7 years ago

Firstly, thanks for all your work on persp-mode!

I've encountered a bad interaction with olivetti-mode. When using a perspective containing vertical splits, and with one or more buffers with olivetti-mode mode active, upon navigating away from, and then back to, the perspective, the window configuration is lost, with the error message:

[persp-mode] Warning: Can not restore the window configuration, because of the error -- (error Window #<window 3 on  *temp*> too small for splitting)

It looks like this has also come up for spacemacs users.

The author of olivetti mode has some ideas about what might be causing it, but doesn't have a good enough understanding of the internals of persp-mode to know how a fix might work. Any ideas about what's going on?

Bad-ptr commented 7 years ago

Try this:

(with-eval-after-load "olivetti"
  (with-eval-after-load "persp-mode"
    (defvar persp-split-window-preferred-function-backup nil)
    (add-hook 'persp-before-deactivate-functions
              #'(lambda (fow)
                  (when (fboundp 'olivetti-reset-all-windows)
                    (when (eq (current-buffer)
                              (variable-binding-locus
                               'split-window-preferred-function))
                      (setq persp-split-window-preferred-function-backup
                            (cons (current-buffer)
                                  split-window-preferred-function))
                      (remove-hook 'window-configuration-change-hook
                                   #'olivetti-set-environment t)
                      (setq-local split-window-preferred-function nil))
                    (olivetti-reset-all-windows))))
    (add-hook 'persp-activated-functions
              #'(lambda (fow)
                  (when persp-split-window-preferred-function-backup
                    (destructuring-bind (buf . swpf)
                        persp-split-window-preferred-function-backup
                      (with-current-buffer buf
                        (setq-local split-window-preferred-function
                                    swpf)
                        (add-hook 'window-configuration-change-hook
                                  #'olivetti-set-environment nil t)))
                    (setq persp-split-window-preferred-function-backup
                          nil))))))
Bad-ptr commented 7 years ago

More correct version(i think):

(with-eval-after-load "olivetti"
  (with-eval-after-load "persp-mode"
    (defvar persp-olivetti-buffers-backup nil)
    (add-hook 'persp-before-deactivate-functions
              #'(lambda (fow)
                  (dolist (b (mapcar #'window-buffer
                                     (window-list (selected-frame)
                                                  'no-minibuf)))
                    (with-current-buffer b
                      (when (eq 'olivetti-split-window-sensibly
                                split-window-preferred-function)
                        (push b persp-olivetti-buffers-backup)
                        (remove-hook 'window-configuration-change-hook
                                     #'olivetti-set-environment t)
                        (setq-local split-window-preferred-function nil)
                        (olivetti-reset-all-windows))))))
    (add-hook 'persp-activated-functions
              #'(lambda (fow)
                  (dolist (b persp-olivetti-buffers-backup)
                    (with-current-buffer b
                      (setq-local split-window-preferred-function
                                  'olivetti-split-window-sensibly)
                      (add-hook 'window-configuration-change-hook
                                #'olivetti-set-environment nil t)))
                  (setq persp-olivetti-buffers-backup nil)))))
brendan-r commented 7 years ago

Thanks for this, and sorry for the delay in responding. I'm afraid with the latter snippet active, when trying to create a new perspective (C-c C-p s) I get the error message Symbol's function definition is void: current-frame.

Bad-ptr commented 7 years ago

hmm... Can you M-x toggle-debug-on-error, try C-c C-p s again and if it errors -- post the contents of the *Backtrace* buffer here?

rnkn commented 7 years ago

Try replace current-frame with selected-frame.

Bad-ptr commented 7 years ago

replace current-frame with selected-frame

Really!

brendan-r commented 7 years ago

Sorry for the delay, here's the backtrace:

Debugger entered--Lisp error: (void-function current-frame)
  (current-frame)
  (window-list (current-frame) (quote no-minibuf))
  (mapcar (function window-buffer) (window-list (current-frame) (quote no-minibuf)))
  (let ((--dolist-tail-- (mapcar (function window-buffer) (window-list (current-frame) (quote no-minibuf)))) b) (while --dolist-tail-- (setq b (car --dolist-tail--)) (save-current-buffer (set-buffer b) (if (eq (quote olivetti-split-window-sensibly) split-window-preferred-function) (progn (setq persp-olivetti-buffers-backup (cons b persp-olivetti-buffers-backup)) (remove-hook (quote window-configuration-change-hook) (function olivetti-set-environment) t) (set (make-local-variable (quote split-window-preferred-function)) nil) (olivetti-reset-all-windows)))) (setq --dolist-tail-- (cdr --dolist-tail--))))
  (lambda (fow) (let ((--dolist-tail-- (mapcar (function window-buffer) (window-list (current-frame) (quote no-minibuf)))) b) (while --dolist-tail-- (setq b (car --dolist-tail--)) (save-current-buffer (set-buffer b) (if (eq (quote olivetti-split-window-sensibly) split-window-preferred-function) (progn (setq persp-olivetti-buffers-backup (cons b persp-olivetti-buffers-backup)) (remove-hook (quote window-configuration-change-hook) (function olivetti-set-environment) t) (set (make-local-variable ...) nil) (olivetti-reset-all-windows)))) (setq --dolist-tail-- (cdr --dolist-tail--)))))(frame)
  run-hook-with-args((lambda (fow) (let ((--dolist-tail-- (mapcar (function window-buffer) (window-list (current-frame) (quote no-minibuf)))) b) (while --dolist-tail-- (setq b (car --dolist-tail--)) (save-current-buffer (set-buffer b) (if (eq (quote olivetti-split-window-sensibly) split-window-preferred-function) (progn (setq persp-olivetti-buffers-backup (cons b persp-olivetti-buffers-backup)) (remove-hook (quote window-configuration-change-hook) (function olivetti-set-environment) t) (set (make-local-variable ...) nil) (olivetti-reset-all-windows)))) (setq --dolist-tail-- (cdr --dolist-tail--))))) frame)
  persp-activate([cl-struct-perspective "TODO" nil nil nil nil nil nil] #<frame emacs25@t440 0x1242690>)
  persp-frame-switch(nil)
  funcall-interactively(persp-frame-switch nil)
  call-interactively(persp-frame-switch nil nil)
  command-execute(persp-frame-switch)
rnkn commented 7 years ago

The backtrace is telling you that function current-Frame doesn't exist. The correct function is selected-frame (see above).

brendan-r commented 7 years ago

Hello both,

Sorry for the long delay. I'm afraid I could never see where I was supposed to replace current-frame. Regardless, trying again a month later seems to have fixed things and made the second elisp suggestion work for me.

Many thanks for the two of you for taking the time to investigate and remedy this! 🙇

rnkn commented 7 years ago

Good to know. The only mystery was that @Bad-ptr already edited his comment and replaced current-frame with selected-frame, hence why it now works.