summaryrefslogtreecommitdiffstats
path: root/emacs.d/lisp/yasnippet/doc/snippet-development.rst
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--emacs.d/lisp/yasnippet/doc/snippet-development.rst660
1 files changed, 660 insertions, 0 deletions
diff --git a/emacs.d/lisp/yasnippet/doc/snippet-development.rst b/emacs.d/lisp/yasnippet/doc/snippet-development.rst
new file mode 100644
index 0000000..cf14e11
--- /dev/null
+++ b/emacs.d/lisp/yasnippet/doc/snippet-development.rst
@@ -0,0 +1,660 @@
+================
+Writing snippets
+================
+
+.. _Organizing Snippets: snippet-organization.html
+.. _Expanding Snippets: snippet-expansion.html
+.. _Writing Snippets: snippet-development.html
+.. _The YASnippet Menu: snippet-menu.html
+
+.. contents::
+
+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:
+
+.. sourcecode:: text
+
+ #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:
+
+.. sourcecode:: text
+
+ # 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.
+
+.. sourcecode:: text
+
+ #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.
+
+.. sourcecode:: text
+
+ #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:
+
+.. sourcecode:: text
+
+ #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:
+
+.. sourcecode:: text
+
+ 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:
+
+.. sourcecode:: text
+
+ <div$1>
+ $0
+ </div>
+
+Placeholder fields
+------------------
+
+Tab stops can have default values -- a.k.a placeholders. The syntax is
+like this:
+
+.. sourcecode:: text
+
+ ${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:
+
+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:
+
+.. sourcecode:: text
+
+ \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
+<http://www.youtube.com/watch?v=vOj7btx3ATg>`_ or `avi video
+<http://yasnippet.googlecode.com/files/yasnippet.avi>`_).
+
+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.
+
+.. _transformations:
+
+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:
+
+.. sourcecode:: text
+
+ - (${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
+
+.. sourcecode:: text
+
+ =====
+ Title
+ =====
+
+is a valid title but
+
+.. sourcecode:: text
+
+ ===
+ Title
+ ===
+
+is not. Here's an snippet for rst title:
+
+.. sourcecode:: text
+
+ ${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
+
+.. sourcecode:: text
+
+ #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.
+
+.. sourcecode:: text
+
+ #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:
+
+.. sourcecode:: text
+
+ <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.
+
+.. sourcecode:: text
+
+ \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
+<http://groups.google.com/group/smart-snippet/browse_thread/thread/282a90a118e1b662>`_
+
+Nested placeholder fields
+-------------------------
+
+From version 0.6 on, you can also have nested placeholders of the type:
+
+.. sourcecode:: text
+
+ <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``.
+
+.. sourcecode:: text
+
+ 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
+selected region, this works mostly for snippets with direct
+keybindings or 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:
+
+ * `a python script by Jeff Wheeler
+ <http://code.nokrev.com/?p=snippet-copier.git;a=blob_plain;f=snippet_copier.py>`_
+
+ * a `ruby tool
+ <http://yasnippet.googlecode.com/svn/trunk/extras/textmate_import.rb>`_
+ , ``textmate_import.rb`` adapted from `Rob Christie's
+ <http://www.neutronflux.net/2009/07/28/shoulda-snippets-for-emacs/>`_,
+ which I have uploaded to the repository.
+
+In this section, i'll shortly cover the **second** option.
+
+Download the ``textmate_import.rb`` tool and the TextMate
+bundle you're interested in.
+
+.. sourcecode:: text
+
+ $ 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:
+
+.. sourcecode:: text
+
+ $ ./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.
+
+.. sourcecode:: text
+
+ $ 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.
+
+.. LocalWords: html YASnippet yas sourcecode pluskid init filenames filename
+.. LocalWords: env varlist keybinding keymap rinari ifndef upcase endif
+.. LocalWords: nondirectory autorelease aValue inline