-
Notifications
You must be signed in to change notification settings - Fork 2
/
ctrlxo.el
145 lines (120 loc) · 4.7 KB
/
ctrlxo.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
;;; ctrlxo.el --- Switch to the most recently used window -*- lexical-binding: t -*-
;; Copyright (C) 2020 Andrii Kolomoiets
;; Author: Andrii Kolomoiets <[email protected]>
;; Keywords: frames
;; URL: https://github.com/muffinmad/emacs-ctrlxo
;; Package-Version: 1.2
;; Package-Requires: ((emacs "25.1"))
;; 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 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 <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Switch to the most recently used window.
;;
;; Use the `ctrlxo' function to start switching between windows on visible
;; frames in the recent usage ordering.
;; `ctrlxo' also activates transient keymap:
;; - o to switch to the next window
;; - O to switch to the previous window
;; - C-g to cancel switching and select window that was active on `ctrlxo'
;; invocation
;;
;; Use the `ctrlxo-current-frame' function to start switching between windows
;; on the current frame.
;;
;; Following example configuration will allow to switch between windows on
;; all visible frames with 'C-TAB' and between windows on the current frame
;; with 'C-x o':
;;
;; (require 'ctrlxo)
;; (global-set-key (kbd "C-<tab>") #'ctrlxo)
;; (global-set-key (kbd "C-x o") #'ctrlxo-current-frame)
;; (define-key ctrlxo-map (kbd "<tab>") #'ctrlxo-forward)
;; (define-key ctrlxo-map (kbd "<S-tab>") #'ctrlxo-backward)
;;; Code:
(require 'seq)
(defgroup ctrlxo nil
"Select most recently used window."
:group 'windows)
(defcustom ctrlxo-inhibit-usage-message nil
"Inhibit usage message on transient keymap activation."
:type 'boolean)
(defcustom ctrlxo-frames 'visible
"What frames to consider."
:type '(choice (const :tag "Current frame" nil)
(const :tag "All visible frames" visible)
(const :tag "All visible and iconified frames" 0)))
(defvar ctrlxo--window-list nil)
(defvar ctrlxo--selected-window nil)
(defun ctrlxo--make-window-list ()
"Build window list sorted by recent usage."
(setq ctrlxo--window-list (sort (window-list-1 nil nil ctrlxo-frames)
(lambda (w1 w2)
(> (window-use-time w1)
(window-use-time w2))))))
(defvar ctrlxo-map
(let ((map (make-sparse-keymap)))
(define-key map "o" #'ctrlxo-forward)
(define-key map "O" #'ctrlxo-backward)
(define-key map "\C-g" #'ctrlxo-cancel)
map)
"Transient keymap for switching to the next recent window.")
(defun ctrlxo--switch (num)
"Select next NUM most recent window."
(unless ctrlxo--window-list
(ctrlxo--make-window-list))
(let* ((idx (seq-position ctrlxo--window-list (selected-window)))
(idx (if idx
(mod (+ idx num) (length ctrlxo--window-list))
0)))
(select-window (elt ctrlxo--window-list idx) 'mark-for-redisplay)
(select-frame-set-input-focus (selected-frame) t)))
(defun ctrlxo--map-exit ()
"Record selected window."
(select-window (selected-window)))
(defun ctrlxo-forward ()
"Select next recent window."
(interactive)
(ctrlxo--switch 1))
(defun ctrlxo-backward ()
"Select previous recent window."
(interactive)
(ctrlxo--switch -1))
(defun ctrlxo-cancel ()
"Cancel window switching.
Select window that was active before invocation of `ctrlxo'."
(interactive)
(when ctrlxo--selected-window
(select-window ctrlxo--selected-window)
(select-frame-set-input-focus (selected-frame))))
;;;###autoload
(defun ctrlxo ()
"Build window list and switch to the most recently used window.
Activate transient keymap to switch to the next recently used window."
(interactive)
(setq ctrlxo--selected-window (selected-window))
(ctrlxo--make-window-list)
(ctrlxo-forward)
(unless ctrlxo-inhibit-usage-message
(message
(substitute-command-keys
"Next window: \\<ctrlxo-map>\\[ctrlxo-forward], previous window: \\<ctrlxo-map>\\[ctrlxo-backward], cancel switch: \\<ctrlxo-map>\\[ctrlxo-cancel].")))
(set-transient-map ctrlxo-map t #'ctrlxo--map-exit))
;;;###autoload
(defun ctrlxo-current-frame ()
"Switch between windows on the current frame."
(interactive)
(let (ctrlxo-frames)
(ctrlxo)))
(provide 'ctrlxo)
;;; ctrlxo.el ends here