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?

  • 1
    How precisely you insert the character "α"? – Name Feb 19 '18 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 '18 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 '18 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 '18 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 '18 at 17:58

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

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'."
  (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
  :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)))
  • 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 '18 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 '18 at 16:43
  • Could you give me an example of this more elegant way? – MaPo Feb 28 '18 at 13:06
  • I've edited my answer to sketch out how the alternative method would work. – Adam Mar 1 '18 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 '18 at 11:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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