Function: org-lint-invalid-macro-argument-and-template
org-lint-invalid-macro-argument-and-template is a byte-compiled
function defined in org-lint.el.gz.
Signature
(org-lint-invalid-macro-argument-and-template AST)
Source Code
;; Defined in /usr/src/emacs/lisp/org/org-lint.el.gz
(defun org-lint-invalid-macro-argument-and-template (ast)
(let* ((reports nil)
(extract-placeholders
(lambda (template)
(let ((start 0)
args)
(while (string-match "\\$\\([1-9][0-9]*\\)" template start)
(setf start (match-end 0))
(push (string-to-number (match-string 1 template)) args))
(sort (org-uniquify args) #'<))))
(check-arity
(lambda (arity macro)
(let* ((name (org-element-property :key macro))
(pos (org-element-begin macro))
(args (org-element-property :args macro))
(l (length args)))
(cond
((< l (1- (car arity)))
(push (list pos (format "Missing arguments in macro %S" name))
reports))
((< l (car arity))
(push (list pos (format "Missing argument in macro %S" name))
reports))
((> l (1+ (cdr arity)))
(push (let ((spurious-args (nthcdr (cdr arity) args)))
(list pos
(format "Spurious arguments in macro %S: %s"
name
(mapconcat #'org-trim spurious-args ", "))))
reports))
((> l (cdr arity))
(push (list pos
(format "Spurious argument in macro %S: %s"
name
(org-last args)))
reports))
(t nil))))))
;; Check arguments for macro templates.
(org-element-map ast 'keyword
(lambda (k)
(when (string= (org-element-property :key k) "MACRO")
(let* ((value (org-element-property :value k))
(name (and (string-match "^\\S-+" value)
(match-string 0 value)))
(template (and name
(org-trim (substring value (match-end 0))))))
(cond
((not name)
(push (list (org-element-post-affiliated k)
"Missing name in MACRO keyword")
reports))
((not (org-string-nw-p template))
(push (list (org-element-post-affiliated k)
"Missing template in macro \"%s\"" name)
reports))
(t
(unless (let ((args (funcall extract-placeholders template)))
(equal (number-sequence 1 (or (org-last args) 0)) args))
(push (list (org-element-post-affiliated k)
(format "Unused placeholders in macro \"%s\""
name))
reports))))))))
;; Check arguments for macros.
(org-macro-initialize-templates)
(let ((templates (append
(mapcar (lambda (m) (cons m "$1"))
'("author" "date" "email" "title" "results"))
org-macro-templates)))
(org-element-map ast 'macro
(lambda (macro)
(let* ((name (org-element-property :key macro))
(template (cdr (assoc-string name templates t))))
(pcase template
(`nil
(push (list (org-element-begin macro)
(format "Undefined macro %S" name))
reports))
((guard (string= name "keyword"))
(funcall check-arity '(1 . 1) macro))
((guard (string= name "modification-time"))
(funcall check-arity '(1 . 2) macro))
((guard (string= name "n"))
(funcall check-arity '(0 . 2) macro))
((guard (string= name "property"))
(funcall check-arity '(1 . 2) macro))
((guard (string= name "time"))
(funcall check-arity '(1 . 1) macro))
((pred functionp)) ;ignore (eval ...) templates
(_
(let* ((arg-numbers (funcall extract-placeholders template))
(arity (if (null arg-numbers)
'(0 . 0)
(let ((m (apply #'max arg-numbers)))
(cons m m)))))
(funcall check-arity arity macro))))))))
reports))