yasnippet.el: Recognize ${N} as an alternative syntax for $N

(yas-define-snippets): Warn about identity conflicts.
(yas--one-simple-fom): New fun, extracted from `yas--simple-fom-create`.
(yas--simple-fom-create): Use it.
(yas--field-parse-create): Use it for ${N}.
This commit is contained in:
Stefan Monnier 2024-02-12 11:45:51 -05:00
parent 297546f085
commit 8e9ce76f7a

View File

@ -1833,10 +1833,17 @@ the current buffers contents."
(insert "\n\n")) (insert "\n\n"))
;; Normal case. ;; Normal case.
(let ((snippet-table (yas--table-get-create mode)) (let ((snippet-table (yas--table-get-create mode))
(uuids nil)
(template nil)) (template nil))
(dolist (snippet snippets) (dolist (snippet snippets)
(setq template (yas--define-snippets-1 snippet (setq template (yas--define-snippets-1 snippet
snippet-table))) snippet-table))
(let ((uuid (yas--template-uuid template)))
(if (member uuid uuids)
;; It's normal for a snippet to override another one
;; in `snippet-table`, but not one in `snippets`.
(message "Multiple snippets with same identity: %S" uuid)
(push uuid uuids))))
template))) template)))
@ -3994,7 +4001,7 @@ SNIPPET may be a snippet structure (e.g., as returned by
`yas-lookup-snippet'), or just a snippet body (which is a string `yas-lookup-snippet'), or just a snippet body (which is a string
for normal snippets, and a list for command snippets)." for normal snippets, and a list for command snippets)."
(cl-assert (and yas-minor-mode (cl-assert (and yas-minor-mode
(memq 'yas--post-command-handler post-command-hook)) (memq #'yas--post-command-handler post-command-hook))
nil nil
"[yas] `yas-expand-snippet' needs properly setup `yas-minor-mode'") "[yas] `yas-expand-snippet' needs properly setup `yas-minor-mode'")
(run-hooks 'yas-before-expand-snippet-hook) (run-hooks 'yas-before-expand-snippet-hook)
@ -4715,20 +4722,22 @@ When multiple expressions are found, only the last one counts."
(point))) (point)))
(number (and (match-string-no-properties 1) (number (and (match-string-no-properties 1)
(string-to-number (match-string-no-properties 1)))) (string-to-number (match-string-no-properties 1))))
(brand-new-field (and real-match-end-0 (field2 (match-string-no-properties 2))
;; break if on "$(" immediately (simple-fom (string-match-p "\\`[0-9]+\\'" field2))
;; after the ":", this will be (brand-new-field
;; caught as a mirror with (and ;; break if on "$(" immediately after the ":", this
;; transform later. ;; will be caught as a mirror with transform later.
(not (string-match-p "\\`\\$[ \t\n]*(" (not (string-match-p "\\`\\$[ \t\n]*(" field2))
(match-string-no-properties 2))) ;; allow ${0: some exit text}
;; allow ${0: some exit text} ;; (not (and number (zerop number)))
;; (not (and number (zerop number))) (yas--make-field number
(yas--make-field number (yas--make-marker (match-beginning 2))
(yas--make-marker (match-beginning 2)) (yas--make-marker (1- real-match-end-0))
(yas--make-marker (1- real-match-end-0)) parent-field))))
parent-field)))) (cond
(when brand-new-field ((and (not number) simple-fom)
(yas--one-simple-fom snippet field2))
(brand-new-field
(goto-char real-match-end-0) (goto-char real-match-end-0)
(push (cons (1- real-match-end-0) real-match-end-0) (push (cons (1- real-match-end-0) real-match-end-0)
yas--dollar-regions) yas--dollar-regions)
@ -4737,9 +4746,11 @@ When multiple expressions are found, only the last one counts."
(push brand-new-field (yas--snippet-fields snippet)) (push brand-new-field (yas--snippet-fields snippet))
(save-excursion (save-excursion
(save-restriction (save-restriction
(narrow-to-region (yas--field-start brand-new-field) (yas--field-end brand-new-field)) (narrow-to-region (yas--field-start brand-new-field)
(yas--field-end brand-new-field))
(goto-char (point-min)) (goto-char (point-min))
(yas--field-parse-create snippet brand-new-field))))))) (yas--field-parse-create snippet brand-new-field))))))))
;; if we entered from a parent field, now search for the ;; if we entered from a parent field, now search for the
;; `yas--multi-dollar-lisp-expression-regexp'. This is used for ;; `yas--multi-dollar-lisp-expression-regexp'. This is used for
;; primary field transformations ;; primary field transformations
@ -4796,31 +4807,35 @@ When multiple expressions are found, only the last one counts."
(defun yas--simple-fom-create (snippet) (defun yas--simple-fom-create (snippet)
"Parse the simple \"$n\" fields/mirrors/exitmarkers in SNIPPET." "Parse the simple \"$n\" fields/mirrors/exitmarkers in SNIPPET."
(while (re-search-forward yas--simple-mirror-regexp nil t) (while (re-search-forward yas--simple-mirror-regexp nil t)
(let ((number (string-to-number (match-string-no-properties 1)))) (yas--one-simple-fom snippet (match-string-no-properties 1))))
(cond ((zerop number)
(setf (yas--snippet-exit snippet) (defun yas--one-simple-fom (snippet numstring)
(yas--make-exit (yas--make-marker (match-end 0)))) (let ((number (string-to-number numstring)))
(push (cons (match-beginning 0) (yas--exit-marker (yas--snippet-exit snippet))) (cond ((zerop number)
yas--dollar-regions)) (setf (yas--snippet-exit snippet)
(t (yas--make-exit (yas--make-marker (match-end 0))))
(let ((field (yas--snippet-find-field snippet number)) (push (cons (match-beginning 0)
(fom)) (yas--exit-marker (yas--snippet-exit snippet)))
(if field yas--dollar-regions))
(push (t
(setq fom (yas--make-mirror (let ((field (yas--snippet-find-field snippet number))
(yas--make-marker (match-beginning 0)) (fom))
(yas--make-marker (match-beginning 0)) (if field
nil))
(yas--field-mirrors field))
(push (push
(setq fom (yas--make-field number (setq fom (yas--make-mirror
(yas--make-marker (match-beginning 0)) (yas--make-marker (match-beginning 0))
(yas--make-marker (match-beginning 0)) (yas--make-marker (match-beginning 0))
nil)) nil))
(yas--snippet-fields snippet))) (yas--field-mirrors field))
(yas--calculate-simple-fom-parentage snippet fom)) (push
(push (cons (match-beginning 0) (match-end 0)) (setq fom (yas--make-field number
yas--dollar-regions)))))) (yas--make-marker (match-beginning 0))
(yas--make-marker (match-beginning 0))
nil))
(yas--snippet-fields snippet)))
(yas--calculate-simple-fom-parentage snippet fom))
(push (cons (match-beginning 0) (match-end 0))
yas--dollar-regions)))))
(defun yas--delete-regions (regions) (defun yas--delete-regions (regions)
"Sort disjuct REGIONS by start point, then delete from the back." "Sort disjuct REGIONS by start point, then delete from the back."