auctex-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: tex-numbers.el


From: Arash Esbati
Subject: Re: tex-numbers.el
Date: Tue, 16 Apr 2024 22:27:05 +0200
User-agent: Gnus/5.13 (Gnus v5.13)

Hi Paul,

Paul Nelson <ultrono@gmail.com> writes:

> I wanted to share a package that I'd like to eventually submit to
> ELPA.  It augments the preview/fold features of AUCTeX with correct
> numbering when possible, and provides an interface that would allow
> other packages to retrieve label numbers.  It's attached to this
> email, and I'll keep an updated version at
> https://github.com/ultronozm/tex-numbers.el.

Nice.  I have a question: Would this feature also work with the CAPF
machinery provided by AUCTeX?  Currently, AUCTeX borrows the context of
a \label from RefTeX and shows a \ref in-buffer completion like this:

PNG image

I wonder if it is possible to attach the number to the context.

> QUESTION: The package currently works only on the master branch for
> AUCTeX because it depends upon patches that have recently been
> installed, so I'm wondering whether I should wait for those to make it
> into a release before attempting to push it further, and when that
> might happen.

I suggest you streamline your initial release with next AUCTeX ELPA
release which will be 14.0.5, so something like this:

;; Package-Requires: ((auctex "14.0.5"))

Also note that AUCTeX requires Emacs 27.1, so it's probably better if
you follow this too.

We don't have a strict release plan, it happens when we feel appropriate
by dropping Tassilo H. a line, and the new release happens usually
within hours.  So that won't be showstopper.  So just ask here if you
feel we should make a new release, and we will see how to organize it.

> I'd appreciate any feedback or advice.

I went briefly through the code, comments below, please feel free to
ignore.

> ;;; tex-numbers.el --- numbering for LaTeX previews and folds  -*- 
> lexical-binding: t; -*-
>
> ;; Copyright (C) 2024  Paul D. Nelson
>
> ;; Author: Paul D. Nelson <nelson.paul.david@gmail.com>
> ;; Version: 0.0
> ;; URL: https://github.com/ultronozm/czm-preview.el
> ;; Package-Requires: ((emacs "26.1") (auctex))

;; Package-Requires: ((emacs "27.1") (auctex "14.0.5"))

> (defgroup tex-numbers nil
>   "Numbering for LaTeX previews and folds."
>   :group 'AUCTeX)
>
> (defun tex-numbers-label-to-number-helper (label aux-file)
>   "Get the number of LABEL from the aux file AUX-FILE.

"Get the number of LABEL from the AUX-FILE."

> (defcustom tex-numbers-label-to-number-function nil
>   "Function to retrieve label numbers.
> If non-nil, `tex-numbers-label-to-number' delegates to this function.
> The function should take a label string as its argument and return the
> corresponding label number as a string, or nil if that number cannot be
> retrieved."
>   :type '(choice (const :tag "Default" nil) function)
>   :group 'tex-numbers)

You can drop ":group 'tex-numbers".  The last `defgroup' name is used
when this keyword is left out.

> (defun tex-numbers-label-to-number (label)
>   "Get number of LABEL for current tex buffer.
> If the buffer does not point to a file, or if the corresponding
> aux file does not exist, or if the label cannot be found, then
> return nil.  Otherwise, return the label number as a string.  If
> the label is found in an external document, prefix the string
> with \"X\"."
>   (if tex-numbers-label-to-number-function
>       (funcall tex-numbers-label-to-number-function label)
>     (or
>      (when-let* ((aux-file (TeX-master-file "aux")))
>        (tex-numbers-label-to-number-helper label aux-file))
>      ;; If we can't retrieve the label from the main file, then we look
>      ;; at any external documents.
>      (save-excursion
>        (save-restriction
>          (widen)
>          (goto-char (point-min))
>          (let (found)
>            (while (and (null found)
>                        (re-search-forward "\\\\externaldocument{\\([^}]+\\)}" 
> nil t))

\external(cite)?document also takes an optional argument, and with
hyperref loaded, xr-hyper makes it take 2 optional arguments:

  \externaldocument[prefix][nocite]{document}[url]

So maybe you want to search after:

  "\\\\external\\(?:cite\\)?document\\(?:\\[[^]]+\\]\\)\\{0,2\\}{\\([^}]+\\)}"

>              (let* ((filename (concat (match-string 1) ".aux")))
>                (setq found (tex-numbers-label-to-number-helper label 
> filename))))
>            (when found
>              (concat "X" found))))))))
>
> (defun tex-numbers-preview-preprocessor (str)
>   "Preprocess STR for preview by adding tags to labels.
> Uses `tex-numbers-label-to-number-function' to retrieve label numbers."
>   (let ((buf (current-buffer)))
>     (with-temp-buffer
>       (insert str)
>       (goto-char (point-min))
>       (while (re-search-forward "\\\\label{\\([^}]+\\)}" nil t)

With cleveref.sty loaded, \label also takes an optional argument, so
better:

  "\\\\label\\(?:\\[[^]]+\\]\\)?{\\([^}]+\\)}"

>         (let ((label (match-string 1)))
>           (when-let ((number
>                       (with-current-buffer buf
>                         (tex-numbers-label-to-number label))))
>             (when (let ((comment-start-skip
>                          "\\(\\(^\\|[^\\
> ]\\)\\(\\\\\\\\\\)*\\)\\(%+[  ]*\\)"))

Why do you insert a hard newline or tab, and not [^\\\r\n] and %+[ \t]*?
Or am I missing something?

>                     ;; HACK: texmathp expects to be run in LaTeX-mode,
>                     ;; but here we are in a temporary buffer.
>                     (texmathp))
>               (insert (format "\\tag{%s}" number))))))
>       (buffer-substring-no-properties (point-min) (point-max)))))
>
> (defun tex-numbers-ref-helper (label default)
>   "Helper function for `tex-numbers-ref-display'.
> Returns a fold display string for LABEL (retrieved via
> `tex-numbers-label-to-number-function'), or DEFAULT if the label number cannot
> be retrieved."
>   (format "[%s]" (or (tex-numbers-label-to-number label) default)))

If this is an internal helper function, you can rename it to
`tex-numbers--ref-helper'

> (defcustom tex-numbers-macro-list '("ref" "eqref" "label")
>   "List of macros to fold with theorem or equation numbers.
> Each element describes a LaTeX macro that takes a label as its argument.
> There should be a corresponding function `tex-numbers-MACRO-display'
> that returns a fold display string for that macro."
>   :type '(repeat string)
>   :group 'tex-numbers)

Again, ":group 'tex-numbers" is not needed.

> ;;;###autoload
> (define-minor-mode tex-numbers-mode
>   "Toggle `tex-numbers' mode."
>   :global t
>   :lighter nil
>   (cond
>    (tex-numbers-mode
>     (setq preview-preprocess-function #'tex-numbers-preview-preprocessor)
>     (require 'tex-fold)
>     (dolist (macro tex-numbers-macro-list)
>       (let ((func (intern (format "tex-numbers-%s-display" macro))))
>         (dolist (spec TeX-fold-macro-spec-list)
>           (when (and (member macro (cadr spec))
>                      (not (eq (car spec) func)))
>             (push (cons macro (car spec)) tex-numbers--saved-spec-list)
>             (setcdr spec (list (cl-remove macro (cadr spec) :test 'equal)))))
>         (add-to-list 'TeX-fold-macro-spec-list (list func (list macro)))))
>     (when TeX-fold-mode
>       (TeX-fold-mode 1)))
>    (t
>     (setq preview-preprocess-function nil)
>     (dolist (macro tex-numbers-macro-list)
>       (let ((func (intern (format "tex-numbers-%s-display" macro))))
>         (setq TeX-fold-macro-spec-list
>               (cl-remove-if (lambda (elem) (eq (car elem) func))
>                             TeX-fold-macro-spec-list)))
>       (when-let ((saved (assoc macro tex-numbers--saved-spec-list)))
>         (dolist (spec TeX-fold-macro-spec-list)
>           (when (eq (car spec) (cdr saved))
>             (push macro (cadr spec))))))
>     (setq tex-numbers--saved-spec-list nil)
>     (when TeX-fold-mode
>       (TeX-fold-mode 1)))))

I think this is a matter of taste, but

  (cond (clause true)
        (t rest))

is the same as

  (if clause
      (progn true)
    rest)

right?

Best, Arash

reply via email to

[Prev in Thread] Current Thread [Next in Thread]