Hi all,
I was thinking about how to extend xparse.el in order to parse argument
specs (which can be quite complicated) and now have a working setup --
diff and patched xparse.el are attached. Main work is done by
`LaTeX-xparse-macro-parse'. I don't have much experience with this kind
of parsing within Emacs. Question: Is this kind of implementation
robust enough or are there better ways to do the job?
Here a small document I played with:
--8<---cut here---start->8---
\documentclass{article}
\usepackage{xparse}
\DeclareDocumentCommand \Foo { > { \ReverseBoolean } s o > { \SplitList { ; } }
m r!! }{
\ProcessList {#1} { \SomeDocumentFunction }
}
\begin{document}
C-c C-m Foo RET
\end{document}
--8<---cut here---end--->8---
Any comments welcome.
Best, Arash
diff --git a/style/xparse.el b/style/xparse.el
index d75f81c..672a609 100644
--- a/style/xparse.el
+++ b/style/xparse.el
@@ -30,12 +30,23 @@
;;; Code:
+;; 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 "\\(?:Declare\\|New\\|Renew\\|Provide\\|DeclareExpandable\\)"
+ "DocumentCommand"
+ "[ \t\n\r]*"
+ "{?"
+ "[ \t\n\r]*"
+ "\\([A-Za-z]+\\)"
+ "[ \t\n\r]*"
+ "}?"
+ "[ \t\n\r]*"
+ "{\\([^}{]*\\({[^}{]*\\({[^}{]*\\({[^}{]*}[^}{]*\\)*}[^}{]*\\)*}[^}{]*\\)*\\)}")
+(1 2) LaTeX-auto-xparse-macro)
"Matches macros by xparse package.")
(defvar LaTeX-xparse-environment-regexp
@@ -43,10 +54,88 @@
"[ \t\n\r]*{[ \t\n\r]*\\([A-Za-z]+\\)[ \t\n\r]*}")
"Matches environments by xparse package.")
+(defun LaTeX-xparse-auto-prepare ()
+ "Clear various `LaTeX-xparse-*' variables before parsing."
+ (setq LaTeX-auto-xparse-macro nil))
+
+(defun LaTeX-xparse-auto-cleanup ()
+ "Process parsed elements for xparse package."
+ (LaTeX-xparse-macro-parse))
+
+(defun LaTeX-xparse-macro-parse ()
+ "tbd"
+ (dolist (xcmd (LaTeX-xparse-macro-list))
+(let ((macro (car xcmd))
+ args
+ have-arg
+ have-star)
+ (with-temp-buffer
+ (insert (replace-regexp-in-string "[ \t\r\n+%]" "" (cadr xcmd)))
+ (goto-char (point-min))
+ (while (cond (;; Skip over Argument processors and return t
+ (looking-at ">")
+ (forward-char 1)
+ (forward-sexp)
+ t)
+ ;; Mandatory arguments:
+ ;; Add t for first occurrence, otherwise nil
+ ((looking-at "[mlv]")
+ (forward-char 1)
+ (if have-arg
+ (push nil args)
+ (progn
+ (push t macro)
+ (setq have-arg t
+ ;; r with `TeX-arg-literal'
+ ((looking-at "r")
+ (save-excursion
+ (re-search-forward "r\\(..\\)" (+ (point) 3) t))
+ (forward-char 3)
+ (push `(TeX-arg-literal ,(match-string-no-properties 1)) args))
+ ;; R {default skipped}, with `TeX-arg-literal'
+ ((looking-at "R")
+ (save-excursion
+ (re-search-forward "R\\(..\\)" (+ (point) 3) t))
+ (forward-char 3)
+ (forward-sexp)
+ (push `(TeX-arg-literal ,(match-string-no-properties 1)) args))
+ ;; Optional arguments:
+ ((looking-at "o")
+ (forward-char 1)
+ (if have-arg
+ (push (vector nil) args)
+ (progn
+ (push (vector t) args)
+ (setq have-arg t
+ ((looking-at "d")
+ (save-excursion
+ (re-search-forward "d\\(..\\)" (+ (point) 3) t))
+ (forward-char 3)
+ (push `(TeX-arg-literal ,(match-string-no-properties 1)) args))
+ ((looking-at "O")
+ (forward-char 1)
+ (forward-sexp)
+ (if have-arg
+ (push (vector nil) args)
+ (progn
+ (push (vector t) args)
+ (setq have-arg t
+ ((looking-at "s")
+ (forward-char 1)
+ (setq have-star t))
+ (t nil
+ (TeX-add-symbols (append (list macro) (reverse args)))
+ (when have-star
+ (TeX-add-symbols (append (list (concat macro "*")) (reverse args)))
+
+(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-macro-regexp)
(TeX-auto-add-regexp
`(,LaTeX-xparse-environment-regexp 1 LaTeX-auto-environment))
(TeX-run-style-hooks
@@ -95,7 +184,7 @@
;; Fontification
(when (and (featurep 'font-latex)
(eq TeX-install-font-lock 'font-latex-setup))
- (font-latex-add-keywords '(("DeclareDocumentCommand" "|{{{")
+