feat!: support for arbitrary objects as indices
BREAKING-CHANGE: Many external and internal functions have been renamed to replace the word "number" with the more general word "index."
This commit is contained in:
parent
c5455e866e
commit
e0c329e0f6
11
README.org
11
README.org
|
@ -19,14 +19,13 @@
|
|||
- [[#future-developments][Future developments]]
|
||||
|
||||
* Introduction
|
||||
Window numbers for Emacs: Navigate your windows and frames using numbers !
|
||||
|
||||
This package is an extended and actively maintained version of the
|
||||
[[https://github.com/nschum/window-numbering.el][window-numbering]] package by Nikolaj Schumacher, with some ideas and code taken
|
||||
from [[https://github.com/abo-abo/ace-window][ace-window]].
|
||||
This package is a fork of the [[https://github.com/deb0ch/emacs-winum][winum]] package, which is itself a fork of the
|
||||
[[https://github.com/nschum/window-numbering.el][window-numbering]] package.
|
||||
|
||||
This version brings, among other things, support for number sets across multiple
|
||||
frames, giving the user a smoother experience of multi-screen Emacs.
|
||||
Compared to winum, this fork adds support for windows having arbitrary Lisp values
|
||||
as identifiers, as opposed to strictly increasing numbers. The public
|
||||
API is largely the same, however, and simple numbers are still the default.
|
||||
|
||||
* Changelog
|
||||
** Sep. 11 2019
|
||||
|
|
408
winum.el
408
winum.el
|
@ -65,18 +65,15 @@ Has effect only when `winum-scope' is not 'frame-local."
|
|||
:group 'winum
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom winum-auto-assign-0-to-minibuffer t
|
||||
"If non-nil, `winum-mode' assigns 0 to the minibuffer when active."
|
||||
(defcustom winum-minibuffer-auto-assign 0
|
||||
"If non-nil, `winum-mode' automatically assigns this index to the minibuffer."
|
||||
:group 'winum
|
||||
:type 'boolean)
|
||||
:type 'sexp)
|
||||
|
||||
(defcustom winum-assign-func nil
|
||||
"Function called for each window by `winum-mode'.
|
||||
This is called before automatic assignment begins. The function should
|
||||
return a number to have it assigned to the current-window, nil otherwise.
|
||||
|
||||
This function along with `winum-auto-assign-0-to-minibuffer' are the only
|
||||
ways to have 0 assigned to a window.
|
||||
return an index to have it assigned to the current-window, nil otherwise.
|
||||
|
||||
Example: always assign *Calculator* the number 9 and *NeoTree* the number 0:
|
||||
|
||||
|
@ -98,21 +95,18 @@ Example: always assign *Calculator* the number 9 and *NeoTree* the number 0:
|
|||
(defcustom winum-assign-functions nil
|
||||
"List of functions called for each window by `winum-mode'.
|
||||
|
||||
These functions allow for deterministic assignment of numbers to windows. Each
|
||||
function is called for every window. A function should return the number to be
|
||||
assigned to a window or nil. The *first* function to output a number for
|
||||
a given window will determine this window's number.
|
||||
These functions allow for deterministic assignment of indices to windows. Each
|
||||
function is called for every window. A function should return the index to be
|
||||
assigned to a window or nil. The *first* function to output a value for a
|
||||
given window will determine this window's number.
|
||||
|
||||
If the list is empty or if every functions returns nil for a given window winum
|
||||
will proceed to automatic number assignment.
|
||||
will proceed to automatic assignment.
|
||||
|
||||
Since this list is meant to allow custom window assignment for *mutiple*
|
||||
packages at once it should never be directly set, only added to and removed
|
||||
from.
|
||||
|
||||
These functions, along with `winum-auto-assign-0-to-minibuffer', are the only
|
||||
way to have 0 assigned to a window.
|
||||
|
||||
Example: always assign *Calculator* the number 9, *Flycheck-errors* the number 8
|
||||
and *NeoTree* the number 0:
|
||||
|
||||
|
@ -129,7 +123,21 @@ and *NeoTree* the number 0:
|
|||
(add-to-list
|
||||
'winum-assign-functions #'winum-assign-0-to-neotree)"
|
||||
:group 'winum
|
||||
:type 'list)
|
||||
:type '(repeat function))
|
||||
|
||||
(defcustom winum-auto-assign-function #'winum--auto-assign
|
||||
"The function called to auto-assign indices to windows.
|
||||
|
||||
This function is called after `winum-assign-functions' to automatically assign
|
||||
indices to the remaining windows. It must take in a list of windows and call
|
||||
the function `winum--assign' to assign an index to each, while avoiding
|
||||
assigning any indices already taken (stored in `winum--assigned-indices').
|
||||
Members of this list should be tested for using `equal'.
|
||||
|
||||
The default auto-assign function is `winum--auto-assign', which assigns strictly
|
||||
increasing integers to each window."
|
||||
:group 'winum
|
||||
:type 'function)
|
||||
|
||||
(defcustom winum-auto-setup-mode-line t
|
||||
"When nil, `winum-mode' will not display window numbers in the mode-line.
|
||||
|
@ -143,33 +151,38 @@ numbers in the mode-line."
|
|||
:group 'winum
|
||||
:type 'integer)
|
||||
|
||||
(defcustom winum-mode-line-p #'integerp
|
||||
"A predicate that determines when to display a window index on the mode-line.
|
||||
By default, only integers are displayed."
|
||||
:group 'winum
|
||||
:type 'function)
|
||||
|
||||
(defcustom winum-format " %s "
|
||||
"Format string defining how the window number looks like in the mode-line.
|
||||
This string is passed to the `format' function along with the
|
||||
result of `winum-get-number-string'."
|
||||
This string is passed to the `format' function along with the index."
|
||||
:group 'winum
|
||||
:type 'string)
|
||||
|
||||
(defcustom winum-ignored-buffers '(" *which-key*")
|
||||
"List of buffers to ignore when assigning numbers."
|
||||
"List of buffers to ignore when assigning indices."
|
||||
:group 'winum
|
||||
:type '(repeat string))
|
||||
|
||||
(defcustom winum-ignored-buffers-regexp '()
|
||||
"List of regexps for buffer names to ignore when assigning numbers.
|
||||
"List of regexps for buffer names to ignore when assigning indices.
|
||||
See Info node `(emacs) Regexps' or Info node `(elisp) Regular Expressions'"
|
||||
:group 'winum
|
||||
:type '(repeat string)
|
||||
:risky t)
|
||||
|
||||
(defface winum-face '()
|
||||
"Face used for the number in the mode-line."
|
||||
"Face used for the index in the mode-line."
|
||||
:group 'winum)
|
||||
|
||||
(defvar winum-base-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "`") 'winum-select-window-by-number)
|
||||
(define-key map (kbd "²") 'winum-select-window-by-number)
|
||||
(define-key map (kbd "`") 'winum-select-window-by-index)
|
||||
(define-key map (kbd "²") 'winum-select-window-by-index)
|
||||
(define-key map (kbd "0") 'winum-select-window-0-or-10)
|
||||
(define-key map (kbd "1") 'winum-select-window-1)
|
||||
(define-key map (kbd "2") 'winum-select-window-2)
|
||||
|
@ -183,9 +196,9 @@ See Info node `(emacs) Regexps' or Info node `(elisp) Regular Expressions'"
|
|||
map)
|
||||
"Keymap to be used under the prefix provided by `winum-keymap-prefix'.")
|
||||
|
||||
(defvar winum-keymap (let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-x w") winum-base-map)
|
||||
map)
|
||||
(defvar winum-mode-map (let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-x w") winum-base-map)
|
||||
map)
|
||||
"Keymap used for `winum-mode'.")
|
||||
|
||||
;; Internal variables ----------------------------------------------------------
|
||||
|
@ -193,37 +206,36 @@ See Info node `(emacs) Regexps' or Info node `(elisp) Regular Expressions'"
|
|||
(defvar winum--max-frames 16
|
||||
"Maximum number of frames that can be numbered.")
|
||||
|
||||
(defvar winum--window-count nil
|
||||
"Current count of windows to be numbered.")
|
||||
(defvar winum--assigned-indices nil
|
||||
"List of indices that have already been assigned by `winum-assign-functions'.")
|
||||
|
||||
(defvar winum--remaining nil
|
||||
"A list of window numbers to assign.")
|
||||
(defvar winum--window-table nil
|
||||
"Hash table with indices as keys and windows as values.
|
||||
Used internally by winum to get a window provided an index.")
|
||||
|
||||
(defvar winum--window-vector nil
|
||||
"Vector of windows indexed by their number.
|
||||
Used internally by winum to get a window provided a number.")
|
||||
|
||||
(defvar winum--numbers-table nil
|
||||
"Hash table of numbers indexed by their window.
|
||||
Used internally by winum to get a number provided a window.")
|
||||
(defvar winum--index-table nil
|
||||
"Hash table with windows as keys and indices as values.
|
||||
Used internally by winum to get an index provided a window.")
|
||||
|
||||
(defvar winum--frames-table nil
|
||||
"Table linking windows to numbers and numbers to windows for each frame.
|
||||
"Table linking windows to indices and indices to windows for each frame.
|
||||
|
||||
Used only when `winum-scope' is 'frame-local to keep track of
|
||||
separate window numbers sets in every frame.
|
||||
separate window index sets in every frame.
|
||||
|
||||
It is a hash table using Emacs frames as keys and cons of the form
|
||||
\(`winum--window-vector' . `winum--numbers-table')
|
||||
\(`winum--window-table' . `winum--index-table')
|
||||
as values.
|
||||
|
||||
To get a window given a number, use the `car' of a value.
|
||||
To get a number given a window, use the `cdr' of a value.
|
||||
To get a window given an index, use the `car' of a value.
|
||||
To get an index given a window, use the `cdr' of a value.
|
||||
|
||||
Such a structure allows for per-frame bidirectional fast access.")
|
||||
|
||||
(defvar winum--mode-line-segment
|
||||
'(:eval (format winum-format (winum-get-number-string)))
|
||||
'(:eval (let ((index (winum-get-index)))
|
||||
(when (funcall winum-mode-line-p index)
|
||||
(propertize (format winum-format index) 'face 'winum-face))))
|
||||
"What is pushed into `mode-line-format' when setting it up automatically.")
|
||||
|
||||
(defvar winum--last-used-scope winum-scope
|
||||
|
@ -235,9 +247,7 @@ Needed to detect scope changes at runtime.")
|
|||
;;;###autoload
|
||||
(define-minor-mode winum-mode
|
||||
"A minor mode that allows for managing windows based on window numbers."
|
||||
nil
|
||||
nil
|
||||
winum-keymap
|
||||
:lighter nil
|
||||
:global t
|
||||
(if winum-mode
|
||||
(winum--init)
|
||||
|
@ -245,115 +255,145 @@ Needed to detect scope changes at runtime.")
|
|||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-0-or-10 (&optional arg)
|
||||
"Jump to window 0 if assigned or 10 if exists.
|
||||
"Jump to window 0, or window 10 if 0 is not assigned.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(let ((n (if (winum-get-window-by-number 0)
|
||||
(if arg '- 0)
|
||||
(if arg -10 10))))
|
||||
(winum-select-window-by-number n)))
|
||||
(let ((n (if (winum-get-window-by-index 0) 0 10)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index n)
|
||||
(winum-select-window-by-index n))))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-0 (&optional arg)
|
||||
"Jump to window 0.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg '- 0)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 0)
|
||||
(winum-select-window-by-index 0)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-1 (&optional arg)
|
||||
"Jump to window 1.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -1 1)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 1)
|
||||
(winum-select-window-by-index 1)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-2 (&optional arg)
|
||||
"Jump to window 2.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -2 2)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 2)
|
||||
(winum-select-window-by-index 2)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-3 (&optional arg)
|
||||
"Jump to window 3.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -3 3)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 3)
|
||||
(winum-select-window-by-index 3)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-4 (&optional arg)
|
||||
"Jump to window 4.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -4 4)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 4)
|
||||
(winum-select-window-by-index 4)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-5 (&optional arg)
|
||||
"Jump to window 5.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -5 5)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 5)
|
||||
(winum-select-window-by-index 5)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-6 (&optional arg)
|
||||
"Jump to window 6.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -6 6)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 6)
|
||||
(winum-select-window-by-index 6)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-7 (&optional arg)
|
||||
"Jump to window 7.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -7 7)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 7)
|
||||
(winum-select-window-by-index 7)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-8 (&optional arg)
|
||||
"Jump to window 8.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -8 8)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 8)
|
||||
(winum-select-window-by-index 8)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-9 (&optional arg)
|
||||
"Jump to window 9.
|
||||
If prefix ARG is given, delete the window instead of selecting it."
|
||||
(interactive "P")
|
||||
(winum-select-window-by-number (if arg -9 9)))
|
||||
(if arg
|
||||
(winum-delete-window-by-index 9)
|
||||
(winum-select-window-by-index 9)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-select-window-by-number (&optional arg)
|
||||
"Select or delete window which number is specified by ARG.
|
||||
If the number is negative, delete the window instead of selecting it.
|
||||
There are several ways to provide the number:
|
||||
(defun winum-select-window-by-index (&optional arg)
|
||||
"Select window whose index is specified by ARG.
|
||||
There are several ways to provide the value:
|
||||
- if called from elisp with an argument, use it.
|
||||
- if called from elisp without an argument, use current window.
|
||||
- if called interactively with a numeric prefix argument, use it.
|
||||
- if prefix argument is the negative argument, delete window 0.
|
||||
- if prefix argument is the default prefix argument, delete current window.
|
||||
- if called interactively and no valid argument is provided, read from
|
||||
minibuffer."
|
||||
- if called interactively with the default prefix argument, use current window.
|
||||
- if called interactively and no argument is provided, read from minibuffer."
|
||||
(interactive "P")
|
||||
(let* ((n (cond
|
||||
((integerp arg) arg)
|
||||
((eq arg '-) 0) ; the negative argument
|
||||
(arg (winum-get-number))
|
||||
((called-interactively-p 'any)
|
||||
(let ((user-input-str (read-from-minibuffer "Window: ")))
|
||||
(if (not (string-match-p "[+-]?[0-9]+\.*" user-input-str))
|
||||
(winum-get-number)
|
||||
(string-to-number user-input-str))))
|
||||
(t (winum-get-number))))
|
||||
(w (winum-get-window-by-number (abs n)))
|
||||
(delete (and arg
|
||||
(or (not (integerp arg))
|
||||
(> 0 n)))))
|
||||
(let* ((i (if (called-interactively-p 'any)
|
||||
(cond
|
||||
((integerp arg) arg)
|
||||
(arg (winum-get-index))
|
||||
(t (read--expression "Window: ")))
|
||||
(or arg (winum-get-index))))
|
||||
(w (winum-get-window-by-index i)))
|
||||
(if w
|
||||
(if delete
|
||||
(delete-window w)
|
||||
(winum--switch-to-window w))
|
||||
(error "No window numbered %d" n))))
|
||||
(winum--switch-to-window w)
|
||||
(user-error "No window with index %S" i))))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-delete-window-by-index (&optional arg)
|
||||
"Delete window whose index is specified by ARG.
|
||||
There are several ways to provide the value:
|
||||
- if called from elisp with an argument, use it.
|
||||
- if called from elisp without an argument, use current window.
|
||||
- if called interactively with a numeric prefix argument, use it.
|
||||
- if called interactively with the default prefix argument, use current window.
|
||||
- if called interactively and no argument is provided, read from minibuffer."
|
||||
(interactive "P")
|
||||
(let* ((i (if (called-interactively-p 'any)
|
||||
(cond
|
||||
((integerp arg) arg)
|
||||
(arg (winum-get-index))
|
||||
(t (read--expression "Window: ")))
|
||||
(or arg (winum-get-index))))
|
||||
(w (winum-get-window-by-index i)))
|
||||
(if w
|
||||
(delete-window w)
|
||||
(user-error "No window with index %S" i))))
|
||||
|
||||
;; Public API ------------------------------------------------------------------
|
||||
|
||||
|
@ -371,41 +411,38 @@ PREFIX must be a key sequence, like the ones returned by `kbd'."
|
|||
winum-keymap))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-get-window-by-number (n)
|
||||
"Return window numbered N if exists, nil otherwise."
|
||||
(let ((window-vector (winum--get-window-vector)))
|
||||
(when (and (>= n 0) (< n (length window-vector)))
|
||||
(aref window-vector n))))
|
||||
(defun winum-get-window-by-index (index)
|
||||
"Return window INDEX if exists, nil otherwise."
|
||||
(let ((window-table (winum--get-window-table)))
|
||||
(gethash index window-table)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-get-index (&optional window)
|
||||
"Get the index of WINDOW or the current window."
|
||||
(let ((w (or window (selected-window))))
|
||||
(gethash w (winum--get-index-table))))
|
||||
|
||||
;; For backwards compatibility
|
||||
;;;###autoload
|
||||
(defun winum-get-number-string (&optional window)
|
||||
"Get the current or specified window's current number as a propertized string.
|
||||
WINDOW: if specified, the window of which we want to know the number.
|
||||
If not specified, the number of the currently selected window is
|
||||
returned."
|
||||
(let* ((n (winum-get-number window))
|
||||
(s (if (numberp n)
|
||||
(int-to-string n)
|
||||
(let* ((n (winum-get-index window))
|
||||
(s (if (funcall winum-mode-line-p n)
|
||||
(format "%s" n)
|
||||
"")))
|
||||
(propertize s 'face 'winum-face)))
|
||||
|
||||
;;;###autoload
|
||||
(defun winum-get-number (&optional window)
|
||||
"Get the current or specified window's current number.
|
||||
WINDOW: if specified, the window of which we want to know the number.
|
||||
If not specified, the number of the currently selected window is
|
||||
returned."
|
||||
(let ((w (or window (selected-window))))
|
||||
(gethash w (winum--get-numbers-table))))
|
||||
|
||||
;; Internal functions ----------------------------------------------------------
|
||||
|
||||
(defun winum--init ()
|
||||
"Initialize winum-mode."
|
||||
(setq winum--window-count (length (winum--window-list)))
|
||||
(if (eq winum-scope 'frame-local)
|
||||
(setq winum--frames-table (make-hash-table :size winum--max-frames))
|
||||
(setq winum--numbers-table (make-hash-table :size winum--window-count)))
|
||||
(setq winum--window-table (make-hash-table :test 'equal)
|
||||
winum--index-table (make-hash-table :test 'equal)))
|
||||
(when winum-auto-setup-mode-line
|
||||
(winum--install-mode-line))
|
||||
(add-hook 'minibuffer-setup-hook 'winum--update)
|
||||
|
@ -423,7 +460,7 @@ WINDOW: if specified, the window of which we want to know the number.
|
|||
(setq winum--frames-table nil))
|
||||
|
||||
(defun winum--install-mode-line (&optional position)
|
||||
"Install the window number from `winum-mode' to the mode-line.
|
||||
"Install the window index from `winum-mode' to the mode-line.
|
||||
POSITION: position in the mode-line."
|
||||
(let ((mode-line (default-value 'mode-line-format))
|
||||
res)
|
||||
|
@ -440,84 +477,76 @@ POSITION: position in the mode-line."
|
|||
(force-mode-line-update t))
|
||||
|
||||
(defun winum--clear-mode-line ()
|
||||
"Remove the window number of `winum-mode' from the mode-line."
|
||||
"Remove the window index of `winum-mode' from the mode-line."
|
||||
(let ((mode-line (default-value 'mode-line-format))
|
||||
res)
|
||||
(while mode-line
|
||||
(let ((item (pop mode-line)))
|
||||
(unless (equal item winum--mode-line-segment)
|
||||
(push item res))))
|
||||
(push item res))))
|
||||
(let ((nres (nreverse res)))
|
||||
(setq mode-line-format nres)
|
||||
(setq-default mode-line-format nres)))
|
||||
(force-mode-line-update t))
|
||||
|
||||
(defun winum--update ()
|
||||
"Update window numbers."
|
||||
"Update window indices."
|
||||
(let ((windows (winum--window-list)))
|
||||
(setq winum--window-count (length windows)
|
||||
winum--remaining (winum--available-numbers))
|
||||
(winum--set-window-vector (make-vector (1+ winum--window-count) nil))
|
||||
(clrhash (winum--get-numbers-table))
|
||||
(setq winum--assigned-indices nil)
|
||||
(clrhash (winum--get-window-table))
|
||||
(clrhash (winum--get-index-table))
|
||||
(when winum-assign-functions
|
||||
(-each windows #'winum--try-to-find-custom-number))
|
||||
(when (and winum-auto-assign-0-to-minibuffer
|
||||
(--each (-copy windows) (when (winum--try-to-find-custom-index it)
|
||||
(setq windows (delq it windows)))))
|
||||
(when (and winum-minibuffer-auto-assign
|
||||
(active-minibuffer-window)
|
||||
(not (winum-get-window-by-number 0)))
|
||||
(winum--assign (active-minibuffer-window) 0))
|
||||
(dolist (w windows)
|
||||
(winum--assign w))))
|
||||
(not (winum-get-window-by-index winum-minibuffer-auto-assign)))
|
||||
(winum--assign (active-minibuffer-window) winum-minibuffer-auto-assign)
|
||||
(push winum-minibuffer-auto-assign winum--assigned-indices))
|
||||
;; Auto-assign remaining windows
|
||||
(when windows
|
||||
(funcall winum-auto-assign-function windows))))
|
||||
|
||||
(defun winum--try-to-find-custom-number (window)
|
||||
"Try to find and assign a custom number for WINDOW.
|
||||
(defun winum--auto-assign (windows)
|
||||
"The default auto-assign function for assigning indices to windows.
|
||||
Takes in the list of windows WINDOWS and uses `winum--assign' to assign
|
||||
increasing integers to it."
|
||||
(let ((index 1))
|
||||
(dolist (w windows)
|
||||
(while (member index winum--assigned-indices)
|
||||
(setq index (1+ index)))
|
||||
(winum--assign w index)
|
||||
(setq index (1+ index)))))
|
||||
|
||||
(defun winum--try-to-find-custom-index (window)
|
||||
"Try to find and assign a custom index for WINDOW.
|
||||
Do so by trying every function in `winum-assign-functions' and assign the
|
||||
*first* non nil integer.
|
||||
When multiple functions assign a number to a window log a warning and use the
|
||||
first number anyway."
|
||||
*first* non nil value.
|
||||
When multiple functions assign an index to a window log a warning and use the
|
||||
first index anyway."
|
||||
(with-selected-window window
|
||||
(with-current-buffer (window-buffer window)
|
||||
(let* ((nums (->> winum-assign-functions
|
||||
(--map (cons it (funcall it)))
|
||||
(--remove (null (cdr it)))))
|
||||
(num (-> nums (cl-first) (cdr))))
|
||||
(when (> (length nums) 1)
|
||||
(message "Winum conflict - window %s was assigned a number by multiple custom assign functions: '%s'"
|
||||
window (--map (format "%s -> %s" (car it) (cdr it)) nums)))
|
||||
(when (integerp num) (winum--assign window num))))))
|
||||
(when-let* ((inds (->> winum-assign-functions
|
||||
(--map (cons it (funcall it)))
|
||||
(--remove (null (cdr it)))))
|
||||
(ind (-> inds (cl-first) (cdr))))
|
||||
(when (> (length inds) 1)
|
||||
(message "Winum conflict - window %s was assigned an index by multiple custom assign functions: '%s'"
|
||||
window (--map (format "%s -> %S" (car it) (cdr it)) inds)))
|
||||
(winum--assign window ind)
|
||||
(push ind winum--assigned-indices)))))
|
||||
|
||||
(defun winum--assign (window &optional number)
|
||||
"Assign to window WINDOW the number NUMBER.
|
||||
If NUMBER is not specified, determine it first based on `winum--remaining'.
|
||||
Returns the assigned number, or nil on error."
|
||||
(if number
|
||||
(defun winum--assign (window index)
|
||||
"Assign to window WINDOW the index INDEX.
|
||||
Returns the assigned index, or nil on error."
|
||||
(if (gethash index (winum--get-window-table))
|
||||
(progn
|
||||
(winum--maybe-expand-window-vector number)
|
||||
(if (aref (winum--get-window-vector) number)
|
||||
(progn
|
||||
(message "Number %s already assigned to %s, can't assign to %s"
|
||||
number (aref (winum--get-window-vector) number) window)
|
||||
nil)
|
||||
(setf (aref (winum--get-window-vector) number) window)
|
||||
(puthash window number (winum--get-numbers-table))
|
||||
(setq winum--remaining (delq number winum--remaining))
|
||||
number))
|
||||
;; else determine number and assign
|
||||
(when winum--remaining
|
||||
(unless (gethash window (winum--get-numbers-table))
|
||||
(let ((number (car winum--remaining)))
|
||||
(winum--assign window number))))))
|
||||
|
||||
(defun winum--maybe-expand-window-vector (number)
|
||||
"Expand `winum--window-vector' if NUMBER is bigger than its size.
|
||||
The size of `winum--window-vector' is normally based on the number of live
|
||||
windows, however a higher number can be reserved by the user-defined
|
||||
`winum-assign-func'."
|
||||
(let* ((window-vector (winum--get-window-vector))
|
||||
(window-vector-length (length window-vector)))
|
||||
(when (> number window-vector-length)
|
||||
(winum--set-window-vector
|
||||
(vconcat window-vector
|
||||
(make-vector (1+ (- number window-vector-length)) nil))))))
|
||||
(message "Index %S already assigned to %s, can't assign to %s"
|
||||
index (gethash index (winum--get-window-table)) window)
|
||||
nil)
|
||||
(puthash index window (winum--get-window-table))
|
||||
(puthash window index (winum--get-index-table))
|
||||
index))
|
||||
|
||||
(defun winum--window-list ()
|
||||
"Return a list of interesting windows."
|
||||
|
@ -537,10 +566,10 @@ windows, however a higher number can be reserved by the user-defined
|
|||
(frame-local
|
||||
(winum--list-windows-in-frame))
|
||||
(t
|
||||
(error "Invalid `winum-scope': %S" winum-scope)))))
|
||||
(user-error "Invalid `winum-scope': %S" winum-scope)))))
|
||||
|
||||
(defun winum--ignore-window-p (window)
|
||||
"Non-nil if WINDOW should be ignored for numbering."
|
||||
"Non-nil if WINDOW should be ignored for indexing."
|
||||
(let ((f (window-frame window)))
|
||||
(or (not (and (frame-live-p f)
|
||||
(frame-visible-p f)))
|
||||
|
@ -554,33 +583,25 @@ windows, however a higher number can be reserved by the user-defined
|
|||
"List windows in frame F using natural Emacs ordering."
|
||||
(window-list f 0 (frame-first-window f)))
|
||||
|
||||
(defun winum--set-window-vector (window-vector)
|
||||
"Set WINDOW-VECTOR according to the current `winum-scope'."
|
||||
(winum--check-for-scope-change)
|
||||
(if (eq winum-scope 'frame-local)
|
||||
(puthash (selected-frame)
|
||||
(cons window-vector
|
||||
(make-hash-table :size winum--window-count))
|
||||
winum--frames-table)
|
||||
(setq winum--window-vector window-vector)))
|
||||
|
||||
(defun winum--get-window-vector ()
|
||||
"Return the window vector used to get a window given a number.
|
||||
This vector is not stored the same way depending on the value of `winum-scope'."
|
||||
(defun winum--get-window-table ()
|
||||
"Return the window table used to get a window given an index.
|
||||
This hashtable is not stored the same way depending on the value of
|
||||
`winum-scope'."
|
||||
(winum--check-for-scope-change)
|
||||
(winum--check-frames-table)
|
||||
(if (eq winum-scope 'frame-local)
|
||||
(car (gethash (selected-frame) winum--frames-table))
|
||||
winum--window-vector))
|
||||
winum--window-table))
|
||||
|
||||
(defun winum--get-numbers-table ()
|
||||
"Return the numbers hashtable used to get a number given a window.
|
||||
(defun winum--get-index-table ()
|
||||
"Return the index hashtable used to get an index given a window.
|
||||
This hashtable is not stored the same way depending on the value of
|
||||
`winum-scope'"
|
||||
`winum-scope'."
|
||||
(winum--check-for-scope-change)
|
||||
(winum--check-frames-table)
|
||||
(if (eq winum-scope 'frame-local)
|
||||
(cdr (gethash (selected-frame) winum--frames-table))
|
||||
winum--numbers-table))
|
||||
winum--index-table))
|
||||
|
||||
(defun winum--check-frames-table ()
|
||||
"Make sure `winum--frames-table' exists and is correctly equipped.
|
||||
|
@ -593,17 +614,12 @@ Verifies 2 things (when `winum-scope' is frame local):
|
|||
(unless winum--frames-table
|
||||
(setq winum--frames-table (make-hash-table :size winum--max-frames)))
|
||||
(unless (gethash (selected-frame) winum--frames-table)
|
||||
(puthash (selected-frame) (cons
|
||||
(make-hash-table :test 'equal)
|
||||
(make-hash-table :test 'equal))
|
||||
winum--frames-table)
|
||||
(winum--update))))
|
||||
|
||||
(defun winum--available-numbers ()
|
||||
"Return a list of numbers from 1 to `winum--window-count'.
|
||||
0 is is not part of the list as its assignment is either manual
|
||||
using the `winum-assign-func', or using `winum-auto-assign-0-to-minibuffer'."
|
||||
(let ((numbers))
|
||||
(dotimes (i winum--window-count)
|
||||
(push (1+ i) numbers))
|
||||
(nreverse numbers)))
|
||||
|
||||
(defun winum--switch-to-window (window)
|
||||
"Switch to the window WINDOW and switch input focus if on a different frame."
|
||||
(let ((frame (window-frame window)))
|
||||
|
@ -629,10 +645,6 @@ internal data structures according to the new scope."
|
|||
|
||||
(add-hook 'delete-frame-functions #'winum--remove-deleted-frame-from-frames-table)
|
||||
|
||||
(push "^No window numbered .$" debug-ignored-errors)
|
||||
(push "^Got a dead window .$" debug-ignored-errors)
|
||||
(push "^Invalid `winum-scope': .$" debug-ignored-errors)
|
||||
|
||||
(provide 'winum)
|
||||
|
||||
;;; winum.el ends here
|
||||
|
|
Loading…
Reference in a new issue