;;; forms.el --- Forms mode: edit a file as a form to fill in
-;; Copyright (C) 1991, 1994-1997, 2001-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1994-1997, 2001-2016 Free Software Foundation,
+;; Inc.
;; Author: Johan Vromans <jvromans@squirrel.nl>
;;; Commentary:
-;; Visit a file using a form. See forms-d2.el for examples.
+;; Visit a file using a form. See etc/forms for examples.
;;
;; === Naming conventions
;;
;;; Global variables and constants:
-(provide 'forms) ;;; official
-(provide 'forms-mode) ;;; for compatibility
-
(defcustom forms-mode-hook nil
"Hook run upon entering Forms mode."
:group 'forms
(defvar forms--rw-face nil
"Face used to represent read-write data on the screen.")
\f
+(defvar read-file-filter) ; bound in forms--intuit-from-file
+
;;;###autoload
(defun forms-mode (&optional primary)
+ ;; FIXME: use define-derived-mode
"Major mode to visit files in a field-structured manner using a form.
Commands: Equivalent keys in read-only mode:
(error (concat "Forms control file error: "
"`forms-modified-record-filter' is not a function")))
- ;; The filters acces the contents of the forms using `forms-fields'.
+ ;; The filters access the contents of the forms using `forms-fields'.
(make-local-variable 'forms-fields)
;; Dynamic text support.
(make-local-variable 'forms--dynamic-text)
;; Prevent accidental overwrite of the control file and auto-save.
- (set-visited-file-name nil)
+ ;; We bind change-major-mode-with-file-name to nil to prevent
+ ;; set-visited-file-name from calling set-auto-mode, which
+ ;; might kill all local variables and set forms-file nil,
+ ;; which will then barf in find-file-noselect below. This can
+ ;; happen when the user sets the default major mode that is
+ ;; different from the Fundamental mode.
+ (let (change-major-mode-with-file-name)
+ (set-visited-file-name nil))
;; Prepare this buffer for further processing.
(setq buffer-read-only nil)
(setq major-mode 'forms-mode)
(setq mode-name "Forms")
+ (cursor-intangible-mode 1)
+
;; find the data file
(setq forms--file-buffer (find-file-noselect forms-file))
(with-current-buffer forms--file-buffer
(let ((inhibit-read-only t)
(file-modified (buffer-modified-p)))
- (run-hooks 'read-file-filter)
+ (mapc #'funcall read-file-filter)
(if (not file-modified) (set-buffer-modified-p nil)))
(if write-file-filter
(add-hook 'write-file-functions write-file-filter nil t)))
;;(message "forms: proceeding setup...")
- ;; Since we aren't really implementing a minor mode, we hack the modeline
+ ;; Since we aren't really implementing a minor mode, we hack the mode line
;; directly to get the text " View " into forms-read-only form buffers. For
;; that reason, this variable must be buffer only.
(make-local-variable 'minor-mode-alist)
(insert
"GNU Emacs Forms Mode\n\n"
(if (file-exists-p forms-file)
- (concat "No records available in file `" forms-file "'\n\n")
- (format "Creating new file `%s'\nwith %d field%s per record\n\n"
- forms-file forms-number-of-fields
- (if (= 1 forms-number-of-fields) "" "s")))
+ (format-message
+ "No records available in file `%s'\n\n" forms-file)
+ (format-message
+ "Creating new file `%s'\nwith %d field%s per record\n\n"
+ forms-file forms-number-of-fields
+ (if (= 1 forms-number-of-fields) "" "s")))
"Use " (substitute-command-keys "\\[forms-insert-record]")
" to create new records.\n")
(setq forms--current-record 1)
(forms-first-record))
)
- ;; user customising
+ ;; user customizing
;;(message "forms: proceeding setup (user hooks)...")
(run-mode-hooks 'forms-mode-hook 'forms-mode-hooks)
;;(message "forms: setting up... done.")
`(lambda (arg)
(let ((inhibit-read-only t))
,@(apply 'append
- (mapcar 'forms--make-format-elt-using-text-properties
+ (mapcar #'forms--make-format-elt-using-text-properties
forms-format-list))
;; Prevent insertion before the first text.
,@(if (numberp (car forms-format-list))
nil
'((add-text-properties (point-min) (1+ (point-min))
- '(front-sticky (read-only intangible)))))
+ '(front-sticky (read-only cursor-intangible)))))
;; Prevent insertion after the last text.
(remove-text-properties (1- (point)) (point)
'(rear-nonsticky)))
(setq forms--iif-start nil))
`(lambda (arg)
,@(apply 'append
- (mapcar 'forms--make-format-elt forms-format-list)))))
+ (mapcar #'forms--make-format-elt forms-format-list)))))
;; We have tallied the number of markers and dynamic texts,
;; so we can allocate the arrays now.
(point))
(list 'face forms--ro-face ; read-only appearance
'read-only ,@(list (1+ forms--marker))
- 'intangible ,@(list (1+ forms--marker))
+ 'cursor-intangible ,@(list (1+ forms--marker))
'insert-in-front-hooks '(forms--iif-hook)
'rear-nonsticky '(face read-only insert-in-front-hooks
- intangible)))))
+ cursor-intangible)))))
((numberp el)
`((let ((here (point)))
(point))
(list 'face forms--ro-face
'read-only ,@(list (1+ forms--marker))
- 'intangible ,@(list (1+ forms--marker))
+ 'cursor-intangible ,@(list (1+ forms--marker))
'insert-in-front-hooks '(forms--iif-hook)
'rear-nonsticky '(read-only face insert-in-front-hooks
- intangible)))))
+ cursor-intangible)))))
;; end of cond
))
(goto-char (point-min))
,@(apply 'append
(mapcar
- 'forms--make-parser-elt
+ #'forms--make-parser-elt
(append forms-format-list (list nil)))))))))
(forms--debug 'forms--parser))
(setq forms--field nil)))
))
\f
-(defvar read-file-filter) ; bound in forms--intuit-from-file
-
(defun forms--intuit-from-file ()
"Get number of fields and a default form using the data file."
)
(defun forms--mode-menu-ro (map)
-;;; Menu initialisation
+;;; Menu initialization
; (define-key map [menu-bar] (make-sparse-keymap))
(define-key map [menu-bar forms]
(cons "Forms" (make-sparse-keymap "Forms")))
(put 'forms-delete-record 'menu-enable '(not forms-read-only))
)
(defun forms--mode-menu-edit (map)
-;;; Menu initialisation
+;;; Menu initialization
; (define-key map [menu-bar] (make-sparse-keymap))
(define-key map [menu-bar forms]
(cons "Forms" (make-sparse-keymap "Forms")))
;; Build new record.
(setq forms--the-record-list (forms--parse-form))
(setq the-record
- (mapconcat 'identity forms--the-record-list forms-field-sep))
+ (mapconcat #'identity forms--the-record-list forms-field-sep))
- (if (string-match (regexp-quote forms-field-sep)
- (mapconcat 'identity forms--the-record-list ""))
+ (if (string-match-p (regexp-quote forms-field-sep)
+ (mapconcat #'identity forms--the-record-list ""))
(error "Field separator occurs in record - update refused"))
;; Handle multi-line fields, if allowed.
(forms--trans the-record "\n" forms-multi-line))
;; A final sanity check before updating.
- (if (string-match "\n" the-record)
+ (if (string-match-p "\n" the-record)
(error "Multi-line fields in this record - update refused"))
(with-current-buffer forms--file-buffer
With ARG: store the record after the current one.
If `forms-new-record-filter' contains the name of a function,
it is called to fill (some of) the fields with default values.
-If `forms-insert-after is non-nil, the default behavior is to insert
+If `forms-insert-after' is non-nil, the default behavior is to insert
after the current record."
(interactive "P")
(setq the-list (cdr (append the-fields nil))))
(setq the-list (make-list forms-number-of-fields "")))
- (setq the-record
- (mapconcat
- 'identity
- the-list
- forms-field-sep))
+ (setq the-record (mapconcat #'identity the-list forms-field-sep))
(with-current-buffer forms--file-buffer
(forms--goto-record ln)
\f
;;; Debugging
-(defvar forms--debug nil
- "*Enables forms-mode debugging if not nil.")
+(defcustom forms--debug nil
+ "If non-nil, enable Forms mode debugging."
+ :type 'boolean
+ :group 'forms)
(defun forms--debug (&rest args)
"Internal debugging routine."
(goto-char (point-max))
(insert ret)))))
+(provide 'forms-mode) ; for compatibility
+(provide 'forms)
;;; forms.el ends here