Skip to content

Instantly share code, notes, and snippets.

@jdtsmith
Last active February 15, 2024 11:27
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

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.

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