diff --git a/.gitmodules b/.gitmodules index e6f981272bbf..39737fcf2c49 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "extensions/elixir-mode"] path = extensions/elixir-mode url = http://github.com/antifuchs/elixir-mode +[submodule "extensions/window-numbering"] + path = extensions/window-numbering + url = http://github.com/nschum/window-numbering.el diff --git a/extensions.el b/extensions.el index 3f94e13f07a2..362060e113d3 100644 --- a/extensions.el +++ b/extensions.el @@ -13,6 +13,7 @@ elixir-mode pylookup ;; pymacs + window-numbering )) ;; load extensions diff --git a/extensions/window-numbering/.dir-locals.el b/extensions/window-numbering/.dir-locals.el new file mode 100644 index 000000000000..a4fea8583326 --- /dev/null +++ b/extensions/window-numbering/.dir-locals.el @@ -0,0 +1,2 @@ +((nil . ((indent-tabs-mode . nil) + (fill-column . 80)))) diff --git a/extensions/window-numbering/.gitignore b/extensions/window-numbering/.gitignore new file mode 100644 index 000000000000..c531d9867f6c --- /dev/null +++ b/extensions/window-numbering/.gitignore @@ -0,0 +1 @@ +*.elc diff --git a/extensions/window-numbering/window-numbering-tests.el b/extensions/window-numbering/window-numbering-tests.el new file mode 100644 index 000000000000..b897a971b6f6 --- /dev/null +++ b/extensions/window-numbering/window-numbering-tests.el @@ -0,0 +1,35 @@ +(require 'elk-test) + +(deftest "window-numbering-assign" + (let ((window-numbering-windows (make-vector 10 nil)) + (window-numbering-numbers (make-hash-table :size 10)) + (window-numbering-left '(1 2 3))) + (assert-nonnil (window-numbering-assign 'xx 7)) + (assert-nil (window-numbering-assign 'yy 7)) + (assert-nonnil (window-numbering-assign 'zz 8)) + (assert-equal 8 (gethash 'zz window-numbering-numbers)) + (assert-equal 7 (gethash 'xx window-numbering-numbers)) + (assert-equal 'zz (aref window-numbering-windows 8)) + (assert-equal 'xx (aref window-numbering-windows 7)) + )) + +(deftest "window-numbering-assign auto" + (let ((window-numbering-windows (make-vector 10 nil)) + (window-numbering-numbers (make-hash-table :size 10)) + (window-numbering-left '(1 2 3 4))) + (assert-eq 1 (window-numbering-assign 'xx)) + (assert-nonnil (window-numbering-assign 'yy 3)) + (assert-eq 2 (window-numbering-assign 'zz)) + (assert-eq 4 (window-numbering-assign 'aa)) +)) + + +(deftest "window-numbering-calculate-left" + (assert-equal '(6) (window-numbering-calculate-left + [t t t t t nil t t t t])) + (assert-equal '(1 2 3) (window-numbering-calculate-left + [nil nil nil t t t t t t t])) + (assert-equal '(1 2 3 4 5 6 7 8 9 0) + (window-numbering-calculate-left + [nil nil nil nil nil nil nil nil nil nil])) + ) diff --git a/extensions/window-numbering/window-numbering.el b/extensions/window-numbering/window-numbering.el new file mode 100644 index 000000000000..b1344e393460 --- /dev/null +++ b/extensions/window-numbering/window-numbering.el @@ -0,0 +1,243 @@ +;;; window-numbering --- Numbered window shortcuts +;; +;; Copyright (C) 2006-2007, 2013 Nikolaj Schumacher +;; +;; Author: Nikolaj Schumacher +;; Version: 1.1.1 +;; Keywords: faces, matching +;; URL: http://nschum.de/src/emacs/window-numbering-mode/ +;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x, GNU Emacs 24.x +;; +;; This file is NOT part of GNU Emacs. +;; +;; 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 2 +;; 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 . +;; +;;; Commentary: +;; +;; Enable window-numbering-mode and use M-1 through M-0 to navigate. +;; +;; If you want to affect the numbers, use window-numbering-before-hook or +;; window-numbering-assign-func. +;; For instance, to always assign the calculator window the number 9, add the +;; following to your .emacs: +;; +;; (setq window-numbering-assign-func +;; (lambda () (when (equal (buffer-name) "*Calculator*") 9))) +;; +;;; Changes Log: +;; +;; Fix numbering in terminal mode with menu bar visible. +;; Add face for window number. (thanks to Chen Bin) +;; +;; 2008-04-11 (1.1.1) +;; Added possibility to delete window with prefix arg. +;; Cleaned up code and migrated to `defcustom'. +;; +;; 2007-02-18 (1.1) +;; Added window-numbering-before-hook, window-numbering-assign-func. +;; +;;; Code: + +(eval-when-compile (require 'cl)) + +(push "^No window numbered .$" debug-ignored-errors) + +(defgroup window-numbering nil + "Numbered window shortcuts" + :group 'convenience) + +(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 '(choice (const :tag "Off" nil) + (const :tag "On" t))) + +(defcustom window-numbering-before-hook nil + "*Hook called before `window-numbering-mode' starts assigning numbers. +The number of windows that will 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) + +(defconst window-numbering-mode-line-position 1 + "The position in the mode-line `window-numbering-mode' displays the number.") + +(defface window-numbering-face '() + "Face used for the number in the mode-line." + :group 'window-numbering) + +(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 ((windows (car (gethash (selected-frame) window-numbering-table))) + window) + (if (and (>= i 0) (< i 10) + (setq window (aref windows i))) + (if arg + (delete-window window) + (select-window window)) + (error "No window numbered %s" i)))) + +;; define interactive functions for keymap +(dotimes (i 10) + (eval `(defun ,(intern (format "select-window-%s" i)) (&optional arg) + ,(format "Select the window with number %i." i) + (interactive "P") + (select-window-by-number ,i arg)))) + +(defvar window-numbering-table nil + "table -> (window vector . number table)") + +(defun window-numbering-calculate-left (windows) + (let ((i 9) left) + (while (>= i 0) + (let ((window (aref windows i))) + (unless window + (push (% (1+ i) 10) left))) + (decf i)) + left)) + +(defvar window-numbering-windows nil + "A vector listing the window for each number.") +(defvar window-numbering-numbers + "A hash map containing each window's number.") +(defvar window-numbering-left + "A list of unused window numbers.") + +(defun window-numbering-assign (window &optional number) + (if number + (if (aref window-numbering-windows number) + (progn (message "Number %s assigned to two buffers (%s and %s)" + number window (aref window-numbering-windows number)) + nil) + (setf (aref window-numbering-windows number) window) + (puthash window number window-numbering-numbers) + (setq window-numbering-left (delq number window-numbering-left)) + t) + ;; else default adding + (when window-numbering-left + (unless (gethash window window-numbering-numbers) + (let ((number (car window-numbering-left))) + (window-numbering-assign window number) + number))))) + +(defun window-numbering-update () + "Update the window numbering for the current frame. +Optional parameter PREASSIGNED-WINDOWS is a hashmap already mapping some +windows to numbers." + (setq window-numbering-windows (make-vector 10 nil) + window-numbering-numbers (make-hash-table :size 10) + window-numbering-left + (window-numbering-calculate-left window-numbering-windows)) + (puthash (selected-frame) + (cons window-numbering-windows window-numbering-numbers) + window-numbering-table) + (when (and window-numbering-auto-assign-0-to-minibuffer + (active-minibuffer-window)) + (window-numbering-assign (active-minibuffer-window) 0)) + (let ((windows (window-list nil 0 (frame-first-window)))) + (run-hook-with-args 'window-numbering-before-hook windows) + (when window-numbering-assign-func + (mapc `(lambda (window) + (with-selected-window window + (with-current-buffer (window-buffer window) + (let ((num (funcall ,window-numbering-assign-func))) + (when num + (window-numbering-assign window num)))))) + windows)) + (dolist (window windows) + (window-numbering-assign window)))) + +(defun window-numbering-get-number-string (&optional window) + (let ((s (concat " |" (int-to-string (window-numbering-get-number window)) "| "))) + (propertize s 'face 'window-numbering-face))) + +(defun window-numbering-get-number (&optional window) + (gethash (or window (selected-window)) + (cdr (gethash (selected-frame) window-numbering-table)))) + +(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 assigns a number to each window." + nil nil window-numbering-keymap :global t + (if window-numbering-mode + (unless window-numbering-table + (save-excursion + (setq window-numbering-table (make-hash-table :size 16)) + (window-numbering-install-mode-line) + (add-hook 'window-configuration-change-hook + 'window-numbering-update) + (dolist (frame (frame-list)) + (select-frame frame) + (window-numbering-update)))) + (window-numbering-clear-mode-line) + (remove-hook 'window-configuration-change-hook + 'window-numbering-update) + (setq window-numbering-table nil))) + +(defun window-numbering-install-mode-line (&optional position) + "Install the window number from `window-numbering-mode' to the mode-line." + (let ((mode-line (default-value 'mode-line-format)) + (res)) + (dotimes (i (min (or position window-numbering-mode-line-position) + (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)) + +(provide 'window-numbering) + +;;; window-numbering.el ends here diff --git a/init-extension/init-window-numbering.el b/init-extension/init-window-numbering.el new file mode 100644 index 000000000000..5f8c06506206 --- /dev/null +++ b/init-extension/init-window-numbering.el @@ -0,0 +1,2 @@ +(require 'window-numbering) +(window-numbering-mode 1) diff --git a/my-keybindings.el b/my-keybindings.el index f05b996862f6..759b5d1d2c4a 100644 --- a/my-keybindings.el +++ b/my-keybindings.el @@ -1,5 +1,4 @@ - -;; First unset shortcuts which shadow evil leader ============================= +;; Unset shortcuts which shadow evil leader ============================= (eval-after-load "compile" (define-key compilation-mode-map (kbd "SPC") nil)) @@ -27,6 +26,17 @@ (evil-leader/set-key ":" 'smex) ;; ace-jump ------------------------------------------------------------------- (evil-leader/set-key "SPC" 'ace-jump-mode) +;; switch window by number ---------------------------------------------------- +(evil-leader/set-key "0" 'select-window-0) +(evil-leader/set-key "1" 'select-window-1) +(evil-leader/set-key "2" 'select-window-2) +(evil-leader/set-key "3" 'select-window-3) +(evil-leader/set-key "4" 'select-window-4) +(evil-leader/set-key "5" 'select-window-5) +(evil-leader/set-key "6" 'select-window-6) +(evil-leader/set-key "7" 'select-window-7) +(evil-leader/set-key "8" 'select-window-8) +(evil-leader/set-key "9" 'select-window-9) ;; applications --------------------------------------------------------------- (evil-leader/set-key "ae" 'erc-start-or-switch) (evil-leader/set-key "am" 'mu4e-up-to-date-status)