Mercurial > emacs
annotate lisp/forms.el @ 1686:10650dfc82d0
* Makefile.in (install, install.sysv, install.xenix, install.aix):
Install the info files in ${infodir}. Install the executable
under both `emacs' and `emacs-VERSION'.
* Makefile.in: Doc fix.
* Makefile.in (exec_prefix): New variable, as per latest version
of coding standards.
(bindir, libdir): Use it, instead of `prefix'.
(lib-src/Makefile): Edit value of exec_prefix into lib-src/Makefile.
* Makefile.in (mandir): Make the default value for this depend on
$(prefix).
* Makefile.in (datadir, statedir, libdir): Make these all default
to ${prefix}/lib.
(lispdir, locallisppath, etcdir, lockdir, archlibdir): Adjusted
to compensate.
* Makefile.in (install, install.sysv, install.xenix, install.aix):
Install the etags and ctags man pages too.
* Makefile.in (distclean): Don't delete backup files; that's the
job of extraclean.
(extraclean): Like distclean, but deletes backup and autosave files.
Make path specification conform to GNU coding standards.
* configure (long_usage): Remove all traces of old arguments from
usage messages, and document the options we do accept in more
detail: -with-x... and --srcdir.
(options, boolean_opts): Deleted; we don't have enough options to
make this worthwhile.
(prefix, bindir, lisppath, datadir, libdir, lockdir): Deleted,
along with the code which supported them; these should be set as
arguments to the top-level make.
(config_h_opts): Since this no longer doubles as a list of option
names, make them upper case; this simplifies the code which uses
them to build the sed command to edit src/config.h. Change the
code which sets them.
(cc, g, O): Don't allow the user to set these using options; they
should be specified using `CC=' and `CFLAGS=' arguments to the
top-level make. Just choose reasonable default values for them,
and edit them into Makefile.in's default CC and CONFIG_CFLAGS
values.
(gnu_malloc, rel_alloc): Don't allow the user to set these using
options; use them whenever the configuration files say they're
possible.
Simplify the argument processing loop. Don't accept abbreviations
for option names; these might conflict with other configuration
options in the future.
Add some support for the `--srcdir' option. Check for the sources
in . and .. if `--srcdir' is omitted. If the directories we will
compile in don't exist yet, create them under the current directory.
Note that the rest of the build process doesn't really support
this.
Edit only the top Makefile. That should edit the others. Edit
into the makefile: `version', from lisp/version.el, `configname'
and `srcdir' from the configuration arguments, `CC' and
`CONFIG_CFLAGS' as guessed from the presence or absence of GCC in
the user's path, and LOADLIBES as gleaned from the system
description files.
Simplify the report generated; it doesn't need to include any
description of paths now.
Make `config.status' exec configure instead of just calling it, so
there's no harm in overwriting `config.status'.
* Makefile.in (version, configname): New variables, used to choose
the default values for datadir and libdir.
Path variables rearranged into two clearer groups:
- In the first group are the variables specified by the GNU coding
standards (prefix, bindir, datadir, statedir, libdir, mandir,
manext, infodir, and srcdir).
- In the second are the variables actually used for Emacs's paths
(lispdir, locallisppath, lisppath, buildlisppath, etcdir, lockdir,
archlibdir), which depend on the first category.
datadir and libdir default to directories under
${prefix}/lib/emacs instead of ${prefix}/emacs, by popular
demand.
etcdir and lispdir default to subdirectories of datadir.
archlibdir defaults to libdir.
The new installation tree is a bit deeper than it used to be, so
use the new make-path program in lib-src to build them all.
Always build a new src/paths.h.tmp and then move-if-change it to
src/paths.h, to avoid unnecessary rebuilds while responding to the
right changes.
Remove all mention of arch-lib. Run utility commands from
lib-src, and let the executables be copied into archlibdir when
Emacs is installed.
Add targets for src/Makefile, lib-src/Makefile, and
oldXMenu/Makefile, editing the values of the path variables into
them.
Let lib-src do its own installation.
(datadir): Default to putting data files under
${prefix}/lib/emacs/${version}, not /usr/local/emacs.
(emacsdir): Variable deleted; it would only be confusing to use.
(lispdir, etcdir): Default to ${datadir}/lisp.
(mkdir): Use make-path for this.
(lockdir): Do this in mkdir.
(Makefile): New target.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Sat, 12 Dec 1992 15:42:14 +0000 |
parents | 7fede845e304 |
children | 994bb6dc9249 |
rev | line source |
---|---|
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1 ;;; forms.el -- Forms Mode - A GNU Emacs Major Mode |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
2 ;;; SCCS Status : @(#)@ forms 1.2.7 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
3 ;;; Author : Johan Vromans |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
4 ;;; Created On : 1989 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
5 ;;; Last Modified By: Johan Vromans |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
6 ;;; Last Modified On: Mon Jul 1 14:13:20 1991 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
7 ;;; Update Count : 15 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
8 ;;; Status : OK |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
9 |
276 | 10 ;;; This file is part of GNU Emacs. |
11 ;;; GNU Emacs is distributed in the hope that it will be useful, | |
12 ;;; but WITHOUT ANY WARRANTY. No author or distributor | |
13 ;;; accepts responsibility to anyone for the consequences of using it | |
14 ;;; or for whether it serves any particular purpose or works at all, | |
15 ;;; unless he says so in writing. Refer to the GNU Emacs General Public | |
16 ;;; License for full details. | |
17 | |
18 ;;; Everyone is granted permission to copy, modify and redistribute | |
19 ;;; GNU Emacs, but only under the conditions described in the | |
20 ;;; GNU Emacs General Public License. A copy of this license is | |
21 ;;; supposed to have been given to you along with GNU Emacs so you | |
22 ;;; can know your rights and responsibilities. | |
23 ;;; If you don't have this copy, write to the Free Software | |
24 ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
25 ;;; | |
26 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
27 ;;; HISTORY |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
28 ;;; 1-Jul-1991 Johan Vromans |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
29 ;;; Normalized error messages. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
30 ;;; 30-Jun-1991 Johan Vromans |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
31 ;;; Add support for forms-modified-record-filter. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
32 ;;; Allow the filter functions to be the name of a function. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
33 ;;; Fix: parse--format used forms--dynamic-text destructively. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
34 ;;; Internally optimized the forms-format-list. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
35 ;;; Added support for debugging. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
36 ;;; Stripped duplicate documentation. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
37 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
38 ;;; 29-Jun-1991 Johan Vromans |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
39 ;;; Add support for functions and lisp symbols in forms-format-list. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
40 ;;; Add function forms-enumerate. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
41 |
276 | 42 (provide 'forms-mode) |
43 | |
44 ;;; Visit a file using a form. | |
45 ;;; | |
46 ;;; === Naming conventions | |
47 ;;; | |
48 ;;; The names of all variables and functions start with 'form-'. | |
49 ;;; Names which start with 'form--' are intended for internal use, and | |
50 ;;; should *NOT* be used from the outside. | |
51 ;;; | |
52 ;;; All variables are buffer-local, to enable multiple forms visits | |
53 ;;; simultaneously. | |
54 ;;; Variable 'forms--mode-setup' is local to *ALL* buffers, for it | |
55 ;;; controls if forms-mode has been enabled in a buffer. | |
56 ;;; | |
57 ;;; === How it works === | |
58 ;;; | |
59 ;;; Forms mode means visiting a data file which is supposed to consist | |
60 ;;; of records each containing a number of fields. The records are | |
61 ;;; separated by a newline, the fields are separated by a user-defined | |
62 ;;; field separater (default: TAB). | |
63 ;;; When shown, a record is transferred to an emacs buffer and | |
64 ;;; presented using a user-defined form. One record is shown at a | |
65 ;;; time. | |
66 ;;; | |
67 ;;; Forms mode is a composite mode. It involves two files, and two | |
68 ;;; buffers. | |
69 ;;; The first file, called the control file, defines the name of the | |
70 ;;; data file and the forms format. This file buffer will be used to | |
71 ;;; present the forms. | |
72 ;;; The second file holds the actual data. The buffer of this file | |
73 ;;; will be buried, for it is never accessed directly. | |
74 ;;; | |
75 ;;; Forms mode is invoked using "forms-find-file control-file". | |
76 ;;; Alternativily forms-find-file-other-window can be used. | |
77 ;;; | |
78 ;;; You may also visit the control file, and switch to forms mode by hand | |
79 ;;; with M-x forms-mode . | |
80 ;;; | |
81 ;;; Automatic mode switching is supported, so you may use "find-file" | |
82 ;;; if you specify "-*- forms -*-" in the first line of the control file. | |
83 ;;; | |
84 ;;; The control file is visited, evaluated using | |
85 ;;; eval-current-buffer, and should set at least the following | |
86 ;;; variables: | |
87 ;;; | |
88 ;;; forms-file [string] the name of the data file. | |
89 ;;; | |
90 ;;; forms-number-of-fields [integer] | |
91 ;;; The number of fields in each record. | |
92 ;;; | |
93 ;;; forms-format-list [list] formatting instructions. | |
94 ;;; | |
95 ;;; The forms-format-list should be a list, each element containing | |
96 ;;; | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
97 ;;; - a string, e.g. "hello" (which is inserted \"as is\"), |
276 | 98 ;;; |
99 ;;; - an integer, denoting a field number. The contents of the field | |
100 ;;; are inserted at this point. | |
101 ;;; The first field has number one. | |
102 ;;; | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
103 ;;; - a function call, e.g. (insert "text"). This function call is |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
104 ;;; dynamically evaluated and should return a string. It should *NOT* |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
105 ;;; have side-effects on the forms being constructed. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
106 ;;; The current fields are available to the function in the variable |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
107 ;;; forms-fields, they should *NOT* be modified. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
108 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
109 ;;; - a lisp symbol, that must evaluate to one of the above. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
110 ;;; |
276 | 111 ;;; Optional variables which may be set in the control file: |
112 ;;; | |
113 ;;; forms-field-sep [string, default TAB] | |
114 ;;; The field separator used to separate the | |
115 ;;; fields in the data file. It may be a string. | |
116 ;;; | |
117 ;;; forms-read-only [bool, default nil] | |
118 ;;; 't' means that the data file is visited read-only. | |
119 ;;; If no write access to the data file is | |
120 ;;; possible, read-only mode is enforced. | |
121 ;;; | |
122 ;;; forms-multi-line [string, default "^K"] | |
123 ;;; If non-null the records of the data file may | |
124 ;;; contain fields which span multiple lines in | |
125 ;;; the form. | |
126 ;;; This variable denoted the separator character | |
127 ;;; to be used for this purpose. Upon display, all | |
128 ;;; occurrencies of this character are translated | |
129 ;;; to newlines. Upon storage they are translated | |
130 ;;; back to the separator. | |
131 ;;; | |
132 ;;; forms-forms-scroll [bool, default t] | |
133 ;;; If non-nil: redefine scroll-up/down to perform | |
134 ;;; forms-next/prev-field if in forms mode. | |
135 ;;; | |
136 ;;; forms-forms-jump [bool, default t] | |
137 ;;; If non-nil: redefine beginning/end-of-buffer | |
138 ;;; to performs forms-first/last-field if in | |
139 ;;; forms mode. | |
140 ;;; | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
141 ;;; forms-new-record-filter [symbol, no default] |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
142 ;;; If defined: this should be the name of a |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
143 ;;; function that is called when a new |
276 | 144 ;;; record is created. It can be used to fill in |
145 ;;; the new record with default fields, for example. | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
146 ;;; Instead of the name of the function, it may |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
147 ;;; be the function itself. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
148 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
149 ;;; forms-modified-record-filter [symbol, no default] |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
150 ;;; If defined: this should be the name of a |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
151 ;;; function that is called when a record has |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
152 ;;; been modified. It is called after the fields |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
153 ;;; are parsed. It can be used to register |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
154 ;;; modification dates, for example. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
155 ;;; Instead of the name of the function, it may |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
156 ;;; be the function itself. |
276 | 157 ;;; |
158 ;;; After evaluating the control file, its buffer is cleared and used | |
159 ;;; for further processing. | |
160 ;;; The data file (as designated by "forms-file") is visited in a buffer | |
161 ;;; (forms--file-buffer) which will not normally be shown. | |
162 ;;; Great malfunctioning may be expected if this file/buffer is modified | |
163 ;;; outside of this package while it's being visited! | |
164 ;;; | |
165 ;;; A record from the data file is transferred from the data file, | |
166 ;;; split into fields (into forms--the-record-list), and displayed using | |
167 ;;; the specs in forms-format-list. | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
168 ;;; A format routine 'forms--format' is built upon startup to format |
276 | 169 ;;; the records. |
170 ;;; | |
171 ;;; When a form is changed the record is updated as soon as this form | |
172 ;;; is left. The contents of the form are parsed using forms-format-list, | |
173 ;;; and the fields which are deduced from the form are modified. So, | |
174 ;;; fields not shown on the forms retain their origional values. | |
175 ;;; The newly formed record and replaces the contents of the | |
176 ;;; old record in forms--file-buffer. | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
177 ;;; A parse routine 'forms--parser' is built upon startup to parse |
276 | 178 ;;; the records. |
179 ;;; | |
180 ;;; Two exit functions exist: forms-exit (which saves) and forms-exit-no-save | |
181 ;;; (which doesn't). However, if forms-exit-no-save is executed and the file | |
182 ;;; buffer has been modified, emacs will ask questions. | |
183 ;;; | |
184 ;;; Other functions are: | |
185 ;;; | |
186 ;;; paging (forward, backward) by record | |
187 ;;; jumping (first, last, random number) | |
188 ;;; searching | |
189 ;;; creating and deleting records | |
190 ;;; reverting the form (NOT the file buffer) | |
191 ;;; switching edit <-> view mode v.v. | |
192 ;;; jumping from field to field | |
193 ;;; | |
194 ;;; As an documented side-effect: jumping to the last record in the | |
195 ;;; file (using forms-last-record) will adjust forms--total-records if | |
196 ;;; needed. | |
197 ;;; | |
198 ;;; Commands and keymaps: | |
199 ;;; | |
200 ;;; A local keymap 'forms-mode-map' is used in the forms buffer. | |
201 ;;; As conventional, this map can be accessed with C-c prefix. | |
202 ;;; In read-only mode, the C-c prefix must be omitted. | |
203 ;;; | |
204 ;;; Default bindings: | |
205 ;;; | |
206 ;;; \C-c forms-mode-map | |
207 ;;; TAB forms-next-field | |
208 ;;; SPC forms-next-record | |
209 ;;; < forms-first-record | |
210 ;;; > forms-last-record | |
211 ;;; ? describe-mode | |
212 ;;; d forms-delete-record | |
213 ;;; e forms-edit-mode | |
214 ;;; i forms-insert-record | |
215 ;;; j forms-jump-record | |
216 ;;; n forms-next-record | |
217 ;;; p forms-prev-record | |
218 ;;; q forms-exit | |
219 ;;; s forms-search | |
220 ;;; v forms-view-mode | |
221 ;;; x forms-exit-no-save | |
222 ;;; DEL forms-prev-record | |
223 ;;; | |
224 ;;; Standard functions scroll-up, scroll-down, beginning-of-buffer and | |
225 ;;; end-of-buffer are wrapped with re-definitions, which map them to | |
226 ;;; next/prev record and first/last record. | |
227 ;;; Buffer-local variables forms-forms-scroll and forms-forms-jump | |
228 ;;; may be used to control these redefinitions. | |
229 ;;; | |
230 ;;; Function save-buffer is also wrapped to perform a sensible action. | |
231 ;;; A revert-file-hook is defined to revert a forms to original. | |
232 ;;; | |
233 ;;; For convenience, TAB is always bound to forms-next-field, so you | |
234 ;;; don't need the C-c prefix for this command. | |
235 ;;; | |
236 ;;; Global variables and constants | |
237 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
238 (defconst forms-version "1.2.7" |
276 | 239 "Version of forms-mode implementation") |
240 | |
241 (defvar forms-forms-scrolls t | |
242 "If non-null: redefine scroll-up/down to be used with forms-mode.") | |
243 | |
244 (defvar forms-forms-jumps t | |
245 "If non-null: redefine beginning/end-of-buffer to be used with forms-mode.") | |
246 | |
247 (defvar forms-mode-hooks nil | |
248 "Hook functions to be run upon entering forms mode.") | |
249 ;;; | |
250 ;;; Mandatory variables - must be set by evaluating the control file | |
251 | |
252 (defvar forms-file nil | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
253 "Name of the file holding the data.") |
276 | 254 |
255 (defvar forms-format-list nil | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
256 "List of formatting specifications.") |
276 | 257 |
258 (defvar forms-number-of-fields nil | |
259 "Number of fields per record.") | |
260 | |
261 ;;; | |
262 ;;; Optional variables with default values | |
263 | |
264 (defvar forms-field-sep "\t" | |
265 "Field separator character (default TAB)") | |
266 | |
267 (defvar forms-read-only nil | |
268 "Read-only mode (defaults to the write access on the data file).") | |
269 | |
270 (defvar forms-multi-line "\C-k" | |
271 "Character to separate multi-line fields (default ^K)") | |
272 | |
273 (defvar forms-forms-scroll t | |
274 "Redefine scroll-up/down to perform forms-next/prev-record when in | |
275 forms mode.") | |
276 | |
277 (defvar forms-forms-jump t | |
278 "Redefine beginning/end-of-buffer to perform forms-first/last-record | |
279 when in forms mode.") | |
280 | |
281 ;;; | |
282 ;;; Internal variables. | |
283 | |
284 (defvar forms--file-buffer nil | |
285 "Buffer which holds the file data") | |
286 | |
287 (defvar forms--total-records 0 | |
288 "Total number of records in the data file.") | |
289 | |
290 (defvar forms--current-record 0 | |
291 "Number of the record currently on the screen.") | |
292 | |
293 (defvar forms-mode-map nil ; yes - this one is global | |
294 "Keymap for form buffer.") | |
295 | |
296 (defvar forms--markers nil | |
297 "Field markers in the screen.") | |
298 | |
299 (defvar forms--number-of-markers 0 | |
300 "Number of fields on screen.") | |
301 | |
302 (defvar forms--the-record-list nil | |
303 "List of strings of the current record, as parsed from the file.") | |
304 | |
305 (defvar forms--search-regexp nil | |
306 "Last regexp used by forms-search.") | |
307 | |
308 (defvar forms--format nil | |
309 "Formatting routine.") | |
310 | |
311 (defvar forms--parser nil | |
312 "Forms parser routine.") | |
313 | |
314 (defvar forms--mode-setup nil | |
315 "Internal - keeps track of forms-mode being set-up.") | |
316 (make-variable-buffer-local 'forms--mode-setup) | |
317 | |
318 (defvar forms--new-record-filter nil | |
319 "Internal - set if a new record filter has been defined.") | |
320 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
321 (defvar forms--modified-record-filter nil |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
322 "Internal - set if a modified record filter has been defined.") |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
323 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
324 (defvar forms--dynamic-text nil |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
325 "Internal - holds dynamic text to insert between fields.") |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
326 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
327 (defvar forms-fields nil |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
328 "List with fields of the current forms. First field has number 1.") |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
329 |
276 | 330 ;;; |
331 ;;; forms-mode | |
332 ;;; | |
333 ;;; This is not a simple major mode, as usual. Therefore, forms-mode | |
334 ;;; takes an optional argument 'primary' which is used for the initial | |
335 ;;; set-up. Normal use would leave 'primary' to nil. | |
336 ;;; | |
337 ;;; A global buffer-local variable 'forms--mode-setup' has the same effect | |
338 ;;; but makes it possible to auto-invoke forms-mode using find-file. | |
339 ;;; | |
340 ;;; Note: although it seems logical to have (make-local-variable) executed | |
341 ;;; where the variable is first needed, I deliberately placed all calls | |
342 ;;; in the forms-mode function. | |
343 | |
344 (defun forms-mode (&optional primary) | |
345 "Major mode to visit files in a field-structured manner using a form. | |
346 | |
347 Commands (prefix with C-c if not in read-only mode): | |
348 \\{forms-mode-map}" | |
349 | |
350 (interactive) ; no - 'primary' is not prefix arg | |
351 | |
352 ;; Primary set-up: evaluate buffer and check if the mandatory | |
353 ;; variables have been set. | |
354 (if (or primary (not forms--mode-setup)) | |
355 (progn | |
356 (kill-all-local-variables) | |
357 | |
358 ;; make mandatory variables | |
359 (make-local-variable 'forms-file) | |
360 (make-local-variable 'forms-number-of-fields) | |
361 (make-local-variable 'forms-format-list) | |
362 | |
363 ;; make optional variables | |
364 (make-local-variable 'forms-field-sep) | |
365 (make-local-variable 'forms-read-only) | |
366 (make-local-variable 'forms-multi-line) | |
367 (make-local-variable 'forms-forms-scroll) | |
368 (make-local-variable 'forms-forms-jump) | |
369 (fmakunbound 'forms-new-record-filter) | |
370 | |
371 ;; eval the buffer, should set variables | |
372 (eval-current-buffer) | |
373 | |
374 ;; check if the mandatory variables make sense. | |
375 (or forms-file | |
376 (error "'forms-file' has not been set")) | |
377 (or forms-number-of-fields | |
378 (error "'forms-number-of-fields' has not been set")) | |
379 (or (> forms-number-of-fields 0) | |
380 (error "'forms-number-of-fields' must be > 0") | |
381 (or (stringp forms-field-sep)) | |
382 (error "'forms-field-sep' is not a string")) | |
383 (if forms-multi-line | |
384 (if (and (stringp forms-multi-line) | |
385 (eq (length forms-multi-line) 1)) | |
386 (if (string= forms-multi-line forms-field-sep) | |
387 (error "'forms-multi-line' is equal to 'forms-field-sep'")) | |
388 (error "'forms-multi-line' must be nil or a one-character string"))) | |
389 | |
390 ;; validate and process forms-format-list | |
391 (make-local-variable 'forms--number-of-markers) | |
392 (make-local-variable 'forms--markers) | |
393 (forms--process-format-list) | |
394 | |
395 ;; build the formatter and parser | |
396 (make-local-variable 'forms--format) | |
397 (forms--make-format) | |
398 (make-local-variable 'forms--parser) | |
399 (forms--make-parser) | |
400 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
401 ;; check if record filters are defined |
276 | 402 (make-local-variable 'forms--new-record-filter) |
403 (setq forms--new-record-filter | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
404 (cond |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
405 ((fboundp 'forms-new-record-filter) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
406 (symbol-function 'forms-new-record-filter)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
407 ((and (boundp 'forms-new-record-filter) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
408 (fboundp forms-new-record-filter)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
409 forms-new-record-filter))) |
276 | 410 (fmakunbound 'forms-new-record-filter) |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
411 (make-local-variable 'forms--modified-record-filter) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
412 (setq forms--modified-record-filter |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
413 (cond |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
414 ((fboundp 'forms-modified-record-filter) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
415 (symbol-function 'forms-modified-record-filter)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
416 ((and (boundp 'forms-modified-record-filter) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
417 (fboundp forms-modified-record-filter)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
418 forms-modified-record-filter))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
419 (fmakunbound 'forms-modified-record-filter) |
276 | 420 |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
421 ;; dynamic text support |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
422 (make-local-variable 'forms--dynamic-text) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
423 (make-local-variable 'forms-fields) |
276 | 424 |
425 ;; prepare this buffer for further processing | |
426 (setq buffer-read-only nil) | |
427 | |
428 ;; prevent accidental overwrite of the control file and autosave | |
429 (setq buffer-file-name nil) | |
430 (auto-save-mode nil) | |
431 | |
432 ;; and clean it | |
433 (erase-buffer))) | |
434 | |
435 ;; make local variables | |
436 (make-local-variable 'forms--file-buffer) | |
437 (make-local-variable 'forms--total-records) | |
438 (make-local-variable 'forms--current-record) | |
439 (make-local-variable 'forms--the-record-list) | |
440 (make-local-variable 'forms--search-rexexp) | |
441 | |
442 ;; A bug in the current Emacs release prevents a keymap | |
443 ;; which is buffer-local from being used by 'describe-mode'. | |
444 ;; Hence we'll leave it global. | |
445 ;;(make-local-variable 'forms-mode-map) | |
446 (if forms-mode-map ; already defined | |
447 nil | |
448 (setq forms-mode-map (make-keymap)) | |
449 (forms--mode-commands forms-mode-map) | |
450 (forms--change-commands)) | |
451 | |
452 ;; find the data file | |
453 (setq forms--file-buffer (find-file-noselect forms-file)) | |
454 | |
455 ;; count the number of records, and set see if it may be modified | |
456 (let (ro) | |
457 (setq forms--total-records | |
458 (save-excursion | |
459 (set-buffer forms--file-buffer) | |
460 (bury-buffer (current-buffer)) | |
461 (setq ro buffer-read-only) | |
462 (count-lines (point-min) (point-max)))) | |
463 (if ro | |
464 (setq forms-read-only t))) | |
465 | |
466 ;; set the major mode indicator | |
467 (setq major-mode 'forms-mode) | |
468 (setq mode-name "Forms") | |
469 (make-local-variable 'minor-mode-alist) ; needed? | |
470 (forms--set-minor-mode) | |
471 (forms--set-keymaps) | |
472 | |
473 (set-buffer-modified-p nil) | |
474 | |
475 ;; We have our own revert function - use it | |
476 (make-local-variable 'revert-buffer-function) | |
477 (setq revert-buffer-function 'forms-revert-buffer) | |
478 | |
479 ;; setup the first (or current) record to show | |
480 (if (< forms--current-record 1) | |
481 (setq forms--current-record 1)) | |
482 (forms-jump-record forms--current-record) | |
483 | |
484 ;; user customising | |
485 (run-hooks 'forms-mode-hooks) | |
486 | |
487 ;; be helpful | |
488 (forms--help) | |
489 | |
490 ;; initialization done | |
491 (setq forms--mode-setup t)) | |
492 | |
493 ;;; | |
494 ;;; forms-process-format-list | |
495 ;;; | |
496 ;;; Validates forms-format-list. | |
497 ;;; | |
498 ;;; Sets forms--number-of-markers and forms--markers. | |
499 | |
500 (defun forms--process-format-list () | |
501 "Validate forms-format-list and set some global variables." | |
502 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
503 (forms--debug "forms-forms-list before 1st pass:\n" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
504 'forms-format-list) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
505 |
276 | 506 ;; it must be non-nil |
507 (or forms-format-list | |
508 (error "'forms-format-list' has not been set")) | |
509 ;; it must be a list ... | |
510 (or (listp forms-format-list) | |
511 (error "'forms-format-list' is not a list")) | |
512 | |
513 (setq forms--number-of-markers 0) | |
514 | |
515 (let ((the-list forms-format-list) ; the list of format elements | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
516 (this-item 0) ; element in list |
276 | 517 (field-num 0)) ; highest field number |
518 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
519 (setq forms-format-list nil) ; gonna rebuild |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
520 |
276 | 521 (while the-list |
522 | |
523 (let ((el (car-safe the-list)) | |
524 (rem (cdr-safe the-list))) | |
525 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
526 ;; if it is a symbol, eval it first |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
527 (if (and (symbolp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
528 (boundp el)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
529 (setq el (eval el))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
530 |
276 | 531 (cond |
532 | |
533 ;; try string ... | |
534 ((stringp el)) ; string is OK | |
535 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
536 ;; try numeric ... |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
537 ((numberp el) |
276 | 538 |
539 (if (or (<= el 0) | |
540 (> el forms-number-of-fields)) | |
541 (error | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
542 "Forms error: field number %d out of range 1..%d" |
276 | 543 el forms-number-of-fields)) |
544 | |
545 (setq forms--number-of-markers (1+ forms--number-of-markers)) | |
546 (if (> el field-num) | |
547 (setq field-num el))) | |
548 | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
549 ;; try function |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
550 ((listp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
551 (or (fboundp (car-safe el)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
552 (error |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
553 "Forms error: not a function: %s" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
554 (prin1-to-string (car-safe el))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
555 |
276 | 556 ;; else |
557 (t | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
558 (error "Invalid element in 'forms-format-list': %s" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
559 (prin1-to-string el)))) |
276 | 560 |
561 ;; advance to next element of the list | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
562 (setq the-list rem) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
563 (setq forms-format-list |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
564 (append forms-format-list (list el) nil))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
565 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
566 (forms--debug "forms-forms-list after 1st pass:\n" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
567 'forms-format-list) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
568 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
569 ;; concat adjacent strings |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
570 (setq forms-format-list (forms--concat-adjacent forms-format-list)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
571 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
572 (forms--debug "forms-forms-list after 2nd pass:\n" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
573 'forms-format-list |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
574 'forms--number-of-markers) |
276 | 575 |
576 (setq forms--markers (make-vector forms--number-of-markers nil))) | |
577 | |
578 | |
579 ;;; | |
580 ;;; Build the format routine from forms-format-list. | |
581 ;;; | |
582 ;;; The format routine (forms--format) will look like | |
583 ;;; | |
584 ;;; (lambda (arg) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
585 ;;; (setq forms--dynamic-text nil) |
276 | 586 ;;; ;; "text: " |
587 ;;; (insert "text: ") | |
588 ;;; ;; 6 | |
589 ;;; (aset forms--markers 0 (point-marker)) | |
590 ;;; (insert (elt arg 5)) | |
591 ;;; ;; "\nmore text: " | |
592 ;;; (insert "\nmore text: ") | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
593 ;;; ;; (tocol 40) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
594 ;;; (let ((the-dyntext (tocol 40))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
595 ;;; (insert the-dyntext) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
596 ;;; (setq forms--dynamic-text (append forms--dynamic-text |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
597 ;;; (list the-dyntext)))) |
276 | 598 ;;; ;; 9 |
599 ;;; (aset forms--markers 1 (point-marker)) | |
600 ;;; (insert (elt arg 8)) | |
601 ;;; | |
602 ;;; ... ) | |
603 ;;; | |
604 | |
605 (defun forms--make-format () | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
606 "Generate format function for forms" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
607 (setq forms--format (forms--format-maker forms-format-list)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
608 (forms--debug 'forms--format)) |
276 | 609 |
610 (defun forms--format-maker (the-format-list) | |
611 "Returns the parser function for forms" | |
612 (let ((the-marker 0)) | |
613 (` (lambda (arg) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
614 (setq forms--dynamic-text nil) |
276 | 615 (,@ (apply 'append |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
616 (mapcar 'forms--make-format-elt the-format-list))))))) |
276 | 617 |
618 (defun forms--make-format-elt (el) | |
619 (cond ((stringp el) | |
620 (` ((insert (, el))))) | |
621 ((numberp el) | |
622 (prog1 | |
623 (` ((aset forms--markers (, the-marker) (point-marker)) | |
624 (insert (elt arg (, (1- el)))))) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
625 (setq the-marker (1+ the-marker)))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
626 ((listp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
627 (prog1 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
628 (` ((let ((the-dyntext (, el))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
629 (insert the-dyntext) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
630 (setq forms--dynamic-text (append forms--dynamic-text |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
631 (list the-dyntext))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
632 ))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
633 )) |
276 | 634 |
635 | |
636 (defun forms--concat-adjacent (the-list) | |
637 "Concatenate adjacent strings in the-list and return the resulting list" | |
638 (if (consp the-list) | |
639 (let ((the-rest (forms--concat-adjacent (cdr the-list)))) | |
640 (if (and (stringp (car the-list)) (stringp (car the-rest))) | |
641 (cons (concat (car the-list) (car the-rest)) | |
642 (cdr the-rest)) | |
643 (cons (car the-list) the-rest))) | |
644 the-list)) | |
645 ;;; | |
646 ;;; forms--make-parser. | |
647 ;;; | |
648 ;;; Generate parse routine from forms-format-list. | |
649 ;;; | |
650 ;;; The parse routine (forms--parser) will look like (give or take | |
651 ;;; a few " " . | |
652 ;;; | |
653 ;;; (lambda nil | |
654 ;;; (let (here) | |
655 ;;; (goto-char (point-min)) | |
656 ;;; | |
657 ;;; ;; "text: " | |
658 ;;; (if (not (looking-at "text: ")) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
659 ;;; (error "Parse error: cannot find \"text: \"")) |
276 | 660 ;;; (forward-char 6) ; past "text: " |
661 ;;; | |
662 ;;; ;; 6 | |
663 ;;; ;; "\nmore text: " | |
664 ;;; (setq here (point)) | |
665 ;;; (if (not (search-forward "\nmore text: " nil t nil)) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
666 ;;; (error "Parse error: cannot find \"\\nmore text: \"")) |
276 | 667 ;;; (aset the-recordv 5 (buffer-substring here (- (point) 12))) |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
668 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
669 ;;; ;; (tocol 40) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
670 ;;; (let ((the-dyntext (car-safe forms--dynamic-text))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
671 ;;; (if (not (looking-at (regexp-quote the-dyntext))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
672 ;;; (error "Parse error: not looking at \"%s\"" the-dyntext)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
673 ;;; (forward-char (length the-dyntext)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
674 ;;; (setq forms--dynamic-text (cdr-safe forms--dynamic-text))) |
276 | 675 ;;; ... |
676 ;;; ;; final flush (due to terminator sentinel, see below) | |
677 ;;; (aset the-recordv 7 (buffer-substring (point) (point-max))) | |
678 ;;; | |
679 | |
680 (defun forms--make-parser () | |
681 "Generate parser function for forms" | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
682 (setq forms--parser (forms--parser-maker forms-format-list)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
683 (forms--debug 'forms--parser)) |
276 | 684 |
685 (defun forms--parser-maker (the-format-list) | |
686 "Returns the parser function for forms" | |
687 (let ((the-field nil) | |
688 (seen-text nil) | |
689 the--format-list) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
690 ;; add a terminator sentinel |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
691 (setq the--format-list (append the-format-list (list nil))) |
276 | 692 (` (lambda nil |
693 (let (here) | |
694 (goto-char (point-min)) | |
695 (,@ (apply 'append | |
696 (mapcar 'forms--make-parser-elt the--format-list)))))))) | |
697 | |
698 (defun forms--make-parser-elt (el) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
699 (cond |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
700 ((stringp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
701 (prog1 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
702 (if the-field |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
703 (` ((setq here (point)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
704 (if (not (search-forward (, el) nil t nil)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
705 (error "Parse error: cannot find \"%s\"" (, el))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
706 (aset the-recordv (, (1- the-field)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
707 (buffer-substring here |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
708 (- (point) (, (length el))))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
709 (` ((if (not (looking-at (, (regexp-quote el)))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
710 (error "Parse error: not looking at \"%s\"" (, el))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
711 (forward-char (, (length el)))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
712 (setq seen-text t) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
713 (setq the-field nil))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
714 ((numberp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
715 (if the-field |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
716 (error "Cannot parse adjacent fields %d and %d" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
717 the-field el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
718 (setq the-field el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
719 nil)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
720 ((null el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
721 (if the-field |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
722 (` ((aset the-recordv (, (1- the-field)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
723 (buffer-substring (point) (point-max))))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
724 ((listp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
725 (prog1 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
726 (if the-field |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
727 (` ((let ((here (point)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
728 (the-dyntext (car-safe forms--dynamic-text))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
729 (if (not (search-forward the-dyntext nil t nil)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
730 (error "Parse error: cannot find \"%s\"" the-dyntext)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
731 (aset the-recordv (, (1- the-field)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
732 (buffer-substring here |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
733 (- (point) (length the-dyntext)))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
734 (setq forms--dynamic-text (cdr-safe forms--dynamic-text))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
735 (` ((let ((the-dyntext (car-safe forms--dynamic-text))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
736 (if (not (looking-at (regexp-quote the-dyntext))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
737 (error "Parse error: not looking at \"%s\"" the-dyntext)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
738 (forward-char (length the-dyntext)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
739 (setq forms--dynamic-text (cdr-safe forms--dynamic-text)))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
740 (setq seen-text t) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
741 (setq the-field nil))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
742 )) |
276 | 743 ;;; |
744 | |
745 (defun forms--set-minor-mode () | |
746 (setq minor-mode-alist | |
747 (if forms-read-only | |
748 " View" | |
749 nil))) | |
750 | |
751 (defun forms--set-keymaps () | |
752 "Set the keymaps used in this mode." | |
753 | |
754 (if forms-read-only | |
755 (use-local-map forms-mode-map) | |
756 (use-local-map (make-sparse-keymap)) | |
757 (define-key (current-local-map) "\C-c" forms-mode-map) | |
758 (define-key (current-local-map) "\t" 'forms-next-field))) | |
759 | |
760 (defun forms--mode-commands (map) | |
761 "Fill map with all commands." | |
762 (define-key map "\t" 'forms-next-field) | |
763 (define-key map " " 'forms-next-record) | |
764 (define-key map "d" 'forms-delete-record) | |
765 (define-key map "e" 'forms-edit-mode) | |
766 (define-key map "i" 'forms-insert-record) | |
767 (define-key map "j" 'forms-jump-record) | |
768 (define-key map "n" 'forms-next-record) | |
769 (define-key map "p" 'forms-prev-record) | |
770 (define-key map "q" 'forms-exit) | |
771 (define-key map "s" 'forms-search) | |
772 (define-key map "v" 'forms-view-mode) | |
773 (define-key map "x" 'forms-exit-no-save) | |
774 (define-key map "<" 'forms-first-record) | |
775 (define-key map ">" 'forms-last-record) | |
776 (define-key map "?" 'describe-mode) | |
777 (define-key map "\177" 'forms-prev-record) | |
778 ; (define-key map "\C-c" map) | |
779 (define-key map "\e" 'ESC-prefix) | |
780 (define-key map "\C-x" ctl-x-map) | |
781 (define-key map "\C-u" 'universal-argument) | |
782 (define-key map "\C-h" help-map) | |
783 ) | |
784 ;;; | |
785 ;;; Changed functions | |
786 ;;; | |
787 ;;; Emacs (as of 18.55) lacks the functionality of buffer-local | |
788 ;;; funtions. Therefore we save the original meaning of some handy | |
789 ;;; functions, and replace them with a wrapper. | |
790 | |
791 (defun forms--change-commands () | |
792 "Localize some commands." | |
793 ;; | |
794 ;; scroll-down -> forms-prev-record | |
795 ;; | |
796 (if (fboundp 'forms--scroll-down) | |
797 nil | |
798 (fset 'forms--scroll-down (symbol-function 'scroll-down)) | |
799 (fset 'scroll-down | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
800 '(lambda (&optional arg) |
276 | 801 (interactive "P") |
802 (if (and forms--mode-setup | |
803 forms-forms-scroll) | |
804 (forms-prev-record arg) | |
805 (forms--scroll-down arg))))) | |
806 ;; | |
807 ;; scroll-up -> forms-next-record | |
808 ;; | |
809 (if (fboundp 'forms--scroll-up) | |
810 nil | |
811 (fset 'forms--scroll-up (symbol-function 'scroll-up)) | |
812 (fset 'scroll-up | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
813 '(lambda (&optional arg) |
276 | 814 (interactive "P") |
815 (if (and forms--mode-setup | |
816 forms-forms-scroll) | |
817 (forms-next-record arg) | |
818 (forms--scroll-up arg))))) | |
819 ;; | |
820 ;; beginning-of-buffer -> forms-first-record | |
821 ;; | |
822 (if (fboundp 'forms--beginning-of-buffer) | |
823 nil | |
824 (fset 'forms--beginning-of-buffer (symbol-function 'beginning-of-buffer)) | |
825 (fset 'beginning-of-buffer | |
826 '(lambda () | |
827 (interactive) | |
828 (if (and forms--mode-setup | |
829 forms-forms-jump) | |
830 (forms-first-record) | |
831 (forms--beginning-of-buffer))))) | |
832 ;; | |
833 ;; end-of-buffer -> forms-end-record | |
834 ;; | |
835 (if (fboundp 'forms--end-of-buffer) | |
836 nil | |
837 (fset 'forms--end-of-buffer (symbol-function 'end-of-buffer)) | |
838 (fset 'end-of-buffer | |
839 '(lambda () | |
840 (interactive) | |
841 (if (and forms--mode-setup | |
842 forms-forms-jump) | |
843 (forms-last-record) | |
844 (forms--end-of-buffer))))) | |
845 ;; | |
846 ;; save-buffer -> forms--save-buffer | |
847 ;; | |
848 (if (fboundp 'forms--save-buffer) | |
849 nil | |
850 (fset 'forms--save-buffer (symbol-function 'save-buffer)) | |
851 (fset 'save-buffer | |
852 '(lambda (&optional arg) | |
853 (interactive "p") | |
854 (if forms--mode-setup | |
855 (progn | |
856 (forms--checkmod) | |
857 (save-excursion | |
858 (set-buffer forms--file-buffer) | |
859 (forms--save-buffer arg))) | |
860 (forms--save-buffer arg))))) | |
861 ;; | |
862 ) | |
863 | |
864 (defun forms--help () | |
865 "Initial help." | |
866 ;; We should use | |
867 ;;(message (substitute-command-keys (concat | |
868 ;;"\\[forms-next-record]:next" | |
869 ;;" \\[forms-prev-record]:prev" | |
870 ;;" \\[forms-first-record]:first" | |
871 ;;" \\[forms-last-record]:last" | |
872 ;;" \\[describe-mode]:help" | |
873 ;;" \\[forms-exit]:exit"))) | |
874 ;; but it's too slow .... | |
875 (if forms-read-only | |
876 (message "SPC:next DEL:prev <:first >:last ?:help q:exit") | |
877 (message "C-c n:next C-c p:prev C-c <:first C-c >:last C-c ?:help C-c q:exit"))) | |
878 | |
879 (defun forms--trans (subj arg rep) | |
880 "Translate in SUBJ all chars ARG into char REP. ARG and REP should | |
881 be single-char strings." | |
882 (let ((i 0) | |
883 (x (length subj)) | |
884 (re (regexp-quote arg)) | |
885 (k (string-to-char rep))) | |
886 (while (setq i (string-match re subj i)) | |
887 (aset subj i k) | |
888 (setq i (1+ i))))) | |
889 | |
890 (defun forms--exit (query &optional save) | |
891 (let ((buf (buffer-name forms--file-buffer))) | |
892 (forms--checkmod) | |
893 (if (and save | |
894 (buffer-modified-p forms--file-buffer)) | |
895 (save-excursion | |
896 (set-buffer forms--file-buffer) | |
897 (save-buffer))) | |
898 (save-excursion | |
899 (set-buffer forms--file-buffer) | |
900 (delete-auto-save-file-if-necessary) | |
901 (kill-buffer (current-buffer))) | |
902 (if (get-buffer buf) ; not killed??? | |
903 (if save | |
904 (progn | |
905 (beep) | |
906 (message "Problem saving buffers?"))) | |
907 (delete-auto-save-file-if-necessary) | |
908 (kill-buffer (current-buffer))))) | |
909 | |
910 (defun forms--get-record () | |
911 "Fetch the current record from the file buffer." | |
912 ;; | |
913 ;; This function is executed in the context of the forms--file-buffer. | |
914 ;; | |
915 (or (bolp) | |
916 (beginning-of-line nil)) | |
917 (let ((here (point))) | |
918 (prog2 | |
919 (end-of-line) | |
920 (buffer-substring here (point)) | |
921 (goto-char here)))) | |
922 | |
923 (defun forms--show-record (the-record) | |
924 "Format THE-RECORD according to forms-format-list, | |
925 and display it in the current buffer." | |
926 | |
927 ;; split the-record | |
928 (let (the-result | |
929 (start-pos 0) | |
930 found-pos | |
931 (field-sep-length (length forms-field-sep))) | |
932 (if forms-multi-line | |
933 (forms--trans the-record forms-multi-line "\n")) | |
934 ;; add an extra separator (makes splitting easy) | |
935 (setq the-record (concat the-record forms-field-sep)) | |
936 (while (setq found-pos (string-match forms-field-sep the-record start-pos)) | |
937 (let ((ent (substring the-record start-pos found-pos))) | |
938 (setq the-result | |
939 (append the-result (list ent))) | |
940 (setq start-pos (+ field-sep-length found-pos)))) | |
941 (setq forms--the-record-list the-result)) | |
942 | |
943 (setq buffer-read-only nil) | |
944 (erase-buffer) | |
945 | |
946 ;; verify the number of fields, extend forms--the-record-list if needed | |
947 (if (= (length forms--the-record-list) forms-number-of-fields) | |
948 nil | |
949 (beep) | |
950 (message "Record has %d fields instead of %d." | |
951 (length forms--the-record-list) forms-number-of-fields) | |
952 (if (< (length forms--the-record-list) forms-number-of-fields) | |
953 (setq forms--the-record-list | |
954 (append forms--the-record-list | |
955 (make-list | |
956 (- forms-number-of-fields | |
957 (length forms--the-record-list)) | |
958 ""))))) | |
959 | |
960 ;; call the formatter function | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
961 (setq forms-fields (append (list nil) forms--the-record-list nil)) |
276 | 962 (funcall forms--format forms--the-record-list) |
963 | |
964 ;; prepare | |
965 (goto-char (point-min)) | |
966 (set-buffer-modified-p nil) | |
967 (setq buffer-read-only forms-read-only) | |
968 (setq mode-line-process | |
969 (concat " " forms--current-record "/" forms--total-records))) | |
970 | |
971 (defun forms--parse-form () | |
972 "Parse contents of form into list of strings." | |
973 ;; The contents of the form are parsed, and a new list of strings | |
974 ;; is constructed. | |
975 ;; A vector with the strings from the original record is | |
976 ;; constructed, which is updated with the new contents. Therefore | |
977 ;; fields which were not in the form are not modified. | |
978 ;; Finally, the vector is transformed into a list for further processing. | |
979 | |
980 (let (the-recordv) | |
981 | |
982 ;; build the vector | |
983 (setq the-recordv (vconcat forms--the-record-list)) | |
984 | |
985 ;; parse the form and update the vector | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
986 (let ((forms--dynamic-text forms--dynamic-text)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
987 (funcall forms--parser)) |
276 | 988 |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
989 (if forms--modified-record-filter |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
990 ;; As a service to the user, we add a zeroth element so she |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
991 ;; can use the same indices as in the forms definition. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
992 (let ((the-fields (vconcat [nil] the-recordv))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
993 (setq the-fields (funcall forms--modified-record-filter the-fields)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
994 (cdr (append the-fields nil))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
995 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
996 ;; transform to a list and return |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
997 (append the-recordv nil)))) |
276 | 998 |
999 (defun forms--update () | |
1000 "Update current record with contents of form. As a side effect: sets | |
1001 forms--the-record-list ." | |
1002 (if forms-read-only | |
1003 (progn | |
1004 (message "Read-only buffer!") | |
1005 (beep)) | |
1006 | |
1007 (let (the-record) | |
1008 ;; build new record | |
1009 (setq forms--the-record-list (forms--parse-form)) | |
1010 (setq the-record | |
1011 (mapconcat 'identity forms--the-record-list forms-field-sep)) | |
1012 | |
1013 ;; handle multi-line fields, if allowed | |
1014 (if forms-multi-line | |
1015 (forms--trans the-record "\n" forms-multi-line)) | |
1016 | |
1017 ;; a final sanity check before updating | |
1018 (if (string-match "\n" the-record) | |
1019 (progn | |
1020 (message "Multi-line fields in this record - update refused!") | |
1021 (beep)) | |
1022 | |
1023 (save-excursion | |
1024 (set-buffer forms--file-buffer) | |
1025 ;; Insert something before kill-line is called. See kill-line | |
1026 ;; doc. Bugfix provided by Ignatios Souvatzis. | |
1027 (insert "*") | |
1028 (beginning-of-line) | |
1029 (kill-line nil) | |
1030 (insert the-record) | |
1031 (beginning-of-line)))))) | |
1032 | |
1033 (defun forms--checkmod () | |
1034 "Check if this form has been modified, and call forms--update if so." | |
1035 (if (buffer-modified-p nil) | |
1036 (let ((here (point))) | |
1037 (forms--update) | |
1038 (set-buffer-modified-p nil) | |
1039 (goto-char here)))) | |
1040 | |
1041 ;;; | |
1042 ;;; Start and exit | |
1043 (defun forms-find-file (fn) | |
1044 "Visit file FN in forms mode" | |
1045 (interactive "fForms file: ") | |
1046 (find-file-read-only fn) | |
1047 (or forms--mode-setup (forms-mode t))) | |
1048 | |
1049 (defun forms-find-file-other-window (fn) | |
1050 "Visit file FN in form mode in other window" | |
1051 (interactive "fFbrowse file in other window: ") | |
1052 (find-file-other-window fn) | |
1053 (eval-current-buffer) | |
1054 (or forms--mode-setup (forms-mode t))) | |
1055 | |
1056 (defun forms-exit (query) | |
1057 "Normal exit. Modified buffers are saved." | |
1058 (interactive "P") | |
1059 (forms--exit query t)) | |
1060 | |
1061 (defun forms-exit-no-save (query) | |
1062 "Exit without saving buffers." | |
1063 (interactive "P") | |
1064 (forms--exit query nil)) | |
1065 | |
1066 ;;; | |
1067 ;;; Navigating commands | |
1068 | |
1069 (defun forms-next-record (arg) | |
1070 "Advance to the ARGth following record." | |
1071 (interactive "P") | |
1072 (forms-jump-record (+ forms--current-record (prefix-numeric-value arg)) t)) | |
1073 | |
1074 (defun forms-prev-record (arg) | |
1075 "Advance to the ARGth previous record." | |
1076 (interactive "P") | |
1077 (forms-jump-record (- forms--current-record (prefix-numeric-value arg)) t)) | |
1078 | |
1079 (defun forms-jump-record (arg &optional relative) | |
1080 "Jump to a random record." | |
1081 (interactive "NRecord number: ") | |
1082 | |
1083 ;; verify that the record number is within range | |
1084 (if (or (> arg forms--total-records) | |
1085 (<= arg 0)) | |
1086 (progn | |
1087 (beep) | |
1088 ;; don't give the message if just paging | |
1089 (if (not relative) | |
1090 (message "Record number %d out of range 1..%d" | |
1091 arg forms--total-records)) | |
1092 ) | |
1093 | |
1094 ;; flush | |
1095 (forms--checkmod) | |
1096 | |
1097 ;; calculate displacement | |
1098 (let ((disp (- arg forms--current-record)) | |
1099 (cur forms--current-record)) | |
1100 | |
1101 ;; forms--show-record needs it now | |
1102 (setq forms--current-record arg) | |
1103 | |
1104 ;; get the record and show it | |
1105 (forms--show-record | |
1106 (save-excursion | |
1107 (set-buffer forms--file-buffer) | |
1108 (beginning-of-line) | |
1109 | |
1110 ;; move, and adjust the amount if needed (shouldn't happen) | |
1111 (if relative | |
1112 (if (zerop disp) | |
1113 nil | |
1114 (setq cur (+ cur disp (- (forward-line disp))))) | |
1115 (setq cur (+ cur disp (- (goto-line arg))))) | |
1116 | |
1117 (forms--get-record))) | |
1118 | |
1119 ;; this shouldn't happen | |
1120 (if (/= forms--current-record cur) | |
1121 (progn | |
1122 (setq forms--current-record cur) | |
1123 (beep) | |
1124 (message "Stuck at record %d." cur)))))) | |
1125 | |
1126 (defun forms-first-record () | |
1127 "Jump to first record." | |
1128 (interactive) | |
1129 (forms-jump-record 1)) | |
1130 | |
1131 (defun forms-last-record () | |
1132 "Jump to last record. As a side effect: re-calculates the number | |
1133 of records in the data file." | |
1134 (interactive) | |
1135 (let | |
1136 ((numrec | |
1137 (save-excursion | |
1138 (set-buffer forms--file-buffer) | |
1139 (count-lines (point-min) (point-max))))) | |
1140 (if (= numrec forms--total-records) | |
1141 nil | |
1142 (beep) | |
1143 (setq forms--total-records numrec) | |
1144 (message "Number of records reset to %d." forms--total-records))) | |
1145 (forms-jump-record forms--total-records)) | |
1146 | |
1147 ;;; | |
1148 ;;; Other commands | |
1149 (defun forms-view-mode () | |
1150 "Visit buffer read-only." | |
1151 (interactive) | |
1152 (if forms-read-only | |
1153 nil | |
1154 (forms--checkmod) ; sync | |
1155 (setq forms-read-only t) | |
1156 (forms-mode))) | |
1157 | |
1158 (defun forms-edit-mode () | |
1159 "Make form suitable for editing, if possible." | |
1160 (interactive) | |
1161 (let ((ro forms-read-only)) | |
1162 (if (save-excursion | |
1163 (set-buffer forms--file-buffer) | |
1164 buffer-read-only) | |
1165 (progn | |
1166 (setq forms-read-only t) | |
1167 (message "No write access to \"%s\"" forms-file) | |
1168 (beep)) | |
1169 (setq forms-read-only nil)) | |
1170 (if (equal ro forms-read-only) | |
1171 nil | |
1172 (forms-mode)))) | |
1173 | |
1174 ;; Sample: | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1175 ;; (defun my-new-record-filter (the-fields) |
276 | 1176 ;; ;; numbers are relative to 1 |
1177 ;; (aset the-fields 4 (current-time-string)) | |
1178 ;; (aset the-fields 6 (user-login-name)) | |
1179 ;; the-list) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1180 ;; (setq forms-new-record-filter 'my-new-record-filter) |
276 | 1181 |
1182 (defun forms-insert-record (arg) | |
1183 "Create a new record before the current one. With ARG: store the | |
1184 record after the current one. | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1185 If a function forms-new-record-filter is defined, or forms-new-record-filter |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1186 contains the name of a function, it is called to |
276 | 1187 fill (some of) the fields with default values." |
1188 ; The above doc is not true, but for documentary purposes only | |
1189 | |
1190 (interactive "P") | |
1191 | |
1192 (let ((ln (if arg (1+ forms--current-record) forms--current-record)) | |
1193 the-list the-record) | |
1194 | |
1195 (forms--checkmod) | |
1196 (if forms--new-record-filter | |
1197 ;; As a service to the user, we add a zeroth element so she | |
1198 ;; can use the same indices as in the forms definition. | |
1199 (let ((the-fields (make-vector (1+ forms-number-of-fields) ""))) | |
1200 (setq the-fields (funcall forms--new-record-filter the-fields)) | |
1201 (setq the-list (cdr (append the-fields nil)))) | |
1202 (setq the-list (make-list forms-number-of-fields ""))) | |
1203 | |
1204 (setq the-record | |
1205 (mapconcat | |
1206 'identity | |
1207 the-list | |
1208 forms-field-sep)) | |
1209 | |
1210 (save-excursion | |
1211 (set-buffer forms--file-buffer) | |
1212 (goto-line ln) | |
1213 (open-line 1) | |
1214 (insert the-record) | |
1215 (beginning-of-line)) | |
1216 | |
1217 (setq forms--current-record ln)) | |
1218 | |
1219 (setq forms--total-records (1+ forms--total-records)) | |
1220 (forms-jump-record forms--current-record)) | |
1221 | |
1222 (defun forms-delete-record (arg) | |
1223 "Deletes a record. With ARG: don't ask." | |
1224 (interactive "P") | |
1225 (forms--checkmod) | |
1226 (if (or arg | |
1227 (y-or-n-p "Really delete this record? ")) | |
1228 (let ((ln forms--current-record)) | |
1229 (save-excursion | |
1230 (set-buffer forms--file-buffer) | |
1231 (goto-line ln) | |
1232 (kill-line 1)) | |
1233 (setq forms--total-records (1- forms--total-records)) | |
1234 (if (> forms--current-record forms--total-records) | |
1235 (setq forms--current-record forms--total-records)) | |
1236 (forms-jump-record forms--current-record))) | |
1237 (message "")) | |
1238 | |
1239 (defun forms-search (regexp) | |
1240 "Search REGEXP in file buffer." | |
1241 (interactive | |
1242 (list (read-string (concat "Search for" | |
1243 (if forms--search-regexp | |
1244 (concat " (" | |
1245 forms--search-regexp | |
1246 ")")) | |
1247 ": ")))) | |
1248 (if (equal "" regexp) | |
1249 (setq regexp forms--search-regexp)) | |
1250 (forms--checkmod) | |
1251 | |
1252 (let (the-line the-record here | |
1253 (fld-sep forms-field-sep)) | |
1254 (if (save-excursion | |
1255 (set-buffer forms--file-buffer) | |
1256 (setq here (point)) | |
1257 (end-of-line) | |
1258 (if (null (re-search-forward regexp nil t)) | |
1259 (progn | |
1260 (goto-char here) | |
1261 (message (concat "\"" regexp "\" not found.")) | |
1262 nil) | |
1263 (setq the-record (forms--get-record)) | |
1264 (setq the-line (1+ (count-lines (point-min) (point)))))) | |
1265 (progn | |
1266 (setq forms--current-record the-line) | |
1267 (forms--show-record the-record) | |
1268 (re-search-forward regexp nil t)))) | |
1269 (setq forms--search-regexp regexp)) | |
1270 | |
1271 (defun forms-revert-buffer (&optional arg noconfirm) | |
1272 "Reverts current form to un-modified." | |
1273 (interactive "P") | |
1274 (if (or noconfirm | |
1275 (yes-or-no-p "Revert form to unmodified? ")) | |
1276 (progn | |
1277 (set-buffer-modified-p nil) | |
1278 (forms-jump-record forms--current-record)))) | |
1279 | |
1280 (defun forms-next-field (arg) | |
1281 "Jump to ARG-th next field." | |
1282 (interactive "p") | |
1283 | |
1284 (let ((i 0) | |
1285 (here (point)) | |
1286 there | |
1287 (cnt 0)) | |
1288 | |
1289 (if (zerop arg) | |
1290 (setq cnt 1) | |
1291 (setq cnt (+ cnt arg))) | |
1292 | |
1293 (if (catch 'done | |
1294 (while (< i forms--number-of-markers) | |
1295 (if (or (null (setq there (aref forms--markers i))) | |
1296 (<= there here)) | |
1297 nil | |
1298 (if (<= (setq cnt (1- cnt)) 0) | |
1299 (progn | |
1300 (goto-char there) | |
1301 (throw 'done t)))) | |
1302 (setq i (1+ i)))) | |
1303 nil | |
1304 (goto-char (aref forms--markers 0))))) | |
307
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1305 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1306 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1307 ;;; Special service |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1308 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1309 (defun forms-enumerate (the-fields) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1310 "Take a quoted list of symbols, and set their values to the numbers |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1311 1, 2 and so on. Returns the higest number. |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1312 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1313 Usage: (setq forms-number-of-fields |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1314 (forms-enumerate |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1315 '(field1 field2 field2 ...)))" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1316 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1317 (let ((the-index 0)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1318 (while the-fields |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1319 (setq the-index (1+ the-index)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1320 (let ((el (car-safe the-fields))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1321 (setq the-fields (cdr-safe the-fields)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1322 (set el the-index))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1323 the-index)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1324 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1325 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1326 ;;; Debugging |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1327 ;;; |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1328 (defvar forms--debug nil |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1329 "*Enables forms-mode debugging if not nil.") |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1330 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1331 (defun forms--debug (&rest args) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1332 "Internal - debugging routine" |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1333 (if forms--debug |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1334 (let ((ret nil)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1335 (while args |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1336 (let ((el (car-safe args))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1337 (setq args (cdr-safe args)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1338 (if (stringp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1339 (setq ret (concat ret el)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1340 (setq ret (concat ret (prin1-to-string el) " = ")) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1341 (if (boundp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1342 (let ((vel (eval el))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1343 (setq ret (concat ret (prin1-to-string vel) "\n"))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1344 (setq ret (concat ret "<unbound>" "\n"))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1345 (if (fboundp el) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1346 (setq ret (concat ret (prin1-to-string (symbol-function el)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1347 "\n")))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1348 (save-excursion |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1349 (set-buffer (get-buffer-create "*forms-mode debug*")) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1350 (goto-char (point-max)) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1351 (insert ret))))) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1352 |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1353 ;;; Local Variables: |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1354 ;;; eval: (headers) |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1355 ;;; eval: (setq comment-start ";;; ") |
7fede845e304
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
276
diff
changeset
|
1356 ;;; End: |