Hi Paul, Paul Nelson <[email protected]> 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:
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 <[email protected]> > ;; 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
