Delete a single char instead of the whole Grapheme Cluster in Emacs
1. Introduction
In Emacs, while writing text in devanāgarī, I often need to delete some character from a pre-composed cluster. This works well, when the character I need to delete is at the end of the cluster, cause <backspace> which is bound by default to delete-backward-char does exactly that: deletes only a single char. BUT when the char is at the start of the cluster say ङ in ङ्क्ष्णुcomposed of ङ+्+क+्+ष+्+ण+ु (I have chosen a ridiculously long conjunct to make a point) I will either have to:
- Press
<backspace>8 times and also lose the characters which I do not need to be deleted. or - Move the cursor to the start of the cluster, press
<delete>and be done.
2. delete-forward-char
Except <delete> does not do that! It will instead delete the whole cluster.
Looks like <delete> is bound to delete-forward-char whose documentation states that:
(delete-forward-char N &optional KILLFLAG)
Inferred type: (function (t &optional t) t)
Delete the following N characters (previous if N is negative).
If Transient Mark mode is enabled, the mark is active, and N is 1,
delete the text in the region and deactivate the mark instead.
To disable this, set variable ‘delete-active-region’ to nil.
If N is positive, characters composed into a single grapheme cluster
count as a single character and are deleted together. Thus,
"C-u 2 <deletechar>" when two grapheme clusters follow point will
delete the characters composed into both of the grapheme clusters.
Optional second arg KILLFLAG non-nil means to kill (save in kill
ring) instead of delete. If called interactively, a numeric
prefix argument specifies N, and KILLFLAG is also set if a prefix
argument is used.
When killing, the killed text is filtered by
‘filter-buffer-substring’ before it is saved in the kill ring, so
the actual saved text might be different from what was killed.
This function is for interactive use only;
in Lisp code use ‘delete-char’ instead.
Probably introduced at or before Emacs version 24.1.That means delete-forward-char is designed to delete a grapheme cluster, but we do not want that in our case, so what should we do (╹ -╹)?
3. delete-char to the rescue
The good ol’ delete-char does not perform any fancy checks to detect whether the text at point is a composition or not. It only has one purpose and that is to delete a char. The function is bound to C-d and with that we can finally get what we wanted.