diff options
| author | Stefan Monnier | 2013-03-13 23:00:18 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-03-13 23:00:18 -0400 |
| commit | c8cefd6a819caa8ad4d863c135a92abc3d33b791 (patch) | |
| tree | 03e8f712536868720df913947acb3718a0caa8ee | |
| parent | b2e37dad6876445f53037e82280cc2b77e6a5086 (diff) | |
| download | emacs-c8cefd6a819caa8ad4d863c135a92abc3d33b791.tar.gz emacs-c8cefd6a819caa8ad4d863c135a92abc3d33b791.zip | |
* leim/quail/latin-ltx.el: Resolve conflicts.
(latin-ltx--mark-map, latin-ltx--mark-re): New constants.
(latin-ltx--define-rules): Check for conflicts. Eval `re's.
(rules): Use tighter regexps to avoid conflicts.
Consolidate the various rules for combining marks.
Fixes: debbugs:13950
| -rw-r--r-- | leim/ChangeLog | 8 | ||||
| -rw-r--r-- | leim/quail/latin-ltx.el | 203 |
2 files changed, 84 insertions, 127 deletions
diff --git a/leim/ChangeLog b/leim/ChangeLog index 21757b8472c..cef14a1a8f7 100644 --- a/leim/ChangeLog +++ b/leim/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2013-03-14 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * quail/latin-ltx.el: Resolve conflicts (bug#13950). | ||
| 4 | (latin-ltx--mark-map, latin-ltx--mark-re): New constants. | ||
| 5 | (latin-ltx--define-rules): Check for conflicts. Eval `re's. | ||
| 6 | (rules): Use tighter regexps to avoid conflicts. | ||
| 7 | Consolidate the various rules for combining marks. | ||
| 8 | |||
| 1 | 2013-03-11 Glenn Morris <rgm@gnu.org> | 9 | 2013-03-11 Glenn Morris <rgm@gnu.org> |
| 2 | 10 | ||
| 3 | * Version 24.3 released. | 11 | * Version 24.3 released. |
diff --git a/leim/quail/latin-ltx.el b/leim/quail/latin-ltx.el index 024bb62c970..30836b8e752 100644 --- a/leim/quail/latin-ltx.el +++ b/leim/quail/latin-ltx.el | |||
| @@ -43,6 +43,26 @@ system, including many technical ones. Examples: | |||
| 43 | t t nil nil nil nil nil nil nil t) | 43 | t t nil nil nil nil nil nil nil t) |
| 44 | 44 | ||
| 45 | (eval-when-compile | 45 | (eval-when-compile |
| 46 | (require 'cl-lib) | ||
| 47 | |||
| 48 | (defconst latin-ltx--mark-map | ||
| 49 | '(("DOT BELOW" . "d") | ||
| 50 | ("DOT ABOVE" . ".") | ||
| 51 | ("OGONEK" . "k") | ||
| 52 | ("CEDILLA" . "c") | ||
| 53 | ("CARON" . "v") | ||
| 54 | ;; ("HOOK ABOVE" . ??) | ||
| 55 | ("MACRON" . "=") | ||
| 56 | ("BREVE" . "u") | ||
| 57 | ("TILDE" . "~") | ||
| 58 | ("GRAVE" . "`") | ||
| 59 | ("CIRCUMFLEX" . "^") | ||
| 60 | ("DIAERESIS" . "\"") | ||
| 61 | ("DOUBLE ACUTE" . "H") | ||
| 62 | ("ACUTE" . "'"))) | ||
| 63 | |||
| 64 | (defconst latin-ltx--mark-re (regexp-opt (mapcar #'car latin-ltx--mark-map))) | ||
| 65 | |||
| 46 | (defun latin-ltx--ascii-p (char) | 66 | (defun latin-ltx--ascii-p (char) |
| 47 | (and (characterp char) (< char 128))) | 67 | (and (characterp char) (< char 128))) |
| 48 | 68 | ||
| @@ -53,7 +73,8 @@ system, including many technical ones. Examples: | |||
| 53 | (pcase rule | 73 | (pcase rule |
| 54 | (`(,_ ,(pred characterp)) (push rule newrules)) ;; Normal quail rule. | 74 | (`(,_ ,(pred characterp)) (push rule newrules)) ;; Normal quail rule. |
| 55 | (`(,seq ,re) | 75 | (`(,seq ,re) |
| 56 | (let ((count 0)) | 76 | (let ((count 0) |
| 77 | (re (eval re t))) | ||
| 57 | (dolist (pair (ucs-names)) | 78 | (dolist (pair (ucs-names)) |
| 58 | (let ((name (car pair)) | 79 | (let ((name (car pair)) |
| 59 | (char (cdr pair))) | 80 | (char (cdr pair))) |
| @@ -68,9 +89,27 @@ system, including many technical ones. Examples: | |||
| 68 | (push (list x char) newrules)) | 89 | (push (list x char) newrules)) |
| 69 | (setq count (1+ count)) | 90 | (setq count (1+ count)) |
| 70 | (push (list keys char) newrules)))))) | 91 | (push (list keys char) newrules)))))) |
| 71 | ;(message "latin-ltx: %d mapping for %S" count re) | 92 | ;; (message "latin-ltx: %d mappings for %S" count re) |
| 72 | )))) | 93 | )))) |
| 73 | `(quail-define-rules ,@(nreverse (delete-dups newrules)))))) | 94 | (setq newrules (delete-dups newrules)) |
| 95 | (let ((rules (copy-sequence newrules))) | ||
| 96 | (while rules | ||
| 97 | (let ((rule (pop rules))) | ||
| 98 | (when (assoc (car rule) rules) | ||
| 99 | (let ((conflicts (list (cadr rule))) | ||
| 100 | (tail rules) | ||
| 101 | c) | ||
| 102 | (while (setq c (assoc (car rule) tail)) | ||
| 103 | (push (cadr c) conflicts) | ||
| 104 | (setq tail (cdr (memq c tail))) | ||
| 105 | (setq rules (delq c rules))) | ||
| 106 | (message "Conflict for %S: %S" | ||
| 107 | (car rule) (apply #'string conflicts))))))) | ||
| 108 | (let ((inputs (mapcar #'car newrules))) | ||
| 109 | (setq inputs (delete-dups inputs)) | ||
| 110 | (message "latin-ltx: %d rules (+ %d conflicts)!" | ||
| 111 | (length inputs) (- (length newrules) (length inputs)))) | ||
| 112 | `(quail-define-rules ,@(nreverse newrules))))) | ||
| 74 | 113 | ||
| 75 | (latin-ltx--define-rules | 114 | (latin-ltx--define-rules |
| 76 | ("!`" ?¡) | 115 | ("!`" ?¡) |
| @@ -89,69 +128,35 @@ system, including many technical ones. Examples: | |||
| 89 | ("$^o$" ?º) | 128 | ("$^o$" ?º) |
| 90 | ("?`" ?¿) | 129 | ("?`" ?¿) |
| 91 | 130 | ||
| 92 | ("\\`" ?̀) | ||
| 93 | ("\\`{}" ?`) | ||
| 94 | ((lambda (name char) | ||
| 95 | (let ((c (if (match-end 1) | ||
| 96 | (downcase (match-string 2 name)) | ||
| 97 | (match-string 2 name)))) | ||
| 98 | (list (format "\\`{%s}" c) (format "\\`%s" c)))) | ||
| 99 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH GRAVE") | ||
| 100 | |||
| 101 | ("\\'" ?́) | ||
| 102 | ("\\'{}" ?´) | ||
| 103 | ((lambda (name char) | ||
| 104 | (let ((c (if (match-end 1) | ||
| 105 | (downcase (match-string 2 name)) | ||
| 106 | (match-string 2 name)))) | ||
| 107 | (list (format "\\'{%s}" c) (format "\\'%s" c)))) | ||
| 108 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH ACUTE") | ||
| 109 | |||
| 110 | ("\\^" ?̂) | ||
| 111 | ("\\^{}" ?^) | ||
| 112 | ((lambda (name char) | 131 | ((lambda (name char) |
| 113 | (let ((c (if (match-end 1) | 132 | (let* ((c (if (match-end 1) |
| 114 | (downcase (match-string 2 name)) | 133 | (downcase (match-string 2 name)) |
| 115 | (match-string 2 name)))) | 134 | (match-string 2 name))) |
| 116 | (list (format "\\^{%s}" c) (format "\\^%s" c)))) | 135 | (mark1 (cdr (assoc (match-string 3 name) latin-ltx--mark-map))) |
| 117 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH CIRCUMFLEX") | 136 | (mark2 (if (match-end 4) |
| 118 | 137 | (cdr (assoc (match-string 4 name) latin-ltx--mark-map)))) | |
| 119 | ("\\~" ?̃) | 138 | (marks (if mark2 (concat mark1 "\\" mark2) mark1))) |
| 120 | ("\\~{}" ?˜) | 139 | (cl-assert mark1) |
| 121 | ((lambda (name char) | 140 | (cons (format "\\%s{%s}" marks c) |
| 122 | (let ((c (if (match-end 1) | 141 | ;; Exclude "d" because we use "\\dh" for something else. |
| 123 | (downcase (match-string 2 name)) | 142 | (unless (member (or mark2 mark1) '("d"));; "k" |
| 124 | (match-string 2 name)))) | 143 | (list (format "\\%s%s" marks c)))))) |
| 125 | (list (format "\\~{%s}" c) (format "\\~%s" c)))) | 144 | (concat "\\`LATIN \\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH \\(" |
| 126 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH TILDE") | 145 | latin-ltx--mark-re "\\)\\(?: AND \\(" |
| 127 | 146 | latin-ltx--mark-re "\\)\\)?\\'")) | |
| 128 | ("\\\"" ?̈) | 147 | |
| 129 | ("\\\"{}" ?¨) | ||
| 130 | ((lambda (name char) | ||
| 131 | (let ((c (if (match-end 1) | ||
| 132 | (downcase (match-string 2 name)) | ||
| 133 | (match-string 2 name)))) | ||
| 134 | (list (format "\\\"{%s}" c) (format "\\\"%s" c)))) | ||
| 135 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH DIAERESIS") | ||
| 136 | |||
| 137 | ("\\k" ?̨) | ||
| 138 | ("\\k{}" ?˛) | ||
| 139 | ((lambda (name char) | 148 | ((lambda (name char) |
| 140 | (let ((c (if (match-end 1) | 149 | (let* ((mark (cdr (assoc (match-string 1 name) latin-ltx--mark-map)))) |
| 141 | (downcase (match-string 2 name)) | 150 | (cl-assert mark) |
| 142 | (match-string 2 name)))) | 151 | (list (format "\\%s" mark)))) |
| 143 | (list (format "\\k{%s}" c) ;; (format "\\k%s" c) | 152 | (concat "\\`COMBINING \\(" latin-ltx--mark-re "\\)\\(?: ACCENT\\)?\\'")) |
| 144 | ))) | 153 | |
| 145 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH OGONEK") | ||
| 146 | |||
| 147 | ("\\c" ?̧) | ||
| 148 | ("\\c{}" ?¸) | ||
| 149 | ((lambda (name char) | 154 | ((lambda (name char) |
| 150 | (let ((c (if (match-end 1) | 155 | (unless (latin-ltx--ascii-p char) |
| 151 | (downcase (match-string 2 name)) | 156 | (let* ((mark (cdr (assoc (match-string 1 name) latin-ltx--mark-map)))) |
| 152 | (match-string 2 name)))) | 157 | (cl-assert mark) |
| 153 | (list (format "\\c{%s}" c) (format "\\c%s" c)))) | 158 | (list (format "\\%s{}" mark))))) |
| 154 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH CEDILLA") | 159 | (concat "\\`\\(?:SPACING \\)?\\(" latin-ltx--mark-re "\\)\\(?: ACCENT\\)?\\'")) |
| 155 | 160 | ||
| 156 | ("\\AA" ?Å) ;; ("{\\AA}" ?Å) | 161 | ("\\AA" ?Å) ;; ("{\\AA}" ?Å) |
| 157 | ("\\AE" ?Æ) ;; ("{\\AE}" ?Æ) | 162 | ("\\AE" ?Æ) ;; ("{\\AE}" ?Æ) |
| @@ -166,42 +171,6 @@ system, including many technical ones. Examples: | |||
| 166 | ("$\\div$" ?÷) ("\\div" ?÷) | 171 | ("$\\div$" ?÷) ("\\div" ?÷) |
| 167 | ("\\o" ?ø) ;; ("{\\o}" ?ø) | 172 | ("\\o" ?ø) ;; ("{\\o}" ?ø) |
| 168 | 173 | ||
| 169 | ("\\=" ?̄) | ||
| 170 | ("\\={}" ?¯) | ||
| 171 | ((lambda (name char) | ||
| 172 | (let ((c (if (match-end 1) | ||
| 173 | (downcase (match-string 2 name)) | ||
| 174 | (match-string 2 name)))) | ||
| 175 | (list (format "\\={%s}" c) (format "\\=%s" c)))) | ||
| 176 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH MACRON") | ||
| 177 | |||
| 178 | ("\\u" ?̆) | ||
| 179 | ("\\u{}" ?˘) | ||
| 180 | ((lambda (name char) | ||
| 181 | (let ((c (if (match-end 1) | ||
| 182 | (downcase (match-string 2 name)) | ||
| 183 | (match-string 2 name)))) | ||
| 184 | (list (format "\\u{%s}" c) (format "\\u%s" c)))) | ||
| 185 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH BREVE") | ||
| 186 | |||
| 187 | ("\\." ?̇) | ||
| 188 | ("\\.{}" ?˙) | ||
| 189 | ((lambda (name char) | ||
| 190 | (let ((c (if (match-end 1) | ||
| 191 | (downcase (match-string 2 name)) | ||
| 192 | (match-string 2 name)))) | ||
| 193 | (list (format "\\.{%s}" c) (format "\\.%s" c)))) | ||
| 194 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH DOT ABOVE") | ||
| 195 | |||
| 196 | ("\\v" ?̌) | ||
| 197 | ("\\v{}" ?ˇ) | ||
| 198 | ((lambda (name char) | ||
| 199 | (let ((c (if (match-end 1) | ||
| 200 | (downcase (match-string 2 name)) | ||
| 201 | (match-string 2 name)))) | ||
| 202 | (list (format "\\v{%s}" c) (format "\\v%s" c)))) | ||
| 203 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH CARON") | ||
| 204 | |||
| 205 | ("\\~{\\i}" ?ĩ) | 174 | ("\\~{\\i}" ?ĩ) |
| 206 | ("\\={\\i}" ?ī) | 175 | ("\\={\\i}" ?ī) |
| 207 | ("\\u{\\i}" ?ĭ) | 176 | ("\\u{\\i}" ?ĭ) |
| @@ -214,12 +183,6 @@ system, including many technical ones. Examples: | |||
| 214 | 183 | ||
| 215 | ("\\H" ?̋) | 184 | ("\\H" ?̋) |
| 216 | ("\\H{}" ?˝) | 185 | ("\\H{}" ?˝) |
| 217 | ((lambda (name char) | ||
| 218 | (let ((c (if (match-end 1) | ||
| 219 | (downcase (match-string 2 name)) | ||
| 220 | (match-string 2 name)))) | ||
| 221 | (list (format "\\H{%s}" c) (format "\\H%s" c)))) | ||
| 222 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH DOUBLE ACUTE") | ||
| 223 | ("\\U{o}" ?ő) ("\\Uo" ?ő) ;; FIXME: Was it just a typo? | 186 | ("\\U{o}" ?ő) ("\\Uo" ?ő) ;; FIXME: Was it just a typo? |
| 224 | 187 | ||
| 225 | ("\\OE" ?Œ) ;; ("{\\OE}" ?Œ) | 188 | ("\\OE" ?Œ) ;; ("{\\OE}" ?Œ) |
| @@ -248,15 +211,11 @@ system, including many technical ones. Examples: | |||
| 248 | (string (if (match-end 2) ?^ ?_) basechar)))) | 211 | (string (if (match-end 2) ?^ ?_) basechar)))) |
| 249 | "\\(.*\\)SU\\(?:B\\|\\(PER\\)\\)SCRIPT \\(.*\\)") | 212 | "\\(.*\\)SU\\(?:B\\|\\(PER\\)\\)SCRIPT \\(.*\\)") |
| 250 | 213 | ||
| 251 | ("^\\gamma" ?ˠ) | 214 | ((lambda (name _char) |
| 252 | 215 | (let* ((basename (match-string 2 name)) | |
| 253 | ((lambda (name char) | 216 | (name (if (match-end 1) (capitalize basename) (downcase basename)))) |
| 254 | (let* ((base (format "LATIN %s LETTER %s" | 217 | (concat "^" (if (> (length name) 1) "\\") name))) |
| 255 | (match-string 1 name) (match-string 2 name))) | 218 | "\\`MODIFIER LETTER \\(?:SMALL\\|CAPITA\\(L\\)\\) \\([[:ascii:]]+\\)\\'") |
| 256 | (basechar (cdr (assoc base (ucs-names))))) | ||
| 257 | (when (latin-ltx--ascii-p basechar) | ||
| 258 | (string ?^ basechar)))) | ||
| 259 | "MODIFIER LETTER \\(SMALL\\|CAPITAL\\) \\(.*\\)") | ||
| 260 | 219 | ||
| 261 | ;; ((lambda (name char) (format "^%s" (downcase (match-string 1 name)))) | 220 | ;; ((lambda (name char) (format "^%s" (downcase (match-string 1 name)))) |
| 262 | ;; "\\`MODIFIER LETTER SMALL \\(.\\)\\'") | 221 | ;; "\\`MODIFIER LETTER SMALL \\(.\\)\\'") |
| @@ -268,22 +227,14 @@ system, including many technical ones. Examples: | |||
| 268 | 227 | ||
| 269 | ("\\b" ?̱) | 228 | ("\\b" ?̱) |
| 270 | 229 | ||
| 271 | ("\\d" ?̣) | ||
| 272 | ;; ("\\d{}" ?) ;; FIXME: can't find the DOT BELOW character. | ||
| 273 | ((lambda (name char) | ||
| 274 | (let ((c (if (match-end 1) | ||
| 275 | (downcase (match-string 2 name)) | ||
| 276 | (match-string 2 name)))) | ||
| 277 | (list (format "\\d{%s}" c) ;; (format "\\d%s" c) | ||
| 278 | ))) | ||
| 279 | "\\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH DOT BELOW") | ||
| 280 | |||
| 281 | ("\\rq" ?’) | 230 | ("\\rq" ?’) |
| 282 | 231 | ||
| 283 | ;; FIXME: Provides some useful entries (yen, euro, copyright, registered, | 232 | ;; FIXME: Provides some useful entries (yen, euro, copyright, registered, |
| 284 | ;; currency, minus, micro), but also a lot of dubious ones. | 233 | ;; currency, minus, micro), but also a lot of dubious ones. |
| 285 | ((lambda (name char) | 234 | ((lambda (name char) |
| 286 | (unless (latin-ltx--ascii-p char) | 235 | (unless (or (latin-ltx--ascii-p char) |
| 236 | ;; We prefer COMBINING LONG SOLIDUS OVERLAY for \not. | ||
| 237 | (member name '("NOT SIGN"))) | ||
| 287 | (concat "\\" (downcase (match-string 1 name))))) | 238 | (concat "\\" (downcase (match-string 1 name))))) |
| 288 | "\\`\\([^- ]+\\) SIGN\\'") | 239 | "\\`\\([^- ]+\\) SIGN\\'") |
| 289 | 240 | ||
| @@ -373,7 +324,6 @@ system, including many technical ones. Examples: | |||
| 373 | ("\\circledcirc" ?⊚) | 324 | ("\\circledcirc" ?⊚) |
| 374 | ("\\circleddash" ?⊝) | 325 | ("\\circleddash" ?⊝) |
| 375 | ("\\clubsuit" ?♣) | 326 | ("\\clubsuit" ?♣) |
| 376 | ("\\colon" ?:) ;FIXME: Conflict with "COLON SIGN" ₡. | ||
| 377 | ("\\coloneq" ?≔) | 327 | ("\\coloneq" ?≔) |
| 378 | ("\\complement" ?∁) | 328 | ("\\complement" ?∁) |
| 379 | ("\\cong" ?≅) | 329 | ("\\cong" ?≅) |
| @@ -396,7 +346,6 @@ system, including many technical ones. Examples: | |||
| 396 | ("\\ddots" ?⋱) | 346 | ("\\ddots" ?⋱) |
| 397 | ("\\diamond" ?⋄) | 347 | ("\\diamond" ?⋄) |
| 398 | ("\\diamondsuit" ?♢) | 348 | ("\\diamondsuit" ?♢) |
| 399 | ("\\digamma" ?Ϝ) | ||
| 400 | ("\\divideontimes" ?⋇) | 349 | ("\\divideontimes" ?⋇) |
| 401 | ("\\doteq" ?≐) | 350 | ("\\doteq" ?≐) |
| 402 | ("\\doteqdot" ?≑) | 351 | ("\\doteqdot" ?≑) |