2d36460356f1442f6ec8daf87d522e40f878c223
[emacs-init.git] / setup / mywin.el
1 (defun split-window-3-horizontally ()
2   "Split window horizontally into three equal sized windows"
3   (interactive)
4   (let ((w (window-width)))
5     (split-window-horizontally (- w (/ w 3) -2))
6     (split-window-horizontally)))
7
8 (defun split-window-n-horizontally (width &optional min)
9   "Split window horizontally into WIDTH wide windows making the last
10 window no smaller than MIN. MIN defaults to WIDTH and WIDTH defaults
11 to 80."
12   (interactive "P")
13   (if (not width) (setq width 80))
14   (if (not min) (setq min width))
15   (save-selected-window
16     (while (> (window-width) (+ width 3 min 3))
17       (select-window (split-window-horizontally (+ width 3)))
18       (switch-to-buffer (get-buffer-create "*scratch*")))))
19
20 (defun maximize-window(&optional min-height)
21   "Enlarge the current window by as many lines as is possible without making any other
22 window smaller than MIN-HEIGHT lines."
23   (interactive)
24   ;; this algorithm is copied from window.el / balance-windows()
25   (let ((min-height (or min-height i(+ window-min-height 0)))
26         (count -1)
27         size)
28         ;; Don't count the lines that are above the uppermost windows.
29         ;; (These are the menu bar lines, if any.)
30     ;; Find all the different vpos's at which windows start,
31     ;; then count them.  But ignore levels that differ by only 1.
32     (save-window-excursion
33       (let (tops (prev-top -2))
34         (walk-windows (function (lambda (w)
35                                   (setq tops (cons (nth 1 (window-edges w))
36                                                    tops))))
37                       'nomini)
38         (setq tops (sort tops '<))
39         (while tops
40           (if (> (car tops) (1+ prev-top))
41               (setq prev-top (car tops)
42                     count (1+ count)))
43           (setq tops (cdr tops)))
44         (setq count (1+ count))))
45     (setq size (- (frame-height) (* (1- count) min-height)))
46     (enlarge-window (- size (window-height)))))
47
48 (defun safe-shrink-window(&optional n min-height)
49   "Like shrink-window but will not remove a window"
50   (interactive)
51   (let* ((min-height (or min-height window-min-height))
52          (n (or n 1)))
53     (if (< (- (window-height) n) min-height)
54         (shrink-window (- (window-height) min-height))
55       (shrink-window n))))
56
57 (defun setup-my-windows ()
58   (interactive)
59   (let ((width 100) (min 100) (distribute t)
60         (currentwindow (selected-window)) topwindows  newwindow newtopwindows)
61     (walk-windows (function (lambda (w)
62                               (let ((e (window-edges w)))
63                                 (if (< (nth 1 e) window-min-height)
64                                     (setq topwindows (cons (list (nth 0 e)
65                                                                  w
66                                                                  (window-buffer w)
67                                                                  (window-point w)
68                                                                  (window-start w)
69                                                                  (equal w currentwindow))
70                                                            topwindows))))))
71                             'nomini)
72     (setq topwindows (sort topwindows (function (lambda (a b) (< (car a) (car b))))))
73     (delete-other-windows (nth 1 (car topwindows)))
74     (setq topwindows (cdr topwindows))
75     (save-selected-window
76       (select-window (split-window-vertically
77                       (- (window-height) (max 5 (/ (* (frame-height) 15) 100)) -1)))
78       (switch-to-buffer (get-buffer-create "*compilation*")))
79     (setq newwindow (selected-window))
80     (setq newtopwindows (list (selected-window)))
81     (while (> (window-width) (+ width 3 min 3))
82       (select-window (split-window-horizontally (+ width 3)))
83       (setq newtopwindows (cons (selected-window) newtopwindows))
84       (if topwindows
85           (progn
86             (switch-to-buffer (nth 2 (car topwindows)))
87             (set-window-start (selected-window) (nth 4 (car topwindows)))
88             (goto-char (nth 3 (car topwindows)))
89             (if (nth 5 (car topwindows))
90                 (setq newwindow (selected-window)))
91             (setq topwindows (cdr topwindows)))
92         (switch-to-buffer (get-buffer-create "*scratch*"))))
93     (select-window newwindow)
94     (if (and distribute (> (length newtopwindows) 1))
95         (balance-windows newwindow))))
96
97 (defun my-split-window-sensibly (window)
98   (if (and (> (window-height window) (- (frame-height (window-frame window)) window-min-height))
99            (> (window-height window) (max 5 (/ (* (frame-height) 15) 100))))
100       (split-window-sensibly window)))
101
102 (setq split-window-preferred-function 'my-split-window-sensibly)
103
104 (global-set-key "\C-x7" 'split-window-3-horizontally)
105 (global-set-key "\C-x8" (lambda () (interactive) (split-window-n-horizontally 100 50)))
106 (global-set-key "\C-x9" 'setup-my-windows)
107 (global-set-key "\C-xp" 'other-window-reverse)
108 (global-set-key "\C-\M-_" (lambda () (interactive) (safe-shrink-window 5)))
109
110 (defun maximize-window-15 ()
111   (interactive)
112   (maximize-window (max 5 (/ (* (frame-height) 15) 100))))
113
114 (global-set-key [(ctrl meta ?+)]  'maximize-window-15)