reddit / emacs

How difficult would it be to implement something like this: double space to escape enclosing asterisk

Bisionte1 · 2022-03-30 13:44
I'm using markdown-mode and have the following custom keybinds: * C-b puts ```**|**``` (```|``` is the cursor), so that the text is bold * C-i puts ```*|*``` so that the text is italic The problem is that I often get in this kind of situation: ( ``|`` represents the cursor) >Lorem ipsum dolor sit amet, \*\*consectetur adipiscing |\*\* elit, sed do eiusmod When I type something between the asterisks I always leave an appending whitespace inside, before getting out of the enclosing asterisks. One solution could be to interpret a double space as "get out of the enclosing asterisks". This way, if I type another space in the example above, this would be the result: >Lorem ipsum dolor sit amet, \*\*consectetur adipiscing\*\*| elit, sed do eiusmod I'd like this to be possible even for backticks. However, it doesn't seem like an easy task (I'm not a elisp expert, but i could make it through its particular syntax). Is there some hint or already built tool out there that could help me? Thank you in advance
Gallipo · 2022-03-30 16:32
Quick and dirty would be simple: bind something like this to SPC: ​ (defun out-of-asteriks-or-space () (interactive) (if (and (looking-at " \\*\\*") (looking-back " ")) (forward-char 3) (insert " "))) ​ But this doesn't check if the cursor is in between paired asterisks. So to refine might be more work, but should not be too complicated. The first thing I would check is, if markdown-mode already provides such a check.
Bisionte1 · 2022-03-30 16:38
Words between asterisks have specific faces: `markdown-bold-face` and `markdown-italic-face`. I could maybe use those to know if i'm between asterisks? However, as long as i put even 1 trailing space after the last word, the face disappears. I was thinking instead of something like this (in pseudocode) bind SPACE to lambda: insert space if current-face is markdown-bold-face AND the cursor is past the last non-blank character then def next_key = read next key (and execute it) if next key is SPACE then delete all trailing spaces get past the closing delimiters
Gallipo · 2022-03-30 16:55
Well, that sounds like a good option to start with. But from here I can not help you. (I do not use markdown-mode and am not interested in getting into it's details) In my experience these little things are easy to fix in a way that is sufficient for your own use-case but hard to get right in a more general sense. But I think the learning-experience is worth it.
oantolin · 2022-03-30 17:49
It's not a very good idea to have an Emacs command read the next key and execute it: let the command loop handle that! How about just modifying u/Gallipo's function to delete the spaces and move forward when the last key you pressed was also space? (I also modified it to work with other markup characters.) (defun out-of-markup-or-space () (interactive) (if (and (looking-at "[*_`]") (eq last-command 'out-of-markup-or-space)) (progn (delete-horizontal-space) (skip-chars-forward "*_`")) (insert " ")))
Bisionte1 · 2022-03-30 18:43
TIL about `last-command`. Thank you both for your help, your code definitely did the trick.
Gallipo · 2022-03-30 19:16
Nice!
zenspider · 2022-04-06 05:17
What makes sense to me is to use context: if you have a selection, it gets wrapped appropriately and the point is moved out, if not selection the point stays put.