mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 13:13:03 +00:00
doc: add commentary section, ran checkdoc
This commit is contained in:
parent
ef1747d947
commit
4732c6993b
91
snippet.el
91
snippet.el
@ -19,6 +19,66 @@
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;;; Commentary:
|
||||
|
||||
;; The yasnippet snippet insertion and navigation engine, though very powerful,
|
||||
;; is bloated and its implementation much contrived.
|
||||
;;
|
||||
;; snippet.el's main goal is to provide yasnippet and other snippet-managing
|
||||
;; frontends with the bare minimum funcionality to define, insert, navigate and
|
||||
;; undo snippets.
|
||||
;;
|
||||
;; Snippets are defined via the `define-snippet' and `make-snippet'
|
||||
;; entrypoints.The snippet definition syntax is as powerful as yasnippet's
|
||||
;; (inspired by textmate's). Since the syntax is now sexp-based, snippets
|
||||
;; definitions are easily manipulated and generated by macros.
|
||||
;;
|
||||
;; Another improvement is that `define-snippet' calls can be now be `edebug'ed
|
||||
;; and stepped through on snippet insertion and navigation.
|
||||
;;
|
||||
;; Once inserted into a buffer, snippets are navigated using
|
||||
;; `snippet-next-field' and `snippet-prev-field', bound to TAB and S-TAB by
|
||||
;; default.
|
||||
;;
|
||||
;; There is a PROPERTIES argument, unimplemented at time of writing, in the
|
||||
;; `define-snippet' macro which will *probably* understand a set of properties
|
||||
;; controlling snippet's indentation, custom keymapping and other per-snippet
|
||||
;; characteristics affecting snippet.el's core functionality.
|
||||
;;
|
||||
;; Funcionality such as snippet management, mode management, tab-trigerring or
|
||||
;; any other fanciness are *not* offered. `define-snippet's PROPERTIES
|
||||
;; mechanism *might* become extensible to provide frontends such as yasnippet
|
||||
;; the capability to conveniently implement said fanciness.
|
||||
;;
|
||||
;; TODO: indentation
|
||||
;;
|
||||
;; TODO: undo, specifically snippet revival
|
||||
;;
|
||||
;; TODO: more documentation
|
||||
;;
|
||||
;; TODO: "protection overlays" or some robust mechanism preventing the use from
|
||||
;; inadvertenly destroying the snippet's structure and leaving its
|
||||
;; incoherent carcass behind. Alternatively, detect this and exit the
|
||||
;; snippet beforehand.
|
||||
;;
|
||||
;; TODO: primary field transformations: the (&transform ...) option to &field
|
||||
;; constructs.
|
||||
;;
|
||||
;; TODO: (&exit ...) constructs with a default string should leave it marked and
|
||||
;; highlighted in the buffer on snippet-exit. Yasnippet tried, but does
|
||||
;; not support this correctly.
|
||||
;;
|
||||
;; TODO: stacked insertion, aka snippet-in-snippet: the ability to expand a
|
||||
;; second snippet while navigating a snippet's field, and returning to the
|
||||
;; original field after exiting the second snippet.
|
||||
;;
|
||||
;; TODO: sub-snippets: the ability to insert navigable sub-snippets into a
|
||||
;; snippet definition by chaining them to the adjoining objects. Yasnippet
|
||||
;; does not provide this. Might become a (&snippet ...) construct to
|
||||
;; `define-snippet'.
|
||||
;;
|
||||
;; TODO: dynamic fields: the ability dinamically add snippet fields and mirrors
|
||||
;; to the snippet currently being navigated. Yasnippet does not provide
|
||||
;; this and seems hard to do. Might become obsolete if stacked insertion
|
||||
;; and primary field transformations are implemented nicely.
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
@ -58,7 +118,7 @@
|
||||
(`(&eval ,_)
|
||||
form)
|
||||
(`(&eval . ,_)
|
||||
(error "provide only one form after &eval in %S" form))
|
||||
(error "Provide only one form after &eval in %S" form))
|
||||
(`(&mirror ,name)
|
||||
`(&mirror ,name (&transform field-string)))
|
||||
(`(&mirror ,_ (&transform ,_))
|
||||
@ -66,10 +126,10 @@
|
||||
(`(&field ,_ (,(or `&transform `&eval) ,_))
|
||||
form)
|
||||
(`(,(or `&mirror `&field) ,_ (,(or `&transform `&eval) ,_ . (,extra)))
|
||||
(error "expected one form after &eval or &transform in %S, you have %d"
|
||||
(error "Expected one form after &eval or &transform in %S, you have %d"
|
||||
form (1+ (length extra))))
|
||||
(`(,(or `&mirror `&field) ,name ,_ . (,extra))
|
||||
(error "expected one form after '%S' in %S, you have %d"
|
||||
(error "Expected one form after '%S' in %S, you have %d"
|
||||
name
|
||||
form (1+ (length extra))))
|
||||
(`(&field ,name (&nested . ,more-forms))
|
||||
@ -90,7 +150,7 @@
|
||||
((pred consp)
|
||||
`(&eval ,form))
|
||||
(t
|
||||
(error "invalid snippet form %s" form))))
|
||||
(error "Invalid snippet form %s" form))))
|
||||
|
||||
(defun snippet--unfold-forms (forms &optional parent-sym)
|
||||
(cl-loop for form in forms
|
||||
@ -102,7 +162,8 @@
|
||||
(snippet--make-field-sym name))))))
|
||||
|
||||
(defun snippet--define-body (body)
|
||||
"Does the actual work for `define-snippet'"
|
||||
"Does the actual work for `define-snippet'.
|
||||
Argument BODY is a list of forms as described in `define-snippet'."
|
||||
(let ((unfolded (snippet--unfold-forms
|
||||
(mapcar #'snippet--canonicalize-form body)))
|
||||
all-objects exit-object)
|
||||
@ -142,7 +203,7 @@
|
||||
',transform))))
|
||||
(`(&exit (&eval ,form) (&parent ,parent))
|
||||
(when exit-object
|
||||
(error "too many &exit forms given"))
|
||||
(error "Too many &exit forms given"))
|
||||
(setq sym (snippet--make-exit-sym)
|
||||
exit-object sym)
|
||||
`((,sym (snippet--make-and-insert-exit
|
||||
@ -164,7 +225,7 @@
|
||||
(snippet--activate-snippet (list ,@all-objects))))))
|
||||
|
||||
|
||||
(cl-defmacro define-snippet (name () &rest snippet-forms)
|
||||
(cl-defmacro define-snippet (name (&rest properties) &rest snippet-forms)
|
||||
"Define NAME as a snippet-inserting function.
|
||||
|
||||
NAME's function definition is set to a function with no arguments
|
||||
@ -223,8 +284,8 @@ empty string.
|
||||
If the form CONSTANT returns nil or the empty string, it is
|
||||
considered to have returned a single whitespace.
|
||||
|
||||
ARGS is an even-numbered property list of (KEY VAL) pairs. Its
|
||||
meaning is not decided yet"
|
||||
PROPERTIES is an even-numbered property list of (KEY VAL)
|
||||
pairs. Its meaning is not decided yet"
|
||||
(declare (debug (&define name sexp &rest snippet-form)))
|
||||
`(defun ,name ()
|
||||
,(snippet--define-body snippet-forms)))
|
||||
@ -236,7 +297,8 @@ meaning is not decided yet"
|
||||
def-form))
|
||||
|
||||
(defun make-snippet (forms)
|
||||
"Same as `define-snippet', but return an anonymous function."
|
||||
"Same as `define-snippet', but return an anonymous function.
|
||||
Argument FORMS is a list of forms as described in `define-snippet'."
|
||||
`(lambda () ,(snippet--define-body forms)))
|
||||
|
||||
|
||||
@ -456,6 +518,11 @@ meaning is not decided yet"
|
||||
(snippet--field-modified-p parent))))
|
||||
|
||||
(defun snippet-next-field (&optional prev)
|
||||
"Move to the start of next field in the current snippet.
|
||||
|
||||
Skips over nested fields if their parent has been modified.
|
||||
|
||||
PREV means move to the previous field."
|
||||
(interactive)
|
||||
(let* ((field (overlay-get snippet--field-overlay 'snippet--field))
|
||||
(sorted (overlay-get snippet--field-overlay 'snippet--fields))
|
||||
@ -474,6 +541,9 @@ meaning is not decided yet"
|
||||
(snippet-exit-snippet))))
|
||||
|
||||
(defun snippet-prev-field ()
|
||||
"Move the the start of the previous field in the current snippet.
|
||||
|
||||
Skips over nested fields if their parent has been modified."
|
||||
(interactive)
|
||||
(snippet-next-field t))
|
||||
|
||||
@ -604,4 +674,5 @@ meaning is not decided yet"
|
||||
;; whitespace-line-column: 80
|
||||
;; fill-column: 80
|
||||
;; End:
|
||||
|
||||
;; snippet.el ends here
|
||||
|
Loading…
x
Reference in New Issue
Block a user