auctex-devel
[Top][All Lists]
Advanced

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

Updating xparse.el


From: Arash Esbati
Subject: Updating xparse.el
Date: Sat, 20 Jun 2020 23:06:34 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50

Hi all,

next LaTeX release will include some code from xparse.sty[1]:

--8<---------------cut here---------------start------------->8---
\section{Providing \pkg{xparse} in the format}

[...]

The ideas developed in \pkg{xparse} are now sufficiently well-tested
that the majority can be transferred into the \LaTeX{} kernel. Thus
the following commands have been added
\begin{itemize}
  \item \cs{NewDocumentCommand}, \cs{RenewDocumentCommand},
    \cs{ProvideDocumentCommand}, \cs{DeclareDocumentCommand}
  \item \cs{NewExpandableDocumentCommand}, \cs{RenewExpandableDocumentCommand},
    \cs{ProvideExpandableDocumentCommand}, \cs{DeclareExpandableDocumentCommand}
  \item \cs{NewDocumentEnvironment}, \cs{RenewDocumentEnvironment},
    \cs{ProvideDocumentEnvironment}, \cs{DeclareDocumentEnvironment}
  \item \cs{BooleanTrue} \cs{BooleanFalse}
  \item \cs{IfBooleanTF}, \cs{IfBooleanT}, \cs{IfBooleanF}
  \item \cs{IfNoValueTF}, \cs{IfNoValueT}, \cs{IfNoValueF}
  \item \cs{IfValueTF}, \cs{IfValueT}, \cs{IfValueF}
  \item \cs{SplitArgument}, \cs{SplitList}, \cs{TrimSpaces},
    \cs{ProcessList}, \cs{ReverseBoolean}
  \item \cs{GetDocumentCommandArgSpec}
    \cs{GetDocumentEnvironmentArgSpec}
\end{itemize}

Most, but not all, of the argument types defined by \pkg{xparse} are
now supported at the kernel level. In particular, the types
\texttt{g}/\texttt{G}, \texttt{l} and \texttt{u} are \emph{not} provided by
the kernel code; these are deprecated but still available by
explicitly loading \pkg{xparse}. All other argument types \emph{are}
now available directly within the \LaTeXe{} kernel.
--8<---------------cut here---------------end--------------->8---

This means that we'll need to move code from xparse.el into latex.el.
Until now, xparse.el doesn't support parsing .tex files.  I've updated
xparse.el to do so and would like to ask for comments here before I move
to the code into the AUCTeX repo.  The .el file is attached, the diff is
attached below.  Any comments welcome.

--8<---------------cut here---------------start------------->8---
diff --git a/style/xparse.el b/style/xparse.el
index 271ec615..76293b69 100644
--- a/style/xparse.el
+++ b/style/xparse.el
@@ -1,9 +1,9 @@
-;;; xparse.el --- AUCTeX style for `xparse.sty' version 4467.
+;;; xparse.el --- AUCTeX style for `xparse.sty' version 2020-03-06

-;; Copyright (C) 2013, 2018 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2020 Free Software Foundation, Inc.

 ;; Maintainer: auctex-devel@gnu.org
-;; Author: Mosè Giordano <giordano.mose@libero.it>
+;; Author: Mosè Giordano <mose@gnu.org>
 ;; Keywords: tex

 ;; This file is part of AUCTeX.
@@ -25,8 +25,13 @@

 ;;; Commentary:

-;; This file adds basic support for `xparse.sty' version 4467.  It
-;; doesn't parse argument specification of macros and environments.
+;; This file adds basic support for `xparse.sty' version 2020-03-06.
+;; It parses argument specification of macros and environments.
+
+;; Currently, this style doesn't parse the embellishments specifiers
+;; `e' and `E'.  The "yet not more supported" specifiers `l', `u', `g'
+;; and `G' are ignored completely and may lead to wrong parsing
+;; results.

 ;;; Code:

@@ -35,25 +40,193 @@
                  "font-latex"
                  (keywords class))

+;; Needed for auto-parsing.
+(require 'tex)
+
+(TeX-auto-add-type "xparse-macro" "LaTeX")
+
 (defvar LaTeX-xparse-macro-regexp
-  (concat "\\\\\\(?:Declare\\|New\\|Renew\\|Provide\\|DeclareExpandable\\)"
-         "DocumentCommand[ \t\n\r]*{?[ \t\n\r]*\\\\\\([A-Za-z]+\\)[ \t\n\r]*}?"
-         ;; The following is the opening brace of argument specification and is
-         ;; needed to skip internal macros containing `:' or `_'.
-         "[ \t\n\r]*{")
+  `(,(concat
+      (regexp-quote TeX-esc)
+      "\\(?:"
+      "New\\|Renew\\|Provide\\|Declare"
+      "\\)"
+      "\\(?:Expandable\\)?"
+      "DocumentCommand"
+      "[ \t\n\r]*"
+      "{?"
+      "[ \t\n\r]*"
+      (regexp-quote TeX-esc)
+      "\\([A-Za-z]+\\)"
+      "[ \t\n\r]*"
+      "}?"
+      "[ \t\n\r]*"
+      
"{\\([^}{]*\\({[^}{]*\\({[^}{]*\\({[^}{]*}[^}{]*\\)*}[^}{]*\\)*}[^}{]*\\)*\\)}")
+    (1 2) LaTeX-auto-xparse-macro)
   "Matches macros by xparse package.")

+(TeX-auto-add-type "xparse-environment" "LaTeX")
+
 (defvar LaTeX-xparse-environment-regexp
-  (concat "\\\\\\(?:Declare\\|New\\|Renew\\|Provide\\)DocumentEnvironment"
-         "[ \t\n\r]*{[ \t\n\r]*\\([A-Za-z]+\\)[ \t\n\r]*}")
+  `(,(concat
+      (regexp-quote TeX-esc)
+      "\\(?:Declare\\|New\\|Provide\\|Renew\\)"
+      "DocumentEnvironment"
+      "[ \t\n\r]*"
+      "{"
+      "[ \t\n\r]*"
+      "\\([A-Za-z]+\\)"
+      "[ \t\n\r]*"
+      "}"
+      "[ \t\n\r]*"
+      
"{\\([^}{]*\\({[^}{]*\\({[^}{]*\\({[^}{]*}[^}{]*\\)*}[^}{]*\\)*}[^}{]*\\)*\\)}")
+    (1 2) LaTeX-auto-xparse-environment)
   "Matches environments by xparse package.")

+(defun LaTeX-arg-xparse-query (optional op-brace cl-brace &optional prompt)
+  "Special query function for parsed elements from xparse package.
+If OPTIONAL is non-nil, indicate it in minibuffer.  OP-BRACE sets
+the opening brace, CL-BRACE sets the closing one.  PROMPT
+replaces the standard one."
+  (let ((TeX-arg-opening-brace op-brace)
+       (TeX-arg-closing-brace cl-brace))
+    (TeX-argument-insert
+     (TeX-read-string (TeX-argument-prompt optional prompt "Text"))
+     optional)))
+
+(defun LaTeX-xparse-macro-parse (type)
+  "Process parsed macro and environment definitions.
+TYPE is one of the symobols mac or env."
+  (dolist (xcmd (if (eq type 'mac)
+                   (LaTeX-xparse-macro-list)
+                 (LaTeX-xparse-environment-list)))
+    (let ((name (car xcmd))
+         (spec (cadr xcmd))
+         args opt-star opt-token)
+      (with-temp-buffer
+       (with-syntax-table LaTeX-mode-syntax-table
+         (goto-char (point-min))
+         (save-excursion
+           (insert (replace-regexp-in-string "[ \t\r\n%]" "" spec)))
+         (while (looking-at-p "[+!>bmrRvodODsteE]")
+           (cond (;; + or !: Long argument or space aware: Move over
+                  ;; them.  b is special; only available for
+                  ;; enviroments
+                  (looking-at-p "[+!b]")
+                  (forward-char 1))
+                 ((looking-at-p ">")
+                  ;; Argument processors: Move over > and a balanced
+                  ;; {}
+                  (forward-char 1)
+                  (forward-sexp))
+                 ;; Mandatory arguments:
+                 ;; m: Ask for input with "Text" as prompt
+                 ((looking-at-p "m")
+                  (forward-char 1)
+                  (push "Text" args))
+                 ;; r<token1><token2>
+                 ((looking-at-p "r")
+                  (re-search-forward "r\\(?:\\(.\\)\\(.\\)\\)" (+ (point) 3) t)
+                  (push `(LaTeX-arg-xparse-query
+                          ,(match-string-no-properties 1)
+                          ,(match-string-no-properties 2))
+                        args))
+                 ;; R<token1><token2>{default}
+                 ((looking-at-p "R")
+                  (re-search-forward "R\\(?:\\(.\\)\\(.\\)\\)" (+ (point) 3) t)
+                  (forward-sexp)
+                  (push `(LaTeX-arg-xparse-query
+                          ,(match-string-no-properties 1)
+                          ,(match-string-no-properties 2))
+                        args))
+                 ;; v: Use `TeX-arg-verb-delim-or-brace'
+                 ((looking-at-p "v")
+                  (forward-char 1)
+                  (push 'TeX-arg-verb-delim-or-brace args))
+                 ;; Optional arguments:
+                 ;; o standard LaTeX optional in square brackets
+                 ((looking-at-p "o")
+                  (forward-char 1)
+                  (push (vector "Text") args))
+                 ;; d<token1><token2>
+                 ((looking-at-p "d")
+                  (re-search-forward "d\\(?:\\(.\\)\\(.\\)\\)" (+ (point) 3) t)
+                  (push (vector 'LaTeX-arg-xparse-query
+                                (match-string-no-properties 1)
+                                (match-string-no-properties 2))
+                        args))
+                 ;; O{default}
+                 ((looking-at-p "O")
+                  (forward-char 1)
+                  (forward-sexp)
+                  (push (vector "Text") args))
+                 ;; D<token1><token2>{default}
+                 ((looking-at-p "D")
+                  (re-search-forward "D\\(?:\\(.\\)\\(.\\)\\)" (+ (point) 3) t)
+                  (forward-sexp)
+                  (push (vector 'LaTeX-arg-xparse-query
+                                (match-string-no-properties 1)
+                                (match-string-no-properties 2))
+                        args))
+                 ;; s: optional star
+                 ((looking-at-p "s")
+                  (forward-char 1)
+                  (setq opt-star t))
+                 ;; t: optional <token>
+                 ((looking-at-p "t")
+                  (re-search-forward "t\\(.\\)" (+ (point) 2) t)
+                  (setq opt-token (match-string-no-properties 1)))
+                 ;; e & E are currently ignored.  e: If looking at a
+                 ;; {, move one balanced expression, otherwise only
+                 ;; one character.
+                 ((looking-at-p "e")
+                  (forward-char)
+                  (if (looking-at-p TeX-grop)
+                      (forward-sexp)
+                    (forward-char)))
+                 ;; E
+                 ((looking-at-p "E")
+                  (forward-char)
+                  (if (looking-at-p TeX-grop)
+                      (forward-sexp)
+                    (forward-char))
+                  (if (looking-at-p TeX-grop)
+                      (forward-sexp)
+                    (forward-char)))
+                 ;; Finished:
+                 (t nil)))))
+      (if (eq type 'env)
+         (LaTeX-add-environments `(,name
+                                   LaTeX-env-args
+                                   ,@(reverse (copy-sequence args))))
+       (TeX-add-symbols (cons name
+                              (reverse (copy-sequence args))))
+       (when opt-star
+         (TeX-add-symbols (cons (concat name "*")
+                                (reverse (copy-sequence args)))))
+       (when opt-token
+         (TeX-add-symbols (cons (concat name opt-token)
+                                (reverse (copy-sequence args)))))))))
+
+(defun LaTeX-xparse-auto-prepare ()
+  "Clear various `LaTeX-auto-xparse-*' variables before parsing."
+  (setq LaTeX-auto-xparse-macro nil
+       LaTeX-auto-xparse-environment nil))
+
+(defun LaTeX-xparse-auto-cleanup ()
+  "Process parsed elements for xparse package."
+  (LaTeX-xparse-macro-parse 'mac)
+  (LaTeX-xparse-macro-parse 'env))
+
+(add-hook 'TeX-auto-prepare-hook #'LaTeX-xparse-auto-prepare t)
+(add-hook 'TeX-auto-cleanup-hook #'LaTeX-xparse-auto-cleanup t)
+(add-hook 'TeX-update-style-hook #'TeX-auto-parse t)
+
 (TeX-add-style-hook
  "xparse"
  (lambda ()
-   (TeX-auto-add-regexp `(,LaTeX-xparse-macro-regexp 1 TeX-auto-symbol))
-   (TeX-auto-add-regexp
-    `(,LaTeX-xparse-environment-regexp 1 LaTeX-auto-environment))
+   (TeX-auto-add-regexp LaTeX-xparse-macro-regexp)
+   (TeX-auto-add-regexp LaTeX-xparse-environment-regexp)
    (TeX-run-style-hooks
     "expl3")
    (TeX-add-symbols
@@ -97,18 +270,24 @@
     '("GetDocumentEnvironmmentArgSpec" TeX-arg-environment)
     '("ShowDocumentCommandArgSpec" TeX-arg-macro)
     '("ShowDocumentEnvironmentArgSpec" TeX-arg-environment))
+
    ;; Fontification
    (when (and (featurep 'font-latex)
              (eq TeX-install-font-lock 'font-latex-setup))
      (font-latex-add-keywords '(("DeclareDocumentCommand" "|{\\{{")
-                               ("NewDocumentCommand" "|{\\{{")
-                               ("RenewDocumentCommand" "|{\\{{")
+                               ("NewDocumentCommand"     "|{\\{{")
                                ("ProvideDocumentCommand" "|{\\{{")
+                               ("RenewDocumentCommand"   "|{\\{{")
+                               ;;
                                ("DeclareExpandableDocumentCommand" "|{\\{{")
+                               ("NewExpandableDocumentCommand"     "|{\\{{")
+                               ("ProvideExpandableDocumentCommand" "|{\\{{")
+                               ("RenewExpandableDocumentCommand"   "|{\\{{")
+                               ;;
                                ("DeclareDocumentEnvironment" "{{{{")
-                               ("NewDocumentEnvironment" "{{{{")
-                               ("RenewDocumentEnvironment" "{{{{")
-                               ("ProvideDocumentEnvironment" "{{{{"))
+                               ("NewDocumentEnvironment"     "{{{{")
+                               ("ProvideDocumentEnvironment" "{{{{")
+                               ("RenewDocumentEnvironment"   "{{{{"))
                              'function)))
  LaTeX-dialect)
--8<---------------cut here---------------end--------------->8---

Best, Arash

Footnotes:
[1]  
https://github.com/latex3/latex2e/blob/e71289ee98362cd7de2f1fe0401b939423c5113d/base/doc/ltnews32.tex#L139

Attachment: xparse.el
Description: application/emacs-lisp


reply via email to

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