persp-mode.el icon indicating copy to clipboard operation
persp-mode.el copied to clipboard

Automatically use projectile perspectives

Open toupeira opened this issue 8 years ago • 36 comments

I'm trying to automatically use project layouts for files that belong to a project, what I have so far is the following:

  (def-auto-persp "projectile"
    :hooks (projectile-mode-hook)
    :predicate (lambda (buffer)
                 (and (not (eq nil (buffer-file-name buffer)))
                      (bound-and-true-p projectile-mode)
                      (projectile-project-p)
                      (projectile-project-buffer-p buffer (projectile-project-root))))
    :on-match (lambda (perspective buffer after-match hook args)
                  (persp-switch (projectile-project-root))))

I had to add the checks for buffer-file-name and projectile-project-buffer-p to avoid issues with things like Helm, but otherwise this seems to work nicely. So my question is basically: do you see any problems with this approach, or maybe there's a more straight-forward or reliable way to accomplish the same thing?

toupeira avatar Jun 04 '16 15:06 toupeira

Well, I don't use the projectile, so can't say for sure. You code looks mostly correct and it should work. But actually when I was writing the def-auto-persp macro I didn't think it could be used to dynamically create perspectives with different names. To adress this I added the :get-name-expr parameter: 7f21fd8207a3584bf1509d345057ef8658d6bfb9. It is intended to be used like this:

 (def-auto-persp "projectile"
    :hooks (projectile-mode-hook)
    :get-name-expr (projectile-project-root)
    :predicate (lambda (buffer)
                 (and (not (eq nil (buffer-file-name buffer)))
                      (bound-and-true-p projectile-mode)
                      (projectile-project-p)
                      (projectile-project-buffer-p buffer (projectile-project-root))))
    :on-match (lambda (perspective buffer after-match hook args)
                  (persp-frame-switch perspective)))

And it is the more correct way(Especially if in the feature I'll decide to change something). I have not tested it though.)

Bad-ptr avatar Jun 06 '16 08:06 Bad-ptr

Thanks, I assumed get-persp-expr was for that but couldn't get it to work :)

I also switched to find-file-hook instead of projectile-mode-hook which seems more reliable, though I still have the problem that previously opened buffers don't trigger that hook, so I end up with a buffer in the "wrong" perspective. Is there perhaps some mechanism in persp-mode to work around this, e.g. by setting a buffer-local variable to trigger a given perspective or something?

toupeira avatar Jun 06 '16 10:06 toupeira

though I still have the problem that previously opened buffers don't trigger that hook, so I end up with a buffer in the "wrong" perspective. Is there perhaps some mechanism in persp-mode to work around this, e.g. by setting a buffer-local variable to trigger a given perspective or something?

Ok, I have long wanted to do this. Breaking changes 5a3f8f92712a5da031cf07674fd4c350e56111e6 (Readme is also updated). def-auto-persp is now a defun, so you must quote arguments(except lambdas). Notice that the argument list of the :on-match callback has changed. Also notice that auto persp definitions is now stored in the persp-auto-persp-alist variable. See the persp-auto-persp-pickup-buffer* family of functions.

Hope this will do it for you(I have not tested how well it works).

Bad-ptr avatar Jun 09 '16 17:06 Bad-ptr

Hmm I get an error "Don't know how to compile nil" with the latest version, running with --debug-init --eval '(setq debug-on-error t byte-compile-debug t) gives me

Debugger entered--Lisp error: (error "Don't know how to compile nil")
  [..]
  byte-compile(nil)
  (set-frame-parameter frame (quote buffer-predicate) (byte-compile new-pred))
  [..]
  persp-set-frame-buffer-predicate(#<frame *spacemacs* [emacs.d] 0x878b140>)
  [..]
  persp-init-frame(#<frame *spacemacs* [emacs.d] 0x878b140>)
  [..]
  persp-mode()
  [..]

It sounds like it's related to your other commit 191715a73b605ad219b9f430b462767fe727fef3

toupeira avatar Jun 09 '16 19:06 toupeira

What version of emacs are you using? Try doing this: M-: (byte-compile nil) RET

For me it outputs:

Function nil is already compiled
#[nil "À‡" [nil] 1]

emacs --version GNU Emacs 25.1.50.1

Bad-ptr avatar Jun 09 '16 19:06 Bad-ptr

(byte-compile nil) gives me the same error. I'm on the latest stable release 24.5 on Debian unstable:

GNU Emacs 24.5.1 (i586-pc-linux-gnu, GTK+ Version 3.18.9) of 2016-04-08 on x86-csail-01, modified by Debian

toupeira avatar Jun 09 '16 22:06 toupeira

Ok latest version compiles again!

Thanks a lot for your changes, I now have the following:

  (def-auto-persp "projectile"
    :parameters '((dont-save-to-file . t))
    :hooks '(after-change-major-mode-hook)
    :predicate
    (lambda (buffer)
      (with-current-buffer buffer
        (and
         (buffer-file-name)
         (projectile-project-p))))
    :get-name-expr
    (lambda ()
      (abbreviate-file-name (projectile-project-root)))
    :after-match
    (lambda (persp-name persp buffer &rest args)
      (persp-frame-switch persp-name)))

I had to add :hooks '(after-change-major-mode-hook) or I would get an error wrong-type-argument consp nil on startup, though everything else still seems to work the same.

Also without the :after-match the new perspective wouldn't be switched to, is that intentional?

There's still an issue though:

  • open file in project A, auto-creates layout A
  • open file from project B, auto-creates layout B
  • switch back to layout A
  • now I still see the file from project B in layout A, even though it's not a member of persp-buffer-list, and persp-remove-buffer (current-buffer) (get-current-persp) doesn't do anything either

toupeira avatar Jun 11 '16 21:06 toupeira

I'm also trying out an advice on find-file:

(advice-add 'find-file :after 'dotfiles/switch-to-project-layout)

(defun dotfiles/switch-to-project-layout (&rest args)
  (when (projectile-project-p)
    (let* ((buffer (current-buffer))
           (old-persp (get-current-persp))
           (new-persp (abbreviate-file-name (projectile-project-root))))
      ;; make sure the old window is still showing the same buffer
      (switch-to-buffer (other-buffer))
      ;; switch to the new perspective
      (persp-switch new-persp)
      ;; make sure the new buffer is added to the perspective and switched to
      (persp-add-buffer buffer)
      ;; if the perspective changed, make sure the new buffer is gone from the old perspective
      (when (and old-persp (not (string= new-persp (persp-name old-persp))))
        (persp-remove-buffer buffer old-persp)))))

So far this seems to cover all edge cases I ran into with my previous attempts, while the approach with def-auto-persp seems to be missing the switch-to-buffer part.

Also, the advice on find-file is the first hook I found that reliably triggers in all the cases I need, the problem with after-change-major-mode-hook is that it doesn't trigger for already opened buffers, and file-find-hook also triggers on find-file-noselect which causes all sorts of weird issues (e.g. company-mode triggers it randomly while typing)

toupeira avatar Jun 12 '16 00:06 toupeira

I had to add :hooks '(after-change-major-mode-hook) or I would get an error wrong-type-argument consp nil

Fixed b91ed0682894bbd97a35e11b9a2554abf08a9750.

Also without the :after-match the new perspective wouldn't be switched to, is that intentional?

Added :switch parameter dfb4e8397e85b241834a65cd797a3d0d9f5d5baf.

now I still see the file from project B in layout A, even though it's not a member of persp-buffer-list

Probably fixed 50c05c56c5b29d9e9bc15416abfc37b87a27151b.

Bad-ptr avatar Jun 12 '16 15:06 Bad-ptr

You could try this:

(defvar after-find-file-hook nil)

(defun dotfiles/after-find-file-adv (&rest args)
  (run-hooks 'after-find-file-hook))

(advice-add 'find-file :after 'dotfiles/after-find-file-adv)

(def-auto-persp "projectile"
  :parameters '((dont-save-to-file . t))
  :hooks '(after-find-file-hook)
  :switch 'frame
  :predicate
  #'(lambda (buffer)
      (and
       (buffer-file-name)
       (projectile-project-p)))
  :get-name-expr
  #'(lambda ()
      (abbreviate-file-name (projectile-project-root))))

Bad-ptr avatar Jun 12 '16 15:06 Bad-ptr

Thanks, I tried your code without changes, but I still experience this issue:

now I still see the file from project B in layout A, even though it's not a member of persp-buffer-list

Also, if I'm switching to an already opened buffer it doesn't get displayed at all in the new perspective, only in the old one.

Let me know if you want to keep looking into this, otherwise I'm happy to keep my mostly-working advice kludge and stop bothering you ;-)

toupeira avatar Jun 14 '16 13:06 toupeira

Let me know if you want to keep looking into this

Yes, I think it can be useful. So I'll install projectile to see what's goes wrong.

Bad-ptr avatar Jun 14 '16 19:06 Bad-ptr

I think I made it to work. (However, there is still a problem with emacsclient and server-switch-hook.) d071a4a7b6997d35bc0b559a01e7975b832bc203...dad19945146ad653fbd618ff477dc19e7b650d60

(defvar after-find-file-hook nil)
(defun my/-after-find-file-adv (&rest args)
    (run-hooks 'after-find-file-hook))
(advice-add 'find-file :after 'my/-after-find-file-adv)

(def-auto-persp "projectile"
    :parameters '((dont-save-to-file . t))
    :hooks '(after-find-file-hook)
    :switch 'frame
    :predicate
    #'(lambda (buffer)
        (and
         (buffer-file-name)
         (projectile-project-p)))
    :get-name-expr
    #'(lambda ()
        (abbreviate-file-name (projectile-project-root))))

(setq persp-add-buffer-on-find-file 'if-not-autopersp)
(add-hook 'persp-after-load-state-functions #'(lambda (&rest args) (persp-auto-persps-pickup-buffers)) t)

Bad-ptr avatar Jun 18 '16 09:06 Bad-ptr

Now I'm getting an error persp-contain-buffer-p: Wrong type argument: arrayp, t on startup, also see https://github.com/syl20bnr/spacemacs/issues/6366

But thanks for your changes, looking forward to try it out!

toupeira avatar Jun 18 '16 14:06 toupeira

persp-contain-buffer-p: Wrong type argument: arrayp, t

shit). This should fix it f9638fac82a5e6a38b329e5d936c7a0067b2ca5e.

Bad-ptr avatar Jun 18 '16 15:06 Bad-ptr

This should fix it f9638fa.

It works. Thanks for the quick fix.

et2010 avatar Jun 18 '16 16:06 et2010

Just had another look with your latest changes, I still had the issue that newly opened buffers were also selected in the old perspective, but after adding the switch-to-buffer line from my version it seems to work the same now. Here's the full code:

  (defvar after-find-file-hook nil)
  (defun dotfiles/after-find-file-adv (&rest args) (run-hooks 'after-find-file-hook))
  (advice-add 'find-file :after 'dotfiles/after-find-file-adv)

  (def-auto-persp "projectile"
    :parameters '((dont-save-to-file . t))
    :hooks '(after-find-file-hook)
    :switch 'frame
    :predicate
    (lambda (buffer)
      (when (and (buffer-file-name)
                 (projectile-project-p))
        (switch-to-buffer (other-buffer))
        t))
    :get-name-expr
    (lambda ()
      (if (string-prefix-p dotfiles/directory (file-truename (buffer-file-name (current-buffer))))
          dotfiles/directory
        (abbreviate-file-name (projectile-project-root)))))

I tried to do the same using the persp-activated-functions hook, but that doesn't seem to work as reliably:

  (add-hook
   'persp-activated-functions
   (lambda (scope)
     (unless (persp-contain-buffer-p (current-buffer))
       ;; first attempt:
       ;; (switch-to-buffer (other-buffer))
       ;; second attempt:
       (persp-switch-to-prev-buffer (current-buffer)))))

I'll keep using the auto-persp now and will see if I run into any problems, thanks again for your help!

toupeira avatar Jul 03 '16 14:07 toupeira

This is strange. Maybe it's because you are using spacemacs, or whatever in your config... Maybe you missed the (setq persp-add-buffer-on-find-file 'if-not-autopersp) thing?

The relevant code is here: https://github.com/Bad-ptr/persp-mode.el/blob/master/persp-mode.el#L1403 maybe you can try to experiment with changing it)

Bad-ptr avatar Jul 04 '16 09:07 Bad-ptr

The last snippet posted by @toupeira is not working for me with the latest version from MELPA.

When evaluating the def-auto-persp form I get a compilation warning: Warning: ‘t’ called as a function and an error condition-case: Symbol’s function definition is void: closure

julienfantin avatar Sep 17 '16 22:09 julienfantin

@julienfantin can you reproduce it with M-x toggle-debug-on-error RET(or starting emacs with --debug-init flag) and post the backtrace here?

Bad-ptr avatar Sep 18 '16 09:09 Bad-ptr

@julienfantin you can see my current configuration here. You have to remove/change the if clause in the :get-name-expr section, that's specific to my setup and requires another variable dotfiles/directory to be set. I assume you have projectile installed?

toupeira avatar Sep 19 '16 17:09 toupeira

@Bad-ptr

Here is the (hairy) backtrace.

I suspect it's picking up something in my environment since I've managed to make it work by running @toupeira's config with (with-temp-buffer (eval '(def-auto-pers ...)))!

Debugger entered--Lisp error: (void-function closure)
  (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t)))
  (funcall (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) buffer)
  (if (funcall (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) buffer) (progn t))
  (when (funcall (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) buffer) t)
  (save-current-buffer (set-buffer buffer) (when (funcall (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) buffer) t))
  (with-current-buffer buffer (when (funcall (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) buffer) t))
  (lambda (buffer) (with-current-buffer buffer (when (funcall (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer ...) t))) buffer) t)))(#<buffer config-layouts.el>)
  funcall((lambda (buffer) (with-current-buffer buffer (when (funcall (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer ...) t))) buffer) t))) #<buffer config-layouts.el>)
  (if (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall (closure (after-find-file-hook t) (_buffer) (if ... ...)) buffer) t))) buffer) (progn (with-current-buffer buffer (let* ((persp-name (funcall (closure ... nil ...))) (persp (persp-add-new persp-name)) (after-match (funcall #[... "\303  \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil #[... "\300\207" [t] 1])) (do-def-after-match (when (functionp after-match) (funcall after-match persp-name persp buffer hook hook-args ... ... nil nil)))) (when do-def-after-match (funcall #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\203@� \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5] persp-name persp buffer hook hook-args (quote frame) (quote (...)) nil nil))))))
  (when (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall (closure (after-find-file-hook t) (_buffer) (if ... ...)) buffer) t))) buffer) (with-current-buffer buffer (let* ((persp-name (funcall (closure (after-find-file-hook t) nil (abbreviate-file-name ...)))) (persp (persp-add-new persp-name)) (after-match (funcall #[(persp-name persp buffer hook hook-args switch parameters noauto weak after-match) "\303    \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] persp-name persp buffer hook hook-args (quote frame) (quote (...)) nil nil #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\300\207" [t] 1])) (do-def-after-match (when (functionp after-match) (funcall after-match persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil)))) (when do-def-after-match (funcall #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\203@�  \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql (quote nil) eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5] persp-name persp buffer hook hook-args (quote frame) (quote ((dont-save-to-file . t))) nil nil)))))
  (let nil (unless buffer (setq buffer (current-buffer))) (when (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall (closure ... ... ...) buffer) t))) buffer) (with-current-buffer buffer (let* ((persp-name (funcall (closure ... nil ...))) (persp (persp-add-new persp-name)) (after-match (funcall #[... "\303   \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil #[... "\300\207" [t] 1])) (do-def-after-match (when (functionp after-match) (funcall after-match persp-name persp buffer hook hook-args ... ... nil nil)))) (when do-def-after-match (funcall #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\203@� \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5] persp-name persp buffer hook hook-args (quote frame) (quote (...)) nil nil))))))
  (lambda (&optional buffer hook hook-args) (let nil (unless buffer (setq buffer (current-buffer))) (when (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall ... buffer) t))) buffer) (with-current-buffer buffer (let* ((persp-name (funcall ...)) (persp (persp-add-new persp-name)) (after-match (funcall #[... "\303 \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] persp-name persp buffer hook hook-args ... ... nil nil #[... "\300\207" [t] 1])) (do-def-after-match (when ... ...))) (when do-def-after-match (funcall #[... "\203@�   \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5] persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil)))))))(#<buffer config-layouts.el>)
  persp--auto-persp-pickup-buffer(("projectile" (:main-action lambda (&optional buffer hook hook-args) (let nil (unless buffer (setq buffer (current-buffer))) (when (funcall (lambda (buffer) (with-current-buffer buffer (when ... t))) buffer) (with-current-buffer buffer (let* ((persp-name ...) (persp ...) (after-match ...) (do-def-after-match ...)) (when do-def-after-match (funcall #[... "\203@�    \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5] persp-name persp buffer hook hook-args ... ... nil nil))))))) (:generated-predicate lambda (buffer) (with-current-buffer buffer (when (funcall (closure (after-find-file-hook t) (_buffer) (if (and ... ...) (progn ... t))) buffer) t))) (:get-name-expr closure (after-find-file-hook t) nil (abbreviate-file-name (projectile-project-root))) (:predicate closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) (:switch . frame) (:hooks (config-layouts-after-find-file-hook . #[128 "\205\205�\301\302\204�p\262r\211q\210\303\304\305!\306 \307 \205)�\310 \205)�\311\312 !\210\305#!\2050�\305)\262\205\203�rq\210\303\304\305!\301\313\314 !# \315!\316\317\320\301\211\321&\n\322!\205m�\211\317\320\301\211& \211\205\200�\323        \317\320\301\211&   \266\204)\266\203\207" [persp-mode nil config-layouts-after-find-file-hook closure after-find-file-hook t _buffer buffer-file-name projectile-project-p switch-to-buffer other-buffer abbreviate-file-name projectile-project-root persp-add-new #[(persp-name persp buffer hook hook-args switch parameters noauto weak after-match) "\303    \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] frame ((dont-save-to-file . t)) #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\300\207" [t] 1] functionp #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\203@�   \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql (quote nil) eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]] 18 "\n\n(fn &rest HOOK-ARGS)"])) (:parameters (dont-save-to-file . t))) #<buffer config-layouts.el>)
  apply(persp--auto-persp-pickup-buffer (("projectile" (:main-action lambda (&optional buffer hook hook-args) (let nil (unless buffer (setq buffer (current-buffer))) (when (funcall (lambda (buffer) (with-current-buffer buffer ...)) buffer) (with-current-buffer buffer (let* (... ... ... ...) (when do-def-after-match ...)))))) (:generated-predicate lambda (buffer) (with-current-buffer buffer (when (funcall (closure (after-find-file-hook t) (_buffer) (if ... ...)) buffer) t))) (:get-name-expr closure (after-find-file-hook t) nil (abbreviate-file-name (projectile-project-root))) (:predicate closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) (:switch . frame) (:hooks (config-layouts-after-find-file-hook . #[128 "\205\205�\301\302\204�p\262r\211q\210\303\304\305!\306 \307 \205)�\310 \205)�\311\312 !\210\305#!\2050�\305)\262\205\203�rq\210\303\304\305!\301\313\314 !# \315!\316\317\320\301\211\321&\n\322!\205m�\211\317\320\301\211&    \211\205\200�\323        \317\320\301\211&   \266\204)\266\203\207" [persp-mode nil config-layouts-after-find-file-hook closure after-find-file-hook t _buffer buffer-file-name projectile-project-p switch-to-buffer other-buffer abbreviate-file-name projectile-project-root persp-add-new #[(persp-name persp buffer hook hook-args switch parameters noauto weak after-match) "\303    \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] frame ((dont-save-to-file . t)) #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\300\207" [t] 1] functionp #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\203@�   \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]] 18 "\n\n(fn &rest HOOK-ARGS)"])) (:parameters (dont-save-to-file . t))) #<buffer config-layouts.el>))
  #[128 "\302\300\303\301\"\"\207" [persp--auto-persp-pickup-buffer (("projectile" (:main-action lambda (&optional buffer hook hook-args) (let nil (unless buffer (setq buffer ...)) (when (funcall ... buffer) (with-current-buffer buffer ...)))) (:generated-predicate lambda (buffer) (with-current-buffer buffer (when (funcall ... buffer) t))) (:get-name-expr closure (after-find-file-hook t) nil (abbreviate-file-name (projectile-project-root))) (:predicate closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer ...) t))) (:switch . frame) (:hooks (config-layouts-after-find-file-hook . #[128 "\205\205�\301\302\204�p\262r\211q\210\303\304\305!\306 \307 \205)�\310 \205)�\311\312 !\210\305#!\2050�\305)\262\205\203�rq\210\303\304\305!\301\313\314 !# \315!\316\317\320\301\211\321&\n\322!\205m�\211\317\320\301\211&   \211\205\200�\323        \317\320\301\211&   \266\204)\266\203\207" [persp-mode nil config-layouts-after-find-file-hook closure after-find-file-hook t _buffer buffer-file-name projectile-project-p switch-to-buffer other-buffer abbreviate-file-name projectile-project-root persp-add-new #[... "\303   \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] frame ... #[... "\300\207" [t] 1] functionp #[... "\203@�   \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]] 18 "\n\n(fn &rest HOOK-ARGS)"])) (:parameters (dont-save-to-file . t)))) apply append] 6 "\n\n(fn &rest ARGS2)"](#<buffer config-layouts.el>)
  mapc(#[128 "\302\300\303\301\"\"\207" [persp--auto-persp-pickup-buffer (("projectile" (:main-action lambda (&optional buffer hook hook-args) (let nil (unless buffer (setq buffer ...)) (when (funcall ... buffer) (with-current-buffer buffer ...)))) (:generated-predicate lambda (buffer) (with-current-buffer buffer (when (funcall ... buffer) t))) (:get-name-expr closure (after-find-file-hook t) nil (abbreviate-file-name (projectile-project-root))) (:predicate closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer ...) t))) (:switch . frame) (:hooks (config-layouts-after-find-file-hook . #[128 "\205\205�\301\302\204�p\262r\211q\210\303\304\305!\306 \307 \205)�\310 \205)�\311\312 !\210\305#!\2050�\305)\262\205\203�rq\210\303\304\305!\301\313\314 !# \315!\316\317\320\301\211\321&\n\322!\205m�\211\317\320\301\211&  \211\205\200�\323        \317\320\301\211&   \266\204)\266\203\207" [persp-mode nil config-layouts-after-find-file-hook closure after-find-file-hook t _buffer buffer-file-name projectile-project-p switch-to-buffer other-buffer abbreviate-file-name projectile-project-root persp-add-new #[... "\303   \"\210\n\207" [buffer persp after-match persp-add-buffer] 3] frame ... #[... "\300\207" [t] 1] functionp #[... "\203@�   \204�\306H\n>\204�\307\310\311D\"\210\211\312\313I\210)\f\203:�\306H\n>\2042�\307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r�\321\322\"\203]�\323!\210\202r�\321\324\"\203m�\325!\210\202r�\326!\210\205{�\327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]] 18 "\n\n(fn &rest HOOK-ARGS)"])) (:parameters (dont-save-to-file . t)))) apply append] 6 "\n\n(fn &rest ARGS2)"] (#<buffer config-layouts.el> #<buffer config-windows.el> #<buffer  *Minibuf-1*> #<buffer  *Minibuf-2*> #<buffer config-modeline.el> #<buffer init.el> #<buffer *scratch*> #<buffer  *Minibuf-0*> #<buffer *Messages*> #<buffer  *code-conversion-work*> #<buffer  *Echo Area 0*> #<buffer  *Echo Area 1*> #<buffer *Warnings*> #<buffer  *diff-hl* > #<buffer  *counsel*> #<buffer *Packages*> #<buffer  *which-key*> #<buffer *Compile-Log*>))
  persp-auto-persp-pickup-bufferlist-for("projectile" (#<buffer config-layouts.el> #<buffer config-windows.el> #<buffer  *Minibuf-1*> #<buffer  *Minibuf-2*> #<buffer config-modeline.el> #<buffer init.el> #<buffer *scratch*> #<buffer  *Minibuf-0*> #<buffer *Messages*> #<buffer  *code-conversion-work*> #<buffer  *Echo Area 0*> #<buffer  *Echo Area 1*> #<buffer *Warnings*> #<buffer  *diff-hl* > #<buffer  *counsel*> #<buffer *Packages*> #<buffer  *which-key*> #<buffer *Compile-Log*>))
  persp-auto-persp-pickup-buffers-for("projectile")
  def-auto-persp("projectile" :parameters ((dont-save-to-file . t)) :hooks (config-layouts-after-find-file-hook) :switch frame :predicate (closure (after-find-file-hook t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t))) :get-name-expr (closure (after-find-file-hook t) nil (abbreviate-file-name (projectile-project-root))))
  (closure (after-find-file-hook t) nil (defvar config-layouts-after-find-file-hook nil) (def-auto-persp "projectile" :parameters (quote ((dont-save-to-file . t))) :hooks (quote (config-layouts-after-find-file-hook)) :switch (quote frame) :predicate (function (lambda (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t)))) :get-name-expr (function (lambda nil (abbreviate-file-name (projectile-project-root))))))()
  eval-after-load(persp-mode (closure (after-find-file-hook t) nil (defvar config-layouts-after-find-file-hook nil) (def-auto-persp "projectile" :parameters (quote ((dont-save-to-file . t))) :hooks (quote (config-layouts-after-find-file-hook)) :switch (quote frame) :predicate (function (lambda (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn (switch-to-buffer (other-buffer)) t)))) :get-name-expr (function (lambda nil (abbreviate-file-name (projectile-project-root)))))))
  (closure (after-find-file-hook t) nil (eval-after-load (quote persp-mode) (function (lambda nil (defvar config-layouts-after-find-file-hook nil) (def-auto-persp "projectile" :parameters (quote ((dont-save-to-file . t))) :hooks (quote (config-layouts-after-find-file-hook)) :switch (quote frame) :predicate (function (lambda (_buffer) (if ... ...))) :get-name-expr (function (lambda nil (abbreviate-file-name ...))))))))()
  eval-after-load(projectile (closure (after-find-file-hook t) nil (eval-after-load (quote persp-mode) (function (lambda nil (defvar config-layouts-after-find-file-hook nil) (def-auto-persp "projectile" :parameters (quote ((dont-save-to-file . t))) :hooks (quote (config-layouts-after-find-file-hook)) :switch (quote frame) :predicate (function (lambda (_buffer) (if ... ...))) :get-name-expr (function (lambda nil (abbreviate-file-name ...)))))))))
  (progn (eval-after-load (quote projectile) (function (lambda nil (eval-after-load (quote persp-mode) (function (lambda nil (defvar config-layouts-after-find-file-hook nil) (def-auto-persp "projectile" :parameters ... :hooks ... :switch ... :predicate ... :get-name-expr ...))))))))
  (progn (defvar after-find-file-hook) (progn (eval-after-load (quote projectile) (function (lambda nil (eval-after-load (quote persp-mode) (function (lambda nil ... ...))))))))
  eval((progn (defvar after-find-file-hook) (progn (eval-after-load (quote projectile) (function (lambda nil (eval-after-load (quote persp-mode) (function (lambda nil ... ...)))))))) t)
  edebug-eval-defun(nil)
  apply(edebug-eval-defun nil)
  eval-defun(nil)
  funcall-interactively(eval-defun nil)
  call-interactively(eval-defun nil nil)
  command-execute(eval-defun)

julienfantin avatar Sep 23 '16 03:09 julienfantin

@julienfantin I think it must be fixed by https://github.com/Bad-ptr/persp-mode.el/commit/5d7e9755a1e5606c63f4832d7d69a979c679696b

Bad-ptr avatar Sep 24 '16 10:09 Bad-ptr

@Bad-ptr thanks for looking into this, but with version 20160924.308 from MELPA, I'm still getting:

Debugger entered--Lisp error: (void-function closure)
  (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t)))
  (funcall (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) buffer)
  (if (funcall (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) buffer) (progn t))
  (when (funcall (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) buffer) t)
  (save-current-buffer (set-buffer buffer) (when (funcall (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) buffer) t))
  (with-current-buffer buffer (when (funcall (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) buffer) t))
  (lambda (buffer) (with-current-buffer buffer (when (funcall (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) buffer) t)))(#<buffer *scratch*>)
  funcall((lambda (buffer) (with-current-buffer buffer (when (funcall (closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) buffer) t))) #<buffer *scratch*>)
  (if (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall (closure (t) (_buffer) (if ... ...)) buffer) t))) buffer) (progn (with-current-buffer buffer (let* ((persp-name (funcall (closure ... nil ...))) (persp (persp-add-new persp-name)) (after-match (funcall (quote #[... "\303    \"\210\n\207" [buffer persp after-match persp-add-buffer] 3]) persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil (quote #[... "\300\207" [t] 1]))) (do-def-after-match (when (functionp after-match) (funcall after-match persp-name persp buffer hook hook-args ... ... nil nil)))) (when do-def-after-match (funcall (quote #[... "\203@   \204 \306H\n>\204 \307\310\311D\"\210\211\312\313I\210)\f\203: \306H\n>\2042 \307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r \321\322\"\203] \323!\210\202r \321\324\"\203m \325!\210\202r \326!\210\205{ \327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]) persp-name persp buffer hook hook-args (quote frame) (quote (...)) nil nil))))))
  (when (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall (closure (t) (_buffer) (if ... ...)) buffer) t))) buffer) (with-current-buffer buffer (let* ((persp-name (funcall (closure (t) nil (abbreviate-file-name ...)))) (persp (persp-add-new persp-name)) (after-match (funcall (quote #[... "\303  \"\210\n\207" [buffer persp after-match persp-add-buffer] 3]) persp-name persp buffer hook hook-args (quote frame) (quote (...)) nil nil (quote #[... "\300\207" [t] 1]))) (do-def-after-match (when (functionp after-match) (funcall after-match persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil)))) (when do-def-after-match (funcall (quote #[(persp-name persp buffer hook hook-args switch parameters noauto weak) "\203@    \204 \306H\n>\204 \307\310\311D\"\210\211\312\313I\210)\f\203: \306H\n>\2042 \307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r \321\322\"\203] \323!\210\202r \321\324\"\203m \325!\210\202r \326!\210\205{ \327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]) persp-name persp buffer hook hook-args (quote frame) (quote ((dont-save-to-file . t))) nil nil)))))
  (let nil (unless buffer (setq buffer (current-buffer))) (when (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall (closure ... ... ...) buffer) t))) buffer) (with-current-buffer buffer (let* ((persp-name (funcall (closure ... nil ...))) (persp (persp-add-new persp-name)) (after-match (funcall (quote #[... "\303    \"\210\n\207" [buffer persp after-match persp-add-buffer] 3]) persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil (quote #[... "\300\207" [t] 1]))) (do-def-after-match (when (functionp after-match) (funcall after-match persp-name persp buffer hook hook-args ... ... nil nil)))) (when do-def-after-match (funcall (quote #[... "\203@   \204 \306H\n>\204 \307\310\311D\"\210\211\312\313I\210)\f\203: \306H\n>\2042 \307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r \321\322\"\203] \323!\210\202r \321\324\"\203m \325!\210\202r \326!\210\205{ \327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]) persp-name persp buffer hook hook-args (quote frame) (quote (...)) nil nil))))))
  (lambda (&optional buffer hook hook-args) (let nil (unless buffer (setq buffer (current-buffer))) (when (funcall (lambda (buffer) (with-current-buffer buffer (when (funcall ... buffer) t))) buffer) (with-current-buffer buffer (let* ((persp-name (funcall ...)) (persp (persp-add-new persp-name)) (after-match (funcall ... persp-name persp buffer hook hook-args ... ... nil nil ...)) (do-def-after-match (when ... ...))) (when do-def-after-match (funcall (quote #[... "\203@     \204 \306H\n>\204 \307\310\311D\"\210\211\312\313I\210)\f\203: \306H\n>\2042 \307\310\311D\"\210\211\314\313I\210)\315\"\210\316!\210\317\320\"\204r \321\322\"\203] \323!\210\202r \321\324\"\203m \325!\210\202r \326!\210\205{ \327!\207" [persp noauto cl-struct-perspective-tags v weak v 0 signal wrong-type-argument perspective 6 t 5 modify-persp-parameters persp-unhide memql ... eql window persp-window-switch frame persp-frame-switch persp-switch persp-switch-to-buffer parameters persp-name switch buffer] 5]) persp-name persp buffer hook hook-args (quote frame) (quote ...) nil nil)))))))(#<buffer *scratch*>)
  persp--auto-persp-pickup-buffer(("projectile" (:main-action lambda (&optional buffer hook hook-args) (let nil (unless buffer (setq buffer (current-buffer))) (when (funcall (lambda (buffer) (with-current-buffer buffer (when ... t))) buffer) (with-current-buffer buffer (let* ((persp-name ...) (persp ...) (after-match ...) (do-def-after-match ...)) (when do-def-after-match (funcall ... persp-name persp buffer hook hook-args ... ... nil nil))))))) (:generated-predicate lambda (buffer) (with-current-buffer buffer (when (funcall (closure (t) (_buffer) (if (and ... ...) (progn t))) buffer) t))) (:get-name-expr closure (t) nil (abbreviate-file-name (projectile-project-root))) (:predicate closure (t) (_buffer) (if (and (buffer-file-name) (projectile-project-p)) (progn t))) (:switch . frame) (:hooks (config-layouts-after-find-file-hook . #[(&rest hook-args) "\205{ \306\307  \211\204 prq\210\310\311 \312 \313 \205&

julienfantin avatar Sep 24 '16 22:09 julienfantin

@julienfantin Thanks, I see that I missed to quote a number of values. Now it must work b811c39bfa542c11bc32b6338381fc1d61fc26d4.

Bad-ptr avatar Sep 25 '16 10:09 Bad-ptr

@Bad-ptr it does! Thank you.

julienfantin avatar Sep 25 '16 19:09 julienfantin

All these things seem to work fine, however I just ran into an issue which I am not sure how to solve.

In projectile together with helm you can select multiple files: http://tuhdo.github.io/helm-projectile.html#sec-1-1

If I select multiple files only the file that the cursor is currently on gets assigned to the projectile auto perspective, but the other ones get opened without being associated with the perspective. Any idea how to configure so all of them gets assigned to the perspective?

terlar avatar Feb 28 '17 10:02 terlar

@terlar

but the other ones get opened without being associated with the perspective

May be one of it is under git control and other is not? Or do they belong to different projects? If it is not the case -- then this is strange.

Bad-ptr avatar Feb 28 '17 19:02 Bad-ptr

This looks to be a request feature here: https://github.com/bbatsov/persp-projectile/issues/7 Perhaps it could be submitted there to address that issue, or separate package created, and submitted to melpa?

nickbroon avatar Mar 01 '17 12:03 nickbroon

They files are all in the same project and has the same git root, even if they are all in the exactly same folder I cannot get it to work. It only adds the file the cursor in to the perspective, the other selected ones are opened as buffers. But don't appear in the persp buffer list. If I go to one of these files by going through the regular buffer list it is recognized as part of the same perspective and if I open the persp buffer list from there it shows the other files, but still doesn't show those other files.

terlar avatar Mar 01 '17 17:03 terlar

@nickbroon Well I don't quite understand what people want from 'persp-mode -> projectile integration'. If you mean that each projectile 'project' must have a corresponding perspective, then this is easy (I beleive:)): https://gist.github.com/Bad-ptr/1aca1ec54c3bdb2ee80996eb2b68ad2d#file-persp-projectile-bridge-el After package-installing this gist. Put the following into your config:

(with-eval-after-load "persp-projectile-bridge-autoloads"
    (add-hook 'persp-projectile-bridge-mode-hook
              #'(lambda ()
                  (if persp-projectile-bridge-mode
                      (persp-projectile-bridge-find-perspectives-for-all-buffers)
                    (persp-projectile-bridge-kill-perspectives))))
    (persp-projectile-bridge-mode 1))

Bad-ptr avatar Mar 04 '17 11:03 Bad-ptr

What you describe there seems quite right, for me I haven't found a configuration where the buffers end up in the wrong projectile persp etc.

Should that one be together with the configuration described here. Or is it stand-alone. Without that config it seems all the persp buffers were assigned to all the projectile perspectives (all buffers everywhere). With that config it still only opens the first file in the selection (using helm), the rest of the buffers get assigned to the none persp. Also it seems to show the buffer from another persp after the operation, but it was never assigned to the current persp.

What I would like to achieve is that when I open a new file belonging to a project (using the projectile projectile-switch-project together with the switch action helm-projectile), if I select one or several files in the helm menu they should be opened and assigned to a persp for that specific project. If I am inside a project already and do the same operation it should do the same but for a new project and persp. If I open files belonging to the same project they should be added as buffers to the same persp.

Thank you for the help @Bad-ptr, your scripts help a great deal to customize the behavior. But I still haven't figured out how to do it and really appreciate your feedback.

terlar avatar Mar 05 '17 09:03 terlar

@Bad-ptr Those look very useful! Would you consider making them part of this repository, or perhaps a stand alone repository and publishing them to MELPA?

nickbroon avatar Mar 06 '17 11:03 nickbroon

@nickbroon Ok, I have created a repo for you https://github.com/Bad-ptr/persp-mode-projectile-bridge.el. You can add it to MELPA if you wish.

@all @terlar I made breaking changes in how auto perspectives works: https://github.com/Bad-ptr/persp-mode.el#auto-perspectives

Here is the auto-persp definition which must do what persp-mode-projectile-bridge.el does: https://gist.github.com/Bad-ptr/1aca1ec54c3bdb2ee80996eb2b68ad2d#file-persp-projectile-auto-persp-el

@terlar It seems like finding multiple files with helm-projectile works for me now(it adds all selected buffers to the perspective).

Bad-ptr avatar Mar 11 '17 15:03 Bad-ptr

@Bad-ptr, That's great, thanks! I'll look to submit it to MELPA. It would perhaps be useful to also fold persp-projectile-auto-persp.el into that repo, as they both relate to integrating with projectile.

nickbroon avatar Mar 13 '17 14:03 nickbroon

For what it's worth I'm using it like this:

(require 'package)
(add-to-list 'package-archives
	     '("melpa" . "http://melpa.org/packages/"))
(package-initialize)

;; Bootstrap `use-package'
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(setq use-package-always-ensure t)

(use-package projectile
  :config
  (projectile-global-mode)
  )

(use-package persp-mode
  :init
  (setq persp-autokill-buffer-on-remove 'kill-weak)
  :config
  (persp-mode 1)
  )

(use-package persp-mode-projectile-bridge
  :config
  (add-hook 'persp-mode-projectile-bridge-mode-hook
            #'(lambda ()
                (if persp-mode-projectile-bridge-mode
                    (persp-mode-projectile-bridge-find-perspectives-for-all-buffers)
                  (persp-mode-projectile-bridge-kill-perspectives))))
  (persp-mode-projectile-bridge-mode 1)
  )

nickbroon avatar Mar 13 '17 16:03 nickbroon