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