From bd4acd1f43809bf39f72515617240d8f05bad833 Mon Sep 17 00:00:00 2001 From: Nikolaj Schumacher Date: Fri, 11 Apr 2008 21:24:04 +0200 Subject: [PATCH] Importing archived version. --- window-numbering.el | 189 ++++++++++++++++++++++++++++---------------- 1 file changed, 121 insertions(+), 68 deletions(-) diff --git a/window-numbering.el b/window-numbering.el index 3a0cb7c..5c77825 100644 --- a/window-numbering.el +++ b/window-numbering.el @@ -1,6 +1,6 @@ ;;; window-numbering --- Emacs window shortcuts -;; Copyright (C) 2006 Nikolaj Schumacher +;; Copyright (C) 2006-2007 Nikolaj Schumacher ;;; License @@ -19,25 +19,23 @@ ;;; Usage -;; Use `deftest' to define a test and `run-elk-test' to run it. -;; Create test bundles with `defsuite' or `build-suite'. -;; Verify your code with `assert-equal', `assert-eq', `assert-eql', -;; `assert-nonnil', `assert-t', `assert-nil' and `assert-error' -;; to verify your code. +;; 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))) -;;; Version 0.9 -(defvar window-numbering-table nil - "table -> (window vector . number table)") +;;; Changes -(defun select-window-by-number (i) - (interactive) - (let ((windows (car (gethash (selected-frame) window-numbering-table))) - window) - (if (and (>= i 0) (< i 10) - (setq window (aref windows i))) - (select-window window) - (error "No window numbered %s" i)))) +;; 2007-02-18 (1.1) +;; added window-numbering-before-hook, window-numbering-assign-func + +;;; Configuration (defvar window-numbering-keymap (let ((map (make-sparse-keymap))) @@ -57,31 +55,96 @@ (defvar window-numbering-auto-assign-0-to-minibuffer t "If non-nil, `window-numbering-mode' assigns 0 to the minibuffer if active.") -(defun window-numbering-enumerate () -;; (let ((table (gethash (selected-frame) window-numbering-table))) - ;; (unless table +(defconst window-numbering-mode-line-position 1 + "The position in the mode-line `window-numbering-mode' displays the number.") - (let ((table (cons (make-vector 10 nil) (make-hash-table :size 10)))) - (puthash (selected-frame) table window-numbering-table) - (let ((window-numbering-windows (car table)) - (window-numbering-numbers (cdr table)) - (minibuffer (when window-numbering-auto-assign-0-to-minibuffer - (active-minibuffer-window)))) - (window-numbering-walk (car (window-tree)) 1 (if minibuffer 9 10)) - (when minibuffer - (set (aref window-numbering-windows 0) minibuffer) - (puthash minibuffer 0 window-numbering-numbers))) - window-numbering-windows)) +(defvar 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.") -;; (setq window-numbering-windows (make-vector 10 nil)) -;; (setq window-numbering-numbers (make-hash-table :size 10)) -;; (let* ((minibuffer (when window-numbering-auto-assign-0-to-minibuffer -;; (active-minibuffer-window)))) -;; (window-numbering-walk (car (window-tree)) 1 (if minibuffer 9 10)) -;; (when minibuffer -;; (setf (aref window-numbering-windows 0) minibuffer) -;; (puthash minibuffer 0 window-numbering-numbers))) -;; window-numbering-windows) +(defvar 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.") + +;;; Code + +(require 'cl) + +(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)) + + +(defun window-numbering-assign (window &optional number) + (assert (boundp 'window-numbering-windows)) + (assert (boundp 'window-numbering-numbers)) + (assert (boundp 'window-numbering-left)) + (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 select-window-by-number (i) + "Select window given number I by `window-numbering-mode'." + (interactive) + (let ((windows (car (gethash (selected-frame) window-numbering-table))) + window) + (if (and (>= i 0) (< i 10) + (setq window (aref windows i))) + (select-window window) + (error "No window numbered %s" i)))) + +(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." + (let* ((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 (window-at 0 0)))) + (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 select-window-0 () (interactive) @@ -114,50 +177,40 @@ (interactive) (select-window-by-number 9)) -(defun window-numbering-walk (tree i max-window) - (if (windowp tree) - (when (<= i max-window) - (let ((pos (if (= i 10) 0 i))) - (set (aref window-numbering-windows pos) tree) - (puthash tree pos window-numbering-numbers)) - (incf i)) - (let ((windows (if (windowp tree) `(,tree) (cddr tree)))) - (dolist (window windows) - (setq i (window-numbering-walk window i max-window))))) - i) +(defun window-numbering-get-number-string (&optional window) + (int-to-string (window-numbering-get-number window))) -(defconst window-numbering-mode-line-position 1 - "The position in the mode-line `window-numbering-mode' displays the number.") -;; (window-numbering-get-number) (defun window-numbering-get-number (&optional window) - (int-to-string - (gethash (or window (selected-window)) window-numbering-numbers))) + (gethash (or window (selected-window)) + (cdr (gethash (selected-frame) window-numbering-table)))) (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 - (save-excursion - (setq window-numbering-table (make-hash-table :size 16)) - (window-numbering-install-mode-line) - (add-hook 'window-configuration-change-hook - 'window-numbering-enumerate) - (dolist (frame (frame-list)) - (select-frame frame) - (window-numbering-enumerate))) + (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-enumerate) + '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)) res) + (push '(:eval (window-numbering-get-number-string)) res) (while mode-line (push (car mode-line) res) (pop mode-line)) @@ -165,12 +218,12 @@ (force-mode-line-update t)) (defun window-numbering-clear-mode-line () - "Remove the dot installed by `test-runner-install-dot' from the 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))) + (unless (equal item '(:eval (window-numbering-get-number-string))) (push item res))) (pop mode-line)) (setq-default mode-line-format (nreverse res)))