diff --git a/modules/lang/org/autoload/org-link.el b/modules/lang/org/autoload/org-link.el index a1dc13eaa..8ee10aab3 100644 --- a/modules/lang/org/autoload/org-link.el +++ b/modules/lang/org/autoload/org-link.el @@ -84,6 +84,50 @@ exist, and `org-link' otherwise." (message "Download of image \"%s\" failed" link) nil))) +(defvar +org--gif-timers nil) +;;;###autoload +(defun +org-play-gif-at-point-h () + "Play the gif at point, while the cursor remains there (looping)." + (dolist (timer +org--gif-timers (setq +org--gif-timers nil)) + (when (timerp (cdr timer)) + (cancel-timer (cdr timer))) + (image-animate (car timer) nil 0)) + (when-let* ((ov (cl-find-if + (lambda (it) (overlay-get it 'org-image-overlay)) + (overlays-at (point)))) + (dov (overlay-get ov 'display)) + (pt (point))) + (when (image-animated-p dov) + (push (cons + dov (run-with-idle-timer + 0.5 nil + (lambda (dov) + (when (equal + ov (cl-find-if + (lambda (it) (overlay-get it 'org-image-overlay)) + (overlays-at (point)))) + (message "playing gif") + (image-animate dov nil t))) + dov)) + +org--gif-timers)))) + +;;;###autoload +(defun +org-play-all-gifs-h () + "Continuously play all gifs in the visible buffer." + (dolist (ov (overlays-in (point-min) (point-max))) + (when-let* (((overlay-get ov 'org-image-overlay)) + (dov (overlay-get ov 'display)) + ((image-animated-p dov)) + (w (selected-window))) + (while-no-input + (run-with-idle-timer + 0.3 nil + (lambda (dov) + (when (pos-visible-in-window-p (overlay-start ov) w nil) + (unless (plist-get (cdr dov) :animate-buffer) + (image-animate dov)))) + dov))))) + ;; ;;; Commands @@ -100,3 +144,13 @@ exist, and `org-link' otherwise." (org-link-unescape (match-string-no-properties 1))))) (delete-region (match-beginning 0) (match-end 0)) (insert label)))) + +;;;###autoload +(defun +org/play-gif-at-point () + "TODO" + (interactive) + (unless (eq 'org-mode major-mode) + (user-error "Not in org-mode")) + (or (+org-play-gif-at-point-h) + (user-error "No gif at point"))) + diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index 80dbeaea6..05773faed 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -64,6 +64,9 @@ Is relative to `org-directory', unless it is absolute. Is used in Doom's default (defvar +org-habit-graph-window-ratio 0.3 "The ratio of the consistency graphs relative to the window width") +(defvar +org-startup-with-animated-gifs nil + "If non-nil, and the cursor is over a gif inline-image preview, animate it!") + ;; ;;; `org-load' hooks @@ -1250,4 +1253,17 @@ compelling reason, so..." :before-while '(org-id-locations-save org-id-locations-load) (file-writable-p org-id-locations-file)) - (add-hook 'org-open-at-point-functions #'doom-set-jump-h)) + (add-hook 'org-open-at-point-functions #'doom-set-jump-h) + + ;; Add the ability to play gifs, at point or throughout the buffer. However, + ;; 'playgifs' is stupid slow and there's not much I can do to fix it; use at + ;; your own risk. + (add-to-list 'org-startup-options '("inlinegifs" +org-startup-with-animated-gifs at-point)) + (add-to-list 'org-startup-options '("playgifs" +org-startup-with-animated-gifs t)) + (add-hook! 'org-mode-local-vars-hook + (defun +org-init-gifs-h () + (remove-hook 'post-command-hook #'+org-play-gif-at-point-h t) + (remove-hook 'post-command-hook #'+org-play-all-gifs-h t) + (pcase +org-startup-with-animated-gifs + (`at-point (add-hook 'post-command-hook #'+org-play-gif-at-point-h nil t)) + (`t (add-hook 'post-command-hook #'+org-play-all-gifs-h nil t))))))