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" "|{{{") + (font-latex-add-keywords '(("DeclareDocumentCommand" "|{\\{{") ("NewDocumentCommand" "|{{{") ("RenewDocumentCommand" "|{{{") ("ProvideDocumentCommand" "|{{{")