Mercurial > hg > xemacs-beta
comparison lisp/utils/forms.el @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | 56c54cf7c5b6 |
children | b9518feda344 |
comparison
equal
deleted
inserted
replaced
69:804d1389bcd6 | 70:131b0175ea99 |
---|---|
1 ;;; forms.el --- Forms mode: edit a file as a form to fill in | 1 ;;; forms.el --- Forms mode: edit a file as a form to fill in. |
2 | 2 |
3 ;; Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. | 3 ;;; Copyright (C) 1991, 1993 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Johan Vromans <jvromans@squirrel.nl> | 5 ;; Author: Johan Vromans <jv@nl.net> |
6 ;; Version: Revision: 2.10 | 6 ;; Version: Revision: 2.10 |
7 ;; Keywords: extensions | 7 ;; Keywords: extensions |
8 ;; hacked on by jwz for XEmacs | 8 ;; hacked on by jwz for XEmacs |
9 | 9 |
10 ;; This file is part of XEmacs. | 10 ;; This file is part of XEmacs. |
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | 18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 ;; General Public License for more details. | 20 ;; General Public License for more details. |
21 | 21 |
22 ;; You should have received a copy of the GNU General Public License | 22 ;; You should have received a copy of the GNU General Public License |
23 ;; along with XEmacs; see the file COPYING. If not, write to the Free | 23 ;; along with XEmacs; see the file COPYING. If not, write to the |
24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | 24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
25 ;; 02111-1307, USA. | 25 ;; Boston, MA 02111-1307, USA. |
26 | 26 |
27 ;;; Synched up with: FSF 19.34. | 27 ;;; Synched up with: FSF 19.28. |
28 | 28 |
29 ;;; Commentary: | 29 ;;; Commentary: |
30 | 30 |
31 ;; Visit a file using a form. | 31 ;;; Visit a file using a form. |
32 ;; | 32 ;;; |
33 ;; === Naming conventions | 33 ;;; === Naming conventions |
34 ;; | 34 ;;; |
35 ;; The names of all variables and functions start with 'forms-'. | 35 ;;; The names of all variables and functions start with 'forms-'. |
36 ;; Names which start with 'forms--' are intended for internal use, and | 36 ;;; Names which start with 'forms--' are intended for internal use, and |
37 ;; should *NOT* be used from the outside. | 37 ;;; should *NOT* be used from the outside. |
38 ;; | 38 ;;; |
39 ;; All variables are buffer-local, to enable multiple forms visits | 39 ;;; All variables are buffer-local, to enable multiple forms visits |
40 ;; simultaneously. | 40 ;;; simultaneously. |
41 ;; Variable `forms--mode-setup' is local to *ALL* buffers, for it | 41 ;;; Variable `forms--mode-setup' is local to *ALL* buffers, for it |
42 ;; controls if forms-mode has been enabled in a buffer. | 42 ;;; controls if forms-mode has been enabled in a buffer. |
43 ;; | 43 ;;; |
44 ;; === How it works === | 44 ;;; === How it works === |
45 ;; | 45 ;;; |
46 ;; Forms mode means visiting a data file which is supposed to consist | 46 ;;; Forms mode means visiting a data file which is supposed to consist |
47 ;; of records each containing a number of fields. The records are | 47 ;;; of records each containing a number of fields. The records are |
48 ;; separated by a newline, the fields are separated by a user-defined | 48 ;;; separated by a newline, the fields are separated by a user-defined |
49 ;; field separator (default: TAB). | 49 ;;; field separater (default: TAB). |
50 ;; When shown, a record is transferred to an Emacs buffer and | 50 ;;; When shown, a record is transferred to an Emacs buffer and |
51 ;; presented using a user-defined form. One record is shown at a | 51 ;;; presented using a user-defined form. One record is shown at a |
52 ;; time. | 52 ;;; time. |
53 ;; | 53 ;;; |
54 ;; Forms mode is a composite mode. It involves two files, and two | 54 ;;; Forms mode is a composite mode. It involves two files, and two |
55 ;; buffers. | 55 ;;; buffers. |
56 ;; The first file, called the control file, defines the name of the | 56 ;;; The first file, called the control file, defines the name of the |
57 ;; data file and the forms format. This file buffer will be used to | 57 ;;; data file and the forms format. This file buffer will be used to |
58 ;; present the forms. | 58 ;;; present the forms. |
59 ;; The second file holds the actual data. The buffer of this file | 59 ;;; The second file holds the actual data. The buffer of this file |
60 ;; will be buried, for it is never accessed directly. | 60 ;;; will be buried, for it is never accessed directly. |
61 ;; | 61 ;;; |
62 ;; Forms mode is invoked using M-x forms-find-file control-file . | 62 ;;; Forms mode is invoked using M-x forms-find-file control-file . |
63 ;; Alternatively `forms-find-file-other-window' can be used. | 63 ;;; Alternativily `forms-find-file-other-window' can be used. |
64 ;; | 64 ;;; |
65 ;; You may also visit the control file, and switch to forms mode by hand | 65 ;;; You may also visit the control file, and switch to forms mode by hand |
66 ;; with M-x forms-mode . | 66 ;;; with M-x forms-mode . |
67 ;; | 67 ;;; |
68 ;; Automatic mode switching is supported if you specify | 68 ;;; Automatic mode switching is supported if you specify |
69 ;; "-*- forms -*-" in the first line of the control file. | 69 ;;; "-*- forms -*-" in the first line of the control file. |
70 ;; | 70 ;;; |
71 ;; The control file is visited, evaluated using `eval-current-buffer', | 71 ;;; The control file is visited, evaluated using `eval-current-buffer', |
72 ;; and should set at least the following variables: | 72 ;;; and should set at least the following variables: |
73 ;; | 73 ;;; |
74 ;; forms-file [string] | 74 ;;; forms-file [string] |
75 ;; The name of the data file. | 75 ;;; The name of the data file. |
76 ;; | 76 ;;; |
77 ;; forms-number-of-fields [integer] | 77 ;;; forms-number-of-fields [integer] |
78 ;; The number of fields in each record. | 78 ;;; The number of fields in each record. |
79 ;; | 79 ;;; |
80 ;; forms-format-list [list] | 80 ;;; forms-format-list [list] |
81 ;; Formatting instructions. | 81 ;;; Formatting instructions. |
82 ;; | 82 ;;; |
83 ;; `forms-format-list' should be a list, each element containing | 83 ;;; `forms-format-list' should be a list, each element containing |
84 ;; | 84 ;;; |
85 ;; - a string, e.g. "hello". The string is inserted in the forms | 85 ;;; - a string, e.g. "hello". The string is inserted in the forms |
86 ;; "as is". | 86 ;;; "as is". |
87 ;; | 87 ;;; |
88 ;; - an integer, denoting a field number. | 88 ;;; - an integer, denoting a field number. |
89 ;; The contents of this field are inserted at this point. | 89 ;;; The contents of this field are inserted at this point. |
90 ;; Fields are numbered starting with number one. | 90 ;;; Fields are numbered starting with number one. |
91 ;; | 91 ;;; |
92 ;; - a function call, e.g. (insert "text"). | 92 ;;; - a function call, e.g. (insert "text"). |
93 ;; This function call is dynamically evaluated and should return a | 93 ;;; This function call is dynamically evaluated and should return a |
94 ;; string. It should *NOT* have side-effects on the forms being | 94 ;;; string. It should *NOT* have side-effects on the forms being |
95 ;; constructed. The current fields are available to the function | 95 ;;; constructed. The current fields are available to the function |
96 ;; in the variable `forms-fields', they should *NOT* be modified. | 96 ;;; in the variable `forms-fields', they should *NOT* be modified. |
97 ;; | 97 ;;; |
98 ;; - a lisp symbol, that must evaluate to one of the above. | 98 ;;; - a lisp symbol, that must evaluate to one of the above. |
99 ;; | 99 ;;; |
100 ;; Optional variables which may be set in the control file: | 100 ;;; Optional variables which may be set in the control file: |
101 ;; | 101 ;;; |
102 ;; forms-field-sep [string, default TAB] | 102 ;;; forms-field-sep [string, default TAB] |
103 ;; The field separator used to separate the | 103 ;;; The field separator used to separate the |
104 ;; fields in the data file. It may be a string. | 104 ;;; fields in the data file. It may be a string. |
105 ;; | 105 ;;; |
106 ;; forms-read-only [bool, default nil] | 106 ;;; forms-read-only [bool, default nil] |
107 ;; Non-nil means that the data file is visited | 107 ;;; Non-nil means that the data file is visited |
108 ;; read-only (view mode) as opposed to edit mode. | 108 ;;; read-only (view mode) as opposed to edit mode. |
109 ;; If no write access to the data file is | 109 ;;; If no write access to the data file is |
110 ;; possible, view mode is enforced. | 110 ;;; possible, view mode is enforced. |
111 ;; | 111 ;;; |
112 ;; forms-check-number-of-fields [bool, default t] | 112 ;;; forms-multi-line [string, default "^K"] |
113 ;; If non-nil, a warning will be issued whenever | 113 ;;; If non-null the records of the data file may |
114 ;; a record is found that does not have the number | 114 ;;; contain fields that can span multiple lines in |
115 ;; of fields specified by `forms-number-of-fields'. | 115 ;;; the form. |
116 ;; | 116 ;;; This variable denotes the separator character |
117 ;; forms-multi-line [string, default "^K"] | 117 ;;; to be used for this purpose. Upon display, all |
118 ;; If non-null the records of the data file may | 118 ;;; occurrencies of this character are translated |
119 ;; contain fields that can span multiple lines in | 119 ;;; to newlines. Upon storage they are translated |
120 ;; the form. | 120 ;;; back to the separator character. |
121 ;; This variable denotes the separator character | 121 ;;; |
122 ;; to be used for this purpose. Upon display, all | 122 ;;; forms-forms-scroll [bool, default nil] |
123 ;; occurrences of this character are translated | 123 ;;; Non-nil means: rebind locally the commands that |
124 ;; to newlines. Upon storage they are translated | 124 ;;; perform `scroll-up' or `scroll-down' to use |
125 ;; back to the separator character. | 125 ;;; `forms-next-field' resp. `forms-prev-field'. |
126 ;; | 126 ;;; |
127 ;; forms-forms-scroll [bool, default nil] | 127 ;;; forms-forms-jump [bool, default nil] |
128 ;; Non-nil means: rebind locally the commands that | 128 ;;; Non-nil means: rebind locally the commands that |
129 ;; perform `scroll-up' or `scroll-down' to use | 129 ;;; perform `beginning-of-buffer' or `end-of-buffer' |
130 ;; `forms-next-field' resp. `forms-prev-field'. | 130 ;;; to perform `forms-first-field' resp. `forms-last-field'. |
131 ;; | 131 ;;; |
132 ;; forms-forms-jump [bool, default nil] | 132 ;;; forms-read-file-filter [symbol, default nil] |
133 ;; Non-nil means: rebind locally the commands that | 133 ;;; If not nil: this should be the name of a |
134 ;; perform `beginning-of-buffer' or `end-of-buffer' | 134 ;;; function that is called after the forms data file |
135 ;; to perform `forms-first-field' and `forms-last-field'. | 135 ;;; has been read. It can be used to transform |
136 ;; | 136 ;;; the contents of the file into a format more suitable |
137 ;; forms-insert-after [bool, default nil] | 137 ;;; for forms-mode processing. |
138 ;; Non-nil means: inserts of new records go after | 138 ;;; |
139 ;; current record, also initial position is at last | 139 ;;; forms-write-file-filter [symbol, default nil] |
140 ;; record. | 140 ;;; If not nil: this should be the name of a |
141 ;; | 141 ;;; function that is called before the forms data file |
142 ;; forms-read-file-filter [symbol, default nil] | 142 ;;; is written (saved) to disk. It can be used to undo |
143 ;; If not nil: this should be the name of a | 143 ;;; the effects of `forms-read-file-filter', if any. |
144 ;; function that is called after the forms data file | 144 ;;; |
145 ;; has been read. It can be used to transform | 145 ;;; forms-new-record-filter [symbol, default nil] |
146 ;; the contents of the file into a format more suitable | 146 ;;; If not nil: this should be the name of a |
147 ;; for forms-mode processing. | 147 ;;; function that is called when a new |
148 ;; | 148 ;;; record is created. It can be used to fill in |
149 ;; forms-write-file-filter [symbol, default nil] | 149 ;;; the new record with default fields, for example. |
150 ;; If not nil: this should be the name of a | 150 ;;; |
151 ;; function that is called before the forms data file | 151 ;;; forms-modified-record-filter [symbol, default nil] |
152 ;; is written (saved) to disk. It can be used to undo | 152 ;;; If not nil: this should be the name of a |
153 ;; the effects of `forms-read-file-filter', if any. | 153 ;;; function that is called when a record has |
154 ;; | 154 ;;; been modified. It is called after the fields |
155 ;; forms-new-record-filter [symbol, default nil] | 155 ;;; are parsed. It can be used to register |
156 ;; If not nil: this should be the name of a | 156 ;;; modification dates, for example. |
157 ;; function that is called when a new | 157 ;;; |
158 ;; record is created. It can be used to fill in | 158 ;;; forms-use-extents [bool, see text for default] |
159 ;; the new record with default fields, for example. | 159 ;;; forms-use-text-properties [bool, see text for default] |
160 ;; | 160 ;;; These variables control if forms mode should use |
161 ;; forms-modified-record-filter [symbol, default nil] | 161 ;;; text properties or extents to protect the form text |
162 ;; If not nil: this should be the name of a | 162 ;;; from being modified (using text-property `read-only'). |
163 ;; function that is called when a record has | 163 ;;; Also, the read-write fields are shown using a |
164 ;; been modified. It is called after the fields | 164 ;;; distinct face, if possible. |
165 ;; are parsed. It can be used to register | 165 ;;; One of these variables defaults to t if running |
166 ;; modification dates, for example. | 166 ;;; FSF or Lucid Emacs 19. |
167 ;; | 167 ;;; |
168 ;; forms-use-extents [bool, see text for default] | 168 ;;; forms-ro-face [symbol, default 'default] |
169 ;; forms-use-text-properties [bool, see text for default] | 169 ;;; This is the face that is used to show |
170 ;; These variables control if forms mode should use | 170 ;;; read-only text on the screen.If used, this |
171 ;; text properties or extents to protect the form text | 171 ;;; variable should be set to a symbol that is a |
172 ;; from being modified (using text-property `read-only'). | 172 ;;; valid face. |
173 ;; Also, the read-write fields are shown using a | 173 ;;; E.g. |
174 ;; distinct face, if possible. | 174 ;;; (make-face 'my-face) |
175 ;; As of emacs 19.29, the `intangible' text property | 175 ;;; (setq forms-ro-face 'my-face) |
176 ;; is used to prevent moving into read-only fields. | 176 ;;; |
177 ;; This variable defaults to t if running Emacs 19 | 177 ;;; forms-rw-face [symbol, default 'region] |
178 ;; with text properties. | 178 ;;; This is the face that is used to show |
179 ;; The default face to show read-write fields is | 179 ;;; read-write text on the screen. |
180 ;; copied from face `region'. | 180 ;;; |
181 ;; | 181 ;;; After evaluating the control file, its buffer is cleared and used |
182 ;; forms-ro-face [symbol, default 'default] | 182 ;;; for further processing. |
183 ;; This is the face that is used to show | 183 ;;; The data file (as designated by `forms-file') is visited in a buffer |
184 ;; read-only text on the screen.If used, this | 184 ;;; `forms--file-buffer' which will not normally be shown. |
185 ;; variable should be set to a symbol that is a | 185 ;;; Great malfunctioning may be expected if this file/buffer is modified |
186 ;; valid face. | 186 ;;; outside of this package while it is being visited! |
187 ;; E.g. | 187 ;;; |
188 ;; (make-face 'my-face) | 188 ;;; Normal operation is to transfer one line (record) from the data file, |
189 ;; (setq forms-ro-face 'my-face) | 189 ;;; split it into fields (into `forms--the-record-list'), and display it |
190 ;; | 190 ;;; using the specs in `forms-format-list'. |
191 ;; forms-rw-face [symbol, default 'region] | 191 ;;; A format routine `forms--format' is built upon startup to format |
192 ;; This is the face that is used to show | 192 ;;; the records according to `forms-format-list'. |
193 ;; read-write text on the screen. | 193 ;;; |
194 ;; | 194 ;;; When a form is changed the record is updated as soon as this form |
195 ;; After evaluating the control file, its buffer is cleared and used | 195 ;;; is left. The contents of the form are parsed using information |
196 ;; for further processing. | 196 ;;; obtained from `forms-format-list', and the fields which are |
197 ;; The data file (as designated by `forms-file') is visited in a buffer | 197 ;;; deduced from the form are modified. Fields not shown on the forms |
198 ;; `forms--file-buffer' which will not normally be shown. | 198 ;;; retain their origional values. The newly formed record then |
199 ;; Great malfunctioning may be expected if this file/buffer is modified | 199 ;;; replaces the contents of the old record in `forms--file-buffer'. |
200 ;; outside of this package while it is being visited! | 200 ;;; A parse routine `forms--parser' is built upon startup to parse |
201 ;; | 201 ;;; the records. |
202 ;; Normal operation is to transfer one line (record) from the data file, | 202 ;;; |
203 ;; split it into fields (into `forms--the-record-list'), and display it | 203 ;;; Two exit functions exist: `forms-exit' and `forms-exit-no-save'. |
204 ;; using the specs in `forms-format-list'. | 204 ;;; `forms-exit' saves the data to the file, if modified. |
205 ;; A format routine `forms--format' is built upon startup to format | 205 ;;; `forms-exit-no-save` does not. However, if `forms-exit-no-save' |
206 ;; the records according to `forms-format-list'. | 206 ;;; is executed and the file buffer has been modified, Emacs will ask |
207 ;; | 207 ;;; questions anyway. |
208 ;; When a form is changed the record is updated as soon as this form | 208 ;;; |
209 ;; is left. The contents of the form are parsed using information | 209 ;;; Other functions provided by forms mode are: |
210 ;; obtained from `forms-format-list', and the fields which are | 210 ;;; |
211 ;; deduced from the form are modified. Fields not shown on the forms | 211 ;;; paging (forward, backward) by record |
212 ;; retain their original values. The newly formed record then | 212 ;;; jumping (first, last, random number) |
213 ;; replaces the contents of the old record in `forms--file-buffer'. | 213 ;;; searching |
214 ;; A parse routine `forms--parser' is built upon startup to parse | 214 ;;; creating and deleting records |
215 ;; the records. | 215 ;;; reverting the form (NOT the file buffer) |
216 ;; | 216 ;;; switching edit <-> view mode v.v. |
217 ;; Two exit functions exist: `forms-exit' and `forms-exit-no-save'. | 217 ;;; jumping from field to field |
218 ;; `forms-exit' saves the data to the file, if modified. | 218 ;;; |
219 ;; `forms-exit-no-save` does not. However, if `forms-exit-no-save' | 219 ;;; As an documented side-effect: jumping to the last record in the |
220 ;; is executed and the file buffer has been modified, Emacs will ask | 220 ;;; file (using forms-last-record) will adjust forms--total-records if |
221 ;; questions anyway. | 221 ;;; needed. |
222 ;; | 222 ;;; |
223 ;; Other functions provided by forms mode are: | 223 ;;; The forms buffer can be in on eof two modes: edit mode or view |
224 ;; | 224 ;;; mode. View mode is a read-only mode, you cannot modify the |
225 ;; paging (forward, backward) by record | 225 ;;; contents of the buffer. |
226 ;; jumping (first, last, random number) | 226 ;;; |
227 ;; searching | 227 ;;; Edit mode commands: |
228 ;; creating and deleting records | 228 ;;; |
229 ;; reverting the form (NOT the file buffer) | 229 ;;; TAB forms-next-field |
230 ;; switching edit <-> view mode v.v. | 230 ;;; \C-c TAB forms-next-field |
231 ;; jumping from field to field | 231 ;;; \C-c < forms-first-record |
232 ;; | 232 ;;; \C-c > forms-last-record |
233 ;; As an documented side-effect: jumping to the last record in the | 233 ;;; \C-c ? describe-mode |
234 ;; file (using forms-last-record) will adjust forms--total-records if | 234 ;;; \C-c \C-k forms-delete-record |
235 ;; needed. | 235 ;;; \C-c \C-q forms-toggle-read-only |
236 ;; | 236 ;;; \C-c \C-o forms-insert-record |
237 ;; The forms buffer can be in on eof two modes: edit mode or view | 237 ;;; \C-c \C-l forms-jump-record |
238 ;; mode. View mode is a read-only mode, you cannot modify the | 238 ;;; \C-c \C-n forms-next-record |
239 ;; contents of the buffer. | 239 ;;; \C-c \C-p forms-prev-record |
240 ;; | 240 ;;; \C-c \C-s forms-search |
241 ;; Edit mode commands: | 241 ;;; \C-c \C-x forms-exit |
242 ;; | 242 ;;; |
243 ;; TAB forms-next-field | 243 ;;; Read-only mode commands: |
244 ;; \C-c TAB forms-next-field | 244 ;;; |
245 ;; \C-c < forms-first-record | 245 ;;; SPC forms-next-record |
246 ;; \C-c > forms-last-record | 246 ;;; DEL forms-prev-record |
247 ;; \C-c ? describe-mode | 247 ;;; ? describe-mode |
248 ;; \C-c \C-k forms-delete-record | 248 ;;; \C-q forms-toggle-read-only |
249 ;; \C-c \C-q forms-toggle-read-only | 249 ;;; l forms-jump-record |
250 ;; \C-c \C-o forms-insert-record | 250 ;;; n forms-next-record |
251 ;; \C-c \C-l forms-jump-record | 251 ;;; p forms-prev-record |
252 ;; \C-c \C-n forms-next-record | 252 ;;; s forms-search |
253 ;; \C-c \C-p forms-prev-record | 253 ;;; x forms-exit |
254 ;; \C-c \C-r forms-search-backward | 254 ;;; |
255 ;; \C-c \C-s forms-search-forward | 255 ;;; Of course, it is also possible to use the \C-c prefix to obtain the |
256 ;; \C-c \C-x forms-exit | 256 ;;; same command keys as in edit mode. |
257 ;; | 257 ;;; |
258 ;; Read-only mode commands: | 258 ;;; The following bindings are available, independent of the mode: |
259 ;; | 259 ;;; |
260 ;; SPC forms-next-record | 260 ;;; [next] forms-next-record |
261 ;; DEL forms-prev-record | 261 ;;; [prior] forms-prev-record |
262 ;; ? describe-mode | 262 ;;; [begin] forms-first-record |
263 ;; \C-q forms-toggle-read-only | 263 ;;; [end] forms-last-record |
264 ;; l forms-jump-record | 264 ;;; [S-TAB] forms-prev-field |
265 ;; n forms-next-record | 265 ;;; [backtab] forms-prev-field |
266 ;; p forms-prev-record | 266 ;;; |
267 ;; r forms-search-backward | 267 ;;; For convenience, TAB is always bound to `forms-next-field', so you |
268 ;; s forms-search-forward | 268 ;;; don't need the C-c prefix for this command. |
269 ;; x forms-exit | 269 ;;; |
270 ;; | 270 ;;; As mentioned above (see `forms-forms-scroll' and `forms-forms-jump') |
271 ;; Of course, it is also possible to use the \C-c prefix to obtain the | 271 ;;; the bindings of standard functions `scroll-up', `scroll-down', |
272 ;; same command keys as in edit mode. | 272 ;;; `beginning-of-buffer' and `end-of-buffer' can be locally replaced with |
273 ;; | 273 ;;; forms mode functions next/prev record and first/last |
274 ;; The following bindings are available, independent of the mode: | 274 ;;; record. |
275 ;; | 275 ;;; |
276 ;; [next] forms-next-record | 276 ;;; `local-write-file hook' is defined to save the actual data file |
277 ;; [prior] forms-prev-record | 277 ;;; instead of the buffer data, `revert-file-hook' is defined to |
278 ;; [begin] forms-first-record | 278 ;;; revert a forms to original. |
279 ;; [end] forms-last-record | |
280 ;; [S-TAB] forms-prev-field | |
281 ;; [backtab] forms-prev-field | |
282 ;; | |
283 ;; For convenience, TAB is always bound to `forms-next-field', so you | |
284 ;; don't need the C-c prefix for this command. | |
285 ;; | |
286 ;; As mentioned above (see `forms-forms-scroll' and `forms-forms-jump') | |
287 ;; the bindings of standard functions `scroll-up', `scroll-down', | |
288 ;; `beginning-of-buffer' and `end-of-buffer' can be locally replaced with | |
289 ;; forms mode functions next/prev record and first/last | |
290 ;; record. | |
291 ;; | |
292 ;; `local-write-file hook' is defined to save the actual data file | |
293 ;; instead of the buffer data, `revert-file-hook' is defined to | |
294 ;; revert a forms to original. | |
295 | 279 |
296 ;;; Code: | 280 ;;; Code: |
297 | 281 |
298 ;;; Global variables and constants: | 282 ;;; Global variables and constants: |
299 | 283 |
300 (provide 'forms) ;;; official | 284 (provide 'forms) ;;; official |
301 (provide 'forms-mode) ;;; for compatibility | 285 (provide 'forms-mode) ;;; for compatibility |
302 | 286 |
303 (defconst forms-version (substring "$Revision: 1.2 $" 11 -2) | 287 (defconst forms-version (substring "!Revision: 2.10 !" 11 -2) |
304 "The version number of forms-mode (as string). The complete RCS id is: | 288 "The version number of forms-mode (as string). The complete RCS id is: |
305 | 289 |
306 $Id: forms.el,v 1.2 1997/08/21 06:24:16 steve Exp $") | 290 !Id: forms.el,v 2.10 1994/07/26 21:31:13 rms Exp !") |
307 | 291 |
308 (defvar forms-mode-hooks nil | 292 (defvar forms-mode-hooks nil |
309 "Hook functions to be run upon entering Forms mode.") | 293 "Hook functions to be run upon entering Forms mode.") |
310 | 294 |
311 ;;; Mandatory variables - must be set by evaluating the control file. | 295 ;;; Mandatory variables - must be set by evaluating the control file. |
319 (defvar forms-number-of-fields nil | 303 (defvar forms-number-of-fields nil |
320 "Number of fields per record.") | 304 "Number of fields per record.") |
321 | 305 |
322 ;;; Optional variables with default values. | 306 ;;; Optional variables with default values. |
323 | 307 |
324 (defvar forms-check-number-of-fields t | |
325 "*If non-nil, warn about records with wrong number of fields.") | |
326 | |
327 (defvar forms-field-sep "\t" | 308 (defvar forms-field-sep "\t" |
328 "Field separator character (default TAB).") | 309 "Field separator character (default TAB).") |
329 | 310 |
330 (defvar forms-read-only nil | 311 (defvar forms-read-only nil |
331 "Non-nil means: visit the file in view (read-only) mode. | 312 "Non-nil means: visit the file in view (read-only) mode. |
365 (defvar forms-use-extents (fboundp 'set-extent-property) ; XEmacs 19.9+ | 346 (defvar forms-use-extents (fboundp 'set-extent-property) ; XEmacs 19.9+ |
366 "*Non-nil means: use XEmacs/Lucid Emacs extents. | 347 "*Non-nil means: use XEmacs/Lucid Emacs extents. |
367 Defaults to t if this emacs is capable of handling text properties.") | 348 Defaults to t if this emacs is capable of handling text properties.") |
368 | 349 |
369 (defvar forms-use-text-properties (and (fboundp 'set-text-properties) | 350 (defvar forms-use-text-properties (and (fboundp 'set-text-properties) |
370 (not forms-use-extents)) ; XEmacs | 351 (not forms-use-extents)) |
371 "*Non-nil means: use emacs-19 text properties. | 352 "*Non-nil means: use emacs-19 text properties. |
372 Defaults to t if this emacs is capable of handling text properties.") | 353 Defaults to t if this emacs is capable of handling text properties.") |
373 | |
374 (defvar forms-insert-after nil | |
375 "*Non-nil means: inserts of new records go after current record. | |
376 Also, initial position is at last record.") | |
377 | 354 |
378 (defvar forms-ro-face (if (string-match "XEmacs" emacs-version) | 355 (defvar forms-ro-face (if (string-match "XEmacs" emacs-version) |
379 'forms-label-face | 356 'forms-label-face |
380 'default) | 357 'default) |
381 "The face (a symbol) that is used to display read-only text on the screen.") | 358 "The face (a symbol) that is used to display read-only text on the screen.") |
413 | 390 |
414 (defvar forms--the-record-list nil | 391 (defvar forms--the-record-list nil |
415 "List of strings of the current record, as parsed from the file.") | 392 "List of strings of the current record, as parsed from the file.") |
416 | 393 |
417 (defvar forms--search-regexp nil | 394 (defvar forms--search-regexp nil |
418 "Last regexp used by forms-search functions.") | 395 "Last regexp used by forms-search.") |
419 | 396 |
420 (defvar forms--format nil | 397 (defvar forms--format nil |
421 "Formatting routine.") | 398 "Formatting routine.") |
422 | 399 |
423 (defvar forms--parser nil | 400 (defvar forms--parser nil |
436 (defvar forms--ro-face nil | 413 (defvar forms--ro-face nil |
437 "Face used to represent read-only data on the screen.") | 414 "Face used to represent read-only data on the screen.") |
438 | 415 |
439 (defvar forms--rw-face nil | 416 (defvar forms--rw-face nil |
440 "Face used to represent read-write data on the screen.") | 417 "Face used to represent read-write data on the screen.") |
418 | |
441 | 419 |
442 ;;;###autoload | 420 ;;;###autoload |
443 (defun forms-mode (&optional primary) | 421 (defun forms-mode (&optional primary) |
444 "Major mode to visit files in a field-structured manner using a form. | 422 "Major mode to visit files in a field-structured manner using a form. |
445 | 423 |
446 Commands: Equivalent keys in read-only mode: | 424 Commands: Equivalent keys in read-only mode: |
447 TAB forms-next-field TAB | 425 |
448 \\C-c TAB forms-next-field | 426 TAB forms-next-field TAB |
449 \\C-c < forms-first-record < | 427 C-c TAB forms-next-field |
450 \\C-c > forms-last-record > | 428 C-c < forms-first-record < |
451 \\C-c ? describe-mode ? | 429 C-c > forms-last-record > |
452 \\C-c \\C-k forms-delete-record | 430 C-c ? describe-mode ? |
453 \\C-c \\C-q forms-toggle-read-only q | 431 C-c C-k forms-delete-record |
454 \\C-c \\C-o forms-insert-record | 432 C-c C-q forms-toggle-read-only q |
455 \\C-c \\C-l forms-jump-record l | 433 C-c C-o forms-insert-record |
456 \\C-c \\C-n forms-next-record n | 434 C-c C-l forms-jump-record l |
457 \\C-c \\C-p forms-prev-record p | 435 C-c C-n forms-next-record n |
458 \\C-c \\C-r forms-search-backward r | 436 C-c C-p forms-prev-record p |
459 \\C-c \\C-s forms-search-forward s | 437 C-c C-s forms-search s |
460 \\C-c \\C-x forms-exit x | 438 C-c C-x forms-exit x" |
461 " | |
462 (interactive) | 439 (interactive) |
463 | 440 |
464 ;; This is not a simple major mode, as usual. Therefore, forms-mode | 441 ;; This is not a simple major mode, as usual. Therefore, forms-mode |
465 ;; takes an optional argument `primary' which is used for the | 442 ;; takes an optional argument `primary' which is used for the |
466 ;; initial set-up. Normal use would leave `primary' to nil. | 443 ;; initial set-up. Normal use would leave `primary' to nil. |
487 (make-local-variable 'forms-field-sep) | 464 (make-local-variable 'forms-field-sep) |
488 (make-local-variable 'forms-read-only) | 465 (make-local-variable 'forms-read-only) |
489 (make-local-variable 'forms-multi-line) | 466 (make-local-variable 'forms-multi-line) |
490 (make-local-variable 'forms-forms-scroll) | 467 (make-local-variable 'forms-forms-scroll) |
491 (make-local-variable 'forms-forms-jump) | 468 (make-local-variable 'forms-forms-jump) |
492 (make-local-variable 'forms-insert-after) | |
493 ;; (make-local-variable 'forms-use-text-properties) | 469 ;; (make-local-variable 'forms-use-text-properties) |
494 | 470 |
495 ;; Filter functions. | 471 ;; Filter functions. |
496 (make-local-variable 'forms-read-file-filter) | 472 (make-local-variable 'forms-read-file-filter) |
497 (make-local-variable 'forms-write-file-filter) | 473 (make-local-variable 'forms-write-file-filter) |
502 (setq forms-read-file-filter nil) | 478 (setq forms-read-file-filter nil) |
503 (setq forms-write-file-filter nil) | 479 (setq forms-write-file-filter nil) |
504 (setq forms-new-record-filter nil) | 480 (setq forms-new-record-filter nil) |
505 (setq forms-modified-record-filter nil) | 481 (setq forms-modified-record-filter nil) |
506 | 482 |
507 (if forms--lemacs-p ; XEmacs | 483 (if forms--lemacs-p |
508 (progn | 484 (progn |
509 ;; forms-field-face defaults to bold. | 485 ;; forms-field-face defaults to bold. |
510 ;; forms-label-face defaults to no attributes | 486 ;; forms-label-face defaults to no attributes |
511 ;; (inherit from default.) | 487 ;; (inherit from default.) |
512 (make-face 'forms-field-face) | 488 (make-face 'forms-field-face) |
600 | 576 |
601 ;; Dynamic text support. | 577 ;; Dynamic text support. |
602 (make-local-variable 'forms--dynamic-text) | 578 (make-local-variable 'forms--dynamic-text) |
603 | 579 |
604 ;; Prevent accidental overwrite of the control file and autosave. | 580 ;; Prevent accidental overwrite of the control file and autosave. |
605 (set-visited-file-name nil) | 581 (setq buffer-file-name nil) |
582 (auto-save-mode nil) | |
606 | 583 |
607 ;; Prepare this buffer for further processing. | 584 ;; Prepare this buffer for further processing. |
608 (setq buffer-read-only nil) | 585 (setq buffer-read-only nil) |
609 (erase-buffer) | 586 (erase-buffer) |
610 | 587 |
642 ;;(message "forms: building keymap...") | 619 ;;(message "forms: building keymap...") |
643 (forms--mode-commands) | 620 (forms--mode-commands) |
644 ;;(message "forms: building keymap... done.") | 621 ;;(message "forms: building keymap... done.") |
645 ) | 622 ) |
646 | 623 |
647 ;; set the major mode indicator | |
648 (setq major-mode 'forms-mode) | |
649 (setq mode-name "Forms") | |
650 | |
651 ;; find the data file | 624 ;; find the data file |
652 (setq forms--file-buffer (find-file-noselect forms-file)) | 625 (setq forms--file-buffer (find-file-noselect forms-file)) |
653 | 626 |
654 ;; Pre-transform. | 627 ;; Pre-transform. |
655 (let ((read-file-filter forms-read-file-filter) | 628 (let ((read-file-filter forms-read-file-filter) |
656 (write-file-filter forms-write-file-filter)) | 629 (write-file-filter forms-write-file-filter)) |
657 (if read-file-filter | 630 (if read-file-filter |
658 (save-excursion | 631 (save-excursion |
659 (set-buffer forms--file-buffer) | 632 (set-buffer forms--file-buffer) |
660 (let ((inhibit-read-only t) | 633 (let ((inhibit-read-only t)) |
661 (file-modified (buffer-modified-p))) | 634 (run-hooks 'read-file-filter)) |
662 (run-hooks 'read-file-filter) | 635 (set-buffer-modified-p nil) |
663 (if (not file-modified) (set-buffer-modified-p nil))) | |
664 (if write-file-filter | 636 (if write-file-filter |
665 (progn | 637 (progn |
666 (make-variable-buffer-local 'local-write-file-hooks) | 638 (make-variable-buffer-local 'local-write-file-hooks) |
667 (setq local-write-file-hooks (list write-file-filter))))) | 639 (setq local-write-file-hooks (list write-file-filter))))) |
668 (if write-file-filter | 640 (if write-file-filter |
669 (save-excursion | 641 (save-excursion |
670 (set-buffer forms--file-buffer) | 642 (set-buffer forms--file-buffer) |
671 (make-variable-buffer-local 'local-write-file-hooks) | 643 (make-variable-buffer-local 'local-write-file-hooks) |
672 ;; (setq local-write-file-hooks (list write-file-filter)))))) | 644 (setq local-write-file-hooks write-file-filter))))) |
673 (add-hook 'local-write-file-hooks 'write-file-filter))))) | |
674 | 645 |
675 ;; count the number of records, and set see if it may be modified | 646 ;; count the number of records, and set see if it may be modified |
676 (let (ro) | 647 (let (ro) |
677 (setq forms--total-records | 648 (setq forms--total-records |
678 (save-excursion | 649 (save-excursion |
687 ))) | 658 ))) |
688 (if ro | 659 (if ro |
689 (setq forms-read-only t))) | 660 (setq forms-read-only t))) |
690 | 661 |
691 ;;(message "forms: proceeding setup...") | 662 ;;(message "forms: proceeding setup...") |
663 ;; set the major mode indicator | |
664 (setq major-mode 'forms-mode) | |
665 (setq mode-name "Forms") | |
692 | 666 |
693 ;; Since we aren't really implementing a minor mode, we hack the modeline | 667 ;; Since we aren't really implementing a minor mode, we hack the modeline |
694 ;; directly to get the text " View " into forms-read-only form buffers. For | 668 ;; directly to get the text " View " into forms-read-only form buffers. For |
695 ;; that reason, this variable must be buffer only. | 669 ;; that reason, this variable must be buffer only. |
696 (make-local-variable 'minor-mode-alist) | 670 (make-local-variable 'minor-mode-alist) |
708 ;;(message "forms: proceeding setup (new file)...") | 682 ;;(message "forms: proceeding setup (new file)...") |
709 (progn | 683 (progn |
710 (insert | 684 (insert |
711 "GNU Emacs Forms Mode version " forms-version "\n\n" | 685 "GNU Emacs Forms Mode version " forms-version "\n\n" |
712 (if (file-exists-p forms-file) | 686 (if (file-exists-p forms-file) |
713 (concat "No records available in file `" forms-file "'\n\n") | 687 (concat "No records available in file \"" forms-file "\".\n\n") |
714 (format "Creating new file `%s'\nwith %d field%s per record\n\n" | 688 (format "Creating new file \"%s\"\nwith %d field%s per record.\n\n" |
715 forms-file forms-number-of-fields | 689 forms-file forms-number-of-fields |
716 (if (= 1 forms-number-of-fields) "" "s"))) | 690 (if (= 1 forms-number-of-fields) "" "s"))) |
717 "Use " (substitute-command-keys "\\[forms-insert-record]") | 691 "Use " (substitute-command-keys "\\[forms-insert-record]") |
718 " to create new records.\n") | 692 " to create new records.\n") |
719 (setq forms--current-record 1) | 693 (setq forms--current-record 1) |
723 ;; setup the first (or current) record to show | 697 ;; setup the first (or current) record to show |
724 (if (< forms--current-record 1) | 698 (if (< forms--current-record 1) |
725 (setq forms--current-record 1)) | 699 (setq forms--current-record 1)) |
726 (forms-jump-record forms--current-record) | 700 (forms-jump-record forms--current-record) |
727 ) | 701 ) |
728 | |
729 (if forms-insert-after | |
730 (forms-last-record) | |
731 (forms-first-record)) | |
732 | 702 |
733 ;; user customising | 703 ;; user customising |
734 ;;(message "forms: proceeding setup (user hooks)...") | 704 ;;(message "forms: proceeding setup (user hooks)...") |
735 (run-hooks 'forms-mode-hooks) | 705 (run-hooks 'forms-mode-hooks) |
736 ;;(message "forms: setting up... done.") | 706 ;;(message "forms: setting up... done.") |
745 ;; concatenated. | 715 ;; concatenated. |
746 ;; Array `forms--elements' is constructed that contains the order | 716 ;; Array `forms--elements' is constructed that contains the order |
747 ;; of the fields on the display. This array is used by | 717 ;; of the fields on the display. This array is used by |
748 ;; `forms--parser-using-text-properties' to extract the fields data | 718 ;; `forms--parser-using-text-properties' to extract the fields data |
749 ;; from the form on the screen. | 719 ;; from the form on the screen. |
750 ;; Upon completion, `forms-format-list' is guaranteed correct, so | 720 ;; Upon completion, `forms-format-list' is garanteed correct, so |
751 ;; `forms--make-format' and `forms--make-parser' do not need to perform | 721 ;; `forms--make-format' and `forms--make-parser' do not need to perform |
752 ;; any checks. | 722 ;; any checks. |
753 | 723 |
754 ;; Verify that `forms-format-list' is not nil. | 724 ;; Verify that `forms-format-list' is not nil. |
755 (or forms-format-list | 725 (or forms-format-list |
817 ((listp el) | 787 ((listp el) |
818 | 788 |
819 ;; Validate. | 789 ;; Validate. |
820 (or (fboundp (car-safe el)) | 790 (or (fboundp (car-safe el)) |
821 (error (concat "Forms format error: " | 791 (error (concat "Forms format error: " |
822 "not a function %S") | 792 "not a function " |
823 (car-safe el))) | 793 (prin1-to-string (car-safe el))))) |
824 | 794 |
825 ;; Shift. | 795 ;; Shift. |
826 (if prev-item | 796 (if prev-item |
827 (setq forms-format-list | 797 (setq forms-format-list |
828 (append forms-format-list (list prev-item) nil))) | 798 (append forms-format-list (list prev-item) nil))) |
829 (setq prev-item el)) | 799 (setq prev-item el)) |
830 | 800 |
831 ;; else | 801 ;; else |
832 (t | 802 (t |
833 (error (concat "Forms format error: " | 803 (error (concat "Forms format error: " |
834 "invalid element %S") | 804 "invalid element " |
835 el))) | 805 (prin1-to-string el))))) |
836 | 806 |
837 ;; Advance to next element of the list. | 807 ;; Advance to next element of the list. |
838 (setq the-list rem))) | 808 (setq the-list rem))) |
839 | 809 |
840 ;; Append last item. | 810 ;; Append last item. |
938 forms-format-list))) | 908 forms-format-list))) |
939 ;; Prevent insertion before the first text. | 909 ;; Prevent insertion before the first text. |
940 (,@ (if (numberp (car forms-format-list)) | 910 (,@ (if (numberp (car forms-format-list)) |
941 nil | 911 nil |
942 '((add-text-properties (point-min) (1+ (point-min)) | 912 '((add-text-properties (point-min) (1+ (point-min)) |
943 '(front-sticky (read-only intangible)))))) | 913 '(front-sticky (read-only)))))) |
944 ;; Prevent insertion after the last text. | 914 ;; Prevent insertion after the last text. |
945 (remove-text-properties (1- (point)) (point) | 915 (remove-text-properties (1- (point)) (point) |
946 '(rear-nonsticky))) | 916 '(rear-nonsticky))) |
947 (setq forms--iif-start nil))) | 917 (setq forms--iif-start nil))) |
948 (if forms-use-extents ; XEmacs version | 918 (if forms-use-extents |
949 (` (lambda (arg) | 919 (` (lambda (arg) |
950 (,@ (apply 'append | 920 (,@ (apply 'append |
951 (mapcar 'forms--make-format-elt-using-extents | 921 (mapcar 'forms--make-format-elt-using-extents |
952 forms-format-list))) | 922 forms-format-list))) |
953 | 923 |
1066 (progn ; until after insertion | 1036 (progn ; until after insertion |
1067 (insert (, el)) | 1037 (insert (, el)) |
1068 (point)) | 1038 (point)) |
1069 (list 'face forms--ro-face ; read-only appearance | 1039 (list 'face forms--ro-face ; read-only appearance |
1070 'read-only (,@ (list (1+ forms--marker))) | 1040 'read-only (,@ (list (1+ forms--marker))) |
1071 'intangible t | |
1072 'insert-in-front-hooks '(forms--iif-hook) | 1041 'insert-in-front-hooks '(forms--iif-hook) |
1073 'rear-nonsticky '(face read-only insert-in-front-hooks | 1042 'rear-nonsticky '(face read-only insert-in-front-hooks)))))) |
1074 intangible)))))) | |
1075 | 1043 |
1076 ((numberp el) | 1044 ((numberp el) |
1077 (` ((let ((here (point))) | 1045 (` ((let ((here (point))) |
1078 (aset forms--markers | 1046 (aset forms--markers |
1079 (, (prog1 forms--marker | 1047 (, (prog1 forms--marker |
1095 (setq forms--dyntext (1+ forms--dyntext)))) | 1063 (setq forms--dyntext (1+ forms--dyntext)))) |
1096 (, el))) | 1064 (, el))) |
1097 (point)) | 1065 (point)) |
1098 (list 'face forms--ro-face | 1066 (list 'face forms--ro-face |
1099 'read-only (,@ (list (1+ forms--marker))) | 1067 'read-only (,@ (list (1+ forms--marker))) |
1100 'intangible t | |
1101 'insert-in-front-hooks '(forms--iif-hook) | 1068 'insert-in-front-hooks '(forms--iif-hook) |
1102 'rear-nonsticky '(read-only face insert-in-front-hooks | 1069 'rear-nonsticky '(read-only face insert-in-front-hooks)))))) |
1103 intangible)))))) | |
1104 | 1070 |
1105 ;; end of cond | 1071 ;; end of cond |
1106 )) | 1072 )) |
1107 | 1073 |
1108 ;; XEmacs | |
1109 (defun forms--make-format-elt-using-extents (el) | 1074 (defun forms--make-format-elt-using-extents (el) |
1110 "Helper routine to generate format function." | 1075 "Helper routine to generate format function." |
1111 | 1076 |
1112 ;; The format routine `forms--format' will look like | 1077 ;; The format routine `forms--format' will look like |
1113 ;; | 1078 ;; |
1271 (if (get-text-property here 'read-only) | 1236 (if (get-text-property here 'read-only) |
1272 (aset forms--recordv (aref forms--elements i) nil) | 1237 (aset forms--recordv (aref forms--elements i) nil) |
1273 (if (setq there | 1238 (if (setq there |
1274 (next-single-property-change here 'read-only)) | 1239 (next-single-property-change here 'read-only)) |
1275 (aset forms--recordv (aref forms--elements i) | 1240 (aset forms--recordv (aref forms--elements i) |
1276 (buffer-substring-no-properties here there)) | 1241 (buffer-substring here there)) |
1277 (aset forms--recordv (aref forms--elements i) | 1242 (aset forms--recordv (aref forms--elements i) |
1278 (buffer-substring-no-properties here (point-max))))) | 1243 (buffer-substring here (point-max))))) |
1279 (setq i (1+ i))))) | 1244 (setq i (1+ i))))) |
1280 | 1245 |
1281 (defun forms--make-parser-elt (el) | 1246 (defun forms--make-parser-elt (el) |
1282 "Helper routine to generate forms parser function." | 1247 "Helper routine to generate forms parser function." |
1283 | 1248 |
1295 ;; ;; 6 | 1260 ;; ;; 6 |
1296 ;; ;; "\nmore text: " | 1261 ;; ;; "\nmore text: " |
1297 ;; (setq here (point)) | 1262 ;; (setq here (point)) |
1298 ;; (if (not (search-forward "\nmore text: " nil t nil)) | 1263 ;; (if (not (search-forward "\nmore text: " nil t nil)) |
1299 ;; (error "Parse error: cannot find \"\\nmore text: \"")) | 1264 ;; (error "Parse error: cannot find \"\\nmore text: \"")) |
1300 ;; (aset forms--recordv 5 (buffer-substring-no-properties here (- (point) 12))) | 1265 ;; (aset forms--recordv 5 (buffer-substring here (- (point) 12))) |
1301 ;; | 1266 ;; |
1302 ;; ;; (tocol 40) | 1267 ;; ;; (tocol 40) |
1303 ;; (let ((forms--dyntext (car-safe forms--dynamic-text))) | 1268 ;; (let ((forms--dyntext (car-safe forms--dynamic-text))) |
1304 ;; (if (not (looking-at (regexp-quote forms--dyntext))) | 1269 ;; (if (not (looking-at (regexp-quote forms--dyntext))) |
1305 ;; (error "Parse error: not looking at \"%s\"" forms--dyntext)) | 1270 ;; (error "Parse error: not looking at \"%s\"" forms--dyntext)) |
1306 ;; (forward-char (length forms--dyntext)) | 1271 ;; (forward-char (length forms--dyntext)) |
1307 ;; (setq forms--dynamic-text (cdr-safe forms--dynamic-text))) | 1272 ;; (setq forms--dynamic-text (cdr-safe forms--dynamic-text))) |
1308 ;; ... | 1273 ;; ... |
1309 ;; ;; final flush (due to terminator sentinel, see below) | 1274 ;; ;; final flush (due to terminator sentinel, see below) |
1310 ;; (aset forms--recordv 7 (buffer-substring-no-properties (point) (point-max))) | 1275 ;; (aset forms--recordv 7 (buffer-substring (point) (point-max))) |
1311 | 1276 |
1312 (cond | 1277 (cond |
1313 ((stringp el) | 1278 ((stringp el) |
1314 (prog1 | 1279 (prog1 |
1315 (if forms--field | 1280 (if forms--field |
1331 (setq forms--field el) | 1296 (setq forms--field el) |
1332 nil)) | 1297 nil)) |
1333 ((null el) | 1298 ((null el) |
1334 (if forms--field | 1299 (if forms--field |
1335 (` ((aset forms--recordv (, (1- forms--field)) | 1300 (` ((aset forms--recordv (, (1- forms--field)) |
1336 (buffer-substring-no-properties (point) (point-max))))))) | 1301 (buffer-substring (point) (point-max))))))) |
1337 ((listp el) | 1302 ((listp el) |
1338 (prog1 | 1303 (prog1 |
1339 (if forms--field | 1304 (if forms--field |
1340 (` ((let ((here (point)) | 1305 (` ((let ((here (point)) |
1341 (forms--dyntext (aref forms--dyntexts (, forms--dyntext)))) | 1306 (forms--dyntext (aref forms--dyntexts (, forms--dyntext)))) |
1342 (if (not (search-forward forms--dyntext nil t nil)) | 1307 (if (not (search-forward forms--dyntext nil t nil)) |
1343 (error "Parse error: cannot find \"%s\"" forms--dyntext)) | 1308 (error "Parse error: cannot find \"%s\"" forms--dyntext)) |
1344 (aset forms--recordv (, (1- forms--field)) | 1309 (aset forms--recordv (, (1- forms--field)) |
1345 (buffer-substring-no-properties here | 1310 (buffer-substring here |
1346 (- (point) (length forms--dyntext))))))) | 1311 (- (point) (length forms--dyntext))))))) |
1347 (` ((let ((forms--dyntext (aref forms--dyntexts (, forms--dyntext)))) | 1312 (` ((let ((forms--dyntext (aref forms--dyntexts (, forms--dyntext)))) |
1348 (if (not (looking-at (regexp-quote forms--dyntext))) | 1313 (if (not (looking-at (regexp-quote forms--dyntext))) |
1349 (error "Parse error: not looking at \"%s\"" forms--dyntext)) | 1314 (error "Parse error: not looking at \"%s\"" forms--dyntext)) |
1350 (forward-char (length forms--dyntext)))))) | 1315 (forward-char (length forms--dyntext)))))) |
1416 (define-key forms-mode-map "\C-q" 'forms-toggle-read-only) | 1381 (define-key forms-mode-map "\C-q" 'forms-toggle-read-only) |
1417 (define-key forms-mode-map "\C-o" 'forms-insert-record) | 1382 (define-key forms-mode-map "\C-o" 'forms-insert-record) |
1418 (define-key forms-mode-map "\C-l" 'forms-jump-record) | 1383 (define-key forms-mode-map "\C-l" 'forms-jump-record) |
1419 (define-key forms-mode-map "\C-n" 'forms-next-record) | 1384 (define-key forms-mode-map "\C-n" 'forms-next-record) |
1420 (define-key forms-mode-map "\C-p" 'forms-prev-record) | 1385 (define-key forms-mode-map "\C-p" 'forms-prev-record) |
1421 (define-key forms-mode-map "\C-r" 'forms-search-backward) | 1386 (define-key forms-mode-map "\C-s" 'forms-search) |
1422 (define-key forms-mode-map "\C-s" 'forms-search-forward) | |
1423 (define-key forms-mode-map "\C-x" 'forms-exit) | 1387 (define-key forms-mode-map "\C-x" 'forms-exit) |
1424 (define-key forms-mode-map "<" 'forms-first-record) | 1388 (define-key forms-mode-map "<" 'forms-first-record) |
1425 (define-key forms-mode-map ">" 'forms-last-record) | 1389 (define-key forms-mode-map ">" 'forms-last-record) |
1426 (define-key forms-mode-map "?" 'describe-mode) ; XEmacs | 1390 (define-key forms-mode-map "?" 'describe-mode) |
1427 (define-key forms-mode-map "\C-?" 'forms-prev-record) | 1391 (define-key forms-mode-map "\C-?" 'forms-prev-record) |
1428 | 1392 |
1429 ;; `forms-mode-ro-map' replaces the local map when in read-only mode. | 1393 ;; `forms-mode-ro-map' replaces the local map when in read-only mode. |
1430 (setq forms-mode-ro-map (make-keymap)) | 1394 (setq forms-mode-ro-map (make-keymap)) |
1431 (suppress-keymap forms-mode-ro-map) | 1395 (suppress-keymap forms-mode-ro-map) |
1433 (define-key forms-mode-ro-map "\t" 'forms-next-field) | 1397 (define-key forms-mode-ro-map "\t" 'forms-next-field) |
1434 (define-key forms-mode-ro-map "q" 'forms-toggle-read-only) | 1398 (define-key forms-mode-ro-map "q" 'forms-toggle-read-only) |
1435 (define-key forms-mode-ro-map "l" 'forms-jump-record) | 1399 (define-key forms-mode-ro-map "l" 'forms-jump-record) |
1436 (define-key forms-mode-ro-map "n" 'forms-next-record) | 1400 (define-key forms-mode-ro-map "n" 'forms-next-record) |
1437 (define-key forms-mode-ro-map "p" 'forms-prev-record) | 1401 (define-key forms-mode-ro-map "p" 'forms-prev-record) |
1438 (define-key forms-mode-ro-map "r" 'forms-search-backward) | 1402 (define-key forms-mode-ro-map "s" 'forms-search) |
1439 (define-key forms-mode-ro-map "s" 'forms-search-forward) | |
1440 (define-key forms-mode-ro-map "x" 'forms-exit) | 1403 (define-key forms-mode-ro-map "x" 'forms-exit) |
1441 (define-key forms-mode-ro-map "<" 'forms-first-record) | 1404 (define-key forms-mode-ro-map "<" 'forms-first-record) |
1442 (define-key forms-mode-ro-map ">" 'forms-last-record) | 1405 (define-key forms-mode-ro-map ">" 'forms-last-record) |
1443 (define-key forms-mode-ro-map "?" 'describe-mode) | 1406 (define-key forms-mode-ro-map "?" 'describe-mode) |
1444 (define-key forms-mode-ro-map " " 'forms-next-record) | 1407 (define-key forms-mode-ro-map " " 'forms-next-record) |
1445 (forms--mode-commands1 forms-mode-ro-map) | 1408 (forms--mode-commands1 forms-mode-ro-map) |
1446 (forms--mode-menu-ro forms-mode-ro-map) | |
1447 | 1409 |
1448 ;; This is the normal, local map. | 1410 ;; This is the normal, local map. |
1449 (setq forms-mode-edit-map (make-keymap)) | 1411 (setq forms-mode-edit-map (make-keymap)) |
1450 (define-key forms-mode-edit-map "\t" 'forms-next-field) | 1412 (define-key forms-mode-edit-map "\t" 'forms-next-field) |
1451 (define-key forms-mode-edit-map "\C-c" forms-mode-map) | 1413 (define-key forms-mode-edit-map "\C-c" forms-mode-map) |
1452 (forms--mode-commands1 forms-mode-edit-map) | 1414 (forms--mode-commands1 forms-mode-edit-map) |
1453 (forms--mode-menu-edit forms-mode-edit-map) | |
1454 ) | 1415 ) |
1455 | 1416 |
1456 (defun forms--mode-menu-ro (map) | 1417 (defun forms--mode-commands1 (map) |
1457 ;;; Menu initialisation | |
1458 ; (define-key map [menu-bar] (make-sparse-keymap)) | |
1459 (define-key map [menu-bar forms] | |
1460 (cons "Forms" (make-sparse-keymap "Forms"))) | |
1461 (define-key map [menu-bar forms menu-forms-exit] | |
1462 '("Exit Forms Mode" . forms-exit)) | |
1463 (define-key map [menu-bar forms menu-forms-sep1] | |
1464 '("----")) | |
1465 (define-key map [menu-bar forms menu-forms-save] | |
1466 '("Save Data" . forms-save-buffer)) | |
1467 (define-key map [menu-bar forms menu-forms-print] | |
1468 '("Print Data" . forms-print)) | |
1469 (define-key map [menu-bar forms menu-forms-describe] | |
1470 '("Describe Mode" . describe-mode)) | |
1471 (define-key map [menu-bar forms menu-forms-toggle-ro] | |
1472 '("Toggle View/Edit" . forms-toggle-read-only)) | |
1473 (define-key map [menu-bar forms menu-forms-jump-record] | |
1474 '("Jump" . forms-jump-record)) | |
1475 (define-key map [menu-bar forms menu-forms-search-backward] | |
1476 '("Search Backward" . forms-search-backward)) | |
1477 (define-key map [menu-bar forms menu-forms-search-forward] | |
1478 '("Search Forward" . forms-search-forward)) | |
1479 (define-key map [menu-bar forms menu-forms-delete-record] | |
1480 '("Delete" . forms-delete-record)) | |
1481 (define-key map [menu-bar forms menu-forms-insert-record] | |
1482 '("Insert" . forms-insert-record)) | |
1483 (define-key map [menu-bar forms menu-forms-sep2] | |
1484 '("----")) | |
1485 (define-key map [menu-bar forms menu-forms-last-record] | |
1486 '("Last Record" . forms-last-record)) | |
1487 (define-key map [menu-bar forms menu-forms-first-record] | |
1488 '("First Record" . forms-first-record)) | |
1489 (define-key map [menu-bar forms menu-forms-prev-record] | |
1490 '("Previous Record" . forms-prev-record)) | |
1491 (define-key map [menu-bar forms menu-forms-next-record] | |
1492 '("Next Record" . forms-next-record)) | |
1493 (define-key map [menu-bar forms menu-forms-sep3] | |
1494 '("----")) | |
1495 (define-key map [menu-bar forms menu-forms-prev-field] | |
1496 '("Previous Field" . forms-prev-field)) | |
1497 (define-key map [menu-bar forms menu-forms-next-field] | |
1498 '("Next Field" . forms-next-field)) | |
1499 (put 'forms-insert-record 'menu-enable '(not forms-read-only)) | |
1500 (put 'forms-delete-record 'menu-enable '(not forms-read-only)) | |
1501 ) | |
1502 (defun forms--mode-menu-edit (map) | |
1503 ;;; Menu initialisation | |
1504 ; (define-key map [menu-bar] (make-sparse-keymap)) | |
1505 (define-key map [menu-bar forms] | |
1506 (cons "Forms" (make-sparse-keymap "Forms"))) | |
1507 (define-key map [menu-bar forms menu-forms-edit--exit] | |
1508 '("Exit" . forms-exit)) | |
1509 (define-key map [menu-bar forms menu-forms-edit-sep1] | |
1510 '("----")) | |
1511 (define-key map [menu-bar forms menu-forms-edit-save] | |
1512 '("Save Data" . forms-save-buffer)) | |
1513 (define-key map [menu-bar forms menu-forms-edit-print] | |
1514 '("Print Data" . forms-print)) | |
1515 (define-key map [menu-bar forms menu-forms-edit-describe] | |
1516 '("Describe Mode" . describe-mode)) | |
1517 (define-key map [menu-bar forms menu-forms-edit-toggle-ro] | |
1518 '("Toggle View/Edit" . forms-toggle-read-only)) | |
1519 (define-key map [menu-bar forms menu-forms-edit-jump-record] | |
1520 '("Jump" . forms-jump-record)) | |
1521 (define-key map [menu-bar forms menu-forms-edit-search-backward] | |
1522 '("Search Backward" . forms-search-backward)) | |
1523 (define-key map [menu-bar forms menu-forms-edit-search-forward] | |
1524 '("Search Forward" . forms-search-forward)) | |
1525 (define-key map [menu-bar forms menu-forms-edit-delete-record] | |
1526 '("Delete" . forms-delete-record)) | |
1527 (define-key map [menu-bar forms menu-forms-edit-insert-record] | |
1528 '("Insert" . forms-insert-record)) | |
1529 (define-key map [menu-bar forms menu-forms-edit-sep2] | |
1530 '("----")) | |
1531 (define-key map [menu-bar forms menu-forms-edit-last-record] | |
1532 '("Last Record" . forms-last-record)) | |
1533 (define-key map [menu-bar forms menu-forms-edit-first-record] | |
1534 '("First Record" . forms-first-record)) | |
1535 (define-key map [menu-bar forms menu-forms-edit-prev-record] | |
1536 '("Previous Record" . forms-prev-record)) | |
1537 (define-key map [menu-bar forms menu-forms-edit-next-record] | |
1538 '("Next Record" . forms-next-record)) | |
1539 (define-key map [menu-bar forms menu-forms-edit-sep3] | |
1540 '("----")) | |
1541 (define-key map [menu-bar forms menu-forms-edit-prev-field] | |
1542 '("Previous Field" . forms-prev-field)) | |
1543 (define-key map [menu-bar forms menu-forms-edit-next-field] | |
1544 '("Next Field" . forms-next-field)) | |
1545 (put 'forms-insert-record 'menu-enable '(not forms-read-only)) | |
1546 (put 'forms-delete-record 'menu-enable '(not forms-read-only)) | |
1547 ) | |
1548 | |
1549 (defun forms--mode-commands1 (map) | |
1550 "Helper routine to define keys." | 1418 "Helper routine to define keys." |
1551 (if forms--lemacs-p ; XEmacs | 1419 (if forms--lemacs-p |
1552 (progn | 1420 (progn |
1553 (define-key map [tab] 'forms-next-field) | 1421 (define-key map [tab] 'forms-next-field) |
1554 (define-key map [(shift tab)] 'forms-prev-field)) | 1422 (define-key map [(shift tab)] 'forms-prev-field)) |
1555 (define-key map [TAB] 'forms-next-field) | 1423 (define-key map [TAB] 'forms-next-field) |
1556 (define-key map [S-tab] 'forms-prev-field)) | 1424 (define-key map [S-tab] 'forms-prev-field)) |
1570 ;; scroll-up -> forms-next-record | 1438 ;; scroll-up -> forms-next-record |
1571 (if forms-forms-scroll | 1439 (if forms-forms-scroll |
1572 (progn | 1440 (progn |
1573 (substitute-key-definition 'scroll-up 'forms-next-record | 1441 (substitute-key-definition 'scroll-up 'forms-next-record |
1574 (current-local-map) | 1442 (current-local-map) |
1575 ;;(current-global-map) ; FSF | 1443 ;;(current-global-map) |
1576 ) | 1444 ) |
1577 (substitute-key-definition 'scroll-down 'forms-prev-record | 1445 (substitute-key-definition 'scroll-down 'forms-prev-record |
1578 (current-local-map) | 1446 (current-local-map) |
1579 ;;(current-global-map) ; FSF | 1447 ;;(current-global-map) |
1580 ))) | 1448 ))) |
1581 ;; | 1449 ;; |
1582 ;; beginning-of-buffer -> forms-first-record | 1450 ;; beginning-of-buffer -> forms-first-record |
1583 ;; end-of-buffer -> forms-end-record | 1451 ;; end-of-buffer -> forms-end-record |
1584 (if forms-forms-jump | 1452 (if forms-forms-jump |
1585 (progn | 1453 (progn |
1586 (substitute-key-definition 'beginning-of-buffer 'forms-first-record | 1454 (substitute-key-definition 'beginning-of-buffer 'forms-first-record |
1587 (current-local-map) | 1455 (current-local-map) |
1588 ;;(current-global-map) ; FSF | 1456 ;;(current-global-map) |
1589 ) | 1457 ) |
1590 (substitute-key-definition 'end-of-buffer 'forms-last-record | 1458 (substitute-key-definition 'end-of-buffer 'forms-last-record |
1591 (current-local-map) | 1459 (current-local-map) |
1592 ;;(current-global-map) ;FSF | 1460 ;;(current-global-map) |
1593 ))) | 1461 ))) |
1594 ;; | 1462 ;; |
1595 ;; Save buffer | 1463 ;; Save buffer |
1596 (local-set-key "\C-x\C-s" 'forms-save-buffer) | 1464 (local-set-key "\C-x\C-s" 'forms-save-buffer) |
1597 ;; | 1465 ;; |
1601 | 1469 |
1602 t) | 1470 t) |
1603 | 1471 |
1604 (defun forms--help () | 1472 (defun forms--help () |
1605 "Initial help for Forms mode." | 1473 "Initial help for Forms mode." |
1606 (message "%s" (substitute-command-keys (concat | 1474 (message (substitute-command-keys (concat |
1607 "\\[forms-next-record]:next" | 1475 "\\[forms-next-record]:next" |
1608 " \\[forms-prev-record]:prev" | 1476 " \\[forms-prev-record]:prev" |
1609 " \\[forms-first-record]:first" | 1477 " \\[forms-first-record]:first" |
1610 " \\[forms-last-record]:last" | 1478 " \\[forms-last-record]:last" |
1611 " \\[describe-mode]:help")))) | 1479 " \\[describe-mode]:help")))) |
1649 (or (bolp) | 1517 (or (bolp) |
1650 (beginning-of-line nil)) | 1518 (beginning-of-line nil)) |
1651 (let ((here (point))) | 1519 (let ((here (point))) |
1652 (prog2 | 1520 (prog2 |
1653 (end-of-line) | 1521 (end-of-line) |
1654 (buffer-substring-no-properties here (point)) | 1522 (buffer-substring here (point)) |
1655 (goto-char here)))) | 1523 (goto-char here)))) |
1656 | 1524 |
1657 (defun forms--show-record (the-record) | 1525 (defun forms--show-record (the-record) |
1658 "Format THE-RECORD and display it in the current buffer." | 1526 "Format THE-RECORD and display it in the current buffer." |
1659 | 1527 |
1675 | 1543 |
1676 (setq buffer-read-only nil) | 1544 (setq buffer-read-only nil) |
1677 (if forms-use-text-properties | 1545 (if forms-use-text-properties |
1678 (let ((inhibit-read-only t)) | 1546 (let ((inhibit-read-only t)) |
1679 (set-text-properties (point-min) (point-max) nil))) | 1547 (set-text-properties (point-min) (point-max) nil))) |
1680 (if forms-use-extents | |
1681 (map-extents '(lambda (x ignore) (detach-extent x) nil))) | |
1682 (erase-buffer) | 1548 (erase-buffer) |
1683 | 1549 |
1684 ;; Verify the number of fields, extend forms--the-record-list if needed. | 1550 ;; Verify the number of fields, extend forms--the-record-list if needed. |
1685 (if (= (length forms--the-record-list) forms-number-of-fields) | 1551 (if (= (length forms--the-record-list) forms-number-of-fields) |
1686 nil | 1552 nil |
1687 (if (null forms-check-number-of-fields) | 1553 (beep) |
1688 nil | 1554 (message "Warning: this record has %d fields instead of %d" |
1689 (beep) | 1555 (length forms--the-record-list) forms-number-of-fields) |
1690 (message "Warning: this record has %d fields instead of %d" | |
1691 (length forms--the-record-list) forms-number-of-fields)) | |
1692 (if (< (length forms--the-record-list) forms-number-of-fields) | 1556 (if (< (length forms--the-record-list) forms-number-of-fields) |
1693 (setq forms--the-record-list | 1557 (setq forms--the-record-list |
1694 (append forms--the-record-list | 1558 (append forms--the-record-list |
1695 (make-list | 1559 (make-list |
1696 (- forms-number-of-fields | 1560 (- forms-number-of-fields |
1704 ;; Prepare. | 1568 ;; Prepare. |
1705 (goto-char (point-min)) | 1569 (goto-char (point-min)) |
1706 (set-buffer-modified-p nil) | 1570 (set-buffer-modified-p nil) |
1707 (setq buffer-read-only forms-read-only) | 1571 (setq buffer-read-only forms-read-only) |
1708 (setq mode-line-process | 1572 (setq mode-line-process |
1709 (concat " " forms--current-record "/" forms--total-records))) | 1573 (format " %d/%d" forms--current-record forms--total-records))) |
1710 | 1574 |
1711 (defun forms--parse-form () | 1575 (defun forms--parse-form () |
1712 "Parse contents of form into list of strings." | 1576 "Parse contents of form into list of strings." |
1713 ;; The contents of the form are parsed, and a new list of strings | 1577 ;; The contents of the form are parsed, and a new list of strings |
1714 ;; is constructed. | 1578 ;; is constructed. |
1895 ;;; Other commands | 1759 ;;; Other commands |
1896 | 1760 |
1897 (defun forms-toggle-read-only (arg) | 1761 (defun forms-toggle-read-only (arg) |
1898 "Toggles read-only mode of a forms mode buffer. | 1762 "Toggles read-only mode of a forms mode buffer. |
1899 With an argument, enables read-only mode if the argument is positive. | 1763 With an argument, enables read-only mode if the argument is positive. |
1900 Otherwise enables edit mode if the visited file is writable." | 1764 Otherwise enables edit mode if the visited file is writeable." |
1901 | 1765 |
1902 (interactive "P") | 1766 (interactive "P") |
1903 | 1767 |
1904 (if (if arg | 1768 (if (if arg |
1905 ;; Negative arg means switch it off. | 1769 ;; Negative arg means switch it off. |
1912 (if (save-excursion | 1776 (if (save-excursion |
1913 (set-buffer forms--file-buffer) | 1777 (set-buffer forms--file-buffer) |
1914 buffer-read-only) | 1778 buffer-read-only) |
1915 (progn | 1779 (progn |
1916 (setq forms-read-only t) | 1780 (setq forms-read-only t) |
1917 (message "No write access to `%s'" forms-file) | 1781 (message "No write access to \"%s\"" forms-file) |
1918 (beep)) | 1782 (beep)) |
1919 (setq forms-read-only nil)) | 1783 (setq forms-read-only nil)) |
1920 (if (equal ro forms-read-only) | 1784 (if (equal ro forms-read-only) |
1921 nil | 1785 nil |
1922 (forms-mode))) | 1786 (forms-mode))) |
1938 | 1802 |
1939 (defun forms-insert-record (arg) | 1803 (defun forms-insert-record (arg) |
1940 "Create a new record before the current one. | 1804 "Create a new record before the current one. |
1941 With ARG: store the record after the current one. | 1805 With ARG: store the record after the current one. |
1942 If `forms-new-record-filter' contains the name of a function, | 1806 If `forms-new-record-filter' contains the name of a function, |
1943 it is called to fill (some of) the fields with default values. | 1807 it is called to fill (some of) the fields with default values." |
1944 If `forms-insert-after is non-nil, the default behavior is to insert | |
1945 after the current record." | |
1946 | 1808 |
1947 (interactive "P") | 1809 (interactive "P") |
1948 | 1810 |
1949 (if forms-read-only | 1811 (if forms-read-only |
1950 (error "")) | 1812 (error "")) |
1951 | 1813 |
1952 (let (ln the-list the-record) | 1814 (let ((ln (if arg (1+ forms--current-record) forms--current-record)) |
1953 | 1815 the-list the-record) |
1954 (if (or (and arg forms-insert-after) | |
1955 (and (not arg) (not forms-insert-after))) | |
1956 (setq ln forms--current-record) | |
1957 (setq ln (1+ forms--current-record))) | |
1958 | 1816 |
1959 (forms--checkmod) | 1817 (forms--checkmod) |
1960 (if forms-new-record-filter | 1818 (if forms-new-record-filter |
1961 ;; As a service to the user, we add a zeroth element so she | 1819 ;; As a service to the user, we add a zeroth element so she |
1962 ;; can use the same indices as in the forms definition. | 1820 ;; can use the same indices as in the forms definition. |
2005 (if (> forms--current-record forms--total-records) | 1863 (if (> forms--current-record forms--total-records) |
2006 (setq forms--current-record forms--total-records)) | 1864 (setq forms--current-record forms--total-records)) |
2007 (forms-jump-record forms--current-record))) | 1865 (forms-jump-record forms--current-record))) |
2008 (message "")) | 1866 (message "")) |
2009 | 1867 |
2010 (defun forms-search-forward (regexp) | 1868 (defun forms-search (regexp) |
2011 "Search forward for record containing REGEXP." | 1869 "Search REGEXP in file buffer." |
2012 (interactive | 1870 (interactive |
2013 (list (read-string (concat "Search forward for" | 1871 (list (read-string (concat "Search for" |
2014 (if forms--search-regexp | 1872 (if forms--search-regexp |
2015 (concat " (" | 1873 (concat " (" |
2016 forms--search-regexp | 1874 forms--search-regexp |
2017 ")")) | 1875 ")")) |
2018 ": ")))) | 1876 ": ")))) |
2027 (setq here (point)) | 1885 (setq here (point)) |
2028 (end-of-line) | 1886 (end-of-line) |
2029 (if (null (re-search-forward regexp nil t)) | 1887 (if (null (re-search-forward regexp nil t)) |
2030 (progn | 1888 (progn |
2031 (goto-char here) | 1889 (goto-char here) |
2032 (message "\"%s\" not found" regexp) | 1890 (message (concat "\"" regexp "\" not found.")) |
2033 nil) | |
2034 (setq the-record (forms--get-record)) | |
2035 (setq the-line (1+ (count-lines (point-min) (point)))))) | |
2036 (progn | |
2037 (setq forms--current-record the-line) | |
2038 (forms--show-record the-record) | |
2039 (re-search-forward regexp nil t)))) | |
2040 (setq forms--search-regexp regexp)) | |
2041 | |
2042 (defun forms-search-backward (regexp) | |
2043 "Search backward for record containing REGEXP." | |
2044 (interactive | |
2045 (list (read-string (concat "Search backward for" | |
2046 (if forms--search-regexp | |
2047 (concat " (" | |
2048 forms--search-regexp | |
2049 ")")) | |
2050 ": ")))) | |
2051 (if (equal "" regexp) | |
2052 (setq regexp forms--search-regexp)) | |
2053 (forms--checkmod) | |
2054 | |
2055 (let (the-line the-record here | |
2056 (fld-sep forms-field-sep)) | |
2057 (if (save-excursion | |
2058 (set-buffer forms--file-buffer) | |
2059 (setq here (point)) | |
2060 (beginning-of-line) | |
2061 (if (null (re-search-backward regexp nil t)) | |
2062 (progn | |
2063 (goto-char here) | |
2064 (message "\"%s\" not found" regexp) | |
2065 nil) | 1891 nil) |
2066 (setq the-record (forms--get-record)) | 1892 (setq the-record (forms--get-record)) |
2067 (setq the-line (1+ (count-lines (point-min) (point)))))) | 1893 (setq the-line (1+ (count-lines (point-min) (point)))))) |
2068 (progn | 1894 (progn |
2069 (setq forms--current-record the-line) | 1895 (setq forms--current-record the-line) |
2101 (interactive "p") | 1927 (interactive "p") |
2102 | 1928 |
2103 (let ((i 0) | 1929 (let ((i 0) |
2104 (here (point)) | 1930 (here (point)) |
2105 there | 1931 there |
2106 (cnt 0) | 1932 (cnt 0)) |
2107 (inhibit-point-motion-hooks t)) | |
2108 | 1933 |
2109 (if (zerop arg) | 1934 (if (zerop arg) |
2110 (setq cnt 1) | 1935 (setq cnt 1) |
2111 (setq cnt (+ cnt arg))) | 1936 (setq cnt (+ cnt arg))) |
2112 | 1937 |
2128 (interactive "p") | 1953 (interactive "p") |
2129 | 1954 |
2130 (let ((i (length forms--markers)) | 1955 (let ((i (length forms--markers)) |
2131 (here (point)) | 1956 (here (point)) |
2132 there | 1957 there |
2133 (cnt 0) | 1958 (cnt 0)) |
2134 (inhibit-point-motion-hooks t)) | |
2135 | 1959 |
2136 (if (zerop arg) | 1960 (if (zerop arg) |
2137 (setq cnt 1) | 1961 (setq cnt 1) |
2138 (setq cnt (+ cnt arg))) | 1962 (setq cnt (+ cnt arg))) |
2139 | 1963 |
2147 (progn | 1971 (progn |
2148 (goto-char there) | 1972 (goto-char there) |
2149 (throw 'done t)))))) | 1973 (throw 'done t)))))) |
2150 nil | 1974 nil |
2151 (goto-char (aref forms--markers (1- (length forms--markers))))))) | 1975 (goto-char (aref forms--markers (1- (length forms--markers))))))) |
2152 | |
2153 (defun forms-print () | |
2154 "Send the records to the printer with 'print-buffer', one record per page." | |
2155 (interactive) | |
2156 (let ((inhibit-read-only t) | |
2157 (save-record forms--current-record) | |
2158 (nb-record 1) | |
2159 (record nil)) | |
2160 (while (<= nb-record forms--total-records) | |
2161 (forms-jump-record nb-record) | |
2162 (setq record (buffer-string)) | |
2163 (save-excursion | |
2164 (set-buffer (get-buffer-create "*forms-print*")) | |
2165 (goto-char (buffer-end 1)) | |
2166 (insert record) | |
2167 (setq buffer-read-only nil) | |
2168 (if (< nb-record forms--total-records) | |
2169 (insert "\n\n"))) | |
2170 (setq nb-record (1+ nb-record))) | |
2171 (save-excursion | |
2172 (set-buffer "*forms-print*") | |
2173 (print-buffer) | |
2174 (set-buffer-modified-p nil) | |
2175 (kill-buffer (current-buffer))) | |
2176 (forms-jump-record save-record))) | |
2177 | |
2178 ;;; | 1976 ;;; |
2179 ;;; Special service | 1977 ;;; Special service |
2180 ;;; | 1978 ;;; |
2181 (defun forms-enumerate (the-fields) | 1979 (defun forms-enumerate (the-fields) |
2182 "Take a quoted list of symbols, and set their values to sequential numbers. | 1980 "Take a quoted list of symbols, and set their values to sequential numbers. |
2183 The first symbol gets number 1, the second 2 and so on. | 1981 The first symbol gets number 1, the second 2 and so on. |
2184 It returns the highest number. | 1982 It returns the higest number. |
2185 | 1983 |
2186 Usage: (setq forms-number-of-fields | 1984 Usage: (setq forms-number-of-fields |
2187 (forms-enumerate | 1985 (forms-enumerate |
2188 '(field1 field2 field2 ...)))" | 1986 '(field1 field2 field2 ...)))" |
2189 | 1987 |