root/lang/elisp/widen-window-mode/trunk/widen-window.el @ 23751

Revision 23751, 8.0 kB (checked in by hayamiz, 5 years ago)

* widen-window.el (ww-advised-functions): added `delete-window'
(ww-setup-advice): Checks if really `ww-advised-functions' are bounded.
(widen-current-window): By calling ww-subtree only once, sometimes resizing windows was not fully done. So I used the trick in balance-window'. Until any windows does not change its size, call ww-subtree' repeatedly.
(ww-bw-wid): an utility function
(ww-bw-hei): an utility function
(ww-sign): an utility function which just returns a sign of an argument(must be a number).
(ww-adjust-window): Smart wrapper of `bw-adjust-window'.
If bw-adjust-window' fails to change the size of a window to specified size(ex. tried too big size), it does nothing (on Emacs22), and widen-current-window' thinks that resizing iteration was finished, and `widen-current-window' actually does nothing.
If `ww-adjust-window' fails to resize, it tries smaller change than specified.
(ww-subtree): fixed the bug that ww-width/ww-height does not work on Emacs23.
When ww-width is nil, any width resize didn't happen because ww-adjust-window' tried too large size and failed, but on Emacs23, of which ww-adjust-window' is a bit smarter, resizing happened.

ver 0.1.0 release

Line 
1;;; widen-window.el --- Widening selecting window
2
3;; Copyright (C) 2008  Yuto Hayamizu
4
5;; Author: Yuto Hayamizu <y.hayamizu@gmail.com>
6;; Keywords: convenience
7;; Version: 0.1.0
8
9;; This file is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 3, or (at your option)
12;; any later version.
13
14;; This file is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs; see the file COPYING.  If not, write to
21;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22;; Boston, MA 02110-1301, USA.
23
24;;; Commentary:
25
26;; This minor mode, widen window mode, provides a function that widen
27;; selected window automatically.
28;; It was tested only on Emacs 22.
29
30;; In order to use this minor mode, put this file into
31;; a directory included in load-path,
32;; and add following code to your .emacs.
33;; +------------------------+
34;; (require 'widen-window)
35;; (global-widen-window-mode t)
36;; +------------------------+
37
38;; You can change the window size ratio by customizing `ww-ratio'.
39;; `ww-ratio' must be greater than 0.0 and less than 1.0 .
40
41;; If you want to avoid widen window mode in a certain
42;; major mode(say `foo-mode'), customize the variable `ww-nonwide-modes'.
43
44;; Because this is still early release, sometimes window widening
45;; might not work even if it should. If you find some functions to be
46;; advised, add them to `ww-advised-functions'.
47
48;;; Code:
49
50(require 'easy-mmode)
51(require 'cl)
52
53(defgroup widen-window nil
54  "Widen selected window"
55  :group 'convenience
56  :prefix "widen-window-")
57
58(defcustom ww-ratio 0.625
59  "This is a ratio which the selected window takes up in window subtree."
60  :group 'widen-window
61  :type 'number
62  )
63
64(defcustom ww-nonwide-modes
65  '(dummy1-mode dummy2-mode)
66  "Major modes `widen-current-window' cannot run."
67  :type '(list symbol)
68  :group 'widen-window)
69
70(defcustom ww-height
71  t
72  "If `ww-height' is non-nil, widen-window for height will work."
73  :type '(choice (const :tag "Yes" t)
74                 (const :tag "No" nil))
75  :group 'widen-window)
76
77(defcustom ww-width
78  t
79  "If `ww-width' is non-nil, widen-window for width will work."
80  :type '(choice (const :tag "Yes" t)
81                 (const :tag "No" nil))
82  :group 'widen-window)
83
84(defcustom ww-advised-functions
85  '(other-window
86    split-window
87    switch-to-buffer
88    mouse-drag-region
89    delete-window
90    add-change-log-entry-other-window
91    )
92  "Functions to be advised. Window widening function `widen-current-window' is fired after advised function was called."
93  :type '(list symbol)
94  :group 'widen-window)
95
96(defun widen-current-window ()
97  (interactive)
98
99  (unless (minibufferp (current-buffer))
100    (cond
101     ((>= 0 ww-ratio) (setq ww-ratio 0.2))
102     ((<= 1 ww-ratio) (setq ww-ratio 0.8)))
103 
104    (let* ((current-window (selected-window))
105           (window-tree (bw-get-tree (selected-frame))))
106      (when window-tree
107        ;; Sometimes, you cannot get correctly resized windows
108        ;; by calling ww-subtree only once.
109        ;; So ww-subtree is called repeatedly until
110        ;; you can get what you want.
111        (let ((sizeinfo-history nil)
112              (last-sizeinfo nil)
113              (windows (window-list nil nil)))
114          (while (not (member last-sizeinfo sizeinfo-history))
115            (setq sizeinfo-history
116                  (cons last-sizeinfo sizeinfo-history))
117            (setq last-sizeinfo
118                  (mapcar (lambda (w)
119                            (window-edges w))
120                          windows))         
121            (ww-subtree
122             window-tree current-window
123             (- (bw-r window-tree) (bw-l window-tree))
124             (- (bw-b window-tree) (bw-t window-tree)))
125            )))
126        )))
127
128(defun ww-bw-wid (window-or-tree)
129  (- (bw-r window-or-tree) (bw-l window-or-tree)))
130
131(defun ww-bw-hei (window-or-tree)
132  (- (bw-b window-or-tree) (bw-t window-or-tree)))
133
134(defun ww-sign (num)
135  (if (>= num 0)
136      +1
137    -1))
138
139(defun ww-adjust-window (wtree delta horiz-p)
140  "Smart wrapper of `bw-adjust-window'
141
142If `bw-adjust-window' fails to change the size of a window to specified size(ex. tried too big size), it does nothing (on Emacs22), and `widen-current-window' thinks that resizing iteration was finished, and `widen-current-window' actually does nothing.
143If `ww-adjust-window' fails to resize, it tries smaller change than specified."
144  (if horiz-p
145        ;; width changes
146      (let (last-width)
147        (while (> (abs delta) 0)
148          (setq last-width (ww-bw-wid wtree))
149          (bw-adjust-window wtree delta horiz-p)
150          (let ((wid-change (- (ww-bw-wid wtree) last-width)))
151            (if (eq wid-change 0)
152                (setq delta (* (ww-sign delta) (floor (* 0.66 (abs delta)))))
153              (setq delta (- delta wid-change))))))
154
155    ;; height changes
156    (let (last-height)
157        (while (> (abs delta) 0)
158          (setq last-height (ww-bw-hei wtree))
159          (bw-adjust-window wtree delta horiz-p)
160          (let ((hei-change (- (ww-bw-hei wtree) last-height)))
161            (if (eq hei-change 0)
162                (setq delta (* (ww-sign delta) (floor (* 0.66 (abs delta)))))
163              (setq delta (- delta hei-change))))))
164        )
165    )
166
167(defun ww-subtree (wtree cur-win wid hei)
168  (setq wtree (bw-refresh-edges wtree))
169  (unless wid (setq wid (ww-bw-wid wtree)))
170  (unless hei (setq hei (ww-bw-hei wtree)))
171  (let ((wtree-wid (ww-bw-wid wtree))
172        (wtree-hei (ww-bw-hei wtree)))
173    (if (windowp wtree)
174        (progn
175          (when wid
176            (let ((dw (- wid wtree-wid)))
177              (when (/= 0 dw)
178                (ww-adjust-window wtree dw t))))
179          (when hei
180            (let ((dh (- hei wtree-hei)))
181              (when (/= 0 dh)
182                (ww-adjust-window wtree dh nil))))
183          )
184      (let* ((children (cdr (assq 'childs wtree)))
185             (cwin-num (length children))
186             (cwin-bigger-wid wid)
187             (cwin-bigger-hei hei)
188             (cwin-smaller-wid wid)
189             (cwin-smaller-hei hei))
190        (case (bw-dir wtree)
191          ((hor)
192           (setq cwin-smaller-wid
193                 (floor (/ (* wtree-wid (- 1 ww-ratio))
194                           (- cwin-num 1))))
195           (setq cwin-bigger-wid
196                 (- wtree-wid (* (- cwin-num 1)
197                               cwin-smaller-wid))))
198          ((ver)
199           (setq cwin-smaller-hei
200                 (floor (/ (* wtree-hei (- 1 ww-ratio))
201                           (- cwin-num 1))))
202           (setq cwin-bigger-hei
203                 (- wtree-hei (* (- cwin-num 1)
204                               cwin-smaller-hei)))))
205        (dolist (cwin children)
206          (if (ww-find-window-in-subtree cwin cur-win)
207              (ww-subtree
208               cwin cur-win
209               (if ww-width cwin-bigger-wid (ww-bw-wid cwin))
210               (if ww-height cwin-bigger-hei (ww-bw-hei cwin)))
211            (ww-subtree
212             cwin cur-win
213             (if ww-width cwin-smaller-wid (ww-bw-wid cwin))
214             (if ww-height cwin-smaller-hei (ww-bw-hei cwin)))))
215        ))))
216
217(defun ww-find-window-in-subtree (wt window)
218  (block func
219    (cond
220     ((windowp wt)
221      (if (equal wt window)
222          window
223        nil))
224     (t
225      (dolist (subwt (cdr (assq 'childs wt)))
226        (let ((ret (ww-find-window-in-subtree subwt window)))
227          (when ret
228            (return-from func window))))
229      nil))))
230
231(defun ww-setup-advice ()
232  (dolist (func ww-advised-functions)
233    (when (fboundp func)
234      (eval `(defadvice ,func (after widen-window-advice)
235               (if (and widen-window-mode (not (memq major-mode ww-nonwide-modes)))
236                   (widen-current-window))))))
237  (ad-activate-regexp "widen-window"))
238
239(define-minor-mode widen-window-mode
240  "Widen Window mode"
241  :lighter " WW"
242  :group 'widen-window
243  (if widen-window-mode
244      (progn
245        (ww-setup-advice)
246        (if (memq major-mode ww-nonwide-modes)
247            (widen-window-mode nil)))
248    nil))
249
250(defun widen-window-mode-maybe ()
251  "Return t if `widen-current-window' can run on current buffer."
252  (if (and (not (minibufferp (current-buffer)))
253           (not (memq major-mode ww-nonwide-modes)))
254      (widen-window-mode t)))
255
256(define-global-minor-mode global-widen-window-mode
257  widen-window-mode widen-window-mode-maybe
258  :group 'widen-window)
259
260;;; for anything.el
261;; (defadvice anything (around disable-ww-mode activate)
262;;   (ad-deactivate-regexp "widen-window")
263;;   (unwind-protect
264;;       ad-do-it
265;;     (ad-activate-regexp "widen-window")))
266
267;; (if (fboundp 'anything)
268;;     (ad-activate-regexp "disable-ww-mode"))
269
270(provide 'widen-window)
271;;; widen-window.el ends here
Note: See TracBrowser for help on using the browser.