doc: add commentary section, ran checkdoc

This commit is contained in:
Joao Tavora 2013-11-07 09:11:41 +00:00
parent ef1747d947
commit 4732c6993b

View File

@ -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