2

Suppose that ("lambda" . 955), e.g., is contained in prettify-symbol-alist. Deleting a character (key del; or x in evil, evil-delete-char), with point on λ, results in ambda, only the first character is removed.

Instead, I would like to have lambda (i.e. λ) entirely removed. Is there a function which does that?

1
  • 1
    M-d perhaps (bound to kill-word) or its evil equivalent?
    – NickD
    Commented Feb 12 at 1:15

2 Answers 2

2

It's pretty easy: such "prettified symbols" have start/end of their region stored in text properties. So you basically just query that and if it's non-nil, then you know you're dealing with "pretty symbol".

Then solution involves adding an around-advice over delete-backward-char which would query the aforementioned properties, and remove the region if they're there otherwise call the original delete-backward-char.

;; an advice around delete-backward-char
(defun delete-backward-pretty-symbol-advice (orig-func n killflag)
  "Remove \"pretty-symbol\" if it's prior to caret, otherwise call
`delete-backward-char'"
  (if-let*
      ((prev-point (when (> (point) (point-min))
                     (- (point) 1)))
       (pretty-start (get-text-property prev-point 'prettify-symbols-start))
       (pretty-past-end (get-text-property prev-point 'prettify-symbols-end)))
      (delete-region pretty-start pretty-past-end)
    (funcall orig-func n killflag)))
(advice-add 'delete-backward-char :around #'delete-backward-pretty-symbol-advice)

;; an advice around evil-delete-char for evil-mode
(defun evil-delete-char-symbol-advice (orig-func beg past-end &optional type register)
  "Include \"pretty-symbol\"s into region calculation for
`evil-delete-char'"
  (let ((new-start
         ;; return `beg' if property is `nil'
         (or (get-text-property beg 'prettify-symbols-start) beg))
        (new-past-end
         (max past-end
              ;; return `0' if property is `nil'
              (or (get-text-property (- past-end 1) 'prettify-symbols-end) 0))))
    (funcall orig-func new-start new-past-end type register)))
(advice-add 'evil-delete-char :around #'evil-delete-char-symbol-advice)

With the first advice in your init file, pressing Backspace should completely remove a "pretty symbol" if it's there.

The second one is for evil-mode: pressing x while in "normal" mode of evil-mode while the caret is over a "pretty symbol" should remove it as well.

16
  • This works, thank you! Very interesting :-) I tried to bind it to evil-delete-char, which requires the additional arguments beg and end. Hmm. Any solution for this as well? Commented Feb 14 at 18:14
  • @AloisPichler sure, here's one for evil-delete-char. In this case the region is passed over to evil-delete-char (rather than being just "at point"), so that simplifies the code, and we just use beg to query the text property. I don't check full range beg..end as I doubt that in practice the function might be called over a string where a "pretty symbol" would be in the middle. Although I suppose a check could be added for end, to make sure there's no region that starts in the middle and goes over end. I'm not sure how realistic such situation tho.
    – Hi-Angel
    Commented Feb 15 at 2:43
  • I see. Your post helped me a lot, and I am accepting it as answer, thank you. Really clever. If a region is selected, however, this deletes only the prettified character. Commented Feb 15 at 16:30
  • @AloisPichler oh, I see, that's easy to fix. My point was that I didn't know the function is actually called over a region in some circumstances simply because I couldn't find such. But now that you mentioned, I found that pressing <kbd>x</kbd> with region selected does that. I fixed the function, please check if it works okay for you now. I think I accounted for everything this time. We don't need to add a similar check for beg because if at beg you found a prettify-symbols-start text property, it's guaranteed to start at least at beg, maybe earlier. So no check required.
    – Hi-Angel
    Commented Feb 15 at 18:34
  • 1
    Excellent, it works amazingly! Thank you again. And I managed to rewrite the function evil-substitute myself :-) (I think this functionality should be standard behavior) Commented Feb 15 at 19:02
2

You might (or might not) want to customize user option prettify-symbols-unprettify-at-point. From the documentation:

If non-nil, show the non-prettified version of a symbol when point is on it. If set to the symbol ‘right-edge’, also unprettify if point is immediately after the symbol. The prettification will be reapplied as soon as point moves away from the symbol. If set to nil, the prettification persists even when point is on the symbol.

I have it set to 'right-edge, so the issue you wish to solve never arises.

Your Answer

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

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