summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhedy <hedy@tilde.cafe>2023-09-10 22:23:13 +0800
committerDaniel Mendler <mail@daniel-mendler.de>2023-09-28 06:20:48 +0200
commit0f4b94109a97d3f94882dae7391f9affc775eb4e (patch)
tree79d540f6868bbac67977ae38a116cd5d28796614
parentf89307f9fe128e58483ffdad2e36a877e511aad9 (diff)
char: More inclusive on the matching translations to include
Note that this is not an atomic commit :') - Previously filtered out translations that are stored as a vector but with only one element. Now those are included with that element as the translation. - Some translations (particularly emoji of country flags) cannot preserve their string when converted to char then back to string. For cases like these they are now stored as strings in the hash table. All other translations are still stored as chars (to save space in storing the hash). One can possibly use (= (string-width value-str) 2) to check, but some strings that satisfy this condition also satisfy string-char reversability, so the naive (string= (char-to-string value-char) value-str) is used. This directly allows for completing emoji country flags. I did not look into any other benefits of this regarding other input methods. Because of this change, new helper functions cape-char --ensure-str and --ensure-char are introduced to ace clarity when updating cape-char--define. - Moved (require 'quail) into the translation function. (resolves review comment) - Better doc string and naming of translation function: This clarifies from the function name that a hash is returned -- better for when the function becomes a public API. - Reverted removing regexp argument from translation function. This allows filtering out name-value translation pairs from the hash that do not match the required prefixes. Waste of space to keep those translations around in the hash. (resolves review comment)
-rw-r--r--cape-char.el56
1 files changed, 38 insertions, 18 deletions
diff --git a/cape-char.el b/cape-char.el
index 67f57de..7c64616 100644
--- a/cape-char.el
+++ b/cape-char.el
@@ -25,33 +25,51 @@
;;; Code:
(require 'cape)
-(require 'quail)
(autoload 'thing-at-point-looking-at "thingatpt")
+(defun cape-char--ensure-str (char-or-str)
+ "Return CHAR-OR-STR as a string"
+ (if (characterp char-or-str)
+ (char-to-string char-or-str) char-or-str))
+
+(defun cape-char--ensure-char (char-or-str)
+ "Return CHAR-OR-STR as a char"
+ (if (stringp char-or-str)
+ (string-to-char char-or-str) char-or-str))
+
;; Declare as pure function which is evaluated at compile time. We don't use a
;; macro for this computation since packages like `helpful' will
;; `macroexpand-all' the expensive `cape-char--define' macro calls.
(eval-when-compile
- (defun cape-char--translation (method)
- "Return character translation hash for METHOD."
+ (defun cape-char--translation-hash (method regexp)
+ "Return character translation hash for input method METHOD.
+REGEXP is the regular expression matching the names."
(declare (pure t))
+ (require 'quail)
(let* ((decode-map (list 'dm))
(quail-current-package (assoc method quail-package-alist))
(map-list (nth 2 quail-current-package))
(hash (make-hash-table :test #'equal)))
(apply #'quail-use-package method (nthcdr 5 (assoc method input-method-alist)))
(quail-build-decode-map (list map-list) "" decode-map 0)
+ ;; decode-map now looks like: (dm (key . value) (key . value) ...)
(dolist (elem (cdr decode-map))
- (let ((key (car elem))
- (value (cdr elem)))
- ;; Drop all translations that map to multiple candidates, like
- ;; how quail hide them from "KEY SEQUENCES"
- (if (not (vectorp value))
- (puthash key (if (stringp value)
- (string-to-char value)
- value)
- hash))))
+ (let ((name (car elem)) (value (cdr elem)) value-char value-str)
+ (if (vectorp value)
+ (if (= (length value) 1)
+ (setq value (aref value 0))))
+ ;; Ignores all translations that map to multiple candidates
+ (when (char-or-string-p value)
+ (setq value-char (cape-char--ensure-char value)
+ value-str (cape-char--ensure-str value))
+ (when (string-match-p regexp name)
+ ;; Store as string if converting it to char and back to
+ ;; string doesn't preserve the original string.
+ ;; Otherwise ensure it gets stored as char.
+ (puthash name (if (string= (char-to-string value-char) value-str)
+ value-char value-str)
+ hash)))))
(quail-deactivate)
hash)))
@@ -69,16 +87,18 @@ PREFIX are the prefix characters."
(properties (intern (format "cape--%s-properties" name)))
(thing-re (concat (regexp-opt (mapcar #'char-to-string prefix)) "[^ \n\t]*" )))
`(progn
- (defvar ,hash (cape-char--translation ,method))
+ (defvar ,hash (cape-char--translation-hash
+ ,method
+ ,(concat "\\`" (regexp-opt (mapcar #'char-to-string prefix)))))
(defcustom ,prefix-required t
,(format "Initial prefix is required for `%s' to trigger." capf)
:type 'boolean
:group 'cape)
(defun ,ann (name)
- (when-let (char (gethash name ,hash))
- (format " %c" char)))
+ (when-let (str (cape-char--ensure-str (gethash name ,hash)))
+ (format " %s" str)))
(defun ,docsig (name)
- (when-let (char (gethash name ,hash))
+ (when-let (char (cape-char--ensure-char (gethash name ,hash)))
(format "%s (%s)"
(get-char-code-property char 'name)
(char-code-property-description
@@ -86,9 +106,9 @@ PREFIX are the prefix characters."
(get-char-code-property char 'general-category)))))
(defun ,exit (name status)
(unless (eq status 'exact)
- (when-let (char (gethash name ,hash))
+ (when-let (str (cape-char--ensure-str (gethash name ,hash)))
(delete-region (max (point-min) (- (point) (length name))) (point))
- (insert (char-to-string char)))))
+ (insert str))))
(defvar ,properties
(list :annotation-function #',ann
:company-docsig #',docsig