-
Notifications
You must be signed in to change notification settings - Fork 2
/
ne2wm-utils.el
252 lines (202 loc) · 7.93 KB
/
ne2wm-utils.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
;;; ne2wm-utils.el --- utility functions
;; Copyright (C) 2012 Takafumi Arakaki
;; Author: Takafumi Arakaki
;; Keywords: tools, window manager
;; 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 <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(eval-when-compile (require 'cl))
(require 'e2wm)
(require 'e2wm-vcs)
(require 'ne2wm-pst-magit+)
(require 'ne2wm-pst-monky+)
;;; Commands
(defun ne2wm:toggle-sub (&optional move-buffer)
"Toggle on/off of e2wm sub window.
If the universal prefix argument is given, the current buffer
will be shown in the next window."
(interactive "P")
(let* ((prev-buf (current-buffer))
(wm (e2wm:pst-get-wm))
;; When *not* in sub, do not specify NEXT-WINDOW so that
;; `e2wm:pst-window-toggle' let me stay in the current
;; window.
(next-window
(when (eq (wlf:get-window-name wm (selected-window)) 'sub)
(e2wm:$pst-main (e2wm:pst-get-instance)))))
(e2wm:aif (e2wm:pst-window-toggle 'sub t next-window)
(when move-buffer
(wlf:set-buffer wm it prev-buf)))))
(defun ne2wm:hide-sub ()
"Hide e2wm sub window."
(interactive)
(let ((wm (e2wm:pst-get-wm)))
(when (eq (wlf:get-window-name wm (selected-window)) 'sub)
(wlf:select wm (e2wm:$pst-main (e2wm:pst-get-instance))))
(wlf:hide wm 'sub)))
(defun ne2wm:select-sub ()
"Focus e2wm sub window."
(interactive)
(let ((wm (e2wm:pst-get-wm)))
(wlf:select wm 'sub)))
(defun ne2wm:popup-sub-tail (buffer)
"Popup BUFFER in sub window and `recenter' at the bottom of the window."
(e2wm:pst-buffer-set 'sub buffer t t)
(set-window-point (selected-window) (point-max))
(recenter -2))
(defun ne2wm:popup-messages ()
"Display *Messages* buffer in sub window."
(interactive)
(ne2wm:popup-sub-tail (get-buffer "*Messages*")))
(defun ne2wm:pst-update-windows-command ()
"Reset window configurations.
This is an extend version of `e2wm:pst-update-windows-command'.
Additional feature:
* Move buffer shown in the current window to the top of the history list.
"
(interactive)
(let* ((wm (e2wm:pst-get-wm))
(curwname (wlf:get-window-name wm (selected-window))))
(e2wm:history-add (current-buffer))
(e2wm:pst-buffer-set curwname (current-buffer)) ; forcefully track buffer
(e2wm:pst-update-windows-command)
(e2wm:pst-window-select curwname))) ; avoid changing window focus
(defun ne2wm:open-vcs ()
"Open VCS perspective depending on the VCS used in the project.
Currently, only Magit (Git) and Monky (Mercurial) are supported."
(interactive)
(let ((dir default-directory))
(cond
;; magit
((and dir (magit-get-top-dir dir))
(ne2wm:dp-magit+))
;; monky
((condition-case err
(monky-get-root-dir)
(error nil))
(ne2wm:dp-monky+))
;; FIXME: support SVN
;; otherwise
(t
(message "Not in VCS")))))
(defun ne2wm:win-ring-get (&optional frame):
(e2wm:frame-param-get 'ne2wm:win-ring frame))
(defun ne2wm:win-ring-set (val &optional frame):
(e2wm:frame-param-set 'ne2wm:win-ring val frame))
(defun ne2wm:rorate-list-right (seq offset)
(if (<= offset 0)
seq
(ne2wm:rorate-list-right
(append (last seq) (nbutlast seq)) (1- offset))))
(defun ne2wm:rorate-list-left (seq offset)
(if (<= offset 0)
seq
(ne2wm:rorate-list-left (append (cdr seq) (list (car seq))) (1- offset))))
(defun ne2wm:rorate-list (seq &optional offset)
"[internal]"
(setq offset (or offset 1))
(if (<= offset 0)
(ne2wm:rorate-list-left seq (- offset))
(ne2wm:rorate-list-right seq offset)))
(defun ne2wm:win-ring-rotate ()
(interactive) ; FIXME: use prefix arg
(loop with ring = (ne2wm:win-ring-get)
for wname in ring
for buf in (ne2wm:rorate-list (mapcar #'e2wm:pst-buffer-get ring))
do (e2wm:pst-buffer-set wname buf))
(e2wm:pst-update-windows))
(defun ne2wm:find-next-in-seq (seq item &optional offset reverse)
"[internal] Return OFFSET-next position from ITEM in SEQ.
If OFFSET is omitted or nil, it is assumed to be 1.
If REVERSE is non-nil, find OFFSET-previous position instead.
Examples:
(ne2wm:find-next-in-seq '(a b c d) 'b) ; => c
(ne2wm:find-next-in-seq '(a b c d) 'd) ; => a
(ne2wm:find-next-in-seq '(a b c d) 'b 2) ; => d
(ne2wm:find-next-in-seq '(a b c d) 'b -1) ; => a
"
(nth (loop for current in seq
for i from 0
when (eql current item)
return (mod (funcall (if reverse #'- #'+) i (or offset 1))
(length seq)))
seq))
(defun ne2wm:win-ring-push (arg)
"Switch the current window with the next window.
If universal prefix argument (C-u) is given, switch with the
previous window instead. If numerical prefix argument (e.g.,
M-2) is given, switch with the ARG-th next window."
(interactive "P")
(let* ((ring (ne2wm:win-ring-get))
(cur-wname (ne2wm:current-wname-in-list ring))
(next-wname
(when cur-wname
(ne2wm:find-next-in-seq ring cur-wname
(when (numberp arg) arg)
(and arg (listp arg))))))
(if (not next-wname)
(message "Not in win-ring windows %S." ring)
(let ((cur-buf (e2wm:pst-buffer-get cur-wname))
(next-buf (e2wm:pst-buffer-get next-wname)))
(e2wm:pst-buffer-set cur-wname next-buf)
(e2wm:pst-buffer-set next-wname cur-buf nil t))
(e2wm:pst-update-windows))))
(defun ne2wm:find-neighbor (seq item &optional reverse)
"[internal] Find neighbor of ITEM in SEQ."
(when reverse
(setq seq (reverse seq)))
(loop for previous = current
for current in seq
for next in (cdr seq)
if (eq current item)
return next
finally return previous))
(defun ne2wm:same-buffer-in-next-window (reverse)
"Show the current buffer in the next window.
When the prefix argument is given, show in the previous window."
(interactive "P")
(let ((ring (ne2wm:win-ring-get))
(wname (e2wm:aand (e2wm:pst-get-wm)
(wlf:get-window-name it (selected-window)))))
(e2wm:pst-buffer-set (ne2wm:find-neighbor ring wname reverse)
(current-buffer) nil t)))
;;; Utility functions for e2wm
(defun ne2wm:current-wname-in-list (wname-list)
"Return current window name if it is found in WNAME-LIST."
(let ((wm (e2wm:pst-get-wm))
(curwin (selected-window)))
(loop for wname in wname-list
when (eql curwin (wlf:get-window wm wname))
return wname)))
(defun ne2wm:current-wname ()
"Return current window name."
(let ((wm (e2wm:pst-get-wm))
(curwin (selected-window)))
(loop for winfo in (wlf:wset-winfo-list wm)
for wname = (wlf:window-name winfo)
when (eql curwin (wlf:get-window wm wname))
return wname)))
(defun ne2wm:pst-buffer-set-current-window (buffer)
"Set the BUFFER in the current window."
(e2wm:aif (ne2wm:current-wname)
(e2wm:pst-buffer-set it buffer)
(message "Failed to set the buffer %S in the current window" it)))
;;; Misc
(defun ne2wm:load-files (&optional regex dir)
(let* ((dir (or dir (file-name-directory load-file-name)))
(regex (or regex ".+"))
(files (and
(file-accessible-directory-p dir)
(directory-files dir 'full regex))))
(mapc #'load files)))
(provide 'ne2wm-utils)
;;; ne2wm-utils.el ends here