3

I had inserted the following code in .emacs:

(quail-define-package "LaTeX-UTF-8" "TeX" "TeX")

(quail-defrule "α" ["\\alpha"])

what I want to do is the following: when I insert the character "α" (I remapped the keyboard so I can do easily) I would like to see it replaced by \alpha. As it is it doesn't work. However if I replace α by some other string it works. How can I do?

6
  • 1
    How precisely you insert the character "α"?
    – Name
    Feb 19, 2018 at 12:34
  • @Name I have a new mapping in my keabord using serverX capabilities. (I'm using Linux). It's an UTF8 character.
    – MaPo
    Feb 19, 2018 at 14:05
  • My guess is that you need to switch to your defined input method to have it work. You could use a hook that enables it in LaTeX buffers or something.
    – user12563
    Feb 21, 2018 at 14:38
  • I activated my input method with C-\ and LaTeX-UTF-8. It does not work. However if I substitute α with aaa, for instance, it does the substitution. So the problem must be with that unicode typed in the .emacs file. Am I right?
    – MaPo
    Feb 21, 2018 at 17:16
  • 1
    I doubt one can do it with quail. You can do it with abbrev-mode as (define-abbrev-table 'global-abbrev-table '( ("α" "\\alpha") ("β" "\\beta") )) (abbrev-mode 1).
    – Name
    Feb 21, 2018 at 17:58

1 Answer 1

2
+50

Unfortunately using quail to convert a character from beyond the Basic Latin and Latin-1 Supplement blocks (i.e. anything with a codepoint above 255) is not possible.

Firstly, the quail-translation-keymap, quail-simple-translation-keymap and quail-conversion-keymap (which are used depending on precisely which quail-based input method you use) are assigned only for characters with codepoints below 256 (see here, here and here, respectively).

Secondly, and more importantly, an input-method-function can only act on a single-byte characters (apart from the DEL character — source). Since the main underlying way quail works, is by setting the input-method-function to quail-input-method (see in the definition of quail-activate here), quail can't easily deal with other input characters.

To be fair, the main point of quail and the like is to facilitate inputting non-ascii characters with a "standard" keyboard and your use-case doesn't usually come up.

Solution without using quail

Define your own special minor mode map. For instance:

(define-minor-mode convert-unicode-to-latex-mode
  "A minor mode to convert inserted Unicode characters into their
canonical LaTeX representation."
  :lighter " cutl"
  :keymap (let ((map (make-sparse-keymap)))
            (define-key map (kbd "α")
              ;; ;; Just using the string is probably preferable to a lambda
              ;; (lambda () (interactive) (insert "\\alpha")) 
              "\\alpha") ;; As suggested by Basil, in the comments
            ;;  [...] define other keys
            map))

Alternatively, if you want to do this globally, just do:

(global-set-key (kbd "α") "\\alpha")

Lookup character in an alist

This was intended as a workaround to using lambdas, when defining many mappings, but just using a macro ((define-key map (kbd char) "latex_string")) is preferable. The method relies on looking up the last entered character in an alist and inserting based on that. Kept here for completeness.

The looping over the alist with dolist could obviously be used with any of the methods (macro, lambda, lookup function).

(defvar convert-unicode-to-latex-alist
  '(("α" . "\\alpha")
    ("β" . "\\beta"))
  "Alist of mappings from Unicode to LaTeX.

Used by `convert-unicode-to-latex--insert'.")

(defun convert-unicode-to-latex--insert ()
  "Insert LaTeX based on last entered Unicode character.

Looks up the character in `convert-unicode-to-latex-alist'."
  (interactive)
  (let* ((key (key-description (this-single-command-keys)))
         (mapping (assoc key convert-unicode-to-latex-alist)))
    (if mapping
        (insert (cdr mapping))
      (message "Character %s not found in alist" key))))

(define-minor-mode convert-unicode-to-latex-mode
  "A minor mode to convert inserted unicode characters into their
canonical LaTeX representation.

See `convert-unicode-to-latex-alist' and
`convert-unicode-to-latex--insert'."
  :lighter " cutl"
  :keymap (let ((map (make-sparse-keymap)))
            (dolist (mapping convert-unicode-to-latex-alist)
              (let ((key (car mapping))
                    (latex (cdr mapping)))
                ;; (define-key map
                ;;   (kbd key) latex)
                (define-key map
                  (kbd key) #'convert-unicode-to-latex--insert)))
            map))
6
  • Thank you! The last thing: I did not understand what you said about a special function that would lookup the last character in an alist ... Why should I need it?
    – MaPo
    Feb 26, 2018 at 14:17
  • If you were to define maps, say for all greek letters, you'd have 48 lines of the form: (define-key map (kbd "α") #'(lambda () (interactive) (insert "\\alpha"))) which some might find unseemly. Instead you could define a function which looks up (this-single-command-keys) in an alist (where the the alist would be something like (("α" . "\\alpha") [...])) and inserts the corresponding value. It's an aesthetic difference—there are arguments for either approach (conciseness vs. explicitness/simplicity). If you're not bothered by the method in the answer, then you don't need anything more.
    – Adam
    Feb 26, 2018 at 16:43
  • Could you give me an example of this more elegant way?
    – MaPo
    Feb 28, 2018 at 13:06
  • I've edited my answer to sketch out how the alternative method would work.
    – Adam
    Mar 1, 2018 at 11:12
  • 1
    If you want, you can replace (lambda () (interactive) (insert "string")) with just "string". See the docstring of define-key.
    – Basil
    Mar 1, 2018 at 11:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.