Skip to content

Instantly share code, notes, and snippets.

@jdtsmith
Last active November 20, 2024 15:44
Show Gist options
  • Save jdtsmith/55e6a660dd4c0779a600ac81bf9bfc23 to your computer and use it in GitHub Desktop.
Save jdtsmith/55e6a660dd4c0779a600ac81bf9bfc23 to your computer and use it in GitHub Desktop.
org-toggle-emphasis: easily toggle emphasis markers: =~*/_+
(defun my/org-toggle-emphasis (type)
"Toggle org emphasis TYPE (a character) at point."
(cl-labels ((in-emph (re)
"See if in org emphasis given by RE."
(and (org-in-regexp re 2)
(>= (point) (match-beginning 3))
(<= (point) (match-end 4))))
(de-emphasize ()
"Remove most recently matched org emphasis markers."
(save-excursion
(replace-match "" nil nil nil 3)
(delete-region (match-end 4) (1+ (match-end 4))))))
(let* ((res (vector org-emph-re org-verbatim-re))
(idx (cl-case type (?/ 0) (?* 0) (?_ 0) (?+ 0) (?= 1) (?~ 1)))
(re (aref res idx))
(other-re (aref res (- 1 idx)))
(type-re (string-replace (if (= idx 1) "=~" "*/_+")
(char-to-string type) re))
add-bounds offset is-word)
(save-match-data
(if (region-active-p)
(if (in-emph type-re) (de-emphasize) (org-emphasize type))
(if (eq (char-before) type) (backward-char))
(if (in-emph type-re) ;nothing marked, in emph text?
(de-emphasize)
(setq add-bounds ; check other flavors
(if (or (in-emph re) (in-emph other-re))
(cons (match-beginning 4) (match-end 4))
(setq is-word t)
(bounds-of-thing-at-point 'symbol))))
(if add-bounds
(let ((off (- (point) (car add-bounds)))
(at-end (= (point) (cdr add-bounds))))
(set-mark (car add-bounds))
(goto-char (cdr add-bounds))
(org-emphasize type) ;deletes marked region!
(unless is-word ; delete extra spaces
(goto-char (car add-bounds))
(when (eq (char-after) ?\s) (delete-char 1))
(goto-char (+ 2 (cdr add-bounds)))
(when (eq (char-after) ?\s) (delete-char 1)))
(goto-char (+ (car add-bounds) off
(cond ((= off 0) 0) (at-end 2) (t 1)))))
(if is-word (org-emphasize type))))))))
@jdtsmith
Copy link
Author

jdtsmith commented Jan 15, 2024

May consider using (bounds-of-thing-at-point 'symbol) instead of 'word, so works on hyphenated words and vari-abl-es.

Thanks! I had in fact wanted this, and reached for current-word, which does the right thing, but that returns the word and not its bounds. Even considered submitting a patch for current-word-bounds.

Also, have you seen this snippet for insert-pair

Nope, I hadn't seen that interesting approach, thanks. I tend to just use s-e when at a blank to get a ~~ with point between. That's what the final (if is-word (org-emphasize type)) does. I.e. it was a word, but we didn't find one, so just emphasize "nothing".

@jdtsmith
Copy link
Author

Just tweaked to correctly de-emphasize right after an emphasized word *word*[s-b] -> word, and to leave point outside the word if point is on the boundary to begin with.

@jeff-phil
Copy link

I had in fact wanted this, and reached for current-word, which does the right thing

Interesting, I thought current-word 'word etc. all used the same underlying syntax tables to define a word. Guess not! Thanks for that.

@artelse
Copy link

artelse commented Nov 19, 2024

Quite like this. My only problem is the mapping of the super key. When I use s-i it is mapped to org-self-insert-command and other keys too. I tried to unmap it (define-key key-translation-map (kbd "s-i") nil) to no avail. How do you get the super key to work? I'm on linux.

@jdtsmith
Copy link
Author

jdtsmith commented Nov 20, 2024

You may need to alter at system level. Consult docs for key bindings.

@artelse
Copy link

artelse commented Nov 20, 2024

That is indeed what is needed. In the mean time I made a transient for textual operations and this works fine; just one extra keystroke. Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment