diff --git a/README.org b/README.org
index 1928613..79c72de 100644
--- a/README.org
+++ b/README.org
@@ -36,9 +36,9 @@ frames, giving the user a smoother experience of multi-screen Emacs.
#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path "/path/to/install/folder/winum.el/")
- (require 'window-numbering)
+ (require 'winum)
- (window-numbering-mode)
+ (winum-mode)
#+END_SRC
@@ -58,17 +58,17 @@ selecting it.
* Configuration
** Custom keymap
To define your own bindings and override the default ones, override
- =window-numbering-keymap= before activating the mode:
+ =winum-keymap= before activating the mode:
#+BEGIN_SRC emacs-lisp
- (require 'window-numbering)
+ (require 'winum)
- (setq window-numbering-keymap (let ((map (make-sparse-keymap)))
- (define-key map "\M-m 0" 'select-window-0)
- ; ...
- (define-key map "\M-m 9" 'select-window-9)
- map))
- (window-numbering-mode)
+ (setq winum-keymap (let ((map (make-sparse-keymap)))
+ (define-key map "\M-m 0" 'select-window-0)
+ ; ...
+ (define-key map "\M-m 9" 'select-window-9)
+ map))
+ (winum-mode)
#+END_SRC
This way your bindings will not error when the mode is turned off.
@@ -76,39 +76,39 @@ This way your bindings will not error when the mode is turned off.
** Customize options
Several options are available through Emacs' =Customize= interface under
-=convenience= > =window-numbering=:
+=convenience= > =winum=:
-- =window-numbering-scope=
+- =winum-scope=
Frames affected by a number set. Choices are 'frame-local 'visible or 'global.
Default: 'global
-- =window-numbering-reverse-frame-list=
+- =winum-reverse-frame-list=
If t, order frames by reverse order of creation. Has effect only when
-`window-numbering-scope' is not 'frame-local.
+`winum-scope' is not 'frame-local.
Default: nil
-- =window-numbering-auto-assign-0-to-minibuffer=
+- =winum-auto-assign-0-to-minibuffer=
-If non-nil, =window-numbering-mode= assigns 0 to the minibuffer if active.
+If non-nil, =winum-mode= assigns 0 to the minibuffer if active.
Default: t
-- =window-numbering-before-hook=
+- =winum-before-hook=
-Hook called before =window-numbering-mode= starts assigning numbers. The list of
-windows to be numbered is passed as a parameter. Use =window-numbering--assign=
+Hook called before =winum-mode= starts assigning numbers. The list of
+windows to be numbered is passed as a parameter. Use =winum--assign=
to manually assign some of them a number. If you want to assign a number to just
-one buffer, use =window-numbering-assign-func= instead.
+one buffer, use =winum-assign-func= instead.
Default: nil
-- =window-numbering-assign-func=
+- =winum-assign-func=
-Function called for each window by =window-numbering-mode=. This is called
+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.
@@ -117,29 +117,29 @@ Default: nil
Example: always assign the calculator window the number 9:
#+BEGIN_SRC emacs-lisp
- (setq window-numbering-assign-func
+ (setq winum-assign-func
(lambda () (when (equal (buffer-name) "*Calculator*") 9)))
#+END_SRC
-- =window-numbering-mode-line-position=
+- =winum-mode-line-position=
-The position in the mode-line `window-numbering-mode' displays the number.
+The position in the mode-line `winum-mode' displays the number.
Default: 1
-- =window-numbering-window-number-max= 10
+- =winum-window-number-max= 10
Max number of windows that can be numbered.
Default: 10
-- =window-numbering-ignored-buffers=
+- =winum-ignored-buffers=
List of buffers to ignore when selecting window.
Default: '(" *which-key*")
-- face: =window-numbering-face=
+- face: =winum-face=
Face used for the number in the mode-line.
diff --git a/window-numbering.el b/window-numbering.el
index 48cb992..b649767 100644
--- a/window-numbering.el
+++ b/window-numbering.el
@@ -1,6 +1,5 @@
-;;; winum.el --- Window numbers for Emacs. An extended version of window-numbering.el, ideal for multi-screen.
+;;; window-numbering.el --- Compatibility code for window-numbering configurations
;;
-;; Copyright (c) 2006-2015 Nikolaj Schumacher
;; Copyright (c) 2016 Thomas Chauvot de Beauchêne
;;
;; This program is free software: you can redistribute it and/or modify
@@ -16,364 +15,31 @@
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see .
;;
-;; Author: Thomas de Beauchêne
-;; Version: 1.0
-;; Keywords: windows, window management, numbers
-;; URL: http://github.com/deb0ch/winum.el
-;; Created: 2016
-;; Compatibility: GNU Emacs 24.x
-;;
-;; This file is NOT part of GNU Emacs.
-;;
;;; Commentary:
;;
-;; Window numbers for Emacs: Navigate your windows and frames using numbers.
+;; Ensure compatibility with existing window-numbering configurations.
;;
-;; This package is an extended and actively maintained version of the
-;; https://github.com/nschum/window-numbering.el package by Nikolaj Schumacher,
-;; with some ideas and code taken from https://github.com/abo-abo/ace-window.
+;; This file exists for transitional purposes and will be deleted in the next
+;; updates.
;;
;;; Code:
-(eval-when-compile (require 'cl))
+(require 'winum)
-;; TODO rename to 'winum.el' and keep backward compatibility
+(defalias 'window-numbering-get-number-string 'winum-get-number-string)
+(defalias 'window-numbering-get-window-by-number 'winum-get-window-by-number)
+(defalias 'window-numbering-get-number 'winum-get-number)
+(defalias 'window-numbering-mode 'winum-mode)
-(defgroup window-numbering nil
- "Navigate and manage windows using numbers."
- :group 'convenience)
-
-;; TODO bug: when changed from frame-local to non-local in customize, need to
-;; force update or `window-numbering-get-number' fails and messes the
-;; modeline until next update.
-(defcustom window-numbering-scope 'global
- "Frames affected by a number set."
- :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-scope' is not 'frame-local."
- :group 'window-numbering
- :type 'boolean)
-
-(defcustom window-numbering-auto-assign-0-to-minibuffer t
- "If non-nil, `window-numbering-mode' assigns 0 to the minibuffer if active."
- :group 'window-numbering
- :type 'boolean)
-
-;; TODO see if useful
-(defcustom window-numbering-before-hook nil
- "Hook called before `window-numbering-mode' starts assigning numbers.
-The list of windows to be numbered is passed as a parameter.
-Use `window-numbering--assign' to manually assign some of them a number.
-If you want to assign a number to just one buffer, use
-`window-numbering-assign-func' instead."
- :group 'window-numbering
- :type 'hook)
-
-(defcustom window-numbering-assign-func nil
- "Function called for each window by `window-numbering-mode'.
-This is called before automatic assignment begins. The function should
-return a number to have it assigned to the current-window, nil otherwise."
- :group 'window-numbering
- :type 'function)
-
-(defcustom window-numbering-mode-line-position 1
- "The position in the mode-line `window-numbering-mode' displays the number."
- :group 'window-numbering
- :type 'integer)
-
-(defcustom window-numbering-window-number-max 10
- "Max number of windows that can be numbered."
- :group 'window-numbering
- :type 'integer)
-
-(defcustom window-numbering-ignored-buffers '(" *which-key*")
- "List of buffers to ignore when selecting window."
- :type '(repeat string))
-
-(defface window-numbering-face '()
- "Face used for the number in the mode-line."
- :group 'window-numbering)
-
-(defvar window-numbering-keymap (let ((map (make-sparse-keymap)))
- (define-key map "\M-0" 'select-window-0)
- (define-key map "\M-1" 'select-window-1)
- (define-key map "\M-2" 'select-window-2)
- (define-key map "\M-3" 'select-window-3)
- (define-key map "\M-4" 'select-window-4)
- (define-key map "\M-5" 'select-window-5)
- (define-key map "\M-6" 'select-window-6)
- (define-key map "\M-7" 'select-window-7)
- (define-key map "\M-8" 'select-window-8)
- (define-key map "\M-9" 'select-window-9)
- map)
- "Keymap used in by `window-numbering-mode'.")
-
-;;;###autoload
-(define-minor-mode window-numbering-mode
- "A minor mode that allows for managing windows based on window numbers."
- nil
- nil
- window-numbering-keymap
- :global t
- (if window-numbering-mode
- (window-numbering--init)
- (window-numbering--deinit)))
-
-;; define interactive functions window-numbering-select-window-[0..n]
-(dotimes (i (max 10 window-numbering-window-number-max))
- (eval `(defun ,(intern (format "select-window-%s" i)) (&optional arg)
- ,(format "Jump to window %d.\nIf prefix ARG is given, delete the\
- window instead of selecting it." i)
- (interactive "P")
- (select-window-by-number ,i arg))))
-
-;;;###autoload
-(defun select-window-by-number (i &optional arg)
- "Select window given number I by `window-numbering-mode'.
-If prefix ARG is given, delete the window instead of selecting it."
- (interactive "P")
- (let ((w (window-numbering-get-window-by-number i)))
- (if arg
- (delete-window w)
- (window-numbering--switch-to-window w))))
-
-;;;###autoload
-(defun window-numbering-get-window-by-number (i)
- "Return window numbered I if exists."
- (let ((windows (if (eq window-numbering-scope 'frame-local)
- (car (gethash (selected-frame)
- window-numbering--frames-table))
- window-numbering--window-vector))
- window)
- (if (and (>= i 0) (< i window-numbering-window-number-max)
- (setq window (aref windows i)))
- window
- (error "No window numbered %s" i))))
-
-;; TODO function to select window of unlimited input number:
-;; - prefix argument
-;; - read-from-minibuffer
-
-;;;###autoload
-(defun window-numbering-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 ((s (int-to-string (window-numbering-get-number window))))
- (propertize s 'face 'window-numbering-face)))
-
-;;;###autoload
-(defun window-numbering-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))))
- (if (eq window-numbering-scope 'frame-local)
- (gethash w (cdr (gethash (selected-frame)
- window-numbering--frames-table)))
- (gethash w window-numbering--numbers-table))))
-
-;; Internal variables
-
-(defvar window-numbering--max-frames 16
- "Maximum number of frames that can be numbered.")
-
-(defvar window-numbering--window-vector nil
- "Vector of windows indexed by their number.
-Used internally by window-numbering to get a window provided a number.")
-
-(defvar window-numbering--numbers-table nil
- "Hash table of numbers indexed by their window.
-Used internally by window-numbering to get a number provided a window.")
-
-(defvar window-numbering--frames-table nil
- "Table linking windows to numbers and numbers to windows for each frame.
-
-Used only when `window-numbering-scope' is 'frame-local to keep track of
-separate window numbers sets in every frame.
-
-It is a hash table using Emacs frames as keys and cons of the form
-\(`window-numbering--window-vector' . `window-numbering--numbers-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.
-
-Such a structure allows for per-frame bidirectional fast access.")
-
-(defvar window-numbering--remaining nil
- "A list of available window numbers.")
-
-(defun window-numbering--init ()
- "Initialize window-numbering-mode."
- (if (eq window-numbering-scope 'frame-local)
- (setq window-numbering--frames-table (make-hash-table :size window-numbering--max-frames))
- (setq window-numbering--numbers-table (make-hash-table :size window-numbering-window-number-max)))
- (window-numbering--install-mode-line)
- (add-hook 'minibuffer-setup-hook 'window-numbering--update)
- (add-hook 'window-configuration-change-hook 'window-numbering--update)
- (dolist (frame (frame-list))
- (select-frame frame)
- (window-numbering--update)))
-
-(defun window-numbering--deinit ()
- "Actions performed when turning off window-numbering-mode."
- (window-numbering--clear-mode-line)
- (remove-hook 'minibuffer-setup-hook 'window-numbering--update)
- (remove-hook 'window-configuration-change-hook 'window-numbering--update)
- (setq window-numbering--frames-table nil))
-
-(defun window-numbering--install-mode-line (&optional position)
- "Install the window number from `window-numbering-mode' to the mode-line.
-POSITION: position in the mode-line."
- (let ((mode-line (default-value 'mode-line-format))
- (res))
- (dotimes (i (min (or position window-numbering-mode-line-position 1)
- (length mode-line)))
- (push (car mode-line) res)
- (pop mode-line))
- (push '(:eval (window-numbering-get-number-string)) res)
- (while mode-line
- (push (car mode-line) res)
- (pop mode-line))
- (setq-default mode-line-format (nreverse res)))
- (force-mode-line-update t))
-
-(defun window-numbering--clear-mode-line ()
- "Remove the window number of `window-numbering-mode' from the mode-line."
- (let ((mode-line (default-value 'mode-line-format))
- (res))
- (while mode-line
- (let ((item (car mode-line)))
- (unless (equal item '(:eval (window-numbering-get-number-string)))
- (push item res)))
- (pop mode-line))
- (setq-default mode-line-format (nreverse res)))
- (force-mode-line-update t))
-
-(defun window-numbering--update ()
- "Update window numbers."
- (setq window-numbering--remaining (window-numbering--available-numbers))
- (if (eq window-numbering-scope 'frame-local)
- (puthash (selected-frame)
- (cons (make-vector window-numbering-window-number-max nil)
- (make-hash-table :size window-numbering-window-number-max))
- window-numbering--frames-table)
- (setq window-numbering--window-vector (make-vector window-numbering-window-number-max nil))
- (clrhash window-numbering--numbers-table))
- (when (and window-numbering-auto-assign-0-to-minibuffer
- (active-minibuffer-window))
- (window-numbering--assign (active-minibuffer-window) 0))
- (let ((windows (window-numbering--window-list)))
- (run-hook-with-args 'window-numbering-before-hook windows)
- (when window-numbering-assign-func
- (mapc (lambda (w)
- (with-selected-window w
- (with-current-buffer (window-buffer w)
- (let ((num (funcall window-numbering-assign-func)))
- (when num
- (window-numbering--assign w num))))))
- windows))
- (dolist (w windows)
- (window-numbering--assign w))))
-
-(defun window-numbering--assign (window &optional number)
- "Assign to window WINDOW the number NUMBER.
-If NUMBER is not specified, determine it first based on
-`window-numbering--remaining'.
-Returns the assigned number, or nil on error."
- (if number
- (if (aref (window-numbering--get-window-vector) number)
- (progn (message "Number %s assigned to two buffers (%s and %s)"
- number window (aref window-numbering--window-vector number))
- nil)
- (setf (aref (window-numbering--get-window-vector) number) window)
- (puthash window number (window-numbering--get-numbers-table))
- (setq window-numbering--remaining (delq number window-numbering--remaining))
- number)
- ;; else determine number and assign
- (when window-numbering--remaining
- (unless (gethash window (window-numbering--get-numbers-table))
- (let ((number (car window-numbering--remaining)))
- (window-numbering--assign window number))))))
-
-(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))
- (member (buffer-name (window-buffer w)) window-numbering-ignored-buffers))))
- (cl-case window-numbering-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-scope': %S" window-numbering-scope)))))
-
-(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--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
-`window-numbering-scope'."
- (if (eq window-numbering-scope 'frame-local)
- (car (gethash (selected-frame)
- window-numbering--frames-table))
- window-numbering--window-vector))
-
-(defun window-numbering--get-numbers-table ()
- "Return the numbers hashtable used to get a number given a window.
-This hashtable is not stored the same way depending on the value of
-`window-numbering-scope'"
- (if (eq window-numbering-scope 'frame-local)
- (cdr (gethash (selected-frame)
- window-numbering--frames-table))
- window-numbering--numbers-table))
-
-(defun window-numbering--available-numbers ()
- "Return a list of numbers from 1 to `window-numbering-window-number-max'.
-0 is the last element of the list."
- (let ((numbers))
- (dotimes (i window-numbering-window-number-max)
- (push (% (1+ i) window-numbering-window-number-max) numbers))
- (nreverse numbers)))
-
-(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))))
-
-(push "^No window numbered .$" debug-ignored-errors)
-(push "^Got a dead window .$" debug-ignored-errors)
-(push "^Invalid `window-numbering-scope': .$" debug-ignored-errors)
+(defvaralias 'window-numbering-mode 'winum-mode)
+(defvaralias 'window-numbering-keymap 'winum-keymap)
+(defvaralias 'window-numbering-ignored-buffers 'winum-ignored-buffers)
+(defvaralias 'window-numbering-mode-line-position 'winum-mode-line-position)
+(defvaralias 'window-numbering-before-hook 'winum-before-hook)
+(defvaralias 'window-numbering-scope 'winum-scope)
+(defvaralias 'window-numbering-auto-assign-0-to-minibuffer 'winum-auto-assign-0-to-minibuffer)
+(defvaralias 'window-numbering-assign-func 'winum-assign-func)
+(defvaralias 'window-numbering-window-number-max 'winum-window-number-max)
+(defvaralias 'window-numbering-reverse-frame-list 'winum-reverse-frame-list)
(provide 'window-numbering)
-
-;;; window-numbering.el ends here
diff --git a/winum.el b/winum.el
new file mode 100644
index 0000000..095da65
--- /dev/null
+++ b/winum.el
@@ -0,0 +1,379 @@
+;;; winum.el --- Window numbers for Emacs. An extended version of window-numbering.el, ideal for multi-screen.
+;;
+;; Copyright (c) 2006-2015 Nikolaj Schumacher
+;; Copyright (c) 2016 Thomas Chauvot de Beauchêne
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see .
+;;
+;; Author: Thomas de Beauchêne
+;; Version: 1.0
+;; Keywords: windows, window management, numbers
+;; URL: http://github.com/deb0ch/winum.el
+;; Created: 2016
+;; Compatibility: GNU Emacs 24.x
+;;
+;; This file is NOT part of GNU Emacs.
+;;
+;;; Commentary:
+;;
+;; 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 package by Nikolaj Schumacher,
+;; with some ideas and code taken from https://github.com/abo-abo/ace-window.
+;;
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+;; TODO make mode-line installation optional
+
+;; TODO bug: Error during redisplay: (eval (winum-get-number-string)) signaled
+;; (wrong-type-argument numberp nil) when opening a helm buffer.
+
+(defgroup winum nil
+ "Navigate and manage windows using numbers."
+ :group 'convenience)
+
+;; TODO bug: when changed from frame-local to non-local in customize, need to
+;; force update or `winum-get-number' fails and messes the
+;; modeline until next update.
+(defcustom winum-scope 'global
+ "Frames affected by a number set."
+ :group 'winum
+ :type '(choice
+ (const :tag "frame local" frame-local)
+ (const :tag "visible frames" visible)
+ (const :tag "global" global)))
+
+(defcustom winum-reverse-frame-list nil
+ "If t, order frames by reverse order of creation.
+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 if active."
+ :group 'winum
+ :type 'boolean)
+
+;; TODO see if useful
+(defcustom winum-before-hook nil
+ "Hook called before `winum-mode' starts assigning numbers.
+The list of windows to be numbered is passed as a parameter.
+Use `winum--assign' to manually assign some of them a number.
+If you want to assign a number to just one buffer, use
+`winum-assign-func' instead."
+ :group 'winum
+ :type 'hook)
+
+(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."
+ :group 'winum
+ :type 'function)
+
+(defcustom winum-mode-line-position 1
+ "The position in the mode-line `winum-mode' displays the number."
+ :group 'winum
+ :type 'integer)
+
+;; TODO other values note tested
+(defcustom winum-window-number-max 10
+ "Max number of windows that can be numbered."
+ :group 'winum
+ :type 'integer)
+
+(defcustom winum-ignored-buffers '(" *which-key*")
+ "List of buffers to ignore when selecting window."
+ :type '(repeat string))
+
+(defface winum-face '()
+ "Face used for the number in the mode-line."
+ :group 'winum)
+
+(defvar winum-keymap (let ((map (make-sparse-keymap)))
+ (define-key map "\M-0" 'select-window-0)
+ (define-key map "\M-1" 'select-window-1)
+ (define-key map "\M-2" 'select-window-2)
+ (define-key map "\M-3" 'select-window-3)
+ (define-key map "\M-4" 'select-window-4)
+ (define-key map "\M-5" 'select-window-5)
+ (define-key map "\M-6" 'select-window-6)
+ (define-key map "\M-7" 'select-window-7)
+ (define-key map "\M-8" 'select-window-8)
+ (define-key map "\M-9" 'select-window-9)
+ map)
+ "Keymap used in by `winum-mode'.")
+
+;;;###autoload
+(define-minor-mode winum-mode
+ "A minor mode that allows for managing windows based on window numbers."
+ nil
+ nil
+ winum-keymap
+ :global t
+ (if winum-mode
+ (winum--init)
+ (winum--deinit)))
+
+;; define interactive functions winum-select-window-[0..n]
+(dotimes (i winum-window-number-max)
+ (eval `(defun ,(intern (format "select-window-%s" i)) (&optional arg)
+ ,(format "Jump to window %d.\nIf prefix ARG is given, delete the\
+ window instead of selecting it." i)
+ (interactive "P")
+ (select-window-by-number ,i arg))))
+
+;;;###autoload
+(defun select-window-by-number (i &optional arg)
+ "Select window given number I by `winum-mode'.
+If prefix ARG is given, delete the window instead of selecting it."
+ (interactive "P")
+ (let ((w (winum-get-window-by-number i)))
+ (if arg
+ (delete-window w)
+ (winum--switch-to-window w))))
+
+;;;###autoload
+(defun winum-get-window-by-number (n)
+ "Return window numbered N if exists."
+ (let ((windows (if (eq winum-scope 'frame-local)
+ (car (gethash (selected-frame)
+ winum--frames-table))
+ winum--window-vector))
+ window)
+ (if (and (>= n 0) (< n winum-window-number-max)
+ (setq window (aref windows n)))
+ window
+ (error "No window numbered %s" n))))
+
+;;;###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 ((s (int-to-string (winum-get-number window))))
+ (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))))
+ (if (eq winum-scope 'frame-local)
+ (gethash w (cdr (gethash (selected-frame)
+ winum--frames-table)))
+ (gethash w winum--numbers-table))))
+
+;; Internal variables
+
+(defvar winum--max-frames 16
+ "Maximum number of frames that can be numbered.")
+
+(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--frames-table nil
+ "Table linking windows to numbers and numbers to windows for each frame.
+
+Used only when `winum-scope' is 'frame-local to keep track of
+separate window numbers 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')
+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.
+
+Such a structure allows for per-frame bidirectional fast access.")
+
+(defvar winum--remaining nil
+ "A list of available window numbers.")
+
+(defun winum--init ()
+ "Initialize winum-mode."
+ (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-number-max)))
+ (winum--install-mode-line)
+ (add-hook 'minibuffer-setup-hook 'winum--update)
+ (add-hook 'window-configuration-change-hook 'winum--update)
+ (dolist (frame (frame-list))
+ (select-frame frame)
+ (winum--update)))
+
+(defun winum--deinit ()
+ "Actions performed when turning off winum-mode."
+ (winum--clear-mode-line)
+ (remove-hook 'minibuffer-setup-hook 'winum--update)
+ (remove-hook 'window-configuration-change-hook 'winum--update)
+ (setq winum--frames-table nil))
+
+(defun winum--install-mode-line (&optional position)
+ "Install the window number from `winum-mode' to the mode-line.
+POSITION: position in the mode-line."
+ (let ((mode-line (default-value 'mode-line-format))
+ (res))
+ (dotimes (i (min (or position winum-mode-line-position 1)
+ (length mode-line)))
+ (push (car mode-line) res)
+ (pop mode-line))
+ (push '(:eval (winum-get-number-string)) res)
+ (while mode-line
+ (push (car mode-line) res)
+ (pop mode-line))
+ (setq-default mode-line-format (nreverse res)))
+ (force-mode-line-update t))
+
+(defun winum--clear-mode-line ()
+ "Remove the window number of `winum-mode' from the mode-line."
+ (let ((mode-line (default-value 'mode-line-format))
+ (res))
+ (while mode-line
+ (let ((item (car mode-line)))
+ (unless (equal item '(:eval (winum-get-number-string)))
+ (push item res)))
+ (pop mode-line))
+ (setq-default mode-line-format (nreverse res)))
+ (force-mode-line-update t))
+
+(defun winum--update ()
+ "Update window numbers."
+ (setq winum--remaining (winum--available-numbers))
+ (if (eq winum-scope 'frame-local)
+ (puthash (selected-frame)
+ (cons (make-vector winum-window-number-max nil)
+ (make-hash-table :size winum-window-number-max))
+ winum--frames-table)
+ (setq winum--window-vector (make-vector winum-window-number-max nil))
+ (clrhash winum--numbers-table))
+ (when (and winum-auto-assign-0-to-minibuffer
+ (active-minibuffer-window))
+ (winum--assign (active-minibuffer-window) 0))
+ (let ((windows (winum--window-list)))
+ (run-hook-with-args 'winum-before-hook windows)
+ (when winum-assign-func
+ (mapc (lambda (w)
+ (with-selected-window w
+ (with-current-buffer (window-buffer w)
+ (let ((num (funcall winum-assign-func)))
+ (when num
+ (winum--assign w num))))))
+ windows))
+ (dolist (w windows)
+ (winum--assign w))))
+
+(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
+ (if (aref (winum--get-window-vector) number)
+ (progn (message "Number %s assigned to two buffers (%s and %s)"
+ number window (aref winum--window-vector number))
+ 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--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))
+ (member (buffer-name (window-buffer w)) winum-ignored-buffers))))
+ (cl-case winum-scope
+ (global
+ (cl-mapcan 'winum--list-windows-in-frame
+ (if winum-reverse-frame-list
+ (frame-list)
+ (nreverse (frame-list)))))
+ (visible
+ (cl-mapcan 'winum--list-windows-in-frame
+ (if winum-reverse-frame-list
+ (visible-frame-list)
+ (nreverse (visible-frame-list)))))
+ (frame-local
+ (winum--list-windows-in-frame))
+ (t
+ (error "Invalid `winum-scope': %S" winum-scope)))))
+
+(defun winum--list-windows-in-frame (&optional f)
+ "List windows in frame F using natural Emacs ordering."
+ (window-list f 0 (frame-first-window f)))
+
+(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'."
+ (if (eq winum-scope 'frame-local)
+ (car (gethash (selected-frame)
+ winum--frames-table))
+ winum--window-vector))
+
+(defun winum--get-numbers-table ()
+ "Return the numbers hashtable used to get a number given a window.
+This hashtable is not stored the same way depending on the value of
+`winum-scope'"
+ (if (eq winum-scope 'frame-local)
+ (cdr (gethash (selected-frame)
+ winum--frames-table))
+ winum--numbers-table))
+
+(defun winum--available-numbers ()
+ "Return a list of numbers from 1 to `winum-window-number-max'.
+0 is the last element of the list."
+ (let ((numbers))
+ (dotimes (i winum-window-number-max)
+ (push (% (1+ i) winum-window-number-max) 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)))
+ (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))))
+
+(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