Initial Commit
[packages] / xemacs-packages / hyperbole / wconfig.el
1 ;;; wconfig.el --- Saves and yanks from save ring of window configurations.
2
3 ;; Copyright (C) 1989-1995, Free Software Foundation, Inc.
4 ;; Developed with support from Motorola Inc.
5
6 ;; Author: Bob Weiner, Brown U.
7 ;; Maintainer: Mats Lidell <matsl@contactor.se>
8 ;; Keywords: frames, hypermedia
9
10 ;; This file is part of GNU Hyperbole.
11
12 ;; GNU Hyperbole is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 3, or (at
15 ;; your option) any later version.
16
17 ;; GNU Hyperbole is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 ;; General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
26
27 ;;; Commentary:
28 ;;
29 ;;   This library provides two unrelated means of managing window
30 ;;   configurations, (the set of windows and associated buffers within a
31 ;;   frame).  The first means associates a name with each stored window
32 ;;   configuration.  The name can then be used to retrieve the window
33 ;;   configuration later.  The following functions provide this behavior:
34 ;;
35 ;;      wconfig-add-by-name
36 ;;      wconfig-delete-by-name
37 ;;      wconfig-restore-by-name
38 ;;
39 ;;   The second means of window configuration management is through
40 ;;   the use of a ring structure, just like the Emacs kill ring except
41 ;;   the elements stored are window configurations instead of textual
42 ;;   regions. These configurations are local for a frame so there is a
43 ;;   ring of configurations for each frame.  The following functions
44 ;;   support storage and sequential retrieval of window
45 ;;   configurations:
46 ;;
47 ;;      wconfig-ring-save
48 ;;      wconfig-yank-pop
49 ;;      wconfig-delete-pop
50 ;;
51 ;;   None of this information is stored between Emacs sessions, so your
52 ;;   window configurations will last only through a single session of use.
53 ;;
54 ;;   Based in part on kill-ring code from simple.el.
55 ;;
56
57 ;;; Code:
58
59 ;;;
60 ;;; Recommended key bindings
61 ;;;
62
63 ;;; Set up in local "hyperbole.el".
64
65 ;;;
66 ;;; Other required Elisp libraries
67 ;;;
68 (require 'ring)
69 (require 'hargs)
70 (require 'set)
71
72 ;;;
73 ;;; Public variables
74 ;;;
75
76 (defconst wconfig-ring-max 10
77   "*Maximum length of window configuration ring before oldest elements are deleted.")
78
79 ;;;
80 ;;; Public functions
81 ;;;
82
83 ;;; Handling of name associations with each stored window configuration.
84 ;;;###autoload
85 (defun wconfig-add-by-name (name)
86   "Saves the current window configuration under the string NAME.
87 When called interactively and a window configuration already exists under
88 NAME, confirms whether or not to replace it."
89   (interactive "sName for current window configuration: ")
90   (or (stringp name)
91       (error "(wconfig-add-by-name): NAME argument is not a string: %s" name))
92   (let ((set:equal-op (function (lambda (key elt)
93                                   (equal key (car elt))))))
94     (if (or (not (interactive-p))
95             (not (set:member name wconfig-names))
96             (y-or-n-p
97               (format "Replace existing '%s' window configuration: " name)))
98         (progn (setq wconfig-names
99                      (set:replace name (current-window-configuration)
100                                   wconfig-names))
101                (if (interactive-p)
102                    (message "Window configuration '%s' saved.  Use 'wconfig-restore-by-name' to restore." name))))))
103
104 ;;;###autoload
105 (defun wconfig-delete-by-name (name)
106   "Deletes window configuration saved under NAME."
107   (interactive (list (hargs:read-match "Delete window configuration named: "
108                                        wconfig-names nil t)))
109   (or (stringp name)
110       (error "(wconfig-delete-by-name): NAME argument is not a string: %s" name))
111   (let ((set:equal-op (function (lambda (key elt)
112                                   (equal key (car elt))))))
113     (setq wconfig-names (set:remove name wconfig-names))))
114
115 ;;;###autoload
116 (defun wconfig-restore-by-name (name)
117   "Restores window configuration saved under NAME."
118   (interactive (list (hargs:read-match "Restore window configuration named: "
119                                        wconfig-names nil t)))
120   (or (stringp name)
121       (error "(wconfig-restore-by-name): NAME argument is not a string: %s" name))
122   (let ((wconfig (set:get name wconfig-names)))
123     (if wconfig
124         (set-window-configuration wconfig)
125       (error "(wconfig-restore-by-name): No window configuration named '%s'" name))))
126
127 ;;; Window configuration ring management (like text kill ring).
128 ;;;###autoload
129 (defun wconfig-delete-pop ()
130   "Replaces current window config with most recently saved config in ring.
131 Then deletes this new configuration from the ring."
132   (interactive)
133   (let ((ring (wconfig-get-ring)))
134     (if (ring-empty-p ring)
135         (error "(wconfig-delete-pop): Window configuration save ring is empty")
136       (ring-remove ring 0)
137       (if (ring-empty-p ring)
138           (message "(wconfig-delete-pop): Window configuration save ring is empty")
139         (set-window-configuration (ring-ref ring 0))))))
140
141 ;;;###autoload
142 (defun wconfig-ring-save ()
143   "Saves the current window configuration onto the save ring.
144 Use {\\[wconfig-yank-pop]} to restore it at a later time."
145   (interactive)
146   (ring-insert (wconfig-get-ring) (current-window-configuration))
147   (if (interactive-p)
148       (message "Window configuration saved.  Use 'wconfig-yank-pop' to restore.")))
149
150 ;;;###autoload
151 (defun wconfig-yank-pop (n)
152   "Replaces current window config with prefix arg Nth prior one in save ring.
153 Interactively, default value of N = 1, meaning the last saved window
154 configuration is displayed.
155
156 The sequence of window configurations wraps around, so that after the oldest
157 one comes the newest one."
158   (interactive "p")
159   (let ((ring (wconfig-get-ring)))
160     (if (ring-empty-p ring)
161         (error "(wconfig-yank-pop): Window configuration save ring is empty")
162       (let ((prev (ring-remove ring (- 1 n))))
163         (ring-insert-at-beginning ring prev)
164         (set-window-configuration (ring-ref ring 0))))))
165
166 ;;; Frames
167 (defun wconfig-get-ring ()
168   (let* ((frame (selected-frame))
169          (ring (frame-property frame 'wconfig-ring)))
170     (if (not ring)
171         (set-frame-property frame 'wconfig-ring (setq ring (make-ring wconfig-ring-max))))
172     ring))
173
174 ;;;
175 ;;; Private variables
176 ;;;
177
178 (defvar wconfig-names (set:create)
179   "Set of (name . window-configuration) elements.")
180
181 (run-hooks 'wconfig-load-hook)
182
183 (provide 'wconfig)
184
185 ;;; wconfig.el ends here