update
[emacs-init.git] / setup / mywin.el
index 2d36460..11891c8 100644 (file)
@@ -22,7 +22,7 @@ to 80."
 window smaller than MIN-HEIGHT lines."
   (interactive)
   ;; this algorithm is copied from window.el / balance-windows()
-  (let ((min-height (or min-height i(+ window-min-height 0)))
+  (let ((min-height (or min-height (+ window-min-height 0)))
         (count -1)
         size)
         ;; Don't count the lines that are above the uppermost windows.
@@ -54,61 +54,197 @@ window smaller than MIN-HEIGHT lines."
         (shrink-window (- (window-height) min-height))
       (shrink-window n))))
 
-(defun setup-my-windows ()
-  (interactive)
-  (let ((width 100) (min 100) (distribute t)
-        (currentwindow (selected-window)) topwindows  newwindow newtopwindows)
+(defconst setup-my-windows-precious-buffers
+  '("*eshell*"))
+(defconst setup-my-windows-junk-buffers
+  '("*scratch*" "*Messages*" "*Calculator" "*Calc Trail*" "*compilation*" "*fetchmail*"))
+
+(defvar my-windows-count nil)
+
+(defun get-top-windows ()
+  (let (topwindows)
     (walk-windows (function (lambda (w)
                               (let ((e (window-edges w)))
                                 (if (< (nth 1 e) window-min-height)
-                                    (setq topwindows (cons (list (nth 0 e)
-                                                                 w
-                                                                 (window-buffer w)
-                                                                 (window-point w)
-                                                                 (window-start w)
-                                                                 (equal w currentwindow))
-                                                           topwindows))))))
-                            'nomini)
-    (setq topwindows (sort topwindows (function (lambda (a b) (< (car a) (car b))))))
+                                  (setq topwindows (cons (cons (nth 0 e) w) topwindows)))))))
+    (loop for w in (sort topwindows (function (lambda (a b) (< (car a) (car b)))))
+          collect (cdr w) )))
+
+(defun setup-my-windows (&optional n)
+  (interactive "P")
+  (if n
+      (if (integerp n)
+          (setq my-windows-count n)
+        (setq my-windows-count nil)))
+  (let* ((width (if my-windows-count
+                    (- (/ (frame-width) my-windows-count) 4)
+                  (or whitespace-line-column 100)))
+         (min width) (distribute t)
+         (currentbuffer (current-buffer))
+         (currentwindow (selected-window))
+         (topwindows (loop for w in (get-top-windows)
+                           for b = (window-buffer w)
+                           if (not (member (buffer-name b)
+                                           setup-my-windows-junk-buffers))
+                           collect (list (nth 0 (window-edges w))
+                                         w
+                                         b
+                                         (window-point w)
+                                         (window-start w)
+                                         (equal w currentwindow))))
+         firstwindow newwindow newtopwindows newbottomwindow)
     (delete-other-windows (nth 1 (car topwindows)))
-    (setq topwindows (cdr topwindows))
     (save-selected-window
-      (select-window (split-window-vertically
-                      (- (window-height) (max 5 (/ (* (frame-height) 15) 100)) -1)))
-      (switch-to-buffer (get-buffer-create "*compilation*")))
-    (setq newwindow (selected-window))
+      (setq newbottomwindow (split-window-vertically
+                             (- (window-height) (max 5 (/ (* (frame-height) 15) 100)) -1)))
+      (select-window newbottomwindow)
+      (switch-to-buffer (get-buffer-create "*compilation*"))
+      (if (eq currentbuffer (current-buffer))
+          (setq newwindow (selected-window))))
+    (setq firstwindow (selected-window))
     (setq newtopwindows (list (selected-window)))
     (while (> (window-width) (+ width 3 min 3))
       (select-window (split-window-horizontally (+ width 3)))
       (setq newtopwindows (cons (selected-window) newtopwindows))
-      (if topwindows
-          (progn
-            (switch-to-buffer (nth 2 (car topwindows)))
-            (set-window-start (selected-window) (nth 4 (car topwindows)))
-            (goto-char (nth 3 (car topwindows)))
-            (if (nth 5 (car topwindows))
-                (setq newwindow (selected-window)))
-            (setq topwindows (cdr topwindows)))
-        (switch-to-buffer (get-buffer-create "*scratch*"))))
+      (switch-to-buffer (get-buffer-create "*scratch*")))
+    (setq newtopwindows (reverse newtopwindows))
+    (loop for w in newtopwindows
+          for (pos win buf point start iscurrent) in
+              (loop for w in topwindows
+                    for (pos win buf point start iscurrent) = w
+                    if (not (member (buffer-name buf) setup-my-windows-precious-buffers))
+                    collect w)
+          do (progn
+               (select-window w)
+               (set-window-buffer w buf)
+               (set-window-start w start)
+               (goto-char point)
+               (if iscurrent
+                   (setq newwindow w))))
+    (setq newtopwindows (reverse newtopwindows))
+    (setq topwindows (reverse topwindows))
+    (loop for w in newtopwindows
+          for (pos win buf point start iscurrent) in
+              (loop for w in topwindows
+                    for (pos win buf point start iscurrent) = w
+                    if (member (buffer-name buf) setup-my-windows-precious-buffers)
+                    collect w)
+          do (progn
+               (select-window w)
+               (set-window-buffer w buf)
+               (set-window-start w start)
+               (goto-char point)
+               (if iscurrent
+                   (setq newwindow w))))
+    (setq newwindow
+          (or newwindow
+              (loop for w in newtopwindows
+                    if (eq (window-buffer w) currentbuffer) return w)
+              (loop for w in newtopwindows
+                    for name = (buffer-name (window-buffer w))
+                    if (string= name "*scratch*") return w)
+              (loop for w in newtopwindows
+                    for name = (buffer-name (window-buffer w))
+                    if (and (= (aref name 0) ?*)
+                            (not (member name setup-my-windows-precious-buffers))) return w)
+              firstwindow))
+    (when (and distribute (> (length newtopwindows) 1))
+      (pjb-balance-windows t))
     (select-window newwindow)
-    (if (and distribute (> (length newtopwindows) 1))
-        (balance-windows newwindow))))
+    (if (not (member (buffer-name currentbuffer) setup-my-windows-junk-buffers))
+        (switch-to-buffer currentbuffer))
+    newbottomwindow))
 
 (defun my-split-window-sensibly (window)
   (if (and (> (window-height window) (- (frame-height (window-frame window)) window-min-height))
            (> (window-height window) (max 5 (/ (* (frame-height) 15) 100))))
       (split-window-sensibly window)))
 
+(defun my-pop-to-buffer (buffer)
+  ;; display buffer in rightmost window if not displayed currently
+  (let ((w (get-buffer-window buffer)))
+    (unless w
+      (setq w (car (last (get-top-windows)))))
+    (select-window w)
+    (switch-to-buffer buffer)))
+
+(defun my-display-at-bottom (&optional buffer)
+  ;; call my-setup-window and display current-buffer or BUFFER in bottom frame
+  (interactive)
+  (if (not buffer) (setq buffer (current-buffer)))
+  (bury-buffer)
+  ;; why does save-selected-window not work here ???
+  (save-selected-window
+    (select-window (setup-my-windows))
+    (switch-to-buffer buffer)))
+
 (setq split-window-preferred-function 'my-split-window-sensibly)
 
 (global-set-key "\C-x7" 'split-window-3-horizontally)
 (global-set-key "\C-x8" (lambda () (interactive) (split-window-n-horizontally 100 50)))
 (global-set-key "\C-x9" 'setup-my-windows)
-(global-set-key "\C-xp" 'other-window-reverse)
 (global-set-key "\C-\M-_" (lambda () (interactive) (safe-shrink-window 5)))
+(global-set-key "\C-x_" 'my-display-at-bottom)
+
+(defun my-swap-window-to-right (&optional below)
+  "If swap buffer in this window with buffer on the right. If BELOW is set,
+instead move current buffer to right and replace it with the next buffer from
+the buffer stack in the current window."
+  (interactive "P")
+  (let ((cb (current-buffer))
+        (cw (selected-window)))
+    (if below
+        (switch-to-buffer nil))
+    (windmove-right)
+    (if (not below)
+        (set-window-buffer cw (current-buffer)))
+    (switch-to-buffer cb)))
+
+(defun my-swap-window-to-left (&optional below)
+  (interactive "P")
+  (let ((cb (current-buffer))
+        (cw (selected-window)))
+    (if below
+        (switch-to-buffer nil))
+    (windmove-left)
+    (if (not below)
+        (set-window-buffer cw (current-buffer)))
+    (switch-to-buffer cb)))
+
+(global-set-key "\C-x>" 'my-swap-window-to-right)
+(global-set-key "\C-x<" 'my-swap-window-to-left)
 
 (defun maximize-window-15 ()
   (interactive)
   (maximize-window (max 5 (/ (* (frame-height) 15) 100))))
 
 (global-set-key [(ctrl meta ?+)]  'maximize-window-15)
+
+(defun safe-max-window-horizontally ()
+  (interactive)
+  (let ((found nil)
+        (width 0)
+        (count 0)
+        (current (selected-window)))
+    (walk-windows (function (lambda (w)
+                              (let ((e (window-edges w)))
+                                (if (< (nth 1 e) window-min-height)
+                                    (progn
+                                      (setq width (+ width (window-width w))
+                                            count (1+ count))
+                                      (if (equal w current)
+                                          (setq found t)))))))
+                  'nomini)
+    (if (not found)
+        (error "Current window is not a top window"))
+    (shrink-window-horizontally (- (- width (window-width) (* window-min-width (1- count)))))))
+
+(defun safe-max-window ()
+  (interactive)
+  (maximize-window 5)
+  (condition-case nil
+      (safe-max-window-horizontally)
+    (error nil)))
+
+(global-set-key "\C-x=" 'safe-max-window)
+(global-set-key "\C-x-" 'maximize-window-15)