Replace text on the fly while typing in EMACS?

86 Views Asked by At

I'm creating a major mode for editing Algol source files which are written using Unicode characters.

(add-to-list 'auto-mode-alist '("\\.a60\\'" . algol-mode))

I want to have the following behaviour when editing .a60 files:

As an example, when I type the two characters <= in succession, I want them to be deleted and the Unicode character inserted instead. But only when typed in that order - if I typed < then a space. then erased the space and typed =, I wouldn't want the replacement to happen - I would expect to see an unaltered <=. And to be clear I want this change to be made to text I type - not existing text already in the file. The replacement text is to be inserted in the file as if it had been typed... it is not just a replacement for display, like the way some language major modes will underline keywords on the screen but not save the underlined text in the file.

So <= was one trivial example - but what I actually want is a fully general-purpose input text filter where I can define pairs of typed text and replacement text in my language mode for .a60 files in .emacs, eg something like

(subtitute "&&", "∧")

or

(subtitute "'begin'", "b̲e̲g̲i̲n̲")

I.e. I can define several replacements for things I can type, with unicode text that I can't easily type.

And to reiterate, I don't want to type any escape characters of any sort - I just want to key in a line of code such as 'if' a <= b 'then' explode; and have i̲f̲ a ≤ b t̲h̲e̲n̲ explode; entered into my file.

(I will be careful not to create definitions that could infinitely recurse.) I naively tried using global-set-key but as you probably know (although I didn't until I tried it) that only works for strings with certain prefix characters. I want this new mechanism to work with arbitrary text. I don't think abbrev mode or flymake are what I'm looking for - those were the closest similar solutions I could find in other postings here.

At the end of the day... I did try the abbrev solution suggested by Rorshach (and modifed by https://emacs.stackexchange.com/questions/36890/alternative-to-abbrev-mode-that-supports-special-characters-in-abbreviations ) but couldn't make it work 100%. I ended up using the following code:

(add-to-list 'auto-mode-alist '("\\.a60\\'" . a60-mode))

(defun a60-chars () "Convert Algol 60 symbols from ISO to Unicode."
  (interactive)
  (if (looking-back "<=") (progn (backward-delete-char 2) (insert "≤") )
  (if (looking-back ">=") (progn (backward-delete-char 2) (insert "≥") )
  ;; (if (looking-back "\\\\")  (progn (backward-delete-char 1) (insert "¬") )
  (if (looking-back "~")  (progn (backward-delete-char 1) (insert "¬") )
  (if (looking-back "&&") (progn (backward-delete-char 2) (insert "∧") )
  (if (looking-back "||") (progn (backward-delete-char 2) (insert "∨") )
  (if (looking-back "!=") (progn (backward-delete-char 2) (insert "≠") )
  (if (looking-back "==") (progn (backward-delete-char 2) (insert "≡") )
  (if (looking-back "*")  (progn (backward-delete-char 1) (insert "×") )
  ;; (if (looking-back "\\^")  (progn (backward-delete-char 1) (insert "↑") )
  (if (looking-back "<>") (progn (backward-delete-char 2) (insert "≠") )
  (if (looking-back "//") (progn (backward-delete-char 2) (insert "÷") )
)))))))))))

;; Only enable when editing .a60 files:
(add-hook 'a60-mode-hook
          '(lambda()
            (add-hook 'post-self-insert-hook #'a60-chars nil 'local)
            )
          t
)

I still have some small tweaking to do (to allow replacements for ^ and \) but basically the above does what I need. Thanks for the help.

0

There are 0 best solutions below