Mercurial > emacs
comparison lisp/abbrev.el @ 85710:beb909dfc54d
Rewrite abbrev.c in Elisp.
* image.c (Qcount): Don't declare as extern.
(syms_of_image): Initialize and staticpro `Qcount'.
* puresize.h (BASE_PURESIZE): Increase for the new abbrev.el functions.
* emacs.c (main): Don't call syms_of_abbrev.
* Makefile.in (obj): Remove abbrev.o.
(abbrev.o): Remove.
* abbrev.c: Remove.
Rewrite abbrev.c in Elisp.
* abbrev.el (abbrev-mode): Move custom group from cus-edit.el.
(abbrev-table-get, abbrev-table-put, abbrev-get)
(abbrev-put, make-abbrev-table, abbrev-table-p, clear-abbrev-table)
(define-abbrev, abbrev--check-chars, define-global-abbrev)
(define-mode-abbrev, abbrev--active-tables, abbrev-symbol)
(abbrev-expansion, abbrev--before-point, expand-abbrev)
(unexpand-abbrev, abbrev--write, abbrev--describe)
(insert-abbrev-table-description, define-abbrev-table):
New funs, largely transcribed from abbrev.c.
(abbrev-with-wrapper-hook): New macro.
(abbrev-table-name-list, global-abbrev-table)
(abbrev-minor-mode-table-alist, fundamental-mode-abbrev-table)
(abbrevs-changed, abbrev-all-caps, abbrev-start-location)
(abbrev-start-location-buffer, last-abbrev, last-abbrev-text)
(last-abbrev-location, pre-abbrev-expand-hook, abbrev-expand-function):
New vars, largely transcribed from abbrev.c.
* cus-edit.el (abbrev-mode): Remove. Move to abbrev.el.
* cus-start.el: Remove abbrev-all-caps and pre-abbrev-expand-hook.
* loadup.el: Load "abbrev.el" before "lisp-mode.el".
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Sun, 28 Oct 2007 02:41:00 +0000 |
parents | 7c8949dbfa0d |
children | 13ae285f009a |
comparison
equal
deleted
inserted
replaced
85709:2dabdbde81e8 | 85710:beb909dfc54d |
---|---|
25 | 25 |
26 ;;; Commentary: | 26 ;;; Commentary: |
27 | 27 |
28 ;; This facility is documented in the Emacs Manual. | 28 ;; This facility is documented in the Emacs Manual. |
29 | 29 |
30 ;; Todo: | |
31 | |
32 ;; - Make abbrev-file-name obey user-emacs-directory. | |
33 ;; - Cleanup name space. | |
34 | |
30 ;;; Code: | 35 ;;; Code: |
36 | |
37 (eval-when-compile (require 'cl)) | |
38 | |
39 (defgroup abbrev-mode nil | |
40 "Word abbreviations mode." | |
41 :link '(custom-manual "(emacs)Abbrevs") | |
42 :group 'abbrev) | |
31 | 43 |
32 (defcustom only-global-abbrevs nil | 44 (defcustom only-global-abbrevs nil |
33 "Non-nil means user plans to use global abbrevs only. | 45 "Non-nil means user plans to use global abbrevs only. |
34 This makes the commands that normally define mode-specific abbrevs | 46 This makes the commands that normally define mode-specific abbrevs |
35 define global abbrevs instead." | 47 define global abbrevs instead." |
361 (save-excursion (forward-word -1) (point)) | 373 (save-excursion (forward-word -1) (point)) |
362 pnt))) | 374 pnt))) |
363 (if (or noquery (y-or-n-p (format "Expand `%s'? " string))) | 375 (if (or noquery (y-or-n-p (format "Expand `%s'? " string))) |
364 (expand-abbrev))))))) | 376 (expand-abbrev))))))) |
365 | 377 |
378 ;;; Abbrev properties. | |
379 | |
380 (defun abbrev-table-get (table prop) | |
381 "Get the PROP property of abbrev table TABLE." | |
382 (let ((sym (intern-soft "" table))) | |
383 (if sym (get sym prop)))) | |
384 | |
385 (defun abbrev-table-put (table prop val) | |
386 "Set the PROP property of abbrev table TABLE to VAL." | |
387 (let ((sym (intern "" table))) | |
388 (set sym nil) ; Make sure it won't be confused for an abbrev. | |
389 (put sym prop val))) | |
390 | |
391 (defun abbrev-get (sym prop) | |
392 "Get the property PROP of abbrev SYM." | |
393 (let ((plist (symbol-plist sym))) | |
394 (if (listp plist) | |
395 (plist-get plist prop) | |
396 (if (eq 'count prop) plist)))) | |
397 | |
398 (defun abbrev-put (sym prop val) | |
399 "Set the property PROP of abbrev SYM to value VAL. | |
400 See `define-abbrev' for the effect of some special properties." | |
401 (let ((plist (symbol-plist sym))) | |
402 (if (consp plist) | |
403 (put sym prop val) | |
404 (setplist sym (if (eq 'count prop) val | |
405 (list 'count plist prop val)))))) | |
406 | |
407 (defmacro abbrev-with-wrapper-hook (var &rest body) | |
408 "Run BODY wrapped with the VAR hook. | |
409 VAR is a special hook: its functions are called with one argument which | |
410 is the \"original\" code (the BODY), so the hook function can wrap the | |
411 original function, can call it several times, or even not call it at all. | |
412 VAR is normally a symbol (a variable) in which case it is treated like a hook, | |
413 with a buffer-local and a global part. But it can also be an arbitrary expression. | |
414 This is similar to an `around' advice." | |
415 (declare (indent 1) (debug t)) | |
416 ;; We need those two gensyms because CL's lexical scoping is not available | |
417 ;; for function arguments :-( | |
418 (let ((funs (make-symbol "funs")) | |
419 (global (make-symbol "global"))) | |
420 ;; Since the hook is a wrapper, the loop has to be done via | |
421 ;; recursion: a given hook function will call its parameter in order to | |
422 ;; continue looping. | |
423 `(labels ((runrestofhook (,funs ,global) | |
424 ;; `funs' holds the functions left on the hook and `global' | |
425 ;; holds the functions left on the global part of the hook | |
426 ;; (in case the hook is local). | |
427 (lexical-let ((funs ,funs) | |
428 (global ,global)) | |
429 (if (consp funs) | |
430 (if (eq t (car funs)) | |
431 (runrestofhook (append global (cdr funs)) nil) | |
432 (funcall (car funs) | |
433 (lambda () (runrestofhook (cdr funs) global)))) | |
434 ;; Once there are no more functions on the hook, run | |
435 ;; the original body. | |
436 ,@body)))) | |
437 (runrestofhook ,var | |
438 ;; The global part of the hook, if any. | |
439 ,(if (symbolp var) | |
440 `(if (local-variable-p ',var) | |
441 (default-value ',var))))))) | |
442 | |
443 | |
444 ;;; Code that used to be implemented in src/abbrev.c | |
445 | |
446 (defvar abbrev-table-name-list '(fundamental-mode-abbrev-table | |
447 global-abbrev-table) | |
448 "List of symbols whose values are abbrev tables.") | |
449 | |
450 (defun make-abbrev-table (&optional props) | |
451 "Create a new, empty abbrev table object. | |
452 PROPS is a " | |
453 ;; The value 59 is an arbitrary prime number. | |
454 (let ((table (make-vector 59 0))) | |
455 ;; Each abbrev-table has a `modiff' counter which can be used to detect | |
456 ;; when an abbreviation was added. An example of use would be to | |
457 ;; construct :regexp dynamically as the union of all abbrev names, so | |
458 ;; `modiff' can let us detect that an abbrev was added and hence :regexp | |
459 ;; needs to be refreshed. | |
460 ;; The presence of `modiff' entry is also used as a tag indicating this | |
461 ;; vector is really an abbrev-table. | |
462 (abbrev-table-put table :abbrev-table-modiff 0) | |
463 (while (consp props) | |
464 (abbrev-table-put table (pop props) (pop props))) | |
465 table)) | |
466 | |
467 (defun abbrev-table-p (object) | |
468 (and (vectorp object) | |
469 (numberp (abbrev-table-get object :abbrev-table-modiff)))) | |
470 | |
471 (defvar global-abbrev-table (make-abbrev-table) | |
472 "The abbrev table whose abbrevs affect all buffers. | |
473 Each buffer may also have a local abbrev table. | |
474 If it does, the local table overrides the global one | |
475 for any particular abbrev defined in both.") | |
476 | |
477 (defvar abbrev-minor-mode-table-alist nil | |
478 "Alist of abbrev tables to use for minor modes. | |
479 Each element looks like (VARIABLE . ABBREV-TABLE); | |
480 ABBREV-TABLE is active whenever VARIABLE's value is non-nil.") | |
481 | |
482 (defvar fundamental-mode-abbrev-table | |
483 (let ((table (make-abbrev-table))) | |
484 ;; Set local-abbrev-table's default to be fundamental-mode-abbrev-table. | |
485 (setq-default local-abbrev-table table) | |
486 table) | |
487 "The abbrev table of mode-specific abbrevs for Fundamental Mode.") | |
488 | |
489 (defvar abbrevs-changed nil | |
490 "Set non-nil by defining or altering any word abbrevs. | |
491 This causes `save-some-buffers' to offer to save the abbrevs.") | |
492 | |
493 (defcustom abbrev-all-caps nil | |
494 "Non-nil means expand multi-word abbrevs all caps if abbrev was so." | |
495 :type 'boolean | |
496 :group 'abbrev-mode) | |
497 | |
498 (defvar abbrev-start-location nil | |
499 "Buffer position for `expand-abbrev' to use as the start of the abbrev. | |
500 When nil, use the word before point as the abbrev. | |
501 Calling `expand-abbrev' sets this to nil.") | |
502 | |
503 (defvar abbrev-start-location-buffer nil | |
504 "Buffer that `abbrev-start-location' has been set for. | |
505 Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.") | |
506 | |
507 (defvar last-abbrev nil | |
508 "The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'.") | |
509 | |
510 (defvar last-abbrev-text nil | |
511 "The exact text of the last abbrev expanded. | |
512 nil if the abbrev has already been unexpanded.") | |
513 | |
514 (defvar last-abbrev-location 0 | |
515 "The location of the start of the last abbrev expanded.") | |
516 | |
517 ;; (defvar local-abbrev-table fundamental-mode-abbrev-table | |
518 ;; "Local (mode-specific) abbrev table of current buffer.") | |
519 ;; (make-variable-buffer-local 'local-abbrev-table) | |
520 | |
521 (defcustom pre-abbrev-expand-hook nil | |
522 "Function or functions to be called before abbrev expansion is done. | |
523 This is the first thing that `expand-abbrev' does, and so this may change | |
524 the current abbrev table before abbrev lookup happens." | |
525 :type 'hook | |
526 :group 'abbrev-mode) | |
527 (make-obsolete-variable 'pre-abbrev-expand-hook 'abbrev-expand-functions "23.1") | |
528 | |
529 (defun clear-abbrev-table (table) | |
530 "Undefine all abbrevs in abbrev table TABLE, leaving it empty." | |
531 (setq abbrevs-changed t) | |
532 (dotimes (i (length table)) | |
533 (aset table i 0))) | |
534 | |
535 (defun define-abbrev (table name expansion &optional hook &rest props) | |
536 "Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK. | |
537 NAME must be a string, and should be lower-case. | |
538 EXPANSION should usually be a string. | |
539 To undefine an abbrev, define it with EXPANSION = nil. | |
540 If HOOK is non-nil, it should be a function of no arguments; | |
541 it is called after EXPANSION is inserted. | |
542 If EXPANSION is not a string, the abbrev is a special one, | |
543 which does not expand in the usual way but only runs HOOK. | |
544 | |
545 PROPS is a property list. The following properties are special: | |
546 - `count': the value for the abbrev's usage-count, which is incremented each time | |
547 the abbrev is used (the default is zero). | |
548 - `system-flag': if non-nil, says that this is a \"system\" abbreviation | |
549 which should not be saved in the user's abbreviation file. | |
550 Unless `system-flag' is `force', a system abbreviation will not | |
551 overwrite a non-system abbreviation of the same name. | |
552 - `:case-fixed': non-nil means that abbreviations are looked up without | |
553 case-folding, and the expansion is not capitalized/upcased. | |
554 - `:enable-function': a function of no argument which returns non-nil iff the | |
555 abbrev should be used for a particular call of `expand-abbrev'. | |
556 | |
557 An obsolete but still supported calling form is: | |
558 | |
559 \(define-abbrev TABLE NAME EXPANSION &optional HOOK COUNT SYSTEM-FLAG)." | |
560 (when (and (consp props) (or (null (car props)) (numberp (car props)))) | |
561 ;; Old-style calling convention. | |
562 (setq props (list* 'count (car props) | |
563 (if (cadr props) (list 'system-flag (cadr props)))))) | |
564 (unless (plist-get props 'count) | |
565 (setq props (plist-put props 'count 0))) | |
566 (let ((system-flag (plist-get props 'system-flag)) | |
567 (sym (intern name table))) | |
568 ;; Don't override a prior user-defined abbrev with a system abbrev, | |
569 ;; unless system-flag is `force'. | |
570 (unless (and (not (memq system-flag '(nil force))) | |
571 (boundp sym) (symbol-value sym) | |
572 (not (abbrev-get sym 'system-flag))) | |
573 (unless (or system-flag | |
574 (and (boundp sym) (fboundp sym) | |
575 ;; load-file-name | |
576 (equal (symbol-value sym) expansion) | |
577 (equal (symbol-function sym) hook))) | |
578 (setq abbrevs-changed t)) | |
579 (set sym expansion) | |
580 (fset sym hook) | |
581 (setplist sym props) | |
582 (abbrev-table-put table :abbrev-table-modiff | |
583 (1+ (abbrev-table-get table :abbrev-table-modiff)))) | |
584 name)) | |
585 | |
586 (defun abbrev--check-chars (abbrev global) | |
587 "Check if the characters in ABBREV have word syntax in either the | |
588 current (if global is nil) or standard syntax table." | |
589 (with-syntax-table | |
590 (cond ((null global) (standard-syntax-table)) | |
591 ;; ((syntax-table-p global) global) | |
592 (t (syntax-table))) | |
593 (when (string-match "\\W" abbrev) | |
594 (let ((badchars ()) | |
595 (pos 0)) | |
596 (while (string-match "\\W" abbrev pos) | |
597 (pushnew (aref abbrev (match-beginning 0)) badchars) | |
598 (setq pos (1+ pos))) | |
599 (error "Some abbrev characters (%s) are not word constituents %s" | |
600 (apply 'string (nreverse badchars)) | |
601 (if global "in the standard syntax" "in this mode")))))) | |
602 | |
603 (defun define-global-abbrev (abbrev expansion) | |
604 "Define ABBREV as a global abbreviation for EXPANSION. | |
605 The characters in ABBREV must all be word constituents in the standard | |
606 syntax table." | |
607 (interactive "sDefine global abbrev: \nsExpansion for %s: ") | |
608 (abbrev--check-chars abbrev 'global) | |
609 (define-abbrev global-abbrev-table (downcase abbrev) expansion)) | |
610 | |
611 (defun define-mode-abbrev (abbrev expansion) | |
612 "Define ABBREV as a mode-specific abbreviation for EXPANSION. | |
613 The characters in ABBREV must all be word-constituents in the current mode." | |
614 (interactive "sDefine mode abbrev: \nsExpansion for %s: ") | |
615 (unless local-abbrev-table | |
616 (error "Major mode has no abbrev table")) | |
617 (abbrev--check-chars abbrev nil) | |
618 (define-abbrev local-abbrev-table (downcase abbrev) expansion)) | |
619 | |
620 (defun abbrev--active-tables (&optional tables) | |
621 "Return the list of abbrev tables currently active. | |
622 TABLES if non-nil overrides the usual rules. It can hold | |
623 either a single abbrev table or a list of abbrev tables." | |
624 ;; We could just remove the `tables' arg and let callers use | |
625 ;; (or table (abbrev--active-tables)) but then they'd have to be careful | |
626 ;; to treat the distinction between a single table and a list of tables. | |
627 (cond | |
628 ((consp tables) tables) | |
629 ((vectorp tables) (list tables)) | |
630 (t | |
631 (let ((tables (if (listp local-abbrev-table) | |
632 (append local-abbrev-table | |
633 (list global-abbrev-table)) | |
634 (list local-abbrev-table global-abbrev-table)))) | |
635 ;; Add the minor-mode abbrev tables. | |
636 (dolist (x abbrev-minor-mode-table-alist) | |
637 (when (and (symbolp (car x)) (boundp (car x)) (symbol-value (car x))) | |
638 (setq tables | |
639 (if (listp (cdr x)) | |
640 (append (cdr x) tables) (cons (cdr x) tables))))) | |
641 tables)))) | |
642 | |
643 | |
644 (defun abbrev-symbol (abbrev &optional table) | |
645 "Return the symbol representing abbrev named ABBREV. | |
646 This symbol's name is ABBREV, but it is not the canonical symbol of that name; | |
647 it is interned in an abbrev-table rather than the normal obarray. | |
648 The value is nil if that abbrev is not defined. | |
649 Optional second arg TABLE is abbrev table to look it up in. | |
650 The default is to try buffer's mode-specific abbrev table, then global table." | |
651 (let ((tables (abbrev--active-tables table)) | |
652 sym) | |
653 (while (and tables (not (symbol-value sym))) | |
654 (let ((table (pop tables)) | |
655 (case-fold (not (abbrev-table-get table :case-fixed)))) | |
656 (setq tables (append (abbrev-table-get table :parents) tables)) | |
657 ;; In case the table doesn't set :case-fixed but some of the | |
658 ;; abbrevs do, we have to be careful. | |
659 (setq sym | |
660 ;; First try without case-folding. | |
661 (or (intern-soft abbrev table) | |
662 (when case-fold | |
663 ;; We didn't find any abbrev, try case-folding. | |
664 (let ((sym (intern-soft (downcase abbrev) table))) | |
665 ;; Only use it if it doesn't require :case-fixed. | |
666 (and sym (not (abbrev-get sym :case-fixed)) | |
667 sym))))))) | |
668 (if (symbol-value sym) | |
669 sym))) | |
670 | |
671 | |
672 (defun abbrev-expansion (abbrev &optional table) | |
673 "Return the string that ABBREV expands into in the current buffer. | |
674 Optionally specify an abbrev table as second arg; | |
675 then ABBREV is looked up in that table only." | |
676 (symbol-value (abbrev-symbol abbrev table))) | |
677 | |
678 | |
679 (defun abbrev--before-point () | |
680 "Try and find an abbrev before point. Return it if found, nil otherwise." | |
681 (unless (eq abbrev-start-location-buffer (current-buffer)) | |
682 (setq abbrev-start-location nil)) | |
683 | |
684 (let ((tables (abbrev--active-tables)) | |
685 (pos (point)) | |
686 start end name res) | |
687 | |
688 (if abbrev-start-location | |
689 (progn | |
690 (setq start abbrev-start-location) | |
691 (setq abbrev-start-location nil) | |
692 ;; Remove the hyphen inserted by `abbrev-prefix-mark'. | |
693 (if (and (< start (point-max)) | |
694 (eq (char-after start) ?-)) | |
695 (delete-region start (1+ start))) | |
696 (skip-syntax-backward " ") | |
697 (setq end (point)) | |
698 (setq name (buffer-substring start end)) | |
699 (goto-char pos) ; Restore point. | |
700 (list (abbrev-symbol name tables) name start end)) | |
701 | |
702 (while (and tables (not (car res))) | |
703 (let* ((table (pop tables)) | |
704 (enable-fun (abbrev-table-get table :enable-function))) | |
705 (setq tables (append (abbrev-table-get table :parents) tables)) | |
706 (setq res | |
707 (and (or (not enable-fun) (funcall enable-fun)) | |
708 (looking-back (or (abbrev-table-get table :regexp) | |
709 "\\<\\(\\w+\\)\\W*") | |
710 (line-beginning-position)) | |
711 (setq start (match-beginning 1)) | |
712 (setq end (match-end 1)) | |
713 (setq name (buffer-substring start end)) | |
714 ;; This will also look it up in parent tables. | |
715 ;; This is not on purpose, but it seems harmless. | |
716 (list (abbrev-symbol name table) name start end))) | |
717 ;; Restore point. | |
718 (goto-char pos))) | |
719 res))) | |
720 | |
721 (defvar abbrev-expand-functions nil | |
722 "Wrapper hook around `expand-abbrev'. | |
723 The functions on this special hook are called with one argument: | |
724 a function that performs the abbrev expansion. It should return | |
725 the abbrev symbol if expansion took place.") | |
726 | |
727 (defun expand-abbrev () | |
728 "Expand the abbrev before point, if there is an abbrev there. | |
729 Effective when explicitly called even when `abbrev-mode' is nil. | |
730 Returns the abbrev symbol, if expansion took place." | |
731 (interactive) | |
732 (run-hooks 'pre-abbrev-expand-hook) | |
733 (abbrev-with-wrapper-hook abbrev-expand-functions | |
734 (destructuring-bind (&optional sym name wordstart wordend) | |
735 (abbrev--before-point) | |
736 (when sym | |
737 (let ((value sym)) | |
738 (unless (or ;; executing-kbd-macro | |
739 noninteractive | |
740 (window-minibuffer-p (selected-window))) | |
741 ;; Add an undo boundary, in case we are doing this for | |
742 ;; a self-inserting command which has avoided making one so far. | |
743 (undo-boundary)) | |
744 ;; Now sym is the abbrev symbol. | |
745 (setq last-abbrev-text name) | |
746 (setq last-abbrev sym) | |
747 (setq last-abbrev-location wordstart) | |
748 ;; Increment use count. | |
749 (abbrev-put sym 'count (1+ (abbrev-get sym 'count))) | |
750 ;; If this abbrev has an expansion, delete the abbrev | |
751 ;; and insert the expansion. | |
752 (when (stringp (symbol-value sym)) | |
753 (goto-char wordend) | |
754 (insert (symbol-value sym)) | |
755 (delete-region wordstart wordend) | |
756 (let ((case-fold-search nil)) | |
757 ;; If the abbrev's name is different from the buffer text (the | |
758 ;; only difference should be capitalization), then we may want | |
759 ;; to adjust the capitalization of the expansion. | |
760 (when (and (not (equal name (symbol-name sym))) | |
761 (string-match "[[:upper:]]" name)) | |
762 (if (not (string-match "[[:lower:]]" name)) | |
763 ;; Abbrev was all caps. If expansion is multiple words, | |
764 ;; normally capitalize each word. | |
765 (if (and (not abbrev-all-caps) | |
766 (save-excursion | |
767 (> (progn (backward-word 1) (point)) | |
768 (progn (goto-char wordstart) | |
769 (forward-word 1) (point))))) | |
770 (upcase-initials-region wordstart (point)) | |
771 (upcase-region wordstart (point))) | |
772 ;; Abbrev included some caps. Cap first initial of expansion. | |
773 (let ((end (point))) | |
774 ;; Find the initial. | |
775 (goto-char wordstart) | |
776 (skip-syntax-forward "^w" (1- end)) | |
777 ;; Change just that. | |
778 (upcase-initials-region (point) (1+ (point)))))))) | |
779 (when (symbol-function sym) | |
780 (let* ((hook (symbol-function sym)) | |
781 (expanded | |
782 ;; If the abbrev has a hook function, run it. | |
783 (funcall hook))) | |
784 ;; In addition, if the hook function is a symbol with | |
785 ;; a non-nil `no-self-insert' property, let the value it | |
786 ;; returned specify whether we consider that an expansion took | |
787 ;; place. If it returns nil, no expansion has been done. | |
788 (if (and (symbolp hook) | |
789 (null expanded) | |
790 (get hook 'no-self-insert)) | |
791 (setq value nil)))) | |
792 value))))) | |
793 | |
794 (defun unexpand-abbrev () | |
795 "Undo the expansion of the last abbrev that expanded. | |
796 This differs from ordinary undo in that other editing done since then | |
797 is not undone." | |
798 (interactive) | |
799 (save-excursion | |
800 (unless (or (< last-abbrev-location (point-min)) | |
801 (> last-abbrev-location (point-max))) | |
802 (goto-char last-abbrev-location) | |
803 (when (stringp last-abbrev-text) | |
804 ;; This isn't correct if last-abbrev's hook was used | |
805 ;; to do the expansion. | |
806 (let ((val (symbol-value last-abbrev))) | |
807 (unless (stringp val) | |
808 (error "value of abbrev-symbol must be a string")) | |
809 (delete-region (point) (+ (point) (length val))) | |
810 ;; Don't inherit properties here; just copy from old contents. | |
811 (insert last-abbrev-text) | |
812 (setq last-abbrev-text nil)))))) | |
813 | |
814 (defun abbrev--write (sym) | |
815 "Write the abbrev in a `read'able form. | |
816 Only writes the non-system abbrevs. | |
817 Presumes that `standard-output' points to `current-buffer'." | |
818 (unless (or (null (symbol-value sym)) (abbrev-get sym 'system-flag)) | |
819 (insert " (") | |
820 (prin1 name) | |
821 (insert " ") | |
822 (prin1 (symbol-value sym)) | |
823 (insert " ") | |
824 (prin1 (symbol-function sym)) | |
825 (insert " ") | |
826 (prin1 (abbrev-get sym 'count)) | |
827 (insert ")\n"))) | |
828 | |
829 (defun abbrev--describe (sym) | |
830 (when (symbol-value sym) | |
831 (prin1 (symbol-name sym)) | |
832 (if (null (abbrev-get sym 'system-flag)) | |
833 (indent-to 15 1) | |
834 (insert " (sys)") | |
835 (indent-to 20 1)) | |
836 (prin1 (abbrev-get sym 'count)) | |
837 (indent-to 20 1) | |
838 (prin1 (symbol-value sym)) | |
839 (when (symbol-function sym) | |
840 (indent-to 45 1) | |
841 (prin1 (symbol-function sym))) | |
842 (terpri))) | |
843 | |
844 (defun insert-abbrev-table-description (name &optional readable) | |
845 "Insert before point a full description of abbrev table named NAME. | |
846 NAME is a symbol whose value is an abbrev table. | |
847 If optional 2nd arg READABLE is non-nil, a human-readable description | |
848 is inserted. Otherwise the description is an expression, | |
849 a call to `define-abbrev-table', which would | |
850 define the abbrev table NAME exactly as it is currently defined. | |
851 | |
852 Abbrevs marked as \"system abbrevs\" are omitted." | |
853 (let ((table (symbol-value name)) | |
854 (symbols ())) | |
855 (mapatoms (lambda (sym) (if (symbol-value sym) (push sym symbols))) table) | |
856 (setq symbols (sort symbols 'string-lessp)) | |
857 (let ((standard-output (current-buffer))) | |
858 (if readable | |
859 (progn | |
860 (insert "(") | |
861 (prin1 name) | |
862 (insert ")\n\n") | |
863 (mapc 'abbrev--describe symbols) | |
864 (insert "\n\n")) | |
865 (insert "(define-abbrev-table '") | |
866 (prin1 name) | |
867 (insert " '(") | |
868 (mapc 'abbrev--write symbols) | |
869 (insert " ))\n\n")) | |
870 nil))) | |
871 | |
872 (defun define-abbrev-table (tablename definitions | |
873 &optional docstring &rest props) | |
874 "Define TABLENAME (a symbol) as an abbrev table name. | |
875 Define abbrevs in it according to DEFINITIONS, which is a list of elements | |
876 of the form (ABBREVNAME EXPANSION HOOK USECOUNT SYSTEMFLAG). | |
877 \(If the list is shorter than that, omitted elements default to nil). | |
878 PROPS is a property list to apply to the table. | |
879 Properties with special meaning: | |
880 - `:parents' contains a list of abbrev tables from which this table inherits | |
881 abbreviations. | |
882 - `:case-fixed' non-nil means that abbreviations are looked up without | |
883 case-folding, and the expansion is not capitalized/upcased. | |
884 - `:regexp' describes the form of abbrevs. It defaults to \\<\\(\\w+\\)\\W* which | |
885 means that an abbrev can only be a single word. The submatch 1 is treated | |
886 as the potential name of an abbrev. | |
887 - `:enable-function' can be set to a function of no argument which returns | |
888 non-nil iff the abbrevs in this table should be used for this instance | |
889 of `expand-abbrev'." | |
890 (let ((table (if (boundp tablename) (symbol-value tablename)))) | |
891 (unless table | |
892 (setq table (make-abbrev-table props)) | |
893 (set tablename table) | |
894 (push tablename abbrev-table-name-list)) | |
895 (when (stringp docstring) | |
896 (put tablename 'variable-documentation docstring)) | |
897 (dolist (elt definitions) | |
898 (apply 'define-abbrev table elt)))) | |
899 | |
366 (provide 'abbrev) | 900 (provide 'abbrev) |
367 | 901 |
368 ;; arch-tag: dbd6f3ae-dfe3-40ba-b00f-f9e3ff960df5 | 902 ;; arch-tag: dbd6f3ae-dfe3-40ba-b00f-f9e3ff960df5 |
369 ;;; abbrev.el ends here | 903 ;;; abbrev.el ends here |