11
README.rst
11
README.rst
@ -46,6 +46,12 @@ window config on slot 2 is saved and the window config from slot 1 is
|
|||||||
loaded. Try switching back and forth between them with ``C-c C-w '``
|
loaded. Try switching back and forth between them with ``C-c C-w '``
|
||||||
to get a feeling for how subsequent window manipulations are handled.
|
to get a feeling for how subsequent window manipulations are handled.
|
||||||
|
|
||||||
|
To make keeping track of workspaces easier, a tagging feature was
|
||||||
|
added. Use ``C-c C-w ,`` to set a tag for the current window config,
|
||||||
|
it will both appear in the modeline indicator and when using ``M-x
|
||||||
|
eyebrowse-switch-to-window-config``. Setting the tag to an empty
|
||||||
|
value will undo this change.
|
||||||
|
|
||||||
Key bindings
|
Key bindings
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@ -58,6 +64,7 @@ Key bind Function
|
|||||||
``C-c C-w >`` Switch to next window config
|
``C-c C-w >`` Switch to next window config
|
||||||
``C-c C-w '`` Switch to last window config
|
``C-c C-w '`` Switch to last window config
|
||||||
``C-c C-w "`` Close current window config
|
``C-c C-w "`` Close current window config
|
||||||
|
``C-c C-w ,`` Rename current window config
|
||||||
``C-c C-w 0`` Switch to window config ``0``
|
``C-c C-w 0`` Switch to window config ``0``
|
||||||
\... ...
|
\... ...
|
||||||
``C-c C-w 9`` Switch to window config ``9``
|
``C-c C-w 9`` Switch to window config ``9``
|
||||||
@ -109,8 +116,8 @@ This mode basically wraps what ``C-x r w`` and ``C-x r j`` do. The
|
|||||||
difference is first, it saves and loads automatically for you upon
|
difference is first, it saves and loads automatically for you upon
|
||||||
switching slots, and second, it doesn't overwrite the general purpose
|
switching slots, and second, it doesn't overwrite the general purpose
|
||||||
registers. What it does instead is keeping its own data structure (a
|
registers. What it does instead is keeping its own data structure (a
|
||||||
list of lists containing slot, window config and point) and using it
|
list of lists containing slot, window config, point and tag) and using
|
||||||
to provide some other convenience keybinds, such as jumping to the
|
it to provide some other convenience keybinds, such as jumping to the
|
||||||
last window config or the next one available.
|
last window config or the next one available.
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
|
|||||||
116
eyebrowse.el
116
eyebrowse.el
@ -37,6 +37,7 @@
|
|||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(require 'dash)
|
(require 'dash)
|
||||||
|
(require 'format-spec)
|
||||||
|
|
||||||
|
|
||||||
;; variables
|
;; variables
|
||||||
@ -147,6 +148,24 @@ t: Clean up and display the scratch buffer."
|
|||||||
:type 'hook
|
:type 'hook
|
||||||
:group 'eyebrowse)
|
:group 'eyebrowse)
|
||||||
|
|
||||||
|
(defcustom eyebrowse-slot-format "%s"
|
||||||
|
"Format string for untagged slots.
|
||||||
|
The following format codes are supported:
|
||||||
|
|
||||||
|
%s: Current slot"
|
||||||
|
:type 'string
|
||||||
|
:group 'eyebrowse)
|
||||||
|
|
||||||
|
(defcustom eyebrowse-tagged-slot-format "%s:%t"
|
||||||
|
"Format string for tagged slots.
|
||||||
|
The following format codes are supported:
|
||||||
|
|
||||||
|
%t: Tag
|
||||||
|
|
||||||
|
%s: Current slot"
|
||||||
|
:type 'string
|
||||||
|
:group 'eyebrowse)
|
||||||
|
|
||||||
(defvar eyebrowse-mode-map
|
(defvar eyebrowse-mode-map
|
||||||
(let ((map (make-sparse-keymap)))
|
(let ((map (make-sparse-keymap)))
|
||||||
(let ((prefix-map (make-sparse-keymap)))
|
(let ((prefix-map (make-sparse-keymap)))
|
||||||
@ -154,6 +173,7 @@ t: Clean up and display the scratch buffer."
|
|||||||
(define-key prefix-map (kbd ">") 'eyebrowse-next-window-config)
|
(define-key prefix-map (kbd ">") 'eyebrowse-next-window-config)
|
||||||
(define-key prefix-map (kbd "'") 'eyebrowse-last-window-config)
|
(define-key prefix-map (kbd "'") 'eyebrowse-last-window-config)
|
||||||
(define-key prefix-map (kbd "\"") 'eyebrowse-close-window-config)
|
(define-key prefix-map (kbd "\"") 'eyebrowse-close-window-config)
|
||||||
|
(define-key prefix-map (kbd ",") 'eyebrowse-rename-window-config)
|
||||||
(define-key prefix-map (kbd "0") 'eyebrowse-switch-to-window-config-0)
|
(define-key prefix-map (kbd "0") 'eyebrowse-switch-to-window-config-0)
|
||||||
(define-key prefix-map (kbd "1") 'eyebrowse-switch-to-window-config-1)
|
(define-key prefix-map (kbd "1") 'eyebrowse-switch-to-window-config-1)
|
||||||
(define-key prefix-map (kbd "2") 'eyebrowse-switch-to-window-config-2)
|
(define-key prefix-map (kbd "2") 'eyebrowse-switch-to-window-config-2)
|
||||||
@ -171,19 +191,6 @@ t: Clean up and display the scratch buffer."
|
|||||||
|
|
||||||
;; functions
|
;; functions
|
||||||
|
|
||||||
;; NOTE: window configurations are at the moment a list of a list
|
|
||||||
;; containing the numerical slot, window configuration and point. To
|
|
||||||
;; add "tagging", it would be useful to save a tag as fourth component
|
|
||||||
;; and display it if present, not only in the mode line, but when
|
|
||||||
;; renaming and selecting a window configuration interactively, too.
|
|
||||||
;; This obviously requires an interactive window switching command.
|
|
||||||
|
|
||||||
;; NOTE: The display of the tag should be configurable via format
|
|
||||||
;; string and that format string be able to resemble vim tabs, i3
|
|
||||||
;; workspaces, tmux sessions, etc. Therefore it has to contain format
|
|
||||||
;; codes for slot, tag and buffer name. A suitable formatting
|
|
||||||
;; function can be found in s.el.
|
|
||||||
|
|
||||||
(defun eyebrowse--get (type &optional frame)
|
(defun eyebrowse--get (type &optional frame)
|
||||||
"Retrieve frame-specific value of TYPE.
|
"Retrieve frame-specific value of TYPE.
|
||||||
If FRAME is nil, use current frame. TYPE can be any of
|
If FRAME is nil, use current frame. TYPE can be any of
|
||||||
@ -215,7 +222,7 @@ If FRAME is nil, use current frame. TYPE can be any of
|
|||||||
(eyebrowse--set 'last-slot 1 frame)
|
(eyebrowse--set 'last-slot 1 frame)
|
||||||
(eyebrowse--set 'current-slot 1 frame)
|
(eyebrowse--set 'current-slot 1 frame)
|
||||||
(eyebrowse--insert-in-window-config-list
|
(eyebrowse--insert-in-window-config-list
|
||||||
(eyebrowse--current-window-config 1) frame)))
|
(eyebrowse--current-window-config 1 "") frame)))
|
||||||
|
|
||||||
(defun eyebrowse--update-window-config-element (new-element)
|
(defun eyebrowse--update-window-config-element (new-element)
|
||||||
"Replace the old element with NEW-ELEMENT in the window config list.
|
"Replace the old element with NEW-ELEMENT in the window config list.
|
||||||
@ -236,9 +243,9 @@ This function keeps the sortedness intact."
|
|||||||
"Non-nil if there is a window config at SLOT."
|
"Non-nil if there is a window config at SLOT."
|
||||||
(assq slot (eyebrowse--get 'window-configs frame)))
|
(assq slot (eyebrowse--get 'window-configs frame)))
|
||||||
|
|
||||||
(defun eyebrowse--current-window-config (slot)
|
(defun eyebrowse--current-window-config (slot tag)
|
||||||
"Returns a window config list appliable for SLOT."
|
"Returns a window config list appliable for SLOT."
|
||||||
(list slot (current-window-configuration) (point)))
|
(list slot (current-window-configuration) (point) tag))
|
||||||
|
|
||||||
(defun eyebrowse--load-window-config (slot)
|
(defun eyebrowse--load-window-config (slot)
|
||||||
"Restore the window config from SLOT."
|
"Restore the window config from SLOT."
|
||||||
@ -250,14 +257,18 @@ This function keeps the sortedness intact."
|
|||||||
(goto-char point)))))
|
(goto-char point)))))
|
||||||
|
|
||||||
(defun eyebrowse--read-slot (&optional initial-slot)
|
(defun eyebrowse--read-slot (&optional initial-slot)
|
||||||
(let* ((candidates (--map (number-to-string (car it))
|
"Read in a window config SLOT to switch to.
|
||||||
|
A formatted list of window configs is presented as candidates.
|
||||||
|
If INITIAL-SLOT is set, use the respective window config as
|
||||||
|
preselected candidate."
|
||||||
|
(let* ((candidates (--map (cons (eyebrowse-format-slot it)
|
||||||
|
(car it))
|
||||||
(eyebrowse--get 'window-configs)))
|
(eyebrowse--get 'window-configs)))
|
||||||
(selection (completing-read
|
(candidate (completing-read
|
||||||
"Enter slot: " candidates
|
"Enter slot: " candidates nil t
|
||||||
nil nil (and initial-slot (number-to-string initial-slot))))
|
(and initial-slot
|
||||||
(slot (string-to-number selection)))
|
(car (rassoc initial-slot candidates))))))
|
||||||
(unless (and (= slot 0) (not (string= selection "0")))
|
(cdr (assoc candidate candidates))))
|
||||||
slot)))
|
|
||||||
|
|
||||||
(defun eyebrowse-switch-to-window-config (slot)
|
(defun eyebrowse-switch-to-window-config (slot)
|
||||||
"Switch to the window config SLOT.
|
"Switch to the window config SLOT.
|
||||||
@ -266,20 +277,24 @@ This will save the current window config to
|
|||||||
`eyebrowse-switch-back-and-forth' is t and
|
`eyebrowse-switch-back-and-forth' is t and
|
||||||
`eyebrowse-current-slot' equals SLOT, this will switch to the
|
`eyebrowse-current-slot' equals SLOT, this will switch to the
|
||||||
last window config."
|
last window config."
|
||||||
(interactive (list (eyebrowse--read-slot (eyebrowse--get 'last-slot))))
|
(interactive (list (if (numberp current-prefix-arg)
|
||||||
|
current-prefix-arg
|
||||||
|
(eyebrowse--read-slot (eyebrowse--get 'last-slot)))))
|
||||||
(when slot
|
(when slot
|
||||||
(let ((current-slot (eyebrowse--get 'current-slot))
|
(let* ((current-slot (eyebrowse--get 'current-slot))
|
||||||
(last-slot (eyebrowse--get 'last-slot)))
|
(window-configs (eyebrowse--get 'window-configs))
|
||||||
|
(current-tag (nth 3 (assoc current-slot window-configs)))
|
||||||
|
(last-slot (eyebrowse--get 'last-slot)))
|
||||||
(when (and eyebrowse-switch-back-and-forth (= current-slot slot))
|
(when (and eyebrowse-switch-back-and-forth (= current-slot slot))
|
||||||
(setq slot last-slot))
|
(setq slot last-slot))
|
||||||
(let ((new-window-config (not (eyebrowse--window-config-present-p slot))))
|
(let ((new-window-config (not (eyebrowse--window-config-present-p slot))))
|
||||||
(when (/= current-slot slot)
|
(when (/= current-slot slot)
|
||||||
(run-hooks 'eyebrowse-pre-window-switch-hook)
|
(run-hooks 'eyebrowse-pre-window-switch-hook)
|
||||||
(eyebrowse--update-window-config-element
|
(eyebrowse--update-window-config-element
|
||||||
(eyebrowse--current-window-config current-slot))
|
(eyebrowse--current-window-config current-slot current-tag))
|
||||||
(when new-window-config
|
(when new-window-config
|
||||||
(eyebrowse--insert-in-window-config-list
|
(eyebrowse--insert-in-window-config-list
|
||||||
(eyebrowse--current-window-config slot)))
|
(eyebrowse--current-window-config slot "")))
|
||||||
(eyebrowse--load-window-config slot)
|
(eyebrowse--load-window-config slot)
|
||||||
(eyebrowse--set 'last-slot current-slot)
|
(eyebrowse--set 'last-slot current-slot)
|
||||||
(eyebrowse--set 'current-slot slot)
|
(eyebrowse--set 'current-slot slot)
|
||||||
@ -358,6 +373,23 @@ another appropriate window config."
|
|||||||
(eyebrowse-next-window-config nil))
|
(eyebrowse-next-window-config nil))
|
||||||
(eyebrowse--delete-window-config (eyebrowse--get 'last-slot)))))
|
(eyebrowse--delete-window-config (eyebrowse--get 'last-slot)))))
|
||||||
|
|
||||||
|
(defun eyebrowse-rename-window-config (slot)
|
||||||
|
"Rename the window config at SLOT.
|
||||||
|
When used interactively, default to the current window config,
|
||||||
|
use the prefix argument to prompt for a slot or a numerical
|
||||||
|
prefix argument to select a slot by its number."
|
||||||
|
(interactive (list (cond
|
||||||
|
((consp current-prefix-arg)
|
||||||
|
(eyebrowse--read-slot))
|
||||||
|
((numberp current-prefix-arg)
|
||||||
|
current-prefix-arg)
|
||||||
|
(t (eyebrowse--get 'current-slot)))))
|
||||||
|
(let* ((window-configs (eyebrowse--get 'window-configs))
|
||||||
|
(window-config (assoc slot window-configs))
|
||||||
|
(current-tag (nth 3 window-config))
|
||||||
|
(tag (read-string "Tag: " current-tag)))
|
||||||
|
(setf (nth 3 window-config) tag)))
|
||||||
|
|
||||||
;; NOTE I've tried out generating the respective commands dynamically
|
;; NOTE I've tried out generating the respective commands dynamically
|
||||||
;; with a macro, but this ended in unreadable code and Emacs not being
|
;; with a macro, but this ended in unreadable code and Emacs not being
|
||||||
;; able to locate the generated commands, using lexical binding and a
|
;; able to locate the generated commands, using lexical binding and a
|
||||||
@ -449,7 +481,16 @@ is detected, extra key bindings will be set up with
|
|||||||
(define-key map (kbd "M-8") 'eyebrowse-switch-to-window-config-8)
|
(define-key map (kbd "M-8") 'eyebrowse-switch-to-window-config-8)
|
||||||
(define-key map (kbd "M-9") 'eyebrowse-switch-to-window-config-9)))
|
(define-key map (kbd "M-9") 'eyebrowse-switch-to-window-config-9)))
|
||||||
|
|
||||||
(defun eyebrowse--update-mode-line ()
|
(defun eyebrowse-format-slot (window-config)
|
||||||
|
(let* ((slot (car window-config))
|
||||||
|
(tag (nth 3 window-config))
|
||||||
|
(format-string (if (and tag (> (length tag) 0))
|
||||||
|
eyebrowse-tagged-slot-format
|
||||||
|
eyebrowse-slot-format)))
|
||||||
|
(format-spec format-string
|
||||||
|
(format-spec-make ?s slot ?t tag))))
|
||||||
|
|
||||||
|
(defun eyebrowse-mode-line-indicator ()
|
||||||
"Return a string representation of the window configurations."
|
"Return a string representation of the window configurations."
|
||||||
(let* ((left-delimiter (propertize eyebrowse-mode-line-left-delimiter
|
(let* ((left-delimiter (propertize eyebrowse-mode-line-left-delimiter
|
||||||
'face 'eyebrowse-mode-line-delimiters))
|
'face 'eyebrowse-mode-line-delimiters))
|
||||||
@ -458,10 +499,7 @@ is detected, extra key bindings will be set up with
|
|||||||
(separator (propertize eyebrowse-mode-line-separator
|
(separator (propertize eyebrowse-mode-line-separator
|
||||||
'face 'eyebrowse-mode-line-separator))
|
'face 'eyebrowse-mode-line-separator))
|
||||||
(current-slot (eyebrowse--get 'current-slot))
|
(current-slot (eyebrowse--get 'current-slot))
|
||||||
(active-item (propertize (number-to-string current-slot)
|
(window-configs (eyebrowse--get 'window-configs)))
|
||||||
'face 'eyebrowse-mode-line-active))
|
|
||||||
(window-configs (eyebrowse--get 'window-configs))
|
|
||||||
(window-config-slots (mapcar 'car window-configs)))
|
|
||||||
(if (and eyebrowse-mode-line-style
|
(if (and eyebrowse-mode-line-style
|
||||||
(not (eq eyebrowse-mode-line-style 'hide))
|
(not (eq eyebrowse-mode-line-style 'hide))
|
||||||
(or (and (not (eq eyebrowse-mode-line-style 'smart))
|
(or (and (not (eq eyebrowse-mode-line-style 'smart))
|
||||||
@ -471,9 +509,13 @@ is detected, extra key bindings will be set up with
|
|||||||
(concat
|
(concat
|
||||||
left-delimiter
|
left-delimiter
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (n) (if (= n current-slot) active-item (number-to-string n)))
|
(lambda (window-config)
|
||||||
window-config-slots
|
(let ((slot (car window-config))
|
||||||
separator)
|
(caption (eyebrowse-format-slot window-config)))
|
||||||
|
(if (= slot current-slot)
|
||||||
|
(propertize caption 'face 'eyebrowse-mode-line-active)
|
||||||
|
caption)))
|
||||||
|
window-configs separator)
|
||||||
right-delimiter)
|
right-delimiter)
|
||||||
"")))
|
"")))
|
||||||
|
|
||||||
@ -494,7 +536,7 @@ behaviour of `ranger`, a file manager."
|
|||||||
(eyebrowse-init)
|
(eyebrowse-init)
|
||||||
(add-hook 'after-make-frame-functions 'eyebrowse-init)
|
(add-hook 'after-make-frame-functions 'eyebrowse-init)
|
||||||
(unless (assoc 'eyebrowse-mode mode-line-misc-info)
|
(unless (assoc 'eyebrowse-mode mode-line-misc-info)
|
||||||
(push '(eyebrowse-mode (:eval (eyebrowse--update-mode-line)))
|
(push '(eyebrowse-mode (:eval (eyebrowse-mode-line-indicator)))
|
||||||
(cdr (last mode-line-misc-info)))))
|
(cdr (last mode-line-misc-info)))))
|
||||||
(remove-hook 'after-make-frame-functions 'eyebrowse-init)))
|
(remove-hook 'after-make-frame-functions 'eyebrowse-init)))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user