How to let Emacs display a different character from that actually stored?
Asked Answered
N

2

8

I want to implement dynamical text replacement (only the display is replaced, the actual stored file is not replaced) for Emacs, using Elisp.

For example, in LaTeX documents, I want to type \alpha, and let Emacs display it just as α, so it is easier to read. But in the result .tex file, I still want \alpha, instead of α to be saved. (Remark: I could use XeTeX or LuaTeX myself to support UTF-8 directly. But for the reason of collaboration and journal requirements, I don't want the UTF-8 characters to be directly saved in the .tex files. Alternatively I could use preview in AUCTeX. But that doesn't help when I am editing the formula)

An existing example is in org-mode, when we type [[link][name]], right after typing the last ], the displayed text is replaced by just the name, with hyperlink. On the other hand, when saving this file, the saved content is the original [[link][name]], different from the displayed one.

Any ideas how this could be implemented?

PS: The Display Specs That Replace The Text section of Emacs manual goes close. However, I need to specify the start and end points, instead of the desired string for the replacements. This means I need to do search after every user input to decide the start and end points. This looks unrealistic due to performance and complexity of algorithm.

Nils answered 28/11, 2012 at 7:42 Comment(0)
L
5

One way to do this is to add font lock keywords for the relevant modes, and to use compose-region to display the new glyph in place of the old string:

(font-lock-add-keywords
 'latex-mode `(("\\(\\\\alpha\\)"
                (0 (progn (compose-region (match-beginning 1)
                                          (match-end 1) "α")
                          nil)))))

Please also note that org-mode has a feature of this kind already built-in, not only for links as you mentioned, but also for LaTeX-like entities:

(setq org-pretty-entities t)
Liebfraumilch answered 28/11, 2012 at 7:55 Comment(1)
compose-region seems to only work when the display result should be a single character. So e.g. if I pass "bar" as the result-string parameter, compose-region collapses all 3 letters to a single one. IOW, passing a "α" and "ααα" both will get the same result.Implement
I
0

The @FrançoisFévotte's answer come pretty close, except that compose-region is not an appropriate function for the task. This function collapses the "display string" to a single character, which is likely not what you wanted. IOW, if instead of passing "α" you decide passing a "ααα" you'll still get a single α character as result.

Instead you want a put-text-property function. So for example:

(font-lock-add-keywords
 'latex-mode `(("\\(\\\\alpha\\)"
                (0 (progn (put-text-property (match-beginning 1) (match-end 1)
                                             'display "α")
                           nil)))))
Implement answered 10/3 at 18:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.