Cleaning up before release commit...

This commit is contained in:
capitaomorte 2009-07-24 19:29:36 +00:00
parent 102424118e
commit 2f21c06622
4 changed files with 277 additions and 113 deletions

View File

@ -10,16 +10,30 @@ ChangeLog
0.6.0b / 2009-07-2x 0.6.0b / 2009-07-2x
=================== ===================
* Nested placeholders of the type <div${1: id="${2:someid}"}> $0 * Nested placeholders of the type ``<div${1: id="${2:someid}"}> $0``.
* More robust undo/redo support
* Stacked snippet expansion (snippet in snippet) * More robust undo/redo support.
* Transformation on a primary field, the syntax being
* Validation on field exit * Stacked snippet expansion (*snippet in snippet*).
* Wrapping the region in the exit marker $0 of the snippet
* Auto-indentation * Transformation on a primary field with syntax ``${1:default$(transform)}``
* Easier definition of snippets
* Customization group * Validations on field exit through the ``yas/verify-value``
* Overriding customization variables in snippets primary field transformation.
* Wrapping the region in the exit marker ``$0`` of the snippet. Use
``yas/wrap-around-region``.
* Auto-indentation. Use ``yas/indent-line`` set to ``'auto``
* Easier definition of snippets. Use ``yas/find-snippets`` or
``yas/visit-snippet-file``. In the new ``snippet-mode`` use
``yas/load-snippet-buffer`` and ``yas/tryout-snippet``.
* Customization group ``yasnippet``.
* Overriding customization variables in snippets. Use the ``env:
let-form`` template keyword.
* Fixed `Issue 60 * Fixed `Issue 60
<http://code.google.com/p/yasnippet/issues/detail?id=60>`_ <http://code.google.com/p/yasnippet/issues/detail?id=60>`_

View File

@ -2,9 +2,9 @@
How to define a snippet ? How to define a snippet ?
========================= =========================
:Author: pluskid :Author: pluskid, joaotavora
:Contact: pluskid@gmail.com :Contact: pluskid@gmail.com
:Date: 2008-03-20 :Date: 2009-07-24
.. contents:: .. contents::
@ -202,7 +202,30 @@ ignored. Here's a list of currently supported meta data:
under the ``loops`` group which is under the ``control structure`` under the ``loops`` group which is under the ``control structure``
group. group.
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 Define snippets using elisp code
-------------------------------- --------------------------------
@ -266,7 +289,7 @@ The basic syntax of ``yas/compile-bundle`` is
.. sourcecode:: common-lisp .. sourcecode:: common-lisp
(yas/compile-bundle &optional yasnippet yasnippet-bundle snippet-roots code) (yas/compile-bundle &optional yasnippet yasnippet-bundle snippet-roots code dropdown)
As you can see, all the parameters are optional. The default values As you can see, all the parameters are optional. The default values
for those parameters are convenient for me to produce the default for those parameters are convenient for me to produce the default
@ -277,7 +300,8 @@ release bundle:
(yas/compile-bundle "yasnippet.el" (yas/compile-bundle "yasnippet.el"
"./yasnippet-bundle.el" "./yasnippet-bundle.el"
'("snippets") '("snippets")
"(yas/initialize)") "(yas/initialize)"
"dropdown-list.el")
The ``snippet-roots`` can be a list of root directories. This is The ``snippet-roots`` can be a list of root directories. This is
useful when you have multiple snippet directories (maybe from other useful when you have multiple snippet directories (maybe from other
@ -286,6 +310,9 @@ customization code instead of the default ``(yas/initialize)``. For
example, you can set ``yas/trigger-key`` to ``(kbd "SPC")`` here if example, you can set ``yas/trigger-key`` to ``(kbd "SPC")`` here if
you like. 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 yas/define
~~~~~~~~~~ ~~~~~~~~~~
@ -419,22 +446,28 @@ When there are multiple candidates, YASnippet will let you select
one. The UI for selecting multiple candidate can be one. The UI for selecting multiple candidate can be
customized. There're two variable related: customized. There're two variable related:
* ``yas/window-system-popup-function``: the function used when you From version 0.6 of YASnippet this has changed significantly. A
have a window system. customization variable, called ``yas/prompt-functions`` defines your
* ``yas/text-popup-function``: the function used when you don't have a preferred method of being prompted for snippets.
window system, i.e. when you are working in a terminal.
Currently there're three solution come with YASnippet. 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 .. image:: images/popup-menu.png
:align: right :align: right
Popup Menu Use the X window system
~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
The function ``yas/x-popup-menu-for-template`` can be used to show a The function ``yas/x-prompt`` can be used to show a popup menu for you
popup menu for you to select. This menu will be part of you native to select. This menu will be part of you native window system widget,
window system widget, which means: which means:
* It usually looks beautiful. E.g. when you compile Emacs with gtk * It usually looks beautiful. E.g. when you compile Emacs with gtk
support, this menu will be rendered with your gtk theme. support, this menu will be rendered with your gtk theme.
@ -442,15 +475,18 @@ window system widget, which means:
``C-p`` to navigate. ``C-p`` to navigate.
* This function can't be used when in a terminal. * This function can't be used when in a terminal.
Just select the first one Use built-in Emacs selection methods
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This one is originally used in terminal mode. It doesn't let you to You can use functions ``yas/completing-prompt`` for the classic emacs
choose anything, it just select the first one on behalf of you. So I completion method or ``yas/ido-prompt`` for a much nicer looking
bet you never want to use this. :p method. The best way is to try it. This works in a terminal.
Use a dropdown-menu.el Use ``dropdown-menu.el``
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
The function ``yas/dropdown-prompt`` can also be placed in the
``yas/prompt-functions`` list.
.. image:: images/dropdown-menu.png .. image:: images/dropdown-menu.png
:align: right :align: right
@ -497,7 +533,9 @@ The Minor Mode
When ``yas/minor-mode`` is enabled, the trigger key will take When ``yas/minor-mode`` is enabled, the trigger key will take
effect. The default key is ``(kbd "TAB")``, however, you can freely effect. The default key is ``(kbd "TAB")``, however, you can freely
set it to some other key. By default, YASnippet add a hook to 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 ``after-change-major-mode-hook`` to enable ``yas/minor-mode`` [2]_ in
every buffer. This works fine for most modes, however, some mode every buffer. This works fine for most modes, however, some mode
doesn't follow the Emacs convention and doens't call this hook. You doesn't follow the Emacs convention and doens't call this hook. You
@ -515,6 +553,10 @@ Note that **should** be put after ``(require 'yasnippet)`` and before
``(yas/initialize)``. Further more, you may report it to me, I'll add ``(yas/initialize)``. Further more, you may report it to me, I'll add
that to the default value. 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 The Fallback
~~~~~~~~~~~~ ~~~~~~~~~~~~
@ -644,8 +686,22 @@ example for ``c-mode`` to calculate the header file guard dynamically:
#endif /* $1 */ #endif /* $1 */
Tab Stops 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.
Fields of type "Tab Stop"
-------------------------
Tab stops are fields that you can navigate back and forth by ``TAB`` Tab stops are fields that you can navigate back and forth by ``TAB``
and ``S-TAB`` [3]_. They are written by ``$`` followed with a and ``S-TAB`` [3]_. They are written by ``$`` followed with a
@ -659,8 +715,8 @@ fields. Here's a typical example:
$0 $0
</div> </div>
Placeholders Fields of type "Placeholder"
------------ ----------------------------
Tab stops can have default values -- a.k.a placeholders. The syntax is Tab stops can have default values -- a.k.a placeholders. The syntax is
like this: like this:
@ -701,8 +757,8 @@ as the field and others mirrors.
.. _transformations: .. _transformations:
Transformations Mirrors with transformations
--------------- ----------------------------
If the default value of a field starts with ``$``, then it is interpreted If the default value of a field starts with ``$``, then it is interpreted
as the transformation code instead of default value. A transformation as the transformation code instead of default value. A transformation
@ -764,6 +820,79 @@ is not. Here's an snippet for rst title:
.. [2] This is done when you call ``yas/initialize``. .. [2] This is done when you call ``yas/initialize``.
.. [3] Of course, this can be customized. .. [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 Indenting
--------- ---------
@ -789,3 +918,7 @@ this to YASnippet. Here's an example of the usage:
$0$> $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``.

View File

@ -28,11 +28,15 @@ following code to your ``.emacs`` *before* loading YASnippet:
.. sourcecode:: lisp .. sourcecode:: lisp
(setq yas/extra-mode-hooks '(the-major-mode)) (add-hook 'the-major-mode-hook 'yas/minor-mode-on)
where ``the-major-mode`` is the major mode in which ``yas/minor-mode`` where ``the-major-mode`` is the major mode in which ``yas/minor-mode``
isn't enabled by default. isn't enabled by default.
From YASnippet 0.6 you can also use the command ``M-x
yas/global-mode`` to turn on YASnippet automatically for *all* major
modes.
If ``yas/minor-mode`` is on but the snippet still not expanded. Then If ``yas/minor-mode`` is on but the snippet still not expanded. Then
try to see what command is bound to the ``TAB`` key: press ``C-h k`` try to see what command is bound to the ``TAB`` key: press ``C-h k``
and then press ``TAB``. Emacs will show you the result. and then press ``TAB``. Emacs will show you the result.

View File

@ -33,7 +33,7 @@
;; (require 'yasnippet) ;; (require 'yasnippet)
;; 2. Place the `snippets' directory somewhere. E.g: ~/.emacs.d/snippets ;; 2. Place the `snippets' directory somewhere. E.g: ~/.emacs.d/snippets
;; 3. In your .emacs file ;; 3. In your .emacs file
;; (setq yas/root-directory "~/.emacs/snippets") ;; (setq yas/root-directory "~/.emacs/snippets")
;; (yas/load-directory yas/root-directory) ;; (yas/load-directory yas/root-directory)
;; 4. To enable the YASnippet menu and tab-trigger expansion ;; 4. To enable the YASnippet menu and tab-trigger expansion
;; M-x yas/minor-mode ;; M-x yas/minor-mode
@ -48,7 +48,7 @@
;; ;;
;; M-x yas/expand ;; M-x yas/expand
;; ;;
;; Try to expand snippets before point. In `yas/minor-mode', ;; Try to expand snippets before point. In `yas/minor-mode',
;; this is bound to `yas/trigger-key' which you can customize. ;; this is bound to `yas/trigger-key' which you can customize.
;; ;;
;; M-x yas/load-directory ;; M-x yas/load-directory
@ -59,7 +59,7 @@
;; ;;
;; Prompts you for possible snippet expansion if that is ;; Prompts you for possible snippet expansion if that is
;; possible according to buffer-local and snippet-local ;; possible according to buffer-local and snippet-local
;; expansion conditions. With prefix argument, ignore these ;; expansion conditions. With prefix argument, ignore these
;; conditions. ;; conditions.
;; ;;
;; M-x yas/find-snippets ;; M-x yas/find-snippets
@ -68,7 +68,7 @@
;; snippet was loaded from (if it exists) like ;; snippet was loaded from (if it exists) like
;; `find-file-other-window'. ;; `find-file-other-window'.
;; ;;
;; M-x yas/find-snippet-file ;; M-x yas/visit-snippet-file
;; ;;
;; Prompts you for possible snippet expasions like ;; Prompts you for possible snippet expasions like
;; `yas/insert-snippet', but instead of expanding it, takes ;; `yas/insert-snippet', but instead of expanding it, takes
@ -77,10 +77,17 @@
;; ;;
;; M-x yas/load-snippet-buffer ;; M-x yas/load-snippet-buffer
;; ;;
;; When editing a snippet, this loads the snippet. This is ;; When editing a snippet, this loads the snippet. This is
;; bound to "C-c C-c" while in the `snippet-mode' editing ;; bound to "C-c C-c" while in the `snippet-mode' editing
;; mode. ;; 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'.
;;
;; The `dropdown-list.el' extension is bundled with YASnippet, you ;; The `dropdown-list.el' extension is bundled with YASnippet, you
;; can optionally use it the preferred "prompting method", puting in ;; can optionally use it the preferred "prompting method", puting in
;; your .emacs file, for example: ;; your .emacs file, for example:
@ -92,9 +99,9 @@
;; ;;
;; Also check out the customization group ;; Also check out the customization group
;; ;;
;; M-x customize-group RET yasnippet RET ;; M-x customize-group RET yasnippet RET
;; ;;
;; For more information and detailed usage, refer to the project page: ;; For more information and detailed usage, refer to the project page:
;; http://code.google.com/p/yasnippet/ ;; http://code.google.com/p/yasnippet/
;;; Code: ;;; Code:
@ -111,18 +118,18 @@
:group 'editing) :group 'editing)
(defcustom yas/root-directory nil (defcustom yas/root-directory nil
"The (list of) root directory that stores the snippets for each "Root directory that stores the snippets for each major mode.
major mode."
Can also be a list of strings, for multiple root directories."
:type '(string) :type '(string)
:group 'yasnippet) :group 'yasnippet)
(defcustom yas/prompt-functions '(yas/x-prompt (defcustom yas/prompt-functions '(yas/x-prompt
yas/ido-prompt
yas/dropdown-prompt yas/dropdown-prompt
yas/completing-prompt yas/completing-prompt
yas/ido-prompt
yas/no-prompt) yas/no-prompt)
"List of functions to prompt the user for keys, templates and "Functions to prompt for keys, templates, etc interactively."
other values interactively."
:type 'list :type 'list
:group 'yasnippet) :group 'yasnippet)
@ -144,17 +151,15 @@ applies)."
:group 'yasnippet) :group 'yasnippet)
(defcustom yas/snippet-revival t (defcustom yas/snippet-revival t
"Non-nil means re-activate snippet fields after an when undoing "Non-nil means re-activate snippet fields after undo/redo."
an exit from an active snippet or redoing a snippet expansion"
:type 'boolean :type 'boolean
:group 'yasnippet) :group 'yasnippet)
(defcustom yas/trigger-key "TAB" (defcustom yas/trigger-key "TAB"
"The key to bind as a trigger of snippet when `yas/minor-mode' "The key bound to `yas/expand' when function `yas/minor-mode' is active.
is active.
Value is a string that is converted to the internal Emacs key Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'. " representation using `read-kbd-macro'."
:type 'string :type 'string
:group 'yasnippet) :group 'yasnippet)
@ -162,7 +167,7 @@ representation using `read-kbd-macro'. "
"The key to navigate to next field when a snippet is active. "The key to navigate to next field when a snippet is active.
Value is a string that is converted to the internal Emacs key Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'. " representation using `read-kbd-macro'."
:type 'string :type 'string
:group 'yasnippet) :group 'yasnippet)
@ -172,7 +177,7 @@ representation using `read-kbd-macro'. "
Can also be a list of keys. Can also be a list of keys.
Value is a string that is converted to the internal Emacs key Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'. " representation using `read-kbd-macro'."
:type 'string :type 'string
:group 'yasnippet) :group 'yasnippet)
@ -180,15 +185,15 @@ representation using `read-kbd-macro'. "
"The key to clear the currently active field. "The key to clear the currently active field.
Value is a string that is converted to the internal Emacs key Value is a string that is converted to the internal Emacs key
representation using `read-kbd-macro'. " representation using `read-kbd-macro'."
:type 'string :type 'string
:group 'yasnippet) :group 'yasnippet)
(defcustom yas/triggers-in-field t (defcustom yas/triggers-in-field nil
"If non-nil, allow `yas/next-field-key' to trigger a stacked "If non-nil, `yas/next-field-key' can trigger stacked expansions.
snippet expansion.
Otherwise, `yas/next-field-key' just tries to move on to the next field" Otherwise, `yas/next-field-key' just tries to move on to the next
field"
:type 'boolean :type 'boolean
:group 'yasnippet) :group 'yasnippet)
@ -217,7 +222,7 @@ templates and inserts the selected one."
(defcustom yas/use-menu t (defcustom yas/use-menu t
"Display a YASnippet menu in the menu bar. "Display a YASnippet menu in the menu bar.
If this is set to `t', all snippet template of the current If this is set to t, all snippet template of the current
mode will be listed under the menu \"yasnippet\"." mode will be listed under the menu \"yasnippet\"."
:type 'boolean :type 'boolean
:group 'yasnippet) :group 'yasnippet)
@ -230,11 +235,11 @@ mode will be listed under the menu \"yasnippet\"."
(defcustom yas/show-all-modes-in-menu nil (defcustom yas/show-all-modes-in-menu nil
"Display \"artificial\" major modes in menu bar as well. "Display \"artificial\" major modes in menu bar as well.
Currently, YASnippet only all \"real modes\" to menubar. For Currently, YASnippet only all \"real modes\" to menubar. For
example, you define snippets for \"cc-mode\" and make it the example, you define snippets for \"cc-mode\" and make it the
parent of `c-mode', `c++-mode' and `java-mode'. There's really parent of `c-mode', `c++-mode' and `java-mode'. There's really
no such mode like \"cc-mode\". So we don't show it in the yasnippet no such mode like \"cc-mode\". So we don't show it in the yasnippet
menu to avoid the menu becoming too big with strange modes. The menu to avoid the menu becoming too big with strange modes. The
snippets defined for \"cc-mode\" can still be accessed from snippets defined for \"cc-mode\" can still be accessed from
menu-bar->c-mode->parent (or c++-mode, java-mode, all are ok). menu-bar->c-mode->parent (or c++-mode, java-mode, all are ok).
However, if you really like to show all modes in the menu, set However, if you really like to show all modes in the menu, set
@ -242,15 +247,15 @@ this variable to t."
:type 'boolean :type 'boolean
:group 'yasnippet) :group 'yasnippet)
(defcustom yas/wrap-around-region t (defcustom yas/wrap-around-region nil
"If non-nil, snippet expansion wraps around selected region. "If non-nil, snippet expansion wraps around selected region.
The wrapping occurs just before the snippet's exit marker. This The wrapping occurs just before the snippet's exit marker. This
can be overriden on a per-snippet basis." can be overriden on a per-snippet basis."
:type 'boolean :type 'boolean
:group 'yasnippet) :group 'yasnippet)
(defcustom yas/good-grace nil (defcustom yas/good-grace t
"If non-nil, don't raise errors in inline elisp evaluation. "If non-nil, don't raise errors in inline elisp evaluation.
An error string \"[yas] error\" is returned instead." An error string \"[yas] error\" is returned instead."
@ -278,7 +283,7 @@ An error string \"[yas] error\" is returned instead."
"The keymap active while a snippet expansion is in progress.") "The keymap active while a snippet expansion is in progress.")
(defun yas/define-some-keys (keys keymap definition) (defun yas/define-some-keys (keys keymap definition)
"Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'" "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'."
(let ((keys (or (and (listp keys) keys) (let ((keys (or (and (listp keys) keys)
(list keys)))) (list keys))))
(dolist (key keys) (dolist (key keys)
@ -378,13 +383,13 @@ Here's an example:
;; Internal variables ;; Internal variables
;; ;;
(defvar yas/version "0.6.0-beta") (defvar yas/version "0.6.0b")
(defvar yas/snippet-tables (make-hash-table) (defvar yas/snippet-tables (make-hash-table)
"A hash table of snippet tables corresponding to each major-mode.") "A hash table of snippet tables corresponding to each major mode.")
(defvar yas/menu-table (make-hash-table) (defvar yas/menu-table (make-hash-table)
"A hash table of menus of corresponding major-mode.") "A hash table of menus of corresponding major mode.")
(defvar yas/known-modes (defvar yas/known-modes
'(ruby-mode rst-mode markdown-mode) '(ruby-mode rst-mode markdown-mode)
@ -392,28 +397,27 @@ Here's an example:
(defvar yas/escaped-characters (defvar yas/escaped-characters
'(?\\ ?` ?' ?$ ?} ) '(?\\ ?` ?' ?$ ?} )
"A list of characters which *might*n need to be escaped in "List of characters which *might* need to be escaped.")
snippet templates")
(defconst yas/field-regexp (defconst yas/field-regexp
"${\\([0-9]+:\\)?\\([^}]*\\)}" "${\\([0-9]+:\\)?\\([^}]*\\)}"
"A regexp to *almost* recognize a field") "A regexp to *almost* recognize a field.")
(defconst yas/multi-dollar-lisp-expression-regexp (defconst yas/multi-dollar-lisp-expression-regexp
"$+[ \t\n]*\\(([^)]*)\\)" "$+[ \t\n]*\\(([^)]*)\\)"
"A regexp to *almost* recognize a \"$(...)\" expression") "A regexp to *almost* recognize a \"$(...)\" expression.")
(defconst yas/backquote-lisp-expression-regexp (defconst yas/backquote-lisp-expression-regexp
"`\\([^`]*\\)`" "`\\([^`]*\\)`"
"A regexp to recognize a \"`lisp-expression`\" expression" ) "A regexp to recognize a \"`lisp-expression`\" expression." )
(defconst yas/transform-mirror-regexp (defconst yas/transform-mirror-regexp
"${\\(?:\\([0-9]+\\):\\)?$\\([^}]*\\)" "${\\(?:\\([0-9]+\\):\\)?$\\([^}]*\\)"
"A regexp to *almost* recognize a mirror with a transform") "A regexp to *almost* recognize a mirror with a transform.")
(defconst yas/simple-mirror-regexp (defconst yas/simple-mirror-regexp
"$\\([0-9]+\\)" "$\\([0-9]+\\)"
"A regexp to recognize a simple mirror") "A regexp to recognize a simple mirror.")
(defvar yas/snippet-id-seed 0 (defvar yas/snippet-id-seed 0
"Contains the next id for a snippet.") "Contains the next id for a snippet.")
@ -428,7 +432,7 @@ snippet templates")
;; ;;
(defvar yas/minor-mode-map (make-sparse-keymap) (defvar yas/minor-mode-map (make-sparse-keymap)
"The keymap used when `yas/minor-mode' is active.") "The keymap used when function `yas/minor-mode' is active.")
(defun yas/init-keymap-and-menu () (defun yas/init-keymap-and-menu ()
(easy-menu-define yas/minor-mode-menu (easy-menu-define yas/minor-mode-menu
@ -552,7 +556,7 @@ TEMPLATES is a list of cons (KEY . TEMPLATE) where KEY is a
string and TEMPLATE is a `yas/template' structure. string and TEMPLATE is a `yas/template' structure.
This function implements the rules described in This function implements the rules described in
`yas/buffer-local-condition'. See that variables documentation." `yas/buffer-local-condition'. See that variables documentation."
(let ((requirement (yas/require-template-specific-condition-p))) (let ((requirement (yas/require-template-specific-condition-p)))
(if (eq requirement 'always) (if (eq requirement 'always)
templates templates
@ -563,7 +567,7 @@ This function implements the rules described in
(cond ((eq requirement t) (cond ((eq requirement t)
result) result)
(t (t
(eq requirement result))))) (eq requirement result)))))
templates)))) templates))))
(defun yas/snippet-table-fetch (table key) (defun yas/snippet-table-fetch (table key)
@ -599,7 +603,7 @@ fetch from parent if any."
(yas/snippet-table-all-keys (yas/snippet-table-parent table)))))) (yas/snippet-table-all-keys (yas/snippet-table-parent table))))))
(defun yas/snippet-table-store (table full-key key template) (defun yas/snippet-table-store (table full-key key template)
"Store a snippet template in the table." "Store a snippet template in the TABLE."
(puthash key (puthash key
(yas/modify-alist (gethash key (yas/modify-alist (gethash key
(yas/snippet-table-hash table)) (yas/snippet-table-hash table))
@ -913,6 +917,7 @@ TEMPLATES is a list of `yas/template'."
(defun yas/load-directory (directory) (defun yas/load-directory (directory)
"Load snippet definition from a directory hierarchy. "Load snippet definition from a directory hierarchy.
Below the top-level directory, each directory is a mode Below the top-level directory, each directory is a mode
name. And under each subdirectory, each file is a definition name. And under each subdirectory, each file is a definition
of a snippet. The file name is the trigger key and the of a snippet. The file name is the trigger key and the
@ -940,7 +945,7 @@ content of the file is the template."
(yas/global-mode -1) (yas/global-mode -1)
(setq restore-global-mode t)) (setq restore-global-mode t))
(when yas/minor-mode (when yas/minor-mode
(yas/minor-mode -1) (yas/minor-mode -1)
(setq restore-minor-mode t)) (setq restore-minor-mode t))
@ -975,7 +980,7 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\""
;;; Yasnipept Bundle ;;; Yasnipept Bundle
(defun yas/initialize () (defun yas/initialize ()
"For backward compatibility, enable `yas/minor-mode' globally" "For backward compatibility, enable `yas/minor-mode' globally"
(yas/global-mode 1)) (yas/global-mode 1))
(defun yas/compile-bundle (defun yas/compile-bundle
@ -1148,7 +1153,7 @@ directory to find snippet files.
(not (string= "" group))) (not (string= "" group)))
(dolist (subgroup (mapcar #'make-symbol (dolist (subgroup (mapcar #'make-symbol
(split-string group "\\."))) (split-string group "\\.")))
(let ((subgroup-keymap (lookup-key group-keymap (let ((subgroup-keymap (lookup-key group-keymap
(vector subgroup)))) (vector subgroup))))
(when (null subgroup-keymap) (when (null subgroup-keymap)
(setq subgroup-keymap (make-sparse-keymap)) (setq subgroup-keymap (make-sparse-keymap))
@ -1289,8 +1294,11 @@ by condition."
(yas/template-env template)) (yas/template-env template))
(message "[yas] No snippets can be inserted here!")))) (message "[yas] No snippets can be inserted here!"))))
(defun yas/find-snippet-file () (defun yas/visit-snippet-file ()
"Choose a snippet to edit, selection like `yas/insert-snippet'." "Choose a snippet to edit, selection like `yas/insert-snippet'.
Only success if selected snippet was loaded from a file. Put the
visited file in `snippet-mode'."
(interactive) (interactive)
(let* ((yas/buffer-local-condition 'always) (let* ((yas/buffer-local-condition 'always)
(templates (mapcar #'cdr (templates (mapcar #'cdr
@ -1317,7 +1325,7 @@ by condition."
(message "This snippet was not loaded from a file!"))))))) (message "This snippet was not loaded from a file!")))))))
(defun yas/guess-snippet-directory () (defun yas/guess-snippet-directory ()
"Try to guess the suitable yassnippet based on `major-mode'" "Try to guess the suitable yassnippet based on `major-mode'"
(let ((loaded-root (or (and (listp yas/root-directory) (let ((loaded-root (or (and (listp yas/root-directory)
(first yas/root-directory)) (first yas/root-directory))
yas/root-directory)) yas/root-directory))
@ -1336,13 +1344,16 @@ by condition."
(defun yas/find-snippets (&optional same-window) (defun yas/find-snippets (&optional same-window)
"Find a snippet file in a suitable directory." "Looks for snippets file in the current mode's directory.
This can be used to create new snippets for the currently active
major mode."
(interactive "P") (interactive "P")
(let* ((current-table (yas/current-snippet-table major-mode 'dont-search-parents)) (let* ((current-table (yas/current-snippet-table major-mode 'dont-search-parents))
(parents-table (yas/current-snippet-table major-mode)) (parents-table (yas/current-snippet-table major-mode))
(parents-directory (and parents-table (parents-directory (and parents-table
(yas/snippet-table-default-directory parents-table))) (yas/snippet-table-default-directory parents-table)))
(guessed-directory (or (and current-table (guessed-directory (or (and current-table
(yas/snippet-table-default-directory current-table)) (yas/snippet-table-default-directory current-table))
(yas/guess-snippet-directory) (yas/guess-snippet-directory)
default-directory)) default-directory))
@ -1392,7 +1403,7 @@ by condition."
(message "Save the buffer as a file first!"))) (message "Save the buffer as a file first!")))
(defun yas/tryout-snippet (&optional debug) (defun yas/tryout-snippet (&optional debug)
"Parse and load current buffer's snippet definition." "Test current buffers's snippet template in other buffer."
(interactive "P") (interactive "P")
(let* ((major-mode-and-parent (or (and buffer-file-name (let* ((major-mode-and-parent (or (and buffer-file-name
(yas/compute-major-mode-and-parent buffer-file-name)) (yas/compute-major-mode-and-parent buffer-file-name))
@ -1525,10 +1536,10 @@ for this field, apply it. Otherwise, returned nil."
(text yas/text) (text yas/text)
(yas/modified-p (yas/field-modified-p field)) (yas/modified-p (yas/field-modified-p field))
(yas/moving-away-p nil) (yas/moving-away-p nil)
(transform (if (yas/mirror-p field-or-mirror) (transform (if (yas/mirror-p field-or-mirror)
(yas/mirror-transform field-or-mirror) (yas/mirror-transform field-or-mirror)
(yas/field-transform field-or-mirror))) (yas/field-transform field-or-mirror)))
(start-point (if (yas/mirror-p field-or-mirror) (start-point (if (yas/mirror-p field-or-mirror)
(yas/mirror-start field-or-mirror) (yas/mirror-start field-or-mirror)
(yas/field-start field-or-mirror))) (yas/field-start field-or-mirror)))
(transformed (and transform (transformed (and transform
@ -1543,7 +1554,7 @@ for this field, apply it. Otherwise, returned nil."
(while (search-forward from nil t) (while (search-forward from nil t)
(replace-match to t t))) (replace-match to t t)))
(defun yas/snippet-find-field (snippet number) (defun yas/snippet-find-field (snippet number)
(find-if #'(lambda (field) (find-if #'(lambda (field)
(eq number (yas/field-number field))) (eq number (yas/field-number field)))
(yas/snippet-fields snippet))) (yas/snippet-fields snippet)))
@ -1564,7 +1575,7 @@ have, compare through the field's start point"
(yas/field-start field2)))))) (yas/field-start field2))))))
(defun yas/field-probably-deleted-p (field) (defun yas/field-probably-deleted-p (field)
"Guess if FIELD was deleted because of his parent-field" "Guess if FIELD was deleted because of his parent-field"
(and (zerop (- (yas/field-start field) (yas/field-end field))) (and (zerop (- (yas/field-start field) (yas/field-end field)))
(yas/field-parent-field field))) (yas/field-parent-field field)))
@ -1637,7 +1648,7 @@ Also create some protection overlays"
(setf (yas/snippet-active-field snippet) field) (setf (yas/snippet-active-field snippet) field)
(yas/place-overlays snippet field) (yas/place-overlays snippet field)
(overlay-put yas/active-field-overlay 'yas/field field) (overlay-put yas/active-field-overlay 'yas/field field)
;;; primary field transform: first call to snippet transform ;;; primary field transform: first call to snippet transform
(unless (yas/field-modified-p field) (unless (yas/field-modified-p field)
(if (yas/field-update-display field snippet) (if (yas/field-update-display field snippet)
(let ((inhibit-modification-hooks t)) (let ((inhibit-modification-hooks t))
@ -1741,7 +1752,7 @@ NO-HOOKS means don't run the `yas/after-exit-snippet-hook' hooks."
(when (and yas/snippet-end previous-field) (when (and yas/snippet-end previous-field)
(yas/advance-field-end-marker previous-field yas/snippet-end))) (yas/advance-field-end-marker previous-field yas/snippet-end)))
;; Convert all markers to points, ;; Convert all markers to points,
;; ;;
(yas/markers-to-points snippet) (yas/markers-to-points snippet)
@ -1770,7 +1781,7 @@ snippet, if so cleans up the whole snippet up."
(let* ((snippets (yas/snippets-at-point 'all-snippets)) (let* ((snippets (yas/snippets-at-point 'all-snippets))
(snippets-left snippets)) (snippets-left snippets))
(dolist (snippet snippets) (dolist (snippet snippets)
(let ((active-field (yas/snippet-active-field snippet))) (let ((active-field (yas/snippet-active-field snippet)))
(cond ((or (prog1 (yas/snippet-force-exit snippet) (cond ((or (prog1 (yas/snippet-force-exit snippet)
(setf (yas/snippet-force-exit snippet) nil)) (setf (yas/snippet-force-exit snippet) nil))
(not (and active-field (yas/field-contains-point-p active-field)))) (not (and active-field (yas/field-contains-point-p active-field))))
@ -1820,7 +1831,7 @@ snippet, if so cleans up the whole snippet up."
(when target-field (when target-field
(yas/move-to-field snippet target-field)))) (yas/move-to-field snippet target-field))))
((not (yas/undo-in-progress)) ((not (yas/undo-in-progress))
;; When not in an undo, check if we must commit the snippet (use exited it). ;; When not in an undo, check if we must commit the snippet (use exited it).
(yas/check-commit-snippet)))) (yas/check-commit-snippet))))
(defun yas/field-text-for-display (field) (defun yas/field-text-for-display (field)
@ -1839,7 +1850,7 @@ holds the keymap."
(let ((overlay (make-overlay start (let ((overlay (make-overlay start
end end
nil nil
nil nil
t))) t)))
(overlay-put overlay 'keymap yas/keymap) (overlay-put overlay 'keymap yas/keymap)
(overlay-put overlay 'yas/snippet snippet) (overlay-put overlay 'yas/snippet snippet)
@ -1847,8 +1858,9 @@ holds the keymap."
overlay)) overlay))
(defun yas/skip-and-clear-or-delete-char (&optional field) (defun yas/skip-and-clear-or-delete-char (&optional field)
"Clears an unmodified field if at field start, otherwise "Clears unmodified field if at field start, skips to next tab.
deletes a character normally."
Otherwise deletes a character normally by calling `delete-char'."
(interactive) (interactive)
(let ((field (or field (let ((field (or field
(and yas/active-field-overlay (and yas/active-field-overlay
@ -1863,7 +1875,7 @@ deletes a character normally."
(call-interactively 'delete-char))))) (call-interactively 'delete-char)))))
(defun yas/skip-and-clear (field) (defun yas/skip-and-clear (field)
"Deletes the region of FIELD and sets it modified state to t" "Deletes the region of FIELD and sets it modified state to t"
(setf (yas/field-modified-p field) t) (setf (yas/field-modified-p field) t)
(delete-region (yas/field-start field) (yas/field-end field))) (delete-region (yas/field-start field) (yas/field-end field)))
@ -2137,7 +2149,7 @@ After revival, push the `yas/take-care-of-redo' in the
(defun yas/snippet-create (begin end) (defun yas/snippet-create (begin end)
"Creates a snippet from an template inserted between BEGIN and END. "Creates a snippet from an template inserted between BEGIN and END.
Returns the newly created snippet." Returns the newly created snippet."
(let ((snippet (yas/make-snippet))) (let ((snippet (yas/make-snippet)))
(goto-char begin) (goto-char begin)
(yas/snippet-parse-create snippet) (yas/snippet-parse-create snippet)
@ -2206,7 +2218,7 @@ Meant to be called in a narrowed buffer, does various passes"
;; ;;
(goto-char parse-start) (goto-char parse-start)
(yas/protect-escapes) (yas/protect-escapes)
;; parse fields with {} ;; parse fields with {}
;; ;;
(goto-char parse-start) (goto-char parse-start)
(yas/field-parse-create snippet) (yas/field-parse-create snippet)
@ -2234,7 +2246,7 @@ Meant to be called in a narrowed buffer, does various passes"
(save-excursion (save-excursion
(while (re-search-forward "$>" nil t) (while (re-search-forward "$>" nil t)
(delete-region (match-beginning 0) (match-end 0)) (delete-region (match-beginning 0) (match-end 0))
(when (not (eq yas/indent-line 'auto)) (when (not (eq yas/indent-line 'auto))
(indent-according-to-mode)))) (indent-according-to-mode))))
(save-excursion (save-excursion
(cond ((eq yas/indent-line 'fixed) (cond ((eq yas/indent-line 'fixed)
@ -2380,7 +2392,7 @@ When multiple expressions are found, only the last one counts."
(while (re-search-forward yas/multi-dollar-lisp-expression-regexp nil t) (while (re-search-forward yas/multi-dollar-lisp-expression-regexp nil t)
(let* ((real-match-end-1 (yas/scan-sexps (match-beginning 1) 1))) (let* ((real-match-end-1 (yas/scan-sexps (match-beginning 1) 1)))
(when real-match-end-1 (when real-match-end-1
(let ((lisp-expression-string (buffer-substring-no-properties (match-beginning 1) real-match-end-1))) (let ((lisp-expression-string (buffer-substring-no-properties (match-beginning 1) real-match-end-1)))
(setf (yas/field-transform parent-field) lisp-expression-string)) (setf (yas/field-transform parent-field) lisp-expression-string))
(delete-region (match-beginning 0) real-match-end-1))))))) (delete-region (match-beginning 0) real-match-end-1)))))))
@ -2393,7 +2405,7 @@ When multiple expressions are found, only the last one counts."
(not (zerop number)) (not (zerop number))
(yas/snippet-find-field snippet number)))) (yas/snippet-find-field snippet number))))
(when (and real-match-end-0 (when (and real-match-end-0
field) field)
(push (yas/make-mirror (yas/make-marker (match-beginning 0)) (push (yas/make-mirror (yas/make-marker (match-beginning 0))
(yas/make-marker (match-beginning 0)) (yas/make-marker (match-beginning 0))
(buffer-substring-no-properties (match-beginning 2) (buffer-substring-no-properties (match-beginning 2)
@ -2440,7 +2452,7 @@ When multiple expressions are found, only the last one counts."
(let ((inhibit-modification-hooks t)) (let ((inhibit-modification-hooks t))
(yas/mirror-update-display mirror field) (yas/mirror-update-display mirror field)
;; Take care of the fields adjacent to this mirror's back ;; Take care of the fields adjacent to this mirror's back
;; TODO: Known bug ;; TODO: Known bug
;; `yas/place-overlays' is needed if the active field and ;; `yas/place-overlays' is needed if the active field and
;; protected overlays have been changed because of insertions ;; protected overlays have been changed because of insertions
@ -2482,6 +2494,7 @@ When multiple expressions are found, only the last one counts."
;; ;;
(defun yas/debug-some-vars () (defun yas/debug-some-vars ()
"Debug snippets, fields, mirrors and the `buffer-undo-list'."
(interactive) (interactive)
(with-output-to-temp-buffer "*YASnippet trace*" (with-output-to-temp-buffer "*YASnippet trace*"
(princ "Interesting YASnippet vars: \n\n") (princ "Interesting YASnippet vars: \n\n")