source: tags/1.2/source/cocoa-ide/hemlock/unused/archive/group.lisp

Last change on this file was 6569, checked in by Gary Byers, 18 years ago

Move more (currently unused, often unlikely to ever be used) stuff to an
archive directory.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1;;; -*- Log: hemlock.log; Package: Hemlock -*-
2;;;
3;;; **********************************************************************
4;;; This code was written as part of the CMU Common Lisp project at
5;;; Carnegie Mellon University, and has been placed in the public domain.
6;;;
7#+CMU (ext:file-comment
8 "$Header$")
9;;;
10;;; **********************************************************************
11;;;
12;;; File group stuff for Hemlock.
13;;; Written by Skef Wholey and Rob MacLachlan.
14;;;
15;;; The "Compile Group" and "List Compile Group" commands in lispeval
16;;; also know about groups.
17;;;
18;;; This file provides Hemlock commands for manipulating groups of files
19;;; that make up a larger system. A file group is a set of files whose
20;;; names are listed in some other file. At any given time one group of
21;;; files is the Active group. The Select Group command makes a group the
22;;; Active group, prompting for the name of a definition file if the group
23;;; has not been selected before. Once a group has been selected once, the
24;;; name of the definition file associated with that group is retained. If
25;;; one wishes to change the name of the definition file after a group has
26;;; been selected, one should call Select Group with a prefix argument.
27
28(in-package :hemlock)
29
30(defvar *file-groups* (make-string-table)
31 "A string table of file groups.")
32
33(defvar *active-file-group* ()
34 "The list of files in the currently active group.")
35
36(defvar *active-file-group-name* ()
37 "The name of the currently active group.")
38
39
40
41
42;;;; Selecting the active group.
43
44(defcommand "Select Group" (p)
45 "Makes a group the active group. With a prefix argument, changes the
46 definition file associated with the group."
47 "Makes a group the active group."
48 (let* ((group-name
49 (prompt-for-keyword
50 (list *file-groups*)
51 :must-exist nil
52 :prompt "Select Group: "
53 :help
54 "Type the name of the file group you wish to become the active group."))
55 (old (getstring group-name *file-groups*))
56 (pathname
57 (if (and old (not p))
58 old
59 (prompt-for-file :must-exist t
60 :prompt "From File: "
61 :default (merge-pathnames
62 (make-pathname
63 :name group-name
64 :type "upd")
65 (value pathname-defaults))))))
66 (setq *active-file-group-name* group-name)
67 (setq *active-file-group* (nreverse (read-file-group pathname nil)))
68 (setf (getstring group-name *file-groups*) pathname)))
69
70
71;;; READ-FILE-GROUP reads an Update format file and returns a list of pathnames
72;;; of the files named in that file. This guy knows about @@ indirection and
73;;; ignores empty lines and lines that begin with @ but not @@. A simpler
74;;; scheme could be used for non-Spice implementations, but all this hair is
75;;; probably useful, so Update format may as well be a standard for this sort
76;;; of thing.
77;;;
78(defun read-file-group (pathname tail)
79 (with-open-file (file pathname)
80 (do* ((name (read-line file nil nil) (read-line file nil nil))
81 (length (if name (length name)) (if name (length name))))
82 ((null name) tail)
83 (declare (type (or simple-string null) name))
84 (cond ((zerop length))
85 ((char= (char name 0) #\@)
86 (when (and (> length 1) (char= (char name 1) #\@))
87 (setq tail (read-file-group
88 (merge-pathnames (subseq name 2)
89 pathname)
90 tail))))
91 (t
92 (push (merge-pathnames (pathname name) pathname) tail))))))
93
94
95
96
97;;;; DO-ACTIVE-GROUP.
98
99(defhvar "Group Find File"
100 "If true, group commands use \"Find File\" to read files, otherwise
101 non-resident files are read into the \"Group Search\" buffer."
102 :value nil)
103
104(defhvar "Group Save File Confirm"
105 "If true, then the group commands will ask for confirmation before saving
106 a modified file." :value t)
107
108(defmacro do-active-group (&rest forms)
109 "This iterates over the active file group executing forms once for each
110 file. When forms are executed, the file will be in the current buffer,
111 and the point will be at the start of the file."
112 (let ((n-buf (gensym))
113 (n-start-buf (gensym))
114 (n-save (gensym)))
115 `(progn
116 (unless *active-file-group*
117 (editor-error "There is no active file group."))
118
119 (let ((,n-start-buf (current-buffer))
120 (,n-buf nil))
121 (unwind-protect
122 (dolist (file *active-file-group*)
123 (catch 'file-not-found
124 (setq ,n-buf (group-read-file file ,n-buf))
125 (with-mark ((,n-save (current-point) :right-inserting))
126 (unwind-protect
127 (progn
128 (buffer-start (current-point))
129 ,@forms)
130 (move-mark (current-point) ,n-save)))
131 (group-save-file)))
132 (if (member ,n-start-buf *buffer-list*)
133 (setf (current-buffer) ,n-start-buf
134 (window-buffer (current-window)) ,n-start-buf)
135 (editor-error "Original buffer deleted!")))))))
136
137;;; GROUP-READ-FILE reads in files for the group commands via DO-ACTIVE-GROUP.
138;;; We use FIND-FILE-BUFFER, which creates a new buffer when the file hasn't
139;;; already been read, to get files in, and then we delete the buffer if it is
140;;; newly created and "Group Find File" is false. This lets FIND-FILE-BUFFER
141;;; do all the work. We don't actually use the "Find File" command, so the
142;;; buffer history isn't affected.
143;;;
144;;; Search-Buffer is any temporary search buffer left over from the last file
145;;; that we want deleted. We don't do the deletion if the buffer is modified.
146;;;
147(defun group-read-file (name search-buffer)
148 (unless (probe-file name)
149 (message "File ~A not found." name)
150 (throw 'file-not-found nil))
151 (multiple-value-bind (buffer created-p)
152 (find-file-buffer name)
153 (setf (current-buffer) buffer)
154 (setf (window-buffer (current-window)) buffer)
155
156 (when (and search-buffer (not (buffer-modified search-buffer)))
157 (dolist (w (buffer-windows search-buffer))
158 (setf (window-buffer w) (current-buffer)))
159 (delete-buffer search-buffer))
160
161 (if (and created-p (not (value group-find-file)))
162 (current-buffer) nil)))
163
164;;; GROUP-SAVE-FILE is used by DO-ACTIVE-GROUP.
165;;;
166(defun group-save-file ()
167 (let* ((buffer (current-buffer))
168 (pn (buffer-pathname buffer))
169 (name (namestring pn)))
170 (when (and (buffer-modified buffer)
171 (or (not (value group-save-file-confirm))
172 (prompt-for-y-or-n
173 :prompt (list "Save changes in ~A? " name)
174 :default t)))
175 (save-file-command ()))))
176
177
178
179
180;;;; Searching and Replacing commands.
181
182(defcommand "Group Search" (p)
183 "Searches the active group for a specified string, which is prompted for."
184 "Searches the active group for a specified string."
185 (declare (ignore p))
186 (let ((string (prompt-for-string :prompt "Group Search: "
187 :help "String to search for in active file group"
188 :default *last-search-string*)))
189 (get-search-pattern string :forward)
190 (do-active-group
191 (do ((won (find-pattern (current-point) *last-search-pattern*)
192 (find-pattern (current-point) *last-search-pattern*)))
193 ((not won))
194 (character-offset (current-point) won)
195 (command-case
196 (:prompt "Group Search: "
197 :help "Type a character indicating the action to perform."
198 :change-window nil)
199 (:no "Search for the next occurrence.")
200 (:do-all "Go on to the next file in the group."
201 (return nil))
202 ((:exit :yes) "Exit the search."
203 (return-from group-search-command))
204 (:recursive-edit "Enter a recursive edit."
205 (do-recursive-edit)
206 (get-search-pattern string :forward)))))
207 (message "All files in group ~S searched." *active-file-group-name*)))
208
209(defcommand "Group Replace" (p)
210 "Replaces one string with another in the active file group."
211 "Replaces one string with another in the active file group."
212 (declare (ignore p))
213 (let* ((target (prompt-for-string :prompt "Group Replace: "
214 :help "Target string"
215 :default *last-search-string*))
216 (replacement (prompt-for-string :prompt "With: "
217 :help "Replacement string")))
218 (do-active-group
219 (query-replace-function nil target replacement
220 "Group Replace on previous file" t))
221 (message "Replacement done in all files in group ~S."
222 *active-file-group-name*)))
223
224(defcommand "Group Query Replace" (p)
225 "Query Replace for the active file group."
226 "Query Replace for the active file group."
227 (declare (ignore p))
228 (let ((target (prompt-for-string :prompt "Group Query Replace: "
229 :help "Target string"
230 :default *last-search-string*)))
231 (let ((replacement (prompt-for-string :prompt "With: "
232 :help "Replacement string")))
233 (do-active-group
234 (unless (query-replace-function
235 nil target replacement "Group Query Replace on previous file")
236 (return nil)))
237 (message "Replacement done in all files in group ~S."
238 *active-file-group-name*))))
Note: See TracBrowser for help on using the repository browser.