Skip to content

Instantly share code, notes, and snippets.

@cvcore
Last active May 30, 2020 18:33
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cvcore/760008a4dfb2eadf42afdc9cf01ef979 to your computer and use it in GitHub Desktop.
Save cvcore/760008a4dfb2eadf42afdc9cf01ef979 to your computer and use it in GitHub Desktop.
Automatic fragment toggling in org-mode
;;
;; 28.07.2017
;; Charles Wang
;;
;;;;;;; Tweaks for Org & org-latex ;;;;;;
(defvar cw/org-last-fragment nil
"Holds the type and position of last valid fragment we were on. Format: (FRAGMENT_TYPE FRAGMENT_POINT_BEGIN)"
)
(setq cw/org-valid-fragment-type
'(latex-fragment
latex-environment
link))
(defun cw/org-curr-fragment ()
"Returns the type and position of the current fragment available for preview inside org-mode. Returns nil at non-displayable fragments"
(let* ((fr (org-element-context))
(fr-type (car fr)))
(when (memq fr-type cw/org-valid-fragment-type)
(list fr-type
(org-element-property :begin fr))))
)
(defun cw/org-remove-fragment-overlay (fr)
"Remove fragment overlay at fr"
(let ((fr-type (nth 0 fr))
(fr-begin (nth 1 fr)))
(goto-char fr-begin)
(cond ((or (eq 'latex-fragment fr-type)
(eq 'latex-environment fr-type))
(let ((ov (loop for ov in (org--list-latex-overlays)
if
(and
(<= (overlay-start ov) (point))
(>= (overlay-end ov) (point)))
return ov)))
(when ov
(delete-overlay ov))))
((eq 'link fr-type)
nil;; delete image overlay here?
))
))
(defun cw/org-preview-fragment (fr)
"Preview org fragment at fr"
(let ((fr-type (nth 0 fr))
(fr-begin (nth 1 fr)))
(goto-char fr-begin)
(cond ((or (eq 'latex-fragment fr-type) ;; latex stuffs
(eq 'latex-environment fr-type))
(when (cw/org-curr-fragment) (org-preview-latex-fragment))) ;; only toggle preview when we're in a valid region (for inserting in the front of a fragment)
((eq 'link fr-type) ;; for images
(let ((fr-end (org-element-property :end (org-element-context))))
(org-display-inline-images nil t fr-begin fr-end))))
))
(defun cw/org-auto-toggle-fragment-display ()
"Automatically toggle a displayable org mode fragment"
(and (eq 'org-mode major-mode)
(let ((curr (cw/org-curr-fragment)))
(cond
;; were on a fragment and now on a new fragment
((and
;; fragment we were on
cw/org-last-fragment
;; and are on a fragment now
curr
;; but not on the last one this is a little tricky. as you edit the
;; fragment, it is not equal to the last one. We use the begin
;; property which is less likely to change for the comparison.
(not (equal curr cw/org-last-fragment)))
;; go back to last one and put image back, provided there is still a fragment there
(save-excursion
(cw/org-preview-fragment cw/org-last-fragment)
;; now remove current image
(cw/org-remove-fragment-overlay curr)
;; and save new fragment
)
(setq cw/org-last-fragment curr))
;; were on a fragment and now are not on a fragment
((and
;; not on a fragment now
(not curr)
;; but we were on one
cw/org-last-fragment)
;; put image back on, provided that there is still a fragment here.
(save-excursion
(cw/org-preview-fragment cw/org-last-fragment))
;; unset last fragment
(setq cw/org-last-fragment nil))
;; were not on a fragment, and now are
((and
;; we were not one one
(not cw/org-last-fragment)
;; but now we are
curr)
;; remove image
(save-excursion
(cw/org-remove-fragment-overlay curr)
)
(setq cw/org-last-fragment curr))
))))
@0lifer
Copy link

0lifer commented Apr 12, 2018

Hi, I saw your youtube video and it's just what I need. However, I can't seem to get it to work (following your youtube example). Below is my part of my dotspacemacs file. I reinstalled Xubuntu recently, so the config file is fresh. Thanks in advance for your help.

(defun dotspacemacs/user-config ()
"Configuration function for user code.
This function is called at the very end of Spacemacs initialization after
layers configuration.
This is the place where most of your configurations should be done. Unless it is
explicitly specified that a variable should be set before a package is loaded,
you should place your code here."

;;;;; ORG MODE ;;;;;
(evil-define-key '(normal visual motion)
"gh" 'outline-up-heading
"gj" 'outline-forward-same-level
"gk" 'outline-backward-same-level
"gl" 'outline-next-visible-heading
"gf" 'outline-previous-visible-heading)

(add-hook 'post-command-hook 'cw/org-auto-toggle-fragment-display t)
(setq org-pretty-entities t)
(setq org-agenda-files (list "~/org"))

;;;;;;; Tweaks for Org & org-latex ;;;;;;

(defvar cw/org-last-fragment nil
"Holds the type and position of last valid fragment we were on. Format: (FRAGMENT_TYPE FRAGMENT_POINT_BEGIN)"
)

(setq cw/org-valid-fragment-type
'(latex-fragment
latex-environment
link))

(defun cw/org-curr-fragment ()
"Returns the type and position of the current fragment available for preview inside org-mode. Returns nil at non-displayable fragments"
(let* ((fr (org-element-context))
(fr-type (car fr)))
(when (memq fr-type cw/org-valid-fragment-type)
(list fr-type
(org-element-property :begin fr))))
)

(defun cw/org-remove-fragment-overlay (fr)
"Remove fragment overlay at fr"
(let ((fr-type (nth 0 fr))
(fr-begin (nth 1 fr)))
(goto-char fr-begin)
(cond ((or (eq 'latex-fragment fr-type)
(eq 'latex-environment fr-type))
(let ((ov (loop for ov in (org--list-latex-overlays)
if
(and
(<= (overlay-start ov) (point))
(>= (overlay-end ov) (point)))
return ov)))
(when ov
(delete-overlay ov))))
((eq 'link fr-type)
nil;; delete image overlay here?
))
))

(defun cw/org-preview-fragment (fr)
"Preview org fragment at fr"
(let ((fr-type (nth 0 fr))
(fr-begin (nth 1 fr)))
(goto-char fr-begin)
(cond ((or (eq 'latex-fragment fr-type) ;; latex stuffs
(eq 'latex-environment fr-type))
(when (cw/org-curr-fragment) (org-preview-latex-fragment))) ;; only toggle preview when we're in a valid region (for inserting in the front of a fragment)

      ((eq 'link fr-type) ;; for images
       (let ((fr-end (org-element-property :end (org-element-context))))
         (org-display-inline-images nil t fr-begin fr-end))))
))

(defun cw/org-auto-toggle-fragment-display ()
"Automatically toggle a displayable org mode fragment"
(and (eq 'org-mode major-mode)
(let ((curr (cw/org-curr-fragment)))
(cond
;; were on a fragment and now on a new fragment
((and
;; fragment we were on
cw/org-last-fragment
;; and are on a fragment now
curr
;; but not on the last one this is a little tricky. as you edit the
;; fragment, it is not equal to the last one. We use the begin
;; property which is less likely to change for the comparison.
(not (equal curr cw/org-last-fragment)))

       ;; go back to last one and put image back, provided there is still a fragment there
       (save-excursion
         (cw/org-preview-fragment cw/org-last-fragment)
         ;; now remove current image
         (cw/org-remove-fragment-overlay curr)
         ;; and save new fragment
         )
       (setq cw/org-last-fragment curr))

      ;; were on a fragment and now are not on a fragment
      ((and
        ;; not on a fragment now
        (not curr)
        ;; but we were on one
        cw/org-last-fragment)
       ;; put image back on, provided that there is still a fragment here.
       (save-excursion
         (cw/org-preview-fragment cw/org-last-fragment))

       ;; unset last fragment
       (setq cw/org-last-fragment nil))

      ;; were not on a fragment, and now are
      ((and
        ;; we were not one one
        (not cw/org-last-fragment)
        ;; but now we are
        curr)
       ;; remove image
       (save-excursion
         (cw/org-remove-fragment-overlay curr)
         )
       (setq cw/org-last-fragment curr))

))))
)

;; Do not write anything past this comment. This is where Emacs will
;; auto-generate custom variable definitions.

@io12
Copy link

io12 commented Feb 2, 2020

I made something like this that works with newer Org versions. https://github.com/io12/org-fragtog

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