mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 13:13:03 +00:00
Internal documentation overhaul. Still unfinished.
This commit is contained in:
parent
ad2bb8bed1
commit
73f208d6d5
175
snippet.el
175
snippet.el
@ -48,8 +48,13 @@
|
|||||||
;; mechanism *might* become extensible to provide frontends such as yasnippet
|
;; mechanism *might* become extensible to provide frontends such as yasnippet
|
||||||
;; the capability to conveniently implement said fanciness.
|
;; the capability to conveniently implement said fanciness.
|
||||||
;;
|
;;
|
||||||
|
;; TODO: primary field transformations: the (&transform ...) option to &field
|
||||||
|
;; constructs. In `define-dynamic-snippet', mirror forms should only be
|
||||||
|
;; evaluated for value. &exit should be generalized to also allow nested
|
||||||
|
;; fields.
|
||||||
|
;;
|
||||||
;; TODO: auto-indentation of the inserted snippet
|
;; TODO: auto-indentation of the inserted snippet
|
||||||
;;
|
;;
|
||||||
;; TODO: there should be somewhere a PROPERTIES argument, unimplemented at time
|
;; TODO: there should be somewhere a PROPERTIES argument, unimplemented at time
|
||||||
;; of writing, in the `define-snippet' macro which should probably understand a
|
;; of writing, in the `define-snippet' macro which should probably understand a
|
||||||
;; set of properties controlling snippet's indentation, custom keymapping and
|
;; set of properties controlling snippet's indentation, custom keymapping and
|
||||||
@ -59,9 +64,6 @@
|
|||||||
;;
|
;;
|
||||||
;; TODO: more documentation
|
;; TODO: more documentation
|
||||||
;;
|
;;
|
||||||
;; TODO: primary field transformations: the (&transform ...) option to &field
|
|
||||||
;; constructs.
|
|
||||||
;;
|
|
||||||
;; TODO: (&exit ...) constructs with a default string should leave it marked and
|
;; TODO: (&exit ...) constructs with a default string should leave it marked and
|
||||||
;; highlighted in the buffer on snippet-exit. Yasnippet tried, but does
|
;; highlighted in the buffer on snippet-exit. Yasnippet tried, but does
|
||||||
;; not support this correctly.
|
;; not support this correctly.
|
||||||
@ -240,60 +242,71 @@ As `define-static-snippet' but doesn't define a function."
|
|||||||
|
|
||||||
(defmacro define-static-snippet (name _properties &optional docstring
|
(defmacro define-static-snippet (name _properties &optional docstring
|
||||||
&rest snippet-forms)
|
&rest snippet-forms)
|
||||||
"Define NAME as a snippet-inserting function.
|
"Define NAME as an interactive snippet-inserting function.
|
||||||
|
|
||||||
Each form in SNIPPET-FORMS, inserted at point in order, can be:
|
Each form in SNIPPET-FORMS, inserted at point in order, can be:
|
||||||
|
|
||||||
* A cons (&field FIELD-NAME FIELD-DEFAULT) definining a snippet
|
* A cons (&field [FIELD-NAME [FIELD-DEFAULT]]) definining a snippet
|
||||||
field. A snippet field can be navigated to using
|
field. Snippet fields can be edited and be navigated to using
|
||||||
`snippet-next-field' and `snippet-prev-field'. FIELD-NAME is
|
`snippet-next-field' and `snippet-prev-field'. FIELD-NAME is
|
||||||
optional and used for referring to the field in mirror
|
optional and used for referring to the field in mirror
|
||||||
transforms. FIELD-DEFAULT is also optional and used for
|
transforms.
|
||||||
producing a string that populates the field's default value at
|
|
||||||
snippet-insertion time.
|
|
||||||
|
|
||||||
FIELD-DEFAULT can thus be a string literal, a lisp form
|
FIELD-DEFAULT is optional and determines the field's starting
|
||||||
returning a string, or have the form (&nested SUB-FORM ...)
|
text. It can be any lisp form returning a string or have be a cons
|
||||||
where each SUB-FORM is evaluated recursively according to the
|
(&transform FIELD-TRANSFORM) where FIELD-TRANSFORM is again a
|
||||||
rules of SNIPPET-FORMS.
|
lisp form returning a string. Choosing between these varieties
|
||||||
|
defines when and how these forms are evaluated. See below for
|
||||||
|
details.
|
||||||
|
|
||||||
FIELD-DEFAULT can additionally also be (&transform
|
FIELD-DEFAULT can also be a cons (&nested SUB-FORMS) where each
|
||||||
FIELD-TRANSFORM) in which case the string value produced by
|
form in SUB-FORMS is evaluated recursively according to the
|
||||||
FIELD-TRANSFORM is used for populating not only the field's
|
rules of SNIPPET-FORMS, thus producing nested fields and
|
||||||
default value, but also the field's value after each command
|
mirrors.
|
||||||
while the snippet is alive.
|
|
||||||
|
|
||||||
* A cons (&mirror FIELD-NAME MIRROR-TRANSFORM) defining a mirror
|
* A cons (&mirror FIELD-NAME [MIRROR-TRANSFORM]) defining a mirror
|
||||||
of the field named FIELD-NAME. MIRROR-TRANSFORM is an optional
|
of the field named FIELD-NAME. MIRROR-TRANSFORM is an optional
|
||||||
form, called after each command while the snippet is alive to
|
form producing a string that becomes the mirror text. If it is
|
||||||
produce a string that becomes the mirror text.
|
not provided the mirror's text always matches FIELD-NAME's.
|
||||||
|
|
||||||
* A string literal or a lisp form, call it CONSTANT, evaluated at
|
* Any lisp form producing a string, call it CONSTANT, that is a
|
||||||
snippet-insertion time and producing a string that is a part of
|
part of the snippet but constant while the snippet is alive.
|
||||||
the snippet but constant while the snippet is alive.
|
|
||||||
|
|
||||||
* A form (&exit EXIT-DEFAULT), defining the point within the
|
* A cons (&exit [EXIT-DEFAULT]), defining a special field within
|
||||||
snippet where point should be placed when the snippet is
|
the snippet where point should be placed when the snippet is
|
||||||
exited. EXIT-DEFAULT is optional and is evaluated at
|
exited normally. EXIT-DEFAULT has the same semantics as
|
||||||
snippet-insertion time to produce a string that remains a
|
FIELD-DEFAULT.
|
||||||
constant part of the snippet while it is alive, but is
|
|
||||||
automatically selected when the snippet is exited.
|
|
||||||
|
|
||||||
The forms CONSTANT, FIELD-DEFAULT, MIRROR-TRANSFORM,
|
The forms CONSTANT, FIELD-DEFAULT, MIRROR-TRANSFORM,
|
||||||
FIELD-TRANSFORM and EXIT-DEFAULT are evaluated with the variable
|
FIELD-TRANSFORM and EXIT-DEFAULT are all evaluated at
|
||||||
`region-string' set to the text of the buffer selected at
|
snippet-insertion-time and with the variable `region-string' set
|
||||||
snippet-insertion time. If no region was selected the value of
|
to the text of the buffer selected at snippet-insertion time. If
|
||||||
this variable is the empty string.
|
no region was active the value of this variable is the empty
|
||||||
|
string.
|
||||||
|
|
||||||
The forms MIRROR-TRANSFORM and FIELD-TRANSFORM are evaluated with
|
The forms MIRROR-TRANSFORM and FIELD-TRANSFORM are additionally
|
||||||
the variable `field-string' set to the text contained in the
|
also evaluated each time the field is changed. Moreover,
|
||||||
corresponding field. If the field is empty, this variable is the
|
FIELD-TRANSFORM is also evaluated when the field is entered or
|
||||||
empty string and the additional variable `field-empty-p' is t.
|
left. These forms are evaluated with the following variables set:
|
||||||
|
|
||||||
|
* `field-string' is set to the text contained in the field;
|
||||||
|
* `field-left' is non-nil if the field is being left;
|
||||||
|
* `field-entered' is non-nil if the field is being entered;
|
||||||
|
* `field-modified-p' is non-nil if the field has ever been modified
|
||||||
|
since snippet creation
|
||||||
|
|
||||||
If the form CONSTANT returns nil or the empty string, it is
|
If the form CONSTANT returns nil or the empty string, it is
|
||||||
considered to have returned a single whitespace. If any other
|
considered to have returned a single whitespace.
|
||||||
form returns nil, it is considered to have returned the empty
|
|
||||||
string.
|
If FIELD-TRANSFORM returns a string, it replaces the fields text,
|
||||||
|
either at snippet-insertion-time or when the field is being
|
||||||
|
edited, entered or left. If FIELD-TRANSFORM returns nil at
|
||||||
|
snippet-insertion-time, it is considered to have returned the
|
||||||
|
empty string. If it returns nil on any other occasion, the field
|
||||||
|
is left unchanged.
|
||||||
|
|
||||||
|
If any other form returns nil, it is considered to have returned
|
||||||
|
the empty string.
|
||||||
|
|
||||||
PROPERTIES is an even-numbered property list of (KEY VAL)
|
PROPERTIES is an even-numbered property list of (KEY VAL)
|
||||||
pairs. Its meaning is not decided yet"
|
pairs. Its meaning is not decided yet"
|
||||||
@ -303,6 +316,7 @@ pairs. Its meaning is not decided yet"
|
|||||||
(push docstring snippet-forms)
|
(push docstring snippet-forms)
|
||||||
(setq docstring nil))
|
(setq docstring nil))
|
||||||
`(defun ,name () ,docstring
|
`(defun ,name () ,docstring
|
||||||
|
(interactive)
|
||||||
(with-static-snippet ,@snippet-forms)))
|
(with-static-snippet ,@snippet-forms)))
|
||||||
|
|
||||||
|
|
||||||
@ -377,13 +391,80 @@ pairs. Its meaning is not decided yet"
|
|||||||
|
|
||||||
|
|
||||||
(defmacro define-dynamic-snippet (name args &optional docstring &rest body)
|
(defmacro define-dynamic-snippet (name args &optional docstring &rest body)
|
||||||
|
"Define NAME as a snippet-inserting function.
|
||||||
|
|
||||||
|
Inside BODY the following local macros are available to
|
||||||
|
create snippet fields and mirrors:
|
||||||
|
|
||||||
|
* (&field NAME [FIELD-BODY]) declares the start of a snippet
|
||||||
|
field at point. Snippet fields can be edited and be navigated
|
||||||
|
to using `snippet-next-field' and
|
||||||
|
`snippet-prev-field'. FIELD-BODY is a list of lisp forms which
|
||||||
|
are evaluted for both return value and side-effects: Any text
|
||||||
|
inserted becomes the field's starting text. If a string is
|
||||||
|
returned, it is also inserted at the end of the field. Since
|
||||||
|
FIELD-BODY is evaluated according to the rules of BODY, nested
|
||||||
|
mirrors and fields become possible. Alternatively, FIELD-BODY
|
||||||
|
can also be a single form, a cons (&transform
|
||||||
|
FIELD-TRANSFORM-ARGS FIELD-TRANSFORM). See below for details.
|
||||||
|
|
||||||
|
* (&mirror FIELD-NAME [MIRROR-TRANSFORM-ARGS MIRROR-TRANSFORM])
|
||||||
|
declares the start of a mirror at point. If
|
||||||
|
MIRROR-TRANSFORM-ARGS and MIRROR-TRANSFORM are ommited the
|
||||||
|
mirror's text always matches FIELD-NAME'S. If provided,
|
||||||
|
MIRROR-TRANSFORM-ARGS is a list of 0 to 4 symbols that are
|
||||||
|
automatically bound to values extracted from the snippet field
|
||||||
|
FIELD-NAME and that can be used by the single form
|
||||||
|
MIRROR-TRANSFORM to produce the mirror's text. The values
|
||||||
|
passed in are, in order:
|
||||||
|
|
||||||
|
* a string containing the field's text;
|
||||||
|
* a boolean indicating if the field has just been entered;
|
||||||
|
* a boolean indicating if the field has just been left;
|
||||||
|
* a boolean indicating if the field has ever been modified since
|
||||||
|
insertion
|
||||||
|
|
||||||
|
MIRROR-TRANSFORM can also refer to any lexically available
|
||||||
|
symbols established in by other forms in BODY.
|
||||||
|
|
||||||
|
* (&exit [EXIT-BODY]) declares a special field special within the
|
||||||
|
snippet where point should be placed when the snippet is exited
|
||||||
|
normally. EXIT-BODY has the same semantics as FIELD-BODY.
|
||||||
|
|
||||||
|
Except for these special cases, forms in BODY are evaluated
|
||||||
|
normally. If at least one snippet field was declared, a navigable
|
||||||
|
snippet is inserted at the end.
|
||||||
|
|
||||||
|
MIRROR-TRANSFORM is evaluated at snippet-insertion time and each
|
||||||
|
time the corresponding field changes to produce the mirror's
|
||||||
|
text. If it returns nil, it is considered to have returned the
|
||||||
|
empty string.
|
||||||
|
|
||||||
|
If FIELD-BODY has the form (&transform FIELD-TRANSFORM-ARGS
|
||||||
|
FIELD-TRANSFORM), FIELD-TRANSFORM is passed the same parameters
|
||||||
|
as MIRROR-TRANSFORM, except that at snippet-insertion time, the
|
||||||
|
value of the first parameter to FIELD-TRANSFORM-ARGS is nil. At
|
||||||
|
snippet-insertion time the field's starting text should be
|
||||||
|
produced. If it returns nil, it is considered to have returned
|
||||||
|
the empty string.
|
||||||
|
|
||||||
|
FIELD-TRANSFORM is also called every time the field is edited or
|
||||||
|
when it is entered or left. It may then return a string replacing
|
||||||
|
the field's text or return nil to leave it unchanged. If the
|
||||||
|
field is changed in this manner, any corresponding mirror's
|
||||||
|
MIRROR-TRANSFORMS are also evaluated at the time."
|
||||||
(declare (debug (&define name sexp def-body))
|
(declare (debug (&define name sexp def-body))
|
||||||
(indent defun))
|
(indent defun))
|
||||||
(unless (stringp docstring)
|
(let ((interactive nil))
|
||||||
(push docstring body)
|
(unless (stringp docstring)
|
||||||
(setq docstring nil))
|
(push docstring body)
|
||||||
`(defun ,name ,args ,docstring
|
(setq docstring nil))
|
||||||
(with-dynamic-snippet ,@body)))
|
(if (eq (car-safe (car body)) 'interactive)
|
||||||
|
(setq interactive (pop body)))
|
||||||
|
`(defun ,name ,args ,docstring
|
||||||
|
,@(when interactive
|
||||||
|
`(,interactive))
|
||||||
|
(with-dynamic-snippet ,@body))))
|
||||||
|
|
||||||
(def-edebug-spec &mirror (sexp &optional sexp &rest form))
|
(def-edebug-spec &mirror (sexp &optional sexp &rest form))
|
||||||
(def-edebug-spec &field (sexp &rest form))
|
(def-edebug-spec &field (sexp &rest form))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user