summaryrefslogtreecommitdiffstats
path: root/bw.el
blob: 7e94a280713b441c8ae9ab9ad10f6b7226f170f0 (plain)
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
;;; bw.el --- Show stuff in a bottom window

;; Copyright (C) 2012  Tom Willemsen

;; Author: Tom Willemsen <slash@drd>
;; Keywords: convenience
;; Version: 0

;; 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:

;; Show stuff in a bottom window.  The idea is taken from ide-skel,
;; which is a very nice extension, but doesn't fit into my workflow at
;; all, the only really nice thing is that all *buffers* appear in a
;; specialized window.

;;; Usage:

;; Make sure it's loadable, you should be able to do this by using:

;;     M-x package-install-file RET /path/to/bw.el RET

;; or if you don't use package.el you could use:

;;     (add-to-list 'load-path "/path/to/bw/directory")
;;     (require 'bw)

;; Once that is done you can set it up for use:

;;     (add-to-list 'display-buffer-alist
;;                  '("^\\*.*\\*$"
;;                    . ((bw-display-in-bottom-window . nil)))

;; And perhaps even bind a key to it:

;; (global-set-key (kbd "<f11>") 'bw-toggle-bottom-window)

;;; Code:

(defvar bw-last-shown-buffer nil
  "The last buffer shown by bw.")

(defadvice quit-window (around delete-window-perhaps activate)
  "Delete the bottom window if necessary."
  (let* ((win (window-normalize-window (ad-get-arg 2)))
         (delp (and (window-parameter win 'bw-bottom)
                    (string-match-p "^\\*.*\\*$"
                                    (buffer-name (window-buffer win))))))
    ad-do-it
    (when delp
      (delete-window win))))

(defun bw-create-window ()
  "Create the bottom window."
  (let ((win (split-window (frame-root-window) -20 'below)))
    (set-window-parameter win 'bw-bottom t)
    ;; Don't allow splitting of the bottom window.
    (set-window-parameter win 'split-window (lambda (window size side) nil))
    ;; Don't allow deleting other windows in the bottom window.
    (set-window-parameter win 'delete-other-windows (lambda (window) nil))
    win))

(defun bw-get-window ()
  "Try to get the bottom window."
  (let (win)
    (mapc
     (lambda (w)
       (when (window-parameter w 'bw-bottom)
         (setq win w)))
     (window-list))
    win))

;;;###autoload
(defun bw-display-in-bottom-window (buffer alist)
  "Show BUFFER in the bottom window, discard ALIST."
  (let ((win (or (bw-get-window) (bw-create-window))))
    (set-window-buffer win buffer)
    (setq bw-last-shown-buffer buffer)
    win))

;;;###autoload
(defun bw-display-in-other-window (buffer alist)
  "Show BUFFER in any window that is not the bottom window.

Discard ALIST."
  (let ((win (get-buffer-window buffer)))
    (when (window-parameter win 'bw-bottom)
      (setq win (next-window win 'no)))
    (set-window-buffer win buffer)))

(add-to-list 'window-persistent-parameters (cons 'bw-bottom t))

(defun bw-find-appropriate-buffer ()
  "Find an appropriate buffer for bw."
  (let ((buffers (buffer-list))
        tmp-buffer buffer)
    (while (and (not buffer) buffers)
      (setq tmp-buffer (car buffers))
      (when (string-match-p "^\\*.*\\*$" (buffer-name tmp-buffer))
        (setq buffer tmp-buffer))
      (setq buffers (cdr buffers)))
    (unless buffer
      (setq buffer "*scratch*"))
    buffer))

;;;###autoload
(defun bw-toggle-bottom-window ()
  "Either show or delete the bottom window."
  (interactive)
  (let ((win (bw-get-window)))
    (if win
        (delete-window win)
      (setq win (bw-create-window))
      (bw-display-in-bottom-window
       (or bw-last-shown-buffer (bw-find-appropriate-buffer)) nil)
      (select-window win))))

(global-set-key (kbd "<f11>") 'bw-toggle-bottom-window)

(provide 'bw)
;;; bw.el ends here