Git Product home page Git Product logo

perspective-el's Introduction

Perspective for Emacs

Test perspective

The Perspective package provides multiple named workspaces (or "perspectives") in Emacs, similar to multiple desktops in window managers like Awesome and XMonad, and Spaces on the Mac.

Each perspective has its own buffer list and its own window layout, along with some other isolated niceties, like the xref ring. This makes it easy to work on many separate projects without getting lost in all the buffers. Switching to a perspective activates its window configuration, and when in a perspective, only its buffers are available (by default).

Each Emacs frame has a distinct list of perspectives.

Perspective supports saving its state to a file, so long-lived work sessions may be saved and recovered as needed.

At long last this project has a changelog; please refer to it for release notes.

Sample Use Cases

Multiple Projects

Working on multiple projects can become difficult to organize as their buffer lists mix together during a long-running Emacs session. Searching for a buffer by name works well if you know what to search for, but sometimes picking from a list is easier — in which case, keeping the list well-pruned for relevant buffers becomes an important source of efficiency in file and buffer management. Perspective helps out by letting you keep separate named buffer lists and window layouts.

This use case works really well in conjunction with Projectile. Projectile helps with buffer navigation (and other project-specific tasks) in cases when a project has a well-defined root directory. Perspective then steps in to help manage unrelated buffers: shells, REPLs, dired buffers visiting directories outside the project, or files relevant to the project not under the same root as the rest of the source. It also helps deal with the situation of one project with multiple source repositories where having a shared window layout or buffer list makes sense.

Suppose you're developing feature X in perspective feature-X. This keeps you working with one set of files and windows. You then realize that this feature requires you to fix a bug in an unrelated set of files. You don't want to lose all the context you have built up for feature X, so you open a new perspective, bugfix-Y, letting you open new files and buffers without disturbing your work on feature-X. Then you are asked to urgently look into something related to development of feature Z, but again: you don't want to lose context. So you open a new perspective feature-Z, and fill it with a whole bunch of new files and windows — all without losing any of the context for your work on bug Y or feature X.

When you finish looking at Z, you close perspective feature-Z, and return to bugfix-Y, and restore its window layout and buffer list. When you finish with Y, you close perspective bugfix-Y and return to feature-X.

(Hint: this workflow works best with the persp-sort variable set to 'created — see documentation below.)

Perspective Merging

Yak shaving is useful for working on projects that are largely unrelated but sometimes you are working on multiple projects that are very much related, to the point that you want to view files from both projects at the same time. This is where perspective merging comes in.

Suppose you are working on a project that requires developing multiple auxiliary libraries. It may get messy to develop both the main project and all the libraries from the same perspective so instead you put each library in its own perspective so you can work on them in isolation. All of a sudden though you wish to see library code from the main projects perspective. Instead of switching back and forth between the library and main projects perspectives you can run M-x persp-merge and import the buffers from the libraries perspective. When you are done you can run remove the imported buffers with M-x persp-unmerge.

The purpose of perspective merging is to combine the buffer lists of different perspectives while keeping a clear distinction of which buffers belong to which perspective.

  • You can merge together as many perspectives as you want.
  • Merging is one directional so if you merge A into B, B's buffers will not be available in A.
  • Merging is not transitive so if you merge A into B, then B into C, the buffers in A will not be available in C.
  • The merge state is saved across sessions when using persp-state-{save,load}.

Similar Packages

The following Emacs packages implement comparable functionality:

  • persp-mode: A Perspective fork, which implements perspective sharing between Emacs frames. It also has a different approach to saving state and different configuration options. There has been some interest expressed in merging the two projects. Due to conflicting function names, persp-mode.el and Perspective cannot be installed simultaneously.
  • Workgroups 2: Similar to Perspective in terms of features. Its original codebase seems to predate Emacs acquiring a native ability to serialize window layouts, so it has custom serialization code.
  • eyebrowse: Supports window layouts but not buffer lists.
  • wconf: Supports window layouts but not buffer lists.
  • ElScreen: Supports window layouts but not buffer lists; seems unmaintained.
  • Burly: An approach to persisting window and frame configurations using Emacs bookmarks.

Emacs 27 includes two new buffer and window organizing features: Tab Line (global-tab-line-mode) and Tab Bar (tab-bar-mode).

  • Tab Line maintains a list of buffers which had been opened in a given window, and anchors it to that window. It is analogous to tabs as used in web browsers and other text editors, and therefore orthogonal to Perspective.
  • Tab Bar maintains window layouts (with optional names). In this, it is similar to Perspective. Unlike Perspective, it does not support buffer lists. Using Perspective and Tab Bar at the same time is not recommended at this time, since the tab list is global (i.e., will show up in all perspectives) and is likely to cause confusion. It would be an interesting future feature for Perspective to adopt the tab bar and allow keeping a distinct set of tabs per-perspective.

Compatibility

Perspective does not work with Emacs desktop.el. This is because Perspective state stores buffer and window information in frame parameters, and desktop-save-mode does not support saving those types of data.

Instead, Perspective provides its own disk save and load feature, which cleanly saves perspectives.

Installation

You should install Perspective from MELPA or MELPA Stable.

Users of use-package can install Perspective as follows:

(use-package perspective
  :bind
  ("C-x C-b" . persp-list-buffers)         ; or use a nicer switcher, see below
  :custom
  (persp-mode-prefix-key (kbd "C-c M-p"))  ; pick your own prefix key here
  :init
  (persp-mode))

Replace the binding for C-x C-b, the default Emacs buffer switcher, with one of the nicer implementations described in the Buffer switchers section.

If not using use-package, put perspective.el from this source repository somewhere on your load path, and use something similar to this:

(require 'perspective)
(global-set-key (kbd "C-x C-b") 'persp-list-buffers)
(customize-set-variable 'persp-mode-prefix-key (kbd "C-c M-p"))
(persp-mode)

Users of Debian 9 or later or Ubuntu 16.04 or later may simply apt-get install elpa-perspective, though be aware that the stable version provided in these repositories is likely to be (extremely) outdated.

Usage

To activate Perspective, use (persp-mode). This creates a single default main perpsective.

ℹ️ Since the release of Emacs 28, Perspective no longer ships with a default command prefix. Users should pick a prefix comfortable for them. In the days of Emacs 27 and earlier, the default prefix was C-x x. This conflicts with bindings built into Emacs 28.

To set a prefix key for all Perspective commands, customize persp-mode-prefix-key. Reasonable choices include C-x x (for users who don't care about the Emacs buffer-related commands this shadows), C-z (for users who don't suspend Emacs to shell background), C-c C-p (for users who don't mind the conflicting keys with org-mode and markdown-mode), C-c M-p (for users who don't mind the slightly awkward chord), and H-p (for users who don't mind relying exclusively on a non-standard Hyper modifier).

The actual command keys (the ones pressed after the prefix) are defined in perspective-map. Here are the main commands defined in perspective-map:

  • spersp-switch: Query a perspective to switch to, or create
  • `persp-switch-by-number: Switch to perspective by number, or switch quickly using numbers 1, 2, 3.. 0 as prefix args; note this will probably be most useful with persp-sort set to 'created
  • kpersp-remove-buffer: Query a buffer to remove from current perspective
  • cpersp-kill : Query a perspective to kill
  • rpersp-rename: Rename current perspective
  • apersp-add-buffer: Query an open buffer to add to current perspective
  • Apersp-set-buffer: Add buffer to current perspective and remove it from all others
  • b - persp-switch-to-buffer: Like switch-to-buffer; includes all buffers from all perspectives; changes perspective if necessary
  • ipersp-import: Import a given perspective from another frame.
  • n, <right>persp-next: Switch to next perspective
  • p, <left>persp-prev: Switch to previous perspective
  • mpersp-merge: Temporarily merge the buffers from one perspective into another
  • upersp-unmerge: Undo the effects of a persp-merge
  • gpersp-add-buffer-to-frame-global: Add buffer to a frame-specific "global" perspective
  • C-spersp-state-save: Save all perspectives in all frames to a file
  • C-lpersp-state-load: Load all perspectives from a file

Buffer Switchers

Since Perspective maintains distinct buffer lists for each perspective, it helps to use a Perspective-aware buffer switcher.

When using one of the following buffer switchers, you will only be prompted for buffers in the current perspective and the frame-specific "global" shared perspective. (The persp-add-buffer-to-frame-global command adds a buffer to this special frame-specific perspective, whose name is determined by persp-frame-global-perspective-name and defaults to GLOBAL.)

Ido: Interactive Do (Ido, ido-mode), in particular its ido-switch-buffer command, is automatically Perspective-aware when persp-mode is enabled.

list-buffers / buffer-menu: Perspective provides wrappers for the similar list-buffers and buffer-menu: persp-list-buffers and persp-buffer-menu. (Note that Emacs binds C-x C-b to list-buffers by default.) When these functions are called normally, they show the buffer menu filtered by the current perspective. With a prefix argument, they show the buffer menu of all the buffers in all perspectives. (The difference between list-buffers and buffer-menu: the former calls display-buffer, i.e., may split windows depending on display-buffer-alist, and the latter calls switch-to-buffer, i.e., flips the current window to the buffer list buffer.)

bs.el: Perspective provides a wrapper for bs-show: persp-bs-show. When this function is called normally, it shows a list of buffers filtered by the current perspective. With a prefix argument, it shows a list of buffers in all perspectives.

IBuffer: Perspective provides a wrapper for ibuffer: persp-ibuffer. When this function is called normally, it shows a list of buffers filtered by the current perspective. With a prefix argument, it shows a list of buffers in all perspectives.

If you want to group buffers by persp-name in ibuffer buffer, use persp-ibuffer-set-filter-groups. Or, make it the default:

(add-hook 'ibuffer-hook
          (lambda ()
            (persp-ibuffer-set-filter-groups)
            (unless (eq ibuffer-sorting-mode 'alphabetic)
              (ibuffer-do-sort-by-alphabetic))))

Helm: Perspective ships with buffer-listing advice for Helm, so Helm's buffer listing code should be automatically Perspective-aware when persp-mode is enabled. (Older versions of Helm relied on the machinery of ido-mode for listing buffers, so they did not require this advice; see this Helm commit and this Perspective commit for details.) If helm-buffers-list is called with a prefix argument, it will show buffers in all perspectives. In addition, Perspective adds actions to helm-buffers-list to add buffers to the current perspective (mainly relevant to the prefix-argument version) and to remove buffers from the current perspective.

Consult: Perspective provides persp-consult-source source that will list buffers in current perspective. You can hide default buffer source and add persp-consult-source to consult-buffer-sources for consult to only list buffers in current perspective like so:

(consult-customize consult--source-buffer :hidden t :default nil)
(add-to-list 'consult-buffer-sources persp-consult-source)

Note that you can still access list of all buffers in all perspectives by narrowing using prefix b.

Ivy / Counsel: Perspective provides two commands for listing buffers using Ivy and Counsel: persp-ivy-switch-buffer and persp-counsel-switch-buffer. When these functions are called normally, they show a list of buffers filtered by the current perspective. With a prefix argument, they shows a list of buffers in all perspectives. The distinction between the ivy and counsel versions is the same as between ivy-switch-buffer and counsel-switch-buffer: the latter shows a preview of the buffer to switch to, and the former does not.

It is a good idea to bind one these helper functions with the :bind form of use-package. Or, if you do not use use-package, it can also be bound globally, e.g.:

(global-set-key (kbd "C-x C-b") (lambda (arg)
                                  (interactive "P")
                                  (if (fboundp 'persp-bs-show)
                                      (persp-bs-show arg)
                                    (bs-show "all"))))

Notes on completing-read Enhancements

Users of a completing-read enhancement framework (such as Ivy, Selectrum, or Vertico) may wish to use the following two functions:

  • persp-switch-to-buffer* replaces switch-to-buffer
  • persp-kill-buffer* replaces kill-buffer

Both these functions behave like the built-ins, but use completing-read directly. When called normally, they list buffers filtered by the current perspective. With a prefix argument, they list buffers in all perspectives.

The following sample use-package invocation changes Emacs default key bindings to use the replacements:

(use-package perspective
  :bind (("C-x b" . persp-switch-to-buffer*)
         ("C-x k" . persp-kill-buffer*))
  :config
  (persp-mode))

Saving Sessions to Disk

A pair of functions, persp-state-save and persp-state-load, implement perspective durability on disk. When called interactively, they prompt for files to save sessions to and restore from.

A custom variable, persp-state-default-file, sets a default file to use for saving and restoring perspectives. When it is set, persp-state-save may be called non-interactively without an argument and it will save to the file referenced by that variable. This makes it easy to automatically save perspective sessions when Emacs exits:

(add-hook 'kill-emacs-hook #'persp-state-save)

A limitation of persp-state-save and persp-state-load is that they do not attempt to deal with non-file-visiting buffers with non-trivial state. Saving shell, REPL, and compilation-mode buffers is not supported. When saved to a file, any windows pointing to them are changed to point to the perspective's *scratch* buffer. (Live windows are, of course, left alone.)

Customization

Perspective supports several custom variables (see its section in M-x customize). The following are likely to be of most interest:

  • persp-sort: Select the order in which to sort perspectives when calling persp-switch. Defaults to 'name (alphabetical), but 'access (by most recently accessed) and 'created (by order created) are available. Note that persp-switch-by-number is likely to be confusing when this is set to 'access, as the numbers associated with a perspective will change all the time.
  • persp-interactive-completion-function: Used for prompting for a perspective name. completing-read is the default, with ido-completing-read enabled with ido-mode. ivy-completing-read is broadly compatible, but unfortunately sorts alphabetically and therefore breaks the persp-sort setting. Helm, unfortunately, does not have a completing-read compatible implementation out of the box (helm-completing-read-default-1 purports to be this but does not have the same &optional defaults). ido-completing-read is the recommended setting here unless a completing-read enhancement framework is used.
  • persp-mode-prefix-key: Changes the default key prefix for Perspective commands.
  • persp-state-default-file: Changes the default file to use for saving and loading Perspective state.
  • persp-show-modestring: Determines if Perspective should show its status in the modeline. It defaults to t, but can also be nil (turning off the modeline status display) or 'header (which uses the header line instead of the modeline).
  • persp-modestring-short: When set to t, show a shortened modeline string with only the current perspective instead of the full list. Defaults to nil.
  • persp-purge-initial-persp-on-save: When set to t, will kill all buffers of the initial perspective upon calling perps-state-save. The buffers whose name match a regexp in the list persp-purge-initial-persp-on-save-exceptions won't get killed. This allows using the initial perspective as a kind of scratch space.

To change keys used after the prefix key, with use-package you can do:

;; remap n to N to switch to next perspective
(use-package perspective
  :bind (
    :map perspective-map
      ("n" . nil)
      ("N" . persp-next)))

Or without use-package:

(define-key perspective-map (kbd "n") nil)
(define-key perspective-map (kbd "N") 'persp-next)

Some Musings on Emacs Window Layouts

The following discussion exceeds the needs of documenting Perspective, but it falls in the category of helping users learn to manage Emacs sessions, and therefore will likely help potential users of Perspective make the experience smoother.

Emacs has bad default behavior when it comes to window handling: many commands and modes have a habit of splitting existing windows and changing the user's carefully thought-out window layout. This tends to be a more serious problem for people who run Emacs on large displays (possibly in full-screen mode): the greater amount of screen real estate makes it easy to split the frame into many smaller windows, making any unexpected alterations more disruptive.

As a result of indiscriminate-seeming window splits and buffer switching in existing windows, new Emacs users can get into the habit of expecting Emacs and its packages to lack basic respect for their layouts. Hence the popularity of things like winner-mode, and packages like shackle.

This may make the value of Perspective seem questionable: why bother with carefully preserving window layouts if Emacs just throws them away on a M-x compile? The answer is to fix the broken defaults. This is fairly easy:

(customize-set-variable 'display-buffer-base-action
  '((display-buffer-reuse-window display-buffer-same-window)
    (reusable-frames . t)))

(customize-set-variable 'even-window-sizes nil)     ; avoid resizing

These settings do the following:

  1. Tell display-buffer to reuse existing windows as much as possible, including in other frames. For example, if there is already a *compilation* buffer in a visible window, switch to that window. This means that Emacs will usually switch windows in a "do what I mean" manner for a warmed-up workflow (one with, say, a couple of source windows, a compilation output window, and a Magit window).
  2. Prevent splits by telling display-buffer to switch to the target buffer in the current window. For example, if there is no *compilation* buffer visible, then the buffer in whichever window was current when compile was run will be replaced with *compilation*. This may seem intrusive, since it changes out the current buffer, but keep in mind that most buffers popped up in this manner are easy to dismiss, either with a dedicated keybinding (often q) or the universally-applicable kill-buffer. This is easier than restoring window arrangements. It is also easier to handle for pre-arranged window layouts, since the appropriate command can simply be run in a window prepared for it in advance. (If this is a step too far, then replace display-buffer-same-window with display-buffer-pop-up-window.)

(An earlier version of this hint modified display-buffer-alist instead of display-buffer-base-action. This was too aggressive and can impact packages which may legitimately want to split windows.)

Documentation of the Emacs framework responsible for "pop-up" windows, display-buffer, is dense and difficult to read, so there have been attempts to summarize the most important bits:

perspective-el's People

Contributors

aaronjensen avatar adrieankhisbe avatar che2 avatar csantosb avatar csrhodes avatar deactivated avatar dme avatar fred-o avatar gcv avatar gzj avatar intramurz avatar ipvych avatar jleechpe avatar john2x avatar mehw avatar nex3 avatar nicholasbhubbard avatar nnicandro avatar qiangf avatar redshirtrob avatar rgilton avatar schouleu avatar senny avatar sillygod avatar spwhitton avatar syohex avatar tarsius avatar txgvnn avatar wfarr avatar zenspider avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

perspective-el's Issues

Feature request - iBuffer support

If you feel like it, could you please add iBuffer support? I use it quite a bit and when in different perspectives, it always displays all the buffers, instead of only those imported.

Thanks!

New update breaks setup because of persp-buffer-in-other-p

Hi guys, I get this error at initialization, don't know how to debug it. i removed every setup I had for perspective in my emacs and it still gives me the same problem. I use custom perspectives a lot, so every time I upgrade all packages from melpa I have to downgrade perspective. Is there a way i can contribute to solving this issue? please let me know.

Warning (initialization): An error occurred while loading `/home/io/.emacs.d/init.el':
Symbol value as a variable is void persp-buffer-in-other-p

can't kill a perspective: `Buffer #<killed-buffer> is not a live buffer`

Hi, I am using perspective 20140606.1246 (installed with melpa under emacs 24.3) and it's a great way to manage so many buffers I have in emacs. However, I find it difficult to kill a perspective properly. I have the same issue as #22 Besides, when I tired to kill a perspective, I often see this error message

Buffer #<killed-buffer> is not a live buffer

How to fix this?

ido-switch-buffer does not honor ido-ignore-buffers

When persp-mode is enabled any ignored buffers become visible. Doing an 'ido-switch-buffer' shows buffers like Minibuf-x and Echo Area x.

Ideally it would be possible to customize (and toggle) ido-ignore-buffers with persp-mode enabled.

Get persp name from number

every perspective has a number and a name. Is there a good way to get the perspective name when you have the number and vice versa?

Feature request: check whether Perspective Mode is enabled.

When an user calls a Perspective command while Perspective Mode is not enabled, the call could fail with a cryptic error. For instance, persp-switch fails with let*: Wrong type argument: hash-table-p, nil. A more user-friendly approach would be to alert the user, for instance by adding this snippet of code at the beginning of each command:

(unless (bound-and-true-p persp-mode)
  (error "Perspective Mode is not enabled."))

Or even:

(unless persp-mode
  (persp-mode 1))

Thanks for your attention.

Confusing package names

I see these packages available in Emacs:

  persp-mode       h 20151017… available  melpa       46  "perspectives" shared among frames + save/load - bugs. 
  perspective      h 20151016… available  melpa      211  switch between named "perspectives" of the editor

Your readme says to install perspective but to activate persp-mode.

What do I do? D:

Add multiple buffers at once

I use Helm, so when I tried persp-add-buffer, I selected several buffers with Helm, but only the first one was added. It would be very helpful if you could add multiple buffers at once. I was going to add all my org-mode buffers to an org-mode perspective, but doing it one-at-a-time...

Cannot kill perspective in emacs --daemon mode

Greetings!

Huge fan of persp-mode; I use it all the time in my development work. I've discovered one small issue with it when using it in an emacsclient connected to a process launched from emacs --daemon. Process I used to get into that state:

emacs --daemon --quick
emacsclient -t

M-x load-file
M-x persp-mode
C-x x s foo
C-x x c foo

At that point, emacs fails with "wrong-type-argument hash-table-p nil"

Here's the debug dump:

Debugger entered--Lisp error: (wrong-type-argument hash-table-p nil)
maphash((lambda (--cl-var-- persp) (if (and ... ...) (progn ...))) nil)
(catch (quote --cl-block---cl-finish----) (maphash (lambda ... ...) (with-selected-frame frame perspectives-hash)))
(cl-block-wrapper (catch (quote --cl-block---cl-finish----) (maphash ... ...)))
(block --cl-finish-- (maphash (lambda ... ...) (with-selected-frame frame perspectives-hash)))
(catch (quote --cl-block-nil--) (block --cl-finish-- (maphash ... ...)) nil)
(cl-block-wrapper (catch (quote --cl-block-nil--) (block --cl-finish-- ...) nil))
(block nil (block --cl-finish-- (maphash ... ...)) nil)
(loop for persp being the hash-values of (with-selected-frame frame perspectives-hash) if (and (not ...) (memq buffer ...)) do (return-from persp-buffer-in-other-p (cons frame ...)))
(while (consp --cl-var--) (setq frame (car --cl-var--)) (loop for persp being the hash-values of (with-selected-frame frame perspectives-hash) if (and ... ...) do (return-from persp-buffer-in-other-p ...)) (setq --cl-var-- (cdr --cl-var--)))
(let* ((--cl-var-- ...) (frame nil)) (while (consp --cl-var--) (setq frame ...) (loop for persp being the hash-values of ... if ... do ...) (setq --cl-var-- ...)) nil)
(catch (quote --cl-block-nil--) (let* (... ...) (while ... ... ... ...) nil))
(cl-block-wrapper (catch (quote --cl-block-nil--) (let* ... ... nil)))
(block nil (let* (... ...) (while ... ... ... ...) nil))
(loop for frame in (frame-list) do (loop for persp being the hash-values of (with-selected-frame frame perspectives-hash) if (and ... ...) do (return-from persp-buffer-in-other-p ...)))
(catch (quote --cl-block-persp-buffer-in-other-p--) (loop for frame in (frame-list) do (loop for persp being the hash-values of ... if ... do ...)) nil)
(cl-block-wrapper (catch (quote --cl-block-persp-buffer-in-other-p--) (loop for frame in ... do ...) nil))
(block persp-buffer-in-other-p (loop for frame in (frame-list) do (loop for persp being the hash-values of ... if ... do ...)) nil)
persp-buffer-in-other-p(#<buffer scratch (foo)>)
(not (persp-buffer-in-other-p buffer))
(cond ((not ...) (kill-buffer buffer)) ((eq buffer ...) (bury-buffer)) (t (bury-buffer buffer)))
persp-remove-buffer(#<buffer scratch (foo)>)
mapcar(persp-remove-buffer (#<buffer scratch (foo)>))
(progn (persp-switch name) (run-hooks (quote persp-killed-hook)) (mapcar (quote persp-remove-buffer) (persp-buffers persp-curr)) (setf (persp-killed persp-curr) t))
(unwind-protect (progn (persp-switch name) (run-hooks ...) (mapcar ... ...) (setf ... t)) (when G92002 (persp-switch G92002)))
(let ((G92002 ...) (last-persp-cache persp-last)) (unwind-protect (progn ... ... ... ...) (when G92002 ...)) (setq persp-last last-persp-cache))
(progn (let (... ...) (unwind-protect ... ...) (setq persp-last last-persp-cache)))
(with-perspective name (run-hooks (quote persp-killed-hook)) (mapcar (quote persp-remove-buffer) (persp-buffers persp-curr)) (setf (persp-killed persp-curr) t))
persp-kill(nil)
call-interactively(persp-kill nil nil)

Known workaround:

  • Running persp-mode again to disable the mode clears the perspectives, and I can then re-create them by hand.

My emacs version is
M-x version
GNU Emacs 23.1.1 (i486-pc-linux-gnu, GTK+ Version 2.20.1) of 2011-03-04 on palmer, modified by Debian

I'd be happy to answer any questions / run any tests on this end that may be helpful!

Dies on load

Disabled elscreen, restarted emacs, ran persp-mode manually and got the following:

Debugger entered--Lisp error: (void-variable +)
  autoload-do-load((autoload "perspective" "Toggle perspective mode.\nWhen active, keeps track of multiple 'perspectives',\nnamed collections of buffers and window configurations.\n\n(fn &optional ARG)" t nil) persp-mode)
  command-execute(persp-mode record)
  execute-extended-command(nil "persp-mode")
  call-interactively(execute-extended-command nil nil)
  command-execute(execute-extended-command)

Maintaining perspective

Per discussion with @nex3... @gcv and I have a vested interest in maintaining perspective. Should we be added as collaborators? Move the project to a new org (possibly breaking melpa, etc)? Etc.

This issue is here to open up the floor for discussion.

perspective hides buffers created by erc-autojoin-channels-alist

Hi. When i turn on perspective via (persp-mode) all buffers created in background by erc from erc-autojoin-channels-alist are not visible in buffers list (M-x list-buffers, C-x C-b)

Thanks.

How to reproduce:

(setq debug-on-error t)

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.milkbox.net/packages/") t)

(package-initialize)

(require 'perspective)
(persp-mode)

(setq erc-join-buffer (quote bury))
(setq erc-autojoin-mode t)
(setq erc-autojoin-channels-alist (list (list "freenode" "#emacs")))

(erc :server "irc.freenode.net" :nick "testtest")

Incompatible with ido-use-virtual-buffers

In the latest Emacs, ido-use-virtual-buffers enables the re-opening of recently-edited files by including them in the buffer list displayed by ido-switch-buffer. In persp-mode, those buffers don't get listed. I'm not exactly sure what the ideal behavior would be in this case, but perhaps it would be useful to add a toggle which would allow persp-mode to honor that ido flag.

Incompatible with lsp-ui

Emacs version - 26.1

I use perspective in pair with lsp-ui.

When lsp-ui-doc feature called (popup with documentation), I got: error in process filter: persp-add-buffer: Wrong type argument: perspective, nil.

On MacOS High Sierra in fullscreen mode, desktop workspace with full screen empty Emacs window created after each of error.

On Ubuntu 18.04 (Emacs 25.3.2) I don't know why, but I don't have this error.

I found a topic with similar error and its dated half year ago:
https://www.reddit.com/r/emacs/comments/93kwtu/how_do_i_debug_a_function_thats_being_called_when/

Perspectives lost after last frame is closed when running in daemon mode

By default, perspectives are not shared between frames. To import a perspective to another frame, the 'persp-import' command can be used. This works as expected as long as the frame from which perspectives are improted is still open, but once that frame is closed, the perspectives belonging to the frame are lost forever, and the only way to recover the buffers from those lost frames are to either:
o use 'persp-add-buffer' to add each buffer manually
o shut down persp-mode

This is not ideal, especially in daemon mode, where the last frame would frequently be closed logging out of an ssh session, but perspectives are gone when a new frame is created in the same emacs daemon after logging back in.

I suggest that either:

  • Add an option to share perspectives between all frames (which is done by https://github.com/Bad-ptr/persp-mode.el).
  • Automatically transfer any perspectives to a closed frame to one of the remaining frames, and if the last frame is closed in daemon mode, the perspectives are automatically transfer to the first new frame is that is created from the same daemon.

Option 1 is probably the simplist to implement (it's already done by persp-mode), and also a good work around to the problem. Option 2 is arguably more sane, as it fixes the (broken) behavior.

Make persp-find-some smarter

I'm not thrilled with the way persp-find-some works when you're killing off perspectives.

The gist: Let's say you're using this mode (persps sorted chronologically) to do a yak shave and you have several perspectives pushed on the stack. You finish up some of them and start to kill the perspectives. The first time, it uses persp-last to switch to the last one you were on. That seems fine. But after that, persp-last is nil and it goes to (car (persp-names)) instead. That doesn't really match the workflow for this mode and should be something a bit smarter (newest, or persp-last should maintain a stack, or something).

Originally posted by @zenspider in #87 (comment)

It cannot be used with elscreen-persist

It would be a really great feature if it would support (elscreen-persist)!

It cannot load, suffering from a # on boot.

Steps to reproduce:

  1. init persp-mode
  2. init elscreen-persist
  3. elscreen-persist-store
  4. restart emacs, and elscreen-persist-restore

Result is that it chokes on a #

Incompatible with ECB

I got error message below when trying to switch perspective with ECB enabled.

ecb-error: ECB 2.40 - Error: switch-to-buffer: Can only switch to visible special ecb-buffers!

emacsclient crashes with error *ERROR*: Perspective `main` already exists

Sometimes, if I already have an emacsclient open (typically a gui window) and try to start another one (typically a terminal client), emacsclient will die immediately

If I start it with emacsclient -c it give me this:
*ERROR*: Perspectivemainalready exists.

If I start with emacsclient -t it just really messes up my terminal because it starts to layout the emacs screen but then crashes in a bad state.

It looks like this error message comes from persp-rename. I'm not sure why persp-rename is called when emacsclient starts. But even if it causes a problem I don't think it should crash the client.

2.0 change of persp-curr from var to fn returning custom type breaking change

this change breaks the ability to grab the current perspective's name;
example:

(evil-leader/set-key
  "sv" (lambda () (interactive)         ; toggle (s)hell (v)isor
         (multi-term-dedicated-toggle)
         (multi-term-dedicated-select))
  "sn" (lambda () (interactive)         ; toggle (s)hell (n)ew
         ;; update buffer name setting dynamically for each perspective
         (setq-default multi-term-buffer-name (concat "term-" (elt persp-curr 1)))
         (multi-term)))

updating this to be a function call to (persp-curr) doesn't resolve the issue as any sequence functions won't work on the return value since type-of is a custom type perspective.

ELISP> (type-of (persp-curr))
perspective

Seems perspective is not working with emacs 26.2

After installed perspective from MELPA, I added (persp-mode) to .emacs.
I got following error when opening emacs...

Symbol's function definition is void: hash-table-values

Seems this also breaks emacs and I am unable to close emacs or switch buffer.
I got following error when I tried to switch buffer.

persp-complete-buffer: Wrong type argument: perspective, nil

Feature request: swich to perspective according to buffer

Hello,

thanks for sharing this useful package.

I wonder whether it could be possible to switch to a perspective by switching to a buffer. Currently, you must switch perspective first and then buffer. Being able to switch to a buffer directly would not only save typing, but also mental overhead. This assumes that each buffer belongs to one perspective only, which should be the case when users are accustomed to use Perspective Mode.

Thanks for your attention.

bug for emacs 23.2.50.1

bug causes constant errors on buffer-changes. very annoying.

>> diff perspective-el/perspective.el elisp/perspective.el 
548c548,549
<   (persp-add-buffer (or (bound-and-true-p buffer) buffer-or-name)))

---
>   (persp-add-buffer (buffer-file-name)))

I don't know how long the buffer-file-name function has been around.

`desktop-read` breaks perspective-mode, and nearly everything else

After attempting to run desktop-read, with nothing terribly complicated in it, all interactions with perspective, or switch-to-buffer, or debugger-on-error fail out. The fact that I can't bring up the debugger at all is the sticking point for me. I can't even provide you with any other info but this:

*Messages* buffer:

Debug on Error enabled globally
ad-handle-definition: ‘imenu’ got redefined
Starting new Ispell process /usr/local/bin/aspell with english dictionary...
Desktop: File "/Users/ryan/Work/git/chef/inspec/results/test.unit.resources.http.test.rb.log" no longer exists.
Desktop: Directory /Users/ryan/Work/git/chef/inspec/results/ no longer exists.
Wrote /Users/ryan/.emacs.d/.emacs.desktop.lock
Desktop: 1 frame, 13 buffers restored, 2 failed to restore.
Entering debugger...
xding
ad-Advice-recursive-edit: Wrong type argument: hash-table-p, "Unprintable entity"
Entering debugger...
xding
ad-Advice-recursive-edit: Wrong type argument: hash-table-p, "Unprintable entity"
Mark set

Those last two errors are me trying to use perspective-switch and switch-to-buffer I believe.

Basic process for PRs

I'm totally fine if we merge if one of us approves a PR, but I'm also open to requiring 2 of us. This issue is here for discussion.

I'd recommend we use PRs as well. I'm not going to process-nazi this up with tons of bureaucracy tho. I'd be fine if something goes straight to master if it is an obvious fix to a recent problem.

Improve kill-buffer behavior

Right now, using kill-buffer can sometimes replace the buffer in the current window with a buffer from a different perspective. It seems to have something to do with which was most recently displayed. I believe this happens because kill-buffer calls replace-buffer-in-windows, which in turn calls switch-to-prev-buffer (which is fairly complicated).

I wonder if there is a way to advise switch-to-prev-buffer to respect perspectives, and not pop up a buffer from a different perspective?

does not work with emacs 26.1

(use-package perspective
:ensure t
:disabled
:config
(persp-mode)
)

(use-package persp-projectile
:after (projectile perspective)
:disabled
:ensure t
:config
;; (define-key projectile-mode-map (kbd "s-s") 'projectile-persp-switch-project)
)

when start emacs, show error:
Error (frameset): Wrong type argument: perspective, "Unprintable entity"

load-theme resets perspectives

When I run (load-theme 'solarized-dark t), all perspectives are lost and only the current perspective is kept. Not sure if this is a bug, and sadly I don't have enough Emacs-fu to help solving this :( Anything else I can do to help?

Question around how to use persp-kill

  ;; Need to skip doing anything if last perspective and last window.
  ;; And also get persp-kill to kill the current perspective instead of forcing interaction.
  (defun delete-perspective-or-window()
    "Delete perspective if last window left but delete window if more than one."
    (interactive)
    (if (eq (count-windows) 1)
        (persp-kill nil) ;; (persp-kill persp-curr)
      (delete-window)))

I'm trying to write a wrapper method to selectively call persp-kill or delete-window depending on the window count. (persp-kill nil) works but brings up interaction. I'd prefer (persp-kill) to automatically end kill the perspective.

Also wondering if perspective is exposing another variable to check the number of perspectives currently up.

Thanks!

Load last perspective session on Emacs startup?

Hi, this is a great Emacs script. Yet I have a question:

How can I keep my persp setup persistant even if I restart Emacs? (autoload on startup)

I searched the source for a solution, but couldn't find it. It would be really nice, if you could help with this. I can't imagine that I have to setup my persp tags on every restart of Emacs.

unusual ordering of the buffers

when I use perspective.el "C-x b" does not seem to change to the last active buffer, which is very annoying. I'm not quite sure how it changes the order but it seems to always switch back to the same buffer.

Automatically switches perspective when switching to a buffer

I think this would be a useful feature. Suppose that perspective now has a command to switch to all buffer currently opened in Emacs. However, the difference is, when a buffer is selected and that buffer belongs to a different perspective, switch to that perspective.

This is similar to how ido-switch-buffer switches buffer when there are 2 or more frames: when a selected buffer is visible in a frame, simply switch to that frame instead.

"Symbol's value as variable is void: <" , after last commit

After updating perspective on melpa .. with the last commit 1358ba2 , I get this error:

Symbol's value as variable is void: <

I'm on Emacs 26.1 on OSX 10.13.6, perspective from Melpa, and this happens even with only this as init.el

(require 'package)
(package-initialize)
(persp-mode)

EDIT:

Deleted some things I wrote before ... because I discovered that this only happens with the MELPA version ...
Cloning the rep and using:

(add-to-list 'load-path "~/.emacs.d/perspective-el")
(require 'perspective)
(persp-mode)

Don't give me any error.

switch-persp not working when given a new perspective name: let: Wrong type argument: stringp, nil

persp-mode loads well now (at least here, where I implemented an admittedly very local bug-fix for the bug that I listed here, earlier), but if you switch to a new perspective, when make-persp is called, it is given a set of args in which name evaluates to name, and not to what the user had typed. So it doesn't work at all. evaluating ARGS at the beginning of execution of MAKE-PERSP gives:

args (:name name (switch-to-buffer (concat "*scratch* (" name ")")) (funcall initial-major-mode) (delete-other-windows))

the result is (after the list is reversed)
keywords (:name name)

and, finally,
let: Wrong type argument: stringp, nil

Feature Request: Perspective-specific next/prev buffer switch

At least I know, perspective doesn't have features that is like switch-to-next-buffer or switch-to-prev-buffer using specific perspective.

In detail, there is no simple way to change C-x <C-left> (switch-to-prev-buffer) to perspective-relative one.
For example, suppose that I have 2 perspective perspA and perspB, and there are 5 buffers in perspA, and there are 7 buffers in perspB. In this case, I can't traverse my buffers only which are in perspA, and while traversing, all buffers of perspB will join to perspA and everything is messed up.

Could you add these features(next/prev) to this wonderful package?

Feature request

Is it possible to add a perspective tab on the side(something like a neotree), listing the current files/buffers/directory structure inside?

Motivation for this is that, I often find myself working with a large code base ( lots of files/directories), but at a given time, I am just interested in a few of them, if perspective allows me to easily define/add/delete/modify the perspective definition, that would be a great productivity boost.

Get a list of perspectives in the modeline/... to act like vim tabs

Hi,

I tend to use perspective (as part of spacemacs) to manage a vim tabs-like environment.
However this approach doesn't give any visual cues as to which perspectives are currently open: you only see the perspective number. Is there a way to see a list?

FTR, this is how it looks on vim:

Not advising buffer-list ?

I looked through the open and closed issues for something related to this and didn't find anything.

I'm a little surprised that you're not advising on buffer-list as that would be the entry point for many/most 3rd party buffer managers (eg I use bs and there are several feature requests for others).

Would this be something you'd like? Or is there a reason not to do it (eg, safety)? I'd like this to support bs-show and would have expected that support to be near free, if not automatic via buffer-list.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.