From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms1.migadu.com with LMTPS id KHq+EjxlJWZWcgEAe85BDQ:P1 (envelope-from ) for ; Sun, 21 Apr 2024 21:13:00 +0200 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2.migadu.com with LMTPS id KHq+EjxlJWZWcgEAe85BDQ (envelope-from ) for ; Sun, 21 Apr 2024 21:13:00 +0200 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" ARC-Seal: i=1; s=key1; d=yhetil.org; t=1713726780; a=rsa-sha256; cv=none; b=UtP0TMzv8SuDoP1vxxi3w7bHUPexrfCHJk0D5ssj+ginDn3ZUF4pRl2i1P69T+T/8vFYy9 pi5RnVFhIIw4G+nD1eQmOUZXpRl1XH8HCb0JI1oqBD9z3InzO2t8QfmyBzodoWQ6cQeDSM yErOuHP13bvjWKcaaxCsuFfhLEVtc/KcS/29N4zGUGa/X/c2NBf1oZZAZe2A+xaIrospZK EvxGMpNfjC/oOJGGMb9/0Bo2otr6aTXvuYsbcaMfFusRtFVFSH0DetRvaSo+1AyZZntP+P XUnLa2/BUpXd9377lCkZM9lWMj2i9LKXlkevTmFCHk9a9u0p4o+QZol8MiflZQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1713726780; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post; bh=g54hV1ylOcoxFK7d5A8YAzf0uoMpvnOtmQHV0IzNqVc=; b=cCFKmZxoivTqa4LRJ3+MCnS0REw0cgqa1aaXFyZoezyB5HZ3qlmYBB/7/qFWrs9OqN3h5l FmDERl5sXU3mh3aUrYVZkuVx5lTwAhePmxD8a9LktdjNDR3hH73OBZgl3yr/1U2369r+5i Ra3SwY2n5Ux2w/DInddh15PRnJU1yNOu+MeaMvXkezgSfr0fGgoY01Zv9BR46w4dljpfqw NbYLKkLv2eN+zP1fK7vS6L7EPwaGWrMqzqEbj05MDZoOVNOowYt0x5bMraER9u9KP4tLMM EejP8Am8dCvIhKz8fKAzChXzY9Dshrns0inmMEmtTYFIXEyKJj2E2NUsvw0gQg== Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id F2A952423A for ; Sun, 21 Apr 2024 21:12:59 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rycbZ-00048W-VN; Sun, 21 Apr 2024 15:12:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rycaz-0003a4-BK for emacs-orgmode@gnu.org; Sun, 21 Apr 2024 15:11:25 -0400 Received: from www553.your-server.de ([78.46.153.203]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rycaj-0007kG-MK for emacs-orgmode@gnu.org; Sun, 21 Apr 2024 15:11:22 -0400 Received: from sslproxy05.your-server.de ([78.46.172.2]) by www553.your-server.de with esmtpsa (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rycaV-000N68-AL; Sun, 21 Apr 2024 21:10:55 +0200 Received: from [2001:9e8:b26:2f00:57ab:fe27:fd25:9999] (helo=comonad) by sslproxy05.your-server.de with esmtpsa (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1rycaU-000Jsk-2U; Sun, 21 Apr 2024 21:10:55 +0200 From: Tony Zorman To: Karthik Chikmagalur , emacs-orgmode@gnu.org Subject: Re: Using org-latex-preview in other major modes In-Reply-To: <87cyqyqp1w.fsf@hyperspace> References: <87edbhljr7.fsf@hyperspace> <874jcdf4hj.fsf@gmail.com> <87wmp8l6dg.fsf@hyperspace> <87y19oe4yd.fsf@gmail.com> <87cyqyqp1w.fsf@hyperspace> User-Agent: Notmuch/0.38.3, Emacs 30.0.50 Date: Sun, 21 Apr 2024 21:10:53 +0200 Message-ID: <87cyqi8rb6.fsf@hyperspace> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Authenticated-Sender: mail@tony-zorman.com X-Virus-Scanned: Clear (ClamAV 0.103.10/27252/Sun Apr 21 10:23:14 2024) Received-SPF: pass client-ip=78.46.153.203; envelope-from=mail@tony-zorman.com; helo=www553.your-server.de X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_SBL_A=0.1 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Spam-Score: -5.65 X-Migadu-Queue-Id: F2A952423A X-Migadu-Spam-Score: -5.65 X-Migadu-Scanner: mx10.migadu.com X-TUID: BUIkWxjpvhWa --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Tue, Apr 09 2024 22:06, Tony Zorman wrote: > As a very brief summary, one currently needs to=E2=80=94in addition to su= pplying > a preamble and a way to recognise maths and environments=E2=80=94patch the > following functions: > > =C2=B7 org-latex-preview--place-from-elements > =C2=B7 org-latex-preview-auto--regenerate-overlay=20 > =C2=B7 org-latex-preview-auto--maybe-track-element-here > =C2=B7 org-latex-preview-live--ensure-overlay > > The last two are only needed for the "live" part of the live previews to > work. > > I will clean the code up a little bit (hopefully by the weekend, but no > promises), Whoops! Anyways, before I put this off for much longer, there is some more code attached. Live previews (and general environments) work now, and besides the above mentioned points there were no new surprises waiting=E2=80=94at l= east for getting the basic functionality to work. I did notice that precompilation being a bit flaky. In the end, this was the result of importing local packages; with the precompilation happening somewhere in /tmp/, access to these files wasn't given. I haven't looked too closely into this=E2=80=94and it's probably a use-case t= hat's specific to LaTeX-mode=E2=80=94but it seems worth considering (lots of peop= le carry one big style file around that they include in all of their projects). Tony --=-=-= Content-Type: application/emacs-lisp Content-Disposition: inline; filename=latex-latex-preview.el Content-Transfer-Encoding: quoted-printable (require 'org-latex-preview) (require 'dash) (require 'tex) (defun latex-latex-preview--make-preamble () "Slurp the preamble from the `TeX-master-file'. Code stolen from `TeX-region-create'." (save-excursion (save-restriction (set-buffer ; TeX master (find-file-noselect (TeX-master-file TeX-default-extension))) (save-excursion (save-restriction (widen) (goto-char (point-min)) (if (not (re-search-forward TeX-header-end nil t)) "" (re-search-backward TeX-header-end nil t) (string-replace "\\pdfoutput=3D1" ; HACK "" (buffer-substring-no-properties (point-min) (point))))))))) (defun latex-latex-preview--env-bounds () "Bet bounds for maths environment at point, if any. Return a list with (BEG END)." (save-excursion ;; `texmathp' wants us to be *inside* a maths env. (save-match-data (when (looking-at org-latex-preview--tentative-math-re) (goto-char (match-end 0)))) (-if-let* (((mm . beg) (and (texmathp) texmathp-why)) (end (save-excursion (and (pcase mm ;; Horrible special casing that should be remo= ved. Also, it ;; *is* possible to mix \( with $ etc., but I'= m not sure I ;; even want to allow that. ("$" (search-forward "$" nil t)) ("$$" (search-forward "$$" nil t)) ("\\[" (search-forward "\\]" nil t)) ("\\(" (search-forward "\\)" nil t)) (_ (LaTeX-find-matching-end))) (point))))) (list beg end) (when-let ((pt (point)) (beg (ignore-errors (LaTeX-find-matching-begin) (point))) (_ (not (looking-at "\\\\begin{document}")))) (list beg (ignore-errors (goto-char pt) (LaTeX-find-matching-end) (poin= t))))))) (defun latex-latex-preview-collect-fragments (&optional beg end) "Collect LaTeX maths fragments between BEG and END. Lots stolen from `org-latex-preview-collect-fragments'." (let (fragments) (save-excursion (goto-char (or beg (point-min))) (while (re-search-forward org-latex-preview--tentative-math-re end t) (when-let ((bounds (latex-latex-preview--env-bounds)) ;; Avoid duplicating nested latex environments. (_ (not (and fragments (=3D (car bounds) (caar fragments= )))))) (push bounds fragments)))) (nreverse fragments))) (defun latex-latex-preview-place (entries &optional preamble) "Preview LaTeX maths fragments ENTRIES. See `org-latex-preview-place'." (unless org-latex-preview--preamble-content (setq org-latex-preview--preamble-content (or preamble (latex-latex-preview--make-preamble)))) (org-latex-preview-place org-latex-preview-process-default entries)) (defun latex-latex-preview--place-from-elements (_processing-type elements) "Preview LaTeX math fragments ELEMENTS, ignoring _PROCESSING-TYPE. See `org-latex-preview--place-from-elements'." (latex-latex-preview-place elements)) ;;;###autoload (defun latex-latex-preview-region (beg end) "Preview all LaTeX fragments in the active region." (interactive "r") (latex-latex-preview-place (latex-latex-preview-collect-fragments beg end= ))) ;;;###autoload (defun latex-latex-preview () "Preview LaTeX fragment at point." (interactive) (latex-latex-preview-place (list (latex-latex-preview--env-bounds)))) (defun latex-latex-preview-clear-cache (beg end) "A primitive version of `org-latex-preview-clear-cache'." (interactive (cond ((use-region-p) (list (region-beginning) (region-end))) ((latex-latex-preview--env-bounds)) (t (error "latex-latex-preview-clear-cache needs something to clea= r")))) (org-latex-preview-clear-overlays beg end) (let ((imagetype (or (plist-get (alist-get org-latex-preview-process-default org-latex-preview-process-alist) :image-output-type) "png"))) ;; TODO: This does not quite work yet. (pcase-dolist (`(,begin ,end) (latex-latex-preview-collect-fragments be= g end)) (pcase-let* ((`(,fg ,bg) (org-latex-preview--colors-around begin end)) (value (buffer-substring begin end))) (org-latex-preview--remove-cached (org-latex-preview--hash org-latex-preview-process-default org-latex-preview--preamble-content value imagetype fg bg nil)))) (message "Cleared LaTeX preview cache for %s." (if (or beg end) "region" "buffer")))) ;;; Auto previewing. (defun latex-latex-preview-auto--regenerate-overlay (ov &optional inhibit-r= enumbering) "Regenerate the LaTeX fragment under overlay OV. See `org-latex-preview-auto--regenerate-overlay'." (with-current-buffer (overlay-buffer ov) (if-let* ((start (overlay-start ov)) (end (overlay-end ov)) (fragment (save-excursion (goto-char start) (latex-latex-preview--env-bounds)))) (if (org-latex-preview--empty-fragment-p ; no org-specific code (buffer-substring-no-properties start end)) (progn (delete-overlay ov) (org-latex-preview--ensure-overlay start end)) ; no org-= specific code (latex-latex-preview-place (list fragment))) ;; Delete overlay of fragment is no longer in maths mode. (delete-overlay ov)))) (defun latex-latex-preview-auto--maybe-track-element-here (_type pos) "Check for an element at `point' and ensure an overlay exists. See `org-latex-preview-auto--maybe-track-element-here'." (and (not (eq (get-char-property (point) 'org-overlay-type) 'org-latex-overlay)) (-when-let* (((elem-beg elem-end) (latex-latex-preview--env-bounds)) (ov (org-latex-preview--ensure-overlay elem-beg elem-en= d)) ((not (and (save-excursion (goto-char elem-beg) (looking-at "\\\\begin{\\([^}]+\\)}")) (member (match-string 1) org-latex-preview-auto-ignored-environ= ments))))) (overlay-put ov 'preview-state 'modified) (if (<=3D elem-beg pos elem-end) (progn (overlay-put ov 'view-text t) ;; Record a position safely inside the created overlay (set-marker org-latex-preview-auto--marker (min pos (1- elem-end))) (setq org-latex-preview-auto--from-overlay t) nil) (setq org-latex-preview-auto--inhibit t) element)))) (defun latex-latex-preview-live--ensure-overlay (&optional ov) "Set up a live preview for the LaTeX fragment with overlay OV. See `org-latex-preview-live--ensure-overlay'." (when-let* ((ov (or ov (let ((props (get-char-property-and-overlay (point) 'org-ove= rlay-type))) (and (eq (car props) 'org-latex-overlay) (cdr props))))) (image (overlay-get ov 'preview-image)) (end (overlay-end ov))) (let ((latex-env-p t)) (when (or (eq org-latex-preview-live t) (memq (if latex-env-p 'block 'inline) org-latex-preview-liv= e)) (when (eq org-latex-preview-live-display-type 'buffer) (unless (overlay-get ov 'after-string) ;; NOTE: The latex-env-specific string includes a zero ;; width space char. This is to force the box around the ;; image to render correctly. (setq org-latex-preview-live--docstring (concat (and latex-env-p "\n=E2=80=8B") " ")) (overlay-put ov 'view-text t) (overlay-put ov 'after-string org-latex-preview-live--docstring= ))) (org-latex-preview-live--update-props image '(:box t)))))) ;;;###autoload (define-minor-mode latex-latex-preview-auto-mode "See `org-latex-preview-auto-mode'." :global nil (if latex-latex-preview-auto-mode (progn (setq org-latex-preview-auto--marker (make-marker)) ;; No numbered previews for now. (setq org-latex-preview-numbered nil) ;; This allows us to reuse the code from lots of functions without ;; having to duplicate them. (advice-add 'org-latex-preview-auto--regenerate-overlay :override #'latex-latex-preview-auto--regenerate-overlay) ;; This is so we can reuse the code from ;; `org-latex-preview-auto--detect-fragments-in-change' for now ;; without having to redefine the whole function. (setq org-latex-preview-numbered nil) (advice-add 'org-latex-preview--place-from-elements :override #'latex-latex-preview--place-from-elements) (advice-add 'org-latex-preview-auto--maybe-track-element-here :over= ride #'latex-latex-preview-auto--maybe-track-element-here) (advice-add 'org-latex-preview-live--ensure-overlay :override #'latex-latex-preview-live--ensure-overlay) ;; Actual hooks (add-hook 'pre-command-hook #'org-latex-preview-auto--handle-pre-cu= rsor nil 'local) (org-latex-preview-auto--handle-pre-cursor) ; Invoke setup before t= he hook even fires. (add-hook 'post-command-hook #'org-latex-preview-auto--handle-post-= cursor nil 'local) (add-hook 'after-change-functions #'org-latex-preview-auto--detect-= fragments-in-change nil 'local) (when org-latex-preview-live (org-latex-preview-live--setup))) ;; Off (remove-hook 'pre-command-hook #'org-latex-preview-auto--handle-pre-cur= sor 'local) (remove-hook 'post-command-hook #'org-latex-preview-auto--handle-post-c= ursor 'local) (remove-hook 'after-change-functions #'org-latex-preview-auto--detect-f= ragments-in-change 'local) (org-latex-preview-live--teardown) ;; Remove temporary advice used to make things work. (advice-remove 'org-latex-preview-auto--regenerate-overlay 'latex-latex= -preview-auto--regenerate-overlay) (advice-remove 'org-latex-preview--place-from-elements 'latex-latex-pre= view--place-from-elements) (advice-remove 'org-latex-preview-auto--maybe-track-element-here 'latex= -latex-preview-auto--maybe-track-element-here))) (provide 'latex-latex-preview) ;;; latex-latex-preview.el ends here --=-=-= Content-Type: text/plain -- Tony Zorman | https://tony-zorman.com/ --=-=-=--