Rework empty abbrev table omitting

There were two problems with the original implementation:

1. It changed the behavior of insert-abbrev-table-description when
READABLE is nil to sometimes insert one Emacs Lisp expression and
sometimes insert nothing.
2. It broke the tests.

This commit reworks this so that insert-abbrev-table-description
always inserts an expressions even if no abbrevs need to be saved and
making only write-abbrev-file check that a table has any abbrevs to
save before calling insert-abbrev-table-description.  This duplicates
the work of filtering the table for savable abbrevs, but the benefit
of keeping the API is worth it.

* doc/lispref/abbrevs.texi (Abbrev Tables): Update documentation.
* lisp/abbrev.el (write-abbrev-file): Skip tables without user abbrevs
(insert-abbrev-table-description): Always insert the define
expression.
(abbrev--table-symbols): New function.
* test/lisp/abbrev-tests.el (abbrev--table-symbols-test):
Add test for abbrev--table-symbols.
This commit is contained in:
Allen Li 2018-09-29 15:19:04 -07:00 committed by Eli Zaretskii
parent 5bd8cfc14d
commit f5896e2cbf
4 changed files with 43 additions and 31 deletions

View file

@ -122,9 +122,7 @@ System abbrevs are listed and identified as such. Otherwise the
description is a Lisp expression---a call to @code{define-abbrev-table}
that would define @var{name} as it is currently defined, but without
the system abbrevs. (The mode or package using @var{name} is supposed
to add these to @var{name} separately.) If the Lisp expression would
not define any abbrevs (i.e.@: it defines an empty abbrev table), this
function inserts nothing.
to add these to @var{name} separately.)
@end defun
@node Defining Abbrevs
@ -234,7 +232,8 @@ Emacs commands to offer to save your abbrevs.
Save all abbrev definitions (except system abbrevs), for all abbrev
tables listed in @code{abbrev-table-name-list}, in the file
@var{filename}, in the form of a Lisp program that when loaded will
define the same abbrevs. If @var{filename} is @code{nil} or omitted,
define the same abbrevs. Tables that do not have any abbrevs to save
are omitted. If @var{filename} is @code{nil} or omitted,
@code{abbrev-file-name} is used. This function returns @code{nil}.
@end deffn

View file

@ -258,10 +258,9 @@ case does not match.
for abbrevs that have them.
+++
** 'insert-abbrev-table-description' skips empty tables.
'insert-abbrev-table-description' skips inserting empty tables when
inserting non-readable tables. By extension, this makes
'write-abbrev-file' skip writing empty tables.
** 'write-abbrev-file' skips empty tables.
'write-abbrev-file' now skips inserting a 'define-abbrev-table' form for
tables which do not have any non-system abbrevs to save.
+++
** The new functions and commands 'text-property-search-forward' and

View file

@ -251,7 +251,8 @@ have been saved."
(lambda (s1 s2)
(string< (symbol-name s1)
(symbol-name s2)))))
(insert-abbrev-table-description table nil))
(if (abbrev--table-symbols table)
(insert-abbrev-table-description table nil)))
(when (unencodable-char-position (point-min) (point-max) 'utf-8)
(setq coding-system-for-write
(if (> emacs-major-version 24)
@ -937,33 +938,38 @@ is inserted.
If READABLE is nil, an expression is inserted. The expression is
a call to `define-abbrev-table' that when evaluated will define
the abbrev table NAME exactly as it is currently defined.
Abbrevs marked as \"system abbrevs\" are ignored. If the
resulting expression would not define any abbrevs, nothing is
inserted."
Abbrevs marked as \"system abbrevs\" are ignored."
(let ((table (symbol-value name))
(symbols (abbrev--table-symbols name readable)))
(setq symbols (sort symbols 'string-lessp))
(let ((standard-output (current-buffer)))
(if readable
(progn
(insert "(")
(prin1 name)
(insert ")\n\n")
(mapc 'abbrev--describe symbols)
(insert "\n\n"))
(insert "(define-abbrev-table '")
(prin1 name)
(if (null symbols)
(insert " '())\n\n")
(insert "\n '(\n")
(mapc 'abbrev--write symbols)
(insert " ))\n\n")))
nil)))
(defun abbrev--table-symbols (name &optional system)
"Return the user abbrev symbols in the abbrev table named NAME.
NAME is a symbol whose value is an abbrev table. System abbrevs
are omitted unless SYSTEM is non-nil."
(let ((table (symbol-value name))
(symbols ()))
(mapatoms (lambda (sym)
(if (and (symbol-value sym) (or readable (not (abbrev-get sym :system))))
(if (and (symbol-value sym) (or system (not (abbrev-get sym :system))))
(push sym symbols)))
table)
(when symbols
(setq symbols (sort symbols 'string-lessp))
(let ((standard-output (current-buffer)))
(if readable
(progn
(insert "(")
(prin1 name)
(insert ")\n\n")
(mapc 'abbrev--describe symbols)
(insert "\n\n"))
(insert "(define-abbrev-table '")
(prin1 name)
(if (null symbols)
(insert " '())\n\n")
(insert "\n '(\n")
(mapc 'abbrev--write symbols)
(insert " ))\n\n")))
nil))))
symbols))
(defun define-abbrev-table (tablename definitions
&optional docstring &rest props)

View file

@ -64,6 +64,14 @@
(should (= (length table) obarray-default-size))
(should (eq (abbrev-table-get table 'foo) 'bar))))
(ert-deftest abbrev--table-symbols-test ()
(let ((ert-test-abbrevs (setup-test-abbrev-table)))
(define-abbrev ert-test-abbrevs "sys" "system abbrev" nil :system t)
(should (equal (mapcar #'symbol-name (abbrev--table-symbols 'ert-test-abbrevs))
'("a-e-t")))
(should (equal (mapcar #'symbol-name (abbrev--table-symbols 'ert-test-abbrevs t))
'("a-e-t" "sys")))))
(ert-deftest abbrev-table-get-put-test ()
(let ((table (make-abbrev-table)))
(should-not (abbrev-table-get table 'foo))