diff options
| author | Kenichi Handa | 1999-12-15 00:42:43 +0000 |
|---|---|---|
| committer | Kenichi Handa | 1999-12-15 00:42:43 +0000 |
| commit | 817e162fea669bc352b6c85314856d10147290ea (patch) | |
| tree | 7da2aec731639ea70018335cc1960042cd7e75a8 | |
| parent | 72594565dbd47168be99134467cbbd15172cd6bc (diff) | |
| download | emacs-817e162fea669bc352b6c85314856d10147290ea.tar.gz emacs-817e162fea669bc352b6c85314856d10147290ea.zip | |
(quail-install-map): New optional arg
NAME.
(quail-get-translation): If DEF is a symbol but not a function,
ignore it.
(quail-start-translation): Put a key sequence undefined in the
translation keymap in unread-command-events, not generated-events.
Return parameterized event (compose-last-chars N) if the input
characters should be composed.
(quail-map-definition): If DEF is t, treat it as nil.
(quail-delete-last-char): Delete the quail region.
(quail-show-translations): Don't show list of translations if the
quail package is deterministic.
(quail-completion-max-depth): New variable.
(quail-completion-1): Pay attention to the above variable. Fix
for the case that a translation is a function.
(quail-map-from-table, quail-map-from-table-1,
quail-map-from-table-2): New functions.
(quail-lookup-map-and-concat): New function
| -rw-r--r-- | lisp/international/quail.el | 173 |
1 files changed, 160 insertions, 13 deletions
diff --git a/lisp/international/quail.el b/lisp/international/quail.el index d3bdafc5ad8..018fdd9ee07 100644 --- a/lisp/international/quail.el +++ b/lisp/international/quail.el | |||
| @@ -673,8 +673,12 @@ If TRANSLATION is a Quail map or a function symbol which returns a Quail map, | |||
| 673 | map))) | 673 | map))) |
| 674 | 674 | ||
| 675 | ;;;###autoload | 675 | ;;;###autoload |
| 676 | (defun quail-install-map (map) | 676 | (defun quail-install-map (map &optional name) |
| 677 | "Install the Quail map MAP in the current Quail package. | 677 | "Install the Quail map MAP in the current Quail package. |
| 678 | |||
| 679 | Optional 2nd arg NAME, if non-nil, is a name of Quail package for | ||
| 680 | which to install MAP. | ||
| 681 | |||
| 678 | The installed map can be referred by the function `quail-map'." | 682 | The installed map can be referred by the function `quail-map'." |
| 679 | (if (null quail-current-package) | 683 | (if (null quail-current-package) |
| 680 | (error "No current Quail package")) | 684 | (error "No current Quail package")) |
| @@ -786,8 +790,10 @@ where VECTOR is a vector of candidates (character or string) for | |||
| 786 | the translation, and INDEX points into VECTOR to specify the currently | 790 | the translation, and INDEX points into VECTOR to specify the currently |
| 787 | selected translation." | 791 | selected translation." |
| 788 | (if (and def (symbolp def)) | 792 | (if (and def (symbolp def)) |
| 789 | ;; DEF is a symbol of a function which returns valid translation. | 793 | (if (functionp def) |
| 790 | (setq def (funcall def key len))) | 794 | ;; DEF is a symbol of a function which returns valid translation. |
| 795 | (setq def (funcall def key len)) | ||
| 796 | (setq def nil))) | ||
| 791 | (if (and (consp def) (not (vectorp (cdr def)))) | 797 | (if (and (consp def) (not (vectorp (cdr def)))) |
| 792 | (setq def (car def))) | 798 | (setq def (car def))) |
| 793 | 799 | ||
| @@ -955,17 +961,33 @@ The returned value is a Quail map specific to KEY." | |||
| 955 | (quail-error (message "%s" (cdr err)) (beep)))) | 961 | (quail-error (message "%s" (cdr err)) (beep)))) |
| 956 | ;; KEYSEQ is not defined in the translation keymap. | 962 | ;; KEYSEQ is not defined in the translation keymap. |
| 957 | ;; Let's return the event(s) to the caller. | 963 | ;; Let's return the event(s) to the caller. |
| 958 | (setq generated-events | 964 | (setq unread-command-events |
| 959 | (string-to-list (this-single-command-raw-keys))) | 965 | (string-to-list (this-single-command-raw-keys))) |
| 960 | (setq quail-translating nil)))) | 966 | (setq quail-translating nil)))) |
| 961 | (quail-delete-region) | 967 | (quail-delete-region) |
| 962 | (if (and quail-current-str (> (length quail-current-str) 0)) | 968 | (if (and quail-current-str (> (length quail-current-str) 0)) |
| 963 | (setq generated-events | 969 | (let* ((len (length quail-current-str)) |
| 964 | (append (string-to-list | 970 | (idx 0) |
| 965 | (if enable-multibyte-characters | 971 | (val (find-composition 0 len quail-current-str)) |
| 966 | quail-current-str | 972 | char) |
| 967 | (string-make-unibyte quail-current-str))) | 973 | ;; Push characters in quail-current-str one by one to |
| 968 | generated-events))) | 974 | ;; generated-events while interleaving it with a special |
| 975 | ;; event (compose-last-chars LEN) at each composition | ||
| 976 | ;; end. | ||
| 977 | (while (<= idx len) | ||
| 978 | (when (and val (= idx (nth 1 val))) | ||
| 979 | (setq generated-events | ||
| 980 | (cons (list 'compose-last-chars (- idx (car val))) | ||
| 981 | generated-events)) | ||
| 982 | (setq val (find-composition idx len quail-current-str))) | ||
| 983 | (when (< idx len) | ||
| 984 | (setq char (aref quail-current-str idx)) | ||
| 985 | (or enable-multibyte-characters | ||
| 986 | (setq char (multibyte-char-to-unibyte char))) | ||
| 987 | (setq generated-events (cons char generated-events))) | ||
| 988 | (setq idx (1+ idx))) | ||
| 989 | ;; Reorder generated-events. | ||
| 990 | (setq generated-events (nreverse generated-events)))) | ||
| 969 | (if (and input-method-exit-on-first-char generated-events) | 991 | (if (and input-method-exit-on-first-char generated-events) |
| 970 | (list (car generated-events)) | 992 | (list (car generated-events)) |
| 971 | generated-events)) | 993 | generated-events)) |
| @@ -1125,6 +1147,8 @@ The returned value is a Quail map specific to KEY." | |||
| 1125 | (let ((def (car map))) | 1147 | (let ((def (car map))) |
| 1126 | (if (and (consp def) (not (vectorp (cdr def)))) | 1148 | (if (and (consp def) (not (vectorp (cdr def)))) |
| 1127 | (setq def (car def))) | 1149 | (setq def (car def))) |
| 1150 | (if (eq def t) | ||
| 1151 | (setq def nil)) | ||
| 1128 | def)) | 1152 | def)) |
| 1129 | 1153 | ||
| 1130 | ;; Return a string to be shown as the current translation of key | 1154 | ;; Return a string to be shown as the current translation of key |
| @@ -1339,6 +1363,7 @@ sequence counting from the head." | |||
| 1339 | (if (= (length quail-current-key) 1) | 1363 | (if (= (length quail-current-key) 1) |
| 1340 | (quail-abort-translation) | 1364 | (quail-abort-translation) |
| 1341 | (setq quail-current-key (substring quail-current-key 0 -1)) | 1365 | (setq quail-current-key (substring quail-current-key 0 -1)) |
| 1366 | (quail-delete-region) | ||
| 1342 | (quail-update-translation (quail-translate-key)))) | 1367 | (quail-update-translation (quail-translate-key)))) |
| 1343 | 1368 | ||
| 1344 | ;; For conversion mode. | 1369 | ;; For conversion mode. |
| @@ -1636,7 +1661,8 @@ or in a newly created frame (if the selected frame has no other windows)." | |||
| 1636 | (insert "]"))) | 1661 | (insert "]"))) |
| 1637 | 1662 | ||
| 1638 | ;; Show list of translations. | 1663 | ;; Show list of translations. |
| 1639 | (if current-translations | 1664 | (if (and current-translations |
| 1665 | (not (quail-deterministic))) | ||
| 1640 | (let* ((indices (car current-translations)) | 1666 | (let* ((indices (car current-translations)) |
| 1641 | (cur (car indices)) | 1667 | (cur (car indices)) |
| 1642 | (start (nth 1 indices)) | 1668 | (start (nth 1 indices)) |
| @@ -1657,10 +1683,13 @@ or in a newly created frame (if the selected frame has no other windows)." | |||
| 1657 | (setq idx (1+ idx))))) | 1683 | (setq idx (1+ idx))))) |
| 1658 | ))) | 1684 | ))) |
| 1659 | 1685 | ||
| 1686 | (defvar quail-completion-max-depth 5 | ||
| 1687 | "The maximum depth of Quail completion list.") | ||
| 1688 | |||
| 1660 | (defun quail-completion () | 1689 | (defun quail-completion () |
| 1661 | "List all completions for the current key. | 1690 | "List all completions for the current key. |
| 1662 | All possible translations of the current key and whole possible longer keys | 1691 | All possible translations of the current key and whole possible longer keys |
| 1663 | are shown." | 1692 | are shown (at most to the depth specified `quail-completion-max-depth')." |
| 1664 | (interactive) | 1693 | (interactive) |
| 1665 | (quail-setup-completion-buf) | 1694 | (quail-setup-completion-buf) |
| 1666 | (let ((win (get-buffer-window quail-completion-buf 'visible)) | 1695 | (let ((win (get-buffer-window quail-completion-buf 'visible)) |
| @@ -1700,10 +1729,12 @@ All possible translations of the current key and whole possible longer keys | |||
| 1700 | (quail-completion-list-translations map key (+ indent len 1)) | 1729 | (quail-completion-list-translations map key (+ indent len 1)) |
| 1701 | (insert " -\n")) | 1730 | (insert " -\n")) |
| 1702 | (setq indent (+ indent 2)) | 1731 | (setq indent (+ indent 2)) |
| 1703 | (if (cdr map) | 1732 | (if (and (cdr map) (< (/ (1- indent) 2) quail-completion-max-depth)) |
| 1704 | (let ((l (cdr map)) | 1733 | (let ((l (cdr map)) |
| 1705 | (newkey (make-string (1+ len) 0)) | 1734 | (newkey (make-string (1+ len) 0)) |
| 1706 | (i 0)) | 1735 | (i 0)) |
| 1736 | (if (functionp l) | ||
| 1737 | (setq l (funcall l))) | ||
| 1707 | ;; Set KEY in the first LEN characters of NEWKEY. | 1738 | ;; Set KEY in the first LEN characters of NEWKEY. |
| 1708 | (while (< i len) | 1739 | (while (< i len) |
| 1709 | (aset newkey i (aref key i)) | 1740 | (aset newkey i (aref key i)) |
| @@ -1965,6 +1996,122 @@ key binding | |||
| 1965 | (message nil) | 1996 | (message nil) |
| 1966 | (quail-update-guidance) | 1997 | (quail-update-guidance) |
| 1967 | )))) | 1998 | )))) |
| 1999 | |||
| 2000 | ;; Quail map generator from state transition table. | ||
| 2001 | |||
| 2002 | (defun quail-map-from-table (table) | ||
| 2003 | "Make quail map from state transition table TABLE. | ||
| 2004 | |||
| 2005 | TABLE is an alist, the form is: | ||
| 2006 | ((STATE-0 TRANSITION-0-1 TRANSITION-0-2 ...) (STATE-1 ...) ...) | ||
| 2007 | |||
| 2008 | STATE-n are symbols to denote state. STATE-0 is the initial state. | ||
| 2009 | |||
| 2010 | TRANSITION-n-m are transition rules from STATE-n, and have the form | ||
| 2011 | \(RULES . STATE-x) or RULES, where STATE-x is one of STATE-n above, | ||
| 2012 | RULES is a symbol whose value is an alist of keys \(string) vs the | ||
| 2013 | correponding characters or strings. The format of the symbol value of | ||
| 2014 | RULES is the same as arguments to `quail-define-rules'. | ||
| 2015 | |||
| 2016 | If TRANSITION-n-m has the form (RULES . STATE-x), it means that | ||
| 2017 | STATE-n transits to STATE-x when keys in RULES are input. Recursive | ||
| 2018 | transition is allowed, i.e. STATE-x may be STATE-n. | ||
| 2019 | |||
| 2020 | If TRANSITION-n-m has the form RULES, the transition terminates | ||
| 2021 | when keys in RULES are input. | ||
| 2022 | |||
| 2023 | The generated map can be set for the current Quail package by the | ||
| 2024 | function `quail-install-map' (which see)." | ||
| 2025 | (let ((state-alist (mapcar (lambda (x) (list (car x))) table)) | ||
| 2026 | tail elt) | ||
| 2027 | ;; STATE-ALIST is an alist of states vs the correponding sub Quail | ||
| 2028 | ;; map. It is now initialized to ((STATE-0) (STATE-1) ...). | ||
| 2029 | ;; Set key sequence mapping rules in cdr part of each element. | ||
| 2030 | (while table | ||
| 2031 | (quail-map-from-table-1 state-alist (car table)) | ||
| 2032 | (setq table (cdr table))) | ||
| 2033 | |||
| 2034 | ;; Now STATE-ALIST has the form ((STATE-0 MAPPING-RULES) ...). | ||
| 2035 | ;; Elements of MAPPING-RULES may have the form (STATE-x). Replace | ||
| 2036 | ;; them with MAPPING-RULES of STATE-x to make elements of | ||
| 2037 | ;; STATE-ALIST valid Quail maps. | ||
| 2038 | (setq tail state-alist) | ||
| 2039 | (while tail | ||
| 2040 | (setq elt (car tail) tail (cdr tail)) | ||
| 2041 | (quail-map-from-table-2 state-alist elt)) | ||
| 2042 | |||
| 2043 | ;; Return the Quail map for the initial state. | ||
| 2044 | (car state-alist))) | ||
| 2045 | |||
| 2046 | ;; STATE-INFO has the form (STATE TRANSITION ...). Set key sequence | ||
| 2047 | ;; mapping rules in the element of STATE-ALIST that corresponds to | ||
| 2048 | ;; STATE according to TRANSITION ... | ||
| 2049 | (defun quail-map-from-table-1 (state-alist state-info) | ||
| 2050 | (let* ((state (car state-info)) | ||
| 2051 | (map (assq state state-alist)) | ||
| 2052 | (transitions (cdr state-info)) | ||
| 2053 | elt) | ||
| 2054 | (while transitions | ||
| 2055 | (setq elt (car transitions) transitions (cdr transitions)) | ||
| 2056 | (let (rules dst-state key trans) | ||
| 2057 | ;; ELT has the form (RULES-SYMBOL . STATE-x) or RULES-SYMBOL. | ||
| 2058 | ;; STATE-x is one of car parts of STATE-ALIST's elements. | ||
| 2059 | (if (consp elt) | ||
| 2060 | (setq rules (symbol-value (car elt)) | ||
| 2061 | ;; Set (STATE-x) as branches for all keys in RULES. | ||
| 2062 | ;; It is replaced with actual branches for STATE-x | ||
| 2063 | ;; later in `quail-map-from-table-2'. | ||
| 2064 | dst-state (list (cdr elt))) | ||
| 2065 | (setq rules (symbol-value elt))) | ||
| 2066 | (while rules | ||
| 2067 | (setq key (car (car rules)) trans (cdr (car rules)) | ||
| 2068 | rules (cdr rules)) | ||
| 2069 | (if (stringp trans) | ||
| 2070 | (if (= (length trans) 1) | ||
| 2071 | (setq trans (aref trans 0)) | ||
| 2072 | (setq trans (string-to-vector trans)))) | ||
| 2073 | (set-nested-alist key trans map nil dst-state)))))) | ||
| 2074 | |||
| 2075 | ;; ELEMENT is one element of STATE-ALIST. ELEMENT is a nested alist; | ||
| 2076 | ;; the form is: | ||
| 2077 | ;; (STATE (CHAR NESTED-ALIST) ...) | ||
| 2078 | ;; NESTED-ALIST is a nested alist; the form is: | ||
| 2079 | ;; (TRANS (CHAR NESTED-ALIST) ...) | ||
| 2080 | ;; or | ||
| 2081 | ;; (TRANS (CHAR NESTED-ALIST) ... . (STATE-x)) | ||
| 2082 | ;; Here, the task is to replace all occurrences of (STATE-x) with: | ||
| 2083 | ;; (cdr (assq STATE-x STATE-ALIST)) | ||
| 2084 | |||
| 2085 | (defun quail-map-from-table-2 (state-alist element) | ||
| 2086 | (let ((prev element) | ||
| 2087 | (tail (cdr element)) | ||
| 2088 | elt) | ||
| 2089 | (while (cdr tail) | ||
| 2090 | (setq elt (car tail) prev tail tail (cdr tail)) | ||
| 2091 | (quail-map-from-table-2 state-alist (cdr elt))) | ||
| 2092 | (setq elt (car tail)) | ||
| 2093 | (if (consp elt) | ||
| 2094 | (quail-map-from-table-2 state-alist (cdr elt)) | ||
| 2095 | (setcdr prev (cdr (assq elt state-alist)))))) | ||
| 2096 | |||
| 2097 | ;; Concatenate translations for all heading substrings of KEY in the | ||
| 2098 | ;; current Quail map. Here, `heading substring' means (substring KEY | ||
| 2099 | ;; 0 LEN), where LEN is 1, 2, ... (length KEY). | ||
| 2100 | (defun quail-lookup-map-and-concat (key) | ||
| 2101 | (let* ((len (length key)) | ||
| 2102 | (translation-list nil) | ||
| 2103 | map) | ||
| 2104 | (while (> len 0) | ||
| 2105 | (setq map (quail-lookup-key key len) | ||
| 2106 | len (1- len)) | ||
| 2107 | (if map | ||
| 2108 | (let* ((def (quail-map-definition map)) | ||
| 2109 | (trans (if (consp def) (aref (cdr def) (car (car def))) | ||
| 2110 | def))) | ||
| 2111 | (if (integerp trans) | ||
| 2112 | (setq trans (char-to-string trans))) | ||
| 2113 | (setq translation-list (cons trans translation-list))))) | ||
| 2114 | (apply 'concat translation-list))) | ||
| 1968 | 2115 | ||
| 1969 | 2116 | ||
| 1970 | (defvar quail-directory-name "quail" | 2117 | (defvar quail-directory-name "quail" |