Move eyebrowse to spacemacs-layouts layer and add documentation

Add toggle capability with ? for workspaces transient state
Remove the variable eyebrowse-display-help
This commit is contained in:
syl20bnr 2016-03-20 21:48:06 -04:00
parent 744cd0f9b7
commit 944960daf8
14 changed files with 945 additions and 1018 deletions

View File

@ -59,14 +59,12 @@
- [[The vim-surround case][The vim-surround case]]
- [[Evil plugins][Evil plugins]]
- [[Binding keys][Binding keys]]
- [[Spacemacs UI][Spacemacs UI]]
- [[Graphical UI][Graphical UI]]
- [[Color themes][Color themes]]
- [[Font][Font]]
- [[Graphical UI Toggles][Graphical UI Toggles]]
- [[GUI Elements][GUI Elements]]
- [[Color themes][Color themes]]
- [[Font][Font]]
- [[GUI Toggles][GUI Toggles]]
- [[Global line numbers][Global line numbers]]
- [[Mouse usage][Mouse usage]]
- [[Mode-line][Mode-line]]
- [[Mode-line][Mode-line]]
- [[Powerline font installation for terminal-mode users][Powerline font installation for terminal-mode users]]
- [[Flycheck integration][Flycheck integration]]
- [[Anzu integration][Anzu integration]]
@ -74,6 +72,15 @@
- [[Powerline separators][Powerline separators]]
- [[Minor Modes][Minor Modes]]
- [[Customizing the mode-line][Customizing the mode-line]]
- [[Layouts and workspaces][Layouts and workspaces]]
- [[Layouts][Layouts]]
- [[The default layout][The default layout]]
- [[Project layouts][Project layouts]]
- [[Custom Layouts][Custom Layouts]]
- [[Save/Load layouts into a file][Save/Load layouts into a file]]
- [[Layout key bindings][Layout key bindings]]
- [[Workspaces][Workspaces]]
- [[Workspace key bindings][Workspace key bindings]]
- [[Commands][Commands]]
- [[Vim key bindings][Vim key bindings]]
- [[Escaping][Escaping]]
@ -167,6 +174,7 @@
- [[Deleting files][Deleting files]]
- [[Editing Lisp code][Editing Lisp code]]
- [[Lisp Key Bindings][Lisp Key Bindings]]
- [[Mouse usage][Mouse usage]]
- [[Managing projects][Managing projects]]
- [[Registers][Registers]]
- [[Errors handling][Errors handling]]
@ -849,20 +857,13 @@ key-discovery tools can use (e.g., which-key).
There is much more to say about bindings keys, but these are the basics. Keys
can be bound in your =~/.spacemacs= file or in individual layers.
* Spacemacs UI
Spacemacs has unique UI elements to make the Emacs experience even more
enjoyable:
- dedicated startup page with a mode aimed at easily managing Spacemacs
- dedicated helm source via =helm-spacemacs-help=
- a [[https://github.com/justbur/emacs-which-key][which-key]] buffer
** Graphical UI
* GUI Elements
Spacemacs has a minimalistic and distraction free graphical UI:
- custom [[https://github.com/milkypostman/powerline][powerline]] mode-line [[Flycheck integration][with color feedback]] according to current [[https://github.com/flycheck/flycheck][Flycheck]] status
- Unicode symbols for minor mode lighters which appear in the mode-line
- [[Errors handling][custom fringe bitmaps]] and error feedbacks for [[https://github.com/flycheck/flycheck][Flycheck]]
*** Color themes
** Color themes
The official Spacemacs theme is [[https://github.com/nashamri/spacemacs-theme][spacemacs-dark]] and it is the default theme
installed when you first started Spacemacs. There are two variants of the
@ -900,7 +901,7 @@ You can see samples of all included themes in this [[http://themegallery.robdor.
*Hint*: If you are an =Org= user, [[https://github.com/fniessen/emacs-leuven-theme][leuven-theme]] is amazing ;-)
*** Font
** Font
The default font used by Spacemacs is [[https://github.com/adobe-fonts/source-code-pro][Source Code Pro]] by Adobe. It is
recommended to install it on your system.
@ -966,7 +967,7 @@ separators like on the following screenshot (default value is 1.1).
[[file:img/crappy-powerline-separators.png]]
*** Graphical UI Toggles
** GUI Toggles
Some graphical UI indicators can be toggled on and off (toggles start with ~t~
and ~T~):
@ -1010,14 +1011,7 @@ If it is set to =relative=, line numbers are show in a relative way:
(setq-default dotspacemacs-line-numbers 'relative)
#+END_SRC
*** Mouse usage
There are some added mouse features set for the line number margin (if shown):
- single click in line number margin visually selects the entire line
- drag across line number margin visually selects the region
- double click in line number margin visually select the current code block
*** Mode-line
** Mode-line
The mode line is a heavily customized [[https://github.com/milkypostman/powerline][powerline]] with the following capabilities:
- show the window number
- color code for current state
@ -1175,6 +1169,160 @@ right hand side variables.
Please see the Spaceline documentation for more information.
* Layouts and workspaces
Layouts are window configurations with buffer isolation, each layout can define
several workspaces (think of them as sub-layouts) sharing the same list of
buffers as their parent layout.
** Layouts
A layout is a window configuration associated with a list of buffers. The list
of buffers can be an arbitrarily chosen set of buffers. Spacemacs provides
some facilities to create meaningful sets of buffers, for instance the buffers
related to a projectile project.
The name of the current layout appears in the mode-line at the far left (first
element of the mode-line).
To create a new layout type a layout number that does not exist yet.
For instance if you have two layouts currently then type ~SPC l 3~ to create a
third layout.
*** The default layout
The =default= layout (the layout created at the startup of Emacs) is not
displayed in the mode-line but it is possible to display it by setting the
variable =dotspacemacs-display-default-layout= to =t=.
Its name is "default" by default but it can be changed by setting the variable
=dotspacemacs-default-layout-name=.
The =default= layout is special because it has a global scope which means that
all the opened buffers belong to it. So using only the =default= layout feels
like not using layouts at all.
*** Project layouts
A project layout is bound to a projectile project. To create a project layout
use ~SPC p l~.
The name of the layout is the name of the project root directory.
*** Custom Layouts
Custom layouts can be defined using the macro ~spacemacs|define-custom-layout~,
they are accessible via ~SPC l o~.
By convention the name of a custom layout should start with =@=.
Example of custom layout definition for =ERC= buffers:
#+BEGIN_SRC emacs-lisp
(spacemacs|define-custom-layout "@ERC"
:binding "E"
:body
(progn
;; hook to add all ERC buffers to the layout
(defun spacemacs-layouts/add-erc-buffer-to-persp ()
(persp-add-buffer (current-buffer)
(persp-get-by-name
erc-spacemacs-layout-name)))
(add-hook 'erc-mode-hook #'spacemacs-layouts/add-erc-buffer-to-persp)
;; Start ERC
(call-interactively 'erc)))
#+END_SRC
Then use ~SPC l o E~ to start ERC inside its own layout. Any new ERC buffer
will be part of the custom layout.
Some custom layouts that ship with Spacemacs:
| Name | Key Binding | Description |
|------------+-------------+---------------------------------------------------------------------------------|
| @Spacemacs | ~e~ | Custom perspective containing all buffers of =~/.emacs.d= |
| @ERC | ~E~ | Custom perspective containing all ERC buffers (needs the erc layer enabled) |
| @RCIRC | ~i~ | Custom perspective containing all RCIRC buffers (needs the rcirc layer enabled) |
| @Org | ~o~ | Custom perspective containing all the =org-agenda= buffers |
*** Save/Load layouts into a file
With ~SPC l s~ and ~SPC l L~ you can save and load layouts to/from a file.
*Note:* By default, Spacemacs will automatically save the layouts under the name
=persp-auto-save=.
Setting the variable =dotspacemacs-auto-resume-layouts= to =t= will
automatically resume the last saved layouts.
*** Layout key bindings
| Key Binding | Description |
|-------------------+------------------------------------------------------------|
| ~SPC l~ | activate the transient- state |
| ~?~ | toggle the documentation |
| ~[1..9, 0]~ | switch to nth layout |
| ~[C-1..C-9, C-0]~ | switch to nth layout and keep the transient-state active |
| ~<tab>~ | switch to the latest layout |
| ~a~ | add a buffer to the current layout |
| ~A~ | add all the buffers from another layout in the current one |
| ~b~ | select a buffer in the current layout |
| ~d~ | delete the current layout and keep its buffers |
| ~D~ | delete the other layouts and keep their buffers |
| ~h~ | go to default layout |
| ~C-h~ | previous layout in list |
| ~l~ | select/create a layout with helm |
| ~L~ | load layouts from file |
| ~C-l~ | next layout in list |
| ~n~ | next layout in list |
| ~N~ | previous layout in list |
| ~o~ | open a custom layout |
| ~p~ | previous layout in list |
| ~r~ | remove current buffer from layout |
| ~R~ | rename current layout |
| ~s~ | save layouts |
| ~t~ | display a buffer without adding it to the current layout |
| ~w~ | workspaces transient-state (needs eyebrowse layer enabled) |
| ~x~ | kill current layout with its buffers |
| ~X~ | kill other layouts with their buffers |
** Workspaces
Workspaces are like sub-layouts, they allow to define multiple layouts into a
given layout, those layouts share the same buffer as the parent layout.
The currently active workspace number is displayed before the window number,
for instance "➊|➍" or "1|4" means the fourth window of the first workspace.
At startup, the workspace number 1 is active. Switching to a workspace will
create it if it does not exist. For instance at startup you can press
~SPC l w 2~ to create the workspace 2.
The key bindings are registered in a transient-state. The docstring of the
transient-state displays the existing workspaces and the currently active
workspace has square brackets. Pressing a workspace number will activate it (or
create a new one) and exit the transient-state. It is possible to just preview a
workspace with ~Ctrl-<number>~. Pressing ~TAB~ will activate the previously
selected workspace. It is also possible to give a label to the current workspace
by pressing ~r~.
*** Workspace key bindings
Global key bindings:
| Key Binding | Description |
|-------------+--------------------------------------|
| ~gt~ | go to next workspace |
| ~gT~ | got to previous workspace |
| ~SPC b W~ | go to workspace and window by buffer |
Transient state key bindings:
| Key Binding | Description |
|-------------------+-------------------------------------------------------------|
| ~SPC l w~ | activate the transient-state |
| ~?~ | toggle the documentation |
| ~[1..9, 0]~ | switch to nth workspace |
| ~[C-1..C-9, C-0]~ | switch to nth workspace and keep the transient-state active |
| ~TAB~ | switch to last active workspace |
| ~d~ | close current workspace |
| ~n~ or ~l~ | switch to next workspace |
| ~N~ or ~p~ or ~h~ | switch to previous workspace |
| ~R~ | set a tag to the current workspace |
| ~w~ | switched to tagged workspace |
* Commands
** Vim key bindings
Spacemacs is based on =Vim= modal user interface to navigate and edit text. If
@ -1229,7 +1377,6 @@ state= to press quickly ~jj~ and inadvertently escape to =normal state=.
The emacs command key ~SPC~ (executed after the leader key) can be changed
with the variable =dotspacemacs-emacs-command-key= of your =~/.spacemacs=.
*** Leader key
On top of =Vim= modes (modes are called states in Spacemacs) there is a
special key called the leader key which once pressed gives a whole new keyboard
@ -2625,6 +2772,13 @@ These commands automatically switch to =lisp state=.
| ~SPC m t b~ | execute buffer tests |
| ~SPC m t q~ | ask for test function to execute |
*** Mouse usage
There are some added mouse features set for the line number margin (if shown):
- single click in line number margin visually selects the entire line
- drag across line number margin visually selects the region
- double click in line number margin visually select the current code block
** Managing projects
Projects in Spacemacs are managed with [[https://github.com/bbatsov/projectile][projectile]]. In =projectile= projects
are defined implicitly, for instance the root of a project is found when a

View File

@ -24,6 +24,9 @@
(defvar spacemacs--layouts-ts-full-hint-toggle 0
"Display a short doc when nil, full doc otherwise.")
(defvar spacemacs--workspaces-ts-full-hint-toggle 0
"Display a short doc when nil, full doc otherwise.")
(defvar spacemacs--last-selected-layout dotspacemacs-default-layout-name
"Previously selected layout.")

View File

@ -0,0 +1,540 @@
;;; funcs.el --- Spacemacs Layouts Layer functions File
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
;; General Persp functions
(defun spacemacs//current-layout-name ()
"Get name of the current perspective."
(safe-persp-name (get-frame-persp)))
(defun spacemacs//layout-autosave ()
"Perspectives mode autosave.
Autosaves perspectives layouts every `persp-autosave-interal' seconds.
Cancels autosave on exiting perspectives mode."
(if (and persp-mode layouts-enable-autosave)
(progn
(message "Perspectives mode autosaving enabled.")
(setq spacemacs--layouts-autosave-timer
(run-with-timer
layouts-autosave-delay
layouts-autosave-delay
(lambda ()
(message "Saving perspectives to file.")
(persp-save-state-to-file)))))
(when spacemacs--layouts-autosave-timer
(cancel-timer spacemacs--layouts-autosave-timer)
(setq spacemacs--layouts-autosave-timer nil))))
(defun spacemacs/jump-to-last-layout ()
"Open the previously selected layout, if it exists."
(interactive)
(unless (eq 'non-existent
(gethash spacemacs--last-selected-layout
*persp-hash* 'non-existent))
(persp-switch spacemacs--last-selected-layout)))
(defun spacemacs/alternate-buffer-in-persp ()
"Switch back and forth between current and last buffer in the
current perspective."
(interactive)
(with-persp-buffer-list ()
(switch-to-buffer (other-buffer (current-buffer) t))))
(defun spacemacs-layouts/non-restricted-buffer-list ()
(interactive)
(remove-hook 'ido-make-buffer-list-hook #'persp-restrict-ido-buffers)
(helm-mini)
(add-hook 'ido-make-buffer-list-hook #'persp-restrict-ido-buffers))
;; Persp transient-state
(defun spacemacs//layouts-ts-toggle-hint ()
"Toggle the full hint docstring for the layouts transient-state."
(interactive)
(setq spacemacs--layouts-ts-full-hint-toggle
(logxor spacemacs--layouts-ts-full-hint-toggle 1)))
(defun spacemacs//layout-format-name (name pos)
"Format the layout name given by NAME for display in mode-line."
(let* ((layout-name (if (file-directory-p name)
(file-name-nondirectory (directory-file-name name))
name))
(string-name (format "%s" layout-name))
(current (equal name (spacemacs//current-layout-name)))
(caption (concat (number-to-string (if (eq 9 pos) 0 (1+ pos)))
":" string-name)))
(if current
(propertize (concat "[" caption "]") 'face 'warning)
caption)))
(defun spacemacs//layouts-ts-hint ()
"Return a one liner string containing all the layout names."
(let* ((persp-list (or (persp-names-current-frame-fast-ordered)
(list persp-nil-name)))
(formatted-persp-list
(concat " "
(mapconcat (lambda (persp)
(spacemacs//layout-format-name
persp (position persp persp-list)))
persp-list " | "))))
(concat
formatted-persp-list
(if (equal 1 spacemacs--layouts-ts-full-hint-toggle)
spacemacs--layouts-ts-full-hint
(concat " (["
(propertize "?" 'face 'hydra-face-red)
"] help)")))))
(defun spacemacs/layout-switch-by-pos (pos)
"Switch to perspective of position POS."
(let ((persp-to-switch
(nth pos (persp-names-current-frame-fast-ordered))))
(if persp-to-switch
(persp-switch persp-to-switch)
(when (y-or-n-p
(concat "Perspective in this position doesn't exist.\n"
"Do you want to create one? "))
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch nil)
(spacemacs/home-delete-other-windows))))))
;; Define all `spacemacs/persp-switch-to-X' functions
(dolist (i (number-sequence 9 0 -1))
(eval `(defun ,(intern (format "spacemacs/persp-switch-to-%s" i)) nil
,(format "Switch to layout %s." i)
(interactive)
(spacemacs/layout-switch-by-pos ,(if (eq 0 i) 9 (1- i))))))
(defun spacemacs/layout-goto-default ()
"Go to `dotspacemacs-default-layout-name` layout"
(interactive)
(when dotspacemacs-default-layout-name
(persp-switch dotspacemacs-default-layout-name)))
(defun spacemacs/layouts-ts-rename ()
"Rename a layout and get back to the perspectives transient-state."
(interactive)
(call-interactively 'persp-rename)
(spacemacs/layouts-transient-state/body))
(defun spacemacs/layouts-ts-close ()
"Kill current perspective"
(interactive)
(persp-kill-without-buffers (spacemacs//current-layout-name)))
(defun spacemacs/layouts-ts-close-other ()
(interactive)
(call-interactively 'spacemacs/helm-persp-close)
(spacemacs/layouts-transient-state/body))
(defun spacemacs/layouts-ts-kill ()
"Kill current perspective"
(interactive)
(persp-kill (spacemacs//current-layout-name)))
(defun spacemacs/layouts-ts-kill-other ()
(interactive)
(call-interactively 'spacemacs/helm-persp-kill)
(spacemacs/layouts-transient-state/body))
;; Custom Persp transient-state
(defun spacemacs//custom-layout-func-name (name)
"Return the name of the custom-perspective function for NAME."
(intern (concat "spacemacs/custom-perspective-" name)))
(defmacro spacemacs|define-custom-layout (name &rest props)
"Define a custom-perspective called NAME.
FUNC is a FUNCTION defined using NAME and the result of
`spacemacs//custom-layout-func-name', it takes care of
creating the perspective NAME and executing the expressions given
in the :body property to this macro.
NAME is a STRING.
Available PROPS:
`:binding STRING'
Key to be bound to the function FUNC
`:body EXPRESSIONS'
One or several EXPRESSIONS that are going to be evaluated after
we change into the perspective NAME."
(declare (indent 1))
(let* ((name (if (symbolp name)
(symbol-value name)
name))
(func (spacemacs//custom-layout-func-name name))
(binding-prop (car (spacemacs/mplist-get props :binding)))
(binding (if (symbolp binding-prop)
(symbol-value binding-prop)
binding-prop))
(body (spacemacs/mplist-get props :body))
(already-defined? (cdr (assoc binding
spacemacs--custom-layout-alist))))
`(progn
(defun ,func ()
,(format "Open custom perspective %s" name)
(interactive)
(let ((initialize (not (gethash ,name *persp-hash*))))
(persp-switch ,name)
(when initialize
(delete-other-windows)
,@body)))
;; Check for Clashes
(if ,already-defined?
(unless (equal ,already-defined? ,name)
(spacemacs-buffer/warning "Replacing existing binding \"%s\" for %s with %s"
,binding ,already-defined? ,name)
(push '(,binding . ,name) spacemacs--custom-layout-alist))
(push '(,binding . ,name) spacemacs--custom-layout-alist)))))
(defun spacemacs/select-custom-layout ()
"Update the custom-perspectives transient-state and then activate it."
(interactive)
(spacemacs//update-custom-layouts)
(spacemacs/custom-layouts-transient-state/body))
(defun spacemacs//custom-layouts-ms-documentation ()
"Return the docstring for the custom perspectives transient-state."
(if spacemacs--custom-layout-alist
(mapconcat (lambda (custom-persp)
(format "[%s] %s"
(car custom-persp) (cdr custom-persp)))
spacemacs--custom-layout-alist " ")
(spacemacs-buffer/warning (format "`spacemacs--custom-layout-alist' variable is empty" ))))
(defun spacemacs//update-custom-layouts ()
"Ensure the custom-perspectives transient-state is updated.
Takes each element in the list `spacemacs--custom-layout-alist'
format so they are supported by the
`spacemacs/custom-layouts-transient-state' macro."
(let (bindings)
(dolist (custom-persp spacemacs--custom-layout-alist bindings)
(let* ((binding (car custom-persp))
(name (cdr custom-persp))
(func-name (spacemacs//custom-layout-func-name name)))
(push (list binding func-name :exit t) bindings)))
(eval `(spacemacs|define-transient-state custom-layouts
:doc (concat (spacemacs//custom-layouts-ms-documentation))
:bindings
,@bindings))))
;; Helm integration
(defun spacemacs/persp-helm-mini ()
"As `helm-mini' but restricts visible buffers by perspective."
(interactive)
(with-persp-buffer-list ()
(helm-mini)))
(defun spacemacs//helm-perspectives-source ()
(helm-build-in-buffer-source
(concat "Current Perspective: " (spacemacs//current-layout-name))
:data (persp-names)
:fuzzy-match t
:action
'(("Switch to perspective" . persp-switch)
("Close perspective(s)" . (lambda (candidate)
(mapcar
'persp-kill-without-buffers
(helm-marked-candidates))))
("Kill perspective(s)" . (lambda (candidate)
(mapcar 'persp-kill
(helm-marked-candidates)))))))
(defun spacemacs/helm-perspectives ()
"Control Panel for perspectives. Has many actions.
If match is found
f1: (default) Select perspective
f2: Close Perspective(s) <- mark with C-SPC to close more than one-window
f3: Kill Perspective(s)
If match is not found
<enter> Creates perspective
Closing doesn't kill buffers inside the perspective while killing
perspectives does."
(interactive)
(helm
:buffer "*Helm Perspectives*"
:sources
`(,(spacemacs//helm-perspectives-source)
,(helm-build-dummy-source "Create new perspective"
:requires-pattern t
:action
'(("Create new perspective" .
(lambda (name)
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch name)
(unless (member name (persp-names-current-frame-fast-ordered))
(spacemacs/home))))))))))
;; ability to use helm find files but also adds to current perspective
(defun spacemacs/helm-persp-close ()
"Kills perspectives without killing the buffers"
(interactive)
(helm
:buffer "*Helm Kill Perspectives (without killing buffers)*"
:sources
(helm-build-in-buffer-source
(concat "Current Perspective: " (spacemacs//current-layout-name))
:data (persp-names)
:fuzzy-match t
:action
'(("Close perspective(s)" . (lambda (candidate)
(mapcar
'persp-kill-without-buffers
(helm-marked-candidates))))))))
(defun spacemacs/helm-persp-kill ()
"Kills perspectives with all their buffers"
(interactive)
(helm
:buffer "*Helm Kill Perspectives with all their buffers*"
:sources (helm-build-in-buffer-source
(s-concat "Current Perspective: "
(spacemacs//current-layout-name))
:data (persp-names)
:fuzzy-match t
:action
'(("Kill perspective(s)" .
(lambda (candidate)
(mapcar 'persp-kill
(helm-marked-candidates))))))))
(defun spacemacs/helm-persp-switch-project (arg)
(interactive "P")
(helm
:sources
(helm-build-in-buffer-source "*Helm Switch Project Layout*"
:data (lambda ()
(if (projectile-project-p)
(cons (abbreviate-file-name (projectile-project-root))
(projectile-relevant-known-projects))
projectile-known-projects))
:fuzzy-match helm-projectile-fuzzy-match
:mode-line helm-read-file-name-mode-line-string
:action '(("Switch to Project Perspective" .
(lambda (project)
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch project)
(let ((projectile-completion-system 'helm))
(projectile-switch-project-by-name project)))))))
:buffer "*Helm Projectile Layouts*"))
;; Ivy integration
(defun spacemacs/ivy-persp-switch-project (arg)
(interactive "P")
(ivy-read "Switch to Project Perspective: "
(if (projectile-project-p)
(cons (abbreviate-file-name (projectile-project-root))
(projectile-relevant-known-projects))
projectile-known-projects)
:action (lambda (project)
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch project)
(let ((projectile-completion-system 'ivy))
(projectile-switch-project-by-name project))))))
;; Eyebrowse
;; Eyebrowse uses window-state objects (as returned by `window-state-get') to
;; store window configurations, so here are some utility functions to help us
;; analyse window-states.
;; it might make more sense to move these functions to a more general place
(defun spacemacs/window-state-window-p (object)
"Return t if OBJECT is a window, as represented in window-state objects.
Note: this function doesn't test for real window objects, but for
representations of a window in a window-state object as returned by
`window-state-get'."
(and (listp object)
(memq (car object) '(leaf vc hc))))
(defun spacemacs/window-state-get-buffer (window)
"Get WINDOW's buffer.
WINDOW is the representation of a window in a window-state object.
The returned value is the representation of a buffer in a window-state
object."
(cdr (assq 'buffer window)))
(defun spacemacs/window-state-get-buffer-name (window)
"Get WINDOW's buffer's name.
WINDOW is the representation of a window in a window-state object."
(car (spacemacs/window-state-get-buffer window)))
(defun spacemacs/window-state-walk-windows-1 (window fn)
"Helper function for `spacemacs/window-state-walk-windows'."
;; WINDOW is a misleading name. WINDOW is a list that can represent a window,
;; or a concatenation of several windows. window-state objects are weird.
(let ((child-windows
(-filter #'spacemacs/window-state-window-p window))
(bare-window
;; if WINDOW contains more than one window, take only the first window
(--take-while (not (spacemacs/window-state-window-p it))
window)))
(--each child-windows
(spacemacs/window-state-walk-windows-1 it fn))
(push (funcall fn bare-window) result)))
(defun spacemacs/window-state-walk-windows (state fn)
"Execute FN once for each window in STATE and make a list of the results.
FN is a function to execute.
STATE is a window-state object."
(let (result)
(spacemacs/window-state-walk-windows-1 (cdr state) fn)
result))
(defun spacemacs/window-state-all-windows (state)
"Get all windows contained in STATE.
STATE is a window-state object.
The returned windows are not actual window objects. They are windows as
represented in window-state objects."
(spacemacs/window-state-walk-windows state #'identity))
(defun spacemacs/window-state-get-buffer-names (state)
"Get names of all buffers saved in STATE.
STATE is a window-state object as returned by `window-state-get'."
(delq nil (spacemacs/window-state-walk-windows state #'spacemacs/window-state-get-buffer-name)))
(defun spacemacs/window-state-get-buffers (state)
"Get all buffers saved in STATE.
STATE is a window-state object as returned by `window-state-get'."
;; delq nil - removes buffers stored in STATE that don't exist anymore
(delq nil (mapcar #'get-buffer (spacemacs/window-state-get-buffer-names state))))
(defun spacemacs/find-workspace (buffer)
"Find Eyebrowse workspace containing BUFFER.
If several workspaces contain BUFFER, return the first one. Workspaces are
ordered by slot number.
If no workspace contains
BUFFER, return nil."
;; the second element of a workspace is its window-state object
(--find (memq buffer (spacemacs/window-state-get-buffers (cadr it)))
(eyebrowse--get 'window-configs)))
(defun spacemacs/display-in-workspace (buffer alist)
"Display BUFFER's workspace.
Return BUFFER's window, if exists, otherwise nil.
If BUFFER is already visible in current workspace, just return its window
without switching workspaces."
(or (get-buffer-window buffer)
(-when-let (workspace (spacemacs/find-workspace buffer))
(eyebrowse-switch-to-window-config (car workspace))
(get-buffer-window buffer))))
(defun spacemacs/goto-buffer-workspace (buffer)
"Switch to BUFFER's window in BUFFER's workspace.
If BUFFER isn't displayed in any workspace, display it in the current
workspace, preferably in the current window."
(interactive "B")
(pop-to-buffer buffer '((;; reuse buffer window from some workspace
spacemacs/display-in-workspace
;; fallback to display in current window
display-buffer-same-window)
(inhibit-same-window . nil))))
;; Eyebrowse transient state
(defun spacemacs//workspaces-ts-toggle-hint ()
"Toggle the full hint docstring for the workspaces transient-state."
(interactive)
(setq spacemacs--workspaces-ts-full-hint-toggle
(logxor spacemacs--workspaces-ts-full-hint-toggle 1)))
(defun spacemacs/workspaces-ts-rename ()
"Rename a workspace and get back to transient-state."
(interactive)
(eyebrowse-rename-window-config (eyebrowse--get 'current-slot) nil)
(spacemacs/workspaces-transient-state/body))
(defun spacemacs//workspace-format-name (workspace)
"Return a porpertized string given a WORKSPACE name."
(let* ((current (eq (eyebrowse--get 'current-slot) (car workspace)))
(name (nth 2 workspace))
(number (car workspace))
(caption (if (< 0 (length name))
(concat (int-to-string number) ":" name)
(int-to-string number))))
(if current
(propertize (concat "[" caption "]") 'face 'warning)
caption)))
(defun spacemacs//workspaces-ts-hint ()
"Return a one liner string containing all the workspaces names."
(concat
" "
(mapconcat 'spacemacs//workspace-format-name
(eyebrowse--get 'window-configs) " | ")
(if (equal 1 spacemacs--workspaces-ts-full-hint-toggle)
spacemacs--workspaces-ts-full-hint
(concat " (["
(propertize "?" 'face 'hydra-face-red)
"] help)"))))
;; Eyebrowse and Persp integration
(defun spacemacs/load-eyebrowse-for-perspective (&optional frame)
"Load an eyebrowse workspace according to a perspective's parameters.
FRAME's perspective is the perspective that is considered, defaulting to
the current frame's perspective.
If the perspective doesn't have a workspace, create one."
(let* ((persp (get-frame-persp frame))
(window-configs (persp-parameter 'eyebrowse-window-configs persp))
(current-slot (persp-parameter 'eyebrowse-current-slot persp))
(last-slot (persp-parameter 'eyebrowse-last-slot persp)))
(if window-configs
(progn
(eyebrowse--set 'window-configs window-configs frame)
(eyebrowse--set 'current-slot current-slot frame)
(eyebrowse--set 'last-slot last-slot frame)
(eyebrowse--load-window-config current-slot))
(eyebrowse--set 'window-configs nil frame)
(eyebrowse-init frame)
(spacemacs/save-eyebrowse-for-perspective frame))))
(defun spacemacs/update-eyebrowse-for-perspective (_new-persp-name)
"Update and save current frame's eyebrowse workspace to its perspective.
Parameter _NEW-PERSP-NAME is ignored, and exists only for compatibility with
`persp-before-switch-functions'."
(let* ((current-slot (eyebrowse--get 'current-slot))
(current-tag (nth 2 (assoc current-slot (eyebrowse--get 'window-configs)))))
(eyebrowse--update-window-config-element
(eyebrowse--current-window-config current-slot current-tag)))
(spacemacs/save-eyebrowse-for-perspective))
(defun spacemacs/save-eyebrowse-for-perspective (&optional frame)
"Save FRAME's eyebrowse workspace to FRAME's perspective.
FRAME defaults to the current frame."
(let ((persp (get-frame-persp frame)))
(set-persp-parameter
'eyebrowse-window-configs (eyebrowse--get 'window-configs frame) persp)
(set-persp-parameter
'eyebrowse-current-slot (eyebrowse--get 'current-slot frame) persp)
(set-persp-parameter
'eyebrowse-last-slot (eyebrowse--get 'last-slot frame) persp)))
(defun spacemacs/layout-workspaces-transient-state ()
"Launches the workspaces transient state, if defined."
(interactive)
(if (fboundp 'spacemacs/workspaces-transient-state/body)
(call-interactively 'spacemacs/workspaces-transient-state/body)
(message "You need the eyebrowse layer to use this feature.")))

View File

@ -0,0 +1,221 @@
;;; packages.el --- Spacemacs Layouts Layer packages File for Spacemacs
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
(setq spacemacs-layouts-packages
'(eyebrowse
helm
;; temporary switch on a fork to fix
;; https://github.com/syl20bnr/spacemacs/issues/4120
(persp-mode :location (recipe :fetcher github
:repo "syl20bnr/persp-mode.el"
:branch "fix-emacsclient-crash"))
spaceline
swiper))
(defun spacemacs-layouts/init-eyebrowse ()
(use-package eyebrowse
:init
(progn
(setq eyebrowse-new-workspace #'spacemacs/home-delete-other-windows
eyebrowse-wrap-around t)
;; always activate eyebrowse
(eyebrowse-mode)
;; transient state
(spacemacs|transient-state-format-hint workspaces
spacemacs--workspaces-ts-full-hint
"\n\n
Go to^^^^^^ Remove/Rename...^^
--^-^--^^^^----------------------- --^-^---------------------------
[_0_,_9_]^^ nth/new workspace [_d_] close current workspace
[_C-0_,_C-9_]^^ nth/new workspace [_R_] rename current workspace
[_n_/_C-l_]^^ next workspace
[_N_/_p_/_C-h_] prev workspace
[_<tab>_]^^^^ last workspace\n")
(spacemacs|define-transient-state workspaces
:title "Workspaces Transient State"
:hint-is-doc t
:dynamic-hint (spacemacs//workspaces-ts-hint)
:bindings
("?" spacemacs//workspaces-ts-toggle-hint)
("0" eyebrowse-switch-to-window-config-0 :exit t)
("1" eyebrowse-switch-to-window-config-1 :exit t)
("2" eyebrowse-switch-to-window-config-2 :exit t)
("3" eyebrowse-switch-to-window-config-3 :exit t)
("4" eyebrowse-switch-to-window-config-4 :exit t)
("5" eyebrowse-switch-to-window-config-5 :exit t)
("6" eyebrowse-switch-to-window-config-6 :exit t)
("7" eyebrowse-switch-to-window-config-7 :exit t)
("8" eyebrowse-switch-to-window-config-8 :exit t)
("9" eyebrowse-switch-to-window-config-9 :exit t)
("C-0" eyebrowse-switch-to-window-config-0)
("C-1" eyebrowse-switch-to-window-config-1)
("C-2" eyebrowse-switch-to-window-config-2)
("C-3" eyebrowse-switch-to-window-config-3)
("C-4" eyebrowse-switch-to-window-config-4)
("C-5" eyebrowse-switch-to-window-config-5)
("C-6" eyebrowse-switch-to-window-config-6)
("C-7" eyebrowse-switch-to-window-config-7)
("C-8" eyebrowse-switch-to-window-config-8)
("C-9" eyebrowse-switch-to-window-config-9)
("<tab>" eyebrowse-last-window-config)
("C-h" eyebrowse-prev-window-config)
("C-i" eyebrowse-last-window-config)
("C-l" eyebrowse-next-window-config)
("d" eyebrowse-close-window-config)
("h" eyebrowse-prev-window-config)
("l" eyebrowse-next-window-config)
("n" eyebrowse-next-window-config)
("N" eyebrowse-prev-window-config)
("p" eyebrowse-prev-window-config)
("R" spacemacs/workspaces-ts-rename :exit t)
("w" eyebrowse-switch-to-window-config :exit t))
(spacemacs/set-leader-keys
"bW" 'spacemacs/goto-buffer-workspace
"lw" 'spacemacs/workspaces-transient-state/body)
;; hooks
(add-hook 'persp-before-switch-functions
#'spacemacs/update-eyebrowse-for-perspective)
(add-hook 'eyebrowse-post-window-switch-hook
#'spacemacs/save-eyebrowse-for-perspective)
(add-hook 'persp-activated-hook
#'spacemacs/load-eyebrowse-for-perspective)
;; vim-style tab switching
(define-key evil-motion-state-map "gt" 'eyebrowse-next-window-config)
(define-key evil-motion-state-map "gT" 'eyebrowse-prev-window-config))))
(defun spacemacs-layouts/post-init-helm ()
(spacemacs/set-leader-keys
"pl" 'spacemacs/helm-persp-switch-project))
(defun spacemacs-layouts/init-persp-mode ()
(use-package persp-mode
:diminish persp-mode
:init
(progn
(setq persp-auto-resume-time (if (or dotspacemacs-auto-resume-layouts
spacemacs-force-resume-layouts)
1 -1)
persp-nil-name dotspacemacs-default-layout-name
persp-reset-windows-on-nil-window-conf nil
persp-set-last-persp-for-new-frames nil
persp-save-dir spacemacs-layouts-directory)
;; always activate persp-mode
(persp-mode)
;; layouts transient state
(spacemacs|transient-state-format-hint layouts
spacemacs--layouts-ts-full-hint
"\n\n
Go to^^^^^^ Add/Remove/Rename...^^
--^-^--^^^^----------------------- --^-^---------------------------
[_b_]^^^^ buffer in layout [_a_] add buffer
[_h_]^^^^ default layout [_A_] add all from layout
[_o_]^^^^ custom layout [_r_] remove current buffer
[_l_]^^^^ layout w/helm/ivy [_d_] close current layout
[_L_]^^^^ layouts in file [_D_] close other layout
[_0_,_9_]^^ nth/new layout [_x_] kill current w/buffers
[_C-0_,_C-9_]^^ nth/new layout [_X_] kill other w/buffers
[_n_/_C-l_]^^ next layout [_R_] rename current layout
[_N_/_p_/_C-h_] prev layout
[_<tab>_]^^^^ last layout
--^^^^^^^^----------------------------------------------------------
[_s_/_S_] save all layouts/save by names
[_t_]^^ show a buffer without adding it to current layout
[_w_]^^ workspaces micro-state (requires eyebrowse layer)
[_?_]^^ toggle help\n")
(spacemacs|define-transient-state layouts
:title "Layouts Transient State"
:hint-is-doc t
:dynamic-hint (spacemacs//layouts-ts-hint)
:bindings
;; need to exit in case number doesn't exist
("?" spacemacs//layouts-ts-toggle-hint)
("1" spacemacs/persp-switch-to-1 :exit t)
("2" spacemacs/persp-switch-to-2 :exit t)
("3" spacemacs/persp-switch-to-3 :exit t)
("4" spacemacs/persp-switch-to-4 :exit t)
("5" spacemacs/persp-switch-to-5 :exit t)
("6" spacemacs/persp-switch-to-6 :exit t)
("7" spacemacs/persp-switch-to-7 :exit t)
("8" spacemacs/persp-switch-to-8 :exit t)
("9" spacemacs/persp-switch-to-9 :exit t)
("0" spacemacs/persp-switch-to-0 :exit t)
("C-1" spacemacs/persp-switch-to-1)
("C-2" spacemacs/persp-switch-to-2)
("C-3" spacemacs/persp-switch-to-3)
("C-4" spacemacs/persp-switch-to-4)
("C-5" spacemacs/persp-switch-to-5)
("C-6" spacemacs/persp-switch-to-6)
("C-7" spacemacs/persp-switch-to-7)
("C-8" spacemacs/persp-switch-to-8)
("C-9" spacemacs/persp-switch-to-9)
("C-0" spacemacs/persp-switch-to-0)
("<tab>" spacemacs/jump-to-last-layout)
("<return>" nil :exit t)
("C-h" persp-prev)
("C-l" persp-next)
("a" persp-add-buffer :exit t)
("A" persp-import-buffers :exit t)
("b" spacemacs/persp-helm-mini :exit t)
("d" spacemacs/layouts-ts-close)
("D" spacemacs/layouts-ts-close-other :exit t)
("h" spacemacs/layout-goto-default :exit t)
("l" spacemacs/helm-perspectives :exit t)
("L" persp-load-state-from-file :exit t)
("n" persp-next)
("N" persp-prev)
("o" spacemacs/select-custom-layout :exit t)
("p" persp-prev)
("r" persp-remove-buffer :exit t)
("R" spacemacs/layouts-ts-rename :exit t)
("s" persp-save-state-to-file :exit t)
("S" persp-save-to-file-by-names :exit t)
("t" persp-temporarily-display-buffer :exit t)
("w" spacemacs/layout-workspaces-transient-state :exit t)
("x" spacemacs/layouts-ts-kill)
("X" spacemacs/layouts-ts-kill-other :exit t))
(spacemacs/set-leader-keys "l" 'spacemacs/layouts-transient-state/body)
;; custom layouts
(spacemacs|define-custom-layout "@Spacemacs"
:binding "e"
:body
(spacemacs/find-dotfile)))
:config
(progn
(defadvice persp-activate (before spacemacs//save-toggle-layout activate)
(setq spacemacs--last-selected-layout persp-last-persp-name))
(add-hook 'persp-mode-hook 'spacemacs//layout-autosave)
(spacemacs/declare-prefix "b" "persp-buffers")
(spacemacs/declare-prefix "B" "global-buffers")
;; Override SPC TAB to only change buffers in perspective
(spacemacs/set-leader-keys
"TAB" 'spacemacs/alternate-buffer-in-persp
"ba" 'persp-add-buffer
"br" 'persp-remove-buffer
"Bb" 'spacemacs-layouts/non-restricted-buffer-list))))
(defun spacemacs-layouts/post-init-spaceline ()
(setq spaceline-display-default-perspective
dotspacemacs-display-default-layout))
(defun spacemacs-layouts/post-init-swiper ()
(spacemacs/set-leader-keys "pl" 'spacemacs/ivy-persp-switch-project))

View File

@ -1,70 +0,0 @@
#+TITLE: Eyebrowse layer
#+HTML_HEAD_EXTRA: <link rel="stylesheet" type="text/css" href="../../../css/readtheorg.css" />
[[file:img/eyebrowse.gif]] [[file:img/i3wm.png]]
* Table of Contents :TOC_4_org:noexport:
- [[Description][Description]]
- [[Install][Install]]
- [[Layer][Layer]]
- [[Removing additional help][Removing additional help]]
- [[Key bindings][Key bindings]]
- [[Transient State][Transient State]]
* Description
This layer adds [[https://i3wm.org/][i3wm]] like workspaces thanks to the [[https://github.com/wasamasa/eyebrowse][eyebrowse]] package.
Once the layer is activated a new number is added to the left side of the
mode-line. This number corresponds to the currently active workspace number.
At startup, the workspace number 1 is active. Switching to a workspace will
create it if it does not exist. For instance at startup you can press
~SPC l w 2~ to create the workspace 2.
The key bindings are registered in a transient-state displayed in the minibuffer.
The docstring of the transient-state displays the existing workspaces and the
currently active workspace has square brackets. Since this is a transient-state it
is possible to just preview a workspace, for instance press ~SPC l w 2~ to see
what's on the workspace 2 then press ~TAB~ to go back to the previously
activated workspace.
It is also possible to give a label to a the current workspace by pressing
~r~ in the transient-state.
* Install
** Layer
To use this configuration layer, add it to your =~/.spacemacs=. You will need to
add =eyebrowse= to the existing =dotspacemacs-configuration-layers= list in this
file.
** Removing additional help
Once you know the key bindings to navigate between the workspaces you
may want to disable the exhaustive help in the workspace transient-state.
Set the variable =eyebrowse-display-help= to =nil=
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-configuration-layers
'((eyebrowse :variables eyebrowse-display-help nil)))
#+END_SRC
* Key bindings
| Key Binding | Description |
|-------------+--------------------------------------|
| ~gt~ | go to next workspace |
| ~gT~ | got to previous workspace |
| ~SPC b W~ | go to workspace and window by buffer |
*** Transient State
| Key Binding | Description |
|-------------------+-------------------------------------------------------------|
| ~SPC l w~ | activate the transient state |
| ~[1..9, 0]~ | switch to nth workspace |
| ~[C-1..C-9, C-0]~ | switch to nth workspace and keep the transient state active |
| ~TAB~ | switch to last active workspace |
| ~d~ | close current workspace |
| ~n~ or ~l~ | switch to next workspace |
| ~N~ or ~p~ or ~h~ | switch to previous workspace |
| ~R~ | set a tag to the current workspace |
| ~w~ | switched to tagged workspace |

View File

@ -1,19 +0,0 @@
;;; config.el --- Eyebrowse Layer configuration File for Spacemacs
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
;; Variables
(defvar eyebrowse-display-help t
"If non-nil additional help is displayed when selecting a workspace.")
;; Prefix commands
(spacemacs/declare-prefix "W" "workspaces")

View File

@ -1,77 +0,0 @@
;;; funcs.el --- Eyebrowse Layer functions File
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
(require 'dash)
;; Eyebrowse uses window-state objects (as returned by `window-state-get') to
;; store window configurations, so here are some utility functions to help us
;; analyse window-states.
;; it might make more sense to move these functions to a more general place
(defun spacemacs/window-state-window-p (object)
"Return t if OBJECT is a window, as represented in window-state objects.
Note: this function doesn't test for real window objects, but for
representations of a window in a window-state object as returned by
`window-state-get'."
(and (listp object)
(memq (car object) '(leaf vc hc))))
(defun spacemacs/window-state-get-buffer (window)
"Get WINDOW's buffer.
WINDOW is the representation of a window in a window-state object.
The returned value is the representation of a buffer in a window-state
object."
(cdr (assq 'buffer window)))
(defun spacemacs/window-state-get-buffer-name (window)
"Get WINDOW's buffer's name.
WINDOW is the representation of a window in a window-state object."
(car (spacemacs/window-state-get-buffer window)))
(defun spacemacs/window-state-walk-windows-1 (window fn)
"Helper function for `spacemacs/window-state-walk-windows'."
;; WINDOW is a misleading name. WINDOW is a list that can represent a window,
;; or a concatenation of several windows. window-state objects are weird.
(let ((child-windows
(-filter #'spacemacs/window-state-window-p window))
(bare-window
;; if WINDOW contains more than one window, take only the first window
(--take-while (not (spacemacs/window-state-window-p it))
window)))
(--each child-windows
(spacemacs/window-state-walk-windows-1 it fn))
(push (funcall fn bare-window) result)))
(defun spacemacs/window-state-walk-windows (state fn)
"Execute FN once for each window in STATE and make a list of the results.
FN is a function to execute.
STATE is a window-state object."
(let (result)
(spacemacs/window-state-walk-windows-1 (cdr state) fn)
result))
(defun spacemacs/window-state-all-windows (state)
"Get all windows contained in STATE.
STATE is a window-state object.
The returned windows are not actual window objects. They are windows as
represented in window-state objects."
(spacemacs/window-state-walk-windows state #'identity))
(defun spacemacs/window-state-get-buffer-names (state)
"Get names of all buffers saved in STATE.
STATE is a window-state object as returned by `window-state-get'."
(delq nil (spacemacs/window-state-walk-windows state #'spacemacs/window-state-get-buffer-name)))
(defun spacemacs/window-state-get-buffers (state)
"Get all buffers saved in STATE.
STATE is a window-state object as returned by `window-state-get'."
;; delq nil - removes buffers stored in STATE that don't exist anymore
(delq nil (mapcar #'get-buffer (spacemacs/window-state-get-buffer-names state))))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,138 +0,0 @@
;;; packages.el --- Eyebrowse Layer packages File for Spacemacs
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
(setq eyebrowse-packages '(eyebrowse))
(defun eyebrowse/init-eyebrowse ()
(use-package eyebrowse
:init
(progn
(setq eyebrowse-new-workspace #'spacemacs/home-delete-other-windows
eyebrowse-wrap-around t)
(eyebrowse-mode)
;; vim-style tab switching
(define-key evil-motion-state-map "gt" 'eyebrowse-next-window-config)
(define-key evil-motion-state-map "gT" 'eyebrowse-prev-window-config)
(spacemacs/set-leader-keys "bW" 'spacemacs/goto-buffer-workspace)
(defun spacemacs/find-workspace (buffer)
"Find Eyebrowse workspace containing BUFFER.
If several workspaces contain BUFFER, return the first one. Workspaces are
ordered by slot number.
If no workspace contains
BUFFER, return nil."
;; the second element of a workspace is its window-state object
(--find (memq buffer (spacemacs/window-state-get-buffers (cadr it)))
(eyebrowse--get 'window-configs)))
(defun spacemacs/display-in-workspace (buffer alist)
"Display BUFFER's workspace.
Return BUFFER's window, if exists, otherwise nil.
If BUFFER is already visible in current workspace, just return its window
without switching workspaces."
(or (get-buffer-window buffer)
(-when-let (workspace (spacemacs/find-workspace buffer))
(eyebrowse-switch-to-window-config (car workspace))
(get-buffer-window buffer))))
(defun spacemacs/goto-buffer-workspace (buffer)
"Switch to BUFFER's window in BUFFER's workspace.
If BUFFER isn't displayed in any workspace, display it in the current
workspace, preferably in the current window."
(interactive "B")
(pop-to-buffer buffer '((;; reuse buffer window from some workspace
spacemacs/display-in-workspace
;; fallback to display in current window
display-buffer-same-window)
(inhibit-same-window . nil))))
(defun spacemacs/workspaces-ts-rename ()
"Rename a workspace and get back to transient-state."
(interactive)
(eyebrowse-rename-window-config (eyebrowse--get 'current-slot) nil)
(spacemacs/workspaces-transient-state/body))
(spacemacs|transient-state-format-hint workspaces
spacemacs--workspaces-ts-full-hint
"\n\n
Go to^^^^^^ Remove/Rename...^^
--^-^--^^^^----------------------- --^-^---------------------------
[_0_,_9_]^^ nth/new workspace [_d_] close current workspace
[_C-0_,_C-9_]^^ nth/new workspace [_R_] rename current workspace
[_n_/_C-l_]^^ next workspace
[_N_/_p_/_C-h_] prev workspace
[_<tab>_]^^^^ last workspace\n")
(spacemacs|define-transient-state workspaces
:title "Workspaces Transient State"
:hint-is-doc t
:dynamic-hint (spacemacs//workspaces-ts-hint)
:bindings
("0" eyebrowse-switch-to-window-config-0 :exit t)
("1" eyebrowse-switch-to-window-config-1 :exit t)
("2" eyebrowse-switch-to-window-config-2 :exit t)
("3" eyebrowse-switch-to-window-config-3 :exit t)
("4" eyebrowse-switch-to-window-config-4 :exit t)
("5" eyebrowse-switch-to-window-config-5 :exit t)
("6" eyebrowse-switch-to-window-config-6 :exit t)
("7" eyebrowse-switch-to-window-config-7 :exit t)
("8" eyebrowse-switch-to-window-config-8 :exit t)
("9" eyebrowse-switch-to-window-config-9 :exit t)
("C-0" eyebrowse-switch-to-window-config-0)
("C-1" eyebrowse-switch-to-window-config-1)
("C-2" eyebrowse-switch-to-window-config-2)
("C-3" eyebrowse-switch-to-window-config-3)
("C-4" eyebrowse-switch-to-window-config-4)
("C-5" eyebrowse-switch-to-window-config-5)
("C-6" eyebrowse-switch-to-window-config-6)
("C-7" eyebrowse-switch-to-window-config-7)
("C-8" eyebrowse-switch-to-window-config-8)
("C-9" eyebrowse-switch-to-window-config-9)
("<tab>" eyebrowse-last-window-config)
("C-h" eyebrowse-prev-window-config)
("C-i" eyebrowse-last-window-config)
("C-l" eyebrowse-next-window-config)
("d" eyebrowse-close-window-config)
("h" eyebrowse-prev-window-config)
("l" eyebrowse-next-window-config)
("n" eyebrowse-next-window-config)
("N" eyebrowse-prev-window-config)
("p" eyebrowse-prev-window-config)
("R" spacemacs/workspaces-ts-rename :exit t)
("w" eyebrowse-switch-to-window-config :exit t))
(defun spacemacs//workspace-format-name (workspace)
"Return a porpertized string given a WORKSPACE name."
(let* ((current (eq (eyebrowse--get 'current-slot) (car workspace)))
(name (nth 2 workspace))
(number (car workspace))
(caption (if (< 0 (length name))
(concat (int-to-string number) ":" name)
(int-to-string number))))
(if current
(propertize (concat "[" caption "]") 'face 'warning)
caption)))
(defun spacemacs//workspaces-ts-hint ()
"Return a one liner string containing all the workspace names."
(concat
" "
(mapconcat 'spacemacs//workspace-format-name
(eyebrowse--get 'window-configs) " | ")
(when eyebrowse-display-help spacemacs--workspaces-ts-full-hint)))
;; The layouts layer defines this keybinding inside a transient-state
;; thus this is only needed if that layer is not used
(unless (configuration-layer/layer-usedp 'spacemacs-layouts)
(spacemacs/set-leader-keys
"lw" 'spacemacs/workspaces-transient-state/body)))))

View File

@ -1,144 +0,0 @@
#+TITLE: Spacemacs Layouts layer
#+HTML_HEAD_EXTRA: <link rel="stylesheet" type="text/css" href="../../../css/readtheorg.css" />
* Table of Contents :TOC_4_org:noexport:
- [[Description][Description]]
- [[Install][Install]]
- [[Layer][Layer]]
- [[Features][Features]]
- [[Transient-states][Transient-states]]
- [[Layouts Transient State][Layouts Transient State]]
- [[Project Layouts][Project Layouts]]
- [[Custom Layouts Transient State][Custom Layouts Transient State]]
- [[Usage][Usage]]
- [[Save/Load layouts into a file][Save/Load layouts into a file]]
- [[Custom Layout Macro][Custom Layout Macro]]
- [[Predefined custom layouts][Predefined custom layouts]]
- [[Org-agenda custom layout][Org-agenda custom layout]]
- [[RCIRC/ERC custom layout][RCIRC/ERC custom layout]]
* Description
This contribution layer adds layouts support to Spacemacs thanks to =persp-mode=.
Layouts are window configurations that have buffer isolation between each other.
* Install
** Layer
This layer is automatically included if you use the =spacemacs= distribution.
If you use =spacemacs-base= distribution then to use this configuration layer,
add it to your =~/.spacemacs=. You will need to add =spacemacs-layout= to the
existing =dotspacemacs-configuration-layers= list in this file.
* Features
** Transient-states
*** Layouts Transient State
The layouts transient-state is initiated with ~SPC l~.
| Key Binding | Description |
|-------------------+------------------------------------------------------------|
| ~?~ | toggle the documentation |
| ~[1..9, 0]~ | switch to nth layout |
| ~[C-1..C-9, C-0]~ | switch to nth layout and keep the transient state active |
| ~<tab>~ | switch to the latest layout |
| ~a~ | add a buffer to the current layout |
| ~A~ | add all the buffers from another layout in the current one |
| ~b~ | select a buffer in the current layout |
| ~d~ | delete the current layout and keep its buffers |
| ~D~ | delete the other layouts and keep their buffers |
| ~h~ | go to default layout |
| ~C-h~ | previous layout in list |
| ~l~ | select/create a layout with helm |
| ~L~ | load layouts from file |
| ~C-l~ | next layout in list |
| ~n~ | next layout in list |
| ~N~ | previous layout in list |
| ~o~ | open a custom layout |
| ~p~ | previous layout in list |
| ~r~ | remove current buffer from layout |
| ~R~ | rename current layout |
| ~s~ | save layouts |
| ~t~ | display a buffer without adding it to the current layout |
| ~w~ | workspaces transient-state (needs eyebrowse layer enabled) |
| ~x~ | kill current layout with its buffers |
| ~X~ | kill other layouts with their buffers |
*** Project Layouts
To create a layout for a specific project use ~SPC p l~.
*** Custom Layouts Transient State
The layouts transient-state is initiated with ~SPC l o~.
Example of default custom layouts that are configured in the corresponding
layers:
| Key Binding | Description |
|-------------+-------------------------------------------------------------------------------------------|
| ~e~ | Emacs custom perspective |
| ~E~ | ERC custom perspective (needs the erc layer enabled - configurable, check ERC docs) |
| ~i~ | RCIRC custom perspective (needs the rcirc layer enabled - configurable, check RCIRC docs) |
| ~o~ | Org custom perspective |
**Note:** You can add more custom perspectives by using the
~spacemacs|define-custom-layout~ macro explained further below.
* Usage
At the beginning there is only one layout called =Default= which contains
all the buffers.
If you keep working within this layout then Emacs behaves as if layouts
don't exist so you are never forced to use them even if they are available.
They are two types of layouts:
- regular layouts which you can create dynamically or which can be bound to
a projectile project (press ~SPC l~ to access them)
- custom layouts which are defined with the macro
=spacemacs|define-custome-layout= and always active (press ~SPC l o~ to
access them).
** Save/Load layouts into a file
With ~SPC l s~ and ~SPC l L~ you can save and load perspectives to a file. This
is available without configuration, support is great for emacs 24.4, but
depends on =workgroups.el= for Emacs <= 24.3.
** Custom Layout Macro
If you want to add a new custom layouts (for example if you want to have
IRC on its own perspective or maybe calendar or gnus) you have to use
the macro =spacemacs|define-custom-layout= as follows:
#+BEGIN_SRC emacs-lisp
(spacemacs|define-custom-layout "<name-to-be-shown-in-the-modeline>"
:binding "<bind-key>"
:body
(...)
;; (stuff to be done in the persp activating)
;; (a major mode like twittering-mode or whatever)
(...))
#+END_SRC
Other example:
#+BEGIN_SRC emacs-lisp
(spacemacs|define-custom-layout "c++"
:binding "+"
:body
(find-file "~/path/to/first/file.cpp")
(split-window-right)
(find-file "~/path/to/second/file.cpp")
;; (... do more stuff but be careful not to destroy the universe ...)
)
#+END_SRC
Then you can access this persp with ~SPC l o +~, where ~+~ is the binding.
** Predefined custom layouts
*** Org-agenda custom layout
Here we define a custom layout that adds items to your org-agenda. If you
do not know what that is check the [[https://www.gnu.org/software/emacs/manual/html_node/org/Agenda-commands.html][docs]].
The cool part is that you can have many org files with todos in the agenda and
with one simple command you can gather all the todos from all the agenda files
you have and show them in a single buffer. (in evil the command starts with ~;a~)
*** RCIRC/ERC custom layout
Now you can also open IRC in a new layout to keep all the chat buffers in
one layout isolated from your work buffers.

View File

@ -1,187 +0,0 @@
;;; funcs.el --- Spacemacs Layouts Layer functions File
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
(defun spacemacs//current-layout-name ()
"Get name of the current perspective."
(safe-persp-name (get-frame-persp)))
;; Helm related functions --------------------------------------------------
(defun spacemacs/persp-helm-mini ()
"As `helm-mini' but restricts visible buffers by perspective."
(interactive)
(with-persp-buffer-list ()
(helm-mini)))
(defun spacemacs//helm-perspectives-source ()
(helm-build-in-buffer-source
(concat "Current Perspective: " (spacemacs//current-layout-name))
:data (persp-names)
:fuzzy-match t
:action
'(("Switch to perspective" . persp-switch)
("Close perspective(s)" . (lambda (candidate)
(mapcar
'persp-kill-without-buffers
(helm-marked-candidates))))
("Kill perspective(s)" . (lambda (candidate)
(mapcar 'persp-kill
(helm-marked-candidates)))))))
(defun spacemacs/helm-perspectives ()
"Control Panel for perspectives. Has many actions.
If match is found
f1: (default) Select perspective
f2: Close Perspective(s) <- mark with C-SPC to close more than one-window
f3: Kill Perspective(s)
If match is not found
<enter> Creates perspective
Closing doesn't kill buffers inside the perspective while killing
perspectives does."
(interactive)
(helm
:buffer "*Helm Perspectives*"
:sources
`(,(spacemacs//helm-perspectives-source)
,(helm-build-dummy-source "Create new perspective"
:requires-pattern t
:action
'(("Create new perspective" .
(lambda (name)
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch name)
(unless (member name (persp-names-current-frame-fast-ordered))
(spacemacs/home))))))))))
;; ability to use helm find files but also adds to current perspective
(defun spacemacs/helm-persp-close ()
"Kills perspectives without killing the buffers"
(interactive)
(helm
:buffer "*Helm Kill Perspectives (without killing buffers)*"
:sources
(helm-build-in-buffer-source
(concat "Current Perspective: " (spacemacs//current-layout-name))
:data (persp-names)
:fuzzy-match t
:action
'(("Close perspective(s)" . (lambda (candidate)
(mapcar
'persp-kill-without-buffers
(helm-marked-candidates))))))))
(defun spacemacs/helm-persp-kill ()
"Kills perspectives with all their buffers"
(interactive)
(helm
:buffer "*Helm Kill Perspectives with all their buffers*"
:sources (helm-build-in-buffer-source
(s-concat "Current Perspective: "
(spacemacs//current-layout-name))
:data (persp-names)
:fuzzy-match t
:action
'(("Kill perspective(s)" .
(lambda (candidate)
(mapcar 'persp-kill
(helm-marked-candidates))))))))
;; Helm Projectile related functions ---------------------------------------
(defun spacemacs/helm-persp-switch-project (arg)
(interactive "P")
(helm
:sources
(helm-build-in-buffer-source "*Helm Switch Project Layout*"
:data (lambda ()
(if (projectile-project-p)
(cons (abbreviate-file-name (projectile-project-root))
(projectile-relevant-known-projects))
projectile-known-projects))
:fuzzy-match helm-projectile-fuzzy-match
:mode-line helm-read-file-name-mode-line-string
:action '(("Switch to Project Perspective" .
(lambda (project)
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch project)
(let ((projectile-completion-system 'helm))
(projectile-switch-project-by-name project)))))))
:buffer "*Helm Projectile Layouts*"))
;; Autosave ----------------------------------------------------------------
(defun spacemacs//layout-autosave ()
"Perspectives mode autosave.
Autosaves perspectives layouts every `persp-autosave-interal' seconds.
Cancels autosave on exiting perspectives mode."
(if (and persp-mode layouts-enable-autosave)
(progn
(message "Perspectives mode autosaving enabled.")
(setq spacemacs--layouts-autosave-timer
(run-with-timer
layouts-autosave-delay
layouts-autosave-delay
(lambda ()
(message "Saving perspectives to file.")
(persp-save-state-to-file)))))
(when spacemacs--layouts-autosave-timer
(cancel-timer spacemacs--layouts-autosave-timer)
(setq spacemacs--layouts-autosave-timer nil))))
;; Eyebrowse - allow perspective-local workspaces --------------------------
(defun spacemacs/load-eyebrowse-for-perspective (&optional frame)
"Load an eyebrowse workspace according to a perspective's parameters.
FRAME's perspective is the perspective that is considered, defaulting to
the current frame's perspective.
If the perspective doesn't have a workspace, create one."
(let* ((persp (get-frame-persp frame))
(window-configs (persp-parameter 'eyebrowse-window-configs persp))
(current-slot (persp-parameter 'eyebrowse-current-slot persp))
(last-slot (persp-parameter 'eyebrowse-last-slot persp)))
(if window-configs
(progn
(eyebrowse--set 'window-configs window-configs frame)
(eyebrowse--set 'current-slot current-slot frame)
(eyebrowse--set 'last-slot last-slot frame)
(eyebrowse--load-window-config current-slot))
(eyebrowse--set 'window-configs nil frame)
(eyebrowse-init frame)
(spacemacs/save-eyebrowse-for-perspective frame))))
(defun spacemacs/update-eyebrowse-for-perspective (_new-persp-name)
"Update and save current frame's eyebrowse workspace to its perspective.
Parameter _NEW-PERSP-NAME is ignored, and exists only for compatibility with
`persp-before-switch-functions'."
(let* ((current-slot (eyebrowse--get 'current-slot))
(current-tag (nth 2 (assoc current-slot (eyebrowse--get 'window-configs)))))
(eyebrowse--update-window-config-element
(eyebrowse--current-window-config current-slot current-tag)))
(spacemacs/save-eyebrowse-for-perspective))
(defun spacemacs/save-eyebrowse-for-perspective (&optional frame)
"Save FRAME's eyebrowse workspace to FRAME's perspective.
FRAME defaults to the current frame."
(let ((persp (get-frame-persp frame)))
(set-persp-parameter
'eyebrowse-window-configs (eyebrowse--get 'window-configs frame) persp)
(set-persp-parameter
'eyebrowse-current-slot (eyebrowse--get 'current-slot frame) persp)
(set-persp-parameter
'eyebrowse-last-slot (eyebrowse--get 'last-slot frame) persp)))
(defun spacemacs/layout-workspaces-transient-state ()
"Launches the workspaces transient state, if defined."
(interactive)
(if (fboundp 'spacemacs/workspaces-transient-state/body)
(call-interactively 'spacemacs/workspaces-transient-state/body)
(message "You need the eyebrowse layer to use this feature.")))

View File

@ -1,268 +0,0 @@
(defun spacemacs/jump-to-last-layout ()
"Open the previously selected layout, if it exists."
(interactive)
(unless (eq 'non-existent
(gethash spacemacs--last-selected-layout
*persp-hash* 'non-existent))
(persp-switch spacemacs--last-selected-layout)))
;; Perspectives transient-state -------------------------------------------
(defun spacemacs//layouts-ts-toggle-hint ()
"Toggle the full hint docstring for the layouts transient-state."
(interactive)
(setq spacemacs--layouts-ts-full-hint-toggle
(logxor spacemacs--layouts-ts-full-hint-toggle 1)))
(defun spacemacs//layout-format-name (name pos)
"Format the layout name given by NAME for display in mode-line."
(let* ((layout-name (if (file-directory-p name)
(file-name-nondirectory (directory-file-name name))
name))
(string-name (format "%s" layout-name))
(current (equal name (spacemacs//current-layout-name)))
(caption (concat (number-to-string (if (eq 9 pos) 0 (1+ pos)))
":" string-name)))
(if current
(propertize (concat "[" caption "]") 'face 'warning)
caption)))
(defun spacemacs//layouts-ts-hint ()
"Return a one liner string containing all the layout names."
(let* ((persp-list (or (persp-names-current-frame-fast-ordered)
(list persp-nil-name)))
(formatted-persp-list
(concat " "
(mapconcat (lambda (persp)
(spacemacs//layout-format-name
persp (position persp persp-list)))
persp-list " | "))))
(concat
formatted-persp-list
(if (equal 1 spacemacs--layouts-ts-full-hint-toggle)
spacemacs--layouts-ts-full-hint
(concat " (["
(propertize "?" 'face 'hydra-face-red)
"] help)")))))
(spacemacs|transient-state-format-hint layouts
spacemacs--layouts-ts-full-hint
"\n\n
Go to^^^^^^ Add/Remove/Rename...^^
--^-^--^^^^----------------------- --^-^---------------------------
[_b_]^^^^ buffer in layout [_a_] add buffer
[_h_]^^^^ default layout [_A_] add all from layout
[_o_]^^^^ custom layout [_r_] remove current buffer
[_l_]^^^^ layout w/helm/ivy [_d_] close current layout
[_L_]^^^^ layouts in file [_D_] close other layout
[_0_,_9_]^^ nth/new layout [_x_] kill current w/buffers
[_C-0_,_C-9_]^^ nth/new layout [_X_] kill other w/buffers
[_n_/_C-l_]^^ next layout [_R_] rename current layout
[_N_/_p_/_C-h_] prev layout
[_<tab>_]^^^^ last layout
--^^^^^^^^----------------------------------------------------------
[_s_/_S_] save all layouts/save by names
[_t_]^^ show a buffer without adding it to current layout
[_w_]^^ workspaces micro-state (requires eyebrowse layer)
[_?_]^^ toggle help\n")
(spacemacs|define-transient-state layouts
:title "Layouts Transient State"
:hint-is-doc t
:dynamic-hint (spacemacs//layouts-ts-hint)
:bindings
;; need to exit in case number doesn't exist
("?" spacemacs//layouts-ts-toggle-hint)
("1" spacemacs/persp-switch-to-1 :exit t)
("2" spacemacs/persp-switch-to-2 :exit t)
("3" spacemacs/persp-switch-to-3 :exit t)
("4" spacemacs/persp-switch-to-4 :exit t)
("5" spacemacs/persp-switch-to-5 :exit t)
("6" spacemacs/persp-switch-to-6 :exit t)
("7" spacemacs/persp-switch-to-7 :exit t)
("8" spacemacs/persp-switch-to-8 :exit t)
("9" spacemacs/persp-switch-to-9 :exit t)
("0" spacemacs/persp-switch-to-0 :exit t)
("C-1" spacemacs/persp-switch-to-1)
("C-2" spacemacs/persp-switch-to-2)
("C-3" spacemacs/persp-switch-to-3)
("C-4" spacemacs/persp-switch-to-4)
("C-5" spacemacs/persp-switch-to-5)
("C-6" spacemacs/persp-switch-to-6)
("C-7" spacemacs/persp-switch-to-7)
("C-8" spacemacs/persp-switch-to-8)
("C-9" spacemacs/persp-switch-to-9)
("C-0" spacemacs/persp-switch-to-0)
("<tab>" spacemacs/jump-to-last-layout)
("<return>" nil :exit t)
("C-h" persp-prev)
("C-l" persp-next)
("a" persp-add-buffer :exit t)
("A" persp-import-buffers :exit t)
("b" spacemacs/persp-helm-mini :exit t)
("d" spacemacs/layouts-ts-close)
("D" spacemacs/layouts-ts-close-other :exit t)
("h" spacemacs/layout-goto-default :exit t)
("l" spacemacs/helm-perspectives :exit t)
("L" persp-load-state-from-file :exit t)
("n" persp-next)
("N" persp-prev)
("o" spacemacs/select-custom-layout :exit t)
("p" persp-prev)
("r" persp-remove-buffer :exit t)
("R" spacemacs/layouts-ts-rename :exit t)
("s" persp-save-state-to-file :exit t)
("S" persp-save-to-file-by-names :exit t)
("t" persp-temporarily-display-buffer :exit t)
("w" spacemacs/layout-workspaces-transient-state :exit t)
("x" spacemacs/layouts-ts-kill)
("X" spacemacs/layouts-ts-kill-other :exit t))
(defun spacemacs/layout-switch-by-pos (pos)
"Switch to perspective of position POS."
(let ((persp-to-switch
(nth pos (persp-names-current-frame-fast-ordered))))
(if persp-to-switch
(persp-switch persp-to-switch)
(when (y-or-n-p
(concat "Perspective in this position doesn't exist.\n"
"Do you want to create one? "))
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch nil)
(spacemacs/home-delete-other-windows))))))
;; Define all `spacemacs/persp-switch-to-X' functions
(dolist (i (number-sequence 9 0 -1))
(eval `(defun ,(intern (format "spacemacs/persp-switch-to-%s" i)) nil
,(format "Switch to layout %s." i)
(interactive)
(spacemacs/layout-switch-by-pos ,(if (eq 0 i) 9 (1- i))))))
(defun spacemacs/layout-goto-default ()
"Go to `dotspacemacs-default-layout-name` layout"
(interactive)
(when dotspacemacs-default-layout-name
(persp-switch dotspacemacs-default-layout-name)))
(defun spacemacs/layouts-ts-rename ()
"Rename a layout and get back to the perspectives transient-state."
(interactive)
(call-interactively 'persp-rename)
(spacemacs/layouts-transient-state/body))
(defun spacemacs/layouts-ts-close ()
"Kill current perspective"
(interactive)
(persp-kill-without-buffers (spacemacs//current-layout-name)))
(defun spacemacs/layouts-ts-close-other ()
(interactive)
(call-interactively 'spacemacs/helm-persp-close)
(spacemacs/layouts-transient-state/body))
(defun spacemacs/layouts-ts-kill ()
"Kill current perspective"
(interactive)
(persp-kill (spacemacs//current-layout-name)))
(defun spacemacs/layouts-ts-kill-other ()
(interactive)
(call-interactively 'spacemacs/helm-persp-kill)
(spacemacs/layouts-transient-state/body))
;; Custom perspectives transient-state -------------------------------------
(defun spacemacs//custom-layout-func-name (name)
"Return the name of the custom-perspective function for NAME."
(intern (concat "spacemacs/custom-perspective-" name)))
(defmacro spacemacs|define-custom-layout (name &rest props)
"Define a custom-perspective called NAME.
FUNC is a FUNCTION defined using NAME and the result of
`spacemacs//custom-layout-func-name', it takes care of
creating the perspective NAME and executing the expressions given
in the :body property to this macro.
NAME is a STRING.
Available PROPS:
`:binding STRING'
Key to be bound to the function FUNC
`:body EXPRESSIONS'
One or several EXPRESSIONS that are going to be evaluated after
we change into the perspective NAME."
(declare (indent 1))
(let* ((name (if (symbolp name)
(symbol-value name)
name))
(func (spacemacs//custom-layout-func-name name))
(binding-prop (car (spacemacs/mplist-get props :binding)))
(binding (if (symbolp binding-prop)
(symbol-value binding-prop)
binding-prop))
(body (spacemacs/mplist-get props :body))
(already-defined? (cdr (assoc binding
spacemacs--custom-layout-alist))))
`(progn
(defun ,func ()
,(format "Open custom perspective %s" name)
(interactive)
(let ((initialize (not (gethash ,name *persp-hash*))))
(persp-switch ,name)
(when initialize
(delete-other-windows)
,@body)))
;; Check for Clashes
(if ,already-defined?
(unless (equal ,already-defined? ,name)
(spacemacs-buffer/warning "Replacing existing binding \"%s\" for %s with %s"
,binding ,already-defined? ,name)
(push '(,binding . ,name) spacemacs--custom-layout-alist))
(push '(,binding . ,name) spacemacs--custom-layout-alist)))))
(defun spacemacs/select-custom-layout ()
"Update the custom-perspectives transient-state and then activate it."
(interactive)
(spacemacs//update-custom-layouts)
(spacemacs/custom-layouts-transient-state/body))
(defun spacemacs//custom-layouts-ms-documentation ()
"Return the docstring for the custom perspectives transient-state."
(if spacemacs--custom-layout-alist
(mapconcat (lambda (custom-persp)
(format "[%s] %s"
(car custom-persp) (cdr custom-persp)))
spacemacs--custom-layout-alist " ")
(spacemacs-buffer/warning (format "`spacemacs--custom-layout-alist' variable is empty" ))))
(defun spacemacs//update-custom-layouts ()
"Ensure the custom-perspectives transient-state is updated.
Takes each element in the list `spacemacs--custom-layout-alist'
format so they are supported by the
`spacemacs/custom-layouts-transient-state' macro."
(let (bindings)
(dolist (custom-persp spacemacs--custom-layout-alist bindings)
(let* ((binding (car custom-persp))
(name (cdr custom-persp))
(func-name (spacemacs//custom-layout-func-name name)))
(push (list binding func-name :exit t) bindings)))
(eval `(spacemacs|define-transient-state custom-layouts
:doc (concat (spacemacs//custom-layouts-ms-documentation))
:bindings
,@bindings))))
(defun spacemacs/alternate-buffer-in-persp ()
"Switch back and forth between current and last buffer in the
current perspective."
(interactive)
(with-persp-buffer-list ()
(switch-to-buffer (other-buffer (current-buffer) t))))
(defun spacemacs-layouts/non-restricted-buffer-list ()
(interactive)
(remove-hook 'ido-make-buffer-list-hook #'persp-restrict-ido-buffers)
(helm-mini)
(add-hook 'ido-make-buffer-list-hook #'persp-restrict-ido-buffers))

View File

@ -1,88 +0,0 @@
;;; packages.el --- Spacemacs Layouts Layer packages File for Spacemacs
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
(setq spacemacs-layouts-packages
'(;; temporary switch on a fork to fix
;; https://github.com/syl20bnr/spacemacs/issues/4120
(persp-mode :location (recipe :fetcher github
:repo "syl20bnr/persp-mode.el"
:branch "fix-emacsclient-crash"))
spaceline
eyebrowse
helm
swiper))
(defun spacemacs-layouts/init-persp-mode ()
(use-package persp-mode
:diminish persp-mode
:init
(progn
(setq persp-auto-resume-time (if (or dotspacemacs-auto-resume-layouts
spacemacs-force-resume-layouts)
1 -1)
persp-nil-name dotspacemacs-default-layout-name
persp-reset-windows-on-nil-window-conf nil
persp-set-last-persp-for-new-frames nil
persp-save-dir spacemacs-layouts-directory)
;; always activate persp-mode
(persp-mode)
(spacemacs/set-leader-keys "l" 'spacemacs/layouts-transient-state/body)
(spacemacs|define-custom-layout "@Spacemacs"
:binding "e"
:body
(spacemacs/find-dotfile)))
:config
(progn
(defadvice persp-activate (before spacemacs//save-toggle-layout activate)
(setq spacemacs--last-selected-layout persp-last-persp-name))
(add-hook 'persp-mode-hook 'spacemacs//layout-autosave)
(spacemacs/declare-prefix "b" "persp-buffers")
(spacemacs/declare-prefix "B" "global-buffers")
;; Override SPC TAB to only change buffers in perspective
(spacemacs/set-leader-keys
"TAB" 'spacemacs/alternate-buffer-in-persp
"ba" 'persp-add-buffer
"br" 'persp-remove-buffer
"Bb" 'spacemacs-layouts/non-restricted-buffer-list))))
(defun spacemacs-layouts/post-init-spaceline ()
(setq spaceline-display-default-perspective
dotspacemacs-display-default-layout))
(defun spacemacs-layouts/post-init-eyebrowse ()
(add-hook 'persp-before-switch-functions #'spacemacs/update-eyebrowse-for-perspective)
(add-hook 'eyebrowse-post-window-switch-hook #'spacemacs/save-eyebrowse-for-perspective)
(add-hook 'persp-activated-hook #'spacemacs/load-eyebrowse-for-perspective))
(defun spacemacs-layouts/post-init-helm ()
(spacemacs/set-leader-keys
"pl" 'spacemacs/helm-persp-switch-project))
(defun spacemacs-layouts/post-init-swiper ()
(defun spacemacs/ivy-persp-switch-project (arg)
(interactive "P")
(ivy-read "Switch to Project Perspective: "
(if (projectile-project-p)
(cons (abbreviate-file-name (projectile-project-root))
(projectile-relevant-known-projects))
projectile-known-projects)
:action (lambda (project)
(let ((persp-reset-windows-on-nil-window-conf t))
(persp-switch project)
(let ((projectile-completion-system 'ivy))
(projectile-switch-project-by-name project))))))
(spacemacs/set-leader-keys
"pl" 'spacemacs/ivy-persp-switch-project))