Skip to content

Commit fc15a32

Browse files
committed
Add switch window mode.
1 parent d06634a commit fc15a32

File tree

3 files changed

+269
-7
lines changed

3 files changed

+269
-7
lines changed

init.el

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
;--------------------------------------------------------------------
2-
; .emacs by Carlos García ;
2+
; .emacs by Carlos García Cordero ;
33
;--------------------------------------------------------------------
44

55
;;--------------------- Global Config -------------------------------
@@ -35,14 +35,8 @@
3535
;;--------------------- Custom Emacs Config -------------------------
3636
(custom-set-variables
3737
;; custom-set-variables was added by Custom.
38-
;; If you edit it by hand, you could mess it up, so be careful.
39-
;; Your init file should contain only one such instance.
40-
;; If there is more than one, they won't work right.
4138
)
4239

4340
(custom-set-faces
4441
;; custom-set-faces was added by Custom.
45-
;; If you edit it by hand, you could mess it up, so be careful.
46-
;; Your init file should contain only one such instance.
47-
;; If there is more than one, they won't work right.
4842
'(org-hide ((((background light)) (:foreground "DarkSlateGray")) (((background dark)) (:foreground "DarkSlateGray")))))

plugins.el

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
;;---------------------- PATH ---------------------------
22
(add-to-list 'load-path "~/.emacs.d/plugins/")
33

4+
;;------------------- Switch Window ----------------------
5+
(require 'switch-window)
6+
(global-set-key (kbd "C-x o") 'switch-window)
7+
48
;;-------------------- Workgroups ------------------------
59
(require 'workgroups2)
610
;; Prefix key

plugins/switch-window.el

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
;;; switch-window.el --- A *visual* way to choose a window to switch to
2+
;;
3+
;; Copyright (C) 2010 Dimitri Fontaine
4+
;;
5+
;; Author: Dimitri Fontaine <dim@tapoueh.org>
6+
;; URL: http://tapoueh.org/emacs/switch-window.html
7+
;; Version: 0.11
8+
;; Created: 2010-04-30
9+
;; Keywords: window navigation
10+
;; Licence: WTFPL, grab your copy here: http://sam.zoy.org/wtfpl/
11+
;;
12+
;; This file is NOT part of GNU Emacs.
13+
;;
14+
;; Install:
15+
;; (require 'switch-window)
16+
;;
17+
;; Rebind your C-x o key:
18+
;; (global-set-key (kbd "C-x o") 'switch-window)
19+
;;
20+
;; Changelog
21+
;;
22+
;; 0.11 - 2013-09-14
23+
;;
24+
;; - restore point to end-of-buffer for windows where it was the case after
25+
;; switching, fixing an anoying bug.
26+
;;
27+
;; 0.10 - 2011-06-19
28+
;;
29+
;; - implement M-x delete-other-window (thanks developernotes on github)
30+
;;
31+
;; 0.9 - 2010-11-11 - emacs22 called, it wants some support
32+
;;
33+
;; - implement a propertize based hack to support emacs22
34+
;;
35+
;; 0.8 - 2010-09-13 - 999
36+
;;
37+
;; - Suport more than 9 windows (with a single key to type)
38+
;; - Use quail-keyboard-layout to choose single key labels for windows
39+
;;
40+
;; 0.7 - 2010-08-23 - window-dedicated-p
41+
;;
42+
;; - temporarily unset the window dedicated flag for displaying the
43+
;; numbers, patch from René Kyllingstad <Rene@Kyllingstad.com>
44+
;; - fix timeout and RET handling wrt to not changing window selection
45+
;;
46+
;; 0.6 - 2010-08-12 - *Minibuf-1*
47+
;;
48+
;; - add support for selecting the minibuffer when it's active
49+
;; - some try at a better horizontal centering
50+
;; - assorted cleanup
51+
;;
52+
;; 0.5 - 2010-08-08 - Polishing
53+
;;
54+
;; - dim:switch-window-increase is now a maximum value
55+
;;
56+
57+
;; We use loop and subseq
58+
(require 'cl)
59+
(require 'quail)
60+
61+
(defgroup switch-window nil "switch-window customization group"
62+
:group 'convenience)
63+
64+
(defcustom switch-window-increase 12
65+
"How much to increase text size in the window numbering, maximum"
66+
:type 'integer
67+
:group 'switch-window)
68+
69+
(defcustom switch-window-timeout 5
70+
"After this many seconds, cancel the window switching"
71+
:type 'integer
72+
:group 'switch-window)
73+
74+
(defcustom switch-window-threshold 2
75+
"Only active switch-window after this many windows open"
76+
:type 'integer
77+
:group 'switch-window)
78+
79+
80+
(defcustom switch-window-relative nil
81+
"Control the ordering of windows, when true this depends on current-window"
82+
:type 'boolean
83+
:group 'switch-window)
84+
85+
(defcustom switch-window-shortcut-style 'quail
86+
"Use either keyboard layout or alphabet shortcut style"
87+
:type '(choice (const :tag "Alphabet" 'alphabet)
88+
(const :tag "Keyboard Layout" 'quail)
89+
(const :tag "Qwerty Homekeys Layout" 'qwerty))
90+
:group 'switch-window)
91+
92+
(defcustom switch-window-qwerty-shortcuts
93+
'("a" "s" "d" "f" "j" "k" "l" ";" "w" "e" "i" "o")
94+
"The list of characters used when switch-window-shortcut-style is 'qwerty'"
95+
:type 'list
96+
:group 'switch-window)
97+
98+
(defun switch-window-list-keyboard-keys ()
99+
"Return a list of current keyboard layout keys"
100+
(loop with layout = (split-string quail-keyboard-layout "")
101+
for row from 1 to 4
102+
nconc (loop for col from 1 to 10
103+
collect (nth (+ 1 (* 2 col) (* 30 row)) layout))))
104+
105+
(defun switch-window-list-keys ()
106+
"Return a list of keys to use depending on `switch-window-shortcut-style'"
107+
(cond ((eq switch-window-shortcut-style 'qwerty)
108+
switch-window-qwerty-shortcuts)
109+
((eq switch-window-shortcut-style 'alphabet)
110+
(loop for i from 0 to 25
111+
collect (byte-to-string (+ (string-to-char "a") i))))
112+
(t (switch-window-list-keyboard-keys))))
113+
114+
(defun switch-window-enumerate ()
115+
"Return a list of one-letter strings to label current windows"
116+
(loop for w being the windows for x in (switch-window-list-keys) collect x))
117+
118+
(defun switch-window-label (num)
119+
"Return the label to use for a given window number"
120+
(nth (- num 1) (switch-window-enumerate)))
121+
122+
(defun switch-window-list (&optional from-current-window)
123+
"list windows for current frame, starting at top left unless
124+
from-current-window is not nil"
125+
(if (or from-current-window switch-window-relative)
126+
(window-list nil nil)
127+
(window-list nil nil (frame-first-window))))
128+
129+
(defun switch-window-display-number (win num)
130+
"prepare a temp buffer to diplay in the window while choosing"
131+
(let* ((label (switch-window-label num))
132+
(buf (get-buffer-create
133+
(format " *%s: %s*" label (buffer-name (window-buffer win))))))
134+
(with-current-buffer buf
135+
(let* ((w (window-width win))
136+
(h (window-body-height win))
137+
(increased-lines (/ (float h) switch-window-increase))
138+
(scale (if (> increased-lines 1) switch-window-increase h))
139+
(lines-before (/ increased-lines 2))
140+
(margin-left (/ w h) ))
141+
;; increase to maximum switch-window-increase
142+
(when (fboundp 'text-scale-increase)
143+
(text-scale-increase scale))
144+
;; make it so that the huge number appears centered
145+
(dotimes (i lines-before) (insert "\n"))
146+
(dotimes (i margin-left) (insert " "))
147+
;; insert the label, with a hack to support ancient emacs
148+
(if (fboundp 'text-scale-increase)
149+
(insert label)
150+
(insert (propertize label 'face
151+
(list :height (* (* h switch-window-increase)
152+
(if (> w h) 2 1))))))))
153+
(set-window-buffer win buf)
154+
buf))
155+
156+
(defun apply-to-window-index (action n message-format)
157+
"apply action to given window index, target is the place of the
158+
window in (switch-window-list)"
159+
(loop for c from 1
160+
for win in (switch-window-list)
161+
until (= c n)
162+
finally (funcall action win))
163+
;; be verbose about it
164+
(unless (minibuffer-window-active-p (selected-window))
165+
(message message-format
166+
(substring-no-properties
167+
(buffer-name (window-buffer (selected-window)))))))
168+
169+
(defun switch-window-list-eobp ()
170+
"Return a list of all the windows where `eobp' is currently
171+
true so that we can restore that important property (think
172+
auto scrolling) after switching."
173+
(loop for win in (switch-window-list)
174+
when (with-current-buffer (window-buffer win) (eobp))
175+
collect win))
176+
177+
(defun switch-window-restore-eobp (eobp-window-list)
178+
"For each window in EOBP-WINDOW-LIST move the point to end of buffer."
179+
(loop for win in eobp-window-list
180+
do (with-current-buffer (window-buffer win) (end-of-buffer))))
181+
182+
;;;###autoload
183+
(defun delete-other-window ()
184+
"Display an overlay in each window showing a unique key, then
185+
ask user which window to delete"
186+
(interactive)
187+
(if (> (length (window-list)) 1)
188+
(progn
189+
(let ((index (prompt-for-selected-window "Delete window: ")))
190+
(apply-to-window-index 'delete-window index "")))))
191+
192+
;;;###autoload
193+
(defun switch-window ()
194+
"Display an overlay in each window showing a unique key, then
195+
ask user for the window where move to"
196+
(interactive)
197+
(if (<= (length (window-list)) switch-window-threshold)
198+
(call-interactively 'other-window)
199+
(progn
200+
(let ((index (prompt-for-selected-window "Move to window: "))
201+
(eobps (switch-window-list-eobp)))
202+
(apply-to-window-index 'select-window index "Moved to %S")
203+
(switch-window-restore-eobp eobps)))))
204+
205+
(defun prompt-for-selected-window (prompt-message)
206+
"Display an overlay in each window showing a unique key, then
207+
ask user for the window to select"
208+
(let ((config (current-window-configuration))
209+
(num 1)
210+
(minibuffer-num nil)
211+
(eobps (switch-window-list-eobp))
212+
key buffers
213+
window-points
214+
dedicated-windows)
215+
216+
;; arrange so that C-g will get back to previous window configuration
217+
(unwind-protect
218+
(progn
219+
;; display big numbers to ease window selection
220+
(dolist (win (switch-window-list))
221+
(push (cons win (window-point win)) window-points)
222+
(when (window-dedicated-p win)
223+
(push (cons win (window-dedicated-p win)) dedicated-windows)
224+
(set-window-dedicated-p win nil))
225+
(if (minibuffer-window-active-p win)
226+
(setq minibuffer-num num)
227+
(push (switch-window-display-number win num) buffers))
228+
(setq num (1+ num)))
229+
230+
(while (not key)
231+
(let ((input
232+
(event-basic-type
233+
(read-event
234+
(if minibuffer-num
235+
(format "Move to window [minibuffer is %s]: "
236+
(switch-window-label minibuffer-num))
237+
prompt-message)
238+
nil switch-window-timeout))))
239+
240+
(if (or (null input) (eq input 'return))
241+
(progn
242+
(switch-window-restore-eobp eobps)
243+
(keyboard-quit)) ; timeout or RET
244+
(unless (symbolp input)
245+
(let* ((wchars (mapcar 'string-to-char
246+
(switch-window-enumerate)))
247+
(pos (position input wchars)))
248+
(if pos
249+
(setq key (1+ pos))
250+
(progn
251+
(switch-window-restore-eobp eobps)
252+
(keyboard-quit)))))))))
253+
254+
;; get those huge numbers away
255+
(mapc 'kill-buffer buffers)
256+
(set-window-configuration config)
257+
(dolist (w window-points)
258+
(set-window-point (car w) (cdr w)))
259+
(dolist (w dedicated-windows)
260+
(set-window-dedicated-p (car w) (cdr w))))
261+
key))
262+
263+
(provide 'switch-window)
264+
;;; switch-window.el ends here

0 commit comments

Comments
 (0)