Allow number set to be common to multiple frames

This allows the user to navigate windows across frames.

3 scopes are possible:

- frame-local: similar to old behaviour, one number set per frame
- visible: Only number windows in visible frames
- global: Number windows in all frames
This commit is contained in:
deb0ch 2016-12-08 15:51:24 +01:00
parent 10809b3993
commit bcccadcf12

View file

@ -85,6 +85,20 @@ return a number to have it assigned to the current-window, nil otherwise."
(defconst window-numbering-mode-line-position 1 (defconst window-numbering-mode-line-position 1
"The position in the mode-line `window-numbering-mode' displays the number.") "The position in the mode-line `window-numbering-mode' displays the number.")
(defcustom window-numbering-frame-scope 'global
"The scope of number sets."
:group 'window-numbering
:type '(choice
(const :tag "frame local" frame-local)
(const :tag "visible frames" visible)
(const :tag "global" global)))
(defcustom window-numbering-reverse-frame-list nil
"If t, order frames by reverse order of creation.
Has effect only when `window-numbering-frame-scope' is not 'frame-local."
:group 'window-numbering
:type 'boolean)
(defface window-numbering-face (defface window-numbering-face
'() '()
"Face used for the number in the mode-line." "Face used for the number in the mode-line."
@ -97,13 +111,16 @@ return a number to have it assigned to the current-window, nil otherwise."
"Select window given number I by `window-numbering-mode'. "Select window given number I by `window-numbering-mode'.
If prefix ARG is given, delete the window instead of selecting it." If prefix ARG is given, delete the window instead of selecting it."
(interactive "P") (interactive "P")
(let ((windows (car (gethash (selected-frame) window-numbering-table))) (let ((windows (if (eq window-numbering-frame-scope 'frame-local)
(car (gethash (selected-frame)
window-numbering-table))
window-numbering-windows))
window) window)
(if (and (>= i 0) (< i 10) (if (and (>= i 0) (< i 10)
(setq window (aref windows i))) (setq window (aref windows i)))
(if arg (if arg
(delete-window window) (delete-window window)
(select-window window)) (window-numbering-switch-to-window window))
(error "No window numbered %s" i)))) (error "No window numbered %s" i))))
;; define interactive functions for keymap ;; define interactive functions for keymap
@ -138,29 +155,27 @@ If prefix ARG is given, delete the window instead of selecting it."
(setf (aref window-numbering-windows number) window) (setf (aref window-numbering-windows number) window)
(puthash window number window-numbering-numbers) (puthash window number window-numbering-numbers)
(setq window-numbering-left (delq number window-numbering-left)) (setq window-numbering-left (delq number window-numbering-left))
t) number)
;; else default adding ;; else determine number and assign
(when window-numbering-left (when window-numbering-left
(unless (gethash window window-numbering-numbers) (unless (gethash window window-numbering-numbers)
(let ((number (car window-numbering-left))) (let ((number (car window-numbering-left)))
(window-numbering-assign window number) (window-numbering-assign window number))))))
number)))))
(defun window-numbering-update () (defun window-numbering-update ()
"Update the window numbering for the current frame. "Update window numbers."
Optional parameter PREASSIGNED-WINDOWS is a hashmap already mapping some
windows to numbers."
(setq window-numbering-windows (make-vector 10 nil) (setq window-numbering-windows (make-vector 10 nil)
window-numbering-numbers (make-hash-table :size 10) window-numbering-numbers (make-hash-table :size 10)
window-numbering-left window-numbering-left (window-numbering-calculate-left
(window-numbering-calculate-left window-numbering-windows)) window-numbering-windows))
(puthash (selected-frame) (when (eq window-numbering-frame-scope 'frame-local)
(cons window-numbering-windows window-numbering-numbers) (puthash (selected-frame)
window-numbering-table) (cons window-numbering-windows window-numbering-numbers)
window-numbering-table))
(when (and window-numbering-auto-assign-0-to-minibuffer (when (and window-numbering-auto-assign-0-to-minibuffer
(active-minibuffer-window)) (active-minibuffer-window))
(window-numbering-assign (active-minibuffer-window) 0)) (window-numbering-assign (active-minibuffer-window) 0))
(let ((windows (window-list nil 0 (frame-first-window)))) (let ((windows (window-numbering-window-list)))
(run-hook-with-args 'window-numbering-before-hook windows) (run-hook-with-args 'window-numbering-before-hook windows)
(when window-numbering-assign-func (when window-numbering-assign-func
(mapc (lambda (window) (mapc (lambda (window)
@ -173,13 +188,57 @@ windows to numbers."
(dolist (window windows) (dolist (window windows)
(window-numbering-assign window)))) (window-numbering-assign window))))
(defun window-numbering-list-windows-in-frame (&optional f)
"List windows in frame F using natural Emacs ordering."
(window-list f 0 (frame-first-window f)))
(defun window-numbering-window-list ()
"Return a list of interesting windows."
(cl-remove-if
(lambda (w)
(let ((f (window-frame w)))
(or (not (and (frame-live-p f)
(frame-visible-p f)))
(string= "initial_terminal" (terminal-name f))
;; (window-numbering-ignored-p w) ;; TODO implement
)))
(cl-case window-numbering-frame-scope
(global
(cl-mapcan 'window-numbering-list-windows-in-frame
(if window-numbering-reverse-frame-list
(frame-list)
(nreverse (frame-list)))))
(visible
(cl-mapcan 'window-numbering-list-windows-in-frame
(if window-numbering-reverse-frame-list
(visible-frame-list)
(nreverse (visible-frame-list)))))
(frame-local
(window-numbering-list-windows-in-frame))
(t
(error "Invalid `window-numbering-frame-scope': %S"
window-numbering-frame-scope)))))
(defun window-numbering-switch-to-window (window)
"Switch to the window WINDOW and switch input focus if on a different frame."
(let ((frame (window-frame window)))
(when (and (frame-live-p frame)
(not (eq frame (selected-frame))))
(select-frame-set-input-focus frame))
(if (window-live-p window)
(select-window window)
(error "Got a dead window %S" window))))
(defun window-numbering-get-number-string (&optional window) (defun window-numbering-get-number-string (&optional window)
(let ((s (int-to-string (window-numbering-get-number window)))) (let ((s (int-to-string (window-numbering-get-number window))))
(propertize s 'face 'window-numbering-face))) (propertize s 'face 'window-numbering-face)))
(defun window-numbering-get-number (&optional window) (defun window-numbering-get-number (&optional window)
(gethash (or window (selected-window)) (let ((w (or window (selected-window))))
(cdr (gethash (selected-frame) window-numbering-table)))) (if (eq window-numbering-frame-scope 'frame-local)
(gethash w (cdr (gethash (selected-frame)
window-numbering-table)))
(gethash w window-numbering-numbers))))
(defvar window-numbering-keymap (defvar window-numbering-keymap
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))