home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume13 / forms.el / part02 < prev    next >
Encoding:
Text File  |  1990-06-15  |  24.3 KB  |  833 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v13i050: Emacs forms mode 1.1 - part 02 of 03
  3. from: jv@mh.nl (Johan Vromans)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 13, Issue 50
  7. Submitted-by: jv@mh.nl (Johan Vromans)
  8. Archive-name: forms.el/part02
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is forms.02 (part 2 of a multipart archive)
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file forms.el continued
  15. #
  16. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  17.  then TOUCH=touch
  18.  else TOUCH=true
  19. fi
  20. if test ! -r shar3_seq_.tmp; then
  21.     echo "Please unpack part 1 first!"
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 2; then
  26.     echo "Please unpack part $Scheck next!"
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < shar3_seq_.tmp || exit 1
  32. echo "x - Continuing file forms.el"
  33. sed 's/^X//' << 'SHAR_EOF' >> forms.el &&
  34. X        (setq the-result
  35. X              (concat the-result
  36. X                  "(aset the-recordv "
  37. X                  (1- pending-field)
  38. X                  " (buffer-substring (point) (point-max))) "))))
  39. X
  40. X      (setq pending-text nil)
  41. X      (setq pending-field el)))
  42. X
  43. X    ;; advance to next element of the list
  44. X    (setq the-list rem)))
  45. X
  46. X    (or (zerop pending-field)
  47. X    (error "forms--make-parser failed - field %d pending" pending-field))
  48. X    (or (null pending-text)
  49. X    (error "forms--make-parser failed - text %s pending"
  50. X           (prin1-to-string pending-text)))
  51. X
  52. X    (setq the-result (concat the-result "))"))
  53. X
  54. X    ;; use the lisp reader to evalute the string to a function
  55. X    (let ((res (read-from-string the-result))
  56. X      (len (length the-result)))
  57. X      ;; has the whole string been parsed?
  58. X      (if (= (cdr res) len)
  59. X      (setq forms--parser (car res))
  60. X    ;; pity
  61. X    (error "forms--make-parser failed at %d [of %d]" (cdr res) len)))))
  62. X
  63. X;;;
  64. X
  65. X(defun forms--set-minor-mode ()
  66. X  (setq minor-mode-alist
  67. X    (if forms-read-only
  68. X        " View"
  69. X      nil)))
  70. X
  71. X(defun forms--set-keymaps ()
  72. X  "Set the keymaps used in this mode."
  73. X
  74. X  (if forms-read-only
  75. X      (use-local-map forms-mode-map)
  76. X    (use-local-map (make-sparse-keymap))
  77. X    (define-key (current-local-map) "\C-c" forms-mode-map)
  78. X    (define-key (current-local-map) "\t"   'forms-next-field)))
  79. X
  80. X(defun forms--mode-commands (map)
  81. X  "Fill map with all commands."
  82. X  (define-key map "\t" 'forms-next-field)
  83. X  (define-key map " " 'forms-next-record)
  84. X  (define-key map "d" 'forms-delete-record)
  85. X  (define-key map "e" 'forms-edit-mode)
  86. X  (define-key map "i" 'forms-insert-record)
  87. X  (define-key map "j" 'forms-jump-record)
  88. X  (define-key map "n" 'forms-next-record)
  89. X  (define-key map "p" 'forms-prev-record)
  90. X  (define-key map "q" 'forms-exit)
  91. X  (define-key map "s" 'forms-search)
  92. X  (define-key map "v" 'forms-view-mode)
  93. X  (define-key map "x" 'forms-exit-no-save)
  94. X  (define-key map "<" 'forms-first-record)
  95. X  (define-key map ">" 'forms-last-record)
  96. X  (define-key map "?" 'describe-mode)
  97. X  (define-key map "\177" 'forms-prev-record)
  98. X ;  (define-key map "\C-c" map)
  99. X  (define-key map "\e" 'ESC-prefix)
  100. X  (define-key map "\C-x" ctl-x-map)
  101. X  (define-key map "\C-u" 'universal-argument)
  102. X  (define-key map "\C-h" help-map)
  103. X  )
  104. X;;;
  105. X;;; Changed functions
  106. X;;;
  107. X;;; Emacs (as of 18.54) lacks the functionality of buffer-local
  108. X;;; funtions. Therefore we save the original meaning of some handy
  109. X;;; functions, and replace them with a wrapper.
  110. X
  111. X(defun forms--change-commands ()
  112. X  "Localize some commands."
  113. X  ;;
  114. X  ;; scroll-down -> forms-prev-record
  115. X  ;;
  116. X  (if (fboundp 'forms--scroll-down)
  117. X      nil
  118. X    (fset 'forms--scroll-down (symbol-function 'scroll-down))
  119. X    (fset 'scroll-down
  120. X      '(lambda (arg) 
  121. X         (interactive "P")
  122. X         (if (and forms--mode-setup
  123. X              forms-forms-scroll)
  124. X         (forms-prev-record arg)
  125. X           (forms--scroll-down arg)))))
  126. X  ;;
  127. X  ;; scroll-up -> forms-next-record
  128. X  ;;
  129. X  (if (fboundp 'forms--scroll-up)
  130. X      nil
  131. X    (fset 'forms--scroll-up   (symbol-function 'scroll-up))
  132. X    (fset 'scroll-up
  133. X      '(lambda (arg) 
  134. X         (interactive "P")
  135. X         (if (and forms--mode-setup
  136. X              forms-forms-scroll)
  137. X         (forms-next-record arg)
  138. X           (forms--scroll-up arg)))))
  139. X  ;;
  140. X  ;; beginning-of-buffer -> forms-first-record
  141. X  ;;
  142. X  (if (fboundp 'forms--beginning-of-buffer)
  143. X      nil
  144. X    (fset 'forms--beginning-of-buffer (symbol-function 'beginning-of-buffer))
  145. X    (fset 'beginning-of-buffer
  146. X      '(lambda ()
  147. X         (interactive)
  148. X         (if (and forms--mode-setup
  149. X              forms-forms-jump)
  150. X         (forms-first-record)
  151. X           (forms--beginning-of-buffer)))))
  152. X  ;;
  153. X  ;; end-of-buffer -> forms-end-record
  154. X  ;;
  155. X  (if (fboundp 'forms--end-of-buffer)
  156. X      nil
  157. X    (fset 'forms--end-of-buffer (symbol-function 'end-of-buffer))
  158. X    (fset 'end-of-buffer
  159. X      '(lambda ()
  160. X         (interactive)
  161. X         (if (and forms--mode-setup
  162. X              forms-forms-jump)
  163. X         (forms-last-record)
  164. X           (forms--end-of-buffer)))))
  165. X  ;;
  166. X  ;; save-buffer -> forms--save-buffer
  167. X  ;;
  168. X  (if (fboundp 'forms--save-buffer)
  169. X      nil
  170. X    (fset 'forms--save-buffer (symbol-function 'save-buffer))
  171. X    (fset 'save-buffer
  172. X      '(lambda (&optional arg)
  173. X         (interactive "P")
  174. X         (if forms--mode-setup
  175. X         (progn
  176. X           (forms--checkmod)
  177. X           (save-excursion
  178. X             (set-buffer forms--file-buffer)
  179. X             (forms--save-buffer arg)))
  180. X           (forms--save-buffer arg)))))
  181. X  ;;
  182. X  )
  183. X
  184. X(defun forms--help ()
  185. X  "Initial help."
  186. X  ;; We should use
  187. X  ;;(message (substitute-command-keys (concat
  188. X  ;;"\\[forms-next-record]:next"
  189. X  ;;"   \\[forms-prev-record]:prev"
  190. X  ;;"   \\[forms-first-record]:first"
  191. X  ;;"   \\[forms-last-record]:last"
  192. X  ;;"   \\[describe-mode]:help"
  193. X  ;;"   \\[forms-exit]:exit")))
  194. X  ;; but it's too slow ....
  195. X  (if forms-read-only
  196. X      (message "SPC:next   DEL:prev   <:first   >:last   ?:help   q:exit")
  197. X    (message "C-c n:next   C-c p:prev   C-c <:first   C-c >:last   C-c ?:help   C-c q:exit")))
  198. X
  199. X(defun forms--trans (subj arg rep)
  200. X  "Translate in SUBJ all chars ARG into char REP. ARG and REP should
  201. X be single-char strings."
  202. X  (let ((i 0)
  203. X    (x (length subj))
  204. X    (re (regexp-quote arg))
  205. X    (k (string-to-char rep)))
  206. X    (while (setq i (string-match re subj i))
  207. X      (aset subj i k)
  208. X      (setq i (1+ i)))))
  209. X
  210. X(defun forms--exit (query &optional save)
  211. X  (let ((buf (buffer-name forms--file-buffer)))
  212. X    (forms--checkmod)
  213. X    (if (and save
  214. X         (buffer-modified-p forms--file-buffer))
  215. X    (save-excursion
  216. X      (set-buffer forms--file-buffer)
  217. X      (save-buffer)))
  218. X    (save-excursion
  219. X      (set-buffer forms--file-buffer)
  220. X      (delete-auto-save-file-if-necessary)
  221. X      (kill-buffer (current-buffer)))
  222. X    (if (get-buffer buf)    ; not killed???
  223. X      (if save
  224. X      (progn
  225. X        (beep)
  226. X        (message "Problem saving buffers?")))
  227. X      (delete-auto-save-file-if-necessary)
  228. X      (kill-buffer (current-buffer)))))
  229. X
  230. X(defun forms--get-record ()
  231. X  "Fetch the current record from the file buffer."
  232. X  ;;
  233. X  ;; This function is executed in the context of the forms--file-buffer.
  234. X  ;;
  235. X  (or (bolp)
  236. X      (beginning-of-line nil))
  237. X  (let ((here (point)))
  238. X    (prog2
  239. X     (end-of-line)
  240. X     (buffer-substring here (point))
  241. X     (goto-char here))))
  242. X
  243. X(defun forms--show-record (the-record)
  244. X  "Format THE-RECORD according to forms-format-list,
  245. X and display it in the current buffer."
  246. X
  247. X  ;; split the-record
  248. X  (let (the-result
  249. X    (start-pos 0)
  250. X    found-pos
  251. X    (field-sep-length (length forms-field-sep)))
  252. X    (if forms-multi-line
  253. X    (forms--trans the-record forms-multi-line "\n"))
  254. X    ;; add an extra separator (makes splitting easy)
  255. X    (setq the-record (concat the-record forms-field-sep))
  256. X    (while (setq found-pos (string-match forms-field-sep the-record start-pos))
  257. X      (let ((ent (substring the-record start-pos found-pos)))
  258. X    (setq the-result
  259. X          (append the-result (list ent)))
  260. X    (setq start-pos (+ field-sep-length found-pos))))
  261. X    (setq forms--the-record-list the-result))
  262. X
  263. X  (setq buffer-read-only nil)
  264. X  (erase-buffer)
  265. X
  266. X  ;; verify the number of fields, extend forms--the-record-list if needed
  267. X  (if (= (length forms--the-record-list) forms-number-of-fields)
  268. X      nil
  269. X    (beep)
  270. X    (message "Record has %d fields instead of %d."
  271. X         (length forms--the-record-list) forms-number-of-fields)
  272. X    (if (< (length forms--the-record-list) forms-number-of-fields)
  273. X    (setq forms--the-record-list 
  274. X          (append forms--the-record-list
  275. X              (make-list 
  276. X               (- forms-number-of-fields 
  277. X              (length forms--the-record-list))
  278. X               "")))))
  279. X
  280. X  ;; call the formatter function
  281. X  (funcall forms--format forms--the-record-list)
  282. X
  283. X  ;; prepare
  284. X  (goto-char (point-min))
  285. X  (set-buffer-modified-p nil)
  286. X  (setq buffer-read-only forms-read-only)
  287. X  (setq mode-line-process
  288. X    (concat " " forms--current-record "/" forms--total-records)))
  289. X
  290. X(defun forms--parse-form ()
  291. X  "Parse contents of form into list of strings."
  292. X  ;; The contents of the form are parsed, and a new list of strings
  293. X  ;; is constructed.
  294. X  ;; A vector with the strings from the original record is 
  295. X  ;; constructed, which is updated with the new contents. Therefore
  296. X  ;; fields which were not in the form are not modified.
  297. X  ;; Finally, the vector is transformed into a list for further processing.
  298. X
  299. X  (let (the-recordv)
  300. X
  301. X    ;; build the vector
  302. X    (setq the-recordv (vconcat forms--the-record-list))
  303. X
  304. X    ;; parse the form and update the vector
  305. X    (funcall forms--parser)
  306. X
  307. X    ;; transform to a list and return
  308. X    (append the-recordv nil)))
  309. X
  310. X(defun forms--update ()
  311. X  "Update current record with contents of form. As a side effect: sets
  312. Xforms--the-record-list ."
  313. X  (if forms-read-only
  314. X      (progn
  315. X    (message "Read-only buffer!")
  316. X    (beep))
  317. X
  318. X    (let (the-record)
  319. X      ;; build new record
  320. X      (setq forms--the-record-list (forms--parse-form))
  321. X      (setq the-record
  322. X        (mapconcat 'identity forms--the-record-list forms-field-sep))
  323. X
  324. X      ;; handle multi-line fields, if allowed
  325. X      (if forms-multi-line
  326. X      (forms--trans the-record "\n" forms-multi-line))
  327. X
  328. X      ;; a final sanity check before updating
  329. X      (if (string-match "\n" the-record)
  330. X      (progn
  331. X        (message "Multi-line fields in this record - update refused!")
  332. X        (beep))
  333. X
  334. X    (save-excursion
  335. X      (set-buffer forms--file-buffer)
  336. X      (kill-line nil)
  337. X      (insert the-record)
  338. X      (beginning-of-line))))))
  339. X
  340. X(defun forms--checkmod ()
  341. X  "Check if this form has been modified, and call forms--update if so."
  342. X  (if (buffer-modified-p nil)
  343. X      (let ((here (point)))
  344. X    (forms--update)
  345. X    (set-buffer-modified-p nil)
  346. X    (goto-char here))))
  347. X
  348. X;;;
  349. X;;; Start and exit
  350. X(defun forms-find-file (fn)
  351. X  "Visit file FN in forms mode"
  352. X  (interactive "fForms file: ")
  353. X  (find-file-read-only fn)
  354. X  (or forms--mode-setup (forms-mode t)))
  355. X
  356. X(defun forms-find-file-other-window (fn)
  357. X  "Visit file FN in form mode in other window"
  358. X  (interactive "fFbrowse file in other window: ")
  359. X  (find-file-other-window fn)
  360. X  (eval-current-buffer)
  361. X  (or forms--mode-setup (forms-mode t)))
  362. X
  363. X(defun forms-exit (query)
  364. X  "Normal exit. Modified buffers are saved."
  365. X  (interactive "P")
  366. X  (forms--exit query t))
  367. X
  368. X(defun forms-exit-no-save (query)
  369. X  "Exit without saving buffers."
  370. X  (interactive "P")
  371. X  (forms--exit query nil))
  372. X
  373. X;;;
  374. X;;; Navigating commands
  375. X
  376. X(defun forms-next-record (arg)
  377. X  "Advance to the ARGth following record."
  378. X  (interactive "P")
  379. X  (forms-jump-record (+ forms--current-record (prefix-numeric-value arg)) t))
  380. X
  381. X(defun forms-prev-record (arg)
  382. X  "Advance to the ARGth previous record."
  383. X  (interactive "P")
  384. X  (forms-jump-record (- forms--current-record (prefix-numeric-value arg)) t))
  385. X
  386. X(defun forms-jump-record (arg &optional relative)
  387. X  "Jump to a random record."
  388. X  (interactive "NRecord number: ")
  389. X
  390. X  ;; verify that the record number is within range
  391. X  (if (or (> arg forms--total-records)
  392. X      (<= arg 0))
  393. X    (progn
  394. X      (beep)
  395. X      ;; don't give the message if just paging
  396. X      (if (not relative)
  397. X      (message "Record number %d out of range 1..%d"
  398. X           arg forms--total-records))
  399. X      )
  400. X
  401. X    ;; flush
  402. X    (forms--checkmod)
  403. X
  404. X    ;; calculate displacement
  405. X    (let ((disp (- arg forms--current-record))
  406. X      (cur forms--current-record))
  407. X
  408. X      ;; forms--show-record needs it now
  409. X      (setq forms--current-record arg)
  410. X
  411. X      ;; get the record and show it
  412. X      (forms--show-record
  413. X       (save-excursion
  414. X     (set-buffer forms--file-buffer)
  415. X     (beginning-of-line)
  416. X
  417. X     ;; move, and adjust the amount if needed (shouldn't happen)
  418. X     (if relative
  419. X         (if (zerop disp)
  420. X         nil
  421. X           (setq cur (+ cur disp (- (forward-line disp)))))
  422. X       (setq cur (+ cur disp (- (goto-line arg)))))
  423. X
  424. X     (forms--get-record)))
  425. X
  426. X      ;; this shouldn't happen
  427. X      (if (/= forms--current-record cur)
  428. X      (progn
  429. X        (setq forms--current-record cur)
  430. X        (beep)
  431. X        (message "Stuck at record %d." cur))))))
  432. X
  433. X(defun forms-first-record ()
  434. X  "Jump to first record."
  435. X  (interactive)
  436. X  (forms-jump-record 1))
  437. X
  438. X(defun forms-last-record ()
  439. X  "Jump to last record. As a side effect: re-calculates the number
  440. X of records in the data file."
  441. X  (interactive)
  442. X  (let
  443. X      ((numrec 
  444. X    (save-excursion
  445. X      (set-buffer forms--file-buffer)
  446. X      (count-lines (point-min) (point-max)))))
  447. X    (if (= numrec forms--total-records)
  448. X    nil
  449. X      (beep)
  450. X      (setq forms--total-records numrec)
  451. X      (message "Number of records reset to %d." forms--total-records)))
  452. X  (forms-jump-record forms--total-records))
  453. X
  454. X;;;
  455. X;;; Other commands
  456. X(defun forms-view-mode ()
  457. X  "Visit buffer read-only."
  458. X  (interactive)
  459. X  (if forms-read-only
  460. X      nil
  461. X    (forms--checkmod)            ; sync
  462. X    (setq forms-read-only t)
  463. X    (forms-mode)))
  464. X
  465. X(defun forms-edit-mode ()
  466. X  "Make form suitable for editing, if possible."
  467. X  (interactive)
  468. X  (let ((ro forms-read-only))
  469. X    (if (save-excursion
  470. X      (set-buffer forms--file-buffer)
  471. X      buffer-read-only)
  472. X    (progn
  473. X      (setq forms-read-only t)
  474. X      (message "No write access to \"%s\"" forms-file)
  475. X      (beep))
  476. X      (setq forms-read-only nil))
  477. X    (if (equal ro forms-read-only)
  478. X    nil
  479. X      (forms-mode))))
  480. X
  481. X(defun forms-insert-record (arg)
  482. X  "Create a new record before the current one. With ARG: store the
  483. X record after the current one."
  484. X
  485. X  (interactive "P")
  486. X
  487. X  (let ((ln (if arg (1+ forms--current-record) forms--current-record))
  488. X        (the-record
  489. X     (mapconcat
  490. X      'identity
  491. X      (make-list forms-number-of-fields "")
  492. X      forms-field-sep)))
  493. X
  494. X    (save-excursion
  495. X      (set-buffer forms--file-buffer)
  496. X      (goto-line ln)
  497. X      (open-line 1)
  498. X      (insert the-record)
  499. X      (beginning-of-line))
  500. X    
  501. X    (setq forms--current-record ln))
  502. X
  503. X  (setq forms--total-records (1+ forms--total-records))
  504. X  (forms-jump-record forms--current-record))
  505. X
  506. X(defun forms-delete-record (arg)
  507. X  "Deletes a record. With ARG: don't ask."
  508. X  (interactive "P")
  509. X  (if (or arg
  510. X      (y-or-n-p "Really delete this record? "))
  511. X      (let ((ln forms--current-record))
  512. X    (save-excursion
  513. X      (set-buffer forms--file-buffer)
  514. X      (goto-line ln)
  515. X      (kill-line 1))
  516. X    (setq forms--total-records (1- forms--total-records))
  517. X    (if (> forms--current-record forms--total-records)
  518. X        (setq forms--current-record forms--total-records))
  519. X    (forms-jump-record forms--current-record)))
  520. X  (message ""))
  521. X
  522. X(defun forms-search (regexp)
  523. X  "Search REGEXP in file buffer."
  524. X  (interactive 
  525. X   (list (read-string (concat "Search for" 
  526. X                  (if forms--search-regexp
  527. X                   (concat " ("
  528. X                       forms--search-regexp
  529. X                       ")"))
  530. X                  ": "))))
  531. X  (if (equal "" regexp)
  532. X      (setq regexp forms--search-regexp))
  533. X
  534. X  (let (the-line the-record here
  535. X         (fld-sep forms-field-sep))
  536. X    (if (save-excursion
  537. X      (set-buffer forms--file-buffer)
  538. X      (setq here (point))
  539. X      (end-of-line)
  540. X      (if (null (re-search-forward regexp nil t))
  541. X          (progn
  542. X        (goto-char here)
  543. X        (message (concat "\"" regexp "\" not found."))
  544. X        nil)
  545. X        (setq the-record (forms--get-record))
  546. X        (setq the-line (1+ (count-lines (point-min) (point))))))
  547. X    (progn
  548. X      (setq forms--current-record the-line)
  549. X      (forms--show-record the-record)
  550. X      (re-search-forward regexp nil t))))
  551. X  (setq forms--search-regexp regexp))
  552. X
  553. X(defun forms-revert-buffer (&optional arg noconfirm)
  554. X  "Reverts current form to un-modified."
  555. X  (interactive "P")
  556. X  (if (or noconfirm
  557. X      (yes-or-no-p "Revert form to unmodified? "))
  558. X      (progn
  559. X    (set-buffer-modified-p nil)
  560. X    (forms-jump-record forms--current-record))))
  561. X
  562. X(defun forms-next-field (arg)
  563. X  "Jump to ARG-th next field."
  564. X  (interactive "p")
  565. X
  566. X  (let ((i 0)
  567. X    (here (point))
  568. X    there
  569. X    (cnt 0))
  570. X
  571. X    (if (zerop arg)
  572. X    (setq cnt 1)
  573. X      (setq cnt (+ cnt arg)))
  574. X
  575. X    (if (catch 'done
  576. X      (while (< i forms--number-of-markers)
  577. X        (if (or (null (setq there (aref forms--markers i)))
  578. X            (<= there here))
  579. X        nil
  580. X          (if (<= (setq cnt (1- cnt)) 0)
  581. X          (progn
  582. X            (goto-char there)
  583. X            (throw 'done t))))
  584. X        (setq i (1+ i))))
  585. X    nil
  586. X      (goto-char (aref forms--markers 0)))))
  587. SHAR_EOF
  588. echo "File forms.el is complete" &&
  589. $TOUCH -am 0610122590 forms.el &&
  590. chmod 0444 forms.el ||
  591. echo "restore of forms.el failed"
  592. set `wc -c forms.el`;Wc_c=$1
  593. if test "$Wc_c" != "36688"; then
  594.     echo original size 36688, current size $Wc_c
  595. fi
  596. # ============= forms.ti ==============
  597. echo "x - extracting forms.ti (Text)"
  598. sed 's/^X//' << 'SHAR_EOF' > forms.ti &&
  599. X\input texinfo            @c -*-texinfo-*- @(#)@ forms 1.1.2
  600. X@comment %**start of header (This is for running Texinfo on a region.)
  601. X@setfilename forms.info
  602. X@settitle Forms Mode User's Manual
  603. X@iftex
  604. X@finalout
  605. X@end iftex
  606. X@setchapternewpage odd
  607. X@c      @smallbook
  608. X@comment %**end of header (This is for running Texinfo on a region.)
  609. X
  610. X@tex
  611. X\global\chapno=30
  612. X@end tex
  613. X
  614. X@ifinfo
  615. XThis file documents forms-mode, a forms based major mode for GNU Emacs.
  616. X
  617. XPermission is granted to make and distribute verbatim copies of this
  618. Xmanual provided the copyright notice and this permission notice are
  619. Xpreserved on all copies.
  620. X
  621. X@ignore
  622. XPermission is granted to process this file through TeX and print the
  623. Xresults, provided the printed document carries copying permission notice
  624. Xidentical to this one except for the removal of this paragraph (this
  625. Xparagraph not being relevant to the printed manual).
  626. X
  627. X@end ignore
  628. X@end ifinfo
  629. X
  630. X@iftex
  631. X@titlepage
  632. X@sp 6
  633. X@center @titlefont{Forms Mode User's Manual}
  634. X@sp 4
  635. X@center First Release, Forms-Mode version 1.1
  636. X@sp 1
  637. X@center June 1990
  638. X@sp 5
  639. X@center Johan Vromans
  640. X@center @i{jv@@mh.nl}
  641. X@page
  642. X
  643. X@vskip 0pt plus 1filll
  644. XCopyright @copyright{} 1989,1990 Free Software Foundation, Inc.
  645. X
  646. XPermission is granted to make and distribute verbatim copies of
  647. Xthis manual provided the copyright notice and this permission notice
  648. Xare preserved on all copies.
  649. X
  650. X@end titlepage
  651. X@page
  652. X@end iftex
  653. X
  654. X@ifinfo
  655. X@node Top, What is in a Forms, , (DIR)
  656. X@end ifinfo
  657. X
  658. X@iftex
  659. X@chapter Forms mode
  660. X@end iftex
  661. X
  662. XForms mode is an Emacs major mode for working with simple plain-text
  663. Xdatabases in a forms-oriented manner. In forms mode, the information in
  664. Xthese files is presented in an Emacs window in a user-defined format,
  665. Xone record at a time. Forms can be inspected read-only (viewing) or
  666. Xmodified and updated.
  667. X@cindex forms-mode
  668. X
  669. XForms mode is not a simple major mode, but requires @dfn{two} files to do its
  670. Xjob: a @dfn{control file} and a @dfn{data file}. The data file holds the
  671. Xactual data which will be presented. The control file describes
  672. X@dfn{how} it will be presented.
  673. X
  674. X@menu
  675. X* What is in a Forms::    Introduction.
  676. X* Data File Format::    How to format the data file.
  677. X* Control File Format::    How to control forms mode.
  678. X* Forms Format Description::
  679. X            How to define the forms layout.
  680. X* Modifying Forms Contents::
  681. X            How to modify.
  682. X* Forms Mode Commands::    The commands available, and how to use them.
  683. X* Key Bindings::    Which keys are bound to what commands.
  684. X* Miscellaneous::    Forms mode messages and other remarks.
  685. X* Credits::        Thanks everyone.
  686. X* Concept Index::    Index of Concepts
  687. X* Variable Index::    Index of Variables.
  688. X* Function Index::    Index of Functions.
  689. X@end menu
  690. X
  691. X@node What is in a Forms, Data File Format, Top, Top
  692. X@section What is in a forms
  693. X
  694. XLet's illustrate forms mode with an example. Suppose you are looking at
  695. Xyour @file{/etc/passwd} file, and your screen looks as follows:
  696. X
  697. X@example
  698. X====== /etc/passwd ======
  699. X
  700. XUser : root   Uid: 0   Gid: 1
  701. X
  702. XName : Super User
  703. X
  704. XHome : /
  705. X
  706. XShell: /bin/sh
  707. X@end example
  708. X
  709. XAs you can see, the familiar fields from the entry for the super user
  710. Xare all there, but instead of one single line, they make up a forms.
  711. X
  712. XThe contents of the forms consists of the contents of the fields of the
  713. Xrecord (e.g. @code{root}, @code{0}, @code{1}, @code{Super User})
  714. Xinterspersed with normal text (e.g @code{User : }, @code{Uid: }).
  715. X
  716. XYou can define yourself how text and fields will be used to make up the
  717. Xforms.
  718. X
  719. XWhen you modifiy the contents of the forms, it will be analyzed and the
  720. Xnew contents of the fields of this record will be extracted. It
  721. Xpossible, the file will be updated with the new contents.
  722. X
  723. X@node Data File Format, Control File Format, What is in a Forms, Top
  724. X@section Data file format
  725. X
  726. XFiles for use with forms mode are very simple -- each record forms the
  727. Xcontents one form.  Each record is supposed to consist of a number of
  728. Xfields. These fields are separated by the value of the string
  729. X@code{forms-field-sep}, which is a @code{TAB} by default.
  730. X
  731. X@cindex pseudo-newline
  732. XFields may contain text which shows up in the forms in multiple lines.
  733. XThese lines are separated in the field using a @var{pseudo-newline}
  734. Xcharacter which is defined by the value of the string
  735. X@code{forms-multi-line}. Its default value is a Control-K character. If
  736. Xit is set to @code{nil} multiple line fields are prohibited.
  737. X
  738. X@node Control File Format, Forms Format Description, Data File Format, Top
  739. X@section Control file format
  740. X
  741. XThe control file serves two purposes.
  742. X
  743. XFirst, it defines the data file to use, and its properties.
  744. X
  745. XSecond, the Emacs buffer it occupies will be used by the forms mode to
  746. Xdisplay the forms.
  747. X
  748. X@findex eval-current-buffer
  749. XThe contents of the control file are evaluated using the Emacs command
  750. X@code{eval-current-buffer}, hence must contain valid Emacs-lisp expressions.
  751. XThese expressions should set the following lisp variables to a suitable
  752. Xvalue:
  753. X
  754. X@table @code
  755. X@vindex forms-file
  756. X@item forms-file
  757. XThis variable must be set to the name of the data file.@*
  758. XExample:
  759. X@example
  760. X(setq forms-file "my/data-file")
  761. X@end example
  762. X
  763. X@item forms-format-list
  764. XThis variable describes the way the fields of the record are formatted on
  765. Xthe screen. See the next section for details.
  766. X
  767. X@vindex forms-field-sep
  768. X@item forms-field-sep
  769. XThis variable may be used to designate the string which separates the fields
  770. Xin the records of the data file. If not set, it defaults to a string
  771. Xcontaining a single @code{TAB} character. @*
  772. XExample:
  773. X@example
  774. X(setq forms-field-sep "\t")
  775. X@end example
  776. X
  777. X@vindex forms-number-of-fields
  778. X@item forms-number-of-fields
  779. XThis variable holds the number of fields in each record of the data
  780. Xfile.@*
  781. XExample:
  782. X@example
  783. X(setq forms-number-of-fields 10)
  784. X@end example
  785. X
  786. X@vindex forms-read-only
  787. X@item forms-read-only
  788. XIf set to a value other than @code{nil}, the data file is treated
  789. Xread-only. If the data file can not be written into, read-only mode is
  790. Xenforced. The default value for @code{forms-read-only} is derieved from
  791. Xthe access permissions of the data file.@*
  792. XExample:
  793. X@example
  794. X(set forms-read-only t)
  795. X@end example
  796. X
  797. X@vindex forms-multi-line
  798. X@item forms-multi-line
  799. XThis variable may be set to allow multi-line text in fields. It should
  800. Xbe set to a string of one character, which denotes the pseudo new-line
  801. Xcharacter to be used to separate the text lines.@*
  802. XIts default value is Control-K (octal 013). If set to @code{nil},
  803. Xmulti-line text fields are prohibited.@*
  804. XIt may not be a character contained in @code{forms-field-sep}.@*
  805. XExample:
  806. X@example
  807. X(setq forms-multi-line "\C-k")
  808. X@end example
  809. X
  810. X@end table
  811. X
  812. XOf these fields, only @code{forms-file}, @code{forms-number-of-fields}
  813. Xand @code{forms-format-list} are mandatory. An error will be given if
  814. Xone of these variables has not been set. All other variables have
  815. Xdefault values which are suitable for most applications.
  816. X
  817. XTwo more variables may be used:
  818. X@code{forms-forms-scroll} and @code{forms-forms-jump}.
  819. X@xref{Forms Mode Commands} for their descriptions.
  820. X
  821. X@node Forms Format Description, Modifying Forms Contents, Control File Format, Top
  822. X@section The forms format description
  823. X
  824. X@vindex forms-format-list
  825. XThe value of the variable @code{forms-format-list} is used to specify
  826. Xthe format of the forms. It must be a @code{list} of formatting elements,
  827. SHAR_EOF
  828. echo "End of  part 2"
  829. echo "File forms.ti is continued in part 3"
  830. echo "3" > shar3_seq_.tmp
  831. exit 0
  832.  
  833.