From 7a6bb0f05e349068b0a89514f1da33d6d7de30a9 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Tue, 24 Apr 2012 23:29:38 +0200 Subject: emacs.d/lisp/yasnippet: added yasnippet --- .../lisp/yasnippet/doc/snippet-development.html | 623 +++++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 emacs.d/lisp/yasnippet/doc/snippet-development.html (limited to 'emacs.d/lisp/yasnippet/doc/snippet-development.html') diff --git a/emacs.d/lisp/yasnippet/doc/snippet-development.html b/emacs.d/lisp/yasnippet/doc/snippet-development.html new file mode 100644 index 0000000..6b55b4c --- /dev/null +++ b/emacs.d/lisp/yasnippet/doc/snippet-development.html @@ -0,0 +1,623 @@ + + + + + + +Writing snippets + + + +
+
+
+
+ +
+
+
+
+

+ Important: This documentation applies to + the SVN trunk of YASnippet, which you + get here. Documentation + for other versions can be found here. +

+ +
+

Snippet development

+
+

Quickly finding snippets

+

There are some ways you can quickly find a snippet file:

+
    +
  • M-x yas/new-snippet

    +

    Prompts you for a snippet name, then tries to guess a suitable +directory to store it, prompting you for creation if it does not +exist. Finally, places you in a new buffer set to snippet-mode +so you can write your snippet.

    +
  • +
  • M-x yas/find-snippets

    +

    Lets you find the snippet file in the directory the snippet was +loaded from (if it exists) like find-file-other-window. The +directory searching logic is similar to M-x yas/new-snippet.

    +
  • +
  • M-x yas/visit-snippet-file

    +

    Prompts you for possible snippet expansions like +yas/insert-snippet, but instead of expanding it, takes you +directly to the snippet definition's file, if it exists.

    +
  • +
+

Once you find this file it will be set to snippet-mode (see ahead) +and you can start editing your snippet.

+
+
+

Using the snippet-mode major mode

+

There is a major mode snippet-mode to edit snippets. You can set +the buffer to this mode with M-x snippet-mode. It provides +reasonably useful syntax highlighting.

+

Two commands are defined in this mode:

+
    +
  • M-x yas/load-snippet-buffer

    +
    +

    When editing a snippet, this loads the snippet into the correct +mode and menu. Bound to C-c C-c by default while in +snippet-mode.

    +
    +
  • +
  • M-x yas/tryout-snippet

    +
    +

    When editing a snippet, this opens a new empty buffer, sets it to +the appropriate major mode and inserts the snippet there, so you +can see what it looks like. This is bound to C-c C-t while in +snippet-mode.

    +
    +
  • +
+

There are also snippets for writing snippets: vars, $f and +$m :-).

+
+
+
+

File content

+

A file defining a snippet generally contains the template to be +expanded.

+

Optionally, if the file contains a line of # --, the lines above +it count as comments, some of which can be directives (or meta +data). Snippet directives look like # property: value and tweak +certain snippets properties described below. If no # -- is found, +the whole file is considered the snippet template.

+

Here's a typical example:

+
#contributor : pluskid <pluskid@gmail.com>
+#name : __...__
+# --
+__${init}__
+
+

Here's a list of currently supported directives:

+
+

# key: snippet abbrev

+

This is the probably the most important directive, it's the +abbreviation you type to expand a snippet just before hitting +yas/trigger-key.

+

If you don't specify this it will default to the name of the file the +snippet is being loaded from, unless YASnippet is ignoring file names +as triggers (see yas/ignore-filenames-as-triggers in Organizing +snippets), in which case this snippet +will not be expandable through the key mechanism.

+

Sometimes the key of a snippet is non-ASCII or not valid filename +(e.g. contains /). One can then define the key property which +will overwrite the filename as the key to expand the snippet.

+
+
+

# name: snippet name

+

This is a one-line description of the snippet. It will be displayed in +the menu. It's a good idea to select a descriptive name for a +snippet -- especially distinguishable among similar snippets.

+

If you omit this name it will default to the file name the snippet was +loaded from.

+
+
+

# condition: snippet condition

+

This is a piece of Emacs-lisp code. If a snippet has a condition, then it +will only be expanded when the condition code evaluate to some non-nil +value.

+

See also yas/buffer-local-condition in Expanding snippets

+
+
+

# group: snippet menu grouping

+

When expanding/visiting snippets from the menu-bar menu, snippets for a +given mode can be grouped into sub-menus . This is useful if one has +too many snippets for a mode which will make the menu too +long.

+

The # group: property only affect menu construction (See the +YASnippet menu) and the same effect can be achieved by grouping +snippets into sub-directories and using the .yas-make-groups +special file (for this see Organizing Snippets

+

Refer to the bundled snippets for ruby-mode for examples on the +# group: directive. Group can also be nested, e.g. control +structure.loops tells that the snippet is under the loops group +which is under the control structure group.

+
+
+

# expand-env: expand environment

+

This is another piece of Emacs-lisp code in the form of a let +varlist form, i.e. a list of lists assigning values to variables. It +can be used to override variable values while the snippet is being +expanded.

+

Interesting variables to override are yas/wrap-around-region and +yas/indent-line (see Expanding Snippets).

+

As an example, you might normally have yas/indent-line set to +'auto and yas/wrap-around-region set to t, but for this +particularly brilliant piece of ASCII art these values would mess up +your hard work. You can then use:

+
# name : ASCII home
+# expand-env: ((yas/indent-line 'fixed) (yas/wrap-around-region 'nil))
+# --
+                welcome to my
+            X      humble
+           / \      home,
+          /   \      $0
+         /     \
+        /-------\
+        |       |
+        |  +-+  |
+        |  | |  |
+        +--+-+--+
+
+
+
+

# binding: direct keybinding

+

You can use this directive to expand a snippet directly from a normal +Emacs keybinding. The keybinding will be registered in the Emacs +keymap named after the major mode the snippet is active +for.

+

Additionally a variable yas/prefix is set to to the prefix +argument you normally use for a command. This allows for small +variations on the same snippet, for example in this "html-mode" +snippet.

+
#name : <p>...</p>
+#binding: "C-c C-c C-m"
+# --
+<p>`(when yas/prefix "\n")`$0`(when yas/prefix "\n")`</p>
+
+

This binding will be recorded in the keymap html-mode-map. To +expand a paragraph tag newlines, just press "C-u C-c C-c +C-m". Omitting the "C-u" will expand the paragraph tag without +newlines.

+

To override the keymap choice based on the major mode name. Use a cons +cell where the first element specifies the name of the keymap where +you want to record the keybinding.

+
#name : <p>...</p>
+#binding: (rinari-minor-mode-map . "C-c C-c C-m")
+# --
+<p>`(when yas/prefix "\n")`$0`(when yas/prefix "\n")`</p>
+
+

Note: this feature is still experimental, it might go away, be +changed in future release, and should be used with caution: It is easy +to override important keybindings for many basic modes and it is hard +to undefine them. For the moment, the variable +yas/active-keybindings can tell you what snippet keybindings are +active and the function yas/kill-snippet-keybindings will attempt +to undefine all the keybindings.

+
+
+

# contributor: snippet author

+

This is optional and has no effect whatsoever on snippet +functionality, but it looks nice.

+
+
+
+

Template syntax

+

The syntax of the snippet template is simple but powerful, very +similar to TextMate's.

+
+

Plain Text

+

Arbitrary text can be included as the content of a template. They are +usually interpreted as plain text, except $ and `. You need to +use \ to escape them: \$ and \`. The \ itself may also +needed to be escaped as \\ sometimes.

+
+
+

Embedded Emacs-lisp code

+

Emacs-Lisp code can be embedded inside the template, written inside +back-quotes (`). The lisp forms are evaluated when the snippet is +being expanded. The evaluation is done in the same buffer as the +snippet being expanded.

+

Here's an example for c-mode to calculate the header file guard +dynamically:

+
#ifndef ${1:_`(upcase (file-name-nondirectory (file-name-sans-extension (buffer-file-name))))`_H_}
+#define $1
+
+$0
+
+#endif /* $1 */
+
+

From version 0.6, snippets expansions are run with some special +Emacs-lisp variables bound. One of this is yas/selected-text. You +can therefore define a snippet like:

+
for ($1;$2;$3) {
+  `yas/selected-text`$0
+}
+
+

to "wrap" the selected region inside your recently inserted +snippet. Alternatively, you can also customize the variable +yas/wrap-around-region to t which will do this automatically.

+
+
+

Tab stop fields

+

Tab stops are fields that you can navigate back and forth by TAB +and S-TAB. They are written by $ followed with a +number. $0 has the special meaning of the exit point of a +snippet. That is the last place to go when you've traveled all the +fields. Here's a typical example:

+
<div$1>
+    $0
+</div>
+
+
+
+

Placeholder fields

+

Tab stops can have default values -- a.k.a placeholders. The syntax is +like this:

+
${N:default value}
+
+

They acts as the default value for a tab stop. But when you firstly +type at a tab stop, the default value will be replaced by your +typing. The number can be omitted if you don't want to create +mirrors or transformations for this field.

+
+
+

Mirrors

+

We refer the tab stops with placeholders as a field. A field can have +mirrors. Its mirrors will get updated when you change the text of a +field. Here's an example:

+
\begin{${1:enumerate}}
+    $0
+\end{$1}
+
+

When you type "document" at ${1:enumerate}, the word +"document" will also be inserted at \end{$1}. The best +explanation is to see the screencast(YouTube or avi video).

+

The tab stops with the same number to the field act as its mirrors. If +none of the tab stops has an initial value, the first one is selected +as the field and others mirrors.

+
+
+

Mirrors with transformations

+

If the value of an ${n:-construct starts with and contains $(, +then it is interpreted as a mirror for field n with a +transformation. The mirror's text content is calculated according to +this transformation, which is Emacs-lisp code that gets evaluated in +an environment where the variable text (or yas/text) is bound +to the text content (string) contained in the field n.Here's an +example for Objective-C:

+
- (${1:id})${2:foo}
+{
+    return $2;
+}
+
+- (void)set${2:$(capitalize text)}:($1)aValue
+{
+    [$2 autorelease];
+    $2 = [aValue retain];
+}
+$0
+
+

Look at ${2:$(capitalize text)}, it is a mirror with +transformation instead of a field. The actual field is at the first +line: ${2:foo}. When you type text in ${2:foo}, the +transformation will be evaluated and the result will be placed there +as the transformed text. So in this example, if you type "baz" in the +field, the transformed text will be "Baz". This example is also +available in the screencast.

+

Another example is for rst-mode. In reStructuredText, the document +title can be some text surrounded by "===" below and above. The "===" +should be at least as long as the text. So

+
=====
+Title
+=====
+
+

is a valid title but

+
===
+Title
+===
+
+

is not. Here's an snippet for rst title:

+
${1:$(make-string (string-width text) ?\=)}
+${1:Title}
+${1:$(make-string (string-width text) ?\=)}
+
+$0
+
+
+
+

Fields with transformations

+

From version 0.6 on, you can also have lisp transformation inside +fields. These work mostly mirror transformations but are evaluated +when you first enter the field, after each change you make to the +field and also just before you exit the field.

+

The syntax is also a tiny bit different, so that the parser can +distinguish between fields and mirrors. In the following example

+
#define "${1:mydefine$(upcase yas/text)}"
+
+

mydefine gets automatically upcased to MYDEFINE once you enter +the field. As you type text, it gets filtered through the +transformation every time.

+

Note that to tell this kind of expression from a mirror with a +transformation, YASnippet needs extra text between the : and the +transformation's $. If you don't want this extra-text, you can use +two $'s instead.

+
#define "${1:$$(upcase yas/text)}"
+
+

Please note that as soon as a transformation takes place, it changes +the value of the field and sets it its internal modification state to +true. As a consequence, the auto-deletion behaviour of normal +fields does not take place. This is by design.

+
+
+

Choosing fields value from a list and other tricks

+

As mentioned, the field transformation is invoked just after you enter +the field, and with some useful variables bound, notably +yas/field-modified-p and yas/moving-away-p. Because of this +feature you can place a transformation in the primary field that lets +you select default values for it.

+

The yas/choose-value does this work for you. For example:

+
<div align="${2:$$(yas/choose-value '("right" "center" "left"))}">
+  $0
+</div>
+
+

See the definition of yas/choose-value to see how it was written +using the two variables.

+

Here's another use, for LaTeX-mode, which calls reftex-label just as +you enter snippet field 2. This one makes use of yas/modified-p +directly.

+
\section{${1:"Titel der Tour"}}%
+\index{$1}%
+\label{{2:"waiting for reftex-label call..."$(unless yas/modified-p (reftex-label nil 'dont-
+insert))}}%
+
+

The function yas/verify-value has another neat trick, and makes +use of yas/moving-away-p. Try it and see! Also, check out this +thread

+
+
+

Nested placeholder fields

+

From version 0.6 on, you can also have nested placeholders of the type:

+
<div${1: id="${2:some_id}"}>$0</div>
+
+

This allows you to choose if you want to give this div an id +attribute. If you tab forward after expanding it will let you change +"some_id" to whatever you like. Alternatively, you can just press +C-d (which executes yas/skip-and-clear-or-delete-char) and go +straight to the exit marker.

+

By the way, C-d will only clear the field if you cursor is at the +beginning of the field and it hasn't been changed yet. Otherwise, it +performs the normal Emacs delete-char command.

+
+
+
+

Customizable variables

+
+

yas/trigger-key

+

The key bound to yas/expand when function yas/minor-mode is +active.

+

Value is a string that is converted to the internal Emacs key +representation using read-kbd-macro.

+

Default value is "TAB".

+
+
+

yas/next-field-key

+

The key to navigate to next field when a snippet is active.

+

Value is a string that is converted to the internal Emacs key +representation using read-kbd-macro.

+

Can also be a list of keys.

+

Default value is "TAB".

+
+
+

yas/prev-field-key

+

The key to navigate to previous field when a snippet is active.

+

Value is a string that is converted to the internal Emacs key +representation using read-kbd-macro.

+

Can also be a list of keys.

+

Default value is ("<backtab>" "<S-tab>)".

+
+
+

yas/skip-and-clear-key

+

The key to clear the currently active field.

+

Value is a string that is converted to the internal Emacs key +representation using read-kbd-macro.

+

Can also be a list of keys.

+

Default value is "C-d".

+
+
+

yas/good-grace

+

If non-nil, don't raise errors in inline Emacs-lisp evaluation inside +snippet definitions. An error string "[yas] error" is returned instead.

+
+
+

yas/indent-line

+

The variable yas/indent-line controls the indenting. It is bound +to 'auto by default, which causes your snippet to be indented +according to the mode of the buffer it was inserted in.

+

Another variable yas/also-auto-indent-first-line, when non-nil +does exactly that :-).

+

To use the hard-coded indentation in your snippet template, set this +variable to fixed.

+

To control indentation on a per-snippet basis, see also the directive +# expand-env: in Writing Snippets.

+

For backward compatibility with earlier versions of YASnippet, you can +also place a $> in your snippet, an (indent-according-to-mode) +will be executed there to indent the line. This only takes effect when +yas/indent-line is set to something other than 'auto.

+
for (${int i = 0}; ${i < 10}; ${++i})
+{$>
+$0$>
+}$>
+
+
+
+

yas/wrap-around-region

+

If non-nil, YASnippet will try to expand the snippet's exit marker +around the currently selected region. When this variable is set to t, +this has the same effect has using the `yas/selected-text` inline +evaluation.

+

Because on most systems starting to type deletes the currently region, +this works mostly with the yas/insert-snippet command.

+

However, when the value is of this variable is cua YASnippet will +additionally look-up any recently selected that you deleted by starting +typing. This allows you select a region, type a snippet key (deleting +the region), then press yas/trigger-key to see the deleted region +spring back to life inside your new snippet.

+
+
+

yas/triggers-in-field

+

If non-nil, yas/next-field-key can trigger stacked expansions, +that is a snippet expansion inside another snippet +expansion. Otherwise, yas/next-field-key just tries to move on to +the next field.

+
+
+

yas/snippet-revival

+

Non-nil means re-activate snippet fields after undo/redo.

+
+
+

yas/after-exit-snippet-hook and yas/before-expand-snippet-hook

+

These hooks are called, respectively, before the insertion of a +snippet and after exiting the snippet. If you find any strange but +functional use for them, that's probably a design flaw in YASnippet, +so let us know.

+
+
+
+

Importing TextMate snippets

+

There are a couple of tools that take TextMate's ".tmSnippet" xml +files and create YASnippet definitions:

+
+ +
+

In this section, i'll shortly cover the second option.

+

Download the textmate_import.rb tool and the TextMate +bundle you're interested in.

+
$ curl -O http://yasnippet.googlecode.com/svn/trunk/extras/textmate_import.rb
+$ svn export http://svn.textmate.org/trunk/Bundles/HTML.tmbundle/
+
+

Then invoke textmate_import.rb like this:

+
$ ./textmate_import.rb -d HTML.tmbundle/Snippets/ -o html-mode -g HTML.tmbundle/info.plist
+
+

You should end up with a html-mode subdir containing snippets +exported from textmate.

+
$ tree html-mode # to view dir contents, if you have 'tree' installed
+
+

The -g is optional but helps the tool figure out the grouping. +According to Organizing Snippets, don't forget to touch +.yas-make-groups and .yas-ignore-filename-triggers inside the +html-mode dir.

+

Also try textmate_import.rb --help for a list of options.

+

Please note that snippet importation is not yet perfect. You'll +probably have some adjustments to some/many snippets. Please +contribute these adjustments to the google group or, better yet, patch +the textmate_import.rb to automatically perform them and submit +that.

+ + + +
+
+
+
+
+
+
+ + +
+ + -- cgit v1.2.3