mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 21:13:04 +00:00
added skeleton of new documentation
This commit is contained in:
parent
9541218756
commit
938e3a6eb8
@ -3,7 +3,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>ChangeLog</title>
|
||||
<meta name="author" content="pluskid" />
|
||||
<meta name="date" content="2008-03-22" />
|
||||
@ -11,30 +11,52 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="changelog">
|
||||
<div id="header-region" class="clear-block"></div>
|
||||
<div id="wrapper">
|
||||
<div id="container" class="clear-block">
|
||||
<div id="header">
|
||||
<div id="logo-floater">
|
||||
<h1 class="title">ChangeLog</h1>
|
||||
<table class="docinfo" frame="void" rules="none">
|
||||
<col class="docinfo-name" />
|
||||
<col class="docinfo-content" />
|
||||
<tbody valign="top">
|
||||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>pluskid</td></tr>
|
||||
<tr><th class="docinfo-name">Contact:</th>
|
||||
<td><a class="first last reference" href="mailto:pluskid@gmail.com">pluskid@gmail.com</a></td></tr>
|
||||
<tr><th class="docinfo-name">Date:</th>
|
||||
<td>2008-03-22</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="section">
|
||||
<h1><a id="c-2009-07-27" name="c-2009-07-27">0.6.0c / 2009-07-27</a></h1>
|
||||
</div>
|
||||
<ul class="primary-links">
|
||||
<li>
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-organization.html">Organize</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-expansion.html">Expand</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-development.html">Write</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="changelog.html">ChangeLog</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="http://code.google.com/p/yasnippet/downloads/list">Download</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="center">
|
||||
<div id="squeeze">
|
||||
<div class="right-corner">
|
||||
<div class="left-corner">
|
||||
<div class="section" id="c-2009-07-27">
|
||||
<h1>0.6.0c / 2009-07-27</h1>
|
||||
<ul class="simple">
|
||||
<li>Now byte compiles correctly with no warnings.</li>
|
||||
<li>Fixed <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=68">Issue 68</a> with
|
||||
<li>Fixed <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=68">Issue 68</a> with
|
||||
mouse-clicking alternatives in <tt class="docutils literal"><span class="pre">ido-mode</span></tt>.</li>
|
||||
<li>Added <tt class="docutils literal"><span class="pre">yas/also-auto-indent-first-line</span></tt> customization variable.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="b-2009-07-25" name="b-2009-07-25">0.6.0b / 2009-07-25</a></h1>
|
||||
<div class="section" id="b-2009-07-25">
|
||||
<h1>0.6.0b / 2009-07-25</h1>
|
||||
<ul class="simple">
|
||||
<li>Nested placeholders of the type <tt class="docutils literal"><span class="pre"><div${1:</span> <span class="pre">id="${2:someid}"}></span> <span class="pre">$0</span></tt>.</li>
|
||||
<li>More robust undo/redo support.</li>
|
||||
@ -51,63 +73,63 @@ primary field transformation.</li>
|
||||
<li>Customization group <tt class="docutils literal"><span class="pre">yasnippet</span></tt>.</li>
|
||||
<li>Overriding customization variables in snippets. Use the <tt class="docutils literal"><span class="pre">env:</span>
|
||||
<span class="pre">let-form</span></tt> template keyword.</li>
|
||||
<li>Fixed <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=60">Issue 60</a></li>
|
||||
<li>Fixed <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=65">Issue 65</a></li>
|
||||
<li>Fixed <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=56">Issue 56</a></li>
|
||||
<li>Fixed <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=60">Issue 60</a></li>
|
||||
<li>Fixed <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=65">Issue 65</a></li>
|
||||
<li>Fixed <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=56">Issue 56</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id1" name="id1">0.5.10 / 2009-02-11</a></h1>
|
||||
<div class="section" id="id1">
|
||||
<h1>0.5.10 / 2009-02-11</h1>
|
||||
<ul class="simple">
|
||||
<li>Added <em>grouping</em> support so that the snippets in the menu can be
|
||||
groupped together.</li>
|
||||
<li>Make the bundle <a class="reference" href="http://tromey.com/elpa/index.html">ELPA</a>
|
||||
<li>Make the bundle <a class="reference external" href="http://tromey.com/elpa/index.html">ELPA</a>
|
||||
compatible.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id2" name="id2">0.5.9 / 2009-01-21</a></h1>
|
||||
<div class="section" id="id2">
|
||||
<h1>0.5.9 / 2009-01-21</h1>
|
||||
<ul class="simple">
|
||||
<li>Fixed the bug of disabling the auto-indenting of <tt class="docutils literal"><span class="pre">cc-mode</span></tt>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id3" name="id3">0.5.8 / 2009-01-15</a></h1>
|
||||
<div class="section" id="id3">
|
||||
<h1>0.5.8 / 2009-01-15</h1>
|
||||
<ul class="simple">
|
||||
<li>Added a <tt class="docutils literal"><span class="pre">key</span></tt> property in snippet definition for snippet names
|
||||
that are not valid path name.</li>
|
||||
<li>Fixed some bugs of indenting (<a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=44">Issue 44</a>, <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=46">Issue
|
||||
<li>Fixed some bugs of indenting (<a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=44">Issue 44</a>, <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=46">Issue
|
||||
46</a>).</li>
|
||||
<li>Fixed <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=45">Issue 45</a> by
|
||||
<li>Fixed <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=45">Issue 45</a> by
|
||||
providing a proper default value for <tt class="docutils literal"><span class="pre">yas/buffer-local-condition</span></tt>.</li>
|
||||
<li>Added helper function <tt class="docutils literal"><span class="pre">yas/substr</span></tt> for convenient mirror
|
||||
transformation.</li>
|
||||
<li>Make variable <tt class="docutils literal"><span class="pre">yas/registered-snippet</span></tt> properly initialized.</li>
|
||||
<li>Fixed the overlay error when overlay becomes empty (<a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=49">Issue 49</a> and
|
||||
<a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=48">Issue 48</a>). This
|
||||
<li>Fixed the overlay error when overlay becomes empty (<a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=49">Issue 49</a> and
|
||||
<a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=48">Issue 48</a>). This
|
||||
bug has occurred and been fixed earlier, and should not have
|
||||
happened if we have proper regression test.</li>
|
||||
<li>Added a workaround for <tt class="docutils literal"><span class="pre">c-electric-</span></tt> serial commands (<a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=27">Issue 27</a>).</li>
|
||||
<li>Added a workaround for <tt class="docutils literal"><span class="pre">c-electric-</span></tt> serial commands (<a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=27">Issue 27</a>).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id4" name="id4">0.5.7 / 2008-12-03</a></h1>
|
||||
<div class="section" id="id4">
|
||||
<h1>0.5.7 / 2008-12-03</h1>
|
||||
<ul class="simple">
|
||||
<li>Fixed <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=28">Issue 28</a> of
|
||||
<li>Fixed <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=28">Issue 28</a> of
|
||||
properly clean up snippet (by joaotavora).</li>
|
||||
<li>Added a new section "Field-level undo functionality" to correct
|
||||
<a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=33">Issue 33</a>
|
||||
<a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=33">Issue 33</a>
|
||||
(by joaotavora).</li>
|
||||
<li>Added some snippets from users for sql, erlang, scala, html, xml, latex, etc.</li>
|
||||
<li>Fixed <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=16">Issue 16</a> by adding
|
||||
<tt class="docutils literal"><span class="pre">$></span></tt> support. Here's the <a class="reference" href="http://pluskid.lifegoo.com/upload/project/yasnippet/doc/define_snippet.html#indenting">doc for $> indenting</a>.</li>
|
||||
<li>Fixed <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=16">Issue 16</a> by adding
|
||||
<tt class="docutils literal"><span class="pre">$></span></tt> support. Here's the <a class="reference external" href="http://pluskid.lifegoo.com/upload/project/yasnippet/doc/define_snippet.html#indenting">doc for $> indenting</a>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id5" name="id5">0.5.6 / 2008-08-07</a></h1>
|
||||
<div class="section" id="id5">
|
||||
<h1>0.5.6 / 2008-08-07</h1>
|
||||
<ul class="simple">
|
||||
<li>Added a buffer local variable <tt class="docutils literal"><span class="pre">yas/dont-activate</span></tt> to turn off
|
||||
<tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt> in some major modes. See <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=29">Issue 29</a>.</li>
|
||||
<tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt> in some major modes. See <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=29">Issue 29</a>.</li>
|
||||
<li>Make the environment of elisp evaluation more friendly to
|
||||
<tt class="docutils literal"><span class="pre">(current-column)</span></tt>.</li>
|
||||
<li>Fixed the regular expression bug in python-mode snippets.</li>
|
||||
@ -115,8 +137,8 @@ properly clean up snippet (by joaotavora).</li>
|
||||
property is defined.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id6" name="id6">0.5.5 / 2008-05-29</a></h1>
|
||||
<div class="section" id="id6">
|
||||
<h1>0.5.5 / 2008-05-29</h1>
|
||||
<ul class="simple">
|
||||
<li>Tweak <tt class="docutils literal"><span class="pre">yas/extra-mode-hooks</span></tt> so that it can be more easily
|
||||
customized.</li>
|
||||
@ -124,38 +146,38 @@ customized.</li>
|
||||
modes.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id7" name="id7">0.5.4 / 2008-05-15</a></h1>
|
||||
<div class="section" id="id7">
|
||||
<h1>0.5.4 / 2008-05-15</h1>
|
||||
<ul class="simple">
|
||||
<li>Added <tt class="docutils literal"><span class="pre">ox-mode-hook</span></tt> and <tt class="docutils literal"><span class="pre">python-mode-hook</span></tt> to
|
||||
<tt class="docutils literal"><span class="pre">yas/extra-mode-hooks</span></tt> to fix the problem YASnippet is not enabled
|
||||
in those modes.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id8" name="id8">0.5.3 / 2008-05-07</a></h1>
|
||||
<div class="section" id="id8">
|
||||
<h1>0.5.3 / 2008-05-07</h1>
|
||||
<ul class="simple">
|
||||
<li>Fix indent of python-mode snippets.</li>
|
||||
<li>Fix a bug of dropdown-list: conflicts with color-theme (<a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=23">Issue 23</a>). Thanks
|
||||
<li>Fix a bug of dropdown-list: conflicts with color-theme (<a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=23">Issue 23</a>). Thanks
|
||||
Mike.</li>
|
||||
<li>Fix a bug of condition system.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id9" name="id9">0.5.2 / 2008-04-20</a></h1>
|
||||
<div class="section" id="id9">
|
||||
<h1>0.5.2 / 2008-04-20</h1>
|
||||
<ul class="simple">
|
||||
<li>Fix a bug for comparing string to symbol using <tt class="docutils literal"><span class="pre">string=</span></tt> (which
|
||||
will fire an error).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id10" name="id10">0.5.1 / 2008-04-14</a></h1>
|
||||
<div class="section" id="id10">
|
||||
<h1>0.5.1 / 2008-04-14</h1>
|
||||
<ul class="simple">
|
||||
<li>Use a beautiful css style in the document.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id11" name="id11">0.5.0 / 2008-04-10</a></h1>
|
||||
<div class="section" id="id11">
|
||||
<h1>0.5.0 / 2008-04-10</h1>
|
||||
<ul class="simple">
|
||||
<li>Integrate with hippie-expand. Just add <tt class="docutils literal"><span class="pre">yas/hippie-try-expand</span></tt> to
|
||||
<tt class="docutils literal"><span class="pre">hippie-expand-try-functions-list</span></tt>.</li>
|
||||
@ -169,76 +191,76 @@ problem now.</li>
|
||||
distribution.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id12" name="id12">0.4.5 / 2008-04-07</a></h1>
|
||||
<div class="section" id="id12">
|
||||
<h1>0.4.5 / 2008-04-07</h1>
|
||||
<ul class="simple">
|
||||
<li>Merge the latest dropdown-list.el.</li>
|
||||
<li>Add snippets for f90-mode from Li Zhu.</li>
|
||||
<li>Bug fix: l-safe-expr-p: Lisp nesting exceeds <tt class="docutils literal"><span class="pre">max-lisp-eval-depth</span></tt>
|
||||
error when several (more than two) snippets overlaps. Thanks
|
||||
<a class="reference" href="mailto:sunwaybupt@newsmth">sunwaybupt@newsmth</a> for reporting this bug.</li>
|
||||
<a class="reference external" href="mailto:sunwaybupt@newsmth">sunwaybupt@newsmth</a> for reporting this bug.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id13" name="id13">0.4.4 / 2008-03-24</a></h1>
|
||||
<div class="section" id="id13">
|
||||
<h1>0.4.4 / 2008-03-24</h1>
|
||||
<ul class="simple">
|
||||
<li>Bug fix: dropdown-list.el doesn't recognize [return] properly.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id14" name="id14">0.4.3 / 2008-03-23</a></h1>
|
||||
<div class="section" id="id14">
|
||||
<h1>0.4.3 / 2008-03-23</h1>
|
||||
<ul class="simple">
|
||||
<li>Bug fix: failed to recognize user customized yas/trigger-key.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id15" name="id15">0.4.2 / 2008-03-22</a></h1>
|
||||
<div class="section" id="id15">
|
||||
<h1>0.4.2 / 2008-03-22</h1>
|
||||
<ul class="simple">
|
||||
<li>Make a separate document package for release. Also make document
|
||||
available online.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id16" name="id16">0.4.1 / 2008-03-21</a></h1>
|
||||
<div class="section" id="id16">
|
||||
<h1>0.4.1 / 2008-03-21</h1>
|
||||
<ul class="simple">
|
||||
<li>Make sure <tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt>'s key bindings always take priority to
|
||||
other minor modes.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id17" name="id17">0.4.0 / 2008-03-20</a></h1>
|
||||
<div class="section" id="id17">
|
||||
<h1>0.4.0 / 2008-03-20</h1>
|
||||
<ul class="simple">
|
||||
<li>Document refinement and released with YASnippet. Most of the Online
|
||||
wiki document will be deprecated soon.</li>
|
||||
<li>Powerful condition system added to yasnippet!</li>
|
||||
<li>Incorporate <tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt> and make it default way for
|
||||
selecting multiple candidates. Thanks to <a class="reference" href="http://groups.google.com/group/smart-snippet/browse_thread/thread/c869158b76addeb3/e7c6372ba457189e">Jaeyoun Chung</a>.</li>
|
||||
selecting multiple candidates. Thanks to <a class="reference external" href="http://groups.google.com/group/smart-snippet/browse_thread/thread/c869158b76addeb3/e7c6372ba457189e">Jaeyoun Chung</a>.</li>
|
||||
<li>yas/before-expand-snippet-hook</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id18" name="id18">0.3.2 / 2008-03-19</a></h1>
|
||||
<div class="section" id="id18">
|
||||
<h1>0.3.2 / 2008-03-19</h1>
|
||||
<ul class="simple">
|
||||
<li>Enhancement: A better way to define minor-mode. Thanks to Kentaro
|
||||
Kuribayashi. See <a class="reference" href="https://groups.google.com/group/smart-snippet/browse_thread/thread/65cb3b5583eda887?hl=en">this thread</a>
|
||||
Kuribayashi. See <a class="reference external" href="https://groups.google.com/group/smart-snippet/browse_thread/thread/65cb3b5583eda887?hl=en">this thread</a>
|
||||
for more details.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id19" name="id19">0.3.1 / 2008-03-17</a></h1>
|
||||
<div class="section" id="id19">
|
||||
<h1>0.3.1 / 2008-03-17</h1>
|
||||
<ul class="simple">
|
||||
<li>Bug fix: Emacs get confused when a field is deleted. See <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=10">issue 10</a>.</li>
|
||||
<li>Bug fix: Emacs get confused when a field is deleted. See <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=10">issue 10</a>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id20" name="id20">0.3.0 / 2008-03-16</a></h1>
|
||||
<div class="section" id="id20">
|
||||
<h1>0.3.0 / 2008-03-16</h1>
|
||||
<ul class="simple">
|
||||
<li>Add a <tt class="docutils literal"><span class="pre">yas/after-exit-snippet-hook</span></tt> so that you can do something like
|
||||
<tt class="docutils literal"><span class="pre">indent-region</span></tt> or <tt class="docutils literal"><span class="pre">fill-region</span></tt> after finish the snippet.</li>
|
||||
<li>Use minor-mode instead of <tt class="docutils literal"><span class="pre">global-set-key</span></tt> to bind the trigger
|
||||
key. Now the trigger key and fall-back behavior can be more
|
||||
flexible. Not constrained to <tt class="docutils literal"><span class="pre"><tab></span></tt>. Thanks to Trey Jackson. See
|
||||
this <a class="reference" href="https://groups.google.com/group/smart-snippet/browse_thread/thread/937f32a2a6dea4f2?hl=en">thread</a>
|
||||
this <a class="reference external" href="https://groups.google.com/group/smart-snippet/browse_thread/thread/937f32a2a6dea4f2?hl=en">thread</a>
|
||||
for more details.</li>
|
||||
<li>Now user can customize the popup function for selecting multiple
|
||||
candidate for the same snippet key.</li>
|
||||
@ -246,48 +268,48 @@ candidate for the same snippet key.</li>
|
||||
candidate when in text mode.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id21" name="id21">0.2.3 / 2008-03-15</a></h1>
|
||||
<div class="section" id="id21">
|
||||
<h1>0.2.3 / 2008-03-15</h1>
|
||||
<ul class="simple">
|
||||
<li>Bug in non-window (-nw) mode when there's multiple candidate to
|
||||
expand. See <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=7">issue 7</a>.</li>
|
||||
expand. See <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=7">issue 7</a>.</li>
|
||||
<li>Allow expanding another snippet as long as not currently inside a
|
||||
field.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id22" name="id22">0.2.2 / 2008-03-13</a></h1>
|
||||
<div class="section" id="id22">
|
||||
<h1>0.2.2 / 2008-03-13</h1>
|
||||
<ul class="simple">
|
||||
<li>Added customized face for fields and mirrors. Better in dark
|
||||
background. And users can customize it.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id23" name="id23">0.2.1 / 2008-03-10</a></h1>
|
||||
<div class="section" id="id23">
|
||||
<h1>0.2.1 / 2008-03-10</h1>
|
||||
<ul class="simple">
|
||||
<li>Fix the insert-behind problem under both Emacs 22 and Emacs 23.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id24" name="id24">0.2.0 / 2008-03-10</a></h1>
|
||||
<div class="section" id="id24">
|
||||
<h1>0.2.0 / 2008-03-10</h1>
|
||||
<ul class="simple">
|
||||
<li>Use big keymap overlay to detect <tt class="docutils literal"><span class="pre">insert-behind</span></tt> event manually to
|
||||
avoid sometimes missed hook calls. See <a class="reference" href="http://code.google.com/p/yasnippet/issues/detail?id=3">issue 3</a> for more
|
||||
avoid sometimes missed hook calls. See <a class="reference external" href="http://code.google.com/p/yasnippet/issues/detail?id=3">issue 3</a> for more
|
||||
details.</li>
|
||||
<li>Support parent snippet table. Now you can set (for example)
|
||||
<tt class="docutils literal"><span class="pre">cc-mode</span></tt> as common mode for <tt class="docutils literal"><span class="pre">c++-mode</span></tt>, <tt class="docutils literal"><span class="pre">c-mode</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">java-mode</span></tt>. They'll share snippets defined for <tt class="docutils literal"><span class="pre">cc-mode</span></tt>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id25" name="id25">0.1.1 / 2008-03-08</a></h1>
|
||||
<div class="section" id="id25">
|
||||
<h1>0.1.1 / 2008-03-08</h1>
|
||||
<ul class="simple">
|
||||
<li>Add a rake task to upload to google code.</li>
|
||||
<li>Use elisp compile-bundle function instead of python scrip</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="id26" name="id26">0.1.0 / 2008-03-07</a></h1>
|
||||
<div class="section" id="id26">
|
||||
<h1>0.1.0 / 2008-03-07</h1>
|
||||
<ul class="simple">
|
||||
<li>Embedded elisp support.</li>
|
||||
<li>Fields navigation support.</li>
|
||||
@ -299,6 +321,12 @@ details.</li>
|
||||
<li>Load directory support.</li>
|
||||
<li>Compile bundle support.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -1,900 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
|
||||
<title>How to define a snippet ?</title>
|
||||
<meta name="author" content="pluskid, joaotavora" />
|
||||
<meta name="date" content="2009-07-24" />
|
||||
<link rel="stylesheet" href="styles.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="how-to-define-a-snippet">
|
||||
<div id="header-region" class="clear-block"></div>
|
||||
<div id="wrapper">
|
||||
<div id="container" class="clear-block">
|
||||
<div id="header">
|
||||
<div id="logo-floater">
|
||||
<h1 class="title">How to define a snippet ?</h1>
|
||||
</div>
|
||||
<ul class="primary-links">
|
||||
<li>
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="define_snippet.html">Howto</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="changelog.html">ChangeLog</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="http://code.google.com/p/yasnippet/downloads/list">Download</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="center">
|
||||
<div id="squeeze">
|
||||
<div class="right-corner">
|
||||
<div class="left-corner">
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#define-snippets-in-files" id="id8">Define snippets in files</a><ul>
|
||||
<li><a class="reference internal" href="#directory-hierarchy" id="id9">Directory hierarchy</a></li>
|
||||
<li><a class="reference internal" href="#file-content" id="id10">File content</a></li>
|
||||
<li><a class="reference internal" href="#quickly-finding-defining-snippets" id="id11">Quickly finding/defining snippets</a></li>
|
||||
<li><a class="reference internal" href="#using-the-snippet-mode-major-mode" id="id12">Using the <tt class="docutils literal"><span class="pre">snippet-mode</span></tt> major mode</a></li>
|
||||
<li><a class="reference internal" href="#define-snippets-using-elisp-code" id="id13">Define snippets using elisp code</a><ul>
|
||||
<li><a class="reference internal" href="#yas-define-snippets" id="id14">yas/define-snippets</a></li>
|
||||
<li><a class="reference internal" href="#yas-compile-bundle" id="id15">yas/compile-bundle</a></li>
|
||||
<li><a class="reference internal" href="#yas-define" id="id16">yas/define</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#the-strategy-to-select-a-snippet" id="id17">The strategy to select a snippet</a><ul>
|
||||
<li><a class="reference internal" href="#finding-the-key" id="id18">Finding the key</a></li>
|
||||
<li><a class="reference internal" href="#the-condition-system" id="id19">The condition system</a></li>
|
||||
<li><a class="reference internal" href="#multiple-snippet-with-the-same-key" id="id20">Multiple snippet with the same key</a><ul>
|
||||
<li><a class="reference internal" href="#use-the-x-window-system" id="id21">Use the X window system</a></li>
|
||||
<li><a class="reference internal" href="#use-built-in-emacs-selection-methods" id="id22">Use built-in Emacs selection methods</a></li>
|
||||
<li><a class="reference internal" href="#use-dropdown-menu-el" id="id23">Use <tt class="docutils literal"><span class="pre">dropdown-menu.el</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#the-trigger-key" id="id24">The Trigger Key</a><ul>
|
||||
<li><a class="reference internal" href="#the-minor-mode" id="id25">The Minor Mode</a></li>
|
||||
<li><a class="reference internal" href="#the-fallback" id="id26">The Fallback</a></li>
|
||||
<li><a class="reference internal" href="#integration-with-hippie-expand" id="id27">Integration with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#other-way-to-select-a-snippet" id="id28">Other way to select a snippet</a><ul>
|
||||
<li><a class="reference internal" href="#yas-insert-snippet" id="id29"><tt class="docutils literal"><span class="pre">yas/insert-snippet</span></tt></a></li>
|
||||
<li><a class="reference internal" href="#the-menu" id="id30">The Menu</a></li>
|
||||
<li><a class="reference internal" href="#expanding-from-elisp-code" id="id31">Expanding From Elisp Code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#the-syntax-of-the-template" id="id32">The Syntax of the Template</a><ul>
|
||||
<li><a class="reference internal" href="#plain-text" id="id33">Plain Text</a></li>
|
||||
<li><a class="reference internal" href="#embedded-elisp-code" id="id34">Embedded elisp code</a></li>
|
||||
<li><a class="reference internal" href="#tab-stop-fields" id="id35">Tab stop fields</a></li>
|
||||
<li><a class="reference internal" href="#placeholder-fields" id="id36">Placeholder fields</a></li>
|
||||
<li><a class="reference internal" href="#id4" id="id37">Mirrors</a></li>
|
||||
<li><a class="reference internal" href="#mirrors-with-transformations" id="id38">Mirrors with transformations</a></li>
|
||||
<li><a class="reference internal" href="#fields-with-transformations" id="id39">Fields with transformations</a></li>
|
||||
<li><a class="reference internal" href="#choosing-fields-value-from-a-list" id="id40">Choosing fields value from a list</a></li>
|
||||
<li><a class="reference internal" href="#nested-placeholder-fields" id="id41">Nested placeholder fields</a></li>
|
||||
<li><a class="reference internal" href="#indenting" id="id42">Indenting</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>The most convenient way to define snippets for YASnippet is to put
|
||||
them in a directory arranged by the mode and use
|
||||
<tt class="docutils literal"><span class="pre">yas/load-directory</span></tt> to load them.</p>
|
||||
<p>However, this might slow down the Emacs startup speed if you have many
|
||||
snippets. You can use <tt class="docutils literal"><span class="pre">yas/define-snippets</span></tt> to define a bunch of
|
||||
snippets for a perticular mode. But this is hard to maintain! So,
|
||||
there's a better way: define your snippets in directory and use
|
||||
<tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt> to compile it into a bundle file when you
|
||||
modified your snippets.</p>
|
||||
<p>The release bundle of YASnippet is produced by
|
||||
<tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt>. The bundle use <tt class="docutils literal"><span class="pre">yas/define-snippets</span></tt> to
|
||||
define snippets. This avoid the IO and parsing overhead when loading
|
||||
snippets.</p>
|
||||
<p>Finally, you can use <tt class="docutils literal"><span class="pre">yas/define</span></tt> to define a single snippet at your
|
||||
convenience. I ofthen use this to do some testing.</p>
|
||||
<div class="section" id="define-snippets-in-files">
|
||||
<h1><a class="toc-backref" href="#id8">Define snippets in files</a></h1>
|
||||
<div class="section" id="directory-hierarchy">
|
||||
<h2><a class="toc-backref" href="#id9">Directory hierarchy</a></h2>
|
||||
<p>Here's the directory hierarchy of the <tt class="docutils literal"><span class="pre">snippets</span></tt> directory comes
|
||||
with YASnippet:</p>
|
||||
<div class="highlight"><pre>snippets
|
||||
`-- text-mode/
|
||||
|-- cc-mode/
|
||||
| |-- c++-mode/
|
||||
| | |-- beginend
|
||||
| | |-- class
|
||||
| | `-- using
|
||||
| |-- c-mode/
|
||||
| | `-- fopen
|
||||
| |-- do
|
||||
| |-- for
|
||||
| |-- if
|
||||
| |-- inc
|
||||
| |-- inc.1
|
||||
| |-- main
|
||||
| |-- once
|
||||
| `-- struct
|
||||
|-- css-mode/
|
||||
| |-- background
|
||||
| |-- background.1
|
||||
| `-- border
|
||||
|-- email
|
||||
|-- html-mode/
|
||||
| |-- div
|
||||
| |-- doctype
|
||||
| |-- doctype.xhml1
|
||||
| |-- doctype.xhtml1_1
|
||||
| |-- doctype.xhtml1_strict
|
||||
| `-- doctype.xhtml1_transitional
|
||||
|-- objc-mode/
|
||||
| `-- prop
|
||||
|-- perl-mode/
|
||||
| |-- cperl-mode/
|
||||
| |-- eval
|
||||
| |-- for
|
||||
| |-- fore
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- ifee
|
||||
| |-- sub
|
||||
| |-- unless
|
||||
| |-- while
|
||||
| |-- xfore
|
||||
| |-- xif
|
||||
| |-- xunless
|
||||
| `-- xwhile
|
||||
|-- python-mode/
|
||||
| |-- __
|
||||
| |-- class
|
||||
| |-- def
|
||||
| |-- for
|
||||
| |-- ifmain
|
||||
| `-- while
|
||||
|-- rst-mode/
|
||||
| |-- chapter
|
||||
| |-- section
|
||||
| `-- title
|
||||
|-- ruby-mode/
|
||||
| |-- #
|
||||
| |-- =b
|
||||
| |-- Comp
|
||||
| |-- all
|
||||
| |-- am
|
||||
| |-- any
|
||||
| |-- app
|
||||
| |-- bm
|
||||
| |-- case
|
||||
| |-- cla
|
||||
| |-- classify
|
||||
| |-- cls
|
||||
| |-- collect
|
||||
| |-- dee
|
||||
| |-- deli
|
||||
| |-- det
|
||||
| |-- ea
|
||||
| |-- eac
|
||||
| |-- eai
|
||||
| |-- eav
|
||||
| |-- eawi
|
||||
| |-- forin
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- inject
|
||||
| |-- mm
|
||||
| |-- r
|
||||
| |-- rb
|
||||
| |-- reject
|
||||
| |-- req
|
||||
| |-- rreq
|
||||
| |-- rw
|
||||
| |-- select
|
||||
| |-- w
|
||||
| |-- y
|
||||
| `-- zip
|
||||
`-- time
|
||||
</pre></div>
|
||||
<p>Snippet definitions are put in plain text files. They are arranged by
|
||||
subdirectories. For example, snippets for <tt class="docutils literal"><span class="pre">c-mode</span></tt> are put in the
|
||||
<tt class="docutils literal"><span class="pre">c-mode</span></tt> directory.</p>
|
||||
<p>The parent directory acts as the <em>parent mode</em>. This is the way of
|
||||
YASnippet to share snippet definitions among different modes. As you
|
||||
can see above, <tt class="docutils literal"><span class="pre">c-mode</span></tt> and <tt class="docutils literal"><span class="pre">c++-mode</span></tt> share the same parents
|
||||
<tt class="docutils literal"><span class="pre">cc-mode</span></tt>, while all modes are derived from <tt class="docutils literal"><span class="pre">text-mode</span></tt>. This can
|
||||
be also used to as an <em>alias</em> -- <tt class="docutils literal"><span class="pre">cperl-mode</span></tt> is an empty directory
|
||||
whose parent is <tt class="docutils literal"><span class="pre">perl-mode</span></tt>.</p>
|
||||
<p>File names act as the snippet trigger key. Note files starting with a
|
||||
dot (<tt class="docutils literal"><span class="pre">.</span></tt>) are ignored.</p>
|
||||
</div>
|
||||
<div class="section" id="file-content">
|
||||
<h2><a class="toc-backref" href="#id10">File content</a></h2>
|
||||
<p>A file defining a snippet may just contain the template for the
|
||||
snippet. Optionally it can also contains some meta data for the
|
||||
snippet as well as comments.</p>
|
||||
<p>Generally speaking, if the file contains a line of <tt class="docutils literal"><span class="pre">#</span> <span class="pre">--</span></tt>, then all
|
||||
contents above that line are considered as meta data and comments;
|
||||
below are template. Or else the whole file content is considered as
|
||||
the template.</p>
|
||||
<p>Here's a typical example:</p>
|
||||
<div class="highlight"><pre>#contributor : pluskid <pluskid@gmail.com>
|
||||
#name : __...__
|
||||
# --
|
||||
__${init}__
|
||||
</pre></div>
|
||||
<p>Meta data are specified in the syntax of</p>
|
||||
<div class="highlight"><pre>#data-name : data value
|
||||
</pre></div>
|
||||
<p>Any other text above <tt class="docutils literal"><span class="pre">#</span> <span class="pre">--</span></tt> is considered as comment and
|
||||
ignored. Here's a list of currently supported meta data:</p>
|
||||
<img align="right" alt="images/group.png" class="align-right" src="images/group.png" />
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">name</span></tt>: The name of the snippet. This is a one-line description of
|
||||
the snippet. It will be displayed in the menu. So it's a good idea
|
||||
to select a descriptive name fo a snippet -- especially
|
||||
distinguishable among similar snippets.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">contributor</span></tt>: The contributor of the snippet.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">condition</span></tt>: The condition of the snippet. This is a piece of
|
||||
elisp code. If a snippet has a condition, then it will only be
|
||||
expanded when the condition code evaluate to some non-nil value.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">key</span></tt>: The key to expand the snippet. Sometimes the key of a
|
||||
snippet is non-ASCII or not valid filename (e.g. contains
|
||||
<tt class="docutils literal"><span class="pre">/</span></tt>). One can then define the <tt class="docutils literal"><span class="pre">key</span></tt> property which will
|
||||
overwrite the filename as the key to expand the snippet.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">group</span></tt>: The snippets for a mode can be grouped. Grouped snippets
|
||||
will be grouped in sub-menu. This is useful if one has too many
|
||||
snippets for a mode which will make the menu too long. <tt class="docutils literal"><span class="pre">group</span></tt>
|
||||
property only affect menu construction (See <a class="reference internal" href="#the-menu">The Menu</a>). Refer to
|
||||
the snippets for <tt class="docutils literal"><span class="pre">ruby-mode</span></tt> for examples. Group can also be
|
||||
nested, e.g. <tt class="docutils literal"><span class="pre">control</span> <span class="pre">structure.loops</span></tt> tells that the snippet is
|
||||
under the <tt class="docutils literal"><span class="pre">loops</span></tt> group which is under the <tt class="docutils literal"><span class="pre">control</span> <span class="pre">structure</span></tt>
|
||||
group.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="quickly-finding-defining-snippets">
|
||||
<h2><a class="toc-backref" href="#id11">Quickly finding/defining snippets</a></h2>
|
||||
<p>From version 0.6 upwards there are two ways you can quickly find a
|
||||
snippet file. Once you find this file it will be set to
|
||||
<tt class="docutils literal"><span class="pre">snippet-mode</span></tt> (see ahead)</p>
|
||||
<ul>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/find-snippets</span></tt></p>
|
||||
<p>Lets you find the snippet file in the directory the snippet was
|
||||
loaded from (if it exists) like <tt class="docutils literal"><span class="pre">find-file-other-window</span></tt>.</p>
|
||||
</li>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/visit-snippet-file</span></tt></p>
|
||||
<p>Prompts you for possible snippet expansions like
|
||||
<tt class="docutils literal"><span class="pre">yas/insert-snippet</span></tt>, but instead of expanding it, takes you
|
||||
directly to the snippet definition's file, if it exists.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="using-the-snippet-mode-major-mode">
|
||||
<h2><a class="toc-backref" href="#id12">Using the <tt class="docutils literal"><span class="pre">snippet-mode</span></tt> major mode</a></h2>
|
||||
<p>From version 0.6 upwards there is a major mode <tt class="docutils literal"><span class="pre">snippet-mode</span></tt> to
|
||||
edit snippets. You can set the buffer to this mode with <tt class="docutils literal"><span class="pre">M-x</span>
|
||||
<span class="pre">snippet-mode</span></tt>. It provides reasonably useful syntax highlighting.</p>
|
||||
<p>Two commands are defined in this mode:</p>
|
||||
<ul>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/load-snippet-buffer</span></tt></p>
|
||||
<blockquote>
|
||||
<p>When editing a snippet, this loads the snippet into the correct
|
||||
mode and menu. Bound to <tt class="docutils literal"><span class="pre">C-c</span> <span class="pre">C-c</span></tt> by default while in
|
||||
<tt class="docutils literal"><span class="pre">snippet-mode</span></tt>.</p>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/tryout-snippet</span></tt></p>
|
||||
<blockquote>
|
||||
<p>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 <tt class="docutils literal"><span class="pre">C-c</span> <span class="pre">C-t</span></tt> while in
|
||||
<tt class="docutils literal"><span class="pre">snippet-mode</span></tt>.</p>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
<p>There are also snippets for making snippets: <tt class="docutils literal"><span class="pre">vars</span></tt>, <tt class="docutils literal"><span class="pre">field</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">mirror</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="define-snippets-using-elisp-code">
|
||||
<h2><a class="toc-backref" href="#id13">Define snippets using elisp code</a></h2>
|
||||
<p>As I mentioned above, you can define snippets directly by writing
|
||||
elisp code.</p>
|
||||
<div class="section" id="yas-define-snippets">
|
||||
<h3><a class="toc-backref" href="#id14">yas/define-snippets</a></h3>
|
||||
<p>The basic syntax of <tt class="docutils literal"><span class="pre">yas/define-snippets</span></tt> is</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define-snippets</span> <span style="color: #19177C">MODE</span> <span style="color: #19177C">SNIPPETS</span> <span style="color: #008000; font-weight: bold">&optional</span> <span style="color: #19177C">PARENT</span>)
|
||||
</pre></div>
|
||||
<p>The parameters are self-descriptive. If you specify a <tt class="docutils literal"><span class="pre">PARENT</span></tt>, then
|
||||
the snippets of the parents may be shared by <tt class="docutils literal"><span class="pre">MODE</span></tt>. Note if you use
|
||||
this function several times, the later specified <tt class="docutils literal"><span class="pre">PARENT</span></tt> will
|
||||
overwrite the original one. However, not specifying a <tt class="docutils literal"><span class="pre">PARENT</span></tt> won't
|
||||
erase the original parent.</p>
|
||||
<p>The <tt class="docutils literal"><span class="pre">SNIPPETS</span></tt> parameter is a list of snippet definitions. Each
|
||||
element should have the following form:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">KEY</span> <span style="color: #19177C">TEMPLATE</span> <span style="color: #19177C">NAME</span> <span style="color: #19177C">CONDITION</span> <span style="color: #19177C">GROUP</span>)
|
||||
</pre></div>
|
||||
<p>The <tt class="docutils literal"><span class="pre">NAME</span></tt>, <tt class="docutils literal"><span class="pre">CONDITION</span></tt> and <tt class="docutils literal"><span class="pre">GROUP</span></tt> can be omitted if you don't
|
||||
want to provide one. Here's an example:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define-snippets</span> <span style="color: #19177C">'c++-mode</span>
|
||||
<span style="color: #666666">'</span>(
|
||||
(<span style="color: #BA2121">"using"</span> <span style="color: #BA2121">"using namespace ${std};</span>
|
||||
<span style="color: #BA2121">$0"</span> <span style="color: #BA2121">"using namespace ... "</span> <span style="color: #880000">nil</span>)
|
||||
(<span style="color: #BA2121">"class"</span> <span style="color: #BA2121">"class ${1:Name}</span>
|
||||
<span style="color: #BA2121">{</span>
|
||||
<span style="color: #BA2121">public:</span>
|
||||
<span style="color: #BA2121"> $1($2);</span>
|
||||
<span style="color: #BA2121"> virtual ~$1();</span>
|
||||
<span style="color: #BA2121">};"</span> <span style="color: #BA2121">"class ... { ... }"</span> <span style="color: #880000">nil</span>)
|
||||
(<span style="color: #BA2121">"beginend"</span> <span style="color: #BA2121">"${1:v}.begin(), $1.end"</span> <span style="color: #BA2121">"v.begin(), v.end()"</span> <span style="color: #880000">nil</span>)
|
||||
)
|
||||
<span style="color: #19177C">'cc-mode</span>)
|
||||
</pre></div>
|
||||
<p>The example above is auto-generated code by <tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="yas-compile-bundle">
|
||||
<h3><a class="toc-backref" href="#id15">yas/compile-bundle</a></h3>
|
||||
<p><tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt> can be used to parse the snippets from a
|
||||
directory hierarchy and translate them into the elisp form. The
|
||||
translated code is faster to load. Further more, the generated bundle
|
||||
is a stand-alone file not depending on <tt class="docutils literal"><span class="pre">yasnippet.el</span></tt>. The released
|
||||
bundles of YASnippet are all generated this way.</p>
|
||||
<p>The basic syntax of <tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt> is</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/compile-bundle</span> <span style="color: #008000; font-weight: bold">&optional</span> <span style="color: #19177C">yasnippet</span> <span style="color: #19177C">yasnippet-bundle</span> <span style="color: #19177C">snippet-roots</span> <span style="color: #19177C">code</span> <span style="color: #19177C">dropdown</span>)
|
||||
</pre></div>
|
||||
<p>As you can see, all the parameters are optional. The default values
|
||||
for those parameters are convenient for me to produce the default
|
||||
release bundle:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/compile-bundle</span> <span style="color: #BA2121">"yasnippet.el"</span>
|
||||
<span style="color: #BA2121">"./yasnippet-bundle.el"</span>
|
||||
<span style="color: #666666">'</span>(<span style="color: #BA2121">"snippets"</span>)
|
||||
<span style="color: #BA2121">"(yas/initialize)"</span>
|
||||
<span style="color: #BA2121">"dropdown-list.el"</span>)
|
||||
</pre></div>
|
||||
<p>The <tt class="docutils literal"><span class="pre">snippet-roots</span></tt> can be a list of root directories. This is
|
||||
useful when you have multiple snippet directories (maybe from other
|
||||
users). The <tt class="docutils literal"><span class="pre">code</span></tt> parameter can be used to specify your own
|
||||
customization code instead of the default <tt class="docutils literal"><span class="pre">(yas/initialize)</span></tt>. For
|
||||
example, you can set <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt> to <tt class="docutils literal"><span class="pre">(kbd</span> <span class="pre">"SPC")</span></tt> here if
|
||||
you like.</p>
|
||||
<p>From release 0.6 you have to specify the <tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt> file if
|
||||
you want it to be a part of the generated bundle.</p>
|
||||
</div>
|
||||
<div class="section" id="yas-define">
|
||||
<h3><a class="toc-backref" href="#id16">yas/define</a></h3>
|
||||
<p>The basic syntax for <tt class="docutils literal"><span class="pre">yas/define</span></tt> is</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define</span> <span style="color: #19177C">mode</span> <span style="color: #19177C">key</span> <span style="color: #19177C">template</span> <span style="color: #008000; font-weight: bold">&optional</span> <span style="color: #19177C">name</span> <span style="color: #B00040">condition</span> <span style="color: #19177C">group</span>)
|
||||
</pre></div>
|
||||
<p>This is only a syntax sugar for</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define-snippets</span> <span style="color: #19177C">mode</span>
|
||||
(<span style="color: #008000">list</span> (<span style="color: #008000">list</span> <span style="color: #19177C">key</span> <span style="color: #19177C">template</span> <span style="color: #19177C">name</span> <span style="color: #B00040">condition</span> <span style="color: #19177C">group</span>)))
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="the-strategy-to-select-a-snippet">
|
||||
<h1><a class="toc-backref" href="#id17">The strategy to select a snippet</a></h1>
|
||||
<p>When user press the <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt>, YASnippet try to find a
|
||||
proper snippet to expand. The strategy to find such a snippet is
|
||||
explained here.</p>
|
||||
<div class="section" id="finding-the-key">
|
||||
<h2><a class="toc-backref" href="#id18">Finding the key</a></h2>
|
||||
<p>YASnippet search from current point backward trying to find the
|
||||
snippet to be expanded. The default searching strategy is quite
|
||||
powerful. For example, in <tt class="docutils literal"><span class="pre">c-mode</span></tt>, <tt class="docutils literal"><span class="pre">"bar"</span></tt>, <tt class="docutils literal"><span class="pre">"foo_bar"</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">"#foo_bar"</span></tt> can all be recognized as a template key. Further more,
|
||||
the searching is in that order. In other words, if <tt class="docutils literal"><span class="pre">"bar"</span></tt> is found
|
||||
to be a key to some <em>valid</em> snippet, then <tt class="docutils literal"><span class="pre">"foo_bar"</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">"#foobar"</span></tt> won't be searched.</p>
|
||||
<p>However, this strategy can also be customized easily from the
|
||||
<tt class="docutils literal"><span class="pre">yas/key-syntaxes</span></tt> variable. It is a list of syntax rules, the
|
||||
default value is <tt class="docutils literal"><span class="pre">("w"</span> <span class="pre">"w_"</span> <span class="pre">"w_."</span> <span class="pre">"^</span> <span class="pre">")</span></tt>. Which means search the
|
||||
following thing until found one:</p>
|
||||
<ul class="simple">
|
||||
<li>a word.</li>
|
||||
<li>a symbol. In lisp, <tt class="docutils literal"><span class="pre">-</span></tt> and <tt class="docutils literal"><span class="pre">?</span></tt> can all be part of a symbol.</li>
|
||||
<li>a sequence of characters of either word, symbol or punctuation.</li>
|
||||
<li>a sequence of characters of non-whitespace characters.</li>
|
||||
</ul>
|
||||
<p>But you'd better keep the default value unless you understand what
|
||||
Emacs's syntax rule mean.</p>
|
||||
</div>
|
||||
<div class="section" id="the-condition-system">
|
||||
<h2><a class="toc-backref" href="#id19">The condition system</a></h2>
|
||||
<p>I write forked snippet.el to make the smart-snippet.el. I call it
|
||||
<em>smart</em>-snippet because a condition can be attached to a snippet. This
|
||||
is really a good idea. However, writing condition for a snippet
|
||||
usually needs good elisp and Emacs knowledge, so it is strange to many
|
||||
user.</p>
|
||||
<p>Later I write YASnippet and persuade people to use it instead of
|
||||
smart-snippet.el. However, some user still love smart-snippet because
|
||||
it is smart. So I make YASnippet smart. Even smarter than
|
||||
smart-snippet.el. :p</p>
|
||||
<p>Consider this scenario: you are an old Emacs hacker. You like the
|
||||
abbrev-way and set <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt> to <tt class="docutils literal"><span class="pre">(kbd</span> <span class="pre">"SPC")</span></tt>. However,
|
||||
you don't want <tt class="docutils literal"><span class="pre">if</span></tt> to be expanded as a snippet when you are typing
|
||||
in a comment block or a string (e.g. in <tt class="docutils literal"><span class="pre">python-mode</span></tt>).</p>
|
||||
<p>It's OK, just specify the condition for <tt class="docutils literal"><span class="pre">if</span></tt> to be <tt class="docutils literal"><span class="pre">(not</span>
|
||||
<span class="pre">(python-in-string/comment))</span></tt>. But how about <tt class="docutils literal"><span class="pre">while</span></tt>, <tt class="docutils literal"><span class="pre">for</span></tt>,
|
||||
etc. ? Writing the same condition for all the snippets is just
|
||||
boring. So YASnippet introduce a buffer local variable
|
||||
<tt class="docutils literal"><span class="pre">yas/buffer-local-condition</span></tt>. You can set this variable to <tt class="docutils literal"><span class="pre">(not</span>
|
||||
<span class="pre">(python-in-string/comment))</span></tt> in <tt class="docutils literal"><span class="pre">python-mode-hook</span></tt>. There's no way
|
||||
to do this in smart-snippet.el!</p>
|
||||
<p>Then, what if you really want some snippet even in comment? This is
|
||||
also possible! But let's stop telling the story and look at the rules:</p>
|
||||
<ul class="simple">
|
||||
<li>If <tt class="docutils literal"><span class="pre">yas/buffer-local-condition</span></tt> evaluate to nil, snippet won't be
|
||||
expanded.</li>
|
||||
<li>If it evaluate to the a cons cell where the <tt class="docutils literal"><span class="pre">car</span></tt> is the symbol
|
||||
<tt class="docutils literal"><span class="pre">require-snippet-condition</span></tt> and the <tt class="docutils literal"><span class="pre">cdr</span></tt> is a symbol (let's
|
||||
call it <tt class="docutils literal"><span class="pre">requirement</span></tt>):<ul>
|
||||
<li>If the snippet has no condition, then it won't be expanded.</li>
|
||||
<li>If the snippet has a condition but evaluate to nil or error
|
||||
occured during evaluation, it won't be expanded.</li>
|
||||
<li>If the snippet has a condition that evaluate to non-nil (let's
|
||||
call it <tt class="docutils literal"><span class="pre">result</span></tt>):<ul>
|
||||
<li>If <tt class="docutils literal"><span class="pre">requirement</span></tt> is <tt class="docutils literal"><span class="pre">t</span></tt>, the snippet is ready to be
|
||||
expanded.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">requirement</span></tt> is <tt class="docutils literal"><span class="pre">eq</span></tt> to <tt class="docutils literal"><span class="pre">result</span></tt>, the snippet is ready
|
||||
to be expanded.</li>
|
||||
<li>Otherwise the snippet won't be expanded.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>If it evaluate to other non-nil value:<ul>
|
||||
<li>If the snippet has no condition, or has a condition that evaluate
|
||||
to non-nil, it is ready to be expanded.</li>
|
||||
<li>Otherwise, it won't be expanded.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>So set <tt class="docutils literal"><span class="pre">yas/buffer-local-condition</span></tt> like this</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">add-hook</span> <span style="color: #19177C">'python-mode-hook</span>
|
||||
<span style="color: #666666">'</span>(<span style="color: #008000; font-weight: bold">lambda</span> ()
|
||||
(<span style="color: #008000; font-weight: bold">setq</span> <span style="color: #19177C">yas/buffer-local-condition</span>
|
||||
<span style="color: #666666">'</span>(<span style="color: #008000; font-weight: bold">if</span> (<span style="color: #19177C">python-in-string/comment</span>)
|
||||
<span style="color: #666666">'</span>(<span style="color: #19177C">require-snippet-condition</span> <span style="color: #666666">.</span> <span style="color: #19177C">force-in-comment</span>)
|
||||
<span style="color: #880000">t</span>))))
|
||||
</pre></div>
|
||||
<p>And specify the condition for a snippet that you're going to expand in
|
||||
comment to be evaluated to the symbol <tt class="docutils literal"><span class="pre">force-in-comment</span></tt>. Then it
|
||||
can be expanded as you expected, while other snippets like <tt class="docutils literal"><span class="pre">if</span></tt>
|
||||
still can't expanded in comment.</p>
|
||||
</div>
|
||||
<div class="section" id="multiple-snippet-with-the-same-key">
|
||||
<h2><a class="toc-backref" href="#id20">Multiple snippet with the same key</a></h2>
|
||||
<p>There can be multiple snippet bind to the same key. If you define a
|
||||
snippet with a key that is already used, you'll overwrite the original
|
||||
snippet definition. However, you can add a different <em>postfix</em> to the
|
||||
key.</p>
|
||||
<p>In general, the <em>extension</em> (consider a file name) is <em>ignored</em> when
|
||||
defining a snippet. So <tt class="docutils literal"><span class="pre">def</span></tt>, <tt class="docutils literal"><span class="pre">def.1</span></tt> and <tt class="docutils literal"><span class="pre">def.mine</span></tt> will all be
|
||||
valid candidates when the key is <tt class="docutils literal"><span class="pre">def</span></tt>.</p>
|
||||
<p>When there are multiple candidates, YASnippet will let you select
|
||||
one. The UI for selecting multiple candidate can be
|
||||
customized. There're two variable related:</p>
|
||||
<p>From version 0.6 of YASnippet this has changed significantly. A new
|
||||
customization variable, called <tt class="docutils literal"><span class="pre">yas/prompt-functions</span></tt> defines your
|
||||
preferred method of being prompted for snippets.</p>
|
||||
<p>You can customize it with <tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">customize-variable</span> <span class="pre">RET</span>
|
||||
<span class="pre">yas/prompt-functions</span> <span class="pre">RET</span></tt>. Alternatively you can put in your
|
||||
emacs-file:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #008000; font-weight: bold">setq</span> <span style="color: #19177C">yas/prompt-functions</span> <span style="color: #666666">'</span>(<span style="color: #19177C">yas/x-prompt</span> <span style="color: #19177C">yas/dropdown-prompt</span>))
|
||||
</pre></div>
|
||||
<p>Currently there are some alternatives solution with YASnippet.</p>
|
||||
<img align="right" alt="images/popup-menu.png" class="align-right" src="images/popup-menu.png" />
|
||||
<div class="section" id="use-the-x-window-system">
|
||||
<h3><a class="toc-backref" href="#id21">Use the X window system</a></h3>
|
||||
<p>The function <tt class="docutils literal"><span class="pre">yas/x-prompt</span></tt> can be used to show a popup menu for you
|
||||
to select. This menu will be part of you native window system widget,
|
||||
which means:</p>
|
||||
<ul class="simple">
|
||||
<li>It usually looks beautiful. E.g. when you compile Emacs with gtk
|
||||
support, this menu will be rendered with your gtk theme.</li>
|
||||
<li>Emacs have little control over it. E.g. you can't use <tt class="docutils literal"><span class="pre">C-n</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">C-p</span></tt> to navigate.</li>
|
||||
<li>This function can't be used when in a terminal.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="use-built-in-emacs-selection-methods">
|
||||
<h3><a class="toc-backref" href="#id22">Use built-in Emacs selection methods</a></h3>
|
||||
<p>You can use functions <tt class="docutils literal"><span class="pre">yas/completing-prompt</span></tt> for the classic emacs
|
||||
completion method or <tt class="docutils literal"><span class="pre">yas/ido-prompt</span></tt> for a much nicer looking
|
||||
method. The best way is to try it. This works in a terminal.</p>
|
||||
<div align="center" class="align-center"><img alt="images/idrop-menu.png" class="align-center" src="images/idrop-menu.png" /></div>
|
||||
</div>
|
||||
<div class="section" id="use-dropdown-menu-el">
|
||||
<h3><a class="toc-backref" href="#id23">Use <tt class="docutils literal"><span class="pre">dropdown-menu.el</span></tt></a></h3>
|
||||
<p>The function <tt class="docutils literal"><span class="pre">yas/dropdown-prompt</span></tt> can also be placed in the
|
||||
<tt class="docutils literal"><span class="pre">yas/prompt-functions</span></tt> list.</p>
|
||||
<img align="right" alt="images/dropdown-menu.png" class="align-right" src="images/dropdown-menu.png" />
|
||||
<p>Originally, only the above two function is available in
|
||||
YASnippet. They are difficult to use -- especially in a
|
||||
terminal. Until later Jaeyoun Chung show me his <tt class="docutils literal"><span class="pre">dropdown-menu.el</span></tt>,
|
||||
I say wow! It's wonderful!</p>
|
||||
<ul class="simple">
|
||||
<li>It works in both window system and terminal.</li>
|
||||
<li>It is customizable, you can use <tt class="docutils literal"><span class="pre">C-n</span></tt>, <tt class="docutils literal"><span class="pre">C-p</span></tt> to navigate, <tt class="docutils literal"><span class="pre">q</span></tt>
|
||||
to quite and even press <tt class="docutils literal"><span class="pre">6</span></tt> as a shortcut to select the 6th
|
||||
candidate.</li>
|
||||
</ul>
|
||||
<p>So I added <tt class="docutils literal"><span class="pre">yas/dropdown-list-popup-for-template</span></tt> to support
|
||||
<tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt>. And upload <tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt> to YASnippet
|
||||
hompage for an optional download (since Jaeyoun didn't provide a URL).</p>
|
||||
<p>Then finally, in 0.4.0, I included a copy of the content of
|
||||
<tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt> <a class="footnote-reference" href="#id5" id="id1">[1]</a> in <tt class="docutils literal"><span class="pre">yasnippet.el</span></tt> and made it the default
|
||||
way for selecting multiple candidates.</p>
|
||||
<p>However, the original functions are still there, you can still use this</p>
|
||||
<div class="highlight"><pre>(<span style="color: #008000; font-weight: bold">setq</span> <span style="color: #19177C">yas/window-system-popup-function</span>
|
||||
<span style="color: #19177C">'yas/x-popup-menu-for-template</span>)
|
||||
</pre></div>
|
||||
<p>if you prefer a <em>modern</em> UI. :)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="the-trigger-key">
|
||||
<h2><a class="toc-backref" href="#id24">The Trigger Key</a></h2>
|
||||
<p>YASnippet is implemented as a minor-mode (<tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt>). The
|
||||
trigger key <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt> is defined in <tt class="docutils literal"><span class="pre">yas/minor-mode-map</span></tt>
|
||||
to call <tt class="docutils literal"><span class="pre">yas/expand</span></tt> to try to expand a snippet.</p>
|
||||
<div class="section" id="the-minor-mode">
|
||||
<h3><a class="toc-backref" href="#id25">The Minor Mode</a></h3>
|
||||
<img align="left" alt="images/minor-mode-indicator.png" class="align-left" src="images/minor-mode-indicator.png" />
|
||||
<p>When <tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt> is enabled, the trigger key will take
|
||||
effect. The default key is <tt class="docutils literal"><span class="pre">(kbd</span> <span class="pre">"TAB")</span></tt>, however, you can freely
|
||||
set it to some other key.</p>
|
||||
<p>In version 0.5, YASnippet add a hook to
|
||||
<tt class="docutils literal"><span class="pre">after-change-major-mode-hook</span></tt> to enable <tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt> <a class="footnote-reference" href="#id6" id="id2">[2]</a> in
|
||||
every buffer. This works fine for most modes, however, some mode
|
||||
doesn't follow the Emacs convention and doens't call this hook. You
|
||||
can either explicitly hook for those mode or just add it to
|
||||
<tt class="docutils literal"><span class="pre">yas/extra-mode-hooks</span></tt> to let YASnippet do it for you:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #008000">require</span> <span style="color: #19177C">'yasnippet</span>)
|
||||
(<span style="color: #19177C">add-to-list</span> <span style="color: #19177C">'yas/extra-mode-hooks</span>
|
||||
<span style="color: #19177C">'ruby-mode-hook</span>)
|
||||
(<span style="color: #19177C">yas/initialize</span>)
|
||||
</pre></div>
|
||||
<p>Note that <strong>should</strong> be put after <tt class="docutils literal"><span class="pre">(require</span> <span class="pre">'yasnippet)</span></tt> and before
|
||||
<tt class="docutils literal"><span class="pre">(yas/initialize)</span></tt>. Further more, you may report it to me, I'll add
|
||||
that to the default value.</p>
|
||||
<p>In version 0.6, just use <tt class="docutils literal"><span class="pre">yas/global-mode</span></tt> to enable YASnippet in
|
||||
all major modes. Or put <tt class="docutils literal"><span class="pre">yas/minor-mode-on</span></tt> in that modes hook. See
|
||||
the <a class="reference external" href="faq.html">FAQ</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="the-fallback">
|
||||
<h3><a class="toc-backref" href="#id26">The Fallback</a></h3>
|
||||
<p>If <tt class="docutils literal"><span class="pre">yas/expand</span></tt> failed to find any suitable snippet to expand, it
|
||||
will disable the minor mode temporarily and find if there's any other
|
||||
command bind the <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt>. If found, the command will be
|
||||
called. Usually this works very well -- when there's a snippet, expand
|
||||
it, otherwise, call whatever command originally bind to the trigger
|
||||
key.</p>
|
||||
<p>However, you can change this behavior by customizing the
|
||||
<tt class="docutils literal"><span class="pre">yas/fallback-behavior</span></tt> variable. If you set this variable to
|
||||
<tt class="docutils literal"><span class="pre">'return-nil</span></tt>, it will return <tt class="docutils literal"><span class="pre">nil</span></tt> instead of trying to call the
|
||||
<em>original</em> command when no snippet is found. This is useful when you
|
||||
would like YASnippet to work with other extensions,
|
||||
e.g. <tt class="docutils literal"><span class="pre">hippie-expand</span></tt>. I'm also glad to tell you that integration
|
||||
with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt> is already included in YASnippet.</p>
|
||||
</div>
|
||||
<div class="section" id="integration-with-hippie-expand">
|
||||
<h3><a class="toc-backref" href="#id27">Integration with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt></a></h3>
|
||||
<p>To integrate with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt>, just put
|
||||
<tt class="docutils literal"><span class="pre">yas/hippie-try-expand</span></tt> in
|
||||
<tt class="docutils literal"><span class="pre">hippie-expand-try-functions-list</span></tt>. Personally I would like to put
|
||||
in front of the list, but it can be put anywhere you prefer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="other-way-to-select-a-snippet">
|
||||
<h2><a class="toc-backref" href="#id28">Other way to select a snippet</a></h2>
|
||||
<p>When you use the trigger key (so <tt class="docutils literal"><span class="pre">yas/expand</span></tt>) to expand a snippet,
|
||||
the key for the snippet is deleted before the template for the snippet
|
||||
is inserted.</p>
|
||||
<p>However, there're other ways to insert a snippet.</p>
|
||||
<div class="section" id="yas-insert-snippet">
|
||||
<h3><a class="toc-backref" href="#id29"><tt class="docutils literal"><span class="pre">yas/insert-snippet</span></tt></a></h3>
|
||||
<p>The command <tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/insert-snippet</span></tt> lets you insert snippets at
|
||||
point <em>for you current major mode</em>. It prompts you for the snippet
|
||||
key first, and then for a snippet template if more than one template
|
||||
exists for the same key.</p>
|
||||
<p>The list presented contains the snippets that can be inserted at
|
||||
point, according to the condition system. If you want to see all
|
||||
applicable snippets for the major mode, prefix this command with
|
||||
<tt class="docutils literal"><span class="pre">C-u</span></tt>.</p>
|
||||
<p>The prompting methods used are again controlled by
|
||||
<tt class="docutils literal"><span class="pre">yas/prompt-functions</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="the-menu">
|
||||
<h3><a class="toc-backref" href="#id30">The Menu</a></h3>
|
||||
<p>YASnippet will setup a menu just after the <em>Buffers</em> Menu in the
|
||||
menubar. The snippets for all <em>real</em> modes are listed there under the
|
||||
menu. You can select a snippet from the menu to expand it. Since you
|
||||
select manually from the menu, you can expand any snippet. For
|
||||
example, you can expand a snippet defined for <tt class="docutils literal"><span class="pre">python-mode</span></tt> in a
|
||||
<tt class="docutils literal"><span class="pre">c-mode</span></tt> buffer by selecting it from the menu:</p>
|
||||
<img align="right" alt="images/menubar.png" class="align-right" src="images/menubar.png" />
|
||||
<ul class="simple">
|
||||
<li>Condition system is ignored since you select to expand it
|
||||
explicitly.</li>
|
||||
<li>There will be no muliple candidates since they are listed in the
|
||||
menu as different items.</li>
|
||||
</ul>
|
||||
<p>This can be convenient sometimes. However, if you don't like the
|
||||
menubar of Emacs and never use it. You can tell YASnippet don't boring
|
||||
to build a menu by setting <tt class="docutils literal"><span class="pre">yas/use-menu</span></tt> to nil.</p>
|
||||
<p>Another thing to note is that only <em>real</em> modes are listed under the
|
||||
menu. As you know, common snippets can be shared by making up a
|
||||
<em>virtual</em> parent mode. It's too bad if the menu is floored by those
|
||||
<em>virtual</em> modes. So YASnippet only show menus for those <em>real</em>
|
||||
modes. But the snippets fo the <em>virtual</em> modes can still be accessed
|
||||
through the <tt class="docutils literal"><span class="pre">parent</span></tt> submenu of some <em>real</em> mode.</p>
|
||||
<p>YASnippet use a simple way to check whether a mode is <em>real</em> or
|
||||
<em>virtual</em>: <tt class="docutils literal"><span class="pre">(fboundp</span> <span class="pre">mode)</span></tt>. For example, the symbol <tt class="docutils literal"><span class="pre">c-mode</span></tt> is
|
||||
bound to a function while <tt class="docutils literal"><span class="pre">cc-mode</span></tt> is not. But this is not enough,
|
||||
some modes aren't part of Emacs, and maybe when initializing
|
||||
YASnippet, those modes haven't been initialized. So YASnippet also
|
||||
maintain a list of known modes (<tt class="docutils literal"><span class="pre">yas/known-modes</span></tt>). You can add item
|
||||
to that list if you need.</p>
|
||||
</div>
|
||||
<div class="section" id="expanding-from-elisp-code">
|
||||
<h3><a class="toc-backref" href="#id31">Expanding From Elisp Code</a></h3>
|
||||
<p>Sometimes you might want to expand a snippet directly by calling a
|
||||
functin from elisp code. You should call <tt class="docutils literal"><span class="pre">yas/expand-snippet</span></tt>
|
||||
instead of <tt class="docutils literal"><span class="pre">yas/expand</span></tt> in this case.</p>
|
||||
<p>As with expanding from the menubar, condition system and multiple
|
||||
candidates won't exists here. In fact, expanding from menubar has the
|
||||
same effect of evaluating the follow code:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/expand-snippet</span> (<span style="color: #19177C">point</span>) (<span style="color: #19177C">point</span>) <span style="color: #19177C">template</span>)
|
||||
</pre></div>
|
||||
<p>Where <tt class="docutils literal"><span class="pre">template</span></tt> is the template of a snippet. It is never required
|
||||
to belong to any snippet -- you can even make up it on the fly. The
|
||||
1st and 2nd parameter defines the region to be deleted after YASnippet
|
||||
inserted the template. It is used by <tt class="docutils literal"><span class="pre">yas/expand</span></tt> to indicate the
|
||||
region of the key. There's usually no need to delete any region when
|
||||
we are expanding a snippet from elisp code, so passing two <tt class="docutils literal"><span class="pre">(point)</span></tt>
|
||||
is fine. Note only <tt class="docutils literal"><span class="pre">(point)</span></tt> will be fine because the 1st parameter
|
||||
also indicate where to insert and expand the <tt class="docutils literal"><span class="pre">template</span></tt>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="the-syntax-of-the-template">
|
||||
<h1><a class="toc-backref" href="#id32">The Syntax of the Template</a></h1>
|
||||
<p>The syntax of the snippet template is simple but powerful, very
|
||||
similar to TextMate's.</p>
|
||||
<div class="section" id="plain-text">
|
||||
<h2><a class="toc-backref" href="#id33">Plain Text</a></h2>
|
||||
<p>Arbitrary text can be included as the content of a template. They are
|
||||
usually interpreted as plain text, except <tt class="docutils literal"><span class="pre">$</span></tt> and <tt class="docutils literal"><span class="pre">`</span></tt>. You need to
|
||||
use <tt class="docutils literal"><span class="pre">\</span></tt> to escape them: <tt class="docutils literal"><span class="pre">\$</span></tt> and <tt class="docutils literal"><span class="pre">\`</span></tt>. The <tt class="docutils literal"><span class="pre">\</span></tt> itself may also
|
||||
needed to be escaped as <tt class="docutils literal"><span class="pre">\\</span></tt> sometimes.</p>
|
||||
</div>
|
||||
<div class="section" id="embedded-elisp-code">
|
||||
<h2><a class="toc-backref" href="#id34">Embedded elisp code</a></h2>
|
||||
<p>Elisp code can be embedded inside the template. They are written
|
||||
inside back-quotes (<tt class="docutils literal"><span class="pre">`</span></tt>):</p>
|
||||
<p>They 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 <tt class="docutils literal"><span class="pre">c-mode</span></tt> to calculate the header file guard dynamically:</p>
|
||||
<div class="highlight"><pre>#ifndef ${1:_`(upcase (file-name-nondirectory (file-name-sans-extension (buffer-file-name))))`_H_}
|
||||
#define $1
|
||||
|
||||
$0
|
||||
|
||||
#endif /* $1 */
|
||||
</pre></div>
|
||||
<p>From version 0.6.0, snippets expansions are run with some special
|
||||
emacs-lisp variables bound. One of this is <tt class="docutils literal"><span class="pre">yas/selected-text</span></tt>. You
|
||||
can therefore define a snippet like:</p>
|
||||
<div class="highlight"><pre>for ($1;$2;$3) {
|
||||
`yas/selected-text`$0
|
||||
}
|
||||
</pre></div>
|
||||
<p>to "wrap" the selected region inside your recently inserted
|
||||
snippet. Alternatively, you can also customize the variable
|
||||
<tt class="docutils literal"><span class="pre">yas/wrap-around-region</span></tt> to <tt class="docutils literal"><span class="pre">t</span></tt> which will do this automatically.</p>
|
||||
</div>
|
||||
<div class="section" id="tab-stop-fields">
|
||||
<h2><a class="toc-backref" href="#id35">Tab stop fields</a></h2>
|
||||
<p>Tab stops are fields that you can navigate back and forth by <tt class="docutils literal"><span class="pre">TAB</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">S-TAB</span></tt> <a class="footnote-reference" href="#id7" id="id3">[3]</a>. They are written by <tt class="docutils literal"><span class="pre">$</span></tt> followed with a
|
||||
number. <tt class="docutils literal"><span class="pre">$0</span></tt> has the special meaning of the <em>exit point</em> of a
|
||||
snippet. That is the last place to go when you've traveled all the
|
||||
fields. Here's a typical example:</p>
|
||||
<div class="highlight"><pre><div$1>
|
||||
$0
|
||||
</div>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="section" id="placeholder-fields">
|
||||
<h2><a class="toc-backref" href="#id36">Placeholder fields</a></h2>
|
||||
<p>Tab stops can have default values -- a.k.a placeholders. The syntax is
|
||||
like this:</p>
|
||||
<div class="highlight"><pre>${N:default value}
|
||||
</pre></div>
|
||||
<p>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
|
||||
<a class="reference internal" href="#mirrors">mirrors</a> or <a class="reference internal" href="#transformations">transformations</a> for this field.</p>
|
||||
</div>
|
||||
<div class="section" id="id4">
|
||||
<span id="mirrors"></span><h2><a class="toc-backref" href="#id37">Mirrors</a></h2>
|
||||
<p>We refer the tab stops with placeholders as a <em>field</em>. A field can have
|
||||
mirrors. Its mirrors will get updated when you change the text of a
|
||||
field. Here's an example:</p>
|
||||
<div class="highlight"><pre>\begin{${1:enumerate}}
|
||||
$0
|
||||
\end{$1}
|
||||
</pre></div>
|
||||
<p>When you type <tt class="docutils literal"><span class="pre">"document"</span></tt> at <tt class="docutils literal"><span class="pre">${1:enumerate}</span></tt>, the word
|
||||
<tt class="docutils literal"><span class="pre">"document"</span></tt> will also be inserted at <tt class="docutils literal"><span class="pre">\end{$1}</span></tt>. The best
|
||||
explanation is to see the screencast(<a class="reference external" href="http://www.youtube.com/watch?v=vOj7btx3ATg">YouTube</a> or <a class="reference external" href="http://yasnippet.googlecode.com/files/yasnippet.avi">avi video</a>).</p>
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="section" id="mirrors-with-transformations">
|
||||
<span id="transformations"></span><h2><a class="toc-backref" href="#id38">Mirrors with transformations</a></h2>
|
||||
<p>If the default value of a field starts with <tt class="docutils literal"><span class="pre">$</span></tt>, then it is interpreted
|
||||
as the transformation code instead of default value. A transformation
|
||||
is some arbitrary elisp code that will get evaluated in an environment
|
||||
when the variable text is bind to the inputted text of the
|
||||
field. Here's an example for Objective-C:</p>
|
||||
<div class="highlight"><pre>- (${1:id})${2:foo}
|
||||
{
|
||||
return $2;
|
||||
}
|
||||
|
||||
- (void)set${2:$(capitalize text)}:($1)aValue
|
||||
{
|
||||
[$2 autorelease];
|
||||
$2 = [aValue retain];
|
||||
}
|
||||
$0
|
||||
</pre></div>
|
||||
<p>Look at <tt class="docutils literal"><span class="pre">${2:$(capitalize</span> <span class="pre">text)}</span></tt>, it is a transformation instead of
|
||||
a placeholder. The actual placeholder is at the first line:
|
||||
<tt class="docutils literal"><span class="pre">${2:foo}</span></tt>. When you type text in <tt class="docutils literal"><span class="pre">${2:foo}</span></tt>, the transformation
|
||||
will be evaluated and the result will be placed there as the
|
||||
transformated 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.</p>
|
||||
<p>Another example is for <tt class="docutils literal"><span class="pre">rst-mode</span></tt>. 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</p>
|
||||
<div class="highlight"><pre>=====
|
||||
Title
|
||||
=====
|
||||
</pre></div>
|
||||
<p>is a valid title but</p>
|
||||
<div class="highlight"><pre>===
|
||||
Title
|
||||
===
|
||||
</pre></div>
|
||||
<p>is not. Here's an snippet for rst title:</p>
|
||||
<div class="highlight"><pre>${1:$(make-string (string-width text) ?\=)}
|
||||
${1:Title}
|
||||
${1:$(make-string (string-width text) ?\=)}
|
||||
|
||||
$0
|
||||
</pre></div>
|
||||
<table class="docutils footnote" frame="void" id="id5" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>With some minor change, mainly for fixing some trivial bugs.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>This is done when you call <tt class="docutils literal"><span class="pre">yas/initialize</span></tt>.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id7" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id3">[3]</a></td><td>Of course, this can be customized.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section" id="fields-with-transformations">
|
||||
<h2><a class="toc-backref" href="#id39">Fields with transformations</a></h2>
|
||||
<p>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.</p>
|
||||
<p>The syntax is also a tiny bit different, so that the parser can
|
||||
distinguish between fields and mirrors. In the following example</p>
|
||||
<div class="highlight"><pre>#define "${1:mydefine$(upcase yas/text)}"
|
||||
</pre></div>
|
||||
<p><tt class="docutils literal"><span class="pre">mydefine</span></tt> gets automatically upcased to <tt class="docutils literal"><span class="pre">MYDEFINE</span></tt> once you enter
|
||||
the field. As you type text, it gets filtered through the
|
||||
transformation every time.</p>
|
||||
<p>Note that this is differentiated from a mirror with a transformation
|
||||
by the existance of extra text between the <tt class="docutils literal"><span class="pre">:</span></tt> and the
|
||||
transformation's <tt class="docutils literal"><span class="pre">$</span></tt>. If you don't want this extra-text, you can use
|
||||
two <tt class="docutils literal"><span class="pre">$</span></tt>'s instead.</p>
|
||||
<div class="highlight"><pre>#define "${1:$$(upcase yas/text)}"
|
||||
</pre></div>
|
||||
<p>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
|
||||
<tt class="docutils literal"><span class="pre">true</span></tt>. As a consequence, the auto-deletion behaviour of normal
|
||||
fields does not take place. This is by design.</p>
|
||||
</div>
|
||||
<div class="section" id="choosing-fields-value-from-a-list">
|
||||
<h2><a class="toc-backref" href="#id40">Choosing fields value from a list</a></h2>
|
||||
<p>As mentioned, the field transformation is invoked just after you enter
|
||||
the field, and with some useful variables bound, notably
|
||||
<tt class="docutils literal"><span class="pre">yas/field-modified-p</span></tt> and <tt class="docutils literal"><span class="pre">yas/moving-away-p</span></tt>. Because of this
|
||||
feature you can place a transformation in the primary field that lets
|
||||
you select default values for it.</p>
|
||||
<p>The <tt class="docutils literal"><span class="pre">yas/choose-value</span></tt> does this work for you. For example:</p>
|
||||
<div class="highlight"><pre><div align="${2:$$(yas/choose-value '("right" "center" "left"))}">
|
||||
$0
|
||||
</div>
|
||||
</pre></div>
|
||||
<p>See the definition of <tt class="docutils literal"><span class="pre">yas/choose-value</span></tt> to see how it was written
|
||||
using the two variables. Also check out <tt class="docutils literal"><span class="pre">yas/verify-value</span></tt> for
|
||||
another neat trick.</p>
|
||||
</div>
|
||||
<div class="section" id="nested-placeholder-fields">
|
||||
<h2><a class="toc-backref" href="#id41">Nested placeholder fields</a></h2>
|
||||
<p>From version 0.6 on, you can also have nested placeholders of the type:</p>
|
||||
<div class="highlight"><pre><div${1: id="${2:some_id}"}>$0</div>
|
||||
</pre></div>
|
||||
<p>This allows you to choose if you want to give this <tt class="docutils literal"><span class="pre">div</span></tt> an <tt class="docutils literal"><span class="pre">id</span></tt>
|
||||
attribute. If you tab forward after expanding it will let you change
|
||||
"some_id" to whatever you like. Alternatively, you can just press
|
||||
<tt class="docutils literal"><span class="pre">C-d</span></tt> (which executes <tt class="docutils literal"><span class="pre">yas/skip-and-clear-or-delete-char</span></tt>) and go
|
||||
straight to the exit marker.</p>
|
||||
<p>By the way, <tt class="docutils literal"><span class="pre">C-d</span></tt> will only clear the field if you cursor is at the
|
||||
beginning of the field <em>and</em> it hasn't been changed yet. Otherwise, it
|
||||
performs the normal Emacs <tt class="docutils literal"><span class="pre">delete-char</span></tt> command.</p>
|
||||
</div>
|
||||
<div class="section" id="indenting">
|
||||
<h2><a class="toc-backref" href="#id42">Indenting</a></h2>
|
||||
<p>Many people miss the indenting feature of smart-snippet: when you
|
||||
place a <tt class="docutils literal"><span class="pre">$></span></tt> in your snippet, an <tt class="docutils literal"><span class="pre">(indent-according-to-mode)</span></tt> will
|
||||
be executed there to indent the line. So you'll not need to hard-code
|
||||
the indenting in the snippet template, and it will be very convenient
|
||||
when you need to work with several different project where coding
|
||||
styles are different.</p>
|
||||
<p>The reason why this feature wasn't added to YASnippet until after
|
||||
0.5.6 is that it doesn't work well for all modes. In some cases
|
||||
(e.g. python-mode), calling <tt class="docutils literal"><span class="pre">indent-according-to-mode</span></tt> will break
|
||||
the overlays created by YASnippet.</p>
|
||||
<p>However, since many people asked for this feature, I finally added
|
||||
this to YASnippet. Here's an example of the usage:</p>
|
||||
<div class="highlight"><pre>for (${int i = 0}; ${i < 10}; ${++i})
|
||||
{$>
|
||||
$0$>
|
||||
}$>
|
||||
</pre></div>
|
||||
<p>In 0.6.0 You should <strong>not</strong> need to use this feature although it's
|
||||
supported for backward compatibility. Just set <tt class="docutils literal"><span class="pre">yas/indent-line</span></tt> to
|
||||
<tt class="docutils literal"><span class="pre">'auto</span></tt>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,963 +0,0 @@
|
||||
=========================
|
||||
How to define a snippet ?
|
||||
=========================
|
||||
|
||||
:Author: pluskid, joaotavora
|
||||
:Contact: pluskid@gmail.com
|
||||
:Date: 2009-07-24
|
||||
|
||||
.. contents::
|
||||
|
||||
The most convenient way to define snippets for YASnippet is to put
|
||||
them in a directory arranged by the mode and use
|
||||
``yas/load-directory`` to load them.
|
||||
|
||||
However, this might slow down the Emacs startup speed if you have many
|
||||
snippets. You can use ``yas/define-snippets`` to define a bunch of
|
||||
snippets for a perticular mode. But this is hard to maintain! So,
|
||||
there's a better way: define your snippets in directory and use
|
||||
``yas/compile-bundle`` to compile it into a bundle file when you
|
||||
modified your snippets.
|
||||
|
||||
The release bundle of YASnippet is produced by
|
||||
``yas/compile-bundle``. The bundle use ``yas/define-snippets`` to
|
||||
define snippets. This avoid the IO and parsing overhead when loading
|
||||
snippets.
|
||||
|
||||
Finally, you can use ``yas/define`` to define a single snippet at your
|
||||
convenience. I ofthen use this to do some testing.
|
||||
|
||||
Define snippets in files
|
||||
========================
|
||||
|
||||
Directory hierarchy
|
||||
-------------------
|
||||
|
||||
Here's the directory hierarchy of the ``snippets`` directory comes
|
||||
with YASnippet:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
snippets
|
||||
`-- text-mode/
|
||||
|-- cc-mode/
|
||||
| |-- c++-mode/
|
||||
| | |-- beginend
|
||||
| | |-- class
|
||||
| | `-- using
|
||||
| |-- c-mode/
|
||||
| | `-- fopen
|
||||
| |-- do
|
||||
| |-- for
|
||||
| |-- if
|
||||
| |-- inc
|
||||
| |-- inc.1
|
||||
| |-- main
|
||||
| |-- once
|
||||
| `-- struct
|
||||
|-- css-mode/
|
||||
| |-- background
|
||||
| |-- background.1
|
||||
| `-- border
|
||||
|-- email
|
||||
|-- html-mode/
|
||||
| |-- div
|
||||
| |-- doctype
|
||||
| |-- doctype.xhml1
|
||||
| |-- doctype.xhtml1_1
|
||||
| |-- doctype.xhtml1_strict
|
||||
| `-- doctype.xhtml1_transitional
|
||||
|-- objc-mode/
|
||||
| `-- prop
|
||||
|-- perl-mode/
|
||||
| |-- cperl-mode/
|
||||
| |-- eval
|
||||
| |-- for
|
||||
| |-- fore
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- ifee
|
||||
| |-- sub
|
||||
| |-- unless
|
||||
| |-- while
|
||||
| |-- xfore
|
||||
| |-- xif
|
||||
| |-- xunless
|
||||
| `-- xwhile
|
||||
|-- python-mode/
|
||||
| |-- __
|
||||
| |-- class
|
||||
| |-- def
|
||||
| |-- for
|
||||
| |-- ifmain
|
||||
| `-- while
|
||||
|-- rst-mode/
|
||||
| |-- chapter
|
||||
| |-- section
|
||||
| `-- title
|
||||
|-- ruby-mode/
|
||||
| |-- #
|
||||
| |-- =b
|
||||
| |-- Comp
|
||||
| |-- all
|
||||
| |-- am
|
||||
| |-- any
|
||||
| |-- app
|
||||
| |-- bm
|
||||
| |-- case
|
||||
| |-- cla
|
||||
| |-- classify
|
||||
| |-- cls
|
||||
| |-- collect
|
||||
| |-- dee
|
||||
| |-- deli
|
||||
| |-- det
|
||||
| |-- ea
|
||||
| |-- eac
|
||||
| |-- eai
|
||||
| |-- eav
|
||||
| |-- eawi
|
||||
| |-- forin
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- inject
|
||||
| |-- mm
|
||||
| |-- r
|
||||
| |-- rb
|
||||
| |-- reject
|
||||
| |-- req
|
||||
| |-- rreq
|
||||
| |-- rw
|
||||
| |-- select
|
||||
| |-- w
|
||||
| |-- y
|
||||
| `-- zip
|
||||
`-- time
|
||||
|
||||
Snippet definitions are put in plain text files. They are arranged by
|
||||
subdirectories. For example, snippets for ``c-mode`` are put in the
|
||||
``c-mode`` directory.
|
||||
|
||||
The parent directory acts as the *parent mode*. This is the way of
|
||||
YASnippet to share snippet definitions among different modes. As you
|
||||
can see above, ``c-mode`` and ``c++-mode`` share the same parents
|
||||
``cc-mode``, while all modes are derived from ``text-mode``. This can
|
||||
be also used to as an *alias* -- ``cperl-mode`` is an empty directory
|
||||
whose parent is ``perl-mode``.
|
||||
|
||||
File names act as the snippet trigger key. Note files starting with a
|
||||
dot (``.``) are ignored.
|
||||
|
||||
File content
|
||||
------------
|
||||
|
||||
A file defining a snippet may just contain the template for the
|
||||
snippet. Optionally it can also contains some meta data for the
|
||||
snippet as well as comments.
|
||||
|
||||
Generally speaking, if the file contains a line of ``# --``, then all
|
||||
contents above that line are considered as meta data and comments;
|
||||
below are template. Or else the whole file content is considered as
|
||||
the template.
|
||||
|
||||
Here's a typical example:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
#contributor : pluskid <pluskid@gmail.com>
|
||||
#name : __...__
|
||||
# --
|
||||
__${init}__
|
||||
|
||||
Meta data are specified in the syntax of
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
#data-name : data value
|
||||
|
||||
Any other text above ``# --`` is considered as comment and
|
||||
ignored. Here's a list of currently supported meta data:
|
||||
|
||||
.. image:: images/group.png
|
||||
:align: right
|
||||
|
||||
* ``name``: The name of the snippet. This is a one-line description of
|
||||
the snippet. It will be displayed in the menu. So it's a good idea
|
||||
to select a descriptive name fo a snippet -- especially
|
||||
distinguishable among similar snippets.
|
||||
* ``contributor``: The contributor of the snippet.
|
||||
* ``condition``: The condition of the snippet. This is a piece of
|
||||
elisp code. If a snippet has a condition, then it will only be
|
||||
expanded when the condition code evaluate to some non-nil value.
|
||||
* ``key``: The key to expand the snippet. 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.
|
||||
* ``group``: The snippets for a mode can be grouped. Grouped snippets
|
||||
will be grouped in sub-menu. This is useful if one has too many
|
||||
snippets for a mode which will make the menu too long. ``group``
|
||||
property only affect menu construction (See `The Menu`_). Refer to
|
||||
the snippets for ``ruby-mode`` for examples. 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.
|
||||
|
||||
Quickly finding/defining snippets
|
||||
---------------------------------
|
||||
|
||||
From version 0.6 upwards there are two ways you can quickly find a
|
||||
snippet file. Once you find this file it will be set to
|
||||
``snippet-mode`` (see ahead)
|
||||
|
||||
* ``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``.
|
||||
|
||||
* ``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.
|
||||
|
||||
|
||||
Using the ``snippet-mode`` major mode
|
||||
-------------------------------------
|
||||
|
||||
From version 0.6 upwards 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 making snippets: ``vars``, ``field`` and
|
||||
``mirror``.
|
||||
|
||||
Define snippets using elisp code
|
||||
--------------------------------
|
||||
|
||||
As I mentioned above, you can define snippets directly by writing
|
||||
elisp code.
|
||||
|
||||
yas/define-snippets
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The basic syntax of ``yas/define-snippets`` is
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define-snippets MODE SNIPPETS &optional PARENT)
|
||||
|
||||
The parameters are self-descriptive. If you specify a ``PARENT``, then
|
||||
the snippets of the parents may be shared by ``MODE``. Note if you use
|
||||
this function several times, the later specified ``PARENT`` will
|
||||
overwrite the original one. However, not specifying a ``PARENT`` won't
|
||||
erase the original parent.
|
||||
|
||||
The ``SNIPPETS`` parameter is a list of snippet definitions. Each
|
||||
element should have the following form:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(KEY TEMPLATE NAME CONDITION GROUP)
|
||||
|
||||
The ``NAME``, ``CONDITION`` and ``GROUP`` can be omitted if you don't
|
||||
want to provide one. Here's an example:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define-snippets 'c++-mode
|
||||
'(
|
||||
("using" "using namespace ${std};
|
||||
$0" "using namespace ... " nil)
|
||||
("class" "class ${1:Name}
|
||||
{
|
||||
public:
|
||||
$1($2);
|
||||
virtual ~$1();
|
||||
};" "class ... { ... }" nil)
|
||||
("beginend" "${1:v}.begin(), $1.end" "v.begin(), v.end()" nil)
|
||||
)
|
||||
'cc-mode)
|
||||
|
||||
The example above is auto-generated code by ``yas/compile-bundle``.
|
||||
|
||||
yas/compile-bundle
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``yas/compile-bundle`` can be used to parse the snippets from a
|
||||
directory hierarchy and translate them into the elisp form. The
|
||||
translated code is faster to load. Further more, the generated bundle
|
||||
is a stand-alone file not depending on ``yasnippet.el``. The released
|
||||
bundles of YASnippet are all generated this way.
|
||||
|
||||
The basic syntax of ``yas/compile-bundle`` is
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/compile-bundle &optional yasnippet yasnippet-bundle snippet-roots code dropdown)
|
||||
|
||||
As you can see, all the parameters are optional. The default values
|
||||
for those parameters are convenient for me to produce the default
|
||||
release bundle:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/compile-bundle "yasnippet.el"
|
||||
"./yasnippet-bundle.el"
|
||||
'("snippets")
|
||||
"(yas/initialize)"
|
||||
"dropdown-list.el")
|
||||
|
||||
The ``snippet-roots`` can be a list of root directories. This is
|
||||
useful when you have multiple snippet directories (maybe from other
|
||||
users). The ``code`` parameter can be used to specify your own
|
||||
customization code instead of the default ``(yas/initialize)``. For
|
||||
example, you can set ``yas/trigger-key`` to ``(kbd "SPC")`` here if
|
||||
you like.
|
||||
|
||||
From release 0.6 you have to specify the ``dropdown-list.el`` file if
|
||||
you want it to be a part of the generated bundle.
|
||||
|
||||
yas/define
|
||||
~~~~~~~~~~
|
||||
|
||||
The basic syntax for ``yas/define`` is
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define mode key template &optional name condition group)
|
||||
|
||||
This is only a syntax sugar for
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define-snippets mode
|
||||
(list (list key template name condition group)))
|
||||
|
||||
The strategy to select a snippet
|
||||
================================
|
||||
|
||||
When user press the ``yas/trigger-key``, YASnippet try to find a
|
||||
proper snippet to expand. The strategy to find such a snippet is
|
||||
explained here.
|
||||
|
||||
Finding the key
|
||||
---------------
|
||||
|
||||
YASnippet search from current point backward trying to find the
|
||||
snippet to be expanded. The default searching strategy is quite
|
||||
powerful. For example, in ``c-mode``, ``"bar"``, ``"foo_bar"``,
|
||||
``"#foo_bar"`` can all be recognized as a template key. Further more,
|
||||
the searching is in that order. In other words, if ``"bar"`` is found
|
||||
to be a key to some *valid* snippet, then ``"foo_bar"`` and
|
||||
``"#foobar"`` won't be searched.
|
||||
|
||||
However, this strategy can also be customized easily from the
|
||||
``yas/key-syntaxes`` variable. It is a list of syntax rules, the
|
||||
default value is ``("w" "w_" "w_." "^ ")``. Which means search the
|
||||
following thing until found one:
|
||||
|
||||
* a word.
|
||||
* a symbol. In lisp, ``-`` and ``?`` can all be part of a symbol.
|
||||
* a sequence of characters of either word, symbol or punctuation.
|
||||
* a sequence of characters of non-whitespace characters.
|
||||
|
||||
But you'd better keep the default value unless you understand what
|
||||
Emacs's syntax rule mean.
|
||||
|
||||
The condition system
|
||||
--------------------
|
||||
|
||||
I write forked snippet.el to make the smart-snippet.el. I call it
|
||||
*smart*-snippet because a condition can be attached to a snippet. This
|
||||
is really a good idea. However, writing condition for a snippet
|
||||
usually needs good elisp and Emacs knowledge, so it is strange to many
|
||||
user.
|
||||
|
||||
Later I write YASnippet and persuade people to use it instead of
|
||||
smart-snippet.el. However, some user still love smart-snippet because
|
||||
it is smart. So I make YASnippet smart. Even smarter than
|
||||
smart-snippet.el. :p
|
||||
|
||||
Consider this scenario: you are an old Emacs hacker. You like the
|
||||
abbrev-way and set ``yas/trigger-key`` to ``(kbd "SPC")``. However,
|
||||
you don't want ``if`` to be expanded as a snippet when you are typing
|
||||
in a comment block or a string (e.g. in ``python-mode``).
|
||||
|
||||
It's OK, just specify the condition for ``if`` to be ``(not
|
||||
(python-in-string/comment))``. But how about ``while``, ``for``,
|
||||
etc. ? Writing the same condition for all the snippets is just
|
||||
boring. So YASnippet introduce a buffer local variable
|
||||
``yas/buffer-local-condition``. You can set this variable to ``(not
|
||||
(python-in-string/comment))`` in ``python-mode-hook``. There's no way
|
||||
to do this in smart-snippet.el!
|
||||
|
||||
Then, what if you really want some snippet even in comment? This is
|
||||
also possible! But let's stop telling the story and look at the rules:
|
||||
|
||||
* If ``yas/buffer-local-condition`` evaluate to nil, snippet won't be
|
||||
expanded.
|
||||
* If it evaluate to the a cons cell where the ``car`` is the symbol
|
||||
``require-snippet-condition`` and the ``cdr`` is a symbol (let's
|
||||
call it ``requirement``):
|
||||
|
||||
* If the snippet has no condition, then it won't be expanded.
|
||||
* If the snippet has a condition but evaluate to nil or error
|
||||
occured during evaluation, it won't be expanded.
|
||||
* If the snippet has a condition that evaluate to non-nil (let's
|
||||
call it ``result``):
|
||||
|
||||
* If ``requirement`` is ``t``, the snippet is ready to be
|
||||
expanded.
|
||||
* If ``requirement`` is ``eq`` to ``result``, the snippet is ready
|
||||
to be expanded.
|
||||
* Otherwise the snippet won't be expanded.
|
||||
|
||||
* If it evaluate to other non-nil value:
|
||||
|
||||
* If the snippet has no condition, or has a condition that evaluate
|
||||
to non-nil, it is ready to be expanded.
|
||||
* Otherwise, it won't be expanded.
|
||||
|
||||
So set ``yas/buffer-local-condition`` like this
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(add-hook 'python-mode-hook
|
||||
'(lambda ()
|
||||
(setq yas/buffer-local-condition
|
||||
'(if (python-in-string/comment)
|
||||
'(require-snippet-condition . force-in-comment)
|
||||
t))))
|
||||
|
||||
And specify the condition for a snippet that you're going to expand in
|
||||
comment to be evaluated to the symbol ``force-in-comment``. Then it
|
||||
can be expanded as you expected, while other snippets like ``if``
|
||||
still can't expanded in comment.
|
||||
|
||||
Multiple snippet with the same key
|
||||
----------------------------------
|
||||
|
||||
There can be multiple snippet bind to the same key. If you define a
|
||||
snippet with a key that is already used, you'll overwrite the original
|
||||
snippet definition. However, you can add a different *postfix* to the
|
||||
key.
|
||||
|
||||
In general, the *extension* (consider a file name) is *ignored* when
|
||||
defining a snippet. So ``def``, ``def.1`` and ``def.mine`` will all be
|
||||
valid candidates when the key is ``def``.
|
||||
|
||||
When there are multiple candidates, YASnippet will let you select
|
||||
one. The UI for selecting multiple candidate can be
|
||||
customized. There're two variable related:
|
||||
|
||||
From version 0.6 of YASnippet this has changed significantly. A new
|
||||
customization variable, called ``yas/prompt-functions`` defines your
|
||||
preferred method of being prompted for snippets.
|
||||
|
||||
You can customize it with ``M-x customize-variable RET
|
||||
yas/prompt-functions RET``. Alternatively you can put in your
|
||||
emacs-file:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(setq yas/prompt-functions '(yas/x-prompt yas/dropdown-prompt))
|
||||
|
||||
Currently there are some alternatives solution with YASnippet.
|
||||
|
||||
.. image:: images/popup-menu.png
|
||||
:align: right
|
||||
|
||||
Use the X window system
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The function ``yas/x-prompt`` can be used to show a popup menu for you
|
||||
to select. This menu will be part of you native window system widget,
|
||||
which means:
|
||||
|
||||
* It usually looks beautiful. E.g. when you compile Emacs with gtk
|
||||
support, this menu will be rendered with your gtk theme.
|
||||
* Emacs have little control over it. E.g. you can't use ``C-n``,
|
||||
``C-p`` to navigate.
|
||||
* This function can't be used when in a terminal.
|
||||
|
||||
Use built-in Emacs selection methods
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can use functions ``yas/completing-prompt`` for the classic emacs
|
||||
completion method or ``yas/ido-prompt`` for a much nicer looking
|
||||
method. The best way is to try it. This works in a terminal.
|
||||
|
||||
.. image:: images/idrop-menu.png
|
||||
:align: center
|
||||
|
||||
Use ``dropdown-menu.el``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The function ``yas/dropdown-prompt`` can also be placed in the
|
||||
``yas/prompt-functions`` list.
|
||||
|
||||
.. image:: images/dropdown-menu.png
|
||||
:align: right
|
||||
|
||||
Originally, only the above two function is available in
|
||||
YASnippet. They are difficult to use -- especially in a
|
||||
terminal. Until later Jaeyoun Chung show me his ``dropdown-menu.el``,
|
||||
I say wow! It's wonderful!
|
||||
|
||||
* It works in both window system and terminal.
|
||||
* It is customizable, you can use ``C-n``, ``C-p`` to navigate, ``q``
|
||||
to quite and even press ``6`` as a shortcut to select the 6th
|
||||
candidate.
|
||||
|
||||
So I added ``yas/dropdown-list-popup-for-template`` to support
|
||||
``dropdown-list.el``. And upload ``dropdown-list.el`` to YASnippet
|
||||
hompage for an optional download (since Jaeyoun didn't provide a URL).
|
||||
|
||||
Then finally, in 0.4.0, I included a copy of the content of
|
||||
``dropdown-list.el`` [1]_ in ``yasnippet.el`` and made it the default
|
||||
way for selecting multiple candidates.
|
||||
|
||||
However, the original functions are still there, you can still use this
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(setq yas/window-system-popup-function
|
||||
'yas/x-popup-menu-for-template)
|
||||
|
||||
if you prefer a *modern* UI. :)
|
||||
|
||||
The Trigger Key
|
||||
---------------
|
||||
|
||||
YASnippet is implemented as a minor-mode (``yas/minor-mode``). The
|
||||
trigger key ``yas/trigger-key`` is defined in ``yas/minor-mode-map``
|
||||
to call ``yas/expand`` to try to expand a snippet.
|
||||
|
||||
The Minor Mode
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. image:: images/minor-mode-indicator.png
|
||||
:align: left
|
||||
|
||||
When ``yas/minor-mode`` is enabled, the trigger key will take
|
||||
effect. The default key is ``(kbd "TAB")``, however, you can freely
|
||||
set it to some other key.
|
||||
|
||||
In version 0.5, YASnippet add a hook to
|
||||
``after-change-major-mode-hook`` to enable ``yas/minor-mode`` [2]_ in
|
||||
every buffer. This works fine for most modes, however, some mode
|
||||
doesn't follow the Emacs convention and doens't call this hook. You
|
||||
can either explicitly hook for those mode or just add it to
|
||||
``yas/extra-mode-hooks`` to let YASnippet do it for you:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(require 'yasnippet)
|
||||
(add-to-list 'yas/extra-mode-hooks
|
||||
'ruby-mode-hook)
|
||||
(yas/initialize)
|
||||
|
||||
Note that **should** be put after ``(require 'yasnippet)`` and before
|
||||
``(yas/initialize)``. Further more, you may report it to me, I'll add
|
||||
that to the default value.
|
||||
|
||||
In version 0.6, just use ``yas/global-mode`` to enable YASnippet in
|
||||
all major modes. Or put ``yas/minor-mode-on`` in that modes hook. See
|
||||
the `FAQ <faq.html>`_.
|
||||
|
||||
The Fallback
|
||||
~~~~~~~~~~~~
|
||||
|
||||
If ``yas/expand`` failed to find any suitable snippet to expand, it
|
||||
will disable the minor mode temporarily and find if there's any other
|
||||
command bind the ``yas/trigger-key``. If found, the command will be
|
||||
called. Usually this works very well -- when there's a snippet, expand
|
||||
it, otherwise, call whatever command originally bind to the trigger
|
||||
key.
|
||||
|
||||
However, you can change this behavior by customizing the
|
||||
``yas/fallback-behavior`` variable. If you set this variable to
|
||||
``'return-nil``, it will return ``nil`` instead of trying to call the
|
||||
*original* command when no snippet is found. This is useful when you
|
||||
would like YASnippet to work with other extensions,
|
||||
e.g. ``hippie-expand``. I'm also glad to tell you that integration
|
||||
with ``hippie-expand`` is already included in YASnippet.
|
||||
|
||||
Integration with ``hippie-expand``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To integrate with ``hippie-expand``, just put
|
||||
``yas/hippie-try-expand`` in
|
||||
``hippie-expand-try-functions-list``. Personally I would like to put
|
||||
in front of the list, but it can be put anywhere you prefer.
|
||||
|
||||
Other way to select a snippet
|
||||
-----------------------------
|
||||
|
||||
When you use the trigger key (so ``yas/expand``) to expand a snippet,
|
||||
the key for the snippet is deleted before the template for the snippet
|
||||
is inserted.
|
||||
|
||||
However, there're other ways to insert a snippet.
|
||||
|
||||
``yas/insert-snippet``
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The command ``M-x yas/insert-snippet`` lets you insert snippets at
|
||||
point *for you current major mode*. It prompts you for the snippet
|
||||
key first, and then for a snippet template if more than one template
|
||||
exists for the same key.
|
||||
|
||||
The list presented contains the snippets that can be inserted at
|
||||
point, according to the condition system. If you want to see all
|
||||
applicable snippets for the major mode, prefix this command with
|
||||
``C-u``.
|
||||
|
||||
The prompting methods used are again controlled by
|
||||
``yas/prompt-functions``.
|
||||
|
||||
The Menu
|
||||
~~~~~~~~
|
||||
|
||||
YASnippet will setup a menu just after the *Buffers* Menu in the
|
||||
menubar. The snippets for all *real* modes are listed there under the
|
||||
menu. You can select a snippet from the menu to expand it. Since you
|
||||
select manually from the menu, you can expand any snippet. For
|
||||
example, you can expand a snippet defined for ``python-mode`` in a
|
||||
``c-mode`` buffer by selecting it from the menu:
|
||||
|
||||
.. image:: images/menubar.png
|
||||
:align: right
|
||||
|
||||
* Condition system is ignored since you select to expand it
|
||||
explicitly.
|
||||
* There will be no muliple candidates since they are listed in the
|
||||
menu as different items.
|
||||
|
||||
This can be convenient sometimes. However, if you don't like the
|
||||
menubar of Emacs and never use it. You can tell YASnippet don't boring
|
||||
to build a menu by setting ``yas/use-menu`` to nil.
|
||||
|
||||
Another thing to note is that only *real* modes are listed under the
|
||||
menu. As you know, common snippets can be shared by making up a
|
||||
*virtual* parent mode. It's too bad if the menu is floored by those
|
||||
*virtual* modes. So YASnippet only show menus for those *real*
|
||||
modes. But the snippets fo the *virtual* modes can still be accessed
|
||||
through the ``parent`` submenu of some *real* mode.
|
||||
|
||||
YASnippet use a simple way to check whether a mode is *real* or
|
||||
*virtual*: ``(fboundp mode)``. For example, the symbol ``c-mode`` is
|
||||
bound to a function while ``cc-mode`` is not. But this is not enough,
|
||||
some modes aren't part of Emacs, and maybe when initializing
|
||||
YASnippet, those modes haven't been initialized. So YASnippet also
|
||||
maintain a list of known modes (``yas/known-modes``). You can add item
|
||||
to that list if you need.
|
||||
|
||||
Expanding From Elisp Code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sometimes you might want to expand a snippet directly by calling a
|
||||
functin from elisp code. You should call ``yas/expand-snippet``
|
||||
instead of ``yas/expand`` in this case.
|
||||
|
||||
As with expanding from the menubar, condition system and multiple
|
||||
candidates won't exists here. In fact, expanding from menubar has the
|
||||
same effect of evaluating the follow code:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/expand-snippet (point) (point) template)
|
||||
|
||||
Where ``template`` is the template of a snippet. It is never required
|
||||
to belong to any snippet -- you can even make up it on the fly. The
|
||||
1st and 2nd parameter defines the region to be deleted after YASnippet
|
||||
inserted the template. It is used by ``yas/expand`` to indicate the
|
||||
region of the key. There's usually no need to delete any region when
|
||||
we are expanding a snippet from elisp code, so passing two ``(point)``
|
||||
is fine. Note only ``(point)`` will be fine because the 1st parameter
|
||||
also indicate where to insert and expand the ``template``.
|
||||
|
||||
The Syntax of the Template
|
||||
==========================
|
||||
|
||||
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 elisp code
|
||||
-------------------
|
||||
|
||||
Elisp code can be embedded inside the template. They are written
|
||||
inside back-quotes (`````):
|
||||
|
||||
They 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.0, 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`` [3]_. 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 default value of a field starts with ``$``, then it is interpreted
|
||||
as the transformation code instead of default value. A transformation
|
||||
is some arbitrary elisp code that will get evaluated in an environment
|
||||
when the variable text is bind to the inputted text of the
|
||||
field. 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 transformation instead of
|
||||
a placeholder. The actual placeholder 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
|
||||
transformated 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
|
||||
|
||||
.. [1] With some minor change, mainly for fixing some trivial bugs.
|
||||
.. [2] This is done when you call ``yas/initialize``.
|
||||
.. [3] Of course, this can be customized.
|
||||
|
||||
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 this is differentiated from a mirror with a transformation
|
||||
by the existance of 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
|
||||
---------------------------------
|
||||
|
||||
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. Also check out ``yas/verify-value`` for
|
||||
another neat trick.
|
||||
|
||||
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.
|
||||
|
||||
Indenting
|
||||
---------
|
||||
|
||||
Many people miss the indenting feature of smart-snippet: when you
|
||||
place a ``$>`` in your snippet, an ``(indent-according-to-mode)`` will
|
||||
be executed there to indent the line. So you'll not need to hard-code
|
||||
the indenting in the snippet template, and it will be very convenient
|
||||
when you need to work with several different project where coding
|
||||
styles are different.
|
||||
|
||||
The reason why this feature wasn't added to YASnippet until after
|
||||
0.5.6 is that it doesn't work well for all modes. In some cases
|
||||
(e.g. python-mode), calling ``indent-according-to-mode`` will break
|
||||
the overlays created by YASnippet.
|
||||
|
||||
However, since many people asked for this feature, I finally added
|
||||
this to YASnippet. Here's an example of the usage:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
for (${int i = 0}; ${i < 10}; ${++i})
|
||||
{$>
|
||||
$0$>
|
||||
}$>
|
||||
|
||||
In 0.6.0 You should **not** need to use this feature although it's
|
||||
supported for backward compatibility. Just set ``yas/indent-line`` to
|
||||
``'auto``.
|
||||
|
10
doc/faq.html
10
doc/faq.html
@ -3,7 +3,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Frequently Asked Questions</title>
|
||||
<meta name="author" content="pluskid" />
|
||||
<meta name="date" content="2008-03-20" />
|
||||
@ -23,7 +23,13 @@
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="define_snippet.html">Howto</a>
|
||||
<a title="" href="snippet-organization.html">Organize</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-expansion.html">Expand</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-development.html">Write</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Yet Another Snippet extension</title>
|
||||
<meta name="author" content="pluskid" />
|
||||
<meta name="date" content="2008-03-20" />
|
||||
@ -23,7 +23,13 @@
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="define_snippet.html">Howto</a>
|
||||
<a title="" href="snippet-organization.html">Organize</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-expansion.html">Expand</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-development.html">Write</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
@ -49,8 +55,9 @@
|
||||
<li><a class="reference internal" href="#normal-install" id="id4">Normal Install</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#customization-group" id="id5">Customization group</a></li>
|
||||
<li><a class="reference internal" href="#bugs-contribution-and-support" id="id6">Bugs, Contribution and Support</a></li>
|
||||
<li><a class="reference internal" href="#how-to-use-yasnippet" id="id5">How to use YASnippet</a></li>
|
||||
<li><a class="reference internal" href="#customization-group" id="id6">Customization group</a></li>
|
||||
<li><a class="reference internal" href="#bugs-contribution-and-support" id="id7">Bugs, Contribution and Support</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>Yasnippet is a template system for emacs. It allows you to type a
|
||||
@ -113,8 +120,35 @@ customization group.</p>
|
||||
<img align="right" alt="images/customization-group.png" class="align-right" src="images/customization-group.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="how-to-use-yasnippet">
|
||||
<h1><a class="toc-backref" href="#id5">How to use YASnippet</a></h1>
|
||||
<p>Since version 0.6, YASnippet contains more functionality. You don't
|
||||
need to know all of it to use it sucessfully, but you it can improve
|
||||
your snippeting experience.</p>
|
||||
<p>Hence this section has been split into separate documents:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><a class="reference external" href="snippet-organization.html">Organizing snippets</a></li>
|
||||
</ol>
|
||||
<p>Describes ways to organize your snippets in the hard disk, or not
|
||||
organize them at all and just use plain old elisp.</p>
|
||||
<p>Also explains how to use the YASnippet menu to explore and learn new
|
||||
snippets.</p>
|
||||
<ol class="arabic simple" start="2">
|
||||
<li><a class="reference external" href="snippet-expansion.html">Controlling snippet expansion</a></li>
|
||||
</ol>
|
||||
<p>Maybe, you'll want some snippets to be expanded in a particular mode,
|
||||
or only under certain conditions. Also you might want snippets to wrap
|
||||
themselves around a region of selected text, use a direct keybinding,
|
||||
control indenting, etc...</p>
|
||||
<ol class="arabic simple" start="3">
|
||||
<li><a class="reference external" href="snippet-development.html">Defining your own snippets</a></li>
|
||||
</ol>
|
||||
<p>Describes the YASnippet definition syntax, which is similar, but not
|
||||
equivalent to Textmate's. Includes a section about converting Textmate
|
||||
snippets.</p>
|
||||
</div>
|
||||
<div class="section" id="customization-group">
|
||||
<h1><a class="toc-backref" href="#id5">Customization group</a></h1>
|
||||
<h1><a class="toc-backref" href="#id6">Customization group</a></h1>
|
||||
<p>From version 0.6 onwards, there is a customization group that you can
|
||||
access with:</p>
|
||||
<p><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">customize-group</span> <span class="pre">RET</span> <span class="pre">yasnippet</span> <span class="pre">RET</span></tt></p>
|
||||
@ -125,7 +159,7 @@ use, whether to expand snippets inside snippets, etc...</p>
|
||||
to explain what it does.</p>
|
||||
</div>
|
||||
<div class="section" id="bugs-contribution-and-support">
|
||||
<h1><a class="toc-backref" href="#id6">Bugs, Contribution and Support</a></h1>
|
||||
<h1><a class="toc-backref" href="#id7">Bugs, Contribution and Support</a></h1>
|
||||
<ul class="simple">
|
||||
<li>If you find a bug, please report it at <a class="reference external" href="http://code.google.com/p/yasnippet/issues/list">Issue List</a>.</li>
|
||||
<li>If you have problem using YASnippet, or have some new ideas, please
|
||||
|
@ -24,7 +24,6 @@ is much cleaner and more powerful than smart-snippet.
|
||||
|
||||
.. _smart-snippet: http://code.google.com/p/smart-snippet/
|
||||
|
||||
|
||||
Video Demo
|
||||
==========
|
||||
|
||||
@ -84,6 +83,36 @@ customization group.
|
||||
.. image:: images/customization-group.png
|
||||
:align: right
|
||||
|
||||
How to use YASnippet
|
||||
====================
|
||||
|
||||
Since version 0.6, YASnippet contains more functionality. You don't
|
||||
need to know all of it to use it sucessfully, but you it can improve
|
||||
your snippeting experience.
|
||||
|
||||
Hence this section has been split into separate documents:
|
||||
|
||||
1. `Organizing snippets <snippet-organization.html>`_
|
||||
|
||||
Describes ways to organize your snippets in the hard disk, or not
|
||||
organize them at all and just use plain old elisp.
|
||||
|
||||
Also explains how to use the YASnippet menu to explore and learn new
|
||||
snippets.
|
||||
|
||||
2. `Controlling snippet expansion <snippet-expansion.html>`_
|
||||
|
||||
Maybe, you'll want some snippets to be expanded in a particular mode,
|
||||
or only under certain conditions. Also you might want snippets to wrap
|
||||
themselves around a region of selected text, use a direct keybinding,
|
||||
control indenting, etc...
|
||||
|
||||
3. `Defining your own snippets <snippet-development.html>`_
|
||||
|
||||
Describes the YASnippet definition syntax, which is similar, but not
|
||||
equivalent to Textmate's. Includes a section about converting Textmate
|
||||
snippets.
|
||||
|
||||
Customization group
|
||||
===================
|
||||
|
||||
|
313
doc/snippet-development.html
Normal file
313
doc/snippet-development.html
Normal file
@ -0,0 +1,313 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Writing snippets</title>
|
||||
<meta name="author" content="pluskid, joaotavora" />
|
||||
<meta name="date" content="2009-08-18" />
|
||||
<link rel="stylesheet" href="styles.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="writing-snippets">
|
||||
<div id="header-region" class="clear-block"></div>
|
||||
<div id="wrapper">
|
||||
<div id="container" class="clear-block">
|
||||
<div id="header">
|
||||
<div id="logo-floater">
|
||||
<h1 class="title">Writing snippets</h1>
|
||||
</div>
|
||||
<ul class="primary-links">
|
||||
<li>
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-organization.html">Organize</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-expansion.html">Expand</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-development.html">Write</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="changelog.html">ChangeLog</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="http://code.google.com/p/yasnippet/downloads/list">Download</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="center">
|
||||
<div id="squeeze">
|
||||
<div class="right-corner">
|
||||
<div class="left-corner">
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#quickly-finding-defining-snippets" id="id6">Quickly finding/defining snippets</a></li>
|
||||
<li><a class="reference internal" href="#using-the-snippet-mode-major-mode" id="id7">Using the <tt class="docutils literal"><span class="pre">snippet-mode</span></tt> major mode</a><ul>
|
||||
<li><a class="reference internal" href="#the-syntax-of-the-template" id="id8">The Syntax of the Template</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#plain-text" id="id9">Plain Text</a></li>
|
||||
<li><a class="reference internal" href="#embedded-elisp-code" id="id10">Embedded elisp code</a></li>
|
||||
<li><a class="reference internal" href="#tab-stop-fields" id="id11">Tab stop fields</a></li>
|
||||
<li><a class="reference internal" href="#placeholder-fields" id="id12">Placeholder fields</a></li>
|
||||
<li><a class="reference internal" href="#id2" id="id13">Mirrors</a></li>
|
||||
<li><a class="reference internal" href="#mirrors-with-transformations" id="id14">Mirrors with transformations</a></li>
|
||||
<li><a class="reference internal" href="#fields-with-transformations" id="id15">Fields with transformations</a></li>
|
||||
<li><a class="reference internal" href="#choosing-fields-value-from-a-list" id="id16">Choosing fields value from a list</a></li>
|
||||
<li><a class="reference internal" href="#nested-placeholder-fields" id="id17">Nested placeholder fields</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="quickly-finding-defining-snippets">
|
||||
<h1><a class="toc-backref" href="#id6">Quickly finding/defining snippets</a></h1>
|
||||
<p>From version 0.6 upwards there are two ways you can quickly find a
|
||||
snippet file. Once you find this file it will be set to
|
||||
<tt class="docutils literal"><span class="pre">snippet-mode</span></tt> (see ahead)</p>
|
||||
<ul>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/find-snippets</span></tt></p>
|
||||
<p>Lets you find the snippet file in the directory the snippet was
|
||||
loaded from (if it exists) like <tt class="docutils literal"><span class="pre">find-file-other-window</span></tt>.</p>
|
||||
</li>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/visit-snippet-file</span></tt></p>
|
||||
<p>Prompts you for possible snippet expansions like
|
||||
<tt class="docutils literal"><span class="pre">yas/insert-snippet</span></tt>, but instead of expanding it, takes you
|
||||
directly to the snippet definition's file, if it exists.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="using-the-snippet-mode-major-mode">
|
||||
<h1><a class="toc-backref" href="#id7">Using the <tt class="docutils literal"><span class="pre">snippet-mode</span></tt> major mode</a></h1>
|
||||
<p>From version 0.6 upwards there is a major mode <tt class="docutils literal"><span class="pre">snippet-mode</span></tt> to
|
||||
edit snippets. You can set the buffer to this mode with <tt class="docutils literal"><span class="pre">M-x</span>
|
||||
<span class="pre">snippet-mode</span></tt>. It provides reasonably useful syntax highlighting.</p>
|
||||
<p>Two commands are defined in this mode:</p>
|
||||
<ul>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/load-snippet-buffer</span></tt></p>
|
||||
<blockquote>
|
||||
<p>When editing a snippet, this loads the snippet into the correct
|
||||
mode and menu. Bound to <tt class="docutils literal"><span class="pre">C-c</span> <span class="pre">C-c</span></tt> by default while in
|
||||
<tt class="docutils literal"><span class="pre">snippet-mode</span></tt>.</p>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first"><tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/tryout-snippet</span></tt></p>
|
||||
<blockquote>
|
||||
<p>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 <tt class="docutils literal"><span class="pre">C-c</span> <span class="pre">C-t</span></tt> while in
|
||||
<tt class="docutils literal"><span class="pre">snippet-mode</span></tt>.</p>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
<p>There are also snippets for making snippets: <tt class="docutils literal"><span class="pre">vars</span></tt>, <tt class="docutils literal"><span class="pre">field</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">mirror</span></tt>.</p>
|
||||
<div class="section" id="the-syntax-of-the-template">
|
||||
<h2><a class="toc-backref" href="#id8">The Syntax of the Template</a></h2>
|
||||
<p>The syntax of the snippet template is simple but powerful, very
|
||||
similar to TextMate's.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="plain-text">
|
||||
<h1><a class="toc-backref" href="#id9">Plain Text</a></h1>
|
||||
<p>Arbitrary text can be included as the content of a template. They are
|
||||
usually interpreted as plain text, except <tt class="docutils literal"><span class="pre">$</span></tt> and <tt class="docutils literal"><span class="pre">`</span></tt>. You need to
|
||||
use <tt class="docutils literal"><span class="pre">\</span></tt> to escape them: <tt class="docutils literal"><span class="pre">\$</span></tt> and <tt class="docutils literal"><span class="pre">\`</span></tt>. The <tt class="docutils literal"><span class="pre">\</span></tt> itself may also
|
||||
needed to be escaped as <tt class="docutils literal"><span class="pre">\\</span></tt> sometimes.</p>
|
||||
</div>
|
||||
<div class="section" id="embedded-elisp-code">
|
||||
<h1><a class="toc-backref" href="#id10">Embedded elisp code</a></h1>
|
||||
<p>Elisp code can be embedded inside the template. They are written
|
||||
inside back-quotes (<tt class="docutils literal"><span class="pre">`</span></tt>):</p>
|
||||
<p>They 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 <tt class="docutils literal"><span class="pre">c-mode</span></tt> to calculate the header file guard dynamically:</p>
|
||||
<div class="highlight"><pre>#ifndef ${1:_`(upcase (file-name-nondirectory (file-name-sans-extension (buffer-file-name))))`_H_}
|
||||
#define $1
|
||||
|
||||
$0
|
||||
|
||||
#endif /* $1 */
|
||||
</pre></div>
|
||||
<p>From version 0.6.0, snippets expansions are run with some special
|
||||
emacs-lisp variables bound. One of this is <tt class="docutils literal"><span class="pre">yas/selected-text</span></tt>. You
|
||||
can therefore define a snippet like:</p>
|
||||
<div class="highlight"><pre>for ($1;$2;$3) {
|
||||
`yas/selected-text`$0
|
||||
}
|
||||
</pre></div>
|
||||
<p>to "wrap" the selected region inside your recently inserted
|
||||
snippet. Alternatively, you can also customize the variable
|
||||
<tt class="docutils literal"><span class="pre">yas/wrap-around-region</span></tt> to <tt class="docutils literal"><span class="pre">t</span></tt> which will do this automatically.</p>
|
||||
</div>
|
||||
<div class="section" id="tab-stop-fields">
|
||||
<h1><a class="toc-backref" href="#id11">Tab stop fields</a></h1>
|
||||
<p>Tab stops are fields that you can navigate back and forth by <tt class="docutils literal"><span class="pre">TAB</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">S-TAB</span></tt> <a class="footnote-reference" href="#id5" id="id1">[3]</a>. They are written by <tt class="docutils literal"><span class="pre">$</span></tt> followed with a
|
||||
number. <tt class="docutils literal"><span class="pre">$0</span></tt> has the special meaning of the <em>exit point</em> of a
|
||||
snippet. That is the last place to go when you've traveled all the
|
||||
fields. Here's a typical example:</p>
|
||||
<div class="highlight"><pre><div$1>
|
||||
$0
|
||||
</div>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="section" id="placeholder-fields">
|
||||
<h1><a class="toc-backref" href="#id12">Placeholder fields</a></h1>
|
||||
<p>Tab stops can have default values -- a.k.a placeholders. The syntax is
|
||||
like this:</p>
|
||||
<div class="highlight"><pre>${N:default value}
|
||||
</pre></div>
|
||||
<p>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
|
||||
<a class="reference internal" href="#mirrors">mirrors</a> or <a class="reference internal" href="#transformations">transformations</a> for this field.</p>
|
||||
</div>
|
||||
<div class="section" id="id2">
|
||||
<span id="mirrors"></span><h1><a class="toc-backref" href="#id13">Mirrors</a></h1>
|
||||
<p>We refer the tab stops with placeholders as a <em>field</em>. A field can have
|
||||
mirrors. Its mirrors will get updated when you change the text of a
|
||||
field. Here's an example:</p>
|
||||
<div class="highlight"><pre>\begin{${1:enumerate}}
|
||||
$0
|
||||
\end{$1}
|
||||
</pre></div>
|
||||
<p>When you type <tt class="docutils literal"><span class="pre">"document"</span></tt> at <tt class="docutils literal"><span class="pre">${1:enumerate}</span></tt>, the word
|
||||
<tt class="docutils literal"><span class="pre">"document"</span></tt> will also be inserted at <tt class="docutils literal"><span class="pre">\end{$1}</span></tt>. The best
|
||||
explanation is to see the screencast(<a class="reference external" href="http://www.youtube.com/watch?v=vOj7btx3ATg">YouTube</a> or <a class="reference external" href="http://yasnippet.googlecode.com/files/yasnippet.avi">avi video</a>).</p>
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="section" id="mirrors-with-transformations">
|
||||
<span id="transformations"></span><h1><a class="toc-backref" href="#id14">Mirrors with transformations</a></h1>
|
||||
<p>If the default value of a field starts with <tt class="docutils literal"><span class="pre">$</span></tt>, then it is interpreted
|
||||
as the transformation code instead of default value. A transformation
|
||||
is some arbitrary elisp code that will get evaluated in an environment
|
||||
when the variable text is bind to the inputted text of the
|
||||
field. Here's an example for Objective-C:</p>
|
||||
<div class="highlight"><pre>- (${1:id})${2:foo}
|
||||
{
|
||||
return $2;
|
||||
}
|
||||
|
||||
- (void)set${2:$(capitalize text)}:($1)aValue
|
||||
{
|
||||
[$2 autorelease];
|
||||
$2 = [aValue retain];
|
||||
}
|
||||
$0
|
||||
</pre></div>
|
||||
<p>Look at <tt class="docutils literal"><span class="pre">${2:$(capitalize</span> <span class="pre">text)}</span></tt>, it is a transformation instead of
|
||||
a placeholder. The actual placeholder is at the first line:
|
||||
<tt class="docutils literal"><span class="pre">${2:foo}</span></tt>. When you type text in <tt class="docutils literal"><span class="pre">${2:foo}</span></tt>, the transformation
|
||||
will be evaluated and the result will be placed there as the
|
||||
transformated 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.</p>
|
||||
<p>Another example is for <tt class="docutils literal"><span class="pre">rst-mode</span></tt>. 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</p>
|
||||
<div class="highlight"><pre>=====
|
||||
Title
|
||||
=====
|
||||
</pre></div>
|
||||
<p>is a valid title but</p>
|
||||
<div class="highlight"><pre>===
|
||||
Title
|
||||
===
|
||||
</pre></div>
|
||||
<p>is not. Here's an snippet for rst title:</p>
|
||||
<div class="highlight"><pre>${1:$(make-string (string-width text) ?\=)}
|
||||
${1:Title}
|
||||
${1:$(make-string (string-width text) ?\=)}
|
||||
|
||||
$0
|
||||
</pre></div>
|
||||
<table class="docutils footnote" frame="void" id="id3" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label">[1]</td><td>With some minor change, mainly for fixing some trivial bugs.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id4" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label">[2]</td><td>This is done when you call <tt class="docutils literal"><span class="pre">yas/initialize</span></tt>.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id5" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1">[3]</a></td><td>Of course, this can be customized.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section" id="fields-with-transformations">
|
||||
<h1><a class="toc-backref" href="#id15">Fields with transformations</a></h1>
|
||||
<p>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.</p>
|
||||
<p>The syntax is also a tiny bit different, so that the parser can
|
||||
distinguish between fields and mirrors. In the following example</p>
|
||||
<div class="highlight"><pre>#define "${1:mydefine$(upcase yas/text)}"
|
||||
</pre></div>
|
||||
<p><tt class="docutils literal"><span class="pre">mydefine</span></tt> gets automatically upcased to <tt class="docutils literal"><span class="pre">MYDEFINE</span></tt> once you enter
|
||||
the field. As you type text, it gets filtered through the
|
||||
transformation every time.</p>
|
||||
<p>Note that this is differentiated from a mirror with a transformation
|
||||
by the existance of extra text between the <tt class="docutils literal"><span class="pre">:</span></tt> and the
|
||||
transformation's <tt class="docutils literal"><span class="pre">$</span></tt>. If you don't want this extra-text, you can use
|
||||
two <tt class="docutils literal"><span class="pre">$</span></tt>'s instead.</p>
|
||||
<div class="highlight"><pre>#define "${1:$$(upcase yas/text)}"
|
||||
</pre></div>
|
||||
<p>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
|
||||
<tt class="docutils literal"><span class="pre">true</span></tt>. As a consequence, the auto-deletion behaviour of normal
|
||||
fields does not take place. This is by design.</p>
|
||||
</div>
|
||||
<div class="section" id="choosing-fields-value-from-a-list">
|
||||
<h1><a class="toc-backref" href="#id16">Choosing fields value from a list</a></h1>
|
||||
<p>As mentioned, the field transformation is invoked just after you enter
|
||||
the field, and with some useful variables bound, notably
|
||||
<tt class="docutils literal"><span class="pre">yas/field-modified-p</span></tt> and <tt class="docutils literal"><span class="pre">yas/moving-away-p</span></tt>. Because of this
|
||||
feature you can place a transformation in the primary field that lets
|
||||
you select default values for it.</p>
|
||||
<p>The <tt class="docutils literal"><span class="pre">yas/choose-value</span></tt> does this work for you. For example:</p>
|
||||
<div class="highlight"><pre><div align="${2:$$(yas/choose-value '("right" "center" "left"))}">
|
||||
$0
|
||||
</div>
|
||||
</pre></div>
|
||||
<p>See the definition of <tt class="docutils literal"><span class="pre">yas/choose-value</span></tt> to see how it was written
|
||||
using the two variables. Also check out <tt class="docutils literal"><span class="pre">yas/verify-value</span></tt> for
|
||||
another neat trick.</p>
|
||||
</div>
|
||||
<div class="section" id="nested-placeholder-fields">
|
||||
<h1><a class="toc-backref" href="#id17">Nested placeholder fields</a></h1>
|
||||
<p>From version 0.6 on, you can also have nested placeholders of the type:</p>
|
||||
<div class="highlight"><pre><div${1: id="${2:some_id}"}>$0</div>
|
||||
</pre></div>
|
||||
<p>This allows you to choose if you want to give this <tt class="docutils literal"><span class="pre">div</span></tt> an <tt class="docutils literal"><span class="pre">id</span></tt>
|
||||
attribute. If you tab forward after expanding it will let you change
|
||||
"some_id" to whatever you like. Alternatively, you can just press
|
||||
<tt class="docutils literal"><span class="pre">C-d</span></tt> (which executes <tt class="docutils literal"><span class="pre">yas/skip-and-clear-or-delete-char</span></tt>) and go
|
||||
straight to the exit marker.</p>
|
||||
<p>By the way, <tt class="docutils literal"><span class="pre">C-d</span></tt> will only clear the field if you cursor is at the
|
||||
beginning of the field <em>and</em> it hasn't been changed yet. Otherwise, it
|
||||
performs the normal Emacs <tt class="docutils literal"><span class="pre">delete-char</span></tt> command.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
295
doc/snippet-development.rst
Normal file
295
doc/snippet-development.rst
Normal file
@ -0,0 +1,295 @@
|
||||
================
|
||||
Writing snippets
|
||||
================
|
||||
|
||||
:Author: pluskid, joaotavora
|
||||
:Contact: pluskid@gmail.com
|
||||
:Date: 2009-08-18
|
||||
|
||||
.. contents::
|
||||
|
||||
Quickly finding/defining snippets
|
||||
---------------------------------
|
||||
|
||||
From version 0.6 upwards there are two ways you can quickly find a
|
||||
snippet file. Once you find this file it will be set to
|
||||
``snippet-mode`` (see ahead)
|
||||
|
||||
* ``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``.
|
||||
|
||||
* ``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.
|
||||
|
||||
|
||||
Using the ``snippet-mode`` major mode
|
||||
-------------------------------------
|
||||
|
||||
From version 0.6 upwards 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 making snippets: ``vars``, ``field`` and
|
||||
``mirror``.
|
||||
|
||||
|
||||
|
||||
The Syntax of the Template
|
||||
==========================
|
||||
|
||||
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 elisp code
|
||||
-------------------
|
||||
|
||||
Elisp code can be embedded inside the template. They are written
|
||||
inside back-quotes (`````):
|
||||
|
||||
They 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.0, 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`` [3]_. 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 default value of a field starts with ``$``, then it is interpreted
|
||||
as the transformation code instead of default value. A transformation
|
||||
is some arbitrary elisp code that will get evaluated in an environment
|
||||
when the variable text is bind to the inputted text of the
|
||||
field. 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 transformation instead of
|
||||
a placeholder. The actual placeholder 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
|
||||
transformated 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
|
||||
|
||||
.. [1] With some minor change, mainly for fixing some trivial bugs.
|
||||
.. [2] This is done when you call ``yas/initialize``.
|
||||
.. [3] Of course, this can be customized.
|
||||
|
||||
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 this is differentiated from a mirror with a transformation
|
||||
by the existance of 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
|
||||
---------------------------------
|
||||
|
||||
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. Also check out ``yas/verify-value`` for
|
||||
another neat trick.
|
||||
|
||||
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.
|
413
doc/snippet-expansion.html
Normal file
413
doc/snippet-expansion.html
Normal file
@ -0,0 +1,413 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Expanding snippets</title>
|
||||
<meta name="author" content="pluskid, joaotavora" />
|
||||
<meta name="date" content="2009-08-18" />
|
||||
<link rel="stylesheet" href="styles.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="expanding-snippets">
|
||||
<div id="header-region" class="clear-block"></div>
|
||||
<div id="wrapper">
|
||||
<div id="container" class="clear-block">
|
||||
<div id="header">
|
||||
<div id="logo-floater">
|
||||
<h1 class="title">Expanding snippets</h1>
|
||||
</div>
|
||||
<ul class="primary-links">
|
||||
<li>
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-organization.html">Organize</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-expansion.html">Expand</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-development.html">Write</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="changelog.html">ChangeLog</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="http://code.google.com/p/yasnippet/downloads/list">Download</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="center">
|
||||
<div id="squeeze">
|
||||
<div class="right-corner">
|
||||
<div class="left-corner">
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#some-stuff" id="id1">Some stuff</a><ul>
|
||||
<li><a class="reference internal" href="#file-content" id="id2">File content</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#the-strategy-to-select-a-snippet" id="id3">The strategy to select a snippet</a><ul>
|
||||
<li><a class="reference internal" href="#finding-the-key" id="id4">Finding the key</a></li>
|
||||
<li><a class="reference internal" href="#the-condition-system" id="id5">The condition system</a></li>
|
||||
<li><a class="reference internal" href="#multiple-snippet-with-the-same-key" id="id6">Multiple snippet with the same key</a><ul>
|
||||
<li><a class="reference internal" href="#use-the-x-window-system" id="id7">Use the X window system</a></li>
|
||||
<li><a class="reference internal" href="#use-built-in-emacs-selection-methods" id="id8">Use built-in Emacs selection methods</a></li>
|
||||
<li><a class="reference internal" href="#use-dropdown-menu-el" id="id9">Use <tt class="docutils literal"><span class="pre">dropdown-menu.el</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#the-trigger-key" id="id10">The Trigger Key</a><ul>
|
||||
<li><a class="reference internal" href="#the-minor-mode" id="id11">The Minor Mode</a></li>
|
||||
<li><a class="reference internal" href="#the-fallback" id="id12">The Fallback</a></li>
|
||||
<li><a class="reference internal" href="#integration-with-hippie-expand" id="id13">Integration with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#other-way-to-select-a-snippet" id="id14">Other way to select a snippet</a><ul>
|
||||
<li><a class="reference internal" href="#yas-insert-snippet" id="id15"><tt class="docutils literal"><span class="pre">yas/insert-snippet</span></tt></a></li>
|
||||
<li><a class="reference internal" href="#expanding-from-elisp-code" id="id16">Expanding From Elisp Code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#indenting" id="id17">Indenting</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="some-stuff">
|
||||
<h1><a class="toc-backref" href="#id1">Some stuff</a></h1>
|
||||
<div class="section" id="file-content">
|
||||
<h2><a class="toc-backref" href="#id2">File content</a></h2>
|
||||
<p>A file defining a snippet may just contain the template for the
|
||||
snippet. Optionally it can also contains some meta data for the
|
||||
snippet as well as comments.</p>
|
||||
<p>Generally speaking, if the file contains a line of <tt class="docutils literal"><span class="pre">#</span> <span class="pre">--</span></tt>, then all
|
||||
contents above that line are considered as meta data and comments;
|
||||
below are template. Or else the whole file content is considered as
|
||||
the template.</p>
|
||||
<p>Here's a typical example:</p>
|
||||
<div class="highlight"><pre>#contributor : pluskid <pluskid@gmail.com>
|
||||
#name : __...__
|
||||
# --
|
||||
__${init}__
|
||||
</pre></div>
|
||||
<p>Meta data are specified in the syntax of</p>
|
||||
<div class="highlight"><pre>#data-name : data value
|
||||
</pre></div>
|
||||
<p>Any other text above <tt class="docutils literal"><span class="pre">#</span> <span class="pre">--</span></tt> is considered as comment and
|
||||
ignored. Here's a list of currently supported meta data:</p>
|
||||
<img align="right" alt="images/group.png" class="align-right" src="images/group.png" />
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">name</span></tt>: The name of the snippet. This is a one-line description of
|
||||
the snippet. It will be displayed in the menu. So it's a good idea
|
||||
to select a descriptive name fo a snippet -- especially
|
||||
distinguishable among similar snippets.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">contributor</span></tt>: The contributor of the snippet.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">condition</span></tt>: The condition of the snippet. This is a piece of
|
||||
elisp code. If a snippet has a condition, then it will only be
|
||||
expanded when the condition code evaluate to some non-nil value.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">key</span></tt>: The key to expand the snippet. Sometimes the key of a
|
||||
snippet is non-ASCII or not valid filename (e.g. contains
|
||||
<tt class="docutils literal"><span class="pre">/</span></tt>). One can then define the <tt class="docutils literal"><span class="pre">key</span></tt> property which will
|
||||
overwrite the filename as the key to expand the snippet.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">group</span></tt>: The snippets for a mode can be grouped. Grouped snippets
|
||||
will be grouped in sub-menu. This is useful if one has too many
|
||||
snippets for a mode which will make the menu too long. <tt class="docutils literal"><span class="pre">group</span></tt>
|
||||
property only affect menu construction (See <a class="reference external" href="snippet-organization.html">Organizing snippets</a>). Refer to
|
||||
the snippets for <tt class="docutils literal"><span class="pre">ruby-mode</span></tt> for examples. Group can also be
|
||||
nested, e.g. <tt class="docutils literal"><span class="pre">control</span> <span class="pre">structure.loops</span></tt> tells that the snippet is
|
||||
under the <tt class="docutils literal"><span class="pre">loops</span></tt> group which is under the <tt class="docutils literal"><span class="pre">control</span> <span class="pre">structure</span></tt>
|
||||
group.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="the-strategy-to-select-a-snippet">
|
||||
<h1><a class="toc-backref" href="#id3">The strategy to select a snippet</a></h1>
|
||||
<p>When user press the <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt>, YASnippet try to find a
|
||||
proper snippet to expand. The strategy to find such a snippet is
|
||||
explained here.</p>
|
||||
<div class="section" id="finding-the-key">
|
||||
<h2><a class="toc-backref" href="#id4">Finding the key</a></h2>
|
||||
<p>YASnippet search from current point backward trying to find the
|
||||
snippet to be expanded. The default searching strategy is quite
|
||||
powerful. For example, in <tt class="docutils literal"><span class="pre">c-mode</span></tt>, <tt class="docutils literal"><span class="pre">"bar"</span></tt>, <tt class="docutils literal"><span class="pre">"foo_bar"</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">"#foo_bar"</span></tt> can all be recognized as a template key. Further more,
|
||||
the searching is in that order. In other words, if <tt class="docutils literal"><span class="pre">"bar"</span></tt> is found
|
||||
to be a key to some <em>valid</em> snippet, then <tt class="docutils literal"><span class="pre">"foo_bar"</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">"#foobar"</span></tt> won't be searched.</p>
|
||||
<p>However, this strategy can also be customized easily from the
|
||||
<tt class="docutils literal"><span class="pre">yas/key-syntaxes</span></tt> variable. It is a list of syntax rules, the
|
||||
default value is <tt class="docutils literal"><span class="pre">("w"</span> <span class="pre">"w_"</span> <span class="pre">"w_."</span> <span class="pre">"^</span> <span class="pre">")</span></tt>. Which means search the
|
||||
following thing until found one:</p>
|
||||
<ul class="simple">
|
||||
<li>a word.</li>
|
||||
<li>a symbol. In lisp, <tt class="docutils literal"><span class="pre">-</span></tt> and <tt class="docutils literal"><span class="pre">?</span></tt> can all be part of a symbol.</li>
|
||||
<li>a sequence of characters of either word, symbol or punctuation.</li>
|
||||
<li>a sequence of characters of non-whitespace characters.</li>
|
||||
</ul>
|
||||
<p>But you'd better keep the default value unless you understand what
|
||||
Emacs's syntax rule mean.</p>
|
||||
</div>
|
||||
<div class="section" id="the-condition-system">
|
||||
<h2><a class="toc-backref" href="#id5">The condition system</a></h2>
|
||||
<p>I write forked snippet.el to make the smart-snippet.el. I call it
|
||||
<em>smart</em>-snippet because a condition can be attached to a snippet. This
|
||||
is really a good idea. However, writing condition for a snippet
|
||||
usually needs good elisp and Emacs knowledge, so it is strange to many
|
||||
user.</p>
|
||||
<p>Later I write YASnippet and persuade people to use it instead of
|
||||
smart-snippet.el. However, some user still love smart-snippet because
|
||||
it is smart. So I make YASnippet smart. Even smarter than
|
||||
smart-snippet.el. :p</p>
|
||||
<p>Consider this scenario: you are an old Emacs hacker. You like the
|
||||
abbrev-way and set <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt> to <tt class="docutils literal"><span class="pre">(kbd</span> <span class="pre">"SPC")</span></tt>. However,
|
||||
you don't want <tt class="docutils literal"><span class="pre">if</span></tt> to be expanded as a snippet when you are typing
|
||||
in a comment block or a string (e.g. in <tt class="docutils literal"><span class="pre">python-mode</span></tt>).</p>
|
||||
<p>It's OK, just specify the condition for <tt class="docutils literal"><span class="pre">if</span></tt> to be <tt class="docutils literal"><span class="pre">(not</span>
|
||||
<span class="pre">(python-in-string/comment))</span></tt>. But how about <tt class="docutils literal"><span class="pre">while</span></tt>, <tt class="docutils literal"><span class="pre">for</span></tt>,
|
||||
etc. ? Writing the same condition for all the snippets is just
|
||||
boring. So YASnippet introduce a buffer local variable
|
||||
<tt class="docutils literal"><span class="pre">yas/buffer-local-condition</span></tt>. You can set this variable to <tt class="docutils literal"><span class="pre">(not</span>
|
||||
<span class="pre">(python-in-string/comment))</span></tt> in <tt class="docutils literal"><span class="pre">python-mode-hook</span></tt>. There's no way
|
||||
to do this in smart-snippet.el!</p>
|
||||
<p>Then, what if you really want some snippet even in comment? This is
|
||||
also possible! But let's stop telling the story and look at the rules:</p>
|
||||
<ul class="simple">
|
||||
<li>If <tt class="docutils literal"><span class="pre">yas/buffer-local-condition</span></tt> evaluate to nil, snippet won't be
|
||||
expanded.</li>
|
||||
<li>If it evaluate to the a cons cell where the <tt class="docutils literal"><span class="pre">car</span></tt> is the symbol
|
||||
<tt class="docutils literal"><span class="pre">require-snippet-condition</span></tt> and the <tt class="docutils literal"><span class="pre">cdr</span></tt> is a symbol (let's
|
||||
call it <tt class="docutils literal"><span class="pre">requirement</span></tt>):<ul>
|
||||
<li>If the snippet has no condition, then it won't be expanded.</li>
|
||||
<li>If the snippet has a condition but evaluate to nil or error
|
||||
occured during evaluation, it won't be expanded.</li>
|
||||
<li>If the snippet has a condition that evaluate to non-nil (let's
|
||||
call it <tt class="docutils literal"><span class="pre">result</span></tt>):<ul>
|
||||
<li>If <tt class="docutils literal"><span class="pre">requirement</span></tt> is <tt class="docutils literal"><span class="pre">t</span></tt>, the snippet is ready to be
|
||||
expanded.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">requirement</span></tt> is <tt class="docutils literal"><span class="pre">eq</span></tt> to <tt class="docutils literal"><span class="pre">result</span></tt>, the snippet is ready
|
||||
to be expanded.</li>
|
||||
<li>Otherwise the snippet won't be expanded.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>If it evaluate to other non-nil value:<ul>
|
||||
<li>If the snippet has no condition, or has a condition that evaluate
|
||||
to non-nil, it is ready to be expanded.</li>
|
||||
<li>Otherwise, it won't be expanded.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>So set <tt class="docutils literal"><span class="pre">yas/buffer-local-condition</span></tt> like this</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">add-hook</span> <span style="color: #19177C">'python-mode-hook</span>
|
||||
<span style="color: #666666">'</span>(<span style="color: #008000; font-weight: bold">lambda</span> ()
|
||||
(<span style="color: #008000; font-weight: bold">setq</span> <span style="color: #19177C">yas/buffer-local-condition</span>
|
||||
<span style="color: #666666">'</span>(<span style="color: #008000; font-weight: bold">if</span> (<span style="color: #19177C">python-in-string/comment</span>)
|
||||
<span style="color: #666666">'</span>(<span style="color: #19177C">require-snippet-condition</span> <span style="color: #666666">.</span> <span style="color: #19177C">force-in-comment</span>)
|
||||
<span style="color: #880000">t</span>))))
|
||||
</pre></div>
|
||||
<p>And specify the condition for a snippet that you're going to expand in
|
||||
comment to be evaluated to the symbol <tt class="docutils literal"><span class="pre">force-in-comment</span></tt>. Then it
|
||||
can be expanded as you expected, while other snippets like <tt class="docutils literal"><span class="pre">if</span></tt>
|
||||
still can't expanded in comment.</p>
|
||||
</div>
|
||||
<div class="section" id="multiple-snippet-with-the-same-key">
|
||||
<h2><a class="toc-backref" href="#id6">Multiple snippet with the same key</a></h2>
|
||||
<p>There can be multiple snippet bind to the same key. If you define a
|
||||
snippet with a key that is already used, you'll overwrite the original
|
||||
snippet definition. However, you can add a different <em>postfix</em> to the
|
||||
key.</p>
|
||||
<p>In general, the <em>extension</em> (consider a file name) is <em>ignored</em> when
|
||||
defining a snippet. So <tt class="docutils literal"><span class="pre">def</span></tt>, <tt class="docutils literal"><span class="pre">def.1</span></tt> and <tt class="docutils literal"><span class="pre">def.mine</span></tt> will all be
|
||||
valid candidates when the key is <tt class="docutils literal"><span class="pre">def</span></tt>.</p>
|
||||
<p>When there are multiple candidates, YASnippet will let you select
|
||||
one. The UI for selecting multiple candidate can be
|
||||
customized. There're two variable related:</p>
|
||||
<p>From version 0.6 of YASnippet this has changed significantly. A new
|
||||
customization variable, called <tt class="docutils literal"><span class="pre">yas/prompt-functions</span></tt> defines your
|
||||
preferred method of being prompted for snippets.</p>
|
||||
<p>You can customize it with <tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">customize-variable</span> <span class="pre">RET</span>
|
||||
<span class="pre">yas/prompt-functions</span> <span class="pre">RET</span></tt>. Alternatively you can put in your
|
||||
emacs-file:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #008000; font-weight: bold">setq</span> <span style="color: #19177C">yas/prompt-functions</span> <span style="color: #666666">'</span>(<span style="color: #19177C">yas/x-prompt</span> <span style="color: #19177C">yas/dropdown-prompt</span>))
|
||||
</pre></div>
|
||||
<p>Currently there are some alternatives solution with YASnippet.</p>
|
||||
<img align="right" alt="images/popup-menu.png" class="align-right" src="images/popup-menu.png" />
|
||||
<div class="section" id="use-the-x-window-system">
|
||||
<h3><a class="toc-backref" href="#id7">Use the X window system</a></h3>
|
||||
<p>The function <tt class="docutils literal"><span class="pre">yas/x-prompt</span></tt> can be used to show a popup menu for you
|
||||
to select. This menu will be part of you native window system widget,
|
||||
which means:</p>
|
||||
<ul class="simple">
|
||||
<li>It usually looks beautiful. E.g. when you compile Emacs with gtk
|
||||
support, this menu will be rendered with your gtk theme.</li>
|
||||
<li>Emacs have little control over it. E.g. you can't use <tt class="docutils literal"><span class="pre">C-n</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">C-p</span></tt> to navigate.</li>
|
||||
<li>This function can't be used when in a terminal.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="use-built-in-emacs-selection-methods">
|
||||
<h3><a class="toc-backref" href="#id8">Use built-in Emacs selection methods</a></h3>
|
||||
<p>You can use functions <tt class="docutils literal"><span class="pre">yas/completing-prompt</span></tt> for the classic emacs
|
||||
completion method or <tt class="docutils literal"><span class="pre">yas/ido-prompt</span></tt> for a much nicer looking
|
||||
method. The best way is to try it. This works in a terminal.</p>
|
||||
<div align="center" class="align-center"><img alt="images/idrop-menu.png" class="align-center" src="images/idrop-menu.png" /></div>
|
||||
</div>
|
||||
<div class="section" id="use-dropdown-menu-el">
|
||||
<h3><a class="toc-backref" href="#id9">Use <tt class="docutils literal"><span class="pre">dropdown-menu.el</span></tt></a></h3>
|
||||
<p>The function <tt class="docutils literal"><span class="pre">yas/dropdown-prompt</span></tt> can also be placed in the
|
||||
<tt class="docutils literal"><span class="pre">yas/prompt-functions</span></tt> list.</p>
|
||||
<img align="right" alt="images/dropdown-menu.png" class="align-right" src="images/dropdown-menu.png" />
|
||||
<p>Originally, only the above two function is available in
|
||||
YASnippet. They are difficult to use -- especially in a
|
||||
terminal. Until later Jaeyoun Chung show me his <tt class="docutils literal"><span class="pre">dropdown-menu.el</span></tt>,
|
||||
I say wow! It's wonderful!</p>
|
||||
<ul class="simple">
|
||||
<li>It works in both window system and terminal.</li>
|
||||
<li>It is customizable, you can use <tt class="docutils literal"><span class="pre">C-n</span></tt>, <tt class="docutils literal"><span class="pre">C-p</span></tt> to navigate, <tt class="docutils literal"><span class="pre">q</span></tt>
|
||||
to quite and even press <tt class="docutils literal"><span class="pre">6</span></tt> as a shortcut to select the 6th
|
||||
candidate.</li>
|
||||
</ul>
|
||||
<p>So I added <tt class="docutils literal"><span class="pre">yas/dropdown-list-popup-for-template</span></tt> to support
|
||||
<tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt>. And upload <tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt> to YASnippet
|
||||
hompage for an optional download (since Jaeyoun didn't provide a URL).</p>
|
||||
<p>Then finally, in 0.4.0, I included a copy of the content of
|
||||
<tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt> in <tt class="docutils literal"><span class="pre">yasnippet.el</span></tt> and made it the default
|
||||
way for selecting multiple candidates.</p>
|
||||
<p>However, the original functions are still there, you can still use this</p>
|
||||
<div class="highlight"><pre>(<span style="color: #008000; font-weight: bold">setq</span> <span style="color: #19177C">yas/window-system-popup-function</span>
|
||||
<span style="color: #19177C">'yas/x-popup-menu-for-template</span>)
|
||||
</pre></div>
|
||||
<p>if you prefer a <em>modern</em> UI. :)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="the-trigger-key">
|
||||
<h2><a class="toc-backref" href="#id10">The Trigger Key</a></h2>
|
||||
<p>YASnippet is implemented as a minor-mode (<tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt>). The
|
||||
trigger key <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt> is defined in <tt class="docutils literal"><span class="pre">yas/minor-mode-map</span></tt>
|
||||
to call <tt class="docutils literal"><span class="pre">yas/expand</span></tt> to try to expand a snippet.</p>
|
||||
<div class="section" id="the-minor-mode">
|
||||
<h3><a class="toc-backref" href="#id11">The Minor Mode</a></h3>
|
||||
<img align="left" alt="images/minor-mode-indicator.png" class="align-left" src="images/minor-mode-indicator.png" />
|
||||
<p>When <tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt> is enabled, the trigger key will take
|
||||
effect. The default key is <tt class="docutils literal"><span class="pre">(kbd</span> <span class="pre">"TAB")</span></tt>, however, you can freely
|
||||
set it to some other key.</p>
|
||||
<p>In version 0.5, YASnippet add a hook to
|
||||
<tt class="docutils literal"><span class="pre">after-change-major-mode-hook</span></tt> to enable <tt class="docutils literal"><span class="pre">yas/minor-mode</span></tt> in
|
||||
every buffer. This works fine for most modes, however, some mode
|
||||
doesn't follow the Emacs convention and doens't call this hook. You
|
||||
can either explicitly hook for those mode or just add it to
|
||||
<tt class="docutils literal"><span class="pre">yas/extra-mode-hooks</span></tt> to let YASnippet do it for you:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #008000">require</span> <span style="color: #19177C">'yasnippet</span>)
|
||||
(<span style="color: #19177C">add-to-list</span> <span style="color: #19177C">'yas/extra-mode-hooks</span>
|
||||
<span style="color: #19177C">'ruby-mode-hook</span>)
|
||||
(<span style="color: #19177C">yas/initialize</span>)
|
||||
</pre></div>
|
||||
<p>Note that <strong>should</strong> be put after <tt class="docutils literal"><span class="pre">(require</span> <span class="pre">'yasnippet)</span></tt> and before
|
||||
<tt class="docutils literal"><span class="pre">(yas/initialize)</span></tt>. Further more, you may report it to me, I'll add
|
||||
that to the default value.</p>
|
||||
<p>In version 0.6, just use <tt class="docutils literal"><span class="pre">yas/global-mode</span></tt> to enable YASnippet in
|
||||
all major modes. Or put <tt class="docutils literal"><span class="pre">yas/minor-mode-on</span></tt> in that modes hook. See
|
||||
the <a class="reference external" href="faq.html">FAQ</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="the-fallback">
|
||||
<h3><a class="toc-backref" href="#id12">The Fallback</a></h3>
|
||||
<p>If <tt class="docutils literal"><span class="pre">yas/expand</span></tt> failed to find any suitable snippet to expand, it
|
||||
will disable the minor mode temporarily and find if there's any other
|
||||
command bind the <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt>. If found, the command will be
|
||||
called. Usually this works very well -- when there's a snippet, expand
|
||||
it, otherwise, call whatever command originally bind to the trigger
|
||||
key.</p>
|
||||
<p>However, you can change this behavior by customizing the
|
||||
<tt class="docutils literal"><span class="pre">yas/fallback-behavior</span></tt> variable. If you set this variable to
|
||||
<tt class="docutils literal"><span class="pre">'return-nil</span></tt>, it will return <tt class="docutils literal"><span class="pre">nil</span></tt> instead of trying to call the
|
||||
<em>original</em> command when no snippet is found. This is useful when you
|
||||
would like YASnippet to work with other extensions,
|
||||
e.g. <tt class="docutils literal"><span class="pre">hippie-expand</span></tt>. I'm also glad to tell you that integration
|
||||
with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt> is already included in YASnippet.</p>
|
||||
</div>
|
||||
<div class="section" id="integration-with-hippie-expand">
|
||||
<h3><a class="toc-backref" href="#id13">Integration with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt></a></h3>
|
||||
<p>To integrate with <tt class="docutils literal"><span class="pre">hippie-expand</span></tt>, just put
|
||||
<tt class="docutils literal"><span class="pre">yas/hippie-try-expand</span></tt> in
|
||||
<tt class="docutils literal"><span class="pre">hippie-expand-try-functions-list</span></tt>. Personally I would like to put
|
||||
in front of the list, but it can be put anywhere you prefer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="other-way-to-select-a-snippet">
|
||||
<h2><a class="toc-backref" href="#id14">Other way to select a snippet</a></h2>
|
||||
<p>When you use the trigger key (so <tt class="docutils literal"><span class="pre">yas/expand</span></tt>) to expand a snippet,
|
||||
the key for the snippet is deleted before the template for the snippet
|
||||
is inserted.</p>
|
||||
<p>However, there're other ways to insert a snippet.</p>
|
||||
<div class="section" id="yas-insert-snippet">
|
||||
<h3><a class="toc-backref" href="#id15"><tt class="docutils literal"><span class="pre">yas/insert-snippet</span></tt></a></h3>
|
||||
<p>The command <tt class="docutils literal"><span class="pre">M-x</span> <span class="pre">yas/insert-snippet</span></tt> lets you insert snippets at
|
||||
point <em>for you current major mode</em>. It prompts you for the snippet
|
||||
key first, and then for a snippet template if more than one template
|
||||
exists for the same key.</p>
|
||||
<p>The list presented contains the snippets that can be inserted at
|
||||
point, according to the condition system. If you want to see all
|
||||
applicable snippets for the major mode, prefix this command with
|
||||
<tt class="docutils literal"><span class="pre">C-u</span></tt>.</p>
|
||||
<p>The prompting methods used are again controlled by
|
||||
<tt class="docutils literal"><span class="pre">yas/prompt-functions</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="expanding-from-elisp-code">
|
||||
<h3><a class="toc-backref" href="#id16">Expanding From Elisp Code</a></h3>
|
||||
<p>Sometimes you might want to expand a snippet directly by calling a
|
||||
functin from elisp code. You should call <tt class="docutils literal"><span class="pre">yas/expand-snippet</span></tt>
|
||||
instead of <tt class="docutils literal"><span class="pre">yas/expand</span></tt> in this case.</p>
|
||||
<p>As with expanding from the menubar, condition system and multiple
|
||||
candidates won't exists here. In fact, expanding from menubar has the
|
||||
same effect of evaluating the follow code:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/expand-snippet</span> (<span style="color: #19177C">point</span>) (<span style="color: #19177C">point</span>) <span style="color: #19177C">template</span>)
|
||||
</pre></div>
|
||||
<p>Where <tt class="docutils literal"><span class="pre">template</span></tt> is the template of a snippet. It is never required
|
||||
to belong to any snippet -- you can even make up it on the fly. The
|
||||
1st and 2nd parameter defines the region to be deleted after YASnippet
|
||||
inserted the template. It is used by <tt class="docutils literal"><span class="pre">yas/expand</span></tt> to indicate the
|
||||
region of the key. There's usually no need to delete any region when
|
||||
we are expanding a snippet from elisp code, so passing two <tt class="docutils literal"><span class="pre">(point)</span></tt>
|
||||
is fine. Note only <tt class="docutils literal"><span class="pre">(point)</span></tt> will be fine because the 1st parameter
|
||||
also indicate where to insert and expand the <tt class="docutils literal"><span class="pre">template</span></tt>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="indenting">
|
||||
<h2><a class="toc-backref" href="#id17">Indenting</a></h2>
|
||||
<p>Many people miss the indenting feature of smart-snippet: when you
|
||||
place a <tt class="docutils literal"><span class="pre">$></span></tt> in your snippet, an <tt class="docutils literal"><span class="pre">(indent-according-to-mode)</span></tt> will
|
||||
be executed there to indent the line. So you'll not need to hard-code
|
||||
the indenting in the snippet template, and it will be very convenient
|
||||
when you need to work with several different project where coding
|
||||
styles are different.</p>
|
||||
<p>The reason why this feature wasn't added to YASnippet until after
|
||||
0.5.6 is that it doesn't work well for all modes. In some cases
|
||||
(e.g. python-mode), calling <tt class="docutils literal"><span class="pre">indent-according-to-mode</span></tt> will break
|
||||
the overlays created by YASnippet.</p>
|
||||
<p>However, since many people asked for this feature, I finally added
|
||||
this to YASnippet. Here's an example of the usage:</p>
|
||||
<div class="highlight"><pre>for (${int i = 0}; ${i < 10}; ${++i})
|
||||
{$>
|
||||
$0$>
|
||||
}$>
|
||||
</pre></div>
|
||||
<p>In 0.6.0 You should <strong>not</strong> need to use this feature although it's
|
||||
supported for backward compatibility. Just set <tt class="docutils literal"><span class="pre">yas/indent-line</span></tt> to
|
||||
<tt class="docutils literal"><span class="pre">'auto</span></tt>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
410
doc/snippet-expansion.rst
Normal file
410
doc/snippet-expansion.rst
Normal file
@ -0,0 +1,410 @@
|
||||
==================
|
||||
Expanding snippets
|
||||
==================
|
||||
|
||||
:Author: pluskid, joaotavora
|
||||
:Contact: pluskid@gmail.com
|
||||
:Date: 2009-08-18
|
||||
|
||||
.. contents::
|
||||
|
||||
Some stuff
|
||||
==========
|
||||
|
||||
File content
|
||||
------------
|
||||
|
||||
A file defining a snippet may just contain the template for the
|
||||
snippet. Optionally it can also contains some meta data for the
|
||||
snippet as well as comments.
|
||||
|
||||
Generally speaking, if the file contains a line of ``# --``, then all
|
||||
contents above that line are considered as meta data and comments;
|
||||
below are template. Or else the whole file content is considered as
|
||||
the template.
|
||||
|
||||
Here's a typical example:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
#contributor : pluskid <pluskid@gmail.com>
|
||||
#name : __...__
|
||||
# --
|
||||
__${init}__
|
||||
|
||||
Meta data are specified in the syntax of
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
#data-name : data value
|
||||
|
||||
Any other text above ``# --`` is considered as comment and
|
||||
ignored. Here's a list of currently supported meta data:
|
||||
|
||||
.. image:: images/group.png
|
||||
:align: right
|
||||
|
||||
* ``name``: The name of the snippet. This is a one-line description of
|
||||
the snippet. It will be displayed in the menu. So it's a good idea
|
||||
to select a descriptive name fo a snippet -- especially
|
||||
distinguishable among similar snippets.
|
||||
* ``contributor``: The contributor of the snippet.
|
||||
* ``condition``: The condition of the snippet. This is a piece of
|
||||
elisp code. If a snippet has a condition, then it will only be
|
||||
expanded when the condition code evaluate to some non-nil value.
|
||||
* ``key``: The key to expand the snippet. 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.
|
||||
* ``group``: The snippets for a mode can be grouped. Grouped snippets
|
||||
will be grouped in sub-menu. This is useful if one has too many
|
||||
snippets for a mode which will make the menu too long. ``group``
|
||||
property only affect menu construction (See `Organizing snippets <snippet-organization.html>`_). Refer to
|
||||
the snippets for ``ruby-mode`` for examples. 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.
|
||||
|
||||
|
||||
|
||||
The strategy to select a snippet
|
||||
================================
|
||||
|
||||
When user press the ``yas/trigger-key``, YASnippet try to find a
|
||||
proper snippet to expand. The strategy to find such a snippet is
|
||||
explained here.
|
||||
|
||||
Finding the key
|
||||
---------------
|
||||
|
||||
YASnippet search from current point backward trying to find the
|
||||
snippet to be expanded. The default searching strategy is quite
|
||||
powerful. For example, in ``c-mode``, ``"bar"``, ``"foo_bar"``,
|
||||
``"#foo_bar"`` can all be recognized as a template key. Further more,
|
||||
the searching is in that order. In other words, if ``"bar"`` is found
|
||||
to be a key to some *valid* snippet, then ``"foo_bar"`` and
|
||||
``"#foobar"`` won't be searched.
|
||||
|
||||
However, this strategy can also be customized easily from the
|
||||
``yas/key-syntaxes`` variable. It is a list of syntax rules, the
|
||||
default value is ``("w" "w_" "w_." "^ ")``. Which means search the
|
||||
following thing until found one:
|
||||
|
||||
* a word.
|
||||
* a symbol. In lisp, ``-`` and ``?`` can all be part of a symbol.
|
||||
* a sequence of characters of either word, symbol or punctuation.
|
||||
* a sequence of characters of non-whitespace characters.
|
||||
|
||||
But you'd better keep the default value unless you understand what
|
||||
Emacs's syntax rule mean.
|
||||
|
||||
The condition system
|
||||
--------------------
|
||||
|
||||
I write forked snippet.el to make the smart-snippet.el. I call it
|
||||
*smart*-snippet because a condition can be attached to a snippet. This
|
||||
is really a good idea. However, writing condition for a snippet
|
||||
usually needs good elisp and Emacs knowledge, so it is strange to many
|
||||
user.
|
||||
|
||||
Later I write YASnippet and persuade people to use it instead of
|
||||
smart-snippet.el. However, some user still love smart-snippet because
|
||||
it is smart. So I make YASnippet smart. Even smarter than
|
||||
smart-snippet.el. :p
|
||||
|
||||
Consider this scenario: you are an old Emacs hacker. You like the
|
||||
abbrev-way and set ``yas/trigger-key`` to ``(kbd "SPC")``. However,
|
||||
you don't want ``if`` to be expanded as a snippet when you are typing
|
||||
in a comment block or a string (e.g. in ``python-mode``).
|
||||
|
||||
It's OK, just specify the condition for ``if`` to be ``(not
|
||||
(python-in-string/comment))``. But how about ``while``, ``for``,
|
||||
etc. ? Writing the same condition for all the snippets is just
|
||||
boring. So YASnippet introduce a buffer local variable
|
||||
``yas/buffer-local-condition``. You can set this variable to ``(not
|
||||
(python-in-string/comment))`` in ``python-mode-hook``. There's no way
|
||||
to do this in smart-snippet.el!
|
||||
|
||||
Then, what if you really want some snippet even in comment? This is
|
||||
also possible! But let's stop telling the story and look at the rules:
|
||||
|
||||
* If ``yas/buffer-local-condition`` evaluate to nil, snippet won't be
|
||||
expanded.
|
||||
* If it evaluate to the a cons cell where the ``car`` is the symbol
|
||||
``require-snippet-condition`` and the ``cdr`` is a symbol (let's
|
||||
call it ``requirement``):
|
||||
|
||||
* If the snippet has no condition, then it won't be expanded.
|
||||
* If the snippet has a condition but evaluate to nil or error
|
||||
occured during evaluation, it won't be expanded.
|
||||
* If the snippet has a condition that evaluate to non-nil (let's
|
||||
call it ``result``):
|
||||
|
||||
* If ``requirement`` is ``t``, the snippet is ready to be
|
||||
expanded.
|
||||
* If ``requirement`` is ``eq`` to ``result``, the snippet is ready
|
||||
to be expanded.
|
||||
* Otherwise the snippet won't be expanded.
|
||||
|
||||
* If it evaluate to other non-nil value:
|
||||
|
||||
* If the snippet has no condition, or has a condition that evaluate
|
||||
to non-nil, it is ready to be expanded.
|
||||
* Otherwise, it won't be expanded.
|
||||
|
||||
So set ``yas/buffer-local-condition`` like this
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(add-hook 'python-mode-hook
|
||||
'(lambda ()
|
||||
(setq yas/buffer-local-condition
|
||||
'(if (python-in-string/comment)
|
||||
'(require-snippet-condition . force-in-comment)
|
||||
t))))
|
||||
|
||||
And specify the condition for a snippet that you're going to expand in
|
||||
comment to be evaluated to the symbol ``force-in-comment``. Then it
|
||||
can be expanded as you expected, while other snippets like ``if``
|
||||
still can't expanded in comment.
|
||||
|
||||
Multiple snippet with the same key
|
||||
----------------------------------
|
||||
|
||||
There can be multiple snippet bind to the same key. If you define a
|
||||
snippet with a key that is already used, you'll overwrite the original
|
||||
snippet definition. However, you can add a different *postfix* to the
|
||||
key.
|
||||
|
||||
In general, the *extension* (consider a file name) is *ignored* when
|
||||
defining a snippet. So ``def``, ``def.1`` and ``def.mine`` will all be
|
||||
valid candidates when the key is ``def``.
|
||||
|
||||
When there are multiple candidates, YASnippet will let you select
|
||||
one. The UI for selecting multiple candidate can be
|
||||
customized. There're two variable related:
|
||||
|
||||
From version 0.6 of YASnippet this has changed significantly. A new
|
||||
customization variable, called ``yas/prompt-functions`` defines your
|
||||
preferred method of being prompted for snippets.
|
||||
|
||||
You can customize it with ``M-x customize-variable RET
|
||||
yas/prompt-functions RET``. Alternatively you can put in your
|
||||
emacs-file:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(setq yas/prompt-functions '(yas/x-prompt yas/dropdown-prompt))
|
||||
|
||||
Currently there are some alternatives solution with YASnippet.
|
||||
|
||||
.. image:: images/popup-menu.png
|
||||
:align: right
|
||||
|
||||
Use the X window system
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The function ``yas/x-prompt`` can be used to show a popup menu for you
|
||||
to select. This menu will be part of you native window system widget,
|
||||
which means:
|
||||
|
||||
* It usually looks beautiful. E.g. when you compile Emacs with gtk
|
||||
support, this menu will be rendered with your gtk theme.
|
||||
* Emacs have little control over it. E.g. you can't use ``C-n``,
|
||||
``C-p`` to navigate.
|
||||
* This function can't be used when in a terminal.
|
||||
|
||||
Use built-in Emacs selection methods
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can use functions ``yas/completing-prompt`` for the classic emacs
|
||||
completion method or ``yas/ido-prompt`` for a much nicer looking
|
||||
method. The best way is to try it. This works in a terminal.
|
||||
|
||||
.. image:: images/idrop-menu.png
|
||||
:align: center
|
||||
|
||||
Use ``dropdown-menu.el``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The function ``yas/dropdown-prompt`` can also be placed in the
|
||||
``yas/prompt-functions`` list.
|
||||
|
||||
.. image:: images/dropdown-menu.png
|
||||
:align: right
|
||||
|
||||
Originally, only the above two function is available in
|
||||
YASnippet. They are difficult to use -- especially in a
|
||||
terminal. Until later Jaeyoun Chung show me his ``dropdown-menu.el``,
|
||||
I say wow! It's wonderful!
|
||||
|
||||
* It works in both window system and terminal.
|
||||
* It is customizable, you can use ``C-n``, ``C-p`` to navigate, ``q``
|
||||
to quite and even press ``6`` as a shortcut to select the 6th
|
||||
candidate.
|
||||
|
||||
So I added ``yas/dropdown-list-popup-for-template`` to support
|
||||
``dropdown-list.el``. And upload ``dropdown-list.el`` to YASnippet
|
||||
hompage for an optional download (since Jaeyoun didn't provide a URL).
|
||||
|
||||
Then finally, in 0.4.0, I included a copy of the content of
|
||||
``dropdown-list.el`` in ``yasnippet.el`` and made it the default
|
||||
way for selecting multiple candidates.
|
||||
|
||||
However, the original functions are still there, you can still use this
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(setq yas/window-system-popup-function
|
||||
'yas/x-popup-menu-for-template)
|
||||
|
||||
if you prefer a *modern* UI. :)
|
||||
|
||||
The Trigger Key
|
||||
---------------
|
||||
|
||||
YASnippet is implemented as a minor-mode (``yas/minor-mode``). The
|
||||
trigger key ``yas/trigger-key`` is defined in ``yas/minor-mode-map``
|
||||
to call ``yas/expand`` to try to expand a snippet.
|
||||
|
||||
The Minor Mode
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. image:: images/minor-mode-indicator.png
|
||||
:align: left
|
||||
|
||||
When ``yas/minor-mode`` is enabled, the trigger key will take
|
||||
effect. The default key is ``(kbd "TAB")``, however, you can freely
|
||||
set it to some other key.
|
||||
|
||||
In version 0.5, YASnippet add a hook to
|
||||
``after-change-major-mode-hook`` to enable ``yas/minor-mode`` in
|
||||
every buffer. This works fine for most modes, however, some mode
|
||||
doesn't follow the Emacs convention and doens't call this hook. You
|
||||
can either explicitly hook for those mode or just add it to
|
||||
``yas/extra-mode-hooks`` to let YASnippet do it for you:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(require 'yasnippet)
|
||||
(add-to-list 'yas/extra-mode-hooks
|
||||
'ruby-mode-hook)
|
||||
(yas/initialize)
|
||||
|
||||
Note that **should** be put after ``(require 'yasnippet)`` and before
|
||||
``(yas/initialize)``. Further more, you may report it to me, I'll add
|
||||
that to the default value.
|
||||
|
||||
In version 0.6, just use ``yas/global-mode`` to enable YASnippet in
|
||||
all major modes. Or put ``yas/minor-mode-on`` in that modes hook. See
|
||||
the `FAQ <faq.html>`_.
|
||||
|
||||
The Fallback
|
||||
~~~~~~~~~~~~
|
||||
|
||||
If ``yas/expand`` failed to find any suitable snippet to expand, it
|
||||
will disable the minor mode temporarily and find if there's any other
|
||||
command bind the ``yas/trigger-key``. If found, the command will be
|
||||
called. Usually this works very well -- when there's a snippet, expand
|
||||
it, otherwise, call whatever command originally bind to the trigger
|
||||
key.
|
||||
|
||||
However, you can change this behavior by customizing the
|
||||
``yas/fallback-behavior`` variable. If you set this variable to
|
||||
``'return-nil``, it will return ``nil`` instead of trying to call the
|
||||
*original* command when no snippet is found. This is useful when you
|
||||
would like YASnippet to work with other extensions,
|
||||
e.g. ``hippie-expand``. I'm also glad to tell you that integration
|
||||
with ``hippie-expand`` is already included in YASnippet.
|
||||
|
||||
Integration with ``hippie-expand``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To integrate with ``hippie-expand``, just put
|
||||
``yas/hippie-try-expand`` in
|
||||
``hippie-expand-try-functions-list``. Personally I would like to put
|
||||
in front of the list, but it can be put anywhere you prefer.
|
||||
|
||||
Other way to select a snippet
|
||||
-----------------------------
|
||||
|
||||
When you use the trigger key (so ``yas/expand``) to expand a snippet,
|
||||
the key for the snippet is deleted before the template for the snippet
|
||||
is inserted.
|
||||
|
||||
However, there're other ways to insert a snippet.
|
||||
|
||||
``yas/insert-snippet``
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The command ``M-x yas/insert-snippet`` lets you insert snippets at
|
||||
point *for you current major mode*. It prompts you for the snippet
|
||||
key first, and then for a snippet template if more than one template
|
||||
exists for the same key.
|
||||
|
||||
The list presented contains the snippets that can be inserted at
|
||||
point, according to the condition system. If you want to see all
|
||||
applicable snippets for the major mode, prefix this command with
|
||||
``C-u``.
|
||||
|
||||
The prompting methods used are again controlled by
|
||||
``yas/prompt-functions``.
|
||||
|
||||
|
||||
|
||||
Expanding From Elisp Code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sometimes you might want to expand a snippet directly by calling a
|
||||
functin from elisp code. You should call ``yas/expand-snippet``
|
||||
instead of ``yas/expand`` in this case.
|
||||
|
||||
As with expanding from the menubar, condition system and multiple
|
||||
candidates won't exists here. In fact, expanding from menubar has the
|
||||
same effect of evaluating the follow code:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/expand-snippet (point) (point) template)
|
||||
|
||||
Where ``template`` is the template of a snippet. It is never required
|
||||
to belong to any snippet -- you can even make up it on the fly. The
|
||||
1st and 2nd parameter defines the region to be deleted after YASnippet
|
||||
inserted the template. It is used by ``yas/expand`` to indicate the
|
||||
region of the key. There's usually no need to delete any region when
|
||||
we are expanding a snippet from elisp code, so passing two ``(point)``
|
||||
is fine. Note only ``(point)`` will be fine because the 1st parameter
|
||||
also indicate where to insert and expand the ``template``.
|
||||
|
||||
|
||||
|
||||
Indenting
|
||||
---------
|
||||
|
||||
Many people miss the indenting feature of smart-snippet: when you
|
||||
place a ``$>`` in your snippet, an ``(indent-according-to-mode)`` will
|
||||
be executed there to indent the line. So you'll not need to hard-code
|
||||
the indenting in the snippet template, and it will be very convenient
|
||||
when you need to work with several different project where coding
|
||||
styles are different.
|
||||
|
||||
The reason why this feature wasn't added to YASnippet until after
|
||||
0.5.6 is that it doesn't work well for all modes. In some cases
|
||||
(e.g. python-mode), calling ``indent-according-to-mode`` will break
|
||||
the overlays created by YASnippet.
|
||||
|
||||
However, since many people asked for this feature, I finally added
|
||||
this to YASnippet. Here's an example of the usage:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
for (${int i = 0}; ${i < 10}; ${++i})
|
||||
{$>
|
||||
$0$>
|
||||
}$>
|
||||
|
||||
In 0.6.0 You should **not** need to use this feature although it's
|
||||
supported for backward compatibility. Just set ``yas/indent-line`` to
|
||||
``'auto``.
|
||||
|
||||
|
325
doc/snippet-organization.html
Normal file
325
doc/snippet-organization.html
Normal file
@ -0,0 +1,325 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Organizing snippets</title>
|
||||
<meta name="author" content="pluskid, joaotavora" />
|
||||
<meta name="date" content="2009-08-18" />
|
||||
<link rel="stylesheet" href="styles.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="organizing-snippets">
|
||||
<div id="header-region" class="clear-block"></div>
|
||||
<div id="wrapper">
|
||||
<div id="container" class="clear-block">
|
||||
<div id="header">
|
||||
<div id="logo-floater">
|
||||
<h1 class="title">Organizing snippets</h1>
|
||||
</div>
|
||||
<ul class="primary-links">
|
||||
<li>
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-organization.html">Organize</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-expansion.html">Expand</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-development.html">Write</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="changelog.html">ChangeLog</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="http://code.google.com/p/yasnippet/downloads/list">Download</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="center">
|
||||
<div id="squeeze">
|
||||
<div class="right-corner">
|
||||
<div class="left-corner">
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#new-style-storage-recommended" id="id1">New-style storage (recommended)</a></li>
|
||||
<li><a class="reference internal" href="#old-style-storage-pre-0-6" id="id2">Old-style storage (pre 0.6)</a></li>
|
||||
<li><a class="reference internal" href="#no-storage-bundle" id="id3">No storage (bundle)</a></li>
|
||||
<li><a class="reference internal" href="#define-snippets-in-files" id="id4">Define snippets in files</a><ul>
|
||||
<li><a class="reference internal" href="#directory-hierarchy" id="id5">Directory hierarchy</a></li>
|
||||
<li><a class="reference internal" href="#define-snippets-using-elisp-code" id="id6">Define snippets using elisp code</a><ul>
|
||||
<li><a class="reference internal" href="#yas-define-snippets" id="id7">yas/define-snippets</a></li>
|
||||
<li><a class="reference internal" href="#yas-define" id="id8">yas/define</a></li>
|
||||
<li><a class="reference internal" href="#yas-compile-bundle" id="id9">yas/compile-bundle</a></li>
|
||||
<li><a class="reference internal" href="#the-menu" id="id10">The Menu</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>There are three ways to keep your snippets:</p>
|
||||
<div class="section" id="new-style-storage-recommended">
|
||||
<h1><a class="toc-backref" href="#id1">New-style storage (recommended)</a></h1>
|
||||
<p>Hehe</p>
|
||||
</div>
|
||||
<div class="section" id="old-style-storage-pre-0-6">
|
||||
<h1><a class="toc-backref" href="#id2">Old-style storage (pre 0.6)</a></h1>
|
||||
<p>Blabla</p>
|
||||
</div>
|
||||
<div class="section" id="no-storage-bundle">
|
||||
<h1><a class="toc-backref" href="#id3">No storage (bundle)</a></h1>
|
||||
<p>The most convenient way to define snippets for YASnippet is to put
|
||||
them in a directory arranged by the mode and use
|
||||
<tt class="docutils literal"><span class="pre">yas/load-directory</span></tt> to load them.</p>
|
||||
<p>However, this might slow down the Emacs startup speed if you have many
|
||||
snippets. You can use <tt class="docutils literal"><span class="pre">yas/define-snippets</span></tt> to define a bunch of
|
||||
snippets for a perticular mode. But this is hard to maintain! So,
|
||||
there's a better way: define your snippets in directory and use
|
||||
<tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt> to compile it into a bundle file when you
|
||||
modified your snippets.</p>
|
||||
<p>The release bundle of YASnippet is produced by
|
||||
<tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt>. The bundle use <tt class="docutils literal"><span class="pre">yas/define-snippets</span></tt> to
|
||||
define snippets. This avoid the IO and parsing overhead when loading
|
||||
snippets.</p>
|
||||
<p>Finally, you can use <tt class="docutils literal"><span class="pre">yas/define</span></tt> to define a single snippet at your
|
||||
convenience. I ofthen use this to do some testing.</p>
|
||||
</div>
|
||||
<div class="section" id="define-snippets-in-files">
|
||||
<h1><a class="toc-backref" href="#id4">Define snippets in files</a></h1>
|
||||
<div class="section" id="directory-hierarchy">
|
||||
<h2><a class="toc-backref" href="#id5">Directory hierarchy</a></h2>
|
||||
<p>Here's the directory hierarchy of the <tt class="docutils literal"><span class="pre">snippets</span></tt> directory comes
|
||||
with YASnippet:</p>
|
||||
<div class="highlight"><pre>snippets
|
||||
`-- text-mode/
|
||||
|-- cc-mode/
|
||||
| |-- c++-mode/
|
||||
| | |-- beginend
|
||||
| | |-- class
|
||||
| | `-- using
|
||||
| |-- c-mode/
|
||||
| | `-- fopen
|
||||
| |-- do
|
||||
| |-- for
|
||||
| |-- if
|
||||
| |-- inc
|
||||
| |-- inc.1
|
||||
| |-- main
|
||||
| |-- once
|
||||
| `-- struct
|
||||
|-- css-mode/
|
||||
| |-- background
|
||||
| |-- background.1
|
||||
| `-- border
|
||||
|-- email
|
||||
|-- html-mode/
|
||||
| |-- div
|
||||
| |-- doctype
|
||||
| |-- doctype.xhml1
|
||||
| |-- doctype.xhtml1_1
|
||||
| |-- doctype.xhtml1_strict
|
||||
| `-- doctype.xhtml1_transitional
|
||||
|-- objc-mode/
|
||||
| `-- prop
|
||||
|-- perl-mode/
|
||||
| |-- cperl-mode/
|
||||
| |-- eval
|
||||
| |-- for
|
||||
| |-- fore
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- ifee
|
||||
| |-- sub
|
||||
| |-- unless
|
||||
| |-- while
|
||||
| |-- xfore
|
||||
| |-- xif
|
||||
| |-- xunless
|
||||
| `-- xwhile
|
||||
|-- python-mode/
|
||||
| |-- __
|
||||
| |-- class
|
||||
| |-- def
|
||||
| |-- for
|
||||
| |-- ifmain
|
||||
| `-- while
|
||||
|-- rst-mode/
|
||||
| |-- chapter
|
||||
| |-- section
|
||||
| `-- title
|
||||
|-- ruby-mode/
|
||||
| |-- #
|
||||
| |-- =b
|
||||
| |-- Comp
|
||||
| |-- all
|
||||
| |-- am
|
||||
| |-- any
|
||||
| |-- app
|
||||
| |-- bm
|
||||
| |-- case
|
||||
| |-- cla
|
||||
| |-- classify
|
||||
| |-- cls
|
||||
| |-- collect
|
||||
| |-- dee
|
||||
| |-- deli
|
||||
| |-- det
|
||||
| |-- ea
|
||||
| |-- eac
|
||||
| |-- eai
|
||||
| |-- eav
|
||||
| |-- eawi
|
||||
| |-- forin
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- inject
|
||||
| |-- mm
|
||||
| |-- r
|
||||
| |-- rb
|
||||
| |-- reject
|
||||
| |-- req
|
||||
| |-- rreq
|
||||
| |-- rw
|
||||
| |-- select
|
||||
| |-- w
|
||||
| |-- y
|
||||
| `-- zip
|
||||
`-- time
|
||||
</pre></div>
|
||||
<p>Snippet definitions are put in plain text files. They are arranged by
|
||||
subdirectories. For example, snippets for <tt class="docutils literal"><span class="pre">c-mode</span></tt> are put in the
|
||||
<tt class="docutils literal"><span class="pre">c-mode</span></tt> directory.</p>
|
||||
<p>The parent directory acts as the <em>parent mode</em>. This is the way of
|
||||
YASnippet to share snippet definitions among different modes. As you
|
||||
can see above, <tt class="docutils literal"><span class="pre">c-mode</span></tt> and <tt class="docutils literal"><span class="pre">c++-mode</span></tt> share the same parents
|
||||
<tt class="docutils literal"><span class="pre">cc-mode</span></tt>, while all modes are derived from <tt class="docutils literal"><span class="pre">text-mode</span></tt>. This can
|
||||
be also used to as an <em>alias</em> -- <tt class="docutils literal"><span class="pre">cperl-mode</span></tt> is an empty directory
|
||||
whose parent is <tt class="docutils literal"><span class="pre">perl-mode</span></tt>.</p>
|
||||
<p>File names act as the snippet trigger key. Note files starting with a
|
||||
dot (<tt class="docutils literal"><span class="pre">.</span></tt>) are ignored.</p>
|
||||
</div>
|
||||
<div class="section" id="define-snippets-using-elisp-code">
|
||||
<h2><a class="toc-backref" href="#id6">Define snippets using elisp code</a></h2>
|
||||
<p>As I mentioned above, you can define snippets directly by writing
|
||||
elisp code.</p>
|
||||
<div class="section" id="yas-define-snippets">
|
||||
<h3><a class="toc-backref" href="#id7">yas/define-snippets</a></h3>
|
||||
<p>The basic syntax of <tt class="docutils literal"><span class="pre">yas/define-snippets</span></tt> is</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define-snippets</span> <span style="color: #19177C">MODE</span> <span style="color: #19177C">SNIPPETS</span> <span style="color: #008000; font-weight: bold">&optional</span> <span style="color: #19177C">PARENT</span>)
|
||||
</pre></div>
|
||||
<p>The parameters are self-descriptive. If you specify a <tt class="docutils literal"><span class="pre">PARENT</span></tt>, then
|
||||
the snippets of the parents may be shared by <tt class="docutils literal"><span class="pre">MODE</span></tt>. Note if you use
|
||||
this function several times, the later specified <tt class="docutils literal"><span class="pre">PARENT</span></tt> will
|
||||
overwrite the original one. However, not specifying a <tt class="docutils literal"><span class="pre">PARENT</span></tt> won't
|
||||
erase the original parent.</p>
|
||||
<p>The <tt class="docutils literal"><span class="pre">SNIPPETS</span></tt> parameter is a list of snippet definitions. Each
|
||||
element should have the following form:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">KEY</span> <span style="color: #19177C">TEMPLATE</span> <span style="color: #19177C">NAME</span> <span style="color: #19177C">CONDITION</span> <span style="color: #19177C">GROUP</span>)
|
||||
</pre></div>
|
||||
<p>The <tt class="docutils literal"><span class="pre">NAME</span></tt>, <tt class="docutils literal"><span class="pre">CONDITION</span></tt> and <tt class="docutils literal"><span class="pre">GROUP</span></tt> can be omitted if you don't
|
||||
want to provide one. Here's an example:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define-snippets</span> <span style="color: #19177C">'c++-mode</span>
|
||||
<span style="color: #666666">'</span>(
|
||||
(<span style="color: #BA2121">"using"</span> <span style="color: #BA2121">"using namespace ${std};</span>
|
||||
<span style="color: #BA2121">$0"</span> <span style="color: #BA2121">"using namespace ... "</span> <span style="color: #880000">nil</span>)
|
||||
(<span style="color: #BA2121">"class"</span> <span style="color: #BA2121">"class ${1:Name}</span>
|
||||
<span style="color: #BA2121">{</span>
|
||||
<span style="color: #BA2121">public:</span>
|
||||
<span style="color: #BA2121"> $1($2);</span>
|
||||
<span style="color: #BA2121"> virtual ~$1();</span>
|
||||
<span style="color: #BA2121">};"</span> <span style="color: #BA2121">"class ... { ... }"</span> <span style="color: #880000">nil</span>)
|
||||
(<span style="color: #BA2121">"beginend"</span> <span style="color: #BA2121">"${1:v}.begin(), $1.end"</span> <span style="color: #BA2121">"v.begin(), v.end()"</span> <span style="color: #880000">nil</span>)
|
||||
)
|
||||
<span style="color: #19177C">'cc-mode</span>)
|
||||
</pre></div>
|
||||
<p>The example above is auto-generated code by <tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="yas-define">
|
||||
<h3><a class="toc-backref" href="#id8">yas/define</a></h3>
|
||||
<p>The basic syntax for <tt class="docutils literal"><span class="pre">yas/define</span></tt> is</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define</span> <span style="color: #19177C">mode</span> <span style="color: #19177C">key</span> <span style="color: #19177C">template</span> <span style="color: #008000; font-weight: bold">&optional</span> <span style="color: #19177C">name</span> <span style="color: #B00040">condition</span> <span style="color: #19177C">group</span>)
|
||||
</pre></div>
|
||||
<p>This is only a syntax sugar for</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/define-snippets</span> <span style="color: #19177C">mode</span>
|
||||
(<span style="color: #008000">list</span> (<span style="color: #008000">list</span> <span style="color: #19177C">key</span> <span style="color: #19177C">template</span> <span style="color: #19177C">name</span> <span style="color: #B00040">condition</span> <span style="color: #19177C">group</span>)))
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="section" id="yas-compile-bundle">
|
||||
<h3><a class="toc-backref" href="#id9">yas/compile-bundle</a></h3>
|
||||
<p><tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt> can be used to parse the snippets from a
|
||||
directory hierarchy and translate them into the elisp form. The
|
||||
translated code is faster to load. Further more, the generated bundle
|
||||
is a stand-alone file not depending on <tt class="docutils literal"><span class="pre">yasnippet.el</span></tt>. The released
|
||||
bundles of YASnippet are all generated this way.</p>
|
||||
</div>
|
||||
<div class="section" id="the-menu">
|
||||
<h3><a class="toc-backref" href="#id10">The Menu</a></h3>
|
||||
<p>YASnippet will setup a menu just after the <em>Buffers</em> Menu in the
|
||||
menubar. The snippets for all <em>real</em> modes are listed there under the
|
||||
menu. You can select a snippet from the menu to expand it. Since you
|
||||
select manually from the menu, you can expand any snippet. For
|
||||
example, you can expand a snippet defined for <tt class="docutils literal"><span class="pre">python-mode</span></tt> in a
|
||||
<tt class="docutils literal"><span class="pre">c-mode</span></tt> buffer by selecting it from the menu:</p>
|
||||
<img align="right" alt="images/menubar.png" class="align-right" src="images/menubar.png" />
|
||||
<ul class="simple">
|
||||
<li>Condition system is ignored since you select to expand it
|
||||
explicitly.</li>
|
||||
<li>There will be no muliple candidates since they are listed in the
|
||||
menu as different items.</li>
|
||||
</ul>
|
||||
<p>This can be convenient sometimes. However, if you don't like the
|
||||
menubar of Emacs and never use it. You can tell YASnippet don't boring
|
||||
to build a menu by setting <tt class="docutils literal"><span class="pre">yas/use-menu</span></tt> to nil.</p>
|
||||
<p>Another thing to note is that only <em>real</em> modes are listed under the
|
||||
menu. As you know, common snippets can be shared by making up a
|
||||
<em>virtual</em> parent mode. It's too bad if the menu is floored by those
|
||||
<em>virtual</em> modes. So YASnippet only show menus for those <em>real</em>
|
||||
modes. But the snippets fo the <em>virtual</em> modes can still be accessed
|
||||
through the <tt class="docutils literal"><span class="pre">parent</span></tt> submenu of some <em>real</em> mode.</p>
|
||||
<p>YASnippet use a simple way to check whether a mode is <em>real</em> or
|
||||
<em>virtual</em>: <tt class="docutils literal"><span class="pre">(fboundp</span> <span class="pre">mode)</span></tt>. For example, the symbol <tt class="docutils literal"><span class="pre">c-mode</span></tt> is
|
||||
bound to a function while <tt class="docutils literal"><span class="pre">cc-mode</span></tt> is not. But this is not enough,
|
||||
some modes aren't part of Emacs, and maybe when initializing
|
||||
YASnippet, those modes haven't been initialized. So YASnippet also
|
||||
maintain a list of known modes (<tt class="docutils literal"><span class="pre">yas/known-modes</span></tt>). You can add item
|
||||
to that list if you need.</p>
|
||||
<p>The basic syntax of <tt class="docutils literal"><span class="pre">yas/compile-bundle</span></tt> is</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/compile-bundle</span> <span style="color: #008000; font-weight: bold">&optional</span> <span style="color: #19177C">yasnippet</span> <span style="color: #19177C">yasnippet-bundle</span> <span style="color: #19177C">snippet-roots</span> <span style="color: #19177C">code</span> <span style="color: #19177C">dropdown</span>)
|
||||
</pre></div>
|
||||
<p>As you can see, all the parameters are optional. The default values
|
||||
for those parameters are convenient for me to produce the default
|
||||
release bundle:</p>
|
||||
<div class="highlight"><pre>(<span style="color: #19177C">yas/compile-bundle</span> <span style="color: #BA2121">"yasnippet.el"</span>
|
||||
<span style="color: #BA2121">"./yasnippet-bundle.el"</span>
|
||||
<span style="color: #666666">'</span>(<span style="color: #BA2121">"snippets"</span>)
|
||||
<span style="color: #BA2121">"(yas/initialize)"</span>
|
||||
<span style="color: #BA2121">"dropdown-list.el"</span>)
|
||||
</pre></div>
|
||||
<p>The <tt class="docutils literal"><span class="pre">snippet-roots</span></tt> can be a list of root directories. This is
|
||||
useful when you have multiple snippet directories (maybe from other
|
||||
users). The <tt class="docutils literal"><span class="pre">code</span></tt> parameter can be used to specify your own
|
||||
customization code instead of the default <tt class="docutils literal"><span class="pre">(yas/initialize)</span></tt>. For
|
||||
example, you can set <tt class="docutils literal"><span class="pre">yas/trigger-key</span></tt> to <tt class="docutils literal"><span class="pre">(kbd</span> <span class="pre">"SPC")</span></tt> here if
|
||||
you like.</p>
|
||||
<p>From release 0.6 you have to specify the <tt class="docutils literal"><span class="pre">dropdown-list.el</span></tt> file if
|
||||
you want it to be a part of the generated bundle.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
307
doc/snippet-organization.rst
Normal file
307
doc/snippet-organization.rst
Normal file
@ -0,0 +1,307 @@
|
||||
===================
|
||||
Organizing snippets
|
||||
===================
|
||||
|
||||
:Author: pluskid, joaotavora
|
||||
:Contact: pluskid@gmail.com
|
||||
:Date: 2009-08-18
|
||||
|
||||
.. contents::
|
||||
|
||||
There are three ways to keep your snippets:
|
||||
|
||||
|
||||
New-style storage (recommended)
|
||||
===============================
|
||||
|
||||
Hehe
|
||||
|
||||
Old-style storage (pre 0.6)
|
||||
===========================
|
||||
|
||||
Blabla
|
||||
|
||||
No storage (bundle)
|
||||
===================
|
||||
|
||||
The most convenient way to define snippets for YASnippet is to put
|
||||
them in a directory arranged by the mode and use
|
||||
``yas/load-directory`` to load them.
|
||||
|
||||
However, this might slow down the Emacs startup speed if you have many
|
||||
snippets. You can use ``yas/define-snippets`` to define a bunch of
|
||||
snippets for a perticular mode. But this is hard to maintain! So,
|
||||
there's a better way: define your snippets in directory and use
|
||||
``yas/compile-bundle`` to compile it into a bundle file when you
|
||||
modified your snippets.
|
||||
|
||||
The release bundle of YASnippet is produced by
|
||||
``yas/compile-bundle``. The bundle use ``yas/define-snippets`` to
|
||||
define snippets. This avoid the IO and parsing overhead when loading
|
||||
snippets.
|
||||
|
||||
Finally, you can use ``yas/define`` to define a single snippet at your
|
||||
convenience. I ofthen use this to do some testing.
|
||||
|
||||
Define snippets in files
|
||||
========================
|
||||
|
||||
Directory hierarchy
|
||||
-------------------
|
||||
|
||||
Here's the directory hierarchy of the ``snippets`` directory comes
|
||||
with YASnippet:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
snippets
|
||||
`-- text-mode/
|
||||
|-- cc-mode/
|
||||
| |-- c++-mode/
|
||||
| | |-- beginend
|
||||
| | |-- class
|
||||
| | `-- using
|
||||
| |-- c-mode/
|
||||
| | `-- fopen
|
||||
| |-- do
|
||||
| |-- for
|
||||
| |-- if
|
||||
| |-- inc
|
||||
| |-- inc.1
|
||||
| |-- main
|
||||
| |-- once
|
||||
| `-- struct
|
||||
|-- css-mode/
|
||||
| |-- background
|
||||
| |-- background.1
|
||||
| `-- border
|
||||
|-- email
|
||||
|-- html-mode/
|
||||
| |-- div
|
||||
| |-- doctype
|
||||
| |-- doctype.xhml1
|
||||
| |-- doctype.xhtml1_1
|
||||
| |-- doctype.xhtml1_strict
|
||||
| `-- doctype.xhtml1_transitional
|
||||
|-- objc-mode/
|
||||
| `-- prop
|
||||
|-- perl-mode/
|
||||
| |-- cperl-mode/
|
||||
| |-- eval
|
||||
| |-- for
|
||||
| |-- fore
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- ifee
|
||||
| |-- sub
|
||||
| |-- unless
|
||||
| |-- while
|
||||
| |-- xfore
|
||||
| |-- xif
|
||||
| |-- xunless
|
||||
| `-- xwhile
|
||||
|-- python-mode/
|
||||
| |-- __
|
||||
| |-- class
|
||||
| |-- def
|
||||
| |-- for
|
||||
| |-- ifmain
|
||||
| `-- while
|
||||
|-- rst-mode/
|
||||
| |-- chapter
|
||||
| |-- section
|
||||
| `-- title
|
||||
|-- ruby-mode/
|
||||
| |-- #
|
||||
| |-- =b
|
||||
| |-- Comp
|
||||
| |-- all
|
||||
| |-- am
|
||||
| |-- any
|
||||
| |-- app
|
||||
| |-- bm
|
||||
| |-- case
|
||||
| |-- cla
|
||||
| |-- classify
|
||||
| |-- cls
|
||||
| |-- collect
|
||||
| |-- dee
|
||||
| |-- deli
|
||||
| |-- det
|
||||
| |-- ea
|
||||
| |-- eac
|
||||
| |-- eai
|
||||
| |-- eav
|
||||
| |-- eawi
|
||||
| |-- forin
|
||||
| |-- if
|
||||
| |-- ife
|
||||
| |-- inject
|
||||
| |-- mm
|
||||
| |-- r
|
||||
| |-- rb
|
||||
| |-- reject
|
||||
| |-- req
|
||||
| |-- rreq
|
||||
| |-- rw
|
||||
| |-- select
|
||||
| |-- w
|
||||
| |-- y
|
||||
| `-- zip
|
||||
`-- time
|
||||
|
||||
Snippet definitions are put in plain text files. They are arranged by
|
||||
subdirectories. For example, snippets for ``c-mode`` are put in the
|
||||
``c-mode`` directory.
|
||||
|
||||
The parent directory acts as the *parent mode*. This is the way of
|
||||
YASnippet to share snippet definitions among different modes. As you
|
||||
can see above, ``c-mode`` and ``c++-mode`` share the same parents
|
||||
``cc-mode``, while all modes are derived from ``text-mode``. This can
|
||||
be also used to as an *alias* -- ``cperl-mode`` is an empty directory
|
||||
whose parent is ``perl-mode``.
|
||||
|
||||
File names act as the snippet trigger key. Note files starting with a
|
||||
dot (``.``) are ignored.
|
||||
|
||||
Define snippets using elisp code
|
||||
--------------------------------
|
||||
|
||||
As I mentioned above, you can define snippets directly by writing
|
||||
elisp code.
|
||||
|
||||
yas/define-snippets
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The basic syntax of ``yas/define-snippets`` is
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define-snippets MODE SNIPPETS &optional PARENT)
|
||||
|
||||
The parameters are self-descriptive. If you specify a ``PARENT``, then
|
||||
the snippets of the parents may be shared by ``MODE``. Note if you use
|
||||
this function several times, the later specified ``PARENT`` will
|
||||
overwrite the original one. However, not specifying a ``PARENT`` won't
|
||||
erase the original parent.
|
||||
|
||||
The ``SNIPPETS`` parameter is a list of snippet definitions. Each
|
||||
element should have the following form:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(KEY TEMPLATE NAME CONDITION GROUP)
|
||||
|
||||
The ``NAME``, ``CONDITION`` and ``GROUP`` can be omitted if you don't
|
||||
want to provide one. Here's an example:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define-snippets 'c++-mode
|
||||
'(
|
||||
("using" "using namespace ${std};
|
||||
$0" "using namespace ... " nil)
|
||||
("class" "class ${1:Name}
|
||||
{
|
||||
public:
|
||||
$1($2);
|
||||
virtual ~$1();
|
||||
};" "class ... { ... }" nil)
|
||||
("beginend" "${1:v}.begin(), $1.end" "v.begin(), v.end()" nil)
|
||||
)
|
||||
'cc-mode)
|
||||
|
||||
The example above is auto-generated code by ``yas/compile-bundle``.
|
||||
|
||||
|
||||
yas/define
|
||||
~~~~~~~~~~
|
||||
|
||||
The basic syntax for ``yas/define`` is
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define mode key template &optional name condition group)
|
||||
|
||||
This is only a syntax sugar for
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/define-snippets mode
|
||||
(list (list key template name condition group)))
|
||||
|
||||
yas/compile-bundle
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``yas/compile-bundle`` can be used to parse the snippets from a
|
||||
directory hierarchy and translate them into the elisp form. The
|
||||
translated code is faster to load. Further more, the generated bundle
|
||||
is a stand-alone file not depending on ``yasnippet.el``. The released
|
||||
bundles of YASnippet are all generated this way.
|
||||
|
||||
|
||||
|
||||
The Menu
|
||||
~~~~~~~~
|
||||
|
||||
YASnippet will setup a menu just after the *Buffers* Menu in the
|
||||
menubar. The snippets for all *real* modes are listed there under the
|
||||
menu. You can select a snippet from the menu to expand it. Since you
|
||||
select manually from the menu, you can expand any snippet. For
|
||||
example, you can expand a snippet defined for ``python-mode`` in a
|
||||
``c-mode`` buffer by selecting it from the menu:
|
||||
|
||||
.. image:: images/menubar.png
|
||||
:align: right
|
||||
|
||||
* Condition system is ignored since you select to expand it
|
||||
explicitly.
|
||||
* There will be no muliple candidates since they are listed in the
|
||||
menu as different items.
|
||||
|
||||
This can be convenient sometimes. However, if you don't like the
|
||||
menubar of Emacs and never use it. You can tell YASnippet don't boring
|
||||
to build a menu by setting ``yas/use-menu`` to nil.
|
||||
|
||||
Another thing to note is that only *real* modes are listed under the
|
||||
menu. As you know, common snippets can be shared by making up a
|
||||
*virtual* parent mode. It's too bad if the menu is floored by those
|
||||
*virtual* modes. So YASnippet only show menus for those *real*
|
||||
modes. But the snippets fo the *virtual* modes can still be accessed
|
||||
through the ``parent`` submenu of some *real* mode.
|
||||
|
||||
YASnippet use a simple way to check whether a mode is *real* or
|
||||
*virtual*: ``(fboundp mode)``. For example, the symbol ``c-mode`` is
|
||||
bound to a function while ``cc-mode`` is not. But this is not enough,
|
||||
some modes aren't part of Emacs, and maybe when initializing
|
||||
YASnippet, those modes haven't been initialized. So YASnippet also
|
||||
maintain a list of known modes (``yas/known-modes``). You can add item
|
||||
to that list if you need.
|
||||
|
||||
The basic syntax of ``yas/compile-bundle`` is
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/compile-bundle &optional yasnippet yasnippet-bundle snippet-roots code dropdown)
|
||||
|
||||
As you can see, all the parameters are optional. The default values
|
||||
for those parameters are convenient for me to produce the default
|
||||
release bundle:
|
||||
|
||||
.. sourcecode:: common-lisp
|
||||
|
||||
(yas/compile-bundle "yasnippet.el"
|
||||
"./yasnippet-bundle.el"
|
||||
'("snippets")
|
||||
"(yas/initialize)"
|
||||
"dropdown-list.el")
|
||||
|
||||
The ``snippet-roots`` can be a list of root directories. This is
|
||||
useful when you have multiple snippet directories (maybe from other
|
||||
users). The ``code`` parameter can be used to specify your own
|
||||
customization code instead of the default ``(yas/initialize)``. For
|
||||
example, you can set ``yas/trigger-key`` to ``(kbd "SPC")`` here if
|
||||
you like.
|
||||
|
||||
From release 0.6 you have to specify the ``dropdown-list.el`` file if
|
||||
you want it to be a part of the generated bundle.
|
@ -14,7 +14,13 @@
|
||||
<a title="" href="index.html">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="define_snippet.html">Howto</a>
|
||||
<a title="" href="snippet-organization.html">Organize</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-expansion.html">Expand</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="snippet-development.html">Write</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="" href="faq.html">FAQ</a>
|
||||
|
167
snippet_copier.rb
Executable file
167
snippet_copier.rb
Executable file
@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env ruby
|
||||
# This is a quick script to generate YASnippets from TextMate Snippets.
|
||||
#
|
||||
# I based the script off of a python script of a similar nature by
|
||||
# Jeff Wheeler: http://nokrev.com
|
||||
# http://code.nokrev.com/?p=snippet-copier.git;a=blob_plain;f=snippet_copier.py
|
||||
#
|
||||
# Usage
|
||||
#
|
||||
# Make sure you have the plist and the choice gem installed
|
||||
# $ sudo gem install plist
|
||||
# $ sudo gem install choice
|
||||
#
|
||||
# Usage: snippet_copier.rb [-dofp]
|
||||
#
|
||||
# Standard Options:
|
||||
# -d, --snippet-dir=PATH Tells the program the directory to find the TextMate Snippets
|
||||
# -o, --output-dir=PATH What directory to write the new YASnippets to
|
||||
# -f, --file=SNIPPET FILE NAME A specific snippet that you want to copy or a glob for various files
|
||||
# -p, --pretty-print Pretty prints multiple snippets when printing to standard out
|
||||
#
|
||||
# Common options:
|
||||
# --help Show this message
|
||||
require 'rubygems'
|
||||
require 'plist'
|
||||
require 'choice'
|
||||
|
||||
Choice.options do
|
||||
header ''
|
||||
header 'Standard Options:'
|
||||
|
||||
option :snippet_dir do
|
||||
short '-d'
|
||||
long '--snippet-dir=PATH'
|
||||
desc 'Tells the program the directory to find the TextMate Snippets'
|
||||
default '.'
|
||||
end
|
||||
|
||||
option :output_dir do
|
||||
short '-o'
|
||||
long '--output-dir=PATH'
|
||||
desc 'What directory to write the new YASnippets to'
|
||||
end
|
||||
|
||||
option :snippet do
|
||||
short '-f'
|
||||
long '--file=SNIPPET FILE NAME'
|
||||
desc 'A specific snippet that you want to copy or a glob for various files'
|
||||
default '*.{tmSnippet,plist}'
|
||||
end
|
||||
|
||||
option :pretty_print do
|
||||
short '-p'
|
||||
long '--pretty-print'
|
||||
desc 'Pretty prints multiple snippets when printing to standard out'
|
||||
end
|
||||
|
||||
separator ''
|
||||
separator 'Common options: '
|
||||
|
||||
option :help do
|
||||
long '--help'
|
||||
desc 'Show this message'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class TmSnippet
|
||||
@@known_substitutions = {
|
||||
"${TM_RAILS_TEMPLATE_START_RUBY_EXPR}" => "<%= ",
|
||||
"${TM_RAILS_TEMPLATE_END_RUBY_EXPR}" => " %>",
|
||||
"${TM_RAILS_TEMPLATE_START_RUBY_INLINE}" => "<% ",
|
||||
"${TM_RAILS_TEMPLATE_END_RUBY_INLINE}" => " -%>",
|
||||
"${TM_RAILS_TEMPLATE_END_RUBY_BLOCK}" => "end" ,
|
||||
/$\{TM_SELECTED_TEXT.*\}/ => "`yas/selected-text`" }
|
||||
|
||||
def initialize(file)
|
||||
@snippet = Plist::parse_xml(file)
|
||||
end
|
||||
|
||||
def name
|
||||
@snippet["name"]
|
||||
end
|
||||
|
||||
def tab_trigger
|
||||
@snippet["tabTrigger"]
|
||||
end
|
||||
|
||||
def key_equivalent
|
||||
@snippet["keyEquivalent"]
|
||||
end
|
||||
|
||||
def content
|
||||
@snippet["content"]
|
||||
end
|
||||
|
||||
def to_yasnippet
|
||||
doc = "# -*- mode: snippet -*-\n"
|
||||
doc << "#key: #{self.tab_trigger}\n" if self.tab_trigger
|
||||
doc << "#contributor : Translated from TextMate Snippet\n"
|
||||
doc << "#name : #{self.name}\n"
|
||||
doc << "#binding : \"#{self.key_equivalent}\"\n" if self.key_equivalent
|
||||
doc << "# --\n"
|
||||
@@known_substitutions.each_pair { |k, v| self.content.gsub!(k,v) }
|
||||
doc << "#{self.content}"
|
||||
end
|
||||
end
|
||||
|
||||
# def yasnippet_file_name(dir, snippet, ext=nil)
|
||||
# begin
|
||||
# file = ""
|
||||
# shortname = (snippet.tab_trigger or
|
||||
# snippet.name.gsub(/[^a-z0-9_-].*/,""))
|
||||
# if ext
|
||||
# file = File.join(dir, shortname + "." + ext.to_s)
|
||||
# else
|
||||
# file = File.join(dir, shortname)
|
||||
# end
|
||||
# if File.exist?(file)
|
||||
# if ext
|
||||
# file = yasnippet_file_name(dir,snippet, ext+1)
|
||||
# else
|
||||
# file = yasnippet_file_name(dir,snippet, 1)
|
||||
# end
|
||||
# end
|
||||
# # puts "returning #{file} since shortname is #{shortname}\n"
|
||||
# file
|
||||
# rescue TypeError
|
||||
# raise "Cannot convert " + snippet.name + " (probably no tab-trigger)"
|
||||
# end
|
||||
# end
|
||||
|
||||
def yasnippet_dir_and_name(dir, file)
|
||||
dir = File.join(dir,File.dirname(file))
|
||||
file = File.join(File.basename(file, File.extname(file))) << ".yasnippet"
|
||||
[dir, file]
|
||||
end
|
||||
|
||||
snippet_files_glob = File.join(Choice.choices.snippet_dir, "**", Choice.choices.snippet)
|
||||
snippet_files = Dir.glob(snippet_files_glob)
|
||||
|
||||
puts "Will try to convert #{snippet_files.length} snippets...\n"
|
||||
|
||||
snippet_files.each do |file|
|
||||
puts "Processing #{file}\n"
|
||||
snippet = TmSnippet.new(file)
|
||||
if Choice.choices.output_dir
|
||||
begin
|
||||
( dir_to_create, file_to_create ) = yasnippet_dir_and_name(Choice.choices.output_dir, file)
|
||||
FileUtils.mkdir_p(dir_to_create)
|
||||
File.open(File.join(dir_to_create,file_to_create), 'w') do |f|
|
||||
f.write(snippet.to_yasnippet)
|
||||
end
|
||||
rescue RuntimeError => error
|
||||
$stderr.print error.message + "\n"
|
||||
end
|
||||
else
|
||||
if Choice.choices.pretty_print
|
||||
puts "--------------------------------------------"
|
||||
end
|
||||
puts snippet.to_yasnippet
|
||||
if Choice.choices.pretty_print
|
||||
puts "--------------------------------------------"
|
||||
end
|
||||
puts "\n\n"
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user