Emacs already has more workspace management packages than I can count. In the past, I exclusively used workgroups2 because no other package had all of the functionality I consider important. These are the main features supported by this package:
While workgroups2 has all of the above functionality, it has serious issues as well:
winner-mode
, on the other hand, doesn’t record window resizing)Workgroups2 is a fairly large package, and I don’t want to attempt to maintain/fix it when I only need some of its functionality. The goal of this package is to be as simple as alternatives while also allowing for the useful functionality they lack. The main principle is to use multiple frames as workspaces instead switching between window layouts inside a single frame. This has several advantages:
winner-mode
keeps track of window configuration changes separately for each framedesktop.el
can be used to persist and restore all framesfg-name
property (e.g. by using fg-after-switch-hook
) and make use of frame-local variablesThe primary issue with using frames for workgroups-like functionality is that emacs (by itself) has no way of displaying only one frame at a time and hiding the others. This isn’t an issue if you are willing to dedicate different desktops to different frames. On the other hand, frames aren’t great if you want a lot of contexts/groups or would prefer to use keys bound in emacs for switching between them instead of always using global hotkeys (since select-frame-set-input-focus
does not work across desktops).
By default, this package attempts address these issues issue by using xdotool
to hide the old frame and switch to a new one. If xelb is able to easily map/unmap windows, I may switch to using it in the future.
Note that this package will only attempt to use xdotool if the user is using X11, xdotool is installed, and the related settings (see below) are non-nil. Otherwise, it will not attempt to hide frames and will use emacs’ builtin frame switching function.
To clarify, if you are not using Linux/X11 or do not wish to use xdotool, most of this package’s functionality is still available:
fg-rename-frame
worksfg-create-frame
worksfg-create-hook
worksfg-switch-to-frame
and fg-switch-to-last-frame
will likely not work across desktops (you’ll need to use global WM keys to switch between desktops); they should work for frames located on the same desktopfg-after-switch-hook
is only triggered from fg-switch-to-(last-)frame
(you can use focus-in-hook
instead if you want to dedicate different WM desktops to different frames)fg-desktop-setup
will not workIn summary, reliable frame switching when using multiple desktops requires xdotool (basically a hack). Using xdotool to hide/switch windows can also cause flicker especially if you are not using a compositor. That said, if all your frames are on a single desktop, using xdotool is not necessary. You can instead have only one frame visible by using the monocle/fullscreen layout for that desktop.
The following sections use the term “framegroup” to refer to a frame that this package is managing (i.e. it was named/focused using this package’s commands).
fg-hide-with-xdotool
(default t): whether to hide the old frame when switching to a new one (only has an effect when using X11 and xdotool is installed)fg-switch-with-xdotool
(default t): whether to switch frames using xdotool instead of emacs’ select-frame-set-input-focus
(only has an effect when using X11 and xdotool is installed and fg-hide-with-xdotool
is nil; when fg-hide-with-xdotool
is non-nil, xdotool must be used to remap hidden windows)fg-auto-create
(default t): whether to automatically create a framegroup when attempting to switch to a non-existent onefg-create-hook
: hook run when a framegroup is first created (renaming also triggers this hook)fg-after-switch-hook
: hook run after switching framegroups; functions are run with the name of the new framegroup as an argumentCommands:
fg-rename-frame
: set the name of the current framegroupfg-create-frame
: choose a name and create a new framegroupfg-switch-to-frame
: switch to another framegroupfg-switch-to-last-frame
: switch to the previously focused framegroupHelper functions/macros:
fg-switch
: a convenience macro that returns a function that will switch to a framegroup (e.g. (define-key "key" (fg-switch "notes"))
)fg-desktop-setup
: will add to desktop-read-hook
to hide all but the last focused frame when restoring a sessionfg-mode-line-string
: return the current framegroup name formatted for the mode lineThis package does not provide numbered workspaces or directional switching commands as I personally prefer to have named contexts. You could of course simply name your frames with numbers and create directional switching keybindings yourself with fg-switch
, but I do not plan to this functionality directly.
;; enable `winner-mode' for undo (winner-mode) (global-set-key "C-c l" 'winner-undo) (global-set-key "C-c L" 'winner-redo) ;; enable `desktop-save-mode' for persistence ;; NOTE: It seems Emacs occasionally hangs when restoring a lot of frames with ;; desktop.el (fg-desktop-setup) (desktop-save-mode) ;; binding keys to switch to specific framegroups (global-set-key "C-c e" (fg-switch "emacs")) (global-set-key "C-c p" (fg-switch "prog")) ;; ... ;; default layouts for framegroups (defun my-framegroup-setup (name &rest _) "Set up default framegroup layouts." (interactive) (pcase name ;; emacs configuration ("emacs" (find-file "~/.emacs.d/other.el") (split-window-right) (find-file "~/.emacs.d/init.el")) ;; programming projects ("prog" (find-file "~/src")) ;; dotfiles ("config" (find-file "~/dotfiles")) ("mail" (mu4e)) ("music" (mingus)))) (add-hook 'fg-create-hook #'my-framegroup-setup) ;; binding keys for the current framegroup (defmacro my-ff (file) "Wrapper for creating `find-file' commands." `(lambda () (interactive) (find-file ,file))) (defun my-framegroup-keybindings (name &rest _) (pcase name ("emacs" (global-set-key "C-c , i" (my-ff "~/.emacs.d/init.el"))) ("prog" (global-set-key "C-c , r" (my-ff "README.org")) (global-set-key "C-c , d" #'projectile-edit-dir-locals)))) (add-hook 'fg-after-switch-hook #'my-framegroup-keybindings)
For mode line integration, you can insert fg-mode-line-string
into the mode line:
(setq-default mode-line-format ;; ... '(:eval (when (fboundp 'fg-mode-line-string) (fg-mode-line-string))) ;; ... )
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4