emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ELPA-diffs] ELPA branch, master, updated. a5433b904ffc3b1cb51cc108e24a9


From: Stefan Monnier
Subject: [ELPA-diffs] ELPA branch, master, updated. a5433b904ffc3b1cb51cc108e24a9d6bd6ca6bc6
Date: Wed, 28 Aug 2013 14:13:11 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "ELPA".

The branch, master has been updated
       via  a5433b904ffc3b1cb51cc108e24a9d6bd6ca6bc6 (commit)
       via  a2f0f7f76777a2f1b525f3e35207a2e68eb2bb48 (commit)
       via  501857e767962be05ac5979b87ba52cc5190b5ea (commit)
       via  80bb95326b38de8109309f8d84b5e2f49fe92ebb (commit)
       via  3acb8c577306a48b6e4f8aa7735e851886ae3d57 (commit)
       via  9e085ec05de4c3d288a787a522c6e5c81d01f1a7 (commit)
       via  636c01d34a8cd7f9acce49ba53b0171931887eb9 (commit)
       via  ccea21bf99e8dc4c6f64225a1d61c5bf4cbd8de3 (commit)
       via  8bf75fe425f39fced497e3e308555e726fe0d6f6 (commit)
       via  9df05fc41302f6e04ffe5e8ff62c573348ec64f1 (commit)
       via  0da56720a8379c7d839043220aadd59a554a41ca (commit)
       via  742b353a81c6226681c4750a2d030b47ce323dbd (commit)
       via  57138e6df432df8bbd0b8ddd69bf94e0136f9313 (commit)
       via  7172a450d25433aaf4af3017c065044fdfff41b2 (commit)
       via  0bd2f3ef6447421436b55ed1b4585805ad952f23 (commit)
       via  d9d7ed32ae11df8cbc91646bd5b6984d37efd3b3 (commit)
       via  e3a5f6e0c76e580a210e28828f83e8ea46a69a19 (commit)
       via  2cf544b67f5a80df470888e6d94f7fdba13b144d (commit)
       via  bf554212d357b842adcf7ff17ad2be1c75eec60e (commit)
       via  61cee70ec0dbf7e1528fc10660468b87a0ffc057 (commit)
       via  8772b51052d94401501cd889f6b60d58d3debc8c (commit)
       via  700a68eb15cb28e71dcadf00e51658394d0b9838 (commit)
       via  2e118646f04c65501ab9887bb018a4173b789cf8 (commit)
       via  618cf506ee2bb7c9e11eeda31090c19dc433f856 (commit)
       via  35493b8f069dd2ed6c3ca75bac30f0ca375409e4 (commit)
       via  74e8f43f065fbb9d775aa105a1e0ffc61358e2c9 (commit)
       via  04970abf300ce85a5245735d14e1fb4edb98fda2 (commit)
       via  810de9a4b066c62b0af4f8d9f452a5adde824aa0 (commit)
       via  e5c41c78d27d00dde14a31a3435d40d12cc1eff5 (commit)
       via  1ef0091de1aa5cce64bc15a6ff11167ed5fa89dd (commit)
       via  9b31880ed19486c3672f467ce6dfd58faf612e39 (commit)
       via  1db685c480f2fda983f3a4f855b3985d6b61bccd (commit)
       via  a74481f491ce03ec90a8c4baed154cf0e9ce2c5d (commit)
       via  1bc497ecbe5223a5de4daa36865fa69567de5d1a (commit)
       via  327fa4b86e927c1ed6def233c113d561eab8ac0d (commit)
       via  d9f966a220393339fd99b26b2bed8c7f6d79d226 (commit)
       via  f6d6d4ca56911e5229ca8aa649ed23aaaf570530 (commit)
       via  100aa7c0af600e95223ddfb0d506e85a945475b5 (commit)
       via  4f99f9dc205db03754d1d4664704e6838e545b2e (commit)
       via  cfefaca284327babde6cf483c8bb2127e8c0e5fd (commit)
       via  7e4876169bd82477f665a75df6550b95ef26a1f1 (commit)
       via  0778a1b61b7a74473b9a34cc8d1fc5ae8561af2f (commit)
       via  b29e4b9259c2b1f483f5fa942756e30da041d078 (commit)
       via  ed4dbdf37848ab715f5daad1888c1103d9d8ee9a (commit)
       via  0ab9fb281e24bc7a35692d720086746dcc27096e (commit)
       via  d5865b1092fd24099f4afedf0e5016fe9da86b5f (commit)
       via  552008872b26dc6e44f93a1673434ef7a6bb9cf5 (commit)
       via  b7fe4c1f8d469f393422480d48309a04056dc191 (commit)
       via  a581ac475d7c4915e0f5c1593f5c299cfeebc1bd (commit)
       via  7d411fbfd7ffa7c49d374fea065fd6f123ebb01f (commit)
       via  880767e66996ef1c4e501c6536ded8ff563fa1cb (commit)
       via  4e07abaec7b21eb649a34d289e90dd7835686ff5 (commit)
       via  185c771dedea5c29fa18dc8d624674c3a62e8326 (commit)
       via  9de1c5f4fb6f281cfa4af869d393db76616cb42e (commit)
       via  81dbf038a10eab484789f159ddb10846438d2c59 (commit)
       via  73a1b485d64efafdae46bde9d54e35f3033fc295 (commit)
       via  cd70010b83bc2c92afcdfec7223ef84ddba285e7 (commit)
       via  f8366214801b52c7c1cc9c091fa5dcb42d3fd217 (commit)
       via  1774d7cbd09241b61d21bc788ffd4186cc932997 (commit)
       via  5aff68266c12ecf4067dae7f0124a9b129246371 (commit)
       via  cbfc82d18660403d3626010232285532406b18ae (commit)
       via  32e56098fb184b00607998efde30bd934652e2b3 (commit)
       via  95742882778ac4080e25b5ae5e5ea6d8b223dc46 (commit)
       via  49dde5177b019add5ab1b7bb60ba8cbd913e7c35 (commit)
       via  f7b786f6df6860f0d9c004266b32792dbf59ca47 (commit)
       via  a5405459456ca6c2c3606f3115b2299d95e3d455 (commit)
       via  42ed181f4a4b383da419ec51a93de4a0e4ee3749 (commit)
       via  7130d9c3653a1102df6b3b2f71eff9ddefb2ac11 (commit)
       via  38db5aa9fbf0f60dce63b83cab8f028bfcd152bd (commit)
       via  9503c332f552e874899ea0ce7801516d4b30bba2 (commit)
       via  8a26ab0a3180b0df2264518ff31dd19564727ba2 (commit)
       via  08c6dd44b340fe0b19352879faffc777a7a4ed93 (commit)
       via  38c4b734c9b02c036818d5c99083c5ebdf704ece (commit)
       via  f28a3df702c62f1b045ea5b57d1344c90ebc9731 (commit)
       via  100beaf735a65dc5f965ebbf55c68f2beef422de (commit)
       via  7981f8d63b133d596c0bd83d0e33534bef36a3f7 (commit)
       via  064c068c453894b8443964698be467f35325c811 (commit)
       via  f96bd13cf77e75d5497efbffede5c55b207786e4 (commit)
       via  926876b1a2b08fbe326aa7d9c3eaef407a922857 (commit)
       via  145448b81530e404e69000158d00aff689aa0a0e (commit)
       via  f82350a75d71496fc549c0682ef6a7a3b4e22128 (commit)
       via  06306181a8920271215df07d547f28c0dc2a7151 (commit)
       via  5eede17563ab2716735fceb4862cd4f07eeb9a66 (commit)
       via  cdea084f7a5002348ef38a9977e6fc4951289d0c (commit)
       via  951fb3cbe779eef8e558f22794244ad58511b828 (commit)
       via  38093c1a9e1f44679f2f41d9df05a8b4fc363c08 (commit)
       via  b4ccb6e9566c17fe38ab30310e2e64749bd2d7ce (commit)
       via  32c65dff47f43194acde6551a4eb1dba99956099 (commit)
       via  18714eac59006568451c921badbbad37e0299e7d (commit)
       via  fd282faaa7413ff8aaaa0dc8a40ba656ac4b0a60 (commit)
       via  c967f748478b4cf03055a9ca58b68d58851fd952 (commit)
       via  197104b450dea3972418a52f56e643a9fd0dd531 (commit)
       via  6aff6a0894dedaacf37f200d11c1204f8ef9b340 (commit)
       via  12c21c6c62d02a27917e4214e4ce0322dcc099fc (commit)
       via  cffd1aa095c0f6d16d1f4f099f97c742d2ee3b9f (commit)
       via  f35d2dba112815af9cb9a08a7d20a8611a1096cf (commit)
       via  6be1de4a09cc24c60d93a256e582b9ef618820e1 (commit)
       via  c13abb7520c3296dd6aaf41d13e6453c106632ce (commit)
       via  71c8e0ea469c2992a31d17b0722ebdeb789fd1bf (commit)
       via  c566c929c04c8e05ba7f37fb39ca7311159b9b26 (commit)
      from  f6920eeb4d23ec582c6d1bb7707cb120d3640883 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a5433b904ffc3b1cb51cc108e24a9d6bd6ca6bc6
Merge: f6920ee a2f0f7f
Author: Stefan Monnier <address@hidden>
Date:   Wed Aug 28 10:12:55 2013 -0400

    Sync with yasnippet/master

diff --cc packages/yasnippet/doc/manual.mdown
index 0000000,aac0d89..aac0d89
mode 000000,100644..100644
--- a/packages/yasnippet/doc/manual.mdown
+++ b/packages/yasnippet/doc/manual.mdown
diff --cc packages/yasnippet/doc/yas-doc-helper.el
index 0000000,3217834..3217834
mode 000000,100755..100755
--- a/packages/yasnippet/doc/yas-doc-helper.el
+++ b/packages/yasnippet/doc/yas-doc-helper.el
diff --cc 
packages/yasnippet/snippets/emacs-lisp-mode/x-dired.process_marked.yasnippet
index 710657c,77ca69d..77ca69d
mode 100644,100755..100644
--- 
a/packages/yasnippet/snippets/emacs-lisp-mode/x-dired.process_marked.yasnippet
+++ 
b/packages/yasnippet/snippets/emacs-lisp-mode/x-dired.process_marked.yasnippet
diff --cc 
packages/yasnippet/snippets/emacs-lisp-mode/x-file.read-lines.yasnippet
index f85fe4e,e4cb092..e4cb092
mode 100644,100755..100644
--- a/packages/yasnippet/snippets/emacs-lisp-mode/x-file.read-lines.yasnippet
+++ b/packages/yasnippet/snippets/emacs-lisp-mode/x-file.read-lines.yasnippet
diff --cc packages/yasnippet/snippets/emacs-lisp-mode/x-find-replace.yasnippet
index e5a1d6c,b0c58ec..b0c58ec
mode 100644,100755..100644
--- a/packages/yasnippet/snippets/emacs-lisp-mode/x-find-replace.yasnippet
+++ b/packages/yasnippet/snippets/emacs-lisp-mode/x-find-replace.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/assert.yasnippet
index 0000000,59ec614..59ec614
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/assert.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/assert.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/cb.yasnippet
index 0000000,9453e6a..9453e6a
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/cb.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/cb.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/com.yasnippet
index 0000000,1eff9fe..1eff9fe
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/com.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/com.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/describe.yasnippet
index 0000000,c40bae7..c40bae7
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/describe.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/describe.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/err.snippet
index 0000000,a4b713b..a4b713b
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/err.snippet
+++ b/packages/yasnippet/snippets/js-mode/err.snippet
diff --cc packages/yasnippet/snippets/js-mode/error.snippet
index 0000000,1c99ad2..1c99ad2
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/error.snippet
+++ b/packages/yasnippet/snippets/js-mode/error.snippet
diff --cc packages/yasnippet/snippets/js-mode/expect.yasnippet
index 0000000,8e0879e..8e0879e
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/expect.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/expect.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/exports.yasnippet
index 0000000,6e183cd..6e183cd
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/exports.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/exports.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/fn.yasnippet
index 0000000,67294fc..67294fc
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/fn.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/fn.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/for.yasnippet
index 0000000,97d772f..97d772f
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/for.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/for.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/id.yasnippet
index 0000000,47f00b9..47f00b9
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/id.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/id.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/if.yasnippet
index 0000000,0fac855..0fac855
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/if.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/if.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/invoc.yasnippet
index 0000000,cf46321..cf46321
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/invoc.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/invoc.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/it.yasnippet
index 0000000,161d51f..161d51f
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/it.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/it.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/log.yasnippet
index 0000000,19ff1be..19ff1be
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/log.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/log.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/method.yasnippet
index 0000000,67fb56a..67fb56a
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/method.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/method.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/mod.yasnippet
index 0000000,c1b9867..c1b9867
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/mod.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/mod.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/prop.yasnippet
index 0000000,dc234c7..dc234c7
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/prop.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/prop.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/proto.yasnippet
index 0000000,c6fe215..c6fe215
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/proto.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/proto.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/rq.yasnippet
index 0000000,864534d..864534d
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/rq.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/rq.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/rt.yasnippet
index 0000000,d9a5bdf..d9a5bdf
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/rt.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/rt.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/slice.yasnippet
index 0000000,2dd65be..2dd65be
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/slice.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/slice.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/super.yasnippet
index 0000000,4638026..4638026
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/super.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/super.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/switch.yasnippet
index 0000000,5e4fc3f..5e4fc3f
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/switch.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/switch.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/throw.yasnippet
index 0000000,dbef383..dbef383
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/throw.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/throw.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/try.yasnippet
index 0000000,903378f..903378f
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/try.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/try.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/var.yasnippet
index 0000000,77d52a5..77d52a5
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/var.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/var.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/wh.yasnippet
index 0000000,f733ac4..f733ac4
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/wh.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/wh.yasnippet
diff --cc packages/yasnippet/snippets/js-mode/while.yasnippet
index 0000000,9eff9df..9eff9df
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/js-mode/while.yasnippet
+++ b/packages/yasnippet/snippets/js-mode/while.yasnippet
diff --cc packages/yasnippet/snippets/ruby-mode/definitions/mod
index 0000000,118400c..118400c
mode 000000,100644..100644
--- a/packages/yasnippet/snippets/ruby-mode/definitions/mod
+++ b/packages/yasnippet/snippets/ruby-mode/definitions/mod

commit a2f0f7f76777a2f1b525f3e35207a2e68eb2bb48
Merge: 9e085ec 501857e
Author: João Távora <address@hidden>
Date:   Tue Aug 20 08:53:32 2013 -0700

    Merge pull request #397 from thisirs/customizable-snippet
    
    Make default snippet customizable


commit 501857e767962be05ac5979b87ba52cc5190b5ea
Author: thisirs <address@hidden>
Date:   Mon Aug 19 22:52:19 2013 +0200

    Assume NO-TEMPLATE is non-nil if `yas-new-snippet-default' is nil

diff --git a/yasnippet.el b/yasnippet.el
index 738a63f..b279f12 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -196,7 +196,8 @@ as the default for storing the user's new snippets."
 # type: command}
 # --
 $0"
-  "Default snippet to use when creating a new snippet."
+  "Default snippet to use when creating a new snippet. If nil,
+don't use any snippet."
   :type 'string
   :group 'yasnippet)
 
@@ -2531,7 +2532,8 @@ NO-TEMPLATE is non-nil."
     (set (make-local-variable 'yas--guessed-modes) (mapcar #'(lambda (d)
                                                               (yas--table-mode 
(car d)))
                                                           guessed-directories))
-    (unless no-template (yas-expand-snippet yas-new-snippet-default))))
+    (if (and (not no-template) yas-new-snippet-default)
+        (yas-expand-snippet yas-new-snippet-default))))
 
 (defun yas--compute-major-mode-and-parents (file)
   "Given FILE, find the nearest snippet directory for a given mode.

commit 80bb95326b38de8109309f8d84b5e2f49fe92ebb
Author: thisirs <address@hidden>
Date:   Mon Aug 19 22:47:14 2013 +0200

    Factor out embedded elisp code
    
    * yasnippet.el (yas--key-from-desc): Added

diff --git a/yasnippet.el b/yasnippet.el
index 0a94ffb..738a63f 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -190,7 +190,7 @@ as the default for storing the user's new snippets."
 (defcustom yas-new-snippet-default "\
 # -*- mode: snippet -*-
 # name: $1
-# key: ${2:${1:$(replace-regexp-in-string \"\\\\\\\\(\\\\\\\\w+\\\\\\\\).*\" 
\"\\\\\\\\1\" yas-text)}}${3:
+# key: ${2:${1:$(yas--key-from-desc yas-text)}}${3:
 # binding: ${4:direct-keybinding}}${5:
 # expand-env: ((${6:some-var} ${7:some-value}))}${8:
 # type: command}
@@ -1523,6 +1523,10 @@ Here's a list of currently recognized directives:
                               (cdr where)
                               (yas--template-expand-env 
yas--current-template)))))))
 
+(defun yas--key-from-desc (text)
+  "Return a yasnippet key from a description string TEXT."
+  (replace-regexp-in-string "\\(\\w+\\).*" "\\1" text))
+
 
 ;;; Popping up for keys and templates
 

commit 3acb8c577306a48b6e4f8aa7735e851886ae3d57
Author: thisirs <address@hidden>
Date:   Mon Aug 5 00:26:49 2013 +0200

    Make default snippet customizable

diff --git a/yasnippet.el b/yasnippet.el
index f44a994..0a94ffb 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -187,6 +187,19 @@ as the default for storing the user's new snippets."
 
 (defvaralias 'yas/root-directory 'yas-snippet-dirs)
 
+(defcustom yas-new-snippet-default "\
+# -*- mode: snippet -*-
+# name: $1
+# key: ${2:${1:$(replace-regexp-in-string \"\\\\\\\\(\\\\\\\\w+\\\\\\\\).*\" 
\"\\\\\\\\1\" yas-text)}}${3:
+# binding: ${4:direct-keybinding}}${5:
+# expand-env: ((${6:some-var} ${7:some-value}))}${8:
+# type: command}
+# --
+$0"
+  "Default snippet to use when creating a new snippet."
+  :type 'string
+  :group 'yasnippet)
+
 (defcustom yas-prompt-functions '(yas-x-prompt
                                   yas-dropdown-prompt
                                   yas-completing-prompt
@@ -2514,15 +2527,7 @@ NO-TEMPLATE is non-nil."
     (set (make-local-variable 'yas--guessed-modes) (mapcar #'(lambda (d)
                                                               (yas--table-mode 
(car d)))
                                                           guessed-directories))
-    (unless no-template (yas-expand-snippet "\
-# -*- mode: snippet -*-
-# name: $1
-# key: ${2:${1:$(replace-regexp-in-string \"\\\\\\\\(\\\\\\\\w+\\\\\\\\).*\" 
\"\\\\\\\\1\" yas-text)}}${3:
-# binding: ${4:direct-keybinding}}${5:
-# expand-env: ((${6:some-var} ${7:some-value}))}${8:
-# type: command}
-# --
-$0"))))
+    (unless no-template (yas-expand-snippet yas-new-snippet-default))))
 
 (defun yas--compute-major-mode-and-parents (file)
   "Given FILE, find the nearest snippet directory for a given mode.

commit 9e085ec05de4c3d288a787a522c6e5c81d01f1a7
Author: Joao Tavora <address@hidden>
Date:   Mon Jul 22 18:32:45 2013 +0100

    closes #391: don't assume `declare-function'/ exists, it doesn't in emacs22

diff --git a/yasnippet.el b/yasnippet.el
index 7e2eeee..f44a994 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1623,7 +1623,10 @@ Optional PROMPT sets the prompt to use."
                 ido-mode))
     (yas-completing-prompt prompt choices display-fn #'ido-completing-read)))
 
-(declare-function dropdown-list "dropdown-list")
+(eval-when-compile
+  (if (fboundp 'declare-function)
+      (declare-function dropdown-list "dropdown-list")))
+
 (defun yas-dropdown-prompt (prompt choices &optional display-fn)
   (when (featurep 'dropdown-list)
     (let (formatted-choices

commit 636c01d34a8cd7f9acce49ba53b0171931887eb9
Author: João Távora <address@hidden>
Date:   Thu May 9 00:07:22 2013 +0100

    doc: finally decided to write the manual in markdown
    
    will use same or similar doc helpers

diff --git a/doc/manual.mdown b/doc/manual.mdown
new file mode 100644
index 0000000..aac0d89
--- /dev/null
+++ b/doc/manual.mdown
@@ -0,0 +1,257 @@
+Quick start
+===========
+
+*YASnippet* is a template system for Emacs. It allows you to type an
+abbreviation and automatically expand it into function templates. Bundled
+language templates includes: C, C++, C#, Perl, Python, Ruby, SQL, LaTeX, HTML,
+CSS and more. The snippet syntax is inspired from TextMate's syntax, you can
+even [import most TextMate snippets](#import-textmate)
+
+YASnippet is an original creation of [pluskid][pluskid] who also wrote its 
predecessor
+[smart-snippet][smart-snippet].
+
+Watch a demo
+------------
+
+Do so on [youtube][youtube]
+
+Installation
+------------
+
+Clone this repository somewhere
+
+    $ cd ~/.emacs.d/plugins
+    $ git clone https://github.com/capitaomorte/yasnippet
+
+Add the following in your =.emacs= file:
+
+    (add-to-list 'load-path
+                  "~/.emacs.d/plugins/yasnippet")
+    (require 'yasnippet)
+    (yas/global-mode 1)
+
+Add your own snippets to `~/.emacs.d/snippets` by placing files there or
+invoking `yas-new-snippet`.
+
+Import textmate snippets (rails example)
+----------------------------------------
+
+YASnippet lets you use TextMate bundles directly:
+
+    $ cd ~/.emacs.d/plugins
+    $ git clone https://github.com/capitaomorte/yasnippet
+    $ cd yasnippet
+    $ git submodule init
+    $ git submodule update
+    $ gem install plist trollop
+    $ rake convert_bundles             # will convert ruby, rails and html 
bundles from drnic
+
+Then, in your `.emacs` file
+
+
+    (add-to-list 'load-path
+                  "~/.emacs.d/plugins/yasnippet")
+    (require 'yasnippet)
+    (setq yas/snippet-dirs '("~/.emacs.d/snippets" 
"~/.emacs.d/extras/imported"))
+    (yas/global-mode 1)
+
+Open some rails file (model, app, etc) and start using the textmate
+snippets. Consider that this is a work-in-progress and many snippets/commands
+might not work. Patches welcome!
+
+Contributing snippets
+---------------------
+
+Please *do not ask me* to add snippets to the default collection under
+`/snippets`. This collection is considered frozen. By customizing
+`yas-snippet-dirs` you can point yasnippet to good snippet collections out
+there.
+
+The `extras/textmate-import.rb` tool can import many actual Textmate snippets.
+I'm focusing on developing it and the accompanying `yas-setup.el` files that
+guide it with more difficult importations. The idea is to deprecate `/snippets=
+and replace it with =extras/imported`.
+
+Documentation, issues, etc
+--------------------------
+
+Please refer to the comprehensive [documentation](docs) for full
+customization and support.  If you think you've found a bug, please report it
+on [the GitHub issue tracker](issues).  (please **do not** submit new
+issues to the old [googlecode tracker](googlecode-tracker))
+
+If you run into problems using YASnippet, or have snippets to contribute,
+post to the [yasnippet forum](forum). Thank you very much for using
+YASnippet!
+
+Organizing snippets
+===================
+
+Basic structure
+---------------
+
+Snippet collections can be stored in plain text files. They are arranged by
+sub-directories naming *snippet tables*. These mostly name Emacs major names.
+
+    .
+    |-- c-mode
+    |   `-- printf
+    |-- java-mode
+    |   `-- println
+    `-- text-mode
+        |-- email
+        `-- time
+
+The collections are loaded into *snippet tables* which the triggering
+mechanism (see [Expanding snippets](#expand-snippets)) looks up and
+(hopefully) cause the right snippet to be expanded for you.
+
+Setting up `yas-snippet-dirs`
+-----------------------------
+
+The emacs variable `yas-snippet-dirs` tells YASnippet
+which collections to consider. It's used when you activate
+`yas-global-mode` or call
+`yas-reload-all` interactively.
+
+The default considers:
+
+ - a personal collection that lives in `~/.emacs.d/snippets`
+ - the bundled collection, taken as a relative path to `yasnippet.el` localtion
+
+When you come across other snippet collections, do the following to try them
+out:
+
+;; Develop in ~/emacs.d/mysnippets, but also
+;; try out snippets in ~/Downloads/interesting-snippets
+(setq yas/snippet-dirs '("~/emacs.d/mysnippets"
+                           "~/Downloads/interesting-snippets"))
+
+;; OR, keeping yasnippet's defaults try out ~/Downloads/interesting-snippets
+(setq yas/snippet-dirs (append yas/snippet-dirs
+                               '("~/Downloads/interesting-snippets")))
+
+Collections appearing earlier in the list shadow snippets with same names
+appearing in collections later in the list. `yas-new-snippet` always stores
+snippets in the first collection.
+
+The `.yas.parents` file
+-----------------------
+
+It's very useful to have certain modes share snippets between themselves. To do
+this, choose a mode subdirectory and place a `.yas-parents` containing a
+whitespace-separated list of other mode names. When you reload those modes
+become parents of the original mode.
+
+    .
+    |-- c-mode
+    |   |-- .yas-parents    # contains "cc-mode text-mode"
+    |   `-- printf
+    |-- cc-mode
+    |   |-- for
+    |   `-- while
+    |-- java-mode
+    |   |-- .yas-parents    # contains "cc-mode text-mode"
+    |   `-- println
+    `-- text-mode
+        |-- email
+        `-- time
+
+The `.yas-make-groups` file
+---------------------------
+
+If you place an empty plain text file `.yas-make-groups` inside one of the mode
+directories, the names of these sub-directories are considered groups of
+snippets and [the menu](snippet-menu) is organized much more cleanly:
+
+(TODO image)
+
+Another alternative way to achieve this is to place a `# group:` directive
+inside the snippet definition. See [Writing Snippets](#writing-snippets)
+
+
+    $ tree ruby-mode/
+    ruby-mode/
+    |-- .yas-make-groups
+    |-- collections
+    |   |-- each
+    |   `-- ...
+    |-- control structure
+    |   |-- forin
+    |   `-- ...
+    |-- definitions
+    |   `-- ...
+    `-- general
+       `-- ...
+
+
+Yet another way to create a nice snippet menu is to write into
+`.yas-make-groups` a menu definition. TODO
+
+TODO The `.yas-setup.el` file
+-----------------------------
+
+*** TODO
+
+TODO The `.yas-compiled-snippet.el` file
+----------------------------------------
+
+*** TODO
+
+The `.yas-skip` file
+--------------------
+
+Expanding Snippets
+==================
+
+This section describes how YASnippet chooses snippets for expansion at point.
+
+Maybe, you'll want some snippets to be expanded in a particular
+mode, or only under certain conditions, or be prompted using
+
+Triggering expansion
+--------------------
+
+To make a snippet expand after the cursor:
+
+* Type an the snippet's *trigger key* then press the key defined in
+  `yas-trigger-key`.
+
+* Use the snippet's *keybinding*.
+
+* Call [`yas-insert-snippet=](#yas-insert-snippet) (use `M-x
+  yas-insert-snippet`= or its keybinding =C-c & C-s`).
+
+* By expanding directly from the "YASnippet" menu in the menu-bar
+
+* Using hippie-expand
+
+* Use m2m's excellent [auto-complete](http://github.com/m2m/autocomplete)
+
+Reference
+=========
+
+    (yas--document-symbols 2 `("Interactive functions" . ,#'interactive-form)
+                             `("Customization variables" . ,#'(lambda (sym)
+                                                                (and (boundp 
sym)
+                                                                     (get sym 
'standard-value))))
+                             `("Useful functions" . ,#'fboundp)
+                             `("Useful variables" . ,#'boundp))
+
+[smart-snippet]:      http://code.google.com/p/smart-snippet
+[pluskid]:            http://pluskid.lifegoo.org
+[screencast]:         http://www.youtube.com/watch?v=ZCGmZK4V7Sg
+[docs]:               http://capitaomorte.github.com/yasnippet
+[issues]:             https://github.com/capitaomorte/yasnippet/issues
+[googlecode-tracker]: http://code.google.com/p/yasnippet/issues/list
+[forum]:              http://groups.google.com/group/smart-snippet
+
+
+
+<!--
+ !-- Local Variables:
+ !-- mode: markdown
+ !-- fill-column: 80
+ !-- coding: utf-8
+ !-- End:
+ !-- -->
diff --git a/doc/manual.org b/doc/manual.org
deleted file mode 100644
index 8c247c6..0000000
--- a/doc/manual.org
+++ /dev/null
@@ -1,266 +0,0 @@
-#+TITLE: Yet another snippet extension
-#+OPTIONS: toc:1
-#+STARTUP: showall
-
-#+STYLE: <link rel="stylesheet" type="text/css" href="stylesheets/styles.css" 
/>
-
-# External links
-#
-#+LINK: smart-snippet http://code.google.com/p/smart-snippet
-#+LINK: pluskid       http://pluskid.lifegoo.org
-
-#+LINK: screencast         http://www.youtube.com/watch?v=ZCGmZK4V7Sg
-#+LINK: docs               http://capitaomorte.github.com/yasnippet
-#+LINK: issues             https://github.com/capitaomorte/yasnippet/issues
-#+LINK: googlecode-tracker http://code.google.com/p/yasnippet/issues/list
-#+LINK: forum              http://groups.google.com/group/smart-snippet
-
-
-* Quick start
-
-  *YASnippet* is a template system for Emacs. It allows you to type an
-  abbreviation and automatically expand it into function templates. Bundled
-  language templates includes: C, C++, C#, Perl, Python, Ruby, SQL, LaTeX, 
HTML,
-  CSS and more. The snippet syntax is inspired from TextMate's syntax, you can
-  even [[#import-textmate][import most TextMate snippets]]
-
-  YASnippet is an original creation of [[pluskid]] who also wrote its 
predecessor
-  [[smart-snippet]].
-
-** Watch a demo
-
-   [[youtube]]
-
-** Installation
-
-   Clone this repository somewhere
-
-   #+begin_example
-   $ cd ~/.emacs.d/plugins
-   $ git clone https://github.com/capitaomorte/yasnippet
-   #+end_example
-
-   Add the following in your =.emacs= file:
-
-   #+begin_src emacs-lisp :exports code
-   (add-to-list 'load-path
-                 "~/.emacs.d/plugins/yasnippet")
-   (require 'yasnippet)
-   (yas/global-mode 1)
-   #+end_src
-
-   Add your own snippets to =~/.emacs.d/snippets= by placing files there or
-   invoking [[#yas-new-snippet][=yas-new-snippet=]].
-
-** Import textmate snippets (rails example)
-   :PROPERTIES:
-   :CUSTOM_ID: import-textmate
-   :END:
-
-   YASnippet lets you use TextMate bundles directly:
-
-   #+begin_example
-   $ cd ~/.emacs.d/plugins
-   $ git clone https://github.com/capitaomorte/yasnippet
-   $ cd yasnippet
-   $ git submodule init
-   $ git submodule update
-   $ gem install plist trollop
-   $ rake convert_bundles             # will convert ruby, rails and html 
bundles from drnic
-   #+end_example
-
-   Then, in your =.emacs= file
-
-   #+begin_example
-   (add-to-list 'load-path
-                 "~/.emacs.d/plugins/yasnippet")
-   (require 'yasnippet)
-   (setq yas/snippet-dirs '("~/.emacs.d/snippets" 
"~/.emacs.d/extras/imported"))
-   (yas/global-mode 1)
-   #+end_example
-
-   Open some rails file (model, app, etc) and start using the textmate
-   snippets. Consider that this is a work-in-progress and many 
snippets/commands
-   might not work. Patches welcome!
-
-** Contributing snippets
-
-   Please *do not ask me* to add snippets to the default collection under
-   =/snippets=. This collection is considered frozen. By customizing
-   [[#yas-snippet-dirs][=yas-snippet-dirs=]] you can point yasnippet to good
-   snippet collections out there.
-
-   The =extras/textmate-import.rb= tool can import many actual Textmate
-   snippets.  I'm focusing on developing it and the accompanying =yas-setup.el=
-   files that guide it with more difficult importations. The idea is to 
deprecate
-   =/snippets=  and replace it with =extras/imported=.
-
-** Documentation, issues, etc
-
-   Please refer to the comprehensive [[docs][documentation]] for full
-   customization and support.  If you think you've found a bug, please report 
it
-   on [[issues][the GitHub issue tracker]].  (please **do not** submit new
-   issues to the old [[googlecode-tracker][googlecode tracker]])
-
-   If you run into problems using YASnippet, or have snippets to contribute,
-   post to the [[forum][yasnippet forum]]. Thank you very much for using
-   YASnippet!
-
-* Organizing snippets
-
-** Basic structure
-
-   Snippet collections can be stored in plain text files. They are arranged by
-   sub-directories naming *snippet tables*. These mostly name Emacs major 
names.
-
-   #+begin_example
-   .
-   |-- c-mode
-   |   `-- printf
-   |-- java-mode
-   |   `-- println
-   `-- text-mode
-       |-- email
-       `-- time
-   #+end_example
-
-   The collections are loaded into *snippet tables* which the triggering
-   mechanism (see [[#expand-snippets][Expanding snippets]]) looks up and
-   (hopefully) cause the right snippet to be expanded for you.
-
-** Setting up =yas-snippet-dirs=
-
-   The emacs variable [[#yas-snippet-dirs][=yas-snippet-dirs=]] tells YASnippet
-   which collections to consider. It's used when you activate
-   [[#yas-global-mode][=yas-global-mode=]] or call
-   [[#yas-reload-all][=yas-reload-all=]] interactively.
-
-   The default considers:
-
-    - a personal collection that lives in =~/.emacs.d/snippets=
-    - the bundled collection, taken as a relative path to =yasnippet.el= 
localtion
-
-   When you come across other snippet collections, do the following to try them
-   out:
-
-   #+begin_src emacs-lisp :exports code
-   ;; Develop in ~/emacs.d/mysnippets, but also
-   ;; try out snippets in ~/Downloads/interesting-snippets
-   (setq yas/snippet-dirs '("~/emacs.d/mysnippets"
-                              "~/Downloads/interesting-snippets"))
-
-   ;; OR, keeping yasnippet's defaults try out ~/Downloads/interesting-snippets
-   (setq yas/snippet-dirs (append yas/snippet-dirs
-                                  '("~/Downloads/interesting-snippets")))
-   #+end_src
-
-   Collections appearing earlier in the list shadow snippets with same names
-   appearing in collections later in the list. 
[[#yas-new-snippet][=yas-new-snippet=]] always stores
-   snippets in the first collection.
-
-** The =.yas.parents= file
-
-   It's very useful to have certain modes share snippets between themselves. 
To do
-   this, choose a mode subdirectory and place a =.yas-parents= containing a
-   whitespace-separated list of other mode names. When you reload those modes
-   become parents of the original mode.
-
-   #+begin_example
-   .
-   |-- c-mode
-   |   |-- .yas-parents    # contains "cc-mode text-mode"
-   |   `-- printf
-   |-- cc-mode
-   |   |-- for
-   |   `-- while
-   |-- java-mode
-   |   |-- .yas-parents    # contains "cc-mode text-mode"
-   |   `-- println
-   `-- text-mode
-       |-- email
-       `-- time
-   #+end_example
-
-** TODO The =.yas-make-groups= file
-
-   If you place an empty plain text file =.yas-make-groups= inside one of the
-   mode directories, the names of these sub-directories are considered groups 
of
-   snippets and [[snippet-menu][the menu]] is organized much more cleanly:
-
-   (TODO image)
-
-   Another alternative way to achieve this is to place a =# group:= directive
-   inside the snippet definition. See [[#writing-snippets][Writing Snippets]]
-
-   #+begin_example
-   $ tree ruby-mode/
-   ruby-mode/
-   |-- .yas-make-groups
-   |-- collections
-   |   |-- each
-   |   `-- ...
-   |-- control structure
-   |   |-- forin
-   |   `-- ...
-   |-- definitions
-   |   `-- ...
-   `-- general
-      `-- ...
-   #+end_example
-
-   Yet another way to create a nice snippet menu is to write into
-   =.yas-make-groups= a menu definition. TODO
-
-** TODO The =.yas-setup.el= file
-
-*** TODO
-
-** TODO The =.yas-compiled-snippet.el= file
-
-*** TODO
-
-** The =.yas-skip= file
-
-* Expanding Snippets
-
-   :PROPERTIES:
-   :CUSTOM_ID: expand-snippets
-   :END:
-
-  This section describes how YASnippet chooses snippets for expansion at point.
-
-  Maybe, you'll want some snippets to be expanded in a particular
-  mode, or only under certain conditions, or be prompted using
-
-** Triggering expansion
-
-   To make a snippet expand after the cursor:
-
-   * Type an the snippet's *trigger key* then press the key defined in
-     [[#yas-trigger-key][=yas-trigger-key=]] (usually to "TAB").
-
-   * Use the snippet's *keybinding*.
-
-   * Call [[#yas-insert-snippet][=yas-insert-snippet=]] (use =M-x
-     yas-insert-snippet== or its keybinding =C-c & C-s=).
-
-   * By expanding directly from the "YASnippet" menu in the menu-bar
-
-   * Using hippie-expand
-
-   * Use m2m's excellent auto-complete
-
-* Reference
-#+BEGIN_SRC emacs-lisp :exports results :results value raw
-(yas--document-symbols 2 `("Interactive functions" . ,#'interactive-form)
-                         `("Customization variables" . ,#'(lambda (sym)
-                                                            (and (boundp sym)
-                                                                 (get sym 
'standard-value))))
-                         `("Useful functions" . ,#'fboundp)
-                         `("Useful variables" . ,#'boundp))
-#+END_SRC
-# Local Variables:
-# mode: org
-# fill-column: 80
-# coding: utf-8
-# End:

commit ccea21bf99e8dc4c6f64225a1d61c5bf4cbd8de3
Author: João Távora <address@hidden>
Date:   Wed May 8 23:50:54 2013 +0100

    doc: remove README.org

diff --git a/README.org b/README.org
deleted file mode 100644
index a29324f..0000000
--- a/README.org
+++ /dev/null
@@ -1,102 +0,0 @@
-# -*- mode: org; fill-column: 80 -*-
-#+TITLE: Yet another snippet extension
-#+OPTIONS: toc:1
-#+STARTUP: showall
-
-#+STYLE: <link rel="stylesheet" type="text/css" href="assets/stylesheet.css" />
-
-# External links
-#
-#+LINK: smart-snippet http://code.google.com/p/smart-snippet
-#+LINK: pluskid       http://pluskid.lifegoo.org
-
-
-#+LINK: screencast         http://www.youtube.com/watch?v=ZCGmZK4V7Sg
-#+LINK: docs               http://capitaomorte.github.com/yasnippet
-#+LINK: issues             https://github.com/capitaomorte/yasnippet/issues
-#+LINK: googlecode-tracker http://code.google.com/p/yasnippet/issues/list
-#+LINK: forum              http://groups.google.com/group/smart-snippet
-
-*YASnippet* is a template system for Emacs. It allows you to type an
-abbreviation and automatically expand it into function templates. Bundled
-language templates includes: C, C++, C#, Perl, Python, Ruby, SQL, LaTeX, HTML,
-CSS and more. The snippet syntax is inspired from TextMate's syntax, you can
-even [[#import-textmate][import most TextMate snippets]]
-
-YASnippet is an original creation of [[pluskid]] who also wrote its predecessor
-[[smart-snippet]].
-
-* Watch a demo [[screencast]]
-
-* Install the most recent version with git
-
-Clone this repository somewhere
-
-#+BEGIN_EXAMPLE
-    $ cd ~/.emacs.d/plugins
-    $ git clone https://github.com/capitaomorte/yasnippet
-#+END_EXAMPLE
-
-Add the following in your =.emacs= file:
-
-#+BEGIN_EXAMPLE
-    (add-to-list 'load-path
-                  "~/.emacs.d/plugins/yasnippet")
-    (require 'yasnippet)
-    (yas/global-mode 1)
-#+END_EXAMPLE
-
-Add your own snippets to `~/.emacs.d/snippets` by placing files there or 
invoking `yas/new-snippet`.
-
-* Install yasnippet with el-get
-
-[[https://github.com/dimitri/el-get.gti][El-get]] is a nice way to get the 
most recent version.
-
-* Import textmate snippets (rails example)
-:PROPERTIES:
-:CUSTOM_ID: import-textmate
-:END:
-
-Clone the yasnippet repository to `~/.emacs.d/plugins/yasnippet`
-
-#+BEGIN_EXAMPLE
-    cd ~/.emacs.d/plugins/yasnippet
-    git submodule init
-    git submodule update
-    gem install plist trollop
-    rake convert_bundles             # will convert ruby, rails and html 
bundles from drnic
-#+END_EXAMPLE
-
-Then, in your .emacs file
-
-#+BEGIN_EXAMPLE
-    (add-to-list 'load-path
-                  "~/.emacs.d/plugins/yasnippet")
-    (require 'yasnippet)
-    (setq yas/snippet-dirs '("~/.emacs.d/snippets" 
"~/.emacs.d/extras/imported"))
-    (yas/global-mode 1)
-#+END_EXAMPLE
-
-Open some rails file (model, app, etc) and start using the textmate snippets.
-
-* Contributing snippets
-
-Please do not ask me to add snippets to the default collection under
-=/snippets=. This is considered frozen and by customizing =yas/snippet-dirs= 
you
-can point yasnippet to good snippet collections out there.
-
-The =extras/textmate-import.rb= tool can import many actual Textmate
-snippets. See [[import-textmate]].
-
-I'm focusing on developping =textmate-import.rb= tool and the =yas-setup.el=
-files that guide it with more difficult importation. In the future =/snippets=
-snippets will be deprecated and replaced with =extras/imported=.
-
-* Documentation, issues, etc
-
-Please refer to the comprehensive [[docs][documentation]] for full 
customization and
-support.  If you think you've found a bug, please report it on [[issues][the 
GitHub issue
-tracker]].  (please **do not** submit new issues to the old 
[[googlecode-tracker][googlecode tracker]])
-
-If you run into problems using YASnippet, or have snippets to contribute, post
-to the [[forum][yasnippet forum]]. Thank you very much for using YASnippet!

commit 8bf75fe425f39fced497e3e308555e726fe0d6f6
Author: Joao Tavora <address@hidden>
Date:   Sun May 5 21:15:27 2013 -0400

    Closes #372: removed trailing spaces in snippets

diff --git a/snippets/c++-mode/ns b/snippets/c++-mode/ns
index a343964..bff9ed7 100644
--- a/snippets/c++-mode/ns
+++ b/snippets/c++-mode/ns
@@ -1,4 +1,4 @@
 # name: namespace ...
 # key: ns
 # --
-namespace 
\ No newline at end of file
+namespace
\ No newline at end of file
diff --git a/snippets/c++-mode/using b/snippets/c++-mode/using
index f28937f..8da5348 100644
--- a/snippets/c++-mode/using
+++ b/snippets/c++-mode/using
@@ -1,4 +1,4 @@
-# name: using namespace ... 
+# name: using namespace ...
 # key: using
 # --
 using namespace ${std};
diff --git a/snippets/c-mode/printf b/snippets/c-mode/printf
index 035d07e..36313de 100644
--- a/snippets/c-mode/printf
+++ b/snippets/c-mode/printf
@@ -1,5 +1,5 @@
 # -*- mode: snippet -*-
-# name: printf 
+# name: printf
 # contributor: joaotavora
 # key: printf
 # --
diff --git a/snippets/csharp-mode/class b/snippets/csharp-mode/class
index 6c74c37..9cb096e 100644
--- a/snippets/csharp-mode/class
+++ b/snippets/csharp-mode/class
@@ -14,7 +14,7 @@ ${5:public} class ${1:Name}
 
     /// <summary>
     /// ${4:Default Destructor}
-    /// </summary>    
+    /// </summary>
     public ~$1()
     {
     }
diff --git a/snippets/emacs-lisp-mode/x-dired.process_marked.yasnippet 
b/snippets/emacs-lisp-mode/x-dired.process_marked.yasnippet
index 710657c..77ca69d 100755
--- a/snippets/emacs-lisp-mode/x-dired.process_marked.yasnippet
+++ b/snippets/emacs-lisp-mode/x-dired.process_marked.yasnippet
@@ -3,7 +3,7 @@
 # key: x-dired
 # --
 ;; idiom for processing a list of files in dired's marked files
- 
+
 ;; suppose myProcessFile is your function that takes a file path
 ;; and do some processing on the file
 
diff --git a/snippets/emacs-lisp-mode/x-file.read-lines.yasnippet 
b/snippets/emacs-lisp-mode/x-file.read-lines.yasnippet
index f85fe4e..e4cb092 100755
--- a/snippets/emacs-lisp-mode/x-file.read-lines.yasnippet
+++ b/snippets/emacs-lisp-mode/x-file.read-lines.yasnippet
@@ -10,8 +10,8 @@
      (buffer-string) "\n" t)) )
 
 ;; process all lines
-(mapc 
- (lambda (aLine) 
+(mapc
+ (lambda (aLine)
    (message aLine) ; do your stuff here
    )
  (read-lines "inputFilePath")
diff --git a/snippets/emacs-lisp-mode/x-find-replace.yasnippet 
b/snippets/emacs-lisp-mode/x-find-replace.yasnippet
index e5a1d6c..b0c58ec 100755
--- a/snippets/emacs-lisp-mode/x-find-replace.yasnippet
+++ b/snippets/emacs-lisp-mode/x-find-replace.yasnippet
@@ -6,7 +6,7 @@
   "Replace “<” to “&lt;” and other chars in HTML.
 This works on the current region."
   (interactive "r")
-  (save-restriction 
+  (save-restriction
     (narrow-to-region start end)
     (goto-char (point-min))
     (while (search-forward "&" nil t) (replace-match "&amp;" nil t))
diff --git a/snippets/f90-mode/au b/snippets/f90-mode/au
index e402b21..1b638db 100644
--- a/snippets/f90-mode/au
+++ b/snippets/f90-mode/au
@@ -2,4 +2,4 @@
 # name: automatic
 # key: au
 # --
-automatic $0 
\ No newline at end of file
+automatic $0
\ No newline at end of file
diff --git a/snippets/f90-mode/ii b/snippets/f90-mode/ii
index 7317cc3..bd89e90 100644
--- a/snippets/f90-mode/ii
+++ b/snippets/f90-mode/ii
@@ -1,5 +1,5 @@
 # contributor: Li Zhu <http://www.zhuli.name>
-# name: implicit integer 
+# name: implicit integer
 # key: ii
 # --
 implicit integer $0
\ No newline at end of file
diff --git a/snippets/html-mode/div b/snippets/html-mode/div
index 8b97ed1..bce4c3a 100644
--- a/snippets/html-mode/div
+++ b/snippets/html-mode/div
@@ -1,4 +1,4 @@
 # name: <div...>...</div>
 # key: div
 # --
-<div${1: id="${2:some_id}"}${3: class="${4:some_class}"}>$0</div> 
\ No newline at end of file
+<div${1: id="${2:some_id}"}${3: class="${4:some_class}"}>$0</div>
\ No newline at end of file
diff --git a/snippets/html-mode/script.javascript 
b/snippets/html-mode/script.javascript
index 9b77e43..c240755 100644
--- a/snippets/html-mode/script.javascript
+++ b/snippets/html-mode/script.javascript
@@ -1,5 +1,5 @@
 # contributor: Jimmy Wu <address@hidden>
-#name :<script type="text/javascript">...</script> 
+#name :<script type="text/javascript">...</script>
 # key: script
 # --
 <script type="text/javascript">
diff --git a/snippets/html-mode/script.javascript-src 
b/snippets/html-mode/script.javascript-src
index a090e72..fd5758d 100644
--- a/snippets/html-mode/script.javascript-src
+++ b/snippets/html-mode/script.javascript-src
@@ -1,5 +1,5 @@
 # contributor: Jimmy Wu <address@hidden>
-#name :<script type="text/javascript" src="..."></script> 
+#name :<script type="text/javascript" src="..."></script>
 # key: script
 # --
 <script type="text/javascript" src="$1"></script>
\ No newline at end of file
diff --git a/snippets/python-mode/def b/snippets/python-mode/def
index ca0ba66..ebc5c10 100644
--- a/snippets/python-mode/def
+++ b/snippets/python-mode/def
@@ -7,7 +7,7 @@
 def ${1:name}($2):
     """$3
     ${2:$
-      (let* 
+      (let*
         ((indent
             (concat "\n" (make-string (current-column) 32)))
            (args
diff --git a/snippets/ruby-mode/general/# b/snippets/ruby-mode/general/#
index 491ca39..6e9c0e0 100644
--- a/snippets/ruby-mode/general/#
+++ b/snippets/ruby-mode/general/#
@@ -1,4 +1,4 @@
 # name: # =>
 # key: #
 # --
-# => 
\ No newline at end of file
+# =>
\ No newline at end of file
diff --git a/snippets/scala-mode/asof b/snippets/scala-mode/asof
index 0736fd6..4f9550e 100644
--- a/snippets/scala-mode/asof
+++ b/snippets/scala-mode/asof
@@ -1,5 +1,5 @@
 # Author: Jonas Bonèr <address@hidden>
-# name: asInstanceOf[T] 
+# name: asInstanceOf[T]
 # key: asof
 # --
 asInstanceOf[${1:type}] $0
\ No newline at end of file
diff --git a/snippets/scala-mode/case b/snippets/scala-mode/case
index c09c17a..aa6da32 100644
--- a/snippets/scala-mode/case
+++ b/snippets/scala-mode/case
@@ -1,5 +1,5 @@
 # Author: Jonas Bonèr <address@hidden>
-# name: case pattern => 
+# name: case pattern =>
 # key: case
 # --
 case ${1:pattern} => $0
\ No newline at end of file
diff --git a/snippets/scala-mode/case.match-all 
b/snippets/scala-mode/case.match-all
index b481c9f..013b8f6 100644
--- a/snippets/scala-mode/case.match-all
+++ b/snippets/scala-mode/case.match-all
@@ -1,5 +1,5 @@
 # Author: Jonas Bonèr <address@hidden>
-# name: case _ => 
+# name: case _ =>
 # key: case
 # --
 case _ => $0
\ No newline at end of file
diff --git a/snippets/scala-mode/cast b/snippets/scala-mode/cast
index 659436d..f89a508 100644
--- a/snippets/scala-mode/cast
+++ b/snippets/scala-mode/cast
@@ -1,5 +1,5 @@
 # Author: Jonas Bonèr <address@hidden>
-# name: asInstanceOf[T] 
+# name: asInstanceOf[T]
 # key: cast
 # --
 asInstanceOf[${1:type}] $0
\ No newline at end of file
diff --git a/snippets/scala-mode/clof b/snippets/scala-mode/clof
index 63fe191..7d5a35d 100644
--- a/snippets/scala-mode/clof
+++ b/snippets/scala-mode/clof
@@ -1,5 +1,5 @@
 # Author: Jonas Bonèr <address@hidden>
-# name: classOf[T] 
+# name: classOf[T]
 # key: clof
 # --
 classOf[${1:type}] $0
\ No newline at end of file
diff --git a/snippets/scala-mode/doc.class b/snippets/scala-mode/doc.class
index a5c9962..9571f1d 100644
--- a/snippets/scala-mode/doc.class
+++ b/snippets/scala-mode/doc.class
@@ -2,8 +2,8 @@
 # name: /** cls/trt/obj name */
 # key: doc
 # --
-/** 
+/**
  * `(scala-mode-find-clstrtobj-name-doc)`
  * ${1:description}
- * $0  
+ * $0
  */
\ No newline at end of file
diff --git a/snippets/scala-mode/doc.def b/snippets/scala-mode/doc.def
index 4944d8e..53b1968 100644
--- a/snippets/scala-mode/doc.def
+++ b/snippets/scala-mode/doc.def
@@ -2,6 +2,6 @@
 # name: /** method name */
 # key: doc
 # --
-/** 
+/**
  * `(scala-mode-def-and-args-doc)`
- */ 
\ No newline at end of file
+ */
\ No newline at end of file
diff --git a/snippets/scala-mode/doc.file b/snippets/scala-mode/doc.file
index 5f02a9e..2bc39bf 100644
--- a/snippets/scala-mode/doc.file
+++ b/snippets/scala-mode/doc.file
@@ -6,5 +6,5 @@
  * `(scala-mode-file-doc)`
  * $0
  * @author ${1:name}
- * @version ${2:0.1} 
+ * @version ${2:0.1}
  */
\ No newline at end of file
diff --git a/snippets/scala-mode/doc.file-scala 
b/snippets/scala-mode/doc.file-scala
index 6c21919..aa9c58f 100644
--- a/snippets/scala-mode/doc.file-scala
+++ b/snippets/scala-mode/doc.file-scala
@@ -9,9 +9,9 @@
 ** /____/\___/_/ |_/____/_/ | |                                         **
 **                          |/                                          **
 \*                                                                      */
-/** 
+/**
  * $0
- * @author ${1:name} 
+ * @author ${1:name}
  * @version ${2:0.1}
  * $Id$
  */
\ No newline at end of file
diff --git a/snippets/scala-mode/doc.file-scala-api 
b/snippets/scala-mode/doc.file-scala-api
index bb306de..ffd4d0d 100644
--- a/snippets/scala-mode/doc.file-scala-api
+++ b/snippets/scala-mode/doc.file-scala-api
@@ -9,9 +9,9 @@
 ** /____/\___/_/ |_/____/_/ | |                                         **
 **                          |/                                          **
 \*                                                                      */
-/** 
+/**
  * $0
- * @author ${1:name} 
+ * @author ${1:name}
  * @version ${2:0.1}
  * $Id$
  */
\ No newline at end of file
diff --git a/snippets/scala-mode/isof b/snippets/scala-mode/isof
index bfb421f..6ab787b 100644
--- a/snippets/scala-mode/isof
+++ b/snippets/scala-mode/isof
@@ -1,5 +1,5 @@
 # Author: Jonas Bonèr <address@hidden>
-# name: isInstanceOf[T] 
+# name: isInstanceOf[T]
 # key: isof
 # --
 isInstanceOf[${1:type}] $0
\ No newline at end of file
diff --git a/snippets/scala-mode/match.can b/snippets/scala-mode/match.can
index 72798c5..e4f15f5 100644
--- a/snippets/scala-mode/match.can
+++ b/snippets/scala-mode/match.can
@@ -5,8 +5,8 @@
 ${1:option} match {
   case Full(res) => $0
 
-  case Empty => 
+  case Empty =>
 
-  case Failure(msg, _, _) => 
+  case Failure(msg, _, _) =>
 
 }
\ No newline at end of file
diff --git a/snippets/scala-mode/match.option b/snippets/scala-mode/match.option
index 01186e3..aa725c9 100644
--- a/snippets/scala-mode/match.option
+++ b/snippets/scala-mode/match.option
@@ -4,6 +4,6 @@
 # --
 ${1:option} match {
   case None => $0
-  case Some(res) => 
+  case Some(res) =>
 
 }
\ No newline at end of file
diff --git a/snippets/scala-mode/try b/snippets/scala-mode/try
index 0b65a6f..c9bf2e2 100644
--- a/snippets/scala-mode/try
+++ b/snippets/scala-mode/try
@@ -5,6 +5,6 @@
 try {
   $0
 } catch {
-  case ${1:e}: ${2:Exception} => 
+  case ${1:e}: ${2:Exception} =>
     ${1:println(\"ERROR: \" + e) // TODO: handle exception}\n}
 }
\ No newline at end of file
diff --git a/snippets/scala-mode/try.catch-finally 
b/snippets/scala-mode/try.catch-finally
index e431b98..52f8c31 100644
--- a/snippets/scala-mode/try.catch-finally
+++ b/snippets/scala-mode/try.catch-finally
@@ -5,7 +5,7 @@
 try {
   $0
 } catch {
-  case ${1:e}: ${2:Exception} => 
+  case ${1:e}: ${2:Exception} =>
     ${1:println(\"ERROR: \" + e) // TODO: handle exception}\n}
 } finally {
 
diff --git a/snippets/sql-mode/constraint b/snippets/sql-mode/constraint
index 5bb1902..bfa2b78 100644
--- a/snippets/sql-mode/constraint
+++ b/snippets/sql-mode/constraint
@@ -2,4 +2,4 @@
 # name: CONSTRAINT [..] PRIMARY KEY ...
 # key: constraint
 # --
-CONSTRAINT [${1:PK_Name}] PRIMARY KEY ${2:CLUSTERED} ([${3:ColumnName}]) 
\ No newline at end of file
+CONSTRAINT [${1:PK_Name}] PRIMARY KEY ${2:CLUSTERED} ([${3:ColumnName}])
\ No newline at end of file
diff --git a/snippets/sql-mode/constraint.1 b/snippets/sql-mode/constraint.1
index 245903f..bfef0b6 100644
--- a/snippets/sql-mode/constraint.1
+++ b/snippets/sql-mode/constraint.1
@@ -2,4 +2,4 @@
 # name: CONSTRAINT [..] FOREIGN KEY ...
 # key: constraint
 # --
-CONSTRAINT [${1:FK_Name}] FOREIGN KEY ${2:CLUSTERED} ([${3:ColumnName}]) 
\ No newline at end of file
+CONSTRAINT [${1:FK_Name}] FOREIGN KEY ${2:CLUSTERED} ([${3:ColumnName}])
\ No newline at end of file
diff --git a/snippets/sql-mode/create b/snippets/sql-mode/create
index 1678ed2..085b267 100644
--- a/snippets/sql-mode/create
+++ b/snippets/sql-mode/create
@@ -2,10 +2,10 @@
 # name: create table ...
 # key: create
 # --
-CREATE TABLE [${1:dbo}].[${2:TableName}] 
+CREATE TABLE [${1:dbo}].[${2:TableName}]
 (
                ${3:Id}         ${4:INT IDENTITY(1,1)}          ${5:NOT NULL}
 $0
-       CONSTRAINT [${6:PK_}] PRIMARY KEY ${7:CLUSTERED} ([$3]) 
+       CONSTRAINT [${6:PK_}] PRIMARY KEY ${7:CLUSTERED} ([$3])
 )
 GO
\ No newline at end of file
diff --git a/snippets/sql-mode/create.1 b/snippets/sql-mode/create.1
index 10b30a4..6c37dd8 100644
--- a/snippets/sql-mode/create.1
+++ b/snippets/sql-mode/create.1
@@ -2,7 +2,7 @@
 # name: create procedure ...
 # key: create
 # --
-CREATE PROCEDURE [${1:dbo}].[${2:Name}] 
+CREATE PROCEDURE [${1:dbo}].[${2:Name}]
 (
                $3              $4              = ${5:NULL}             
${6:OUTPUT}
 )

commit 9df05fc41302f6e04ffe5e8ff62c573348ec64f1
Author: Joao Tavora <address@hidden>
Date:   Sun May 5 20:42:18 2013 -0400

    Minor: indenting in for yasnippet-tests.el macro

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 4741a6d..257fd24 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -279,20 +279,20 @@ TODO: correct this bug!"
   `(yas-saving-variables
     (yas-with-overriden-buffer-list
      (yas-with-snippet-dirs
-      '((".emacs.d/snippets"
-         ("c-mode"
-          (".yas-parents" . "cc-mode")
-          ("printf" . "printf($1);"))  ;; notice the overriding for issue #281
-         ("emacs-lisp-mode" ("ert-deftest" . "(ert-deftest ${1:name} () $0)"))
-         ("lisp-interaction-mode" (".yas-parents" . "emacs-lisp-mode")))
-        ("library/snippets"
-         ("c-mode"
-          (".yas-parents" . "c++-mode")
-          ("printf" . "printf"))
-         ("cc-mode" ("def" . "# define"))
-         ("emacs-lisp-mode" ("dolist" . "(dolist)"))
-         ("lisp-interaction-mode" ("sc" . "brother from another mother"))))
-      ,@body))))
+       '((".emacs.d/snippets"
+          ("c-mode"
+           (".yas-parents" . "cc-mode")
+           ("printf" . "printf($1);"))  ;; notice the overriding for issue #281
+          ("emacs-lisp-mode" ("ert-deftest" . "(ert-deftest ${1:name} () $0)"))
+          ("lisp-interaction-mode" (".yas-parents" . "emacs-lisp-mode")))
+         ("library/snippets"
+          ("c-mode"
+           (".yas-parents" . "c++-mode")
+           ("printf" . "printf"))
+          ("cc-mode" ("def" . "# define"))
+          ("emacs-lisp-mode" ("dolist" . "(dolist)"))
+          ("lisp-interaction-mode" ("sc" . "brother from another mother"))))
+       ,@body))))
 
 (ert-deftest basic-jit-loading ()
   "Test basic loading and expansion of snippets"
@@ -357,34 +357,34 @@ TODO: correct this bug!"
 (defmacro yas-with-even-more-interesting-snippet-dirs (&rest body)
   `(yas-saving-variables
     (yas-with-snippet-dirs
-     `((".emacs.d/snippets"
-        ("c-mode"
-         (".yas-make-groups" . "")
-         ("printf" . "printf($1);")
-         ("foo-group-a"
-          ("fnprintf" . "fprintf($1);")
-          ("snprintf" . "snprintf($1);"))
-         ("foo-group-b"
-          ("strcmp" . "strecmp($1);")
-          ("strcasecmp" . "strcasecmp($1);")))
-        ("lisp-interaction-mode"
-         ("ert-deftest" . "# group: barbar\n# --\n(ert-deftest ${1:name} () 
$0)"))
-        ("fancy-mode"
-         ("a-guy" . "# uuid: 999\n# --\nyo!")
-         ("a-sir" . "# uuid: 12345\n# --\nindeed!")
-         ("a-lady" . "# uuid: 54321\n# --\noh-la-la!")
-         ("a-beggar" . "# uuid: 0101\n# --\narrrgh!")
-         ("an-outcast" . "# uuid: 666\n# --\narrrgh!")
-         (".yas-setup.el" . , (pp-to-string
-                               '(yas-define-menu 'fancy-mode
-                                                 '((yas-ignore-item "0101")
-                                                   (yas-item "999")
-                                                   (yas-submenu "sirs"
-                                                                ((yas-item 
"12345")))
-                                                   (yas-submenu "ladies"
-                                                                ((yas-item 
"54321"))))
-                                                 '("666")))))))
-     ,@body)))
+      `((".emacs.d/snippets"
+         ("c-mode"
+          (".yas-make-groups" . "")
+          ("printf" . "printf($1);")
+          ("foo-group-a"
+           ("fnprintf" . "fprintf($1);")
+           ("snprintf" . "snprintf($1);"))
+          ("foo-group-b"
+           ("strcmp" . "strecmp($1);")
+           ("strcasecmp" . "strcasecmp($1);")))
+         ("lisp-interaction-mode"
+          ("ert-deftest" . "# group: barbar\n# --\n(ert-deftest ${1:name} () 
$0)"))
+         ("fancy-mode"
+          ("a-guy" . "# uuid: 999\n# --\nyo!")
+          ("a-sir" . "# uuid: 12345\n# --\nindeed!")
+          ("a-lady" . "# uuid: 54321\n# --\noh-la-la!")
+          ("a-beggar" . "# uuid: 0101\n# --\narrrgh!")
+          ("an-outcast" . "# uuid: 666\n# --\narrrgh!")
+          (".yas-setup.el" . , (pp-to-string
+                                '(yas-define-menu 'fancy-mode
+                                                  '((yas-ignore-item "0101")
+                                                    (yas-item "999")
+                                                    (yas-submenu "sirs"
+                                                                 ((yas-item 
"12345")))
+                                                    (yas-submenu "ladies"
+                                                                 ((yas-item 
"54321"))))
+                                                  '("666")))))))
+      ,@body)))
 
 (ert-deftest test-yas-define-menu ()
   (let ((yas-use-menu t))
@@ -594,6 +594,7 @@ TODO: be meaner"
           (delete-directory default-directory 'recursive))))))
 
 (defmacro yas-with-snippet-dirs (dirs &rest body)
+  (declare (indent defun))
   `(yas-call-with-snippet-dirs ,dirs
                                #'(lambda ()
                                    ,@body)))

commit 0da56720a8379c7d839043220aadd59a554a41ca
Author: Joao Tavora <address@hidden>
Date:   Sun May 5 20:41:04 2013 -0400

    Closes #318: now checks for circular parenthood in snippet dirs

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 6d57d86..4741a6d 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -312,6 +312,22 @@ TODO: correct this bug!"
      (yas-reload-all)
      (yas--basic-jit-loading-1))))
 
+(ert-deftest loading-with-cyclic-parenthood ()
+  "Test loading when cyclic parenthood is setup."
+  (yas-saving-variables
+   (yas-with-snippet-dirs '((".emacs.d/snippets"
+                             ("c-mode"
+                              (".yas-parents" . "cc-mode"))
+                             ("cc-mode"
+                              (".yas-parents" . "yet-another-c-mode"))
+                             ("yet-another-c-mode"
+                              (".yas-parents" . "c-mode"))))
+     (yas-reload-all)
+     (condition-case nil
+         (yas--all-parents 'c-mode)
+       (error
+        (ert-fail "cyclic parenthood test failed"))))))
+
 (defun yas--basic-jit-loading-1 (&optional compile)
   (with-temp-buffer
     (should (= 4 (hash-table-count yas--scheduled-jit-loads)))
diff --git a/yasnippet.el b/yasnippet.el
index f799ad5..7e2eeee 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -660,6 +660,11 @@ There might be additional parenting information stored in 
the
 `derived-mode-parent' property of some mode symbols, but that is
 not recorded here.")
 
+(defvar yas--ancestors (make-hash-table)
+  "A hash table of mode symbols do lists of all parent mode symbols.
+
+A cache managed by `yas--all-parents'")
+
 (defvar yas--direct-keymaps (list)
   "Keymap alist supporting direct snippet keybindings.
 
@@ -1151,9 +1156,21 @@ conditions to filter out potential expansions."
 
 (defun yas--all-parents (mode)
   "Returns a list of all parent modes of MODE."
-  (let ((parents (gethash mode yas--parents)))
-    (append parents
-            (mapcan #'yas--all-parents parents))))
+  (or (gethash mode yas--ancestors)
+      (let ((seen '()))
+        (labels ((yas--all-parents-1
+                  (m)
+                  (cond ((memq m seen)
+                         (yas--message 1
+                                       "Cyclic parenthood: mode %s has already 
seen as a parent of mode %s"
+                                       m mode)
+                         nil)
+                        (t
+                         (let* ((parents (gethash m yas--parents)))
+                           (setq seen (append seen parents))
+                           (append parents (mapcan #'yas--all-parents-1 
parents)))))))
+          (puthash mode (yas--all-parents-1 mode)
+                   yas--ancestors)))))
 
 (defun yas--table-templates (table)
   (when table
@@ -1866,6 +1883,7 @@ loading."
       ;;
       (setq yas--tables (make-hash-table))
       (setq yas--parents (make-hash-table))
+      (setq yas--ancestors (make-hash-table))
 
       ;; Before killing `yas--menu-table' use its keys to cleanup the
       ;; mode menu parts of `yas--minor-mode-menu' (thus also cleaning
@@ -2531,7 +2549,7 @@ neither do the elements of PARENTS."
                                     (buffer-substring-no-properties (point-min)
                                                                     
(point-max))))))))
     (when major-mode-sym
-      (cons major-mode-sym parents))))
+      (cons major-mode-sym (remove major-mode-sym parents)))))
 
 (defvar yas--editing-template nil
   "Supporting variable for `yas-load-snippet-buffer' and 
`yas--visit-snippet'.")

commit 742b353a81c6226681c4750a2d030b47ce323dbd
Merge: 7172a45 57138e6
Author: João Távora <address@hidden>
Date:   Sat May 4 06:39:45 2013 -0700

    Merge pull request #377 from tarsius/master
    
    do not require dropdown-list at compile time


commit 57138e6df432df8bbd0b8ddd69bf94e0136f9313
Author: Jonas Bernoulli <address@hidden>
Date:   Sat May 4 03:36:06 2013 +0200

    do not require dropdown-list at compile time
    
    It might not be available.
    
    Also update commentary with respect to dropdown-list.

diff --git a/yasnippet.el b/yasnippet.el
index 625204f..f799ad5 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -110,9 +110,9 @@
 ;;           are to be displayed, or all the tables for all major
 ;;           modes.
 ;;
-;;   The `dropdown-list.el' extension is bundled with YASnippet, you
-;;   can optionally use it the preferred "prompting method", putting in
-;;   your .emacs file, for example:
+;;   If you have `dropdown-list' installed, you can optionally use it
+;;   as the preferred "prompting method", putting in your .emacs file,
+;;   for example:
 ;;
 ;;       (require 'dropdown-list)
 ;;       (setq yas-prompt-functions '(yas-dropdown-prompt
@@ -1606,7 +1606,7 @@ Optional PROMPT sets the prompt to use."
                 ido-mode))
     (yas-completing-prompt prompt choices display-fn #'ido-completing-read)))
 
-(eval-when-compile (require 'dropdown-list nil t))
+(declare-function dropdown-list "dropdown-list")
 (defun yas-dropdown-prompt (prompt choices &optional display-fn)
   (when (featurep 'dropdown-list)
     (let (formatted-choices

commit 7172a450d25433aaf4af3017c065044fdfff41b2
Merge: d9d7ed3 0bd2f3e
Author: João Távora <address@hidden>
Date:   Thu May 2 00:34:49 2013 -0700

    Merge pull request #370 from tarsius/master
    
    remove bundled dropdown-list.el


commit 0bd2f3ef6447421436b55ed1b4585805ad952f23
Author: Jonas Bernoulli <address@hidden>
Date:   Tue Mar 12 19:35:01 2013 +0100

    remove bundled dropdown-list.el
    
    It is available from melpa, so no need to bundle it.

diff --git a/dropdown-list.el b/dropdown-list.el
deleted file mode 100644
index bf55ebe..0000000
--- a/dropdown-list.el
+++ /dev/null
@@ -1,254 +0,0 @@
-;;; dropdown-list.el --- Drop-down menu interface
-;;
-;; Filename: dropdown-list.el
-;; Description: Drop-down menu interface
-;; Copyright (C) 2008-2012 Free Software Foundation, Inc.
-;; Author: Jaeyoun Chung address@hidden
-;; Maintainer:
-;; Authors: pluskid <address@hidden>,  João Távora <address@hidden>
-;; Created: Sun Mar 16 11:20:45 2008 (Pacific Daylight Time)
-;; Version:
-;; Last-Updated: Sun Mar 16 12:19:49 2008 (Pacific Daylight Time)
-;;           By: dradams
-;;     Update #: 43
-;; URL: http://www.emacswiki.org/cgi-bin/wiki/dropdown-list.el
-;; Keywords: convenience menu
-;; Compatibility: GNU Emacs 21.x, GNU Emacs 22.x
-;;
-;; Features that might be required by this library:
-;;
-;;   `cl'.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;;  According to Jaeyoun Chung, "overlay code stolen from company-mode.el."
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Change log:
-;;
-;; 2008/03/16 dadams
-;;     Clean-up - e.g. use char-to-string for control chars removed by email 
posting.
-;;     Moved example usage code (define-key*, command-selector) inside the 
library.
-;;     Require cl.el at byte-compile time.
-;;     Added GPL statement.
-;; 2008/01/06 Jaeyoun Chung
-;;     Posted to address@hidden at 9:10 p.m.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Code:
-
-(eval-when-compile (require 'cl)) ;; decf, fourth, incf, loop, mapcar*
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defface dropdown-list-face
-  '((t :inherit default :background "lightyellow" :foreground "black"))
-  "*Bla." :group 'dropdown-list)
-
-(defface dropdown-list-selection-face
-  '((t :inherit dropdown-list-face :background "purple"))
-  "*Bla." :group 'dropdown-list)
-
-(defvar dropdown-list-overlays nil)
-
-(defun dropdown-list-hide ()
-  (while dropdown-list-overlays
-    (delete-overlay (pop dropdown-list-overlays))))
-
-(defun dropdown-list-put-overlay (beg end &optional prop value prop2 value2)
-  (let ((ov (make-overlay beg end)))
-    (overlay-put ov 'window t)
-    (when prop
-      (overlay-put ov prop value)
-      (when prop2 (overlay-put ov prop2 value2)))
-    ov))
-
-(defun dropdown-list-line (start replacement &optional no-insert)
-  ;; start might be in the middle of a tab, which means we need to hide the
-  ;; tab and add spaces
-  (let ((end (+ start (length replacement)))
-        beg-point end-point
-        before-string after-string)
-    (goto-char (point-at-eol))
-    (if (< (current-column) start)
-        (progn (setq before-string (make-string (- start (current-column)) ? ))
-               (setq beg-point (point)))
-      (goto-char (point-at-bol)) ;; Emacs bug, move-to-column is wrong 
otherwise
-      (move-to-column start)
-      (setq beg-point (point))
-      (when (> (current-column) start)
-        (goto-char (1- (point)))
-        (setq beg-point (point))
-        (setq before-string (make-string (- start (current-column)) ? ))))
-    (move-to-column end)
-    (setq end-point (point))
-    (let ((end-offset (- (current-column) end)))
-      (when (> end-offset 0) (setq after-string (make-string end-offset ?b))))
-    (when no-insert
-      ;; prevent inheriting of faces
-      (setq before-string (when before-string (propertize before-string 'face 
'default)))
-      (setq after-string (when after-string (propertize after-string 'face 
'default))))
-    (let ((string (concat before-string replacement after-string)))
-      (if no-insert
-          string
-        (push (dropdown-list-put-overlay beg-point end-point 'invisible t
-                                         'after-string string)
-              dropdown-list-overlays)))))
-
-(defun dropdown-list-start-column (display-width)
-  (let ((column (mod (current-column) (window-width)))
-        (width (window-width)))
-    (cond ((<= (+ column display-width) width) column)
-          ((> column display-width) (- column display-width))
-          ((>= width display-width) (- width display-width))
-          (t nil))))
-
-(defun dropdown-list-move-to-start-line (candidate-count)
-  (decf candidate-count)
-  (let ((above-line-count (save-excursion (- (vertical-motion (- 
candidate-count)))))
-        (below-line-count (save-excursion (vertical-motion candidate-count))))
-    (cond ((= below-line-count candidate-count)
-           t)
-          ((= above-line-count candidate-count)
-           (vertical-motion (- candidate-count))
-           t)
-          ((>= (+ below-line-count above-line-count) candidate-count)
-           (vertical-motion (- (- candidate-count below-line-count)))
-           t)
-          (t nil))))
-
-(defun dropdown-list-at-point (candidates &optional selidx)
-  (dropdown-list-hide)
-  (let* ((lengths (mapcar #'length candidates))
-         (max-length (apply #'max lengths))
-         (start (dropdown-list-start-column (+ max-length 3)))
-         (i -1)
-         (candidates (mapcar* (lambda (candidate length)
-                                (let ((diff (- max-length length)))
-                                  (propertize
-                                   (concat (if (> diff 0)
-                                               (concat candidate (make-string 
diff ? ))
-                                             (substring candidate 0 
max-length))
-                                           (format "%3d" (+ 2 i)))
-                                   'face (if (eql (incf i) selidx)
-                                             'dropdown-list-selection-face
-                                           'dropdown-list-face))))
-                              candidates
-                              lengths)))
-    (save-excursion
-      (and start
-           (dropdown-list-move-to-start-line (length candidates))
-           (loop initially (vertical-motion 0)
-                 for candidate in candidates
-                 do (dropdown-list-line (+ (current-column) start) candidate)
-                 while (/= (vertical-motion 1) 0)
-                 finally return t)))))
-
-(defun dropdown-list (candidates)
-  (let ((selection)
-        (temp-buffer))
-    (save-window-excursion
-      (unwind-protect
-          (let ((candidate-count (length candidates))
-                done key (selidx 0))
-            (while (not done)
-              (unless (dropdown-list-at-point candidates selidx)
-                (switch-to-buffer (setq temp-buffer (get-buffer-create 
"*selection*"))
-                                  'norecord)
-                (delete-other-windows)
-                (delete-region (point-min) (point-max))
-                (insert (make-string (length candidates) ?\n))
-                (goto-char (point-min))
-                (dropdown-list-at-point candidates selidx))
-              (setq key (read-key-sequence ""))
-              (cond ((and (stringp key)
-                          (>= (aref key 0) ?1)
-                          (<= (aref key 0) (+ ?0 (min 9 candidate-count))))
-                     (setq selection (- (aref key 0) ?1)
-                           done      t))
-                    ((member key `(,(char-to-string ?\C-p) [up] "p"))
-                     (setq selidx (mod (+ candidate-count (1- (or selidx 0)))
-                                       candidate-count)))
-                    ((member key `(,(char-to-string ?\C-n) [down] "n"))
-                     (setq selidx (mod (1+ (or selidx -1)) candidate-count)))
-                    ((member key `(,(char-to-string ?\f))))
-                    ((member key `(,(char-to-string ?\r) [return]))
-                     (setq selection selidx
-                           done      t))
-                    (t (setq done t)))))
-        (dropdown-list-hide)
-        (and temp-buffer (kill-buffer temp-buffer)))
-      ;;     (when selection
-      ;;       (message "your selection => %d: %s" selection (nth selection 
candidates))
-      ;;       (sit-for 1))
-      selection)))
-
-(defun define-key* (keymap key command)
-  "Add COMMAND to the multiple-command binding of KEY in KEYMAP.
-Use multiple times to bind different COMMANDs to the same KEY."
-  (define-key keymap key (combine-command command (lookup-key keymap key))))
-
-(defun combine-command (command defs)
-  "$$$$$ FIXME - no doc string"
-  (cond ((null defs) command)
-        ((and (listp defs)
-              (eq 'lambda (car defs))
-              (= (length defs) 4)
-              (listp (fourth defs))
-              (eq 'command-selector (car (fourth defs))))
-         (unless (member `',command (cdr (fourth defs)))
-           (setcdr (fourth defs) (nconc (cdr (fourth defs)) `(',command))))
-         defs)
-        (t
-         `(lambda () (interactive) (command-selector ',defs ',command)))))
-
-(defvar command-selector-last-command nil "$$$$$ FIXME - no doc string")
-
-(defun command-selector (&rest candidates)
-  "$$$$$ FIXME - no doc string"
-  (if (and (eq last-command this-command) command-selector-last-command)
-      (call-interactively command-selector-last-command)
-    (let* ((candidate-strings
-            (mapcar (lambda (candidate)
-                      (format "%s" (if (symbolp candidate)
-                                       candidate
-                                     (let ((s (format "%s" candidate)))
-                                       (if (>= (length s) 7)
-                                           (concat (substring s 0 7) "...")
-                                         s)))))
-                    candidates))
-           (selection (dropdown-list candidate-strings)))
-      (when selection
-        (let ((cmd (nth selection candidates)))
-          (call-interactively cmd)
-          (setq command-selector-last-command cmd))))))
-
-;;;;;;;;;;;;;;;;;;;;
-
-(provide 'dropdown-list)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; dropdown-list.el ends here
-;; Local Variables:
-;; coding: utf-8
-;; byte-compile-warnings: (not cl-functions)
-;; End:

commit d9d7ed32ae11df8cbc91646bd5b6984d37efd3b3
Author: Joao Tavora <address@hidden>
Date:   Wed Feb 20 11:07:13 2013 +0000

    Closes #312: YAS-MODE-SYMBOL does not exist anymore, replaced by 
YAS-EXTRA-MODES

diff --git a/extras/imported/html-mode/.yas-setup.el 
b/extras/imported/html-mode/.yas-setup.el
index e6faf15..48159a6 100644
--- a/extras/imported/html-mode/.yas-setup.el
+++ b/extras/imported/html-mode/.yas-setup.el
@@ -8,7 +8,7 @@
   "Html-mode snippets behave as close to TextMate as possible.")
 
 (defun yas-html-activate ()
-  (add-to-list (make-local-variable 'yas-mode-symbol) 'html-mode))
+  (add-to-list (make-local-variable 'yas-extra-modes) 'html-mode))
 
 (add-hook 'nxml-mode-hook 'yas-html-activate)
 (add-hook 'rhtml-mode-hook 'yas-html-activate)
@@ -227,67 +227,67 @@
 ;; 991E7EBD-F3F5-469A-BA01-DC30E04AD472                                        
               =yyas> (yas-html-wrap-each-line-in-openclose-tag)
 
 ;; Substitutions for: binding
-;; 
+;;
 ;; # as in Snippets/Strong.yasnippet
 ;; @b                                                                          
               =yyas> s-b
-;; 
+;;
 ;; # as in Snippets/Emphasize.yasnippet
-;; address@hidden                                                              
                          =yyas>   
+;; address@hidden                                                              
                          =yyas>
 ;; @i                                                                          
               =yyas> s-i
-;; 
+;;
 ;; # as in Snippets/Wrap Selection In Tag.yasnippet
 ;; ^W                                                                          
               =yyas> C-c M-w
-;; 
+;;
 ;; # as in Commands/Insert Tag Pair.yasnippet
 ;; ^<                                                                          
               =yyas> C-<
 ;;
 ;; # as in Commands/Documentation for Tag.yasnippet
 ;; ^h                                                                          
               =yyas> C-c M-h
-;; 
+;;
 ;; # as in Commands/Wrap Each Selected Line in OpenClose Tag.yasnippet
 ;; address@hidden                                                              
                          =yyas> C-c M-W
-;; 
+;;
 ;; # as in Snippets/XHTML &nbsp NonBreakingSpace.yasnippet
 ;; ~                                                                           
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Insert Entity.yasnippet
 ;; @&                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Refresh All Active Browsers.yasnippet
 ;; @r                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Persistent Include.yasnippet
 ;; address@hidden                                                              
                          =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/CodeCompletion HTML Tags.yasnippet
 ;; ~                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Update Includes.yasnippet
 ;; address@hidden                                                              
                          =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Macros/Delete whitespace between tags.yasnippet
 ;; ^~                                                                       
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Tidy.yasnippet
 ;; ^H                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;;
 ;; --**--
 ;; Automatically generated code, do not edit this part
-;; 
+;;
 ;; Translated menu
-;; 
+;;
 (yas-define-menu 'html-mode
                  '(;; Documentation for Tag
                    (yas-item "637CEA2B-578C-429C-BB74-30E8D42BFA22")
                    ;; Ignoring Validate Syntax (W3C)
                    (yas-ignore-item "3F26240E-6E4A-11D9-B411-000D93589AF6")
-                   
+
                    ;; Open Document in Running Browser(s)
                    (yas-item "970EE6B4-A091-11D9-A5A2-000D93C8BE28")
                    ;; Ignoring Refresh Running Browser(s)
                    (yas-ignore-item "B8651C6E-A05E-11D9-86AC-000D93C8BE28")
-                   
+
                    (yas-submenu "Entities"
                                 (;; Ignoring Convert Character / Selection to 
Entities
                                  (yas-ignore-item 
"3DD8406C-A116-11D9-A5A2-000D93C8BE28")
@@ -295,7 +295,7 @@
                                  (yas-ignore-item 
"43C9E8AE-3E53-4B82-A1AF-56697BB3EF09")
                                  ;; Ignoring Decode Entities in Line / 
Selection
                                  (yas-ignore-item 
"C183920D-A126-11D9-A5A2-000D93C8BE28")
-                                 
+
                                  ;; Non-Breaking Space
                                  (yas-item 
"73B40BAE-A295-11D9-87F7-000D93C8BE28")
                                  ;; →
@@ -340,7 +340,7 @@
                                  (yas-ignore-item 
"2C4C9673-B166-432A-8938-75A5CA622481")))
                    ;; Ignoring Encrypt Line / Selection (ROT 13)
                    (yas-ignore-item "9B13543F-8356-443C-B6E7-D9259B604927")
-                   
+
                    ;; Ignoring CodeCompletion HTML Attributes
                    (yas-ignore-item "CBD82CF3-74E9-4E7A-B3F6-9348754EB5AA")
                    ;; Insert Open/Close Tag (With Current Word)
@@ -364,7 +364,7 @@
                    (yas-submenu "Insert Tag"
                                 (;; Ignoring CodeCompletion HTML Tags
                                  (yas-ignore-item 
"3463E85F-F500-49A0-8631-D78ED85F9D60")
-                                 
+
                                  ;; Base
                                  (yas-item 
"4462A6B8-A08A-11D9-A5A2-000D93C8BE28")
                                  ;; Body
@@ -409,7 +409,7 @@
                                  (yas-item 
"AAC9D7B8-A12C-11D9-A5A2-000D93C8BE28")
                                  ;; Title
                                  (yas-item 
"B62ECABE-A086-11D9-A5A2-000D93C8BE28")))
-                   
+
                    (yas-submenu "Includes"
                                 (;; Ignoring Add Persistent Include
                                  (yas-ignore-item 
"0D814247-7A00-46EE-A2A4-45FBBF4B1181")
@@ -439,7 +439,7 @@
                                  (yas-item 
"CBC24AF4-88E0-498B-BE50-934B9CF29EC7")
                                  ;; IE Conditional Comment: NOT Internet 
Explorer
                                  (yas-item 
"F00170EE-4A82-413F-A88B-85293E69A88B")))
-                   
+
                    ;; Wrap Selection in Open/Close Tag
                    (yas-item "BC8B8AE2-5F16-11D9-B9C3-000D93589AF6")
                    ;; Wrap Each Selected Line in Open/Close Tag
@@ -482,209 +482,209 @@
                        "CDE8EFD6-9DE2-4E8C-BB6A-52E8CCD2E977"))
 
 ;; Unknown substitutions
-;; 
+;;
 ;; Substitutions for: content
-;; 
+;;
 ;; # as in Snippets/Emphasize.yasnippet
 ;; `(yas-html-toggle-wrap yas-selected-text "em")`                             
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML h1.yasnippet
 ;; `yas-selected-text`                                                         
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment Internet Explorer 5_0 only.yasnippet
 ;; `(or (yas-selected-text) "   IE Conditional Comment: Internet Explorer 5.0 
only ")`        =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment Internet Explorer 5_5 only.yasnippet
 ;; `(or (yas-selected-text) "   IE Conditional Comment: Internet Explorer 5.5 
only ")`        =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment Internet Explorer 5_x.yasnippet
 ;; `(or (yas-selected-text) "  IE Conditional Comment: Internet Explorer 5.x   
   ")`         =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment Internet Explorer 6 and 
below.yasnippet
 ;; `(or (yas-selected-text) " IE Conditional Comment: Internet Explorer 6 and 
below ")`       =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment Internet Explorer 6 only.yasnippet
 ;; `(or (yas-selected-text) "     IE Conditional Comment: Internet Explorer 6 
only   ")`      =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment Internet Explorer 7+.yasnippet
 ;; `(or (yas-selected-text) " IE Conditional Comment: Internet Explorer 7 and 
above ")`       =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment Internet Explorer.yasnippet
 ;; `(or (yas-selected-text) "       IE Conditional Comment: Internet Explorer  
        ")`    =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/IE Conditional Comment NOT Internet Explorer.yasnippet
 ;; `(or (yas-selected-text) "  IE Conditional Comment: NOT Internet Explorer   
   ")`         =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML meta.yasnippet
 ;; `yas-html-xhtml-attr`                                                       
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/Strong.yasnippet
 ;; `(yas-html-toggle-wrap yas-selected-text "strong")`                         
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/About Persistent Includes.yasnippet
 ;; 9AFDEB2C-D9F0-423E-8211-EBB089F51F0C                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/CodeCompletion HTML Attributes.yasnippet
 ;; CBD82CF3-74E9-4E7A-B3F6-9348754EB5AA                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/CodeCompletion HTML Tags.yasnippet
 ;; 3463E85F-F500-49A0-8631-D78ED85F9D60                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Encrypt Line Selection (ROT 13).yasnippet
 ;; 9B13543F-8356-443C-B6E7-D9259B604927                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Persistent Include.yasnippet
 ;; 0D814247-7A00-46EE-A2A4-45FBBF4B1181                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Update Includes.yasnippet
 ;; 4400BCE9-20E3-426E-B1D7-2C0BCA53BCF8                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Convert Line Selection to URL Escapes.yasnippet
 ;; 6B024865-6095-4CE3-8EDD-DC6F2230C2FF                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Convert to HTML Entities.yasnippet
 ;; 3DD8406C-A116-11D9-A5A2-000D93C8BE28                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Convert to named entities excl tags.yasnippet
 ;; 43C9E8AE-3E53-4B82-A1AF-56697BB3EF09                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Decode HTML Entities.yasnippet
 ;; C183920D-A126-11D9-A5A2-000D93C8BE28                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Decode Numeric URL Escapes in Line Selection.yasnippet
 ;; 2C4C9673-B166-432A-8938-75A5CA622481                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Insert Close Tag.yasnippet
 ;; 0658019F-3635-462E-AAC2-74E4FE508A9B                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Insert Entity.yasnippet
 ;; 89E5CC0A-3EFF-4DEF-A299-2E9651DE6529                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Refresh All Active Browsers.yasnippet
 ;; B8651C6E-A05E-11D9-86AC-000D93C8BE28                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Strip HTML tags.yasnippet
 ;; 20D760B5-A127-11D9-A5A2-000D93C8BE28                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Tidy.yasnippet
 ;; 45F92B81-6F0E-11D9-A1E4-000D9332809C                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/W3C validation.yasnippet
 ;; 3F26240E-6E4A-11D9-B411-000D93589AF6                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in DragCommands/Anchor Tag.yasnippet
 ;; B23D6E15-6B33-11D9-86C1-000D93589AF6                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in DragCommands/CSS Link.yasnippet
 ;; C8B717C2-6B33-11D9-BB47-000D93589AF6                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in DragCommands/Image Tag.yasnippet
 ;; CD6D2CC6-6B33-11D9-BDFD-000D93589AF6                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Macros/Delete whitespace between tags.yasnippet
 ;; 7B7E945E-A112-11D9-A5A2-000D93C8BE28                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML body.yasnippet
 ;; ${TM_FILENAME/(.*)\..*/\L$1/}                                               
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML form.yasnippet
 ;; ${TM_FILENAME/(.*?)\..*/$1_submit/}                                         
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML title.yasnippet
 ;; ${TM_FILENAME/((.+)\..*)?/(?2:$2:Page Title)/}                              
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Templates/HTML 4.0 Strict/info.yasnippet
 ;; 04332FA8-8157-46C4-9854-8C190FFD96C6                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Templates/HTML 4.0 Transitional/info.yasnippet
 ;; E6F19171-F664-4B4F-92DA-3E15E6CAD35C                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Templates/XHTML 1.0 Frameset/info.yasnippet
 ;; 26068A55-4C84-409D-BA00-162B55AF6961                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Templates/XHTML 1.0 Strict/info.yasnippet
 ;; EBEE6B51-29C7-4362-818F-A190CACD5296                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Templates/XHTML 1.0 Transitional/info.yasnippet
 ;; 65D38039-6B0A-48E9-9E49-43832ECC4107                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Templates/XHTML 1.1/info.yasnippet
 ;; CDE8EFD6-9DE2-4E8C-BB6A-52E8CCD2E977                                        
               =yyas> (yas-unknown)
-;; 
-;; 
+;;
+;;
 
 ;; Substitutions for: condition
-;; 
+;;
 ;; # as in Templates/XHTML 1.1/info.yasnippet
 ;; text.html                                                                   
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/CodeCompletion HTML Attributes.yasnippet
 ;; text.html punctuation.definition.tag -source, text.html meta.tag 
-entity.other.attribute-name -source  =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/CodeCompletion HTML Tags.yasnippet
 ;; text.html -entity.other.attribute-name -string.quoted, 
invalid.illegal.incomplete.html     =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Documentation for Tag.yasnippet
 ;; text.html, text.html entity.name.tag                                        
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Refresh All Active Browsers.yasnippet
 ;; text.html, source.css                                                       
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/Smart returnindent for tag pairs.yasnippet
 ;; meta.scope.between-tag-pair                                                 
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/Wrap Selection In Tag.yasnippet
 ;; text.html,                                                                  
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/Wrap in =.yasnippet
 ;; text.html string                                                            
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML head.yasnippet
 ;; text.html - text.html source                                                
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML title.yasnippet
 ;; text.html - text.blog                                                       
               =yyas> (yas-unknown)
-;; 
-;; 
+;;
+;;
 
 ;; Substitutions for: binding
-;; 
+;;
 ;; # as in Commands/CodeCompletion HTML Tags.yasnippet
 ;; ~                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Insert Entity.yasnippet
 ;; @&                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Persistent Include.yasnippet
 ;;                                                                             
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Update Includes.yasnippet
 ;; address@hidden                                                              
                          =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Insert Close Tag.yasnippet
 ;; address@hidden                                                              
                          =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Refresh All Active Browsers.yasnippet
 ;; @r                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/Tidy.yasnippet
 ;; ^H                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Commands/W3C validation.yasnippet
 ;; ^V                                                                          
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Macros/Delete whitespace between tags.yasnippet
 ;; ^~                                                                       
                 =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/Smart returnindent for tag pairs.yasnippet
 ;; 
                                                                                
          =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML &nbsp NonBreakingSpace.yasnippet
 ;; ~                                                                           
               =yyas> (yas-unknown)
-;; 
+;;
 ;; # as in Snippets/XHTML br.yasnippet
 ;; ^
                                                                                
         =yyas> (yas-unknown)
-;; 
-;; 
+;;
+;;
 
 ;; .yas-setup.el for html-mode ends here

commit e3a5f6e0c76e580a210e28828f83e8ea46a69a19
Author: João Távora <address@hidden>
Date:   Mon Feb 18 22:29:25 2013 +0000

    Fix: moved snippets/js2-mode to snippets/js-mode

diff --git a/snippets/js2-mode/assert.yasnippet 
b/snippets/js-mode/assert.yasnippet
similarity index 100%
rename from snippets/js2-mode/assert.yasnippet
rename to snippets/js-mode/assert.yasnippet
diff --git a/snippets/js2-mode/cb.yasnippet b/snippets/js-mode/cb.yasnippet
similarity index 100%
rename from snippets/js2-mode/cb.yasnippet
rename to snippets/js-mode/cb.yasnippet
diff --git a/snippets/js2-mode/com.yasnippet b/snippets/js-mode/com.yasnippet
similarity index 100%
rename from snippets/js2-mode/com.yasnippet
rename to snippets/js-mode/com.yasnippet
diff --git a/snippets/js2-mode/describe.yasnippet 
b/snippets/js-mode/describe.yasnippet
similarity index 100%
rename from snippets/js2-mode/describe.yasnippet
rename to snippets/js-mode/describe.yasnippet
diff --git a/snippets/js2-mode/err.snippet b/snippets/js-mode/err.snippet
similarity index 100%
rename from snippets/js2-mode/err.snippet
rename to snippets/js-mode/err.snippet
diff --git a/snippets/js2-mode/error.snippet b/snippets/js-mode/error.snippet
similarity index 100%
rename from snippets/js2-mode/error.snippet
rename to snippets/js-mode/error.snippet
diff --git a/snippets/js2-mode/expect.yasnippet 
b/snippets/js-mode/expect.yasnippet
similarity index 100%
rename from snippets/js2-mode/expect.yasnippet
rename to snippets/js-mode/expect.yasnippet
diff --git a/snippets/js2-mode/exports.yasnippet 
b/snippets/js-mode/exports.yasnippet
similarity index 100%
rename from snippets/js2-mode/exports.yasnippet
rename to snippets/js-mode/exports.yasnippet
diff --git a/snippets/js2-mode/fn.yasnippet b/snippets/js-mode/fn.yasnippet
similarity index 100%
rename from snippets/js2-mode/fn.yasnippet
rename to snippets/js-mode/fn.yasnippet
diff --git a/snippets/js2-mode/for.yasnippet b/snippets/js-mode/for.yasnippet
similarity index 100%
rename from snippets/js2-mode/for.yasnippet
rename to snippets/js-mode/for.yasnippet
diff --git a/snippets/js2-mode/id.yasnippet b/snippets/js-mode/id.yasnippet
similarity index 100%
rename from snippets/js2-mode/id.yasnippet
rename to snippets/js-mode/id.yasnippet
diff --git a/snippets/js2-mode/if.yasnippet b/snippets/js-mode/if.yasnippet
similarity index 100%
rename from snippets/js2-mode/if.yasnippet
rename to snippets/js-mode/if.yasnippet
diff --git a/snippets/js2-mode/invoc.yasnippet 
b/snippets/js-mode/invoc.yasnippet
similarity index 100%
rename from snippets/js2-mode/invoc.yasnippet
rename to snippets/js-mode/invoc.yasnippet
diff --git a/snippets/js2-mode/it.yasnippet b/snippets/js-mode/it.yasnippet
similarity index 100%
rename from snippets/js2-mode/it.yasnippet
rename to snippets/js-mode/it.yasnippet
diff --git a/snippets/js2-mode/log.yasnippet b/snippets/js-mode/log.yasnippet
similarity index 100%
rename from snippets/js2-mode/log.yasnippet
rename to snippets/js-mode/log.yasnippet
diff --git a/snippets/js2-mode/method.yasnippet 
b/snippets/js-mode/method.yasnippet
similarity index 100%
rename from snippets/js2-mode/method.yasnippet
rename to snippets/js-mode/method.yasnippet
diff --git a/snippets/js2-mode/mod.yasnippet b/snippets/js-mode/mod.yasnippet
similarity index 100%
rename from snippets/js2-mode/mod.yasnippet
rename to snippets/js-mode/mod.yasnippet
diff --git a/snippets/js2-mode/prop.yasnippet b/snippets/js-mode/prop.yasnippet
similarity index 100%
rename from snippets/js2-mode/prop.yasnippet
rename to snippets/js-mode/prop.yasnippet
diff --git a/snippets/js2-mode/proto.yasnippet 
b/snippets/js-mode/proto.yasnippet
similarity index 100%
rename from snippets/js2-mode/proto.yasnippet
rename to snippets/js-mode/proto.yasnippet
diff --git a/snippets/js2-mode/rq.yasnippet b/snippets/js-mode/rq.yasnippet
similarity index 100%
rename from snippets/js2-mode/rq.yasnippet
rename to snippets/js-mode/rq.yasnippet
diff --git a/snippets/js2-mode/rt.yasnippet b/snippets/js-mode/rt.yasnippet
similarity index 100%
rename from snippets/js2-mode/rt.yasnippet
rename to snippets/js-mode/rt.yasnippet
diff --git a/snippets/js2-mode/slice.yasnippet 
b/snippets/js-mode/slice.yasnippet
similarity index 100%
rename from snippets/js2-mode/slice.yasnippet
rename to snippets/js-mode/slice.yasnippet
diff --git a/snippets/js2-mode/super.yasnippet 
b/snippets/js-mode/super.yasnippet
similarity index 100%
rename from snippets/js2-mode/super.yasnippet
rename to snippets/js-mode/super.yasnippet
diff --git a/snippets/js2-mode/switch.yasnippet 
b/snippets/js-mode/switch.yasnippet
similarity index 100%
rename from snippets/js2-mode/switch.yasnippet
rename to snippets/js-mode/switch.yasnippet
diff --git a/snippets/js2-mode/throw.yasnippet 
b/snippets/js-mode/throw.yasnippet
similarity index 100%
rename from snippets/js2-mode/throw.yasnippet
rename to snippets/js-mode/throw.yasnippet
diff --git a/snippets/js2-mode/try.yasnippet b/snippets/js-mode/try.yasnippet
similarity index 100%
rename from snippets/js2-mode/try.yasnippet
rename to snippets/js-mode/try.yasnippet
diff --git a/snippets/js2-mode/var.yasnippet b/snippets/js-mode/var.yasnippet
similarity index 100%
rename from snippets/js2-mode/var.yasnippet
rename to snippets/js-mode/var.yasnippet
diff --git a/snippets/js2-mode/wh.yasnippet b/snippets/js-mode/wh.yasnippet
similarity index 100%
rename from snippets/js2-mode/wh.yasnippet
rename to snippets/js-mode/wh.yasnippet
diff --git a/snippets/js2-mode/while.yasnippet 
b/snippets/js-mode/while.yasnippet
similarity index 100%
rename from snippets/js2-mode/while.yasnippet
rename to snippets/js-mode/while.yasnippet

commit 2cf544b67f5a80df470888e6d94f7fdba13b144d
Merge: bf55421 61cee70
Author: João Távora <address@hidden>
Date:   Sat Feb 16 10:27:54 2013 -0800

    Merge pull request #363 from azer/master
    
    Add JavaScript Snippets


commit bf554212d357b842adcf7ff17ad2be1c75eec60e
Merge: 700a68e 8772b51
Author: João Távora <address@hidden>
Date:   Sat Feb 16 10:24:43 2013 -0800

    Merge pull request #358 from Sarcasm/master
    
    Make yas--version compatible with version-to-list()


commit 61cee70ec0dbf7e1528fc10660468b87a0ffc057
Author: E.Azer Koçulu <address@hidden>
Date:   Fri Feb 15 14:22:23 2013 -0800

    add js snippets

diff --git a/snippets/js2-mode/assert.yasnippet 
b/snippets/js2-mode/assert.yasnippet
new file mode 100644
index 0000000..59ec614
--- /dev/null
+++ b/snippets/js2-mode/assert.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: assert
+# key: assert
+# --
+assert.${1:equal}($0);
diff --git a/snippets/js2-mode/cb.yasnippet b/snippets/js2-mode/cb.yasnippet
new file mode 100644
index 0000000..9453e6a
--- /dev/null
+++ b/snippets/js2-mode/cb.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: cb
+# key: cb
+# --
+function(error, $1){
+$0
+}
diff --git a/snippets/js2-mode/com.yasnippet b/snippets/js2-mode/com.yasnippet
new file mode 100644
index 0000000..1eff9fe
--- /dev/null
+++ b/snippets/js2-mode/com.yasnippet
@@ -0,0 +1,10 @@
+# -*- mode: snippet -*-
+# name: com
+# key: com
+# --
+
+/**
+ * $0
+ * @param {${1:String}} $2
+ * @return {${3:String}}
+ */
diff --git a/snippets/js2-mode/describe.yasnippet 
b/snippets/js2-mode/describe.yasnippet
new file mode 100644
index 0000000..c40bae7
--- /dev/null
+++ b/snippets/js2-mode/describe.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: desc
+# key: desc
+# --
+describe('$1', function(){
+$2
+});
diff --git a/snippets/js2-mode/err.snippet b/snippets/js2-mode/err.snippet
new file mode 100644
index 0000000..a4b713b
--- /dev/null
+++ b/snippets/js2-mode/err.snippet
@@ -0,0 +1,9 @@
+# -*- mode: snippet -*-
+# name: err
+# key: err
+# --
+if(${1:error}){
+  callback($1);
+  return;
+}
+$2
diff --git a/snippets/js2-mode/error.snippet b/snippets/js2-mode/error.snippet
new file mode 100644
index 0000000..1c99ad2
--- /dev/null
+++ b/snippets/js2-mode/error.snippet
@@ -0,0 +1,9 @@
+# -*- mode: snippet -*-
+# name: error
+# key: error
+# --
+if(${1:error}){
+  callback($1);
+  return;
+}
+$2
diff --git a/snippets/js2-mode/expect.yasnippet 
b/snippets/js2-mode/expect.yasnippet
new file mode 100644
index 0000000..8e0879e
--- /dev/null
+++ b/snippets/js2-mode/expect.yasnippet
@@ -0,0 +1,6 @@
+# -*- mode: snippet -*-
+# name: expect
+# key: expect
+# --
+expect($1).to.${2:equal}($3);
+$0
\ No newline at end of file
diff --git a/snippets/js2-mode/exports.yasnippet 
b/snippets/js2-mode/exports.yasnippet
new file mode 100644
index 0000000..6e183cd
--- /dev/null
+++ b/snippets/js2-mode/exports.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: exports
+# key: exports
+# --
+module.exports = {
+$0
+};
diff --git a/snippets/js2-mode/fn.yasnippet b/snippets/js2-mode/fn.yasnippet
new file mode 100644
index 0000000..67294fc
--- /dev/null
+++ b/snippets/js2-mode/fn.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: fn
+# key: fn
+# --
+function$1($2){
+$0
+}
diff --git a/snippets/js2-mode/for.yasnippet b/snippets/js2-mode/for.yasnippet
new file mode 100644
index 0000000..97d772f
--- /dev/null
+++ b/snippets/js2-mode/for.yasnippet
@@ -0,0 +1,9 @@
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+var ${1:i} = ${2:-1}, len = $3.length;
+
+for(; ++$1 < len;){
+  $4
+}
diff --git a/snippets/js2-mode/id.yasnippet b/snippets/js2-mode/id.yasnippet
new file mode 100644
index 0000000..47f00b9
--- /dev/null
+++ b/snippets/js2-mode/id.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: id
+# key: id
+# --
+document.getElementById('$0');
diff --git a/snippets/js2-mode/if.yasnippet b/snippets/js2-mode/if.yasnippet
new file mode 100644
index 0000000..0fac855
--- /dev/null
+++ b/snippets/js2-mode/if.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if( ${1} ){
+$0
+}
diff --git a/snippets/js2-mode/invoc.yasnippet 
b/snippets/js2-mode/invoc.yasnippet
new file mode 100644
index 0000000..cf46321
--- /dev/null
+++ b/snippets/js2-mode/invoc.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: invoc
+# key: invoc
+# --
+(function($1){
+$0
+})($2);
diff --git a/snippets/js2-mode/it.yasnippet b/snippets/js2-mode/it.yasnippet
new file mode 100644
index 0000000..161d51f
--- /dev/null
+++ b/snippets/js2-mode/it.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: it
+# key: it
+# --
+it('$1', function(done){
+$2
+});
diff --git a/snippets/js2-mode/log.yasnippet b/snippets/js2-mode/log.yasnippet
new file mode 100644
index 0000000..19ff1be
--- /dev/null
+++ b/snippets/js2-mode/log.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: log
+# key: log
+# --
+console.${1:log}( $0 );
diff --git a/snippets/js2-mode/method.yasnippet 
b/snippets/js2-mode/method.yasnippet
new file mode 100644
index 0000000..67fb56a
--- /dev/null
+++ b/snippets/js2-mode/method.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: method
+# key: method
+# --
+$1.prototype.$2 = function($3){
+${0}
+};
diff --git a/snippets/js2-mode/mod.yasnippet b/snippets/js2-mode/mod.yasnippet
new file mode 100644
index 0000000..c1b9867
--- /dev/null
+++ b/snippets/js2-mode/mod.yasnippet
@@ -0,0 +1,11 @@
+# -*- mode: snippet -*-
+# name: mod
+# key: mod
+# --
+var $1 = require("${2:$1}")$3
+
+module.exports = {
+  $4: $4$5
+};
+
+$0
diff --git a/snippets/js2-mode/prop.yasnippet b/snippets/js2-mode/prop.yasnippet
new file mode 100644
index 0000000..dc234c7
--- /dev/null
+++ b/snippets/js2-mode/prop.yasnippet
@@ -0,0 +1,19 @@
+# -*- mode: snippet -*-
+# name: prop
+# key: prop
+# --
+
+var $1 = (function(){
+
+  var value = undefined;
+
+  return function $1(newValue){
+
+    if( $1.arguments.length > 0 ){
+      value = newValue;
+    }
+
+    return value;
+  };
+
+})();
diff --git a/snippets/js2-mode/proto.yasnippet 
b/snippets/js2-mode/proto.yasnippet
new file mode 100644
index 0000000..c6fe215
--- /dev/null
+++ b/snippets/js2-mode/proto.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: proto
+# key: proto
+# --
+$1.prototype.$2 = $0
diff --git a/snippets/js2-mode/rq.yasnippet b/snippets/js2-mode/rq.yasnippet
new file mode 100644
index 0000000..864534d
--- /dev/null
+++ b/snippets/js2-mode/rq.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: rq
+# key: rq
+# --
+$1 = require("${2:$1}")$0
diff --git a/snippets/js2-mode/rt.yasnippet b/snippets/js2-mode/rt.yasnippet
new file mode 100644
index 0000000..d9a5bdf
--- /dev/null
+++ b/snippets/js2-mode/rt.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: rt
+# key: rt
+# --
+return$0;
diff --git a/snippets/js2-mode/slice.yasnippet 
b/snippets/js2-mode/slice.yasnippet
new file mode 100644
index 0000000..2dd65be
--- /dev/null
+++ b/snippets/js2-mode/slice.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: slice
+# key: slice
+# --
+Array.prototype.slice.${1:call}($0);
diff --git a/snippets/js2-mode/super.yasnippet 
b/snippets/js2-mode/super.yasnippet
new file mode 100644
index 0000000..4638026
--- /dev/null
+++ b/snippets/js2-mode/super.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: super
+# key: super
+# --
+$1.prototype.${2:constructor}.${3:call}($0);
diff --git a/snippets/js2-mode/switch.yasnippet 
b/snippets/js2-mode/switch.yasnippet
new file mode 100644
index 0000000..5e4fc3f
--- /dev/null
+++ b/snippets/js2-mode/switch.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: switch
+# key: switch
+# --
+switch($1){
+$0
+};
diff --git a/snippets/js2-mode/throw.yasnippet 
b/snippets/js2-mode/throw.yasnippet
new file mode 100644
index 0000000..dbef383
--- /dev/null
+++ b/snippets/js2-mode/throw.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: throw
+# key: throw
+# --
+throw new Error("$1");
diff --git a/snippets/js2-mode/try.yasnippet b/snippets/js2-mode/try.yasnippet
new file mode 100644
index 0000000..903378f
--- /dev/null
+++ b/snippets/js2-mode/try.yasnippet
@@ -0,0 +1,9 @@
+# -*- mode: snippet -*-
+# name: try
+# key: try
+# --
+try {
+  $1
+} catch(error) {
+  $0
+}
diff --git a/snippets/js2-mode/var.yasnippet b/snippets/js2-mode/var.yasnippet
new file mode 100644
index 0000000..77d52a5
--- /dev/null
+++ b/snippets/js2-mode/var.yasnippet
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: var
+# key: var
+# --
+var $1 = $0
diff --git a/snippets/js2-mode/wh.yasnippet b/snippets/js2-mode/wh.yasnippet
new file mode 100644
index 0000000..f733ac4
--- /dev/null
+++ b/snippets/js2-mode/wh.yasnippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: wh
+# key: wh
+# --
+while($1){
+$0
+}
diff --git a/snippets/js2-mode/while.yasnippet 
b/snippets/js2-mode/while.yasnippet
new file mode 100644
index 0000000..9eff9df
--- /dev/null
+++ b/snippets/js2-mode/while.yasnippet
@@ -0,0 +1,10 @@
+# -*- mode: snippet -*-
+# name: while
+# key: while
+# --
+
+var i = $1.length;
+
+while( i -- ){
+  $0
+}
\ No newline at end of file

commit 8772b51052d94401501cd889f6b60d58d3debc8c
Author: Guillaume Papin <address@hidden>
Date:   Mon Feb 4 10:42:09 2013 +0100

    Fix yas--version to compatible with version-to-list

diff --git a/yasnippet.el b/yasnippet.el
index 2e6301a..625204f 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -475,7 +475,7 @@ snippet itself contains a condition that returns the symbol
 
 ;;; Internal variables
 
-(defvar yas--version "0.8.0 (beta)")
+(defvar yas--version "0.8.0beta")
 
 (defvar yas--menu-table (make-hash-table)
   "A hash table of MAJOR-MODE symbols to menu keymaps.")

commit 700a68eb15cb28e71dcadf00e51658394d0b9838
Merge: 618cf50 2e11864
Author: João Távora <address@hidden>
Date:   Sat Jan 12 21:53:17 2013 -0800

    Merge pull request #355 from tkf/fix-yas--message
    
    Fix yas--message for the case message contains %


commit 2e118646f04c65501ab9887bb018a4173b789cf8
Author: Takafumi Arakaki <address@hidden>
Date:   Sat Jan 12 18:23:16 2013 +0100

    Fix yas--message for the case message contains %

diff --git a/yasnippet.el b/yasnippet.el
index 1c1d461..2e6301a 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -4391,7 +4391,7 @@ Remaining args as in `yas-expand-snippet'."
 (defun yas--message (level message &rest args)
   "When LEVEL is above `yas-verbosity-level', log MESSAGE and ARGS."
   (when (> yas-verbosity level)
-    (message (apply #'yas--format message args))))
+    (message "%s" (apply #'yas--format message args))))
 
 (defun yas--format (format-control &rest format-args)
   (apply #'format (concat "[yas] " format-control) format-args))

commit 618cf506ee2bb7c9e11eeda31090c19dc433f856
Author: João Távora <address@hidden>
Date:   Tue Dec 25 04:29:51 2012 +0000

    Doc: document structures YAS--FIELD and YAS--MIRROR

diff --git a/yasnippet.el b/yasnippet.el
index d51a7ed..1c1d461 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -2909,7 +2909,16 @@ Use this in primary and mirror transformations to tget."
   force-exit)
 
 (defstruct (yas--field (:constructor yas--make-field (number start end 
parent-field)))
-  "A field."
+  "A field.
+
+NUMBER is the field number.
+START and END are mostly buffer markers, but see \"apropos markers-to-points\".
+PARENT-FIELD is a `yas--field' this field is nested under, or nil.
+MIRRORS is a list of `yas--mirror's
+TRANSFORM is a lisp form.
+MODIFIED-P is a boolean set to true once user inputs text.
+NEXT is another `yas--field' or `yas--mirror' or `yas--exit'.
+"
   number
   start end
   parent-field
@@ -2918,8 +2927,15 @@ Use this in primary and mirror transformations to tget."
   (modified-p nil)
   next)
 
+
 (defstruct (yas--mirror (:constructor yas--make-mirror (start end transform)))
-  "A mirror."
+  "A mirror.
+
+START and END are mostly buffer markers, but see \"apropos markers-to-points\".
+TRANSFORM is a lisp form.
+PARENT-FIELD is a `yas--field' this mirror is nested under, or nil.
+NEXT is another `yas--field' or `yas--mirror' or `yas--exit'
+DEPTH is a count of how many nested mirrors can affect this mirror"
   start end
   (transform nil)
   parent-field

commit 35493b8f069dd2ed6c3ca75bac30f0ca375409e4
Author: João Távora <address@hidden>
Date:   Tue Dec 25 04:25:16 2012 +0000

    Fix: enclose this test in WITH-TEMP-BUFFER

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 0af1452..6d57d86 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -96,14 +96,14 @@
                      "brother from another bla!"))))
 
 (ert-deftest mirrors-adjacent-to-fields-with-nested-mirrors ()
-  (with-temp-buffer)
-  (yas-minor-mode 1)
-  (yas-expand-snippet "<%= f.submit \"${1:Submit}\"${2:$(and (yas-text) \", 
:disable_with => '\")}${2:$1ing...}${2:$(and (yas-text) \"'\")} %>")
-  (should (string= (yas--buffer-contents)
-                   "<%= f.submit \"Submit\", :disable_with => 'Submiting...' 
%>"))
-  (ert-simulate-command `(yas-mock-insert "Send"))
-  (should (string= (yas--buffer-contents)
-                   "<%= f.submit \"Send\", :disable_with => 'Sending...' %>")))
+  (with-temp-buffer
+    (yas-minor-mode 1)
+    (yas-expand-snippet "<%= f.submit \"${1:Submit}\"${2:$(and (yas-text) \", 
:disable_with => '\")}${2:$1ing...}${2:$(and (yas-text) \"'\")} %>")
+    (should (string= (yas--buffer-contents)
+                     "<%= f.submit \"Submit\", :disable_with => 'Submiting...' 
%>"))
+    (ert-simulate-command `(yas-mock-insert "Send"))
+    (should (string= (yas--buffer-contents)
+                     "<%= f.submit \"Send\", :disable_with => 'Sending...' 
%>"))))
 
 (ert-deftest deep-nested-mirroring-issue-351 ()
   (with-temp-buffer

commit 74e8f43f065fbb9d775aa105a1e0ffc61358e2c9
Author: João Távora <address@hidden>
Date:   Tue Dec 25 04:20:03 2012 +0000

    Closes #351: sort mirrors by nesting depth when updating

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index e8c4a11..0af1452 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -105,6 +105,13 @@
   (should (string= (yas--buffer-contents)
                    "<%= f.submit \"Send\", :disable_with => 'Sending...' %>")))
 
+(ert-deftest deep-nested-mirroring-issue-351 ()
+  (with-temp-buffer
+    (yas-minor-mode 1)
+    (yas-expand-snippet "${1:FOOOOOOO}${2:$1}${3:$2}${4:$3}")
+    (ert-simulate-command `(yas-mock-insert "abc"))
+    (should (string= (yas--buffer-contents) "abcabcabcabc"))))
+
 ;; (ert-deftest in-snippet-undo ()
 ;;   (with-temp-buffer
 ;;     (yas-minor-mode 1)
diff --git a/yasnippet.el b/yasnippet.el
index cc14fa0..d51a7ed 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -2923,7 +2923,8 @@ Use this in primary and mirror transformations to tget."
   start end
   (transform nil)
   parent-field
-  next)
+  next
+  depth)
 
 (defstruct (yas--exit (:constructor yas--make-exit (marker)))
   marker
@@ -4155,6 +4156,26 @@ When multiple expressions are found, only the last one 
counts."
               #'(lambda (r1 r2)
                   (>= (car r1) (car r2))))))
 
+(defun yas--calculate-mirror-depth (mirror &optional traversed)
+  (let* ((parent (yas--mirror-parent-field mirror))
+         (parents-mirrors (and parent
+                               (yas--field-mirrors parent))))
+    (or (yas--mirror-depth mirror)
+        (setf (yas--mirror-depth mirror)
+              (cond ((memq mirror traversed)
+                     0)
+                    ((and parent parents-mirrors)
+                     (1+ (reduce #'max
+                                 (mapcar #'(lambda (m)
+                                             (yas--calculate-mirror-depth m
+                                                                          
(cons mirror
+                                                                               
 traversed)))
+                                         parents-mirrors))))
+                    (parent
+                     1)
+                    (t
+                     0))))))
+
 (defun yas--update-mirrors (snippet)
   "Updates all the mirrors of SNIPPET."
   (save-excursion
@@ -4173,7 +4194,8 @@ When multiple expressions are found, only the last one 
counts."
                                ;; another mirror to need reupdating
                                ;;
                                #'(lambda (field-and-mirror1 field-and-mirror2)
-                                   (yas--mirror-parent-field (cdr 
field-and-mirror1)))))
+                                   (> (yas--calculate-mirror-depth (cdr 
field-and-mirror1))
+                                      (yas--calculate-mirror-depth (cdr 
field-and-mirror2))))))
       (let* ((field (car field-and-mirror))
              (mirror (cdr field-and-mirror))
              (parent-field (yas--mirror-parent-field mirror)))

commit 04970abf300ce85a5245735d14e1fb4edb98fda2
Author: Joao Tavora <address@hidden>
Date:   Mon Dec 24 16:35:03 2012 +0000

    Closes #315: don't consider keybindings when filtering snippets in 
YAS-ACTIVE-KEYS

diff --git a/yasnippet.el b/yasnippet.el
index 7c8d0aa..cc14fa0 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -2658,8 +2658,9 @@ whether (and where) to save the snippet, then quit the 
window."
 
 (defun yas-active-keys ()
   "Return all active trigger keys for current buffer and point."
-  (remove-duplicates (mapcan #'yas--table-all-keys (yas--get-snippet-tables))
-                     :test #'string=))
+  (remove-duplicates
+   (remove-if-not #'stringp (mapcan #'yas--table-all-keys 
(yas--get-snippet-tables)))
+   :test #'string=))
 
 (defun yas--template-fine-group (template)
   (car (last (or (yas--template-group template)

commit 810de9a4b066c62b0af4f8d9f452a5adde824aa0
Author: João Távora <address@hidden>
Date:   Mon Dec 24 01:45:59 2012 +0000

    Add: unit test for YAS-MINOR-MODE-MAP rebindings

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 783eb38..e8c4a11 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -462,6 +462,21 @@ TODO: be meaner"
     (should (eq (key-binding [(shift tab)]) 'yas-prev-field))
     (should (eq (key-binding [backtab]) 'yas-prev-field))))
 
+(ert-deftest test-rebindings ()
+  (unwind-protect
+      (progn
+        (define-key yas-minor-mode-map [tab] nil)
+        (define-key yas-minor-mode-map (kbd "TAB") nil)
+        (define-key yas-minor-mode-map (kbd "SPC") 'yas-expand)
+        (with-temp-buffer
+          (yas-minor-mode 1)
+          (should (not (eq (key-binding (yas--read-keybinding "TAB")) 
'yas-expand)))
+          (should (eq (key-binding (yas--read-keybinding "SPC")) 'yas-expand))
+          (yas-reload-all)
+          (should (not (eq (key-binding (yas--read-keybinding "TAB")) 
'yas-expand)))
+          (should (eq (key-binding (yas--read-keybinding "SPC")) 
'yas-expand))))
+    (setcdr yas-minor-mode-map (cdr (yas--init-minor-keymap)))))
+
 (ert-deftest test-yas-in-org ()
   (with-temp-buffer
     (org-mode)

commit e5c41c78d27d00dde14a31a3435d40d12cc1eff5
Author: João Távora <address@hidden>
Date:   Mon Dec 24 01:35:05 2012 +0000

    Fix: tests also use YAS--WITH-TEMPORARY-REDEFINITIONS to make stubs

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index cdb781a..783eb38 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -260,11 +260,12 @@ TODO: correct this bug!"
 (defmacro yas-with-overriden-buffer-list (&rest body)
   (let ((saved-sym (gensym)))
     `(let ((,saved-sym (symbol-function 'buffer-list)))
-       (cl-flet ((buffer-list ()
-                              (remove-if #'(lambda (buf)
-                                             (with-current-buffer buf
-                                               (eq major-mode 
'lisp-interaction-mode)))
-                                         (funcall ,saved-sym))))
+       (yas--with-temporary-redefinitions
+           ((buffer-list ()
+                         (remove-if #'(lambda (buf)
+                                        (with-current-buffer buf
+                                          (eq major-mode 
'lisp-interaction-mode)))
+                                    (funcall ,saved-sym))))
          ,@body))))
 
 (defmacro yas-with-some-interesting-snippet-dirs (&rest body)
@@ -474,9 +475,10 @@ TODO: be meaner"
 (defun yas/ert ()
   (interactive)
   (with-temp-buffer
-    (cl-flet ((message (&rest args)        ;
-                       (declare (ignore args))
-                       nil))
+    (yas--with-temporary-redefinitions
+        ((message (&rest args)        ;
+                  (declare (ignore args))
+                  nil))
       (ert t (buffer-name (current-buffer)))
       (princ (buffer-string)))))
 

commit 1ef0091de1aa5cce64bc15a6ff11167ed5fa89dd
Author: João Távora <address@hidden>
Date:   Sun Dec 23 20:43:23 2012 +0000

    Fix: YAS-RELOAD-ALL preserves user bindings on YAS-MINOR-MODE-MAP cleanup
    
    - Don't create a new keymap on every reload

diff --git a/yasnippet.el b/yasnippet.el
index 175ba13..7c8d0aa 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1862,21 +1862,25 @@ loading."
             ;; `yas--editing-template' to nil, make it guess it next time 
around
             (mapc #'(lambda (buffer) (setq yas--editing-template nil)) 
(buffer-list))))
 
-      ;; Empty all snippet tables, parenting info and all menu tables
+      ;; Empty all snippet tables and parenting info
       ;;
       (setq yas--tables (make-hash-table))
       (setq yas--parents (make-hash-table))
+
+      ;; Before killing `yas--menu-table' use its keys to cleanup the
+      ;; mode menu parts of `yas--minor-mode-menu' (thus also cleaning
+      ;; up `yas-minor-mode-map', which points to it)
+      ;;
+      (maphash #'(lambda (menu-symbol keymap)
+                   (define-key yas--minor-mode-menu (vector menu-symbol) nil))
+               yas--menu-table)
+      ;; Now empty `yas--menu-table' as well
       (setq yas--menu-table (make-hash-table))
 
       ;; Cancel all pending 'yas--scheduled-jit-loads'
       ;;
       (setq yas--scheduled-jit-loads (make-hash-table))
 
-      ;; Init the `yas-minor-mode-map', taking care not to break the
-      ;; menu....
-      ;;
-      (setcdr yas-minor-mode-map (cdr (yas--init-minor-keymap)))
-
       ;; Reload the directories listed in `yas-snippet-dirs' or prompt
       ;; the user to select one.
       ;;

commit 9b31880ed19486c3672f467ce6dfd58faf612e39
Author: João Távora <address@hidden>
Date:   Sat Dec 22 18:18:04 2012 +0000

    Fix: double check if mac trigger symbol is available

diff --git a/yasnippet.el b/yasnippet.el
index 6f3fd92..175ba13 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -311,8 +311,9 @@ Any other non-nil value, every submenu is listed."
                  (const :tag "No menu" nil))
   :group 'yasnippet)
 
-(defcustom yas-trigger-symbol (if (eq window-system 'mac)
-                                  (char-to-string ?\x21E5) ;; little ->| sign
+(defcustom yas-trigger-symbol (or (and (eq window-system 'mac)
+                                       (ignore-errors
+                                         (char-to-string ?\x21E5))) ;; little 
->| sign
                                   " =>")
   "The text that will be used in menu to represent the trigger."
   :type 'string

commit 1db685c480f2fda983f3a4f855b3985d6b61bccd
Author: João Távora <address@hidden>
Date:   Sat Dec 22 18:04:54 2012 +0000

    Fix: YAS--CALLED-INTERACTIVELY-P should reverse its condition check

diff --git a/yasnippet.el b/yasnippet.el
index 613bddb..6f3fd92 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1320,7 +1320,7 @@ them all in `yas--menu-table'"
 
 Optional KIND is as documented at `called-interactively-p'
 in GNU Emacs 24.1 or higher."
-  (if (string< "24.1" emacs-version)
+  (if (string< emacs-version "24.1")
       '(called-interactively-p)
     `(called-interactively-p ,kind)))
 

commit a74481f491ce03ec90a8c4baed154cf0e9ce2c5d
Merge: 1bc497e 100aa7c
Author: João Távora <address@hidden>
Date:   Mon Dec 17 03:59:18 2012 -0800

    Merge pull request #343 from dgutov/zip
    
    Remove group-name prefix from ruby-mode/collections/zip


commit 1bc497ecbe5223a5de4daa36865fa69567de5d1a
Author: João Távora <address@hidden>
Date:   Mon Dec 17 00:05:29 2012 +0000

    Closes #335: YAS-DONT-ACTIVATE is only buffer-local in pre-24 emacsen

diff --git a/yasnippet.el b/yasnippet.el
index ee99e50..613bddb 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -743,17 +743,26 @@ Key bindings:
          (remove-hook 'emulation-mode-map-alists 'yas--direct-keymaps))))
 
 (defvar yas-dont-activate '(minibufferp)
-  "If non-nil don't let `yas-minor-mode-on' activate for this buffer.
+  "If non-nil don't let `yas-global-mode' affect some buffers.
 
-If a function, then its result is used.
+If a function of zero arguments, then its result is used.
 
 If a list of functions, then all functions must return nil to
 activate yas for this buffer.
 
-`yas-minor-mode-on' is usually called by `yas-global-mode' so
-this effectively lets you define exceptions to the \"global\"
-behaviour. Can also be a function of zero arguments.")
-(make-variable-buffer-local 'yas-dont-activate)
+In Emacsen <= 23, this variable is buffer-local. Because
+`yas-minor-mode-on' is called by `yas-global-mode' after
+executing the buffer's major mode hook, setting this variable
+there is an effective way to define exceptions to the \"global\"
+activation behaviour.
+
+In Emacsen > 23, only the global value is used. To define
+per-mode exceptions to the \"global\" activation behaviour, call
+`yas-minor-mode' with a negative argument directily in the major
+mode's hook.")
+(unless (> emacs-major-version 23)
+  (make-variable-buffer-local 'yas-dont-activate))
+
 
 (defun yas-minor-mode-on ()
   "Turn on YASnippet minor mode.

commit 327fa4b86e927c1ed6def233c113d561eab8ac0d
Merge: d9f966a f6d6d4c
Author: João Távora <address@hidden>
Date:   Sun Dec 16 15:53:04 2012 -0800

    Merge pull request #344 from dgutov/no-aget
    
    Fix: remove the use of AGET that has creeped in


commit d9f966a220393339fd99b26b2bed8c7f6d79d226
Author: João Távora <address@hidden>
Date:   Sun Dec 16 14:36:14 2012 +0000

    Closes #347: can't expect THIS-COMMAND to have valid value in 
YAS-BUFFER-LOCAL-CONDITION

diff --git a/yasnippet.el b/yasnippet.el
index 42227f1..c33c3c6 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -415,7 +415,8 @@ Attention: These hooks are not run when exiting 
nested/stacked snippet expansion
 (defvar yas-buffer-local-condition
   '(if (and (or (fourth (syntax-ppss))
                 (fifth (syntax-ppss)))
-            (eq (symbol-function this-command) 'yas-expand-from-trigger-key))
+           this-command
+            (eq this-command 'yas-expand-from-trigger-key))
        '(require-snippet-condition . force-in-comment)
      t)
   "Snippet expanding condition.

commit f6d6d4ca56911e5229ca8aa649ed23aaaf570530
Author: Dmitry Gutov <address@hidden>
Date:   Sun Dec 9 03:08:57 2012 +0400

    Remove the use of `aget` that has creeped in
    
    See also c38c3aa, 38db5aa9fbf0f60dce63b83cab8f028bfcd152bd and
    9de1c5f4fb6f281cfa4af869d393db76616cb42e#commitcomment-2265088

diff --git a/yasnippet.el b/yasnippet.el
index 42227f1..2314b56 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -136,7 +136,6 @@
 (require 'cl)
 (require 'easymenu)
 (require 'help-mode)
-(require 'assoc)
 
 (eval-when-compile
   (defvar yas--editing-template)
@@ -2302,7 +2301,7 @@ vector of keys. FIXME not thoroughly tested"
         (while (and (< j (length keys))
                     translated
                     (keymapp translated))
-          (setq translated (aget (remove 'keymap translated) (aref keys j))
+          (setq translated (cdr (assoc (aref keys j) (remove 'keymap 
translated)))
                 j (1+ j)))
         (setq retval (vconcat retval (cond ((symbolp translated)
                                             `[,translated])

commit 100aa7c0af600e95223ddfb0d506e85a945475b5
Author: Dmitry Gutov <address@hidden>
Date:   Sun Dec 9 02:15:43 2012 +0400

    Remove group-name prefix from ruby-mode/collections/zip
    
    Bug introduced in f48317e7c5ecdbb7680d0ea2c595cfda0342c3bb and not-fixed in
    3aea27042bc2a0f05b2755e0c5c4edc43b426aed.

diff --git a/snippets/ruby-mode/collections/zip 
b/snippets/ruby-mode/collections/zip
index 9db20ed..8081d79 100644
--- a/snippets/ruby-mode/collections/zip
+++ b/snippets/ruby-mode/collections/zip
@@ -1,4 +1,4 @@
 #name : zip(...) { |...| ... }
-# key: collectionszip
+# key: zip
 # --
 zip(${enums}) { |${row}| $0 }
\ No newline at end of file

commit 4f99f9dc205db03754d1d4664704e6838e545b2e
Author: João Távora <address@hidden>
Date:   Tue Nov 27 00:25:51 2012 +0000

    Closes #339

diff --git a/yasnippet.el b/yasnippet.el
index d5b6973..42227f1 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1311,7 +1311,7 @@ them all in `yas--menu-table'"
 
 Optional KIND is as documented at `called-interactively-p'
 in GNU Emacs 24.1 or higher."
-  (if (eq 0 (cdr (subr-arity (symbol-function 'called-interactively-p))))
+  (if (string< "24.1" emacs-version)
       '(called-interactively-p)
     `(called-interactively-p ,kind)))
 

commit cfefaca284327babde6cf483c8bb2127e8c0e5fd
Author: João Távora <address@hidden>
Date:   Sat Nov 17 16:38:00 2012 +0000

    Fix: cleanup after #333 fix, use 'cl-flet'

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 194c0fd..cdb781a 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -222,7 +222,7 @@
                          \"ok\"
                          \"fail\")`"))
       (yas-expand-snippet snippet))
-      (should (string= (yas--buffer-contents) "ok"))))
+    (should (string= (yas--buffer-contents) "ok"))))
 
 (ert-deftest string-match-with-subregexp-in-mirror-transformations ()
   (with-temp-buffer
@@ -260,11 +260,11 @@ TODO: correct this bug!"
 (defmacro yas-with-overriden-buffer-list (&rest body)
   (let ((saved-sym (gensym)))
     `(let ((,saved-sym (symbol-function 'buffer-list)))
-       (flet ((buffer-list ()
-                           (remove-if #'(lambda (buf)
-                                          (with-current-buffer buf
-                                            (eq major-mode 
'lisp-interaction-mode)))
-                                      (funcall ,saved-sym))))
+       (cl-flet ((buffer-list ()
+                              (remove-if #'(lambda (buf)
+                                             (with-current-buffer buf
+                                               (eq major-mode 
'lisp-interaction-mode)))
+                                         (funcall ,saved-sym))))
          ,@body))))
 
 (defmacro yas-with-some-interesting-snippet-dirs (&rest body)
@@ -474,9 +474,9 @@ TODO: be meaner"
 (defun yas/ert ()
   (interactive)
   (with-temp-buffer
-    (flet ((message (&rest args)
-                    (declare (ignore args))
-                    nil))
+    (cl-flet ((message (&rest args)        ;
+                       (declare (ignore args))
+                       nil))
       (ert t (buffer-name (current-buffer)))
       (princ (buffer-string)))))
 

commit 7e4876169bd82477f665a75df6550b95ef26a1f1
Author: Joao Tavora <address@hidden>
Date:   Fri Nov 16 15:15:56 2012 +0000

    Fix: also use $EMACS env var in compilation

diff --git a/Rakefile b/Rakefile
index c68929c..d133218 100644
--- a/Rakefile
+++ b/Rakefile
@@ -2,6 +2,8 @@
 
 require 'fileutils'
 
+$EMACS=ENV["EMACS"] || "emacs"
+
 def find_version
   File.read("yasnippet.el", :encoding => "UTF-8") =~ /;; Package-version: 
*([0-9.]+?) *$/
   $version = $1
@@ -11,7 +13,6 @@ FileUtils.mkdir_p('pkg')
 
 desc "run tests in batch mode"
 task :tests do
-  $EMACS=ENV["EMACS"] || "emacs"
   sh "#{$EMACS} -Q -L . -l yasnippet-tests.el -nw --batch -e yas/ert"
 end
 
@@ -87,7 +88,7 @@ end
 desc "Compile yasnippet.el into yasnippet.elc"
 
 rule '.elc' => '.el' do |t|
-  sh "emacs --batch -L . --eval \"(byte-compile-file \\\"#{t.source}\\\")\""
+  sh "#{$EMACS} --batch -L . --eval \"(byte-compile-file 
\\\"#{t.source}\\\")\""
 end
 task :compile => FileList["yasnippet.el", "dropdown-list.el"].ext('elc')
 

commit 0778a1b61b7a74473b9a34cc8d1fc5ae8561af2f
Author: Joao Tavora <address@hidden>
Date:   Fri Nov 16 15:15:24 2012 +0000

    Fix: Closes #330

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 388b7ea..194c0fd 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -297,9 +297,10 @@ TODO: correct this bug!"
   (yas-with-some-interesting-snippet-dirs
    (yas-reload-all)
    (yas-recompile-all)
-   (flet ((yas--load-directory-2
-           (&rest dummies)
-           (ert-fail "yas--load-directory-2 shouldn't be called when snippets 
have been compiled")))
+   (yas--with-temporary-redefinitions ((yas--load-directory-2
+                                        (&rest dummies)
+                                        (declare (ignore dummies))
+                                        (ert-fail "yas--load-directory-2 
shouldn't be called when snippets have been compiled")))
      (yas-reload-all)
      (yas--basic-jit-loading-1))))
 
diff --git a/yasnippet.el b/yasnippet.el
index bc238ae..d5b6973 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -147,13 +147,6 @@
   (defvar yas-selected-text)
   (defvar yas-verbosity))
 
-;; Future-proof against obsoleting flet, see github #324
-;;
-(eval-and-compile
-  (unless (fboundp 'cl-flet)
-    (defalias 'cl-flet 'flet)
-    (put 'cl-flet 'lisp-indent-function 1)
-    (put 'cl-flet 'edebug-form-spec '((&rest (defun*)) cl-declarations body))))
 
 
 ;;; User customizable variables
@@ -1312,6 +1305,7 @@ them all in `yas--menu-table'"
                     :visible (yas--show-menu-p ',mode)))
     menu-keymap))
 
+
 (defmacro yas--called-interactively-p (&optional kind)
   "A backward-compatible version of `called-interactively-p'.
 
@@ -1321,6 +1315,43 @@ in GNU Emacs 24.1 or higher."
       '(called-interactively-p)
     `(called-interactively-p ,kind)))
 
+
+(defun yas--call-with-temporary-redefinitions (function
+                                               &rest 
function-names-and-overriding-functions)
+  (let* ((overrides (remove-if-not #'(lambda (fdef)
+                                       (fboundp (first fdef)))
+                                   function-names-and-overriding-functions))
+         (definition-names (mapcar #'first overrides))
+         (overriding-functions (mapcar #'second overrides))
+         (saved-functions (mapcar #'symbol-function definition-names)))
+    ;; saving all definitions before overriding anything ensures FDEFINITION
+    ;; errors don't cause accidental permanent redefinitions.
+    ;;
+    (labels ((set-fdefinitions (names functions)
+                               (loop for name in names
+                                     for fn in functions
+                                     do (fset name fn))))
+      (set-fdefinitions definition-names overriding-functions)
+      (unwind-protect (funcall function)
+       (set-fdefinitions definition-names saved-functions)))))
+
+
+(defmacro yas--with-temporary-redefinitions (fdefinitions &rest body)
+  ;; "Temporarily (but globally) redefine each function in FDEFINITIONS.
+  ;; E.g.: (yas--with-temporary-redefinitions ((foo (x) ...)
+  ;;                                           (bar (x) ...))
+  ;;         ;; code that eventually calls foo, bar of (setf foo)
+  ;;         ...)"
+  `(yas--call-with-temporary-redefinitions
+    (lambda () ,@body)
+    ,@(mapcar #'(lambda (thingy)
+                  `(list ',(first thingy)
+                         (lambda ,@(rest thingy))))
+              fdefinitions)))
+
+(put 'yas--with-temporary-redefinitions 'lisp-indent-function 1)
+(put 'yas--with-temporary-redefinitions 'edebug-form-spec '((&rest (defun*)) 
cl-declarations body))
+
 
 ;;; Template-related and snippet loading functions
 
@@ -1882,49 +1913,50 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\""
 This works by stubbing a few functions, then calling
 `yas-load-directory'."
   (interactive "DTop level snippet directory?")
-  (cl-flet ((yas--load-yas-setup-file
-          (file)
-          (let ((elfile (concat file ".el")))
-            (when (file-exists-p elfile)
-              (insert ";;; .yas-setup.el support file if any:\n;;;\n")
-              (insert-file-contents elfile)
-              (goto-char (point-max))
-              )))
-         (yas-define-snippets
-          (mode snippets)
-          (insert ";;; Snippet definitions:\n;;;\n")
-          (let ((literal-snippets (list))
-                (print-length nil))
-            (dolist (snippet snippets)
-              (let ((key                    (first   snippet))
-                    (template-content       (second  snippet))
-                    (name                   (third   snippet))
-                    (condition              (fourth  snippet))
-                    (group                  (fifth   snippet))
-                    (expand-env             (sixth   snippet))
-                    (file                   nil) ;; (seventh snippet)) ;; omit 
on purpose
-                    (binding                (eighth  snippet))
-                    (uuid                    (ninth   snippet)))
-                (push `(,key
-                        ,template-content
-                        ,name
-                        ,condition
-                        ,group
-                        ,expand-env
-                        ,file
-                        ,binding
-                        ,uuid)
-                      literal-snippets)))
-            (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
-            (insert "\n\n")))
-         (yas--load-directory-1
-          (dir mode parents &rest ignore)
-          (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
-            (with-temp-file output-file
-              (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
-              (yas--load-directory-2 dir mode)
-              (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
-    (yas-load-directory top-level-dir nil)))
+  (yas--with-temporary-redefinitions
+   ((yas--load-yas-setup-file
+     (file)
+     (let ((elfile (concat file ".el")))
+       (when (file-exists-p elfile)
+         (insert ";;; .yas-setup.el support file if any:\n;;;\n")
+         (insert-file-contents elfile)
+         (goto-char (point-max))
+         )))
+    (yas-define-snippets
+     (mode snippets)
+     (insert ";;; Snippet definitions:\n;;;\n")
+     (let ((literal-snippets (list))
+           (print-length nil))
+       (dolist (snippet snippets)
+         (let ((key                    (first   snippet))
+               (template-content       (second  snippet))
+               (name                   (third   snippet))
+               (condition              (fourth  snippet))
+               (group                  (fifth   snippet))
+               (expand-env             (sixth   snippet))
+               (file                   nil) ;; (seventh snippet)) ;; omit on 
purpose
+               (binding                (eighth  snippet))
+               (uuid                    (ninth   snippet)))
+           (push `(,key
+                   ,template-content
+                   ,name
+                   ,condition
+                   ,group
+                   ,expand-env
+                   ,file
+                   ,binding
+                   ,uuid)
+                 literal-snippets)))
+       (insert (pp-to-string `(yas-define-snippets ',mode ',literal-snippets)))
+       (insert "\n\n")))
+    (yas--load-directory-1
+     (dir mode parents &rest ignore)
+     (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
+       (with-temp-file output-file
+         (insert (format ";;; Compiled snippets and support files for `%s'\n" 
mode))
+         (yas--load-directory-2 dir mode)
+         (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
+   (yas-load-directory top-level-dir nil)))
 
 (defun yas-recompile-all ()
   "Compile every dir in `yas-snippet-dirs'."
@@ -3662,18 +3694,18 @@ Returns the newly created snippet."
 
 This is according to their relative positions in the buffer, and
 has to be called before the $-constructs are deleted."
-  (cl-flet ((yas--fom-set-next-fom (fom nextfom)
+  (labels ((yas--fom-set-next-fom (fom nextfom)
                                   (cond ((yas--field-p fom)
                                          (setf (yas--field-next fom) nextfom))
                                         ((yas--mirror-p fom)
                                          (setf (yas--mirror-next fom) nextfom))
                                         (t
                                          (setf (yas--exit-next fom) nextfom))))
-            (yas--compare-fom-begs (fom1 fom2)
+           (yas--compare-fom-begs (fom1 fom2)
                                   (if (= (yas--fom-start fom2) (yas--fom-start 
fom1))
                                       (yas--mirror-p fom2)
                                     (>= (yas--fom-start fom2) (yas--fom-start 
fom1))))
-            (yas--link-foms (fom1 fom2)
+           (yas--link-foms (fom1 fom2)
                            (yas--fom-set-next-fom fom1 fom2)))
     ;; make some yas--field, yas--mirror and yas--exit soup
     (let ((soup))

commit b29e4b9259c2b1f483f5fa942756e30da041d078
Author: João Távora <address@hidden>
Date:   Fri Nov 9 14:07:32 2012 +0000

    Doc: update "reporting bugs" section in README

diff --git a/README.mdown b/README.mdown
index 075951e..3289b1e 100644
--- a/README.mdown
+++ b/README.mdown
@@ -133,18 +133,22 @@ and support.  If you find a bug, please report it on
 
 ## Important note regarding bug reporting
 If you think have found a bug, please report it clearly.  Yasnippet
-does have (lots of) bugs and your reporting is very valuable. But I
-have little time to analyse bugs and the following helps a lot.
+does have (lots of) bugs and your reports are very valuable. Here's 
+a  [great example](https://github.com/capitaomorte/yasnippet/issues/318) 
+of a bug report. It has everything needed for a sucessfull analysis and 
+speedy resolution:
 
-So, *before* reporting try to reproduce the bug **without** your usual
+*Before* reporting try to reproduce the bug **without** your usual
 `.emacs` (or whatever startup file you use). Do so either by starting
 emacs from the command line with the `-Q` switch, or by temporarily
 moving away your `.emacs` and creating a new smaller one just for
-reproducing the bug.
+reproducing the bug. Paste that file in your bug report. Paste any sequence 
+of relevant shell commands before you launch Emacs.
 
-Then paste that file, and describe steps taken to reproduce, from an
-end-user perspective. Try to be as unambiguous as possible. Also,
-don't forget to state the Emacs version (use `M-x emacs-version`) and
+*Then*, describe steps taken to reproduce from an
+end-user perspective. Try to be as unambiguous as possible. 
+
+Also, don't forget to state the Emacs version (use `M-x emacs-version`) and
 the yasnippet version you are using (if using the latest from github,
 do `git log -1` in the dir).
 
@@ -153,9 +157,6 @@ message string you got. I'm not saying your analysis might 
not be
 useful but following the instructions above immediately gives me a
 clear picture of what is happening.
 
-There's an example of a great bug report from
-[issue #189](https://github.com/capitaomorte/yasnippet/issues/189)
-
 There is also a [YASnippet google group][forum]. I will keep the group
 open for reference and for discussion among users, unfortunately I
 can't guarantee a timely response, so maybe creating a github issue

commit ed4dbdf37848ab715f5daad1888c1103d9d8ee9a
Author: João Távora <address@hidden>
Date:   Thu Nov 8 22:59:45 2012 +0000

    Doc: added notice about bug reporting

diff --git a/README.mdown b/README.mdown
index dc10bfb..075951e 100644
--- a/README.mdown
+++ b/README.mdown
@@ -131,8 +131,37 @@ and support.  If you find a bug, please report it on
 [the GitHub issue tracker][issues].  (please **do not** submit new issues to 
the old
 [googlecode tracker][googlecode tracker])
 
-If you run into problems using YASnippet, or have snippets to contribute, post
-to the [YASnippet google group][forum]. Thank you very much for using 
YASnippet!
+## Important note regarding bug reporting
+If you think have found a bug, please report it clearly.  Yasnippet
+does have (lots of) bugs and your reporting is very valuable. But I
+have little time to analyse bugs and the following helps a lot.
+
+So, *before* reporting try to reproduce the bug **without** your usual
+`.emacs` (or whatever startup file you use). Do so either by starting
+emacs from the command line with the `-Q` switch, or by temporarily
+moving away your `.emacs` and creating a new smaller one just for
+reproducing the bug.
+
+Then paste that file, and describe steps taken to reproduce, from an
+end-user perspective. Try to be as unambiguous as possible. Also,
+don't forget to state the Emacs version (use `M-x emacs-version`) and
+the yasnippet version you are using (if using the latest from github,
+do `git log -1` in the dir).
+
+Any more info is welcome, but don't just paste a backtrace or an error
+message string you got. I'm not saying your analysis might not be
+useful but following the instructions above immediately gives me a
+clear picture of what is happening.
+
+There's an example of a great bug report from
+[issue #189](https://github.com/capitaomorte/yasnippet/issues/189)
+
+There is also a [YASnippet google group][forum]. I will keep the group
+open for reference and for discussion among users, unfortunately I
+can't guarantee a timely response, so maybe creating a github issue
+clearly marking your intent (user support/bug/feature request).
+
+Finally, thank you very much for using YASnippet!
 
 [docs]: http://capitaomorte.github.com/yasnippet/
 [issues]: https://github.com/capitaomorte/yasnippet/issues

commit 0ab9fb281e24bc7a35692d720086746dcc27096e
Author: João Távora <address@hidden>
Date:   Thu Nov 8 22:22:41 2012 +0000

    Minor: make 'yas--define-snippets-1' an internal defun

diff --git a/yasnippet.el b/yasnippet.el
index 32c150c..bc238ae 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1618,7 +1618,7 @@ Optional PROMPT sets the prompt to use."
 ;; correct tables.
 ;;
 
-(defun yas-define-snippets-1 (snippet snippet-table)
+(defun yas--define-snippets-1 (snippet snippet-table)
   "Helper for `yas-define-snippets'."
   ;; X) Calculate some more defaults on the values returned by
   ;; `yas--parse-template'.
@@ -1688,7 +1688,7 @@ the current buffers contents."
   (let ((snippet-table (yas--table-get-create mode))
         (template nil))
     (dolist (snippet snippets)
-      (setq template (yas-define-snippets-1 snippet
+      (setq template (yas--define-snippets-1 snippet
                                             snippet-table)))
     template))
 
@@ -2530,7 +2530,7 @@ whether (and where) to save the snippet, then quit the 
window."
    ;;  template which is already loaded and neatly positioned,...
    ;;
    (yas--editing-template
-    (yas-define-snippets-1 (yas--parse-template (yas--template-file 
yas--editing-template))
+    (yas--define-snippets-1 (yas--parse-template (yas--template-file 
yas--editing-template))
                            (yas--template-table yas--editing-template)))
    ;; Try to use `yas--guessed-modes'. If we don't have that use the
    ;; value from `yas--compute-major-mode-and-parents'
@@ -2540,7 +2540,7 @@ whether (and where) to save the snippet, then quit the 
window."
       (set (make-local-variable 'yas--guessed-modes) (or 
(yas--compute-major-mode-and-parents buffer-file-name))))
     (let* ((table (yas--table-get-create table)))
       (set (make-local-variable 'yas--editing-template)
-           (yas-define-snippets-1 (yas--parse-template buffer-file-name)
+           (yas--define-snippets-1 (yas--parse-template buffer-file-name)
                                   table)))))
 
   (when (and interactive

commit d5865b1092fd24099f4afedf0e5016fe9da86b5f
Merge: 5520088 b7fe4c1
Author: João Távora <address@hidden>
Date:   Thu Nov 8 22:21:19 2012 +0000

    Merge remote-tracking branch 'rolandwalker/byte-compiler-3'
    
    Fix: reorder defuns to quieten byte-compiler
    
    Conflicts:
        yasnippet.el

diff --cc yasnippet.el
index a7ddc8c,9491603..32c150c
--- a/yasnippet.el
+++ b/yasnippet.el
@@@ -1612,12 -1610,96 +1612,99 @@@ Optional PROMPT sets the prompt to use.
  (defun yas-no-prompt (prompt choices &optional display-fn)
    (first choices))
  
 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 -;; Defining snippets
 +
++;;; Defining snippets
++;; This consists of creating and registering `yas--template' objects in the
++;; correct tables.
+ ;;
 -(defun yas--define-parents (mode parents)
 -  "Add PARENTS to the list of MODE's parents."
 -  (puthash mode (remove-duplicates
 -                 (append parents
 -                         (gethash mode yas--parents)))
 -           yas--parents))
+ 
+ (defun yas-define-snippets-1 (snippet snippet-table)
+   "Helper for `yas-define-snippets'."
+   ;; X) Calculate some more defaults on the values returned by
+   ;; `yas--parse-template'.
+   ;;
+   (let* ((file (seventh snippet))
+          (key (car snippet))
+          (name (or (third snippet)
+                    (and file
+                         (file-name-directory file))))
+          (condition (fourth snippet))
+          (group (fifth snippet))
+          (keybinding (yas--read-keybinding (eighth snippet)))
+          (uuid (or (ninth snippet)
+                   name))
+          (template (or (gethash uuid (yas--table-uuidhash snippet-table))
+                        (yas--make-blank-template))))
+     ;; X) populate the template object
+     ;;
+     (yas--populate-template template
+                            :table       snippet-table
+                            :key         key
+                            :content     (second snippet)
+                            :name        (or name key)
+                            :group       group
+                            :condition   condition
+                            :expand-env  (sixth snippet)
+                            :file        (seventh snippet)
+                            :keybinding  keybinding
+                            :uuid         uuid)
+     ;; X) Update this template in the appropriate table. This step
+     ;;    also will take care of adding the key indicators in the
+     ;;    templates menu entry, if any
+     ;;
+     (yas--update-template snippet-table template)
+     ;; X) Return the template
+     ;;
+     ;;
+     template))
+ 
+ (defun yas-define-snippets (mode snippets)
+   "Define SNIPPETS for MODE.
+ 
+ SNIPPETS is a list of snippet definitions, each taking the
+ following form
+ 
+  (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
+ 
+ Within these, only KEY and TEMPLATE are actually mandatory.
+ 
+ TEMPLATE might be a lisp form or a string, depending on whether
+ this is a snippet or a snippet-command.
+ 
+ CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
+ been `yas--read-lisp'-ed and will eventually be
+ `yas--eval-lisp'-ed.
+ 
+ The remaining elements are strings.
+ 
+ FILE is probably of very little use if you're programatically
+ defining snippets.
+ 
+ UUID is the snippets \"unique-id\". Loading a second snippet file
+ with the same uuid replaced the previous snippet.
+ 
+ You can use `yas--parse-template' to return such lists based on
+ the current buffers contents."
+   (let ((snippet-table (yas--table-get-create mode))
+         (template nil))
+     (dolist (snippet snippets)
+       (setq template (yas-define-snippets-1 snippet
+                                             snippet-table)))
+     template))
+ 
 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 -;; Loading snippets from files
 -;;
++
 +;;; Loading snippets from files
 +
  (defun yas--load-yas-setup-file (file)
    (load file 'noerror))
  
++(defun yas--define-parents (mode parents)
++  "Add PARENTS to the list of MODE's parents."
++  (puthash mode (remove-duplicates
++                 (append parents
++                         (gethash mode yas--parents)))
++           yas--parents))
++
  (defun yas-load-directory (top-level-dir &optional use-jit)
    "Load snippets in directory hierarchy TOP-LEVEL-DIR.
  

commit 552008872b26dc6e44f93a1673434ef7a6bb9cf5
Author: João Távora <address@hidden>
Date:   Thu Nov 8 22:15:42 2012 +0000

    Minor: cleanup internal doc headings slightly

diff --git a/yasnippet.el b/yasnippet.el
index 301b4de..a7ddc8c 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -375,6 +375,8 @@ the trigger key itself."
   :group 'yasnippet)
 
 
+;;; User-visible variables
+
 (defvar yas-keymap  (let ((map (make-sparse-keymap)))
                       (define-key map [(tab)]       
'yas-next-field-or-maybe-expand)
                       (define-key map (kbd "TAB")   
'yas-next-field-or-maybe-expand)
@@ -784,9 +786,9 @@ Honour `yas-dont-activate', which see."
 
 (add-hook 'yas-global-mode-hook 'yas--global-mode-reload-with-jit-maybe)
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Major mode stuff
-;;
+
+;;; Major mode stuff
+
 (defvar yas--font-lock-keywords
   (append '(("^#.*$" . font-lock-comment-face))
           lisp-font-lock-keywords
@@ -1319,7 +1321,7 @@ in GNU Emacs 24.1 or higher."
       '(called-interactively-p)
     `(called-interactively-p ,kind)))
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 ;;; Template-related and snippet loading functions
 
 (defun yas--parse-template (&optional file)
@@ -1450,9 +1452,9 @@ Here's a list of currently recognized directives:
                               (cdr where)
                               (yas--template-expand-env 
yas--current-template)))))))
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Popping up for keys and templates
-;;
+
+;;; Popping up for keys and templates
+
 (defvar yas--x-pretty-prompt-templates nil
   "If non-nil, attempt to prompt for templates like TextMate.")
 
@@ -1610,9 +1612,9 @@ Optional PROMPT sets the prompt to use."
 (defun yas-no-prompt (prompt choices &optional display-fn)
   (first choices))
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Loading snippets from files
-;;
+
+;;; Loading snippets from files
+
 (defun yas--load-yas-setup-file (file)
   (load file 'noerror))
 
@@ -1780,7 +1782,7 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\""
                                     string
                                     t)
           "\""))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 ;;; Snippet compilation function
 
 (defun yas--initialize ()
@@ -1856,9 +1858,8 @@ This works by stubbing a few functions, then calling
            yas--scheduled-jit-loads))
 
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 ;;; Some user level functions
-;;;
 
 (defun yas-about ()
   (interactive)
@@ -3414,7 +3415,7 @@ The error should be ignored in `debug-ignored-errors'"
 (add-to-list 'debug-ignored-errors "^Exit the snippet first!$")
 
 
-;; Snippet expansion and "stacked" expansion:
+;;; Snippet expansion and "stacked" expansion:
 ;;
 ;; Stacked expansion is when you try to expand a snippet when already
 ;; inside a snippet expansion.
@@ -4180,7 +4181,7 @@ When multiple expressions are found, only the last one 
counts."
 
 
 ;;; Post-command hook:
-
+;;
 (defun yas--post-command-handler ()
   "Handles various yasnippet conditions after each command."
   (cond (yas--protection-violation
@@ -4396,6 +4397,7 @@ handle the end-of-buffer error fired in it by calling
                  k 'self-insert-command))))
 
 ;;; Backward compatibility to yasnippet <= 0.7
+
 (defvar yas--exported-syms '(;; `defcustom's
                              ;;
                              yas-snippet-dirs

commit b7fe4c1f8d469f393422480d48309a04056dc191
Author: Roland Walker <address@hidden>
Date:   Thu Nov 8 14:33:21 2012 -0500

    reorder defuns to quieten byte-compiler
    Two warnings avoided:
    function `yas-define-snippets' defined multiple times in this file
    the function `yas-define-snippets' is not known to be defined

diff --git a/yasnippet.el b/yasnippet.el
index 301b4de..9491603 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1611,6 +1611,90 @@ Optional PROMPT sets the prompt to use."
   (first choices))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Defining snippets
+;;
+(defun yas--define-parents (mode parents)
+  "Add PARENTS to the list of MODE's parents."
+  (puthash mode (remove-duplicates
+                 (append parents
+                         (gethash mode yas--parents)))
+           yas--parents))
+
+(defun yas-define-snippets-1 (snippet snippet-table)
+  "Helper for `yas-define-snippets'."
+  ;; X) Calculate some more defaults on the values returned by
+  ;; `yas--parse-template'.
+  ;;
+  (let* ((file (seventh snippet))
+         (key (car snippet))
+         (name (or (third snippet)
+                   (and file
+                        (file-name-directory file))))
+         (condition (fourth snippet))
+         (group (fifth snippet))
+         (keybinding (yas--read-keybinding (eighth snippet)))
+         (uuid (or (ninth snippet)
+                  name))
+         (template (or (gethash uuid (yas--table-uuidhash snippet-table))
+                       (yas--make-blank-template))))
+    ;; X) populate the template object
+    ;;
+    (yas--populate-template template
+                           :table       snippet-table
+                           :key         key
+                           :content     (second snippet)
+                           :name        (or name key)
+                           :group       group
+                           :condition   condition
+                           :expand-env  (sixth snippet)
+                           :file        (seventh snippet)
+                           :keybinding  keybinding
+                           :uuid         uuid)
+    ;; X) Update this template in the appropriate table. This step
+    ;;    also will take care of adding the key indicators in the
+    ;;    templates menu entry, if any
+    ;;
+    (yas--update-template snippet-table template)
+    ;; X) Return the template
+    ;;
+    ;;
+    template))
+
+(defun yas-define-snippets (mode snippets)
+  "Define SNIPPETS for MODE.
+
+SNIPPETS is a list of snippet definitions, each taking the
+following form
+
+ (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
+
+Within these, only KEY and TEMPLATE are actually mandatory.
+
+TEMPLATE might be a lisp form or a string, depending on whether
+this is a snippet or a snippet-command.
+
+CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
+been `yas--read-lisp'-ed and will eventually be
+`yas--eval-lisp'-ed.
+
+The remaining elements are strings.
+
+FILE is probably of very little use if you're programatically
+defining snippets.
+
+UUID is the snippets \"unique-id\". Loading a second snippet file
+with the same uuid replaced the previous snippet.
+
+You can use `yas--parse-template' to return such lists based on
+the current buffers contents."
+  (let ((snippet-table (yas--table-get-create mode))
+        (template nil))
+    (dolist (snippet snippets)
+      (setq template (yas-define-snippets-1 snippet
+                                            snippet-table)))
+    template))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Loading snippets from files
 ;;
 (defun yas--load-yas-setup-file (file)
@@ -1866,87 +1950,6 @@ This works by stubbing a few functions, then calling
                    yas--version
                    ") -- pluskid <address@hidden>/joaotavora 
<address@hidden>")))
 
-(defun yas--define-parents (mode parents)
-  "Add PARENTS to the list of MODE's parents."
-  (puthash mode (remove-duplicates
-                 (append parents
-                         (gethash mode yas--parents)))
-           yas--parents))
-
-(defun yas-define-snippets (mode snippets)
-  "Define SNIPPETS for MODE.
-
-SNIPPETS is a list of snippet definitions, each taking the
-following form
-
- (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
-
-Within these, only KEY and TEMPLATE are actually mandatory.
-
-TEMPLATE might be a lisp form or a string, depending on whether
-this is a snippet or a snippet-command.
-
-CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
-been `yas--read-lisp'-ed and will eventually be
-`yas--eval-lisp'-ed.
-
-The remaining elements are strings.
-
-FILE is probably of very little use if you're programatically
-defining snippets.
-
-UUID is the snippets \"unique-id\". Loading a second snippet file
-with the same uuid replaced the previous snippet.
-
-You can use `yas--parse-template' to return such lists based on
-the current buffers contents."
-  (let ((snippet-table (yas--table-get-create mode))
-        (template nil))
-    (dolist (snippet snippets)
-      (setq template (yas-define-snippets-1 snippet
-                                            snippet-table)))
-    template))
-
-(defun yas-define-snippets-1 (snippet snippet-table)
-  "Helper for `yas-define-snippets'."
-  ;; X) Calculate some more defaults on the values returned by
-  ;; `yas--parse-template'.
-  ;;
-  (let* ((file (seventh snippet))
-         (key (car snippet))
-         (name (or (third snippet)
-                   (and file
-                        (file-name-directory file))))
-         (condition (fourth snippet))
-         (group (fifth snippet))
-         (keybinding (yas--read-keybinding (eighth snippet)))
-         (uuid (or (ninth snippet)
-                  name))
-         (template (or (gethash uuid (yas--table-uuidhash snippet-table))
-                       (yas--make-blank-template))))
-    ;; X) populate the template object
-    ;;
-    (yas--populate-template template
-                           :table       snippet-table
-                           :key         key
-                           :content     (second snippet)
-                           :name        (or name key)
-                           :group       group
-                           :condition   condition
-                           :expand-env  (sixth snippet)
-                           :file        (seventh snippet)
-                           :keybinding  keybinding
-                           :uuid         uuid)
-    ;; X) Update this template in the appropriate table. This step
-    ;;    also will take care of adding the key indicators in the
-    ;;    templates menu entry, if any
-    ;;
-    (yas--update-template snippet-table template)
-    ;; X) Return the template
-    ;;
-    ;;
-    template))
-
 
 ;;; Apropos snippet menu:
 ;;

commit a581ac475d7c4915e0f5c1593f5c299cfeebc1bd
Merge: 880767e 7d411fb
Author: João Távora <address@hidden>
Date:   Thu Nov 8 10:22:33 2012 -0800

    Merge pull request #328 from rolandwalker/byte-compiler-2
    
    Fix: new 'yas--called-interactively-p' to shoosh byte-compiler


commit 7d411fbfd7ffa7c49d374fea065fd6f123ebb01f
Author: Roland Walker <address@hidden>
Date:   Thu Nov 8 12:47:00 2012 -0500

    replace interactive-p with called-interactively-p macro
    tested compatible with GNU Emacs v 22.x - 24.x

diff --git a/yasnippet.el b/yasnippet.el
index a62dc4a..301b4de 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1200,7 +1200,7 @@ the template of a snippet in the current snippet-table."
   (intern (yas--table-name table)))
 
 
-;;; Internal functions:
+;;; Internal functions and macros:
 
 (defun yas--real-mode? (mode)
   "Try to find out if MODE is a real mode.
@@ -1310,6 +1310,15 @@ them all in `yas--menu-table'"
                     :visible (yas--show-menu-p ',mode)))
     menu-keymap))
 
+(defmacro yas--called-interactively-p (&optional kind)
+  "A backward-compatible version of `called-interactively-p'.
+
+Optional KIND is as documented at `called-interactively-p'
+in GNU Emacs 24.1 or higher."
+  (if (eq 0 (cdr (subr-arity (symbol-function 'called-interactively-p))))
+      '(called-interactively-p)
+    `(called-interactively-p ,kind)))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Template-related and snippet loading functions
 
@@ -1646,7 +1655,7 @@ Optional USE-JIT use jit-loading of snippets."
                             (buffer-list))))
             (yas--schedule-jit mode-sym form)
             (eval form)))))
-  (when (interactive-p)
+  (when (yas--called-interactively-p 'interactive)
     (yas--message 3 "Loaded snippets from %s." top-level-dir)))
 
 (defun yas--load-directory-1 (directory mode-sym parents &optional 
no-compiled-snippets)

commit 880767e66996ef1c4e501c6536ded8ff563fa1cb
Merge: 185c771 4e07aba
Author: João Távora <address@hidden>
Date:   Tue Nov 6 18:33:37 2012 +0000

    Merge remote-tracking branch 'rolandwalker/flet'
    
    Conflicts:
        yasnippet.el

diff --cc yasnippet.el
index cd944d2,cdfba3b..a62dc4a
--- a/yasnippet.el
+++ b/yasnippet.el
@@@ -136,17 -135,15 +136,25 @@@
  (require 'cl)
  (require 'easymenu)
  (require 'help-mode)
 -
 -;; Future-proof against obsoleting flet, per discussion at
 -;; http://github.com/capitaomorte/yasnippet/issues/324
 +(require 'assoc)
 +
 +(eval-when-compile
 +  (defvar yas--editing-template)
 +  (defvar yas--guessed-modes)
 +  (defvar yas--indent-original-column)
 +  (defvar yas--scheduled-jit-loads)
 +  (defvar yas-keymap)
 +  (defvar yas-selected-text)
 +  (defvar yas-verbosity))
 +
++;; Future-proof against obsoleting flet, see github #324
++;;
+ (eval-and-compile
+   (unless (fboundp 'cl-flet)
+     (defalias 'cl-flet 'flet)
+     (put 'cl-flet 'lisp-indent-function 1)
+     (put 'cl-flet 'edebug-form-spec '((&rest (defun*)) cl-declarations 
body))))
+ 
  
  ;;; User customizable variables
  
@@@ -1776,48 -1851,48 +1784,48 @@@ foo\"bar\\! -> \"foo\\\"bar\\\\!\"
  This works by stubbing a few functions, then calling
  `yas-load-directory'."
    (interactive "DTop level snippet directory?")
-   (flet ((yas--load-yas-setup-file
+   (cl-flet ((yas--load-yas-setup-file
 -             (file)
 -             (let ((elfile (concat file ".el")))
 -               (when (file-exists-p elfile)
 -                 (insert ";;; .yas-setup.el support file if any:\n;;;\n")
 -                 (insert-file-contents elfile)
 -                 (end-of-buffer)
 -                 )))
 -            (yas-define-snippets
 -             (mode snippets)
 -             (insert ";;; Snippet definitions:\n;;;\n")
 -             (let ((literal-snippets (list))
 -                   (print-length nil))
 -               (dolist (snippet snippets)
 -                 (let ((key                    (first   snippet))
 -                       (template-content       (second  snippet))
 -                       (name                   (third   snippet))
 -                       (condition              (fourth  snippet))
 -                       (group                  (fifth   snippet))
 -                       (expand-env             (sixth   snippet))
 -                       (file                   nil) ;; (seventh snippet)) ;; 
omit on purpose
 -                       (binding                (eighth  snippet))
 -                       (uuid                    (ninth   snippet)))
 -                   (push `(,key
 -                           ,template-content
 -                           ,name
 -                           ,condition
 -                           ,group
 -                           ,expand-env
 -                           ,file
 -                           ,binding
 -                           ,uuid)
 -                         literal-snippets)))
 -               (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
 -               (insert "\n\n")))
 -            (yas--load-directory-1
 -             (dir mode parents &rest ignore)
 -             (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
 -               (with-temp-file output-file
 -                 (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
 -                 (yas--load-directory-2 dir mode)
 -                 (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
 +          (file)
 +          (let ((elfile (concat file ".el")))
 +            (when (file-exists-p elfile)
 +              (insert ";;; .yas-setup.el support file if any:\n;;;\n")
 +              (insert-file-contents elfile)
 +              (goto-char (point-max))
 +              )))
 +         (yas-define-snippets
 +          (mode snippets)
 +          (insert ";;; Snippet definitions:\n;;;\n")
 +          (let ((literal-snippets (list))
 +                (print-length nil))
 +            (dolist (snippet snippets)
 +              (let ((key                    (first   snippet))
 +                    (template-content       (second  snippet))
 +                    (name                   (third   snippet))
 +                    (condition              (fourth  snippet))
 +                    (group                  (fifth   snippet))
 +                    (expand-env             (sixth   snippet))
 +                    (file                   nil) ;; (seventh snippet)) ;; 
omit on purpose
 +                    (binding                (eighth  snippet))
 +                    (uuid                    (ninth   snippet)))
 +                (push `(,key
 +                        ,template-content
 +                        ,name
 +                        ,condition
 +                        ,group
 +                        ,expand-env
 +                        ,file
 +                        ,binding
 +                        ,uuid)
 +                      literal-snippets)))
 +            (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
 +            (insert "\n\n")))
 +         (yas--load-directory-1
 +          (dir mode parents &rest ignore)
 +          (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
 +            (with-temp-file output-file
 +              (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
 +              (yas--load-directory-2 dir mode)
 +              (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
      (yas-load-directory top-level-dir nil)))
  
  (defun yas-recompile-all ()

commit 4e07abaec7b21eb649a34d289e90dd7835686ff5
Author: Roland Walker <address@hidden>
Date:   Tue Nov 6 13:06:01 2012 -0500

    comment

diff --git a/yasnippet.el b/yasnippet.el
index 56088e7..cdfba3b 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -136,6 +136,8 @@
 (require 'easymenu)
 (require 'help-mode)
 
+;; Future-proof against obsoleting flet, per discussion at
+;; http://github.com/capitaomorte/yasnippet/issues/324
 (eval-and-compile
   (unless (fboundp 'cl-flet)
     (defalias 'cl-flet 'flet)

commit 185c771dedea5c29fa18dc8d624674c3a62e8326
Author: João Távora <address@hidden>
Date:   Tue Nov 6 15:52:33 2012 +0000

    Closes #253.

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index ca80346..388b7ea 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -257,23 +257,34 @@ TODO: correct this bug!"
 
 ;;; Loading
 ;;;
+(defmacro yas-with-overriden-buffer-list (&rest body)
+  (let ((saved-sym (gensym)))
+    `(let ((,saved-sym (symbol-function 'buffer-list)))
+       (flet ((buffer-list ()
+                           (remove-if #'(lambda (buf)
+                                          (with-current-buffer buf
+                                            (eq major-mode 
'lisp-interaction-mode)))
+                                      (funcall ,saved-sym))))
+         ,@body))))
+
 (defmacro yas-with-some-interesting-snippet-dirs (&rest body)
   `(yas-saving-variables
-    (yas-with-snippet-dirs
-     '((".emacs.d/snippets"
-        ("c-mode"
-         (".yas-parents" . "cc-mode")
-         ("printf" . "printf($1);"))  ;; notice the overriding for issue #281
-        ("emacs-lisp-mode" ("ert-deftest" . "(ert-deftest ${1:name} () $0)"))
-        ("lisp-interaction-mode" (".yas-parents" . "emacs-lisp-mode")))
-       ("library/snippets"
-        ("c-mode"
-         (".yas-parents" . "c++-mode")
-         ("printf" . "printf"))
-        ("cc-mode" ("def" . "# define"))
-        ("emacs-lisp-mode" ("dolist" . "(dolist)"))
-        ("lisp-interaction-mode" ("sc" . "brother from another mother"))))
-     ,@body)))
+    (yas-with-overriden-buffer-list
+     (yas-with-snippet-dirs
+      '((".emacs.d/snippets"
+         ("c-mode"
+          (".yas-parents" . "cc-mode")
+          ("printf" . "printf($1);"))  ;; notice the overriding for issue #281
+         ("emacs-lisp-mode" ("ert-deftest" . "(ert-deftest ${1:name} () $0)"))
+         ("lisp-interaction-mode" (".yas-parents" . "emacs-lisp-mode")))
+        ("library/snippets"
+         ("c-mode"
+          (".yas-parents" . "c++-mode")
+          ("printf" . "printf"))
+         ("cc-mode" ("def" . "# define"))
+         ("emacs-lisp-mode" ("dolist" . "(dolist)"))
+         ("lisp-interaction-mode" ("sc" . "brother from another mother"))))
+      ,@body))))
 
 (ert-deftest basic-jit-loading ()
   "Test basic loading and expansion of snippets"
diff --git a/yasnippet.el b/yasnippet.el
index 2acc384..cd944d2 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1629,7 +1629,13 @@ Optional USE-JIT use jit-loading of snippets."
       (let ((form `(yas--load-directory-1 ,dir
                                          ',mode-sym
                                          ',parents)))
-        (if use-jit
+        (if (and use-jit
+                 (not (some #'(lambda (buffer)
+                                (with-current-buffer buffer
+                                  (when (eq major-mode mode-sym)
+                                    (yas--message 3 "Discovered there was 
already %s in %s" buffer mode-sym)
+                                    t)))
+                            (buffer-list))))
             (yas--schedule-jit mode-sym form)
             (eval form)))))
   (when (interactive-p)
@@ -1737,14 +1743,13 @@ loading."
                    (if errors " (some errors, check *Messages*)" "")))))
 
 (defun yas--load-pending-jits ()
-  (when yas-minor-mode
-    (dolist (mode (yas--modes-to-activate))
-      (let ((forms (reverse (gethash mode yas--scheduled-jit-loads))))
-        ;; must reverse to maintain coherence with `yas-snippet-dirs'
-        (dolist (form forms)
-          (yas--message  3 "Loading for `%s', just-in-time: %s!" mode form)
-          (eval form))
-        (remhash mode yas--scheduled-jit-loads)))))
+  (dolist (mode (yas--modes-to-activate))
+    (let ((forms (reverse (gethash mode yas--scheduled-jit-loads))))
+      ;; must reverse to maintain coherence with `yas-snippet-dirs'
+      (dolist (form forms)
+        (yas--message  3 "Loading for `%s', just-in-time: %s!" mode form)
+        (eval form))
+      (remhash mode yas--scheduled-jit-loads))))
 
 ;; (when (<= emacs-major-version 22)
 ;;   (add-hook 'after-change-major-mode-hook 'yas--load-pending-jits))

commit 9de1c5f4fb6f281cfa4af869d393db76616cb42e
Author: João Távora <address@hidden>
Date:   Tue Nov 6 15:51:32 2012 +0000

    Fix: need to require `assoc`, since using `aget` somewhere

diff --git a/yasnippet.el b/yasnippet.el
index b0b8dc0..2acc384 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -136,6 +136,7 @@
 (require 'cl)
 (require 'easymenu)
 (require 'help-mode)
+(require 'assoc)
 
 (eval-when-compile
   (defvar yas--editing-template)

commit 81dbf038a10eab484789f159ddb10846438d2c59
Author: João Távora <address@hidden>
Date:   Tue Nov 6 15:18:04 2012 +0000

    Fix: expose and honour `yas-dont-activate`

diff --git a/yasnippet.el b/yasnippet.el
index f224fe1..b0b8dc0 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -738,8 +738,8 @@ Key bindings:
          (remove-hook 'post-command-hook 'yas--post-command-handler t)
          (remove-hook 'emulation-mode-map-alists 'yas--direct-keymaps))))
 
-(defvar yas--dont-activate '(minibufferp)
-  "If non-nil don't let `yas-minor-mode-on' active yas for this buffer.
+(defvar yas-dont-activate '(minibufferp)
+  "If non-nil don't let `yas-minor-mode-on' activate for this buffer.
 
 If a function, then its result is used.
 
@@ -749,21 +749,19 @@ activate yas for this buffer.
 `yas-minor-mode-on' is usually called by `yas-global-mode' so
 this effectively lets you define exceptions to the \"global\"
 behaviour. Can also be a function of zero arguments.")
-(make-variable-buffer-local 'yas--dont-activate)
+(make-variable-buffer-local 'yas-dont-activate)
 
 (defun yas-minor-mode-on ()
   "Turn on YASnippet minor mode.
 
-Do this unless `yas--dont-activate' is truish."
+Honour `yas-dont-activate', which see."
   (interactive)
-  (unless (cond ((functionp yas--dont-activate)
-                 (funcall yas--dont-activate))
-                ((consp yas--dont-activate)
-                 (some #'funcall yas--dont-activate))
-                (yas--dont-activate))
-    ;; Load all snippets definitions unless we still don't have a
-    ;; root-directory or some snippets have already been loaded.
-    ;;
+  ;; Check `yas-dont-activate'
+  (unless (cond ((functionp yas-dont-activate)
+                 (funcall yas-dont-activate))
+                ((consp yas-dont-activate)
+                 (some #'funcall yas-dont-activate))
+                (yas-dont-activate))
     (yas-minor-mode 1)))
 
 ;;;###autoload
@@ -4403,6 +4401,7 @@ handle the end-of-buffer error fired in it by calling
                              yas-after-exit-snippet-hook
                              yas-before-expand-snippet-hook
                              yas-buffer-local-condition
+                             yas-dont-activate
 
                              ;; prompting functions
                              ;;

commit 73a1b485d64efafdae46bde9d54e35f3033fc295
Merge: 5aff682 cd70010
Author: João Távora <address@hidden>
Date:   Tue Nov 6 14:16:46 2012 +0000

    Merge branch 'trigger-key-fallback-cleanup'
    
    Conflicts:
        yasnippet.el

diff --cc yasnippet.el
index 6f337ae,95c9f3a..f224fe1
--- a/yasnippet.el
+++ b/yasnippet.el
@@@ -4275,14 -4166,13 +4192,13 @@@ When multiple expressions are found, on
  (put 'yas-expand  'function-documentation
       '(yas--expand-from-trigger-key-doc))
  (defun yas--expand-from-trigger-key-doc ()
 -  "A doc synthethizer for `yas--expand-from-trigger-key-doc'."
 +  "A doc synthesizer for `yas--expand-from-trigger-key-doc'."
    (let ((fallback-description
           (cond ((eq yas-fallback-behavior 'call-other-command)
-                 (let* ((yas-minor-mode nil)
-                        (fallback (key-binding (read-kbd-macro 
(yas--trigger-key-for-fallback)))))
+                 (let* ((fallback (yas--keybinding-beyond-yasnippet)))
                    (or (and fallback
                             (format " call command `%s'." (pp-to-string 
fallback)))
-                       " do nothing.")))
+                       " do nothing (`yas-expand' doesn't shadow\nanything)")))
                 ((eq yas-fallback-behavior 'return-nil)
                  ", do nothing.")
                 (t

commit cd70010b83bc2c92afcdfec7223ef84ddba285e7
Author: João Távora <address@hidden>
Date:   Tue Nov 6 14:12:18 2012 +0000

    Closes #296: No longer use customizable `yas-trigger-key` and friends.
    
    Use keymaps that the user can customise with `define-key` like all the
    other modes

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index f95e772..ca80346 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -444,21 +444,19 @@ TODO: be meaner"
     (yas-minor-mode 1)
     (should (eq (key-binding (yas--read-keybinding "<tab>")) 'yas-expand))
     (yas-expand-snippet "$1 $2 $3")
-    (dolist (k (if (listp yas-next-field-key)
-                   yas-next-field-key
-                 (list yas-next-field-key)))
-      (should (eq (key-binding (yas--read-keybinding k)) 
'yas-next-field-or-maybe-expand)))
-    (dolist (k (if (listp yas-prev-field-key)
-                   yas-prev-field-key
-                 (list yas-prev-field-key)))
-      (should (eq (key-binding (yas--read-keybinding k)) 'yas-prev-field)))))
+    (should (eq (key-binding [(tab)]) 'yas-next-field-or-maybe-expand))
+    (should (eq (key-binding (kbd "TAB")) 'yas-next-field-or-maybe-expand))
+    (should (eq (key-binding [(shift tab)]) 'yas-prev-field))
+    (should (eq (key-binding [backtab]) 'yas-prev-field))))
 
 (ert-deftest test-yas-in-org ()
   (with-temp-buffer
     (org-mode)
     (yas-minor-mode 1)
-    (should (eq (key-binding (yas--read-keybinding "<tab>")) 'yas-expand))))
+    (should (eq (key-binding [(tab)]) 'yas-expand))
+    (should (eq (key-binding (kbd "TAB")) 'yas-expand))))
 
+
 ;;; Helpers
 ;;;
 (defun yas/ert ()
diff --git a/yasnippet.el b/yasnippet.el
index 9535d32..95c9f3a 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -63,7 +63,8 @@
 ;;       M-x yas-expand
 ;;
 ;;           Try to expand snippets before point.  In `yas-minor-mode',
-;;           this is bound to `yas-trigger-key' which you can customize.
+;;           this is normally bound to TAB, but you can customize it in
+;;           `yas-minor-mode-map'.
 ;;
 ;;       M-x yas-load-directory
 ;;
@@ -236,81 +237,20 @@ Naturally this is only valid when `yas-indent-line' is 
`auto'"
   :type 'boolean
   :group 'yasnippet)
 
-(defcustom yas-trigger-key "<tab>"
-  "The key bound to `yas-expand' when `yas-minor-mode' is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'."
-  :type 'string
-  :group 'yasnippet
-  :set #'(lambda (symbol key)
-           (let ((old (and (boundp symbol)
-                           (symbol-value symbol))))
-             (set-default symbol key)
-             ;; On very first loading of this defcustom,
-             ;; `yas-trigger-key' is *not* loaded.
-             (if (fboundp 'yas--trigger-key-reload)
-                 (yas--trigger-key-reload old)))))
-
-(defcustom yas-next-field-key '("TAB" "<tab>")
-  "The key to navigate to next field when a snippet is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-
-(defcustom yas-prev-field-key '("<backtab>" "<S-tab>")
-  "The key to navigate to previous field when a snippet is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-(defcustom yas-skip-and-clear-key '("C-d" "<delete>" "<deletechar>")
-  "The key to clear the currently active field.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
 (defcustom yas-triggers-in-field nil
-  "If non-nil, `yas-next-field-key' can trigger stacked expansions.
+  "If non-nil, allow stacked expansions (snippets inside snippets).
 
-Otherwise, `yas-next-field-key' just tries to move on to the next
-field"
+Otherwise `yas-next-field-or-maybe-expand' just moves on to the
+next field"
   :type 'boolean
   :group 'yasnippet)
 
 (defcustom yas-fallback-behavior 'call-other-command
-  "How to act when `yas-trigger-key' does *not* expand a snippet.
+  "How to act when `yas-expand' does *not* expand a snippet.
 
 - `call-other-command' means try to temporarily disable YASnippet
-    and call the next command bound to `yas-trigger-key'.
+    and call the next command bound to whatever key was used to
+    invoke `yas-expand'.
 
 - nil or the symbol `return-nil' mean do nothing. (and
   `yas-expand' returns nil)
@@ -417,28 +357,15 @@ the trigger key itself."
   :group 'yasnippet)
 
 
-;;; User can also customize the next defvars
-
-(defun yas--define-some-keys (keys keymap definition)
-  "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'."
-  (let ((keys (or (and (listp keys) keys)
-                  (list keys))))
-    (dolist (key keys)
-      (define-key keymap (read-kbd-macro key) definition))))
-
-(defun yas--init-yas-in-snippet-keymap ()
-  (setq yas-keymap
-        (let ((map (make-sparse-keymap)))
-          (mapc #'(lambda (binding)
-                    (yas--define-some-keys (car binding) map (cdr binding)))
-                `((,yas-next-field-key     . yas-next-field-or-maybe-expand)
-                  (,yas-prev-field-key     . yas-prev-field)
-                  ("C-g"                   . yas-abort-snippet)
-                  (,yas-skip-and-clear-key . 
yas-skip-and-clear-or-delete-char)))
-          map)))
-
-(defvar yas-keymap (yas--init-yas-in-snippet-keymap)
-  "The keymap active while a snippet expansion is in progress.")
+(defvar yas-keymap  (let ((map (make-sparse-keymap)))
+                      (define-key map [(tab)]       
'yas-next-field-or-maybe-expand)
+                      (define-key map (kbd "TAB")   
'yas-next-field-or-maybe-expand)
+                      (define-key map [(shift tab)] 'yas-prev-field)
+                      (define-key map [backtab]     'yas-prev-field)
+                      (define-key map (kbd "C-g")   'yas-abort-snippet)
+                      (define-key map (kbd "C-d")   
'yas-skip-and-clear-or-delete-char)
+                      map)
+  "The active keymap while a snippet expansion is in progress.")
 
 (defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ")
   "List of character syntaxes used to find a trigger key before point.
@@ -694,6 +621,8 @@ snippet itself contains a condition that returns the symbol
 
     ;; Now for the stuff that has direct keybindings
     ;;
+    (define-key map [(tab)]     'yas-expand)
+    (define-key map (kbd "TAB") 'yas-expand)
     (define-key map "\C-c&\C-s" 'yas-insert-snippet)
     (define-key map "\C-c&\C-n" 'yas-new-snippet)
     (define-key map "\C-c&\C-v" 'yas-visit-snippet-file)
@@ -702,20 +631,6 @@ snippet itself contains a condition that returns the symbol
 (defvar yas-minor-mode-map (yas--init-minor-keymap)
   "The keymap used when `yas-minor-mode' is active.")
 
-(defun yas--trigger-key-reload (&optional unbind-key)
-  "Rebind `yas-expand' to the new value of `yas-trigger-key'.
-
-With optional UNBIND-KEY, try to unbind that key from
-`yas-minor-mode-map'."
-  (when (and unbind-key
-             (stringp unbind-key)
-             (not (string= unbind-key "")))
-    (define-key yas-minor-mode-map (read-kbd-macro unbind-key) nil))
-  (when  (and yas-trigger-key
-              (stringp yas-trigger-key)
-              (not (string= yas-trigger-key "")))
-    (define-key yas-minor-mode-map (read-kbd-macro yas-trigger-key) 
'yas-expand)))
-
 (defvar yas--tables (make-hash-table)
   "A hash table of mode symbols to `yas--table' objects.")
 
@@ -774,15 +689,14 @@ and friends."
 (define-minor-mode yas-minor-mode
   "Toggle YASnippet mode.
 
-When YASnippet mode is enabled, the `yas-trigger-key' key expands
-snippets of code depending on the major mode.
+When YASnippet mode is enabled, `yas-expand', normally bound to
+the TAB key, expands snippets of code depending on the major
+mode.
 
 With no argument, this command toggles the mode.
 positive prefix argument turns on the mode.
 Negative prefix argument turns off the mode.
 
-You can customize the key through `yas-trigger-key'.
-
 Key bindings:
 \\{yas-minor-mode-map}"
   nil
@@ -790,9 +704,6 @@ Key bindings:
   " yas"
   :group 'yasnippet
   (cond (yas-minor-mode
-         ;; Reload the trigger key
-         ;;
-         (yas--trigger-key-reload)
          ;; Install the direct keymaps in `emulation-mode-map-alists'
          ;; (we use `add-hook' even though it's not technically a hook,
          ;; but it works). Then define variables named after modes to
@@ -1800,9 +1711,6 @@ loading."
       ;; Reload the direct keybindings
       ;;
       (yas-direct-keymaps-reload)
-      ;; Reload the trigger-key (shoudn't be needed, but see issue #237)
-      ;;
-      (yas--trigger-key-reload)
 
       (yas--message 3 "Reloaded everything%s...%s."
                    (if interactive "" " (snippets will load just-in-time)")
@@ -2259,12 +2167,10 @@ expand immediately. Common gateway for
 
 ;; Apropos the trigger key and the fallback binding:
 ;;
-;; When `yas-trigger-key' is <tab> it correctly overrides
-;; org-mode's <tab>, for example and searching for fallbacks
-;; correctly returns `org-cycle'. However, most other modes bind
-;; "TAB" (which is translated from <tab>), and calling
-;; (key-binding "TAB") does not place return that command into
-;; our command-2 local. So we cheat.
+;; When `yas-minor-mode-map' binds <tab>, that correctly overrides
+;; org-mode's <tab>, for example and searching for fallbacks correctly
+;; returns `org-cycle'. However, most other modes bind "TAB". TODO,
+;; improve this explanation.
 ;;
 (defun yas--fallback (&optional from-trigger-key-p)
   "Fallback after expansion has failed.
@@ -2275,15 +2181,11 @@ Common gateway for `yas-expand-from-trigger-key' and
          ;; return nil
          nil)
         ((eq yas-fallback-behavior 'call-other-command)
-         (let* ((yas-minor-mode nil)
-                (yas--direct-keymaps nil)
-                (keys (this-single-command-keys))
-                (beyond-yasnippet (or (key-binding keys t)
-                                      (key-binding 
(yas--fallback-translate-input keys) t))))
+         (let* ((beyond-yasnippet (yas--keybinding-beyond-yasnippet)))
            (yas--message 4 "Falling back to %s"  beyond-yasnippet)
-           (when (commandp beyond-yasnippet)
-             (setq this-original-command beyond-yasnippet)
-             (call-interactively beyond-yasnippet))))
+           (assert (or (null beyond-yasnippet) (commandp beyond-yasnippet)))
+           (setq this-original-command beyond-yasnippet)
+           (call-interactively beyond-yasnippet)))
         ((and (listp yas-fallback-behavior)
               (cdr yas-fallback-behavior)
               (eq 'apply (car yas-fallback-behavior)))
@@ -2297,11 +2199,19 @@ Common gateway for `yas-expand-from-trigger-key' and
          ;; also return nil if all the other fallbacks have failed
          nil)))
 
+(defun yas--keybinding-beyond-yasnippet ()
+  "Returns the "
+  (let* ((yas-minor-mode nil)
+         (yas--direct-keymaps nil)
+         (keys (this-single-command-keys)))
+    (or (key-binding keys t)
+        (key-binding (yas--fallback-translate-input keys) t))))
+
 (defun yas--fallback-translate-input (keys)
   "Emulate `read-key-sequence', at least what I think it does.
 
 Keys should be an untranslated key vector. Returns a translated
-vector of keys. XXX not working yet"
+vector of keys. FIXME not thoroughly tested"
   (let ((retval [])
         (i 0))
     (while (< i (length keys))
@@ -4259,15 +4169,14 @@ When multiple expressions are found, only the last one 
counts."
   "A doc synthethizer for `yas--expand-from-trigger-key-doc'."
   (let ((fallback-description
          (cond ((eq yas-fallback-behavior 'call-other-command)
-                (let* ((yas-minor-mode nil)
-                       (fallback (key-binding (read-kbd-macro 
(yas--trigger-key-for-fallback)))))
+                (let* ((fallback (yas--keybinding-beyond-yasnippet)))
                   (or (and fallback
                            (format " call command `%s'." (pp-to-string 
fallback)))
-                      " do nothing.")))
+                      " do nothing (`yas-expand' doesn't shadow\nanything)")))
                ((eq yas-fallback-behavior 'return-nil)
                 ", do nothing.")
                (t
-                ", defer to `yas--fallback-behaviour' :-)"))))
+                ", defer to `yas-fallback-behaviour' (which see)"))))
     (concat "Expand a snippet before point. If no snippet
 expansion is possible,"
             fallback-description
@@ -4446,10 +4355,6 @@ handle the end-of-buffer error fired in it by calling
                              yas-indent-line
                              yas-also-auto-indent-first-line
                              yas-snippet-revival
-                             yas-trigger-key
-                             yas-next-field-key
-                             yas-prev-field-key
-                             yas-skip-and-clear-key
                              yas-triggers-in-field
                              yas-fallback-behavior
                              yas-choose-keys-first

commit f8366214801b52c7c1cc9c091fa5dcb42d3fd217
Author: João Távora <address@hidden>
Date:   Tue Nov 6 14:09:51 2012 +0000

    Fix: correct expectation for this test in batch-mode

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index c3ed30e..f95e772 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -198,6 +198,12 @@
       (should (string= (yas--buffer-contents) "if 
condition\naaa\nelse\nbbb\nend")))))
 
 (ert-deftest another-example-for-issue-271 ()
+  ;; expect this to fail in batch mode since `region-active-p' doesn't
+  ;; used by `yas-expand-snippet' doesn't make sense in that context.
+  ;;
+  :expected-result (if noninteractive
+                       :failed
+                     :passed)
   (with-temp-buffer
     (yas-minor-mode 1)
     (let ((snippet "\\${${1:1}:`yas/selected-text`}"))

commit 1774d7cbd09241b61d21bc788ffd4186cc932997
Author: João Távora <address@hidden>
Date:   Tue Nov 6 13:27:37 2012 +0000

    Add: easier to run tests

diff --git a/Rakefile b/Rakefile
index 1bf0045..c68929c 100644
--- a/Rakefile
+++ b/Rakefile
@@ -9,6 +9,11 @@ end
 find_version
 FileUtils.mkdir_p('pkg')
 
+desc "run tests in batch mode"
+task :tests do
+  $EMACS=ENV["EMACS"] || "emacs"
+  sh "#{$EMACS} -Q -L . -l yasnippet-tests.el -nw --batch -e yas/ert"
+end
 
 desc "convert some textmate bundles to yasnippets"
 task :convert_bundles do
diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 62653b0..c3ed30e 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -455,6 +455,15 @@ TODO: be meaner"
 
 ;;; Helpers
 ;;;
+(defun yas/ert ()
+  (interactive)
+  (with-temp-buffer
+    (flet ((message (&rest args)
+                    (declare (ignore args))
+                    nil))
+      (ert t (buffer-name (current-buffer)))
+      (princ (buffer-string)))))
+
 
 (defun yas-should-expand (keys-and-expansions)
   (dolist (key-and-expansion keys-and-expansions)

commit 5aff68266c12ecf4067dae7f0124a9b129246371
Merge: cbfc82d 49dde51
Author: João Távora <address@hidden>
Date:   Tue Nov 6 04:50:38 2012 -0800

    Merge pull request #323 from rolandwalker/byte-compiler
    
    Fix: quieten byte-compiler


commit cbfc82d18660403d3626010232285532406b18ae
Merge: f7b786f 9574288
Author: João Távora <address@hidden>
Date:   Tue Nov 6 04:44:48 2012 -0800

    Merge pull request #325 from rolandwalker/doc
    
    Docfix: checkdoc + spelling


commit 32e56098fb184b00607998efde30bd934652e2b3
Author: Roland Walker <address@hidden>
Date:   Mon Nov 5 11:09:25 2012 -0500

    future-proof against obsoleting of `flet'
    flet will be marked obsolete starting in Emacs 24.3

diff --git a/yasnippet.el b/yasnippet.el
index ed6644f..56088e7 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -136,6 +136,12 @@
 (require 'easymenu)
 (require 'help-mode)
 
+(eval-and-compile
+  (unless (fboundp 'cl-flet)
+    (defalias 'cl-flet 'flet)
+    (put 'cl-flet 'lisp-indent-function 1)
+    (put 'cl-flet 'edebug-form-spec '((&rest (defun*)) cl-declarations body))))
+
 
 ;;; User customizable variables
 
@@ -1843,48 +1849,48 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\""
 This works by stubbing a few functions, then calling
 `yas-load-directory'."
   (interactive "DTop level snippet directory?")
-  (flet ((yas--load-yas-setup-file
-          (file)
-          (let ((elfile (concat file ".el")))
-            (when (file-exists-p elfile)
-              (insert ";;; .yas-setup.el support file if any:\n;;;\n")
-              (insert-file-contents elfile)
-              (end-of-buffer)
-              )))
-         (yas-define-snippets
-          (mode snippets)
-          (insert ";;; Snippet definitions:\n;;;\n")
-          (let ((literal-snippets (list))
-                (print-length nil))
-            (dolist (snippet snippets)
-              (let ((key                    (first   snippet))
-                    (template-content       (second  snippet))
-                    (name                   (third   snippet))
-                    (condition              (fourth  snippet))
-                    (group                  (fifth   snippet))
-                    (expand-env             (sixth   snippet))
-                    (file                   nil) ;; (seventh snippet)) ;; omit 
on purpose
-                    (binding                (eighth  snippet))
-                    (uuid                    (ninth   snippet)))
-                (push `(,key
-                        ,template-content
-                        ,name
-                        ,condition
-                        ,group
-                        ,expand-env
-                        ,file
-                        ,binding
-                        ,uuid)
-                      literal-snippets)))
-            (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
-            (insert "\n\n")))
-         (yas--load-directory-1
-          (dir mode parents &rest ignore)
-          (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
-            (with-temp-file output-file
-              (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
-              (yas--load-directory-2 dir mode)
-              (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
+  (cl-flet ((yas--load-yas-setup-file
+             (file)
+             (let ((elfile (concat file ".el")))
+               (when (file-exists-p elfile)
+                 (insert ";;; .yas-setup.el support file if any:\n;;;\n")
+                 (insert-file-contents elfile)
+                 (end-of-buffer)
+                 )))
+            (yas-define-snippets
+             (mode snippets)
+             (insert ";;; Snippet definitions:\n;;;\n")
+             (let ((literal-snippets (list))
+                   (print-length nil))
+               (dolist (snippet snippets)
+                 (let ((key                    (first   snippet))
+                       (template-content       (second  snippet))
+                       (name                   (third   snippet))
+                       (condition              (fourth  snippet))
+                       (group                  (fifth   snippet))
+                       (expand-env             (sixth   snippet))
+                       (file                   nil) ;; (seventh snippet)) ;; 
omit on purpose
+                       (binding                (eighth  snippet))
+                       (uuid                    (ninth   snippet)))
+                   (push `(,key
+                           ,template-content
+                           ,name
+                           ,condition
+                           ,group
+                           ,expand-env
+                           ,file
+                           ,binding
+                           ,uuid)
+                         literal-snippets)))
+               (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
+               (insert "\n\n")))
+            (yas--load-directory-1
+             (dir mode parents &rest ignore)
+             (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
+               (with-temp-file output-file
+                 (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
+                 (yas--load-directory-2 dir mode)
+                 (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
     (yas-load-directory top-level-dir nil)))
 
 (defun yas-recompile-all ()
@@ -3685,19 +3691,19 @@ Returns the newly created snippet."
 
 This is according to their relative positions in the buffer, and
 has to be called before the $-constructs are deleted."
-  (flet ((yas--fom-set-next-fom (fom nextfom)
-                               (cond ((yas--field-p fom)
-                                      (setf (yas--field-next fom) nextfom))
-                                     ((yas--mirror-p fom)
-                                      (setf (yas--mirror-next fom) nextfom))
-                                     (t
-                                      (setf (yas--exit-next fom) nextfom))))
-         (yas--compare-fom-begs (fom1 fom2)
-                               (if (= (yas--fom-start fom2) (yas--fom-start 
fom1))
-                                   (yas--mirror-p fom2)
-                                 (>= (yas--fom-start fom2) (yas--fom-start 
fom1))))
-         (yas--link-foms (fom1 fom2)
-                        (yas--fom-set-next-fom fom1 fom2)))
+  (cl-flet ((yas--fom-set-next-fom (fom nextfom)
+                                  (cond ((yas--field-p fom)
+                                         (setf (yas--field-next fom) nextfom))
+                                        ((yas--mirror-p fom)
+                                         (setf (yas--mirror-next fom) nextfom))
+                                        (t
+                                         (setf (yas--exit-next fom) nextfom))))
+            (yas--compare-fom-begs (fom1 fom2)
+                                  (if (= (yas--fom-start fom2) (yas--fom-start 
fom1))
+                                      (yas--mirror-p fom2)
+                                    (>= (yas--fom-start fom2) (yas--fom-start 
fom1))))
+            (yas--link-foms (fom1 fom2)
+                           (yas--fom-set-next-fom fom1 fom2)))
     ;; make some yas--field, yas--mirror and yas--exit soup
     (let ((soup))
       (when (yas--snippet-exit snippet)

commit 95742882778ac4080e25b5ae5e5ea6d8b223dc46
Author: Roland Walker <address@hidden>
Date:   Mon Nov 5 10:59:34 2012 -0500

    checkdoc + spelling

diff --git a/yasnippet.el b/yasnippet.el
index ed6644f..a9a504f 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -37,10 +37,10 @@
 ;;       `yas-snippet-dirs'
 ;;
 ;;           The directory where user-created snippets are to be
-;;           stored. Can also be a list of directories. In that case,
+;;           stored.  Can also be a list of directories.  In that case,
 ;;           when used for bulk (re)loading of snippets (at startup or
 ;;           via `yas-reload-all'), directories appearing earlier in
-;;           the list shadow other dir's snippets. Also, the first
+;;           the list shadow other dir's snippets.  Also, the first
 ;;           directory is taken as the default for storing the user's
 ;;           new snippets.
 ;;
@@ -50,7 +50,7 @@
 ;;       `yas-extra-modes'
 ;;
 ;;           A local variable that you can set in a hook to override
-;;           snippet-lookup based on major mode. It is a a symbol (or
+;;           snippet-lookup based on major mode.  It is a symbol (or
 ;;           list of symbols) that correspond to subdirectories of
 ;;           `yas-snippet-dirs' and is used for deciding which
 ;;           snippets to consider for the active buffer.
@@ -104,13 +104,13 @@
 ;;
 ;;       M-x yas-describe-tables
 ;;
-;;           Lists known snippets in a separate buffer. User is
+;;           Lists known snippets in a separate buffer.  User is
 ;;           prompted as to whether only the currently active tables
 ;;           are to be displayed, or all the tables for all major
 ;;           modes.
 ;;
 ;;   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", putting in
 ;;   your .emacs file, for example:
 ;;
 ;;       (require 'dropdown-list)
@@ -152,11 +152,11 @@
                                             (concat (file-name-directory 
yas--load-file-name) "snippets"))))
   "Directory or list of snippet dirs for each major mode.
 
-The directory where user-created snippets are to be stored. Can
-also be a list of directories. In that case, when used for
+The directory where user-created snippets are to be stored.  Can
+also be a list of directories.  In that case, when used for
 bulk (re)loading of snippets (at startup or via
 `yas-reload-all'), directories appearing earlier in the list
-shadow other dir's snippets. Also, the first directory is taken
+shadow other dir's snippets.  Also, the first directory is taken
 as the default for storing the user's new snippets."
   :type '(choice (string :tag "Single directory (string)")
                  (repeat :args (string) :tag "List of directories (strings)"))
@@ -216,7 +216,7 @@ The following values are possible:
 
 - `auto' Indent each line of the snippet with `indent-according-to-mode'
 
-Every other value means don't apply any snippet-side indendation
+Every other value means don't apply any snippet-side indentation
 after expansion (the manual per-line \"$>\" indentation still
 applies)."
   :type '(choice (const :tag "Nothing"  nothing)
@@ -315,7 +315,7 @@ field"
 - nil or the symbol `return-nil' mean do nothing. (and
   `yas-expand' returns nil)
 
-- A lisp form (apply COMMAND . ARGS) means interactively call
+- A Lisp form (apply COMMAND . ARGS) means interactively call
   COMMAND, if ARGS is non-nil, call COMMAND non-interactively
   with ARGS as arguments."
   :type '(choice (const :tag "Call previous command"  call-other-command)
@@ -372,7 +372,7 @@ Any other non-nil value, every submenu is listed."
   "If non-nil, snippet expansion wraps around selected region.
 
 The wrapping occurs just before the snippet's exit marker.  This
-can be overriden on a per-snippet basis."
+can be overridden on a per-snippet basis."
   :type 'boolean
   :group 'yasnippet)
 
@@ -386,7 +386,7 @@ An error string \"[yas] error\" is returned instead."
 (defcustom yas-visit-from-menu nil
   "If non-nil visit snippets's files from menu, instead of expanding them.
 
-This cafn only work when snippets are loaded from files."
+This can only work when snippets are loaded from files."
   :type 'boolean
   :group 'yasnippet)
 
@@ -397,7 +397,7 @@ Leave this set at nil (the default) to be able to trigger an
 expansion simply by placing the cursor after a valid tab trigger,
 using whichever commands.
 
-Optionallly, set this to something like '(self-insert-command) if
+Optionally, set this to something like '(self-insert-command) if
 you to wish restrict expansion to only happen when the last
 letter of the snippet tab trigger was typed immediately before
 the trigger key itself."
@@ -427,6 +427,7 @@ the trigger key itself."
       (define-key keymap (read-kbd-macro key) definition))))
 
 (defun yas--init-yas-in-snippet-keymap ()
+  "Set the value of `yas-keymap'."
   (setq yas-keymap
         (let ((map (make-sparse-keymap)))
           (mapc #'(lambda (binding)
@@ -443,15 +444,15 @@ the trigger key itself."
 (defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ")
   "List of character syntaxes used to find a trigger key before point.
 The list is tried in the order while scanning characters
-backwards from point. For example, if the list is '(\"w\" \"w_\")
+backwards from point.  For example, if the list is '(\"w\" \"w_\")
 first look for trigger keys which are composed exclusively of
 \"word\"-syntax characters, and then, if that fails, look for
 keys which are either of \"word\" or \"symbol\"
-syntax. Triggering after
+syntax.  Triggering after
 
 foo-bar
 
-will, according to the \"w\" element first try \"bar\". If that
+will, according to the \"w\" element first try \"bar\".  If that
 isn't a trigger key, \"foo-bar\" is tried, respecting a second
 \"w_\" element.")
 
@@ -466,7 +467,7 @@ proper values:
 
 `yas-snippet-end' : Similar to beg.
 
-Attention: These hooks are not run when exiting nested/stackd snippet 
expansion!")
+Attention: These hooks are not run when exiting nested/stacked snippet 
expansion!")
 
 (defvar yas-before-expand-snippet-hook
   '()
@@ -480,8 +481,8 @@ Attention: These hooks are not run when exiting 
nested/stackd snippet expansion!
      t)
   "Snippet expanding condition.
 
-This variable is a lisp form which is evaluated everytime a
-snippet expansion is attemped:
+This variable is a Lisp form which is evaluated every time a
+snippet expansion is attempted:
 
     * If it evaluates to nil, no snippets can be expanded.
 
@@ -492,7 +493,7 @@ snippet expansion is attemped:
          considered
 
        * Snippets bearing conditions that evaluate to nil (or
-         produce an error) won't be onsidered.
+         produce an error) won't be considered.
 
        * If the snippet has a condition that evaluates to non-nil
          RESULT:
@@ -541,7 +542,7 @@ snippet itself contains a condition that returns the symbol
 
 (defvar yas--known-modes
   '(ruby-mode rst-mode markdown-mode)
-  "A list of mode which is well known but not part of emacs.")
+  "A list of mode which is well known but not part of Emacs.")
 
 (defvar yas--escaped-characters
   '(?\\ ?` ?\" ?' ?$ ?} ?{ ?\( ?\))
@@ -582,9 +583,10 @@ snippet itself contains a condition that returns the symbol
 (defvar last-buffer-undo-list nil)
 
 (defvar yas--minor-mode-menu nil
-  "Holds the YASnippet menu")
+  "Holds the YASnippet menu.")
 
 (defun yas--init-minor-keymap ()
+  "Set up the `yas-minor-mode' keymap."
   (let ((map (make-sparse-keymap)))
     (when yas-use-menu
       (easy-menu-define yas--minor-mode-menu
@@ -681,7 +683,7 @@ snippet itself contains a condition that returns the symbol
          ["Good grace "
           (setq yas-good-grace
                 (not yas-good-grace))
-          :help "If non-nil don't raise errors in bad embedded eslip in 
snippets"
+          :help "If non-nil don't raise errors in bad embedded elisp in 
snippets"
           :style toggle :selected yas-good-grace]
          )
         "----"
@@ -690,7 +692,7 @@ snippet itself contains a condition that returns the symbol
         ["Reload everything" yas-reload-all
          :help "Cleanup stuff, reload snippets, rebuild menus"]
         ["About"            yas-about
-         :help "Display some information about YASsnippet"])))
+         :help "Display some information about YASnippet"])))
 
     ;; Now for the stuff that has direct keybindings
     ;;
@@ -726,19 +728,19 @@ This list is populated when reading the \".yas-parents\" 
files
 found when traversing snippet directories with
 `yas-load-directory'.
 
-There might be additionalal parenting information stored in the
+There might be additional parenting information stored in the
 `derived-mode-parent' property of some mode symbols, but that is
 not recorded here.")
 
 (defvar yas--direct-keymaps (list)
   "Keymap alist supporting direct snippet keybindings.
 
-This variable is is placed in `emulation-mode-map-alists'.
+This variable is placed in `emulation-mode-map-alists'.
 
-Its elements looks like (TABLE-NAME . KEYMAP). They're
+Its elements looks like (TABLE-NAME . KEYMAP).  They're
 instantiated on `yas-reload-all' but KEYMAP is added to only when
-loading snippets. `yas--direct-TABLE-NAME' is then a variable set
-buffer-locally when entering `yas-minor-mode'. KEYMAP binds all
+loading snippets.  `yas--direct-TABLE-NAME' is then a variable set
+buffer-locally when entering `yas-minor-mode'.  KEYMAP binds all
 defined direct keybindings to the command
 `yas-expand-from-keymap' which then which snippet to expand.")
 
@@ -768,7 +770,7 @@ and friends."
                      modes-to-activate)))))
 
 (defvar yas-minor-mode-hook nil
-  "Hook run when yas-minor-mode is turned on")
+  "Hook run when `yas-minor-mode' is turned on.")
 
 ;;;###autoload
 (define-minor-mode yas-minor-mode
@@ -833,7 +835,7 @@ behaviour. Can also be a function of zero arguments.")
 (defun yas-minor-mode-on ()
   "Turn on YASnippet minor mode.
 
-Do this unless `yas--dont-activate' is truish "
+Do this unless `yas--dont-activate' is truish."
   (interactive)
   (unless (cond ((functionp yas--dont-activate)
                  (funcall yas--dont-activate))
@@ -851,6 +853,7 @@ Do this unless `yas--dont-activate' is truish "
   :require 'yasnippet)
 
 (defun yas--global-mode-reload-with-jit-maybe ()
+  "Run `yas-reload-all' when `yas-global-mode' is on."
   (when yas-global-mode (yas-reload-all)))
 
 (add-hook 'yas-global-mode-hook 'yas--global-mode-reload-with-jit-maybe)
@@ -876,6 +879,7 @@ Do this unless `yas--dont-activate' is truish "
              (0 font-lock-keyword-face)))))
 
 (defun yas--init-major-keymap ()
+  "Setup YASnippet major-mode keymap."
   (let ((map (make-sparse-keymap)))
     (easy-menu-define nil
       map
@@ -892,7 +896,7 @@ Do this unless `yas--dont-activate' is truish "
 
 (defvar snippet-mode-map
   (yas--init-major-keymap)
-  "The keymap used when `snippet-mode' is active")
+  "The keymap used when `snippet-mode' is active.")
 
 
 (define-derived-mode snippet-mode text-mode "Snippet"
@@ -923,7 +927,7 @@ Do this unless `yas--dont-activate' is truish "
   )
 
 (defun yas--populate-template (template &rest args)
-  "Helper function to populate a template with properties"
+  "Helper function to populate TEMPLATE with properties."
   (let (p v)
     (while args
       (aset template
@@ -979,7 +983,7 @@ Has the following fields:
 ;; Apropos storing/updating in TABLE, this works in two steps:
 ;;
 ;; 1. `yas--remove-template-by-uuid' removes any
-;;    keyhash-namehash-template mappings from TABLE, grabing the
+;;    keyhash-namehash-template mappings from TABLE, grabbing the
 ;;    snippet by its uuid. Also removes mappings from TABLE's
 ;;    `yas--table-direct-keymap' (FIXME: and should probably take care
 ;;    of potentially stale menu bindings right?.)
@@ -1098,7 +1102,7 @@ Also takes care of adding and updating to the associated 
menu."
     (yas--update-template-menu table template)))
 
 (defun yas--update-template-menu (table template)
-  "Update every menu-related for TEMPLATE"
+  "Update every menu-related for TEMPLATE."
   (let ((menu-binding-pair (yas--template-menu-binding-pair-get-create 
template))
         (key (yas--template-key template))
         (keybinding (yas--template-keybinding template)))
@@ -1142,6 +1146,7 @@ Also takes care of adding and updating to the associated 
menu."
         (car (yas--template-menu-binding-pair template))))))
 
 (defun yas--namehash-templates-alist (namehash)
+  "Return NAMEHASH as an alist."
   (let (alist)
     (maphash #'(lambda (k v)
                  (push (cons k v) alist))
@@ -1205,7 +1210,7 @@ conditions to filter out potential expansions."
                (cdr local-condition)))))))
 
 (defun yas--template-can-expand-p (condition requirement)
-  "Evaluates CONDITION and REQUIREMENT and returns a boolean"
+  "Evaluates CONDITION and REQUIREMENT and returns a boolean."
   (let* ((result (or (null condition)
                      (yas--eval-condition condition))))
     (cond ((eq requirement t)
@@ -1214,7 +1219,7 @@ conditions to filter out potential expansions."
            (eq requirement result)))))
 
 (defun yas--all-parents (mode)
-  "Returns a list of all parent modes of MODE"
+  "Returns a list of all parent modes of MODE."
   (let ((parents (gethash mode yas--parents)))
     (append parents
             (mapcan #'yas--all-parents parents))))
@@ -1257,7 +1262,7 @@ the template of a snippet in the current snippet-table."
 
 
 (defun yas--table-all-keys (table)
-  "Get trigger keys of all active snippets in TABLE"
+  "Get trigger keys of all active snippets in TABLE."
   (let ((acc))
     (maphash #'(lambda (key namehash)
                  (when (yas--filter-templates-by-condition 
(yas--namehash-templates-alist namehash))
@@ -1272,11 +1277,12 @@ the template of a snippet in the current snippet-table."
 ;;; Internal functions:
 
 (defun yas--real-mode? (mode)
-  "Try to find out if MODE is a real mode. The MODE bound to
-a function (like `c-mode') is considered real mode. Other well
-known mode like `ruby-mode' which is not part of Emacs might
-not bound to a function until it is loaded. So yasnippet keeps
-a list of modes like this to help the judgement."
+  "Try to find out if MODE is a real mode.
+
+The MODE bound to a function (like `c-mode') is considered real
+mode.  Other well known mode like `ruby-mode' which is not part of
+Emacs might not bound to a function until it is loaded.  So
+yasnippet keeps a list of modes like this to help the judgment."
   (or (fboundp mode)
       (find mode yas--known-modes)))
 
@@ -1358,7 +1364,7 @@ ensure your use `make-local-variable' when you set it.")
 (defun yas--get-snippet-tables ()
   "Get snippet tables for current buffer.
 
-Return a list of `yas--table' objects. The list of modes to
+Return a list of `yas--table' objects.  The list of modes to
 consider is returned by `yas--modes-to-activate'"
   (remove nil
           (mapcar #'(lambda (mode-name)
@@ -1519,7 +1525,9 @@ Here's a list of currently recognized directives:
 (defun yas--prompt-for-template (templates &optional prompt)
   "Interactively choose a template from the list TEMPLATES.
 
-TEMPLATES is a list of `yas--template'."
+TEMPLATES is a list of `yas--template'.
+
+Optional PROMPT sets the prompt to use."
   (when templates
     (setq templates
           (sort templates #'(lambda (t1 t2)
@@ -1534,13 +1542,18 @@ TEMPLATES is a list of `yas--template'."
             yas-prompt-functions))))
 
 (defun yas--prompt-for-keys (keys &optional prompt)
-  "Interactively choose a template key from the list KEYS."
+  "Interactively choose a template key from the list KEYS.
+
+Optional PROMPT sets the prompt to use."
   (when keys
     (some #'(lambda (fn)
               (funcall fn (or prompt "Choose a snippet key: ") keys))
           yas-prompt-functions)))
 
 (defun yas--prompt-for-table (tables &optional prompt)
+  "Interactively choose a table from the list TABLES.
+
+Optional PROMPT sets the prompt to use."
   (when tables
     (some #'(lambda (fn)
               (funcall fn (or prompt "Choose a snippet table: ")
@@ -1554,7 +1567,7 @@ TEMPLATES is a list of `yas--template'."
   ;; actually a `yas--template', defer to `yas--x-prompt-pretty-templates'
   ;;
   ;; This would be better implemented by passing CHOICES as a
-  ;; strucutred tree rather than a list. Modifications would go as far
+  ;; structured tree rather than a list. Modifications would go as far
   ;; up as `yas--all-templates' I think.
   ;;
   (when (and window-system choices)
@@ -1738,7 +1751,7 @@ Optional USE-JIT use jit-loading of snippets."
 
 (defun yas--load-snippet-dirs (&optional nojit)
   "Reload the directories listed in `yas-snippet-dirs' or
-   prompt the user to select one."
+prompt the user to select one."
   (let (errors)
     (if yas-snippet-dirs
         (dolist (directory (reverse (yas-snippet-dirs)))
@@ -1770,7 +1783,7 @@ loading."
       ;;
       (when snippet-editing-buffers
           (if interactive
-              (if (y-or-n-p "Some buffers editing live snippets, close them 
and proceed with reload?")
+              (if (y-or-n-p "Some buffers editing live snippets, close them 
and proceed with reload? ")
                   (mapc #'kill-buffer snippet-editing-buffers)
                 (yas--message 1 "Aborted reload...")
                 (throw 'abort nil))
@@ -1800,7 +1813,7 @@ loading."
       ;; Reload the direct keybindings
       ;;
       (yas-direct-keymaps-reload)
-      ;; Reload the trigger-key (shoudn't be needed, but see issue #237)
+      ;; Reload the trigger-key (shouldn't be needed, but see issue #237)
       ;;
       (yas--trigger-key-reload)
 
@@ -1834,7 +1847,7 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\""
 ;;; Snippet compilation function
 
 (defun yas--initialize ()
-  "For backward compatibility, enable `yas-minor-mode' globally"
+  "For backward compatibility, enable `yas-minor-mode' globally."
   (yas-global-mode 1))
 
 (defun yas-compile-directory (top-level-dir)
@@ -1917,7 +1930,7 @@ This works by stubbing a few functions, then calling
                    ") -- pluskid <address@hidden>/joaotavora 
<address@hidden>")))
 
 (defun yas--define-parents (mode parents)
-  "Add PARENTS to the list of MODE's parents"
+  "Add PARENTS to the list of MODE's parents."
   (puthash mode (remove-duplicates
                  (append parents
                          (gethash mode yas--parents)))
@@ -2032,7 +2045,7 @@ the current buffers contents."
 (defun yas--template-menu-binding-pair-get-create (template &optional type)
   "Get TEMPLATE's menu binding or assign it a new one.
 
-TYPE may be `:stay', signalling this menu binding should be
+TYPE may be `:stay', signaling this menu binding should be
 static in the menu."
   (or (yas--template-menu-binding-pair template)
       (let ((key (yas--template-key template))
@@ -2085,25 +2098,24 @@ static in the menu."
                             (rest keymap))))
 
 (defun yas-define-menu (mode menu &optional omit-items)
-  "Define a snippet menu for MODE according to MENU, ommitting OMIT-ITEMS.
+  "Define a snippet menu for MODE according to MENU, omitting OMIT-ITEMS.
 
 MENU is a list, its elements can be:
 
 - (yas-item UUID) : Creates an entry the snippet identified with
-  UUID. The menu entry for a snippet thus identified is
+  UUID.  The menu entry for a snippet thus identified is
   permanent, i.e. it will never move (be reordered) in the menu.
 
 - (yas-separator) : Creates a separator
 
 - (yas-submenu NAME SUBMENU) : Creates a submenu with NAME,
-  SUBMENU has the same form as MENU. NAME is also added to the
+  SUBMENU has the same form as MENU.  NAME is also added to the
   list of groups of the snippets defined thereafter.
 
 OMIT-ITEMS is a list of snippet uuid's that will always be
-ommited from MODE's menu, even if they're manually loaded.
+omitted from MODE's menu, even if they're manually loaded.
 
-This function does nothing if `yas-use-menu' is nil.
-"
+This function does nothing if `yas-use-menu' is nil."
   (when yas-use-menu
     (let* ((table (yas--table-get-create mode))
            (hash (yas--table-uuidhash table)))
@@ -2121,6 +2133,7 @@ This function does nothing if `yas-use-menu' is nil.
           (setf (yas--template-menu-binding-pair template) (cons nil 
:none)))))))
 
 (defun yas--define-menu-1 (table menu-keymap menu uuidhash &optional 
group-list)
+  "Helper for `yas-define-menu'."
   (dolist (e (reverse menu))
     (cond ((eq (first e) 'yas-item)
            (let ((template (or (gethash (second e) uuidhash)
@@ -2158,8 +2171,9 @@ will only be expanded when the condition evaluated to 
non-nil."
                        (list (list key template name condition group))))
 
 (defun yas-hippie-try-expand (first-time?)
-  "Integrate with hippie expand.  Just put this function in
-`hippie-expand-try-functions-list'."
+  "Integrate with hippie expand.
+
+Just put this function in `hippie-expand-try-functions-list'."
   (when yas-minor-mode
     (if (not first-time?)
         (let ((yas-fallback-behavior 'return-nil))
@@ -2246,7 +2260,7 @@ If expansion fails, execute the previous binding for this 
key"
   "Expand one of TEMPLATES from START to END.
 
 Prompt the user if TEMPLATES has more than one element, else
-expand immediately. Common gateway for
+expand immediately.  Common gateway for
 `yas-expand-from-trigger-key' and `yas-expand-from-keymap'."
   (let ((yas--current-template (or (and (rest templates) ;; more than one
                                        (yas--prompt-for-template (mapcar #'cdr 
templates)))
@@ -2379,6 +2393,7 @@ visited file in `snippet-mode'."
       (message "No snippets tables active!"))))
 
 (defun yas--visit-snippet-file-1 (template)
+  "Helper for `yas-visit-snippet-file'."
   (let ((file (yas--template-file template)))
     (cond ((and file (file-readable-p file))
            (find-file-other-window file)
@@ -2419,7 +2434,7 @@ visited file in `snippet-mode'."
   "Try to guess suitable directories based on the current active
 tables (or optional TABLE).
 
-Returns a list of elemts (TABLE . DIRS) where TABLE is a
+Returns a list of elements (TABLE . DIRS) where TABLE is a
 `yas--table' object and DIRS is a list of all possible directories
 where snippets of table might exist."
   (let ((main-dir (replace-regexp-in-string
@@ -2443,7 +2458,7 @@ where snippets of table might exist."
             tables)))
 
 (defun yas--make-directory-maybe (table-and-dirs &optional main-table-string)
-  "Returns a dir inside  TABLE-AND-DIRS, prompts for creation if none exists."
+  "Returns a dir inside TABLE-AND-DIRS, prompts for creation if none exists."
   (or (some #'(lambda (dir) (when (file-directory-p dir) dir)) (cdr 
table-and-dirs))
       (let ((candidate (first (cdr table-and-dirs))))
         (unless (file-writable-p (file-name-directory candidate))
@@ -2489,8 +2504,9 @@ NO-TEMPLATE is non-nil."
 $0"))))
 
 (defun yas--compute-major-mode-and-parents (file)
-  "Given FILE, find the nearest snippet directory for a given
-mode, then return a list (MODE-SYM PARENTS), the mode's symbol and a list
+  "Given FILE, find the nearest snippet directory for a given mode.
+
+Returns a list (MODE-SYM PARENTS), the mode's symbol and a list
 representing one or more of the mode's parents.
 
 Note that MODE-SYM need not be the symbol of a real major mode,
@@ -2518,7 +2534,7 @@ neither do the elements of PARENTS."
       (cons major-mode-sym parents))))
 
 (defvar yas--editing-template nil
-  "Supporting variable for `yas-load-snippet-buffer' and `yas--visit-snippet'")
+  "Supporting variable for `yas-load-snippet-buffer' and 
`yas--visit-snippet'.")
 
 (defvar yas--current-template nil
   "Holds the current template being expanded into a snippet.")
@@ -2604,7 +2620,7 @@ whether (and where) to save the snippet, then quit the 
window."
     (quit-window interactive)))
 
 (defun yas-tryout-snippet (&optional debug)
-  "Test current buffers's snippet template in other buffer."
+  "Test current buffer's snippet template in other buffer."
   (interactive "P")
   (let* ((major-mode-and-parent (yas--compute-major-mode-and-parents 
buffer-file-name))
          (parsed (yas--parse-template))
@@ -2641,7 +2657,7 @@ whether (and where) to save the snippet, then quit the 
window."
            (yas--message 3 "Cannot test snippet for unknown major mode")))))
 
 (defun yas-active-keys ()
-  "Return all active trigger keys for current buffer and point"
+  "Return all active trigger keys for current buffer and point."
   (remove-duplicates (mapcan #'yas--table-all-keys (yas--get-snippet-tables))
                      :test #'string=))
 
@@ -2792,7 +2808,6 @@ The last element of POSSIBILITIES may be a list of 
strings."
           yas-prompt-functions)))
 
 (defun yas-key-to-value (alist)
-  "Prompt for a string in the list POSSIBILITIES and return it."
   (unless (or yas-moving-away-p
               yas-modified-p)
     (let ((key (read-key-sequence "")))
@@ -2805,7 +2820,7 @@ The last element of POSSIBILITIES may be a list of 
strings."
   (throw 'yas--exception (cons 'yas--exception text)))
 
 (defun yas-verify-value (possibilities)
-  "Verify that the current field value is in POSSIBILITIES
+  "Verify that the current field value is in POSSIBILITIES.
 
 Otherwise throw exception."
   (when (and yas-moving-away-p (notany #'(lambda (pos) (string= pos yas-text)) 
possibilities))
@@ -2844,6 +2859,7 @@ Use this in primary and mirror transformations to tget."
     (yas-field-value number)))
 
 (defun yas-inside-string ()
+  "Return non-nil if the point is inside a string according to font-lock."
   (equal 'font-lock-string-face (get-char-property (1- (point)) 'face)))
 
 (defun yas-unimplemented (&optional missing-feature)
@@ -2861,10 +2877,10 @@ Use this in primary and mirror transformations to tget."
   "Overlays the currently active field.")
 
 (defvar yas--field-protection-overlays nil
-  "Two overlays protect the current active field ")
+  "Two overlays protect the current active field.")
 
 (defconst yas--prefix nil
-  "A prefix argument for expansion direct from keybindings")
+  "A prefix argument for expansion direct from keybindings.")
 
 (defvar yas-selected-text nil
   "The selected region deleted on the last snippet expansion.")
@@ -2937,7 +2953,7 @@ string iff EMPTY-ON-NIL-P is true."
     transformed))
 
 (defsubst yas--replace-all (from to &optional text)
-  "Replace all occurance from FROM to TO.
+  "Replace all occurrences from FROM to TO.
 
 With optional string TEXT do it in that string."
   (if text
@@ -2958,9 +2974,11 @@ With optional string TEXT do it in that string."
               #'yas--snippet-field-compare)))
 
 (defun yas--snippet-field-compare (field1 field2)
-  "Compare two fields. The field with a number is sorted first.
-If they both have a number, compare through the number. If neither
-have, compare through the field's start point"
+  "Compare FIELD1 and FIELD2.
+
+The field with a number is sorted first.  If they both have a
+number, compare through the number.  If neither have, compare
+through the field's start point"
   (let ((n1 (yas--field-number field1))
         (n2 (yas--field-number field2)))
     (if n1
@@ -2976,7 +2994,7 @@ have, compare through the field's start point"
 (defun yas--field-probably-deleted-p (snippet field)
   "Guess if SNIPPET's FIELD should be skipped."
   (and
-   ;; field must be zero lentgh
+   ;; field must be zero length
    ;;
    (zerop (- (yas--field-start field) (yas--field-end field)))
    ;; skip if:
@@ -2995,8 +3013,9 @@ have, compare through the field's start point"
    (not (zerop (yas--field-number field)))))
 
 (defun yas--snippets-at-point (&optional all-snippets)
-  "Return a sorted list of snippets at point, most recently
-inserted first."
+  "Return a sorted list of snippets at point.
+
+The most recently-inserted snippets are returned first."
   (sort
    (remove nil (remove-duplicates (mapcar #'(lambda (ov)
                                               (overlay-get ov 'yas--snippet))
@@ -3007,8 +3026,9 @@ inserted first."
        (<= (yas--snippet-id s2) (yas--snippet-id s1)))))
 
 (defun yas-next-field-or-maybe-expand ()
-  "Try to expand a snippet at a key before point, otherwise
-delegate to `yas-next-field'."
+  "Try to expand a snippet at a key before point.
+
+Otherwise delegate to `yas-next-field'."
   (interactive)
   (if yas-triggers-in-field
       (let ((yas-fallback-behavior 'return-nil)
@@ -3019,7 +3039,9 @@ delegate to `yas-next-field'."
     (yas-next-field)))
 
 (defun yas-next-field (&optional arg)
-  "Navigate to next field.  If there's none, exit the snippet."
+  "Navigate to the ARGth next field.
+
+If there's none, exit the snippet."
   (interactive)
   (let* ((arg (or arg
                   1))
@@ -3051,7 +3073,7 @@ delegate to `yas-next-field'."
            nil))))
 
 (defun yas--place-overlays (snippet field)
-  "Correctly place overlays for SNIPPET's FIELD"
+  "Correctly place overlays for SNIPPET's FIELD."
   (yas--make-move-field-protection-overlays snippet field)
   (yas--make-move-active-field-overlay snippet field))
 
@@ -3116,12 +3138,13 @@ Also create some protection overlays"
   `(let ((yas--inhibit-overlay-hooks t))
      (progn ,@body)))
 
-(defvar yas-snippet-beg nil "Beginning position of the last snippet commited.")
-(defvar yas-snippet-end nil "End position of the last snippet commited.")
+(defvar yas-snippet-beg nil "Beginning position of the last snippet 
committed.")
+(defvar yas-snippet-end nil "End position of the last snippet committed.")
 
 (defun yas--commit-snippet (snippet)
-  "Commit SNIPPET, but leave point as it is.  This renders the
-snippet as ordinary text."
+  "Commit SNIPPET, but leave point as it is.
+
+This renders the snippet as ordinary text."
 
   (let ((control-overlay (yas--snippet-control-overlay snippet)))
     ;;
@@ -3171,8 +3194,9 @@ snippet as ordinary text."
 
 
 (defun yas--check-commit-snippet ()
-  "Checks if point exited the currently active field of the
-snippet, if so cleans up the whole snippet up."
+  "Checks if point exited the currently active field of the snippet.
+
+If so cleans up the whole snippet up."
   (let* ((snippets (yas--snippets-at-point 'all-snippets))
          (snippets-left snippets)
          (snippet-exit-transform))
@@ -3239,8 +3263,9 @@ the original marker object with the position set to nil."
         (setf (yas--exit-marker snippet-exit) (cons exit (yas--exit-marker 
snippet-exit)))))))
 
 (defun yas--points-to-markers (snippet)
-  "Convert all cons (POINT . MARKER) in SNIPPET to markers. This
-is done by setting MARKER to POINT with `set-marker'."
+  "Convert all cons (POINT . MARKER) in SNIPPET to markers.
+
+This is done by setting MARKER to POINT with `set-marker'."
   (dolist (field (yas--snippet-fields snippet))
     (setf (yas--field-start field) (set-marker (cdr (yas--field-start field))
                                               (car (yas--field-start field))))
@@ -3263,11 +3288,11 @@ is done by setting MARKER to POINT with `set-marker'."
          (<= point (yas--field-end field)))))
 
 (defun yas--field-text-for-display (field)
-  "Return the propertized display text for field FIELD.  "
+  "Return the propertized display text for field FIELD."
   (buffer-substring (yas--field-start field) (yas--field-end field)))
 
 (defun yas--undo-in-progress ()
-  "True if some kind of undo is in progress"
+  "True if some kind of undo is in progress."
   (or undo-in-progress
       (eq this-command 'undo)
       (eq this-command 'redo)))
@@ -3303,9 +3328,9 @@ Otherwise deletes a character normally by calling 
`delete-char'."
            (call-interactively 'delete-char)))))
 
 (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's modified state to t."
   ;; Just before skipping-and-clearing the field, mark its children
-  ;; fields as modified, too. If the childen have mirrors-in-fields
+  ;; fields as modified, too. If the children have mirrors-in-fields
   ;; this prevents them from updating erroneously (we're skipping and
   ;; deleting!).
   ;;
@@ -3345,7 +3370,7 @@ Move the overlay, or create it if it does not exit."
                  '(yas--on-field-overlay-modification))))
 
 (defvar yas--inhibit-overlay-hooks nil
-  "Bind this temporarity to non-nil to prevent running 
`yas--on-*-modification'.")
+  "Bind this temporarily to non-nil to prevent running 
`yas--on-*-modification'.")
 
 (defun yas--on-field-overlay-modification (overlay after? beg end &optional 
length)
   "Clears the field and updates mirrors, conditionally.
@@ -3385,7 +3410,7 @@ progress."
 ;;
 ;; Alternatively, I've experimented with an implementation that
 ;; commits the snippet before actually calling `this-command'
-;; interactively, and then signals an eror, which is ignored. but
+;; interactively, and then signals an error, which is ignored. but
 ;; blocks all other million modification hooks. This presented some
 ;; problems with stacked expansion.
 ;;
@@ -3422,11 +3447,11 @@ Move the overlays, or create them if they do not exit."
              (overlay-put ov 'modification-hooks 
'(yas--on-protection-overlay-modification)))))))
 
 (defvar yas--protection-violation nil
-  "When non-nil, signals attempts to erronesly exit or modify the snippet.
+  "When non-nil, signals attempts to erroneously exit or modify the snippet.
 
 Functions in the `post-command-hook', for example
 `yas--post-command-handler' can check it and reset its value to
-nil. The variables value is the point where the violation
+nil.  The variables value is the point where the violation
 originated")
 
 (defun yas--on-protection-overlay-modification (overlay after? beg end 
&optional length)
@@ -3459,7 +3484,7 @@ The error should be ignored in `debug-ignored-errors'"
 ;; `yas--commit-snippet'. I've tried to mark them with "stacked
 ;; expansion:".
 ;;
-;; This was thought to be safer in in an undo/redo perpective, but
+;; This was thought to be safer in an undo/redo perspective, but
 ;; maybe the correct implementation is to make the globals
 ;; `yas--active-field-overlay' and `yas--field-protection-overlays' be
 ;; snippet-local and be active even while the child snippet is
@@ -3471,7 +3496,7 @@ The error should be ignored in `debug-ignored-errors'"
   "Expand snippet CONTENT at current point.
 
 Text between START and END will be deleted before inserting
-template. EXPAND-ENV is are let-style variable to value bindings
+template.  EXPAND-ENV is are let-style variable to value bindings
 considered when expanding the snippet."
   (run-hooks 'yas-before-expand-snippet-hook)
 
@@ -3532,7 +3557,7 @@ considered when expanding the snippet."
                          (yas--snippet-create (point-min) (point-max)))))))
 
            ;; stacked-expansion: This checks for stacked expansion, save the
-           ;; `yas--previous-active-field' and advance its boudary.
+           ;; `yas--previous-active-field' and advance its boundary.
            ;;
            (let ((existing-field (and yas--active-field-overlay
                                       (overlay-buffer 
yas--active-field-overlay)
@@ -3573,8 +3598,7 @@ considered when expanding the snippet."
            t))))
 
 (defun yas--take-care-of-redo (beg end snippet)
-  "Commits SNIPPET, which in turn pushes an undo action for
-reviving it.
+  "Commits SNIPPET, which in turn pushes an undo action for reviving it.
 
 Meant to exit in the `buffer-undo-list'."
   ;; slightly optimize: this action is only needed for snippets with
@@ -3583,10 +3607,9 @@ Meant to exit in the `buffer-undo-list'."
     (yas--commit-snippet snippet)))
 
 (defun yas--snippet-revive (beg end snippet)
-  "Revives the SNIPPET and creates a control overlay from BEG to
-END.
+  "Revives SNIPPET and creates a control overlay from BEG to END.
 
-BEG and END are, we hope, the original snippets boudaries. All
+BEG and END are, we hope, the original snippets boundaries. All
 the markers/points exiting existing inside SNIPPET should point
 to their correct locations *at the time the snippet is revived*.
 
@@ -3715,8 +3738,8 @@ has to be called before the $-constructs are deleted."
 (defun yas--calculate-mirrors-in-fields (snippet mirror)
   "Attempt to assign a parent field of SNIPPET to the mirror MIRROR.
 
-Use the tighest containing field if more than one field contains
-the mirror. Intended to be called *before* the dollar-regions are
+Use the tightest containing field if more than one field contains
+the mirror.  Intended to be called *before* the dollar-regions are
 deleted."
   (let ((min (point-min))
         (max (point-max)))
@@ -3740,10 +3763,8 @@ If it does, also:
   field
 
 Also, if FOM is an exit-marker, always call
-`yas--advance-start-maybe' on its next fom. This is beacuse
-exit-marker have identical start and end markers.
-
-"
+`yas--advance-start-maybe' on its next fom.  This is because
+exit-marker have identical start and end markers."
   (cond ((and fom (< (yas--fom-end fom) newend))
          (set-marker (yas--fom-end fom) newend)
          (yas--advance-start-maybe (yas--fom-next fom) newend)
@@ -3771,12 +3792,12 @@ next FOM. Works its way up recursively for parents of 
parents."
 
 (defvar yas--dollar-regions nil
   "When expanding the snippet the \"parse-create\" functions add
-  cons cells to this var")
+cons cells to this var.")
 
 (defvar yas--backquote-markers-and-strings nil
-  "List of (MARKER . STRING) marking where the the values
-  from backquoted lisp expressions should be inserted at the end of
-  expansion" )
+  "List of (MARKER . STRING) marking where the values from
+backquoted lisp expressions should be inserted at the end of
+expansion.")
 
 (defun yas--snippet-parse-create (snippet)
   "Parse a recently inserted snippet template, creating all
@@ -3831,8 +3852,7 @@ Meant to be called in a narrowed buffer, does various 
passes"
     (yas--indent snippet)))
 
 (defun yas--indent-according-to-mode (snippet-markers)
-  "Indent current line according to mode, preserving
-SNIPPET-MARKERS."
+  "Indent current line according to mode, preserving SNIPPET-MARKERS."
   ;;; Apropos indenting problems....
   ;;
   ;; `indent-according-to-mode' uses whatever `indent-line-function'
@@ -3950,8 +3970,8 @@ With optional string TEXT do it in string instead of the 
buffer."
     changed-text))
 
 (defun yas--save-backquotes ()
-  "Save all the \"`(lisp-expression)`\"-style expression
-with their evaluated value into `yas--backquote-markers-and-strings'"
+  "Save all the \"`(lisp-expression)`\"-style expressions
+with their evaluated value into `yas--backquote-markers-and-strings'."
   (while (re-search-forward yas--backquote-lisp-expression-regexp nil t)
     (let ((current-string (match-string-no-properties 1)) transformed)
       (delete-region (match-beginning 0) (match-end 0))
@@ -3965,8 +3985,7 @@ with their evaluated value into 
`yas--backquote-markers-and-strings'"
           (push (cons marker transformed) 
yas--backquote-markers-and-strings))))))
 
 (defun yas--restore-backquotes ()
-  "Replace all the markers in
-`yas--backquote-markers-and-strings' with their values"
+  "Replace markers in `yas--backquote-markers-and-strings' with their values."
   (while yas--backquote-markers-and-strings
     (let* ((marker-and-string (pop yas--backquote-markers-and-strings))
            (marker (car marker-and-string))
@@ -3986,13 +4005,13 @@ with their evaluated value into 
`yas--backquote-markers-and-strings'"
      nil)))
 
 (defun yas--make-marker (pos)
-  "Create a marker at POS with `nil' `marker-insertion-type'"
+  "Create a marker at POS with nil `marker-insertion-type'."
   (let ((marker (set-marker (make-marker) pos)))
     (set-marker-insertion-type marker nil)
     marker))
 
 (defun yas--field-parse-create (snippet &optional parent-field)
-  "Parse most field expressions, except for the simple one \"$n\".
+  "Parse most field expressions in SNIPPET, except for the simple one \"$n\".
 
 The following count as a field:
 
@@ -4037,7 +4056,7 @@ When multiple expressions are found, only the last one 
counts."
               (goto-char (point-min))
               (yas--field-parse-create snippet brand-new-field)))))))
   ;; if we entered from a parent field, now search for the
-  ;; `yas--multi-dollar-lisp-expression-regexp'. THis is used for
+  ;; `yas--multi-dollar-lisp-expression-regexp'. This is used for
   ;; primary field transformations
   ;;
   (when parent-field
@@ -4067,7 +4086,7 @@ When multiple expressions are found, only the last one 
counts."
                   yas--dollar-regions)))))))
 
 (defun yas--transform-mirror-parse-create (snippet)
-  "Parse the \"${n:$(lisp-expression)}\" mirror transformations."
+  "Parse the \"${n:$(lisp-expression)}\" mirror transformations in SNIPPET."
   (while (re-search-forward yas--transform-mirror-regexp nil t)
     (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
            (number (string-to-number (match-string-no-properties 1)))
@@ -4090,7 +4109,7 @@ When multiple expressions are found, only the last one 
counts."
         (push (cons (match-beginning 0) real-match-end-0) 
yas--dollar-regions)))))
 
 (defun yas--simple-mirror-parse-create (snippet)
-  "Parse the simple \"$n\" fields/mirrors/exitmarkers."
+  "Parse the simple \"$n\" fields/mirrors/exitmarkers in SNIPPET."
   (while (re-search-forward yas--simple-mirror-regexp nil t)
     (let ((number (string-to-number (match-string-no-properties 1))))
       (cond ((zerop number)
@@ -4194,7 +4213,7 @@ When multiple expressions are found, only the last one 
counts."
         (yas--advance-end-of-parents-maybe mirror-parent-field (point))))))
 
 (defun yas--field-update-display (field snippet)
-  "Much like `yas--mirror-update-display', but for fields"
+  "Much like `yas--mirror-update-display', but for fields."
   (when (yas--field-transform field)
     (let ((transformed (and (not (eq (yas--field-number field) 0))
                             (yas--apply-transform field field)))
@@ -4247,7 +4266,7 @@ When multiple expressions are found, only the last one 
counts."
 (put 'yas-expand  'function-documentation
      '(yas--expand-from-trigger-key-doc))
 (defun yas--expand-from-trigger-key-doc ()
-  "A doc synthethizer for `yas--expand-from-trigger-key-doc'."
+  "A doc synthesizer for `yas--expand-from-trigger-key-doc'."
   (let ((fallback-description
          (cond ((eq yas-fallback-behavior 'call-other-command)
                 (let* ((yas-minor-mode nil)
@@ -4267,7 +4286,7 @@ object satisfying `yas--field-p' to restrict the 
expansion to.")))
 
 (put 'yas-expand-from-keymap  'function-documentation 
'(yas--expand-from-keymap-doc))
 (defun yas--expand-from-keymap-doc ()
-  "A doc synthethizer for `yas--expand-from-keymap-doc'."
+  "A doc synthesizer for `yas--expand-from-keymap-doc'."
   (add-hook 'temp-buffer-show-hook 'yas--snippet-description-finish-runonce)
   (concat "Expand/run snippets from keymaps, possibly falling back to original 
binding.\n"
           (when (eq this-command 'describe-key)
@@ -4332,6 +4351,7 @@ Remaining args as in `yas-expand-snippet'."
   "Log level for `yas--message' 4 means trace most anything, 0 means nothing.")
 
 (defun yas--message (level message &rest args)
+  "When LEVEL is above `yas-verbosity-level', log MESSAGE and ARGS."
   (when (> yas-verbosity level)
     (message (apply #'yas--format message args))))
 
@@ -4429,7 +4449,7 @@ handle the end-of-buffer error fired in it by calling
                (define-key (symbol-value (make-local-variable 'yas-keymap))
                  k 'self-insert-command))))
 
-;;; Backward compatibility to to yasnippet <= 0.7
+;;; Backward compatibility to yasnippet <= 0.7
 (defvar yas--exported-syms '(;; `defcustom's
                              ;;
                              yas-snippet-dirs
@@ -4540,14 +4560,14 @@ handle the end-of-buffer error fired in it by calling
                              ;; yas-call-with-snippet-dirs
                              ;; yas-with-snippet-dirs
 )
-  "Exported yassnippet symbols.
+  "Exported yasnippet symbols.
 
 i.e. ones that I will try to keep in future yasnippet versions
 and ones that other elisp libraries can more or less safely rely
 upon.")
 
 (defvar yas--dont-backport '(yas-active-keys)
-  "Exported symbols that don't map back to \"yas/*\" variants")
+  "Exported symbols that don't map back to \"yas/*\" variants.")
 
 (dolist (sym (set-difference yas--exported-syms yas--dont-backport))
   (let ((backported (intern (replace-regexp-in-string "^yas-" "yas/" 
(symbol-name sym)))))

commit 49dde5177b019add5ab1b7bb60ba8cbd913e7c35
Author: Roland Walker <address@hidden>
Date:   Mon Nov 5 10:07:46 2012 -0500

    quieten byte-compiler

diff --git a/dropdown-list.el b/dropdown-list.el
index ed4e3dd..bf55ebe 100644
--- a/dropdown-list.el
+++ b/dropdown-list.el
@@ -250,4 +250,5 @@ Use multiple times to bind different COMMANDs to the same 
KEY."
 ;;; dropdown-list.el ends here
 ;; Local Variables:
 ;; coding: utf-8
+;; byte-compile-warnings: (not cl-functions)
 ;; End:
diff --git a/yasnippet.el b/yasnippet.el
index ed6644f..fb977d5 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -136,6 +136,15 @@
 (require 'easymenu)
 (require 'help-mode)
 
+(eval-when-compile
+  (defvar yas--editing-template)
+  (defvar yas--guessed-modes)
+  (defvar yas--indent-original-column)
+  (defvar yas--scheduled-jit-loads)
+  (defvar yas-keymap)
+  (defvar yas-selected-text)
+  (defvar yas-verbosity))
+
 
 ;;; User customizable variables
 
@@ -1849,7 +1858,7 @@ This works by stubbing a few functions, then calling
             (when (file-exists-p elfile)
               (insert ";;; .yas-setup.el support file if any:\n;;;\n")
               (insert-file-contents elfile)
-              (end-of-buffer)
+              (goto-char (point-max))
               )))
          (yas-define-snippets
           (mode snippets)
@@ -4564,4 +4573,5 @@ upon.")
 ;;; yasnippet.el ends here
 ;; Local Variables:
 ;; coding: utf-8
+;; byte-compile-warnings: (not cl-functions)
 ;; End:

commit f7b786f6df6860f0d9c004266b32792dbf59ca47
Merge: 42ed181 a540545
Author: João Távora <address@hidden>
Date:   Mon Nov 5 06:21:34 2012 -0800

    Merge pull request #321 from luismbo/patch-1
    
    Fix: aesthetic fix to README.mdown


commit a5405459456ca6c2c3606f3115b2299d95e3d455
Author: Luís Oliveira <address@hidden>
Date:   Sat Nov 3 14:05:21 2012 +0000

    Aesthetic fix to README.mdown

diff --git a/README.mdown b/README.mdown
index f003bcb..dc10bfb 100644
--- a/README.mdown
+++ b/README.mdown
@@ -1,15 +1,13 @@
 # Intro
 
-**YASnippet** is a template system for Emacs. It allows you to type an
-abbreviation and automatically expand it into function
-templates. Bundled language templates includes: C, C++, C#, Perl,
-Python, Ruby,
-
-SQL, LaTeX, HTML, CSS and more. The snippet syntax is inspired from
-[TextMate's][textmate-snippets] syntax, you can even
-[import][import-docs] most TextMate templates to YASnippet. Watch
-[a demo on YouTube][youtube-demo] or download a
-[higher resolution version][high-res-demo]
+**YASnippet** is a template system for Emacs. It allows you to
+type an abbreviation and automatically expand it into function
+templates. Bundled language templates include: C, C++, C#, Perl,
+Python, Ruby, SQL, LaTeX, HTML, CSS and more. The snippet syntax
+is inspired from [TextMate's][textmate-snippets] syntax, you can
+even [import][import-docs] most TextMate templates to
+YASnippet. Watch [a demo on YouTube][youtube-demo] or download a
+[higher resolution version][high-res-demo].
 
 [textmate-snippets]: http://manual.macromates.com/en/snippets
 [import-docs]: 
http://yasnippet.googlecode.com/svn/trunk/doc/snippet-development.html#importing-textmate-snippets

commit 42ed181f4a4b383da419ec51a93de4a0e4ee3749
Merge: 9503c33 7130d9c
Author: João Távora <address@hidden>
Date:   Sun Sep 23 08:50:08 2012 -0700

    Merge pull request #308 from monsanto/yas-load-snippet-buffer-fix
    
    Fix: "arrayp, nil" bug in yas-load-snippet-buffer.


commit 7130d9c3653a1102df6b3b2f71eff9ddefb2ac11
Author: Christopher Monsanto <address@hidden>
Date:   Sun Sep 23 11:25:24 2012 -0400

    Fix "arrayp, nil" bug in yas-load-snippet-buffer.

diff --git a/yasnippet.el b/yasnippet.el
index c65aa2f..ed6644f 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -2598,11 +2598,10 @@ whether (and where) to save the snippet, then quit the 
window."
                                                     default-file-name)))
           (setf (yas--template-file yas--editing-template) 
buffer-file-name)))))
   (when interactive
-    (quit-window interactive)
     (yas--message 3 "Snippet \"%s\" loaded for %s."
                   (yas--template-name yas--editing-template)
-                  (yas--table-name (yas--template-table 
yas--editing-template)))))
-
+                  (yas--table-name (yas--template-table 
yas--editing-template)))
+    (quit-window interactive)))
 
 (defun yas-tryout-snippet (&optional debug)
   "Test current buffers's snippet template in other buffer."

commit 38db5aa9fbf0f60dce63b83cab8f028bfcd152bd
Author: João Távora <address@hidden>
Date:   Wed Aug 22 22:56:30 2012 +0100

    Refactor: remove horrible 'yas--trigger-key-for-fallback' and rework 
'yas--fallback'

diff --git a/yasnippet.el b/yasnippet.el
index c65aa2f..9535d32 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -2257,18 +2257,15 @@ expand immediately. Common gateway for
                           end
                           (yas--template-expand-env yas--current-template)))))
 
-(defun yas--trigger-key-for-fallback ()
-  ;; When `yas-trigger-key' is <tab> it correctly overrides
-  ;; org-mode's <tab>, for example and searching for fallbacks
-  ;; correctly returns `org-cycle'. However, most other modes bind
-  ;; "TAB" (which is translated from <tab>), and calling
-  ;; (key-binding "TAB") does not place return that command into
-  ;; our command-2 local. So we cheat.
-  ;;
-  (if (string= yas-trigger-key "<tab>")
-      "TAB"
-    yas-trigger-key))
-
+;; Apropos the trigger key and the fallback binding:
+;;
+;; When `yas-trigger-key' is <tab> it correctly overrides
+;; org-mode's <tab>, for example and searching for fallbacks
+;; correctly returns `org-cycle'. However, most other modes bind
+;; "TAB" (which is translated from <tab>), and calling
+;; (key-binding "TAB") does not place return that command into
+;; our command-2 local. So we cheat.
+;;
 (defun yas--fallback (&optional from-trigger-key-p)
   "Fallback after expansion has failed.
 
@@ -2280,25 +2277,13 @@ Common gateway for `yas-expand-from-trigger-key' and
         ((eq yas-fallback-behavior 'call-other-command)
          (let* ((yas-minor-mode nil)
                 (yas--direct-keymaps nil)
-                (yas-trigger-key (yas--trigger-key-for-fallback))
-                (keys-1 (this-command-keys-vector))
-                (keys-2 (and yas-trigger-key
-                             from-trigger-key-p
-                             (stringp yas-trigger-key)
-                             (read-kbd-macro yas-trigger-key)))
-                (command-1 (and keys-1 (key-binding keys-1)))
-                (command-2 (and keys-2 (key-binding keys-2)))
-                ;; An (ugly) safety: prevents infinite recursion of
-                ;; yas-expand* calls.
-                (command (or (and (symbolp command-1)
-                                  (not (string-match "yas-expand" (symbol-name 
command-1)))
-                                  command-1)
-                             (and (symbolp command-2)
-                                  command-2))))
-           (when (and (commandp command)
-                      (not (string-match "yas-expand" (symbol-name command))))
-             (setq this-command command)
-             (call-interactively command))))
+                (keys (this-single-command-keys))
+                (beyond-yasnippet (or (key-binding keys t)
+                                      (key-binding 
(yas--fallback-translate-input keys) t))))
+           (yas--message 4 "Falling back to %s"  beyond-yasnippet)
+           (when (commandp beyond-yasnippet)
+             (setq this-original-command beyond-yasnippet)
+             (call-interactively beyond-yasnippet))))
         ((and (listp yas-fallback-behavior)
               (cdr yas-fallback-behavior)
               (eq 'apply (car yas-fallback-behavior)))
@@ -2312,6 +2297,29 @@ Common gateway for `yas-expand-from-trigger-key' and
          ;; also return nil if all the other fallbacks have failed
          nil)))
 
+(defun yas--fallback-translate-input (keys)
+  "Emulate `read-key-sequence', at least what I think it does.
+
+Keys should be an untranslated key vector. Returns a translated
+vector of keys. XXX not working yet"
+  (let ((retval [])
+        (i 0))
+    (while (< i (length keys))
+      (let ((j i)
+            (translated local-function-key-map))
+        (while (and (< j (length keys))
+                    translated
+                    (keymapp translated))
+          (setq translated (aget (remove 'keymap translated) (aref keys j))
+                j (1+ j)))
+        (setq retval (vconcat retval (cond ((symbolp translated)
+                                            `[,translated])
+                                           ((vectorp translated)
+                                            translated)
+                                           (t
+                                            (substring keys i j)))))
+        (setq i j)))
+    retval))
 
 
 ;;; Utils for snippet development:

commit 9503c332f552e874899ea0ce7801516d4b30bba2
Author: João Távora <address@hidden>
Date:   Wed Aug 22 00:52:17 2012 +0100

    Closes #290: problem when advancing the start of a mirror-in-field
    
    * Rewrote 'yas--update-mirrors'
    * Added unit test
    * Advancing is done exceptionally in 'yas--update-mirrors'
      not 'yas--mirror-update-display' and just before we need to
      re-update the mirror-in-field.
    * Alternative to prior point would be to have fields carry a reference
      to their child mirrors.

diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index 9af244b..62653b0 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -95,6 +95,16 @@
     (should (string= (yas--buffer-contents)
                      "brother from another bla!"))))
 
+(ert-deftest mirrors-adjacent-to-fields-with-nested-mirrors ()
+  (with-temp-buffer)
+  (yas-minor-mode 1)
+  (yas-expand-snippet "<%= f.submit \"${1:Submit}\"${2:$(and (yas-text) \", 
:disable_with => '\")}${2:$1ing...}${2:$(and (yas-text) \"'\")} %>")
+  (should (string= (yas--buffer-contents)
+                   "<%= f.submit \"Submit\", :disable_with => 'Submiting...' 
%>"))
+  (ert-simulate-command `(yas-mock-insert "Send"))
+  (should (string= (yas--buffer-contents)
+                   "<%= f.submit \"Send\", :disable_with => 'Sending...' %>")))
+
 ;; (ert-deftest in-snippet-undo ()
 ;;   (with-temp-buffer
 ;;     (yas-minor-mode 1)
diff --git a/yasnippet.el b/yasnippet.el
index d03f428..c65aa2f 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -4139,27 +4139,39 @@ When multiple expressions are found, only the last one 
counts."
 (defun yas--update-mirrors (snippet)
   "Updates all the mirrors of SNIPPET."
   (save-excursion
-    (let* ((fields (copy-list (yas--snippet-fields snippet)))
-           (field (car fields)))
-      (while field
-        (dolist (mirror (yas--field-mirrors field))
-          (let ((mirror-parent-field (yas--mirror-parent-field mirror)))
-            ;; updatte this mirror
-            ;;
-            (yas--mirror-update-display mirror field)
-            ;; for mirrors-in-fields: schedule a possible
-            ;; parent field for reupdting later on
-            ;;
-            (when mirror-parent-field
-              (add-to-list 'fields mirror-parent-field 'append #'eq))
-            ;; `yas--place-overlays' is needed if the active field and
-            ;; protected overlays have been changed because of insertions
-            ;; in `yas--mirror-update-display'
-            ;;
-            (when (eq field (yas--snippet-active-field snippet))
-              (yas--place-overlays snippet field))))
-        (setq fields (cdr fields))
-        (setq field (car fields))))))
+    (dolist (field-and-mirror (sort
+                               ;; make a list of ((F1 . M1) (F1 . M2) (F2 . 
M3) (F2 . M4) ...)
+                               ;; where F is the field that M is mirroring
+                               ;;
+                               (mapcan #'(lambda (field)
+                                           (mapcar #'(lambda (mirror)
+                                                       (cons field mirror))
+                                                   (yas--field-mirrors field)))
+                                       (yas--snippet-fields snippet))
+                               ;; then sort this list so that entries with 
mirrors with parent
+                               ;; fields appear before. This was important for 
fixing #290, and
+                               ;; luckily also handles the case where a mirror 
in a field causes
+                               ;; another mirror to need reupdating
+                               ;;
+                               #'(lambda (field-and-mirror1 field-and-mirror2)
+                                   (yas--mirror-parent-field (cdr 
field-and-mirror1)))))
+      (let* ((field (car field-and-mirror))
+             (mirror (cdr field-and-mirror))
+             (parent-field (yas--mirror-parent-field mirror)))
+        ;; before updating a mirror with a parent-field, maybe advance
+        ;; its start (#290)
+        ;;
+        (when parent-field
+          (yas--advance-start-maybe mirror (yas--fom-start parent-field)))
+        ;; update this mirror
+        ;;
+        (yas--mirror-update-display mirror field)
+        ;; `yas--place-overlays' is needed if the active field and
+        ;; protected overlays have been changed because of insertions
+        ;; in `yas--mirror-update-display'
+        ;;
+        (when (eq field (yas--snippet-active-field snippet))
+          (yas--place-overlays snippet field))))))
 
 (defun yas--mirror-update-display (mirror field)
   "Update MIRROR according to FIELD (and mirror transform)."

commit 8a26ab0a3180b0df2264518ff31dd19564727ba2
Author: João Távora <address@hidden>
Date:   Sun Aug 19 13:51:33 2012 +0100

    Closes #277: add new `yas-active-keys` (for auto-complete)
    
    Also documented and reviewed related functionality slightly.
    commit 51b182104b

diff --git a/yasnippet.el b/yasnippet.el
index 393c25e..d03f428 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1257,13 +1257,13 @@ the template of a snippet in the current snippet-table."
 
 
 (defun yas--table-all-keys (table)
-  (when table
-    (let ((acc))
-      (maphash #'(lambda (key namehash)
-                   (when (yas--filter-templates-by-condition 
(yas--namehash-templates-alist namehash))
-                     (push key acc)))
-               (yas--table-hash table))
-      acc)))
+  "Get trigger keys of all active snippets in TABLE"
+  (let ((acc))
+    (maphash #'(lambda (key namehash)
+                 (when (yas--filter-templates-by-condition 
(yas--namehash-templates-alist namehash))
+                   (push key acc)))
+             (yas--table-hash table))
+    acc))
 
 (defun yas--table-mode (table)
   (intern (yas--table-name table)))
@@ -2317,7 +2317,7 @@ Common gateway for `yas-expand-from-trigger-key' and
 ;;; Utils for snippet development:
 
 (defun yas--all-templates (tables)
-  "Return all snippet tables applicable for the current buffer.
+  "Get `yas--template' objects in TABLES, applicable for buffer and point.
 
 Honours `yas-choose-tables-first', `yas-choose-keys-first' and
 `yas-buffer-local-condition'"
@@ -2641,6 +2641,11 @@ whether (and where) to save the snippet, then quit the 
window."
           (t
            (yas--message 3 "Cannot test snippet for unknown major mode")))))
 
+(defun yas-active-keys ()
+  "Return all active trigger keys for current buffer and point"
+  (remove-duplicates (mapcan #'yas--table-all-keys (yas--get-snippet-tables))
+                     :test #'string=))
+
 (defun yas--template-fine-group (template)
   (car (last (or (yas--template-group template)
                  (yas--template-perm-group template)))))
@@ -4507,6 +4512,7 @@ handle the end-of-buffer error fired in it by calling
                              yas-unimplemented
                              yas-define-condition-cache
                              yas-hippie-try-expand
+                             yas-active-keys
 
                              ;; debug definitions
                              ;; yas-debug-snippet-vars
@@ -4522,9 +4528,17 @@ handle the end-of-buffer error fired in it by calling
                              ;; yas-saving-variables
                              ;; yas-call-with-snippet-dirs
                              ;; yas-with-snippet-dirs
-))
+)
+  "Exported yassnippet symbols.
+
+i.e. ones that I will try to keep in future yasnippet versions
+and ones that other elisp libraries can more or less safely rely
+upon.")
+
+(defvar yas--dont-backport '(yas-active-keys)
+  "Exported symbols that don't map back to \"yas/*\" variants")
 
-(dolist (sym yas--exported-syms)
+(dolist (sym (set-difference yas--exported-syms yas--dont-backport))
   (let ((backported (intern (replace-regexp-in-string "^yas-" "yas/" 
(symbol-name sym)))))
     (when (boundp sym)
       (make-obsolete-variable backported sym "yasnippet 0.8")

commit 08c6dd44b340fe0b19352879faffc777a7a4ed93
Author: João Távora <address@hidden>
Date:   Sun Aug 19 13:46:34 2012 +0100

    Fix: arrgh remove the ^M line-endings again

diff --git a/yasnippet.el b/yasnippet.el
index 7c763f4..393c25e 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1,4542 +1,4542 @@
-;;; yasnippet.el --- Yet another snippet extension for Emacs.
-
-;; Copyright (C) 2008-2012 Free Software Foundation, Inc.
-;; Authors: pluskid <address@hidden>,  João Távora <address@hidden>
-;; Version: 0.8.0
-;; Package-version: 0.8.0
-;; X-URL: http://github.com/capitaomorte/yasnippet
-;; Keywords: convenience, emulation
-;; URL: http://github.com/capitaomorte/yasnippet
-;; EmacsWiki: YaSnippetMode
-
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;;   Basic steps to setup:
-;;
-;;    (add-to-list 'load-path
-;;                 "~/path-to-yasnippet")
-;;    (require 'yasnippet)
-;;    (yas-global-mode 1)
-;;
-;;
-;;   Interesting variables are:
-;;
-;;       `yas-snippet-dirs'
-;;
-;;           The directory where user-created snippets are to be
-;;           stored. Can also be a list of directories. In that case,
-;;           when used for bulk (re)loading of snippets (at startup or
-;;           via `yas-reload-all'), directories appearing earlier in
-;;           the list shadow other dir's snippets. Also, the first
-;;           directory is taken as the default for storing the user's
-;;           new snippets.
-;;
-;;           The deprecated `yas/root-directory' aliases this variable
-;;           for backward-compatibility.
-;;
-;;       `yas-extra-modes'
-;;
-;;           A local variable that you can set in a hook to override
-;;           snippet-lookup based on major mode. It is a a symbol (or
-;;           list of symbols) that correspond to subdirectories of
-;;           `yas-snippet-dirs' and is used for deciding which
-;;           snippets to consider for the active buffer.
-;;
-;;           Deprecated `yas/mode-symbol' aliases this variable for
-;;           backward-compatibility.
-;;
-;;   Major commands are:
-;;
-;;       M-x yas-expand
-;;
-;;           Try to expand snippets before point.  In `yas-minor-mode',
-;;           this is bound to `yas-trigger-key' which you can customize.
-;;
-;;       M-x yas-load-directory
-;;
-;;           Prompts you for a directory hierarchy of snippets to load.
-;;
-;;       M-x yas-insert-snippet
-;;
-;;           Prompts you for possible snippet expansion if that is
-;;           possible according to buffer-local and snippet-local
-;;           expansion conditions.  With prefix argument, ignore these
-;;           conditions.
-;;
-;;       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.
-;;
-;;       M-x yas-new-snippet
-;;
-;;           Lets you create a new snippet file in the correct
-;;           subdirectory of `yas-snippet-dirs', according to the
-;;           active major mode.
-;;
-;;       M-x yas-load-snippet-buffer
-;;
-;;           When editing a snippet, this loads the snippet.  This is
-;;           bound to "C-c C-c" while in the `snippet-mode' editing
-;;           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'.
-;;
-;;       M-x yas-describe-tables
-;;
-;;           Lists known snippets in a separate buffer. User is
-;;           prompted as to whether only the currently active tables
-;;           are to be displayed, or all the tables for all major
-;;           modes.
-;;
-;;   The `dropdown-list.el' extension is bundled with YASnippet, you
-;;   can optionally use it the preferred "prompting method", puting in
-;;   your .emacs file, for example:
-;;
-;;       (require 'dropdown-list)
-;;       (setq yas-prompt-functions '(yas-dropdown-prompt
-;;                                    yas-ido-prompt
-;;                                    yas-completing-prompt))
-;;
-;;   Also check out the customization group
-;;
-;;        M-x customize-group RET yasnippet RET
-;;
-;;   If you use the customization group to set variables
-;;   `yas-snippet-dirs' or `yas-global-mode', make sure the path to
-;;   "yasnippet.el" is present in the `load-path' *before* the
-;;   `custom-set-variables' is executed in your .emacs file.
-;;
-;;   For more information and detailed usage, refer to the project page:
-;;      http://github.com/capitaomorte/yasnippet
-
-;;; Code:
-
-(require 'cl)
-(require 'easymenu)
-(require 'help-mode)
-
-
-;;; User customizable variables
-
-(defgroup yasnippet nil
-  "Yet Another Snippet extension"
-  :group 'editing)
-
-(defvar yas--load-file-name load-file-name
-  "Store the filename that yasnippet.el was originally loaded from.")
-
-(defcustom yas-snippet-dirs (remove nil
-                                    (list "~/.emacs.d/snippets"
-                                          (when yas--load-file-name
-                                            (concat (file-name-directory 
yas--load-file-name) "snippets"))))
-  "Directory or list of snippet dirs for each major mode.
-
-The directory where user-created snippets are to be stored. Can
-also be a list of directories. In that case, when used for
-bulk (re)loading of snippets (at startup or via
-`yas-reload-all'), directories appearing earlier in the list
-shadow other dir's snippets. Also, the first directory is taken
-as the default for storing the user's new snippets."
-  :type '(choice (string :tag "Single directory (string)")
-                 (repeat :args (string) :tag "List of directories (strings)"))
-  :group 'yasnippet
-  :require 'yasnippet
-  :set #'(lambda (symbol new)
-           (let ((old (and (boundp symbol)
-                           (symbol-value symbol))))
-             (set-default symbol new)
-             (unless (or (not (fboundp 'yas-reload-all))
-                         (equal old new))
-               (yas-reload-all)))))
-
-(defun yas-snippet-dirs ()
-  "Returns `yas-snippet-dirs' (which see) as a list."
-  (if (listp yas-snippet-dirs) yas-snippet-dirs (list yas-snippet-dirs)))
-
-(defvaralias 'yas/root-directory 'yas-snippet-dirs)
-
-(defcustom yas-prompt-functions '(yas-x-prompt
-                                  yas-dropdown-prompt
-                                  yas-completing-prompt
-                                  yas-ido-prompt
-                                  yas-no-prompt)
-  "Functions to prompt for keys, templates, etc interactively.
-
-These functions are called with the following arguments:
-
-- PROMPT: A string to prompt the user
-
-- CHOICES: a list of strings or objects.
-
-- optional DISPLAY-FN : A function that, when applied to each of
-the objects in CHOICES will return a string.
-
-The return value of any function you put here should be one of
-the objects in CHOICES, properly formatted with DISPLAY-FN (if
-that is passed).
-
-- To signal that your particular style of prompting is
-unavailable at the moment, you can also have the function return
-nil.
-
-- To signal that the user quit the prompting process, you can
-signal `quit' with
-
-  (signal 'quit \"user quit!\")."
-  :type '(repeat function)
-  :group 'yasnippet)
-
-(defcustom yas-indent-line 'auto
-  "Controls indenting applied to a recent snippet expansion.
-
-The following values are possible:
-
-- `fixed' Indent the snippet to the current column;
-
-- `auto' Indent each line of the snippet with `indent-according-to-mode'
-
-Every other value means don't apply any snippet-side indendation
-after expansion (the manual per-line \"$>\" indentation still
-applies)."
-  :type '(choice (const :tag "Nothing"  nothing)
-                 (const :tag "Fixed"    fixed)
-                 (const :tag "Auto"     auto))
-  :group 'yasnippet)
-
-(defcustom yas-also-auto-indent-first-line nil
-  "Non-nil means also auto indent first line according to mode.
-
-Naturally this is only valid when `yas-indent-line' is `auto'"
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-snippet-revival t
-  "Non-nil means re-activate snippet fields after undo/redo."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-trigger-key "<tab>"
-  "The key bound to `yas-expand' when `yas-minor-mode' is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'."
-  :type 'string
-  :group 'yasnippet
-  :set #'(lambda (symbol key)
-           (let ((old (and (boundp symbol)
-                           (symbol-value symbol))))
-             (set-default symbol key)
-             ;; On very first loading of this defcustom,
-             ;; `yas-trigger-key' is *not* loaded.
-             (if (fboundp 'yas--trigger-key-reload)
-                 (yas--trigger-key-reload old)))))
-
-(defcustom yas-next-field-key '("TAB" "<tab>")
-  "The key to navigate to next field when a snippet is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-
-(defcustom yas-prev-field-key '("<backtab>" "<S-tab>")
-  "The key to navigate to previous field when a snippet is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-(defcustom yas-skip-and-clear-key '("C-d" "<delete>" "<deletechar>")
-  "The key to clear the currently active field.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-(defcustom yas-triggers-in-field nil
-  "If non-nil, `yas-next-field-key' can trigger stacked expansions.
-
-Otherwise, `yas-next-field-key' just tries to move on to the next
-field"
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-fallback-behavior 'call-other-command
-  "How to act when `yas-trigger-key' does *not* expand a snippet.
-
-- `call-other-command' means try to temporarily disable YASnippet
-    and call the next command bound to `yas-trigger-key'.
-
-- nil or the symbol `return-nil' mean do nothing. (and
-  `yas-expand' returns nil)
-
-- A lisp form (apply COMMAND . ARGS) means interactively call
-  COMMAND, if ARGS is non-nil, call COMMAND non-interactively
-  with ARGS as arguments."
-  :type '(choice (const :tag "Call previous command"  call-other-command)
-                 (const :tag "Do nothing"             return-nil))
-  :group 'yasnippet)
-
-(defcustom yas-choose-keys-first nil
-  "If non-nil, prompt for snippet key first, then for template.
-
-Otherwise prompts for all possible snippet names.
-
-This affects `yas-insert-snippet' and `yas-visit-snippet-file'."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-choose-tables-first nil
-  "If non-nil, and multiple eligible snippet tables, prompts user for tables 
first.
-
-Otherwise, user chooses between the merging together of all
-eligible tables.
-
-This affects `yas-insert-snippet', `yas-visit-snippet-file'"
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-use-menu 'abbreviate
-  "Display a YASnippet menu in the menu bar.
-
-When non-nil, submenus for each snippet table will be listed
-under the menu \"Yasnippet\".
-
-- If set to `abbreviate', only the current major-mode
-menu and the modes set in `yas-extra-modes' are listed.
-
-- If set to `full', every submenu is listed
-
-- It set to nil, don't display a menu at all (this requires a
-  `yas-reload-all' call if the menu is already visible).
-
-Any other non-nil value, every submenu is listed."
-  :type '(choice (const :tag "Full"  full)
-                 (const :tag "Abbreviate" abbreviate)
-                 (const :tag "No menu" nil))
-  :group 'yasnippet)
-
-(defcustom yas-trigger-symbol (if (eq window-system 'mac)
-                                  (char-to-string ?\x21E5) ;; little ->| sign
-                                  " =>")
-  "The text that will be used in menu to represent the trigger."
-  :type 'string
-  :group 'yasnippet)
-
-(defcustom yas-wrap-around-region nil
-  "If non-nil, snippet expansion wraps around selected region.
-
-The wrapping occurs just before the snippet's exit marker.  This
-can be overriden on a per-snippet basis."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-good-grace t
-  "If non-nil, don't raise errors in inline elisp evaluation.
-
-An error string \"[yas] error\" is returned instead."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-visit-from-menu nil
-  "If non-nil visit snippets's files from menu, instead of expanding them.
-
-This cafn only work when snippets are loaded from files."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-expand-only-for-last-commands nil
-  "List of `last-command' values to restrict tab-triggering to, or nil.
-
-Leave this set at nil (the default) to be able to trigger an
-expansion simply by placing the cursor after a valid tab trigger,
-using whichever commands.
-
-Optionallly, set this to something like '(self-insert-command) if
-you to wish restrict expansion to only happen when the last
-letter of the snippet tab trigger was typed immediately before
-the trigger key itself."
-  :type '(repeat function)
-  :group 'yasnippet)
-
-;; Only two faces, and one of them shouldn't even be used...
-;;
-(defface yas-field-highlight-face
-  '((t (:inherit 'region)))
-  "The face used to highlight the currently active field of a snippet"
-  :group 'yasnippet)
-
-(defface yas--field-debug-face
-  '()
-  "The face used for debugging some overlays normally hidden"
-  :group 'yasnippet)
-
-
-;;; User can also customize the next defvars
-
-(defun yas--define-some-keys (keys keymap definition)
-  "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'."
-  (let ((keys (or (and (listp keys) keys)
-                  (list keys))))
-    (dolist (key keys)
-      (define-key keymap (read-kbd-macro key) definition))))
-
-(defun yas--init-yas-in-snippet-keymap ()
-  (setq yas-keymap
-        (let ((map (make-sparse-keymap)))
-          (mapc #'(lambda (binding)
-                    (yas--define-some-keys (car binding) map (cdr binding)))
-                `((,yas-next-field-key     . yas-next-field-or-maybe-expand)
-                  (,yas-prev-field-key     . yas-prev-field)
-                  ("C-g"                   . yas-abort-snippet)
-                  (,yas-skip-and-clear-key . 
yas-skip-and-clear-or-delete-char)))
-          map)))
-
-(defvar yas-keymap (yas--init-yas-in-snippet-keymap)
-  "The keymap active while a snippet expansion is in progress.")
-
-(defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ")
-  "List of character syntaxes used to find a trigger key before point.
-The list is tried in the order while scanning characters
-backwards from point. For example, if the list is '(\"w\" \"w_\")
-first look for trigger keys which are composed exclusively of
-\"word\"-syntax characters, and then, if that fails, look for
-keys which are either of \"word\" or \"symbol\"
-syntax. Triggering after
-
-foo-bar
-
-will, according to the \"w\" element first try \"bar\". If that
-isn't a trigger key, \"foo-bar\" is tried, respecting a second
-\"w_\" element.")
-
-(defvar yas-after-exit-snippet-hook
-  '()
-  "Hooks to run after a snippet exited.
-
-The hooks will be run in an environment where some variables bound to
-proper values:
-
-`yas-snippet-beg' : The beginning of the region of the snippet.
-
-`yas-snippet-end' : Similar to beg.
-
-Attention: These hooks are not run when exiting nested/stackd snippet 
expansion!")
-
-(defvar yas-before-expand-snippet-hook
-  '()
-  "Hooks to run just before expanding a snippet.")
-
-(defvar yas-buffer-local-condition
-  '(if (and (or (fourth (syntax-ppss))
-                (fifth (syntax-ppss)))
-            (eq (symbol-function this-command) 'yas-expand-from-trigger-key))
-       '(require-snippet-condition . force-in-comment)
-     t)
-  "Snippet expanding condition.
-
-This variable is a lisp form which is evaluated everytime a
-snippet expansion is attemped:
-
-    * If it evaluates to nil, no snippets can be expanded.
-
-    * If it evaluates to the a cons (require-snippet-condition
-      . REQUIREMENT)
-
-       * Snippets bearing no \"# condition:\" directive are not
-         considered
-
-       * Snippets bearing conditions that evaluate to nil (or
-         produce an error) won't be onsidered.
-
-       * If the snippet has a condition that evaluates to non-nil
-         RESULT:
-
-          * If REQUIREMENT is t, the snippet is considered
-
-          * If REQUIREMENT is `eq' RESULT, the snippet is
-            considered
-
-          * Otherwise, the snippet is not considered.
-
-    * If it evaluates to the symbol 'always, all snippets are
-      considered for expansion, regardless of any conditions.
-
-    * If it evaluates to t or some other non-nil value
-
-       * Snippet bearing no conditions, or conditions that
-         evaluate to non-nil, are considered for expansion.
-
-       * Otherwise, the snippet is not considered.
-
-Here's an example preventing snippets from being expanded from
-inside comments, in `python-mode' only, with the exception of
-snippets returning the symbol 'force-in-comment in their
-conditions.
-
- (add-hook 'python-mode-hook
-           '(lambda ()
-              (setq yas-buffer-local-condition
-                    '(if (python-in-string/comment)
-                         '(require-snippet-condition . force-in-comment)
-                       t))))
-
-The default value is similar, it filters out potential snippet
-expansions inside comments and string literals, unless the
-snippet itself contains a condition that returns the symbol
-`force-in-comment'.")
-
-
-;;; Internal variables
-
-(defvar yas--version "0.8.0 (beta)")
-
-(defvar yas--menu-table (make-hash-table)
-  "A hash table of MAJOR-MODE symbols to menu keymaps.")
-
-(defvar yas--known-modes
-  '(ruby-mode rst-mode markdown-mode)
-  "A list of mode which is well known but not part of emacs.")
-
-(defvar yas--escaped-characters
-  '(?\\ ?` ?\" ?' ?$ ?} ?{ ?\( ?\))
-  "List of characters which *might* need to be escaped.")
-
-(defconst yas--field-regexp
-  "${\\([0-9]+:\\)?\\([^}]*\\)}"
-  "A regexp to *almost* recognize a field.")
-
-(defconst yas--multi-dollar-lisp-expression-regexp
-  "$+[ \t\n]*\\(([^)]*)\\)"
-  "A regexp to *almost* recognize a \"$(...)\" expression.")
-
-(defconst yas--backquote-lisp-expression-regexp
-  "`\\([^`]*\\)`"
-  "A regexp to recognize a \"`lisp-expression`\" expression." )
-
-(defconst yas--transform-mirror-regexp
-  "${\\(?:\\([0-9]+\\):\\)?$\\([ \t\n]*([^}]*\\)"
-  "A regexp to *almost* recognize a mirror with a transform.")
-
-(defconst yas--simple-mirror-regexp
-  "$\\([0-9]+\\)"
-  "A regexp to recognize a simple mirror.")
-
-(defvar yas--snippet-id-seed 0
-  "Contains the next id for a snippet.")
-
-(defun yas--snippet-next-id ()
-  (let ((id yas--snippet-id-seed))
-    (incf yas--snippet-id-seed)
-    id))
-
-
-;;; Minor mode stuff
-
-;; XXX: `last-buffer-undo-list' is somehow needed in Carbon Emacs for MacOSX
-(defvar last-buffer-undo-list nil)
-
-(defvar yas--minor-mode-menu nil
-  "Holds the YASnippet menu")
-
-(defun yas--init-minor-keymap ()
-  (let ((map (make-sparse-keymap)))
-    (when yas-use-menu
-      (easy-menu-define yas--minor-mode-menu
-      map
-      "Menu used when `yas-minor-mode' is active."
-      '("YASnippet"
-        "----"
-        ["Expand trigger" yas-expand
-         :help "Possibly expand tab trigger before point"]
-        ["Insert at point..." yas-insert-snippet
-         :help "Prompt for an expandable snippet and expand it at point"]
-        ["New snippet..." yas-new-snippet
-         :help "Create a new snippet in an appropriate directory"]
-        ["Visit snippet file..." yas-visit-snippet-file
-         :help "Prompt for an expandable snippet and find its file"]
-        "----"
-        ("Snippet menu behaviour"
-         ["Visit snippets" (setq yas-visit-from-menu t)
-          :help "Visit snippets from the menu"
-          :active t :style radio   :selected yas-visit-from-menu]
-         ["Expand snippets" (setq yas-visit-from-menu nil)
-          :help "Expand snippets from the menu"
-          :active t :style radio :selected (not yas-visit-from-menu)]
-         "----"
-         ["Show all known modes" (setq yas-use-menu 'full)
-          :help "Show one snippet submenu for each loaded table"
-          :active t :style radio   :selected (eq yas-use-menu 'full)]
-         ["Abbreviate according to current mode" (setq yas-use-menu 
'abbreviate)
-          :help "Show only snippet submenus for the current active modes"
-          :active t :style radio   :selected (eq yas-use-menu 'abbreviate)])
-        ("Indenting"
-         ["Auto" (setq yas-indent-line 'auto)
-          :help "Indent each line of the snippet with 
`indent-according-to-mode'"
-          :active t :style radio   :selected (eq yas-indent-line 'auto)]
-         ["Fixed" (setq yas-indent-line 'fixed)
-          :help "Indent the snippet to the current column"
-          :active t :style radio   :selected (eq yas-indent-line 'fixed)]
-         ["None" (setq yas-indent-line 'none)
-          :help "Don't apply any particular snippet indentation after 
expansion"
-          :active t :style radio   :selected (not (member yas-indent-line 
'(fixed auto)))]
-         "----"
-         ["Also auto indent first line" (setq yas-also-auto-indent-first-line
-                                              (not 
yas-also-auto-indent-first-line))
-          :help "When auto-indenting also, auto indent the first line menu"
-          :active (eq yas-indent-line 'auto)
-          :style toggle :selected yas-also-auto-indent-first-line]
-         )
-        ("Prompting method"
-         ["System X-widget" (setq yas-prompt-functions
-                                  (cons 'yas-x-prompt
-                                        (remove 'yas-x-prompt
-                                                yas-prompt-functions)))
-          :help "Use your windowing system's (gtk, mac, windows, etc...) 
default menu"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-x-prompt)]
-         ["Dropdown-list" (setq yas-prompt-functions
-                                (cons 'yas-dropdown-prompt
-                                      (remove 'yas-dropdown-prompt
-                                              yas-prompt-functions)))
-          :help "Use a special dropdown list"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-dropdown-prompt)]
-         ["Ido" (setq yas-prompt-functions
-                      (cons 'yas-ido-prompt
-                            (remove 'yas-ido-prompt
-                                    yas-prompt-functions)))
-          :help "Use an ido-style minibuffer prompt"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-ido-prompt)]
-         ["Completing read" (setq yas-prompt-functions
-                                  (cons 'yas-completing-prompt
-                                        (remove 'yas-completing-prompt
-                                                yas-prompt-functions)))
-          :help "Use a normal minibuffer prompt"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-completing-prompt)]
-         )
-        ("Misc"
-         ["Wrap region in exit marker"
-          (setq yas-wrap-around-region
-                (not yas-wrap-around-region))
-          :help "If non-nil automatically wrap the selected text in the $0 
snippet exit"
-          :style toggle :selected yas-wrap-around-region]
-         ["Allow stacked expansions "
-          (setq yas-triggers-in-field
-                (not yas-triggers-in-field))
-          :help "If non-nil allow snippets to be triggered inside other 
snippet fields"
-          :style toggle :selected yas-triggers-in-field]
-         ["Revive snippets on undo "
-          (setq yas-snippet-revival
-                (not yas-snippet-revival))
-          :help "If non-nil allow snippets to become active again after undo"
-          :style toggle :selected yas-snippet-revival]
-         ["Good grace "
-          (setq yas-good-grace
-                (not yas-good-grace))
-          :help "If non-nil don't raise errors in bad embedded eslip in 
snippets"
-          :style toggle :selected yas-good-grace]
-         )
-        "----"
-        ["Load snippets..."  yas-load-directory
-         :help "Load snippets from a specific directory"]
-        ["Reload everything" yas-reload-all
-         :help "Cleanup stuff, reload snippets, rebuild menus"]
-        ["About"            yas-about
-         :help "Display some information about YASsnippet"])))
-
-    ;; Now for the stuff that has direct keybindings
-    ;;
-    (define-key map "\C-c&\C-s" 'yas-insert-snippet)
-    (define-key map "\C-c&\C-n" 'yas-new-snippet)
-    (define-key map "\C-c&\C-v" 'yas-visit-snippet-file)
-    map))
-
-(defvar yas-minor-mode-map (yas--init-minor-keymap)
-  "The keymap used when `yas-minor-mode' is active.")
-
-(defun yas--trigger-key-reload (&optional unbind-key)
-  "Rebind `yas-expand' to the new value of `yas-trigger-key'.
-
-With optional UNBIND-KEY, try to unbind that key from
-`yas-minor-mode-map'."
-  (when (and unbind-key
-             (stringp unbind-key)
-             (not (string= unbind-key "")))
-    (define-key yas-minor-mode-map (read-kbd-macro unbind-key) nil))
-  (when  (and yas-trigger-key
-              (stringp yas-trigger-key)
-              (not (string= yas-trigger-key "")))
-    (define-key yas-minor-mode-map (read-kbd-macro yas-trigger-key) 
'yas-expand)))
-
-(defvar yas--tables (make-hash-table)
-  "A hash table of mode symbols to `yas--table' objects.")
-
-(defvar yas--parents (make-hash-table)
-  "A hash table of mode symbols do lists of direct parent mode symbols.
-
-This list is populated when reading the \".yas-parents\" files
-found when traversing snippet directories with
-`yas-load-directory'.
-
-There might be additionalal parenting information stored in the
-`derived-mode-parent' property of some mode symbols, but that is
-not recorded here.")
-
-(defvar yas--direct-keymaps (list)
-  "Keymap alist supporting direct snippet keybindings.
-
-This variable is is placed in `emulation-mode-map-alists'.
-
-Its elements looks like (TABLE-NAME . KEYMAP). They're
-instantiated on `yas-reload-all' but KEYMAP is added to only when
-loading snippets. `yas--direct-TABLE-NAME' is then a variable set
-buffer-locally when entering `yas-minor-mode'. KEYMAP binds all
-defined direct keybindings to the command
-`yas-expand-from-keymap' which then which snippet to expand.")
-
-(defun yas-direct-keymaps-reload ()
-  "Force reload the direct keybinding for active snippet tables."
-  (interactive)
-  (setq yas--direct-keymaps nil)
-  (maphash #'(lambda (name table)
-               (push (cons (intern (format "yas--direct-%s" name))
-                           (yas--table-direct-keymap table))
-                     yas--direct-keymaps))
-           yas--tables))
-
-(defun yas--modes-to-activate ()
-  "Compute list of mode symbols that are active for `yas-expand'
-and friends."
-  (let ((modes-to-activate (list major-mode))
-        (mode major-mode))
-    (while (setq mode (get mode 'derived-mode-parent))
-      (push mode modes-to-activate))
-    (dolist (mode (yas-extra-modes))
-      (push mode modes-to-activate))
-    (remove-duplicates
-     (append modes-to-activate
-             (mapcan #'(lambda (mode)
-                         (yas--all-parents mode))
-                     modes-to-activate)))))
-
-(defvar yas-minor-mode-hook nil
-  "Hook run when yas-minor-mode is turned on")
-
-;;;###autoload
-(define-minor-mode yas-minor-mode
-  "Toggle YASnippet mode.
-
-When YASnippet mode is enabled, the `yas-trigger-key' key expands
-snippets of code depending on the major mode.
-
-With no argument, this command toggles the mode.
-positive prefix argument turns on the mode.
-Negative prefix argument turns off the mode.
-
-You can customize the key through `yas-trigger-key'.
-
-Key bindings:
-\\{yas-minor-mode-map}"
-  nil
-  ;; The indicator for the mode line.
-  " yas"
-  :group 'yasnippet
-  (cond (yas-minor-mode
-         ;; Reload the trigger key
-         ;;
-         (yas--trigger-key-reload)
-         ;; Install the direct keymaps in `emulation-mode-map-alists'
-         ;; (we use `add-hook' even though it's not technically a hook,
-         ;; but it works). Then define variables named after modes to
-         ;; index `yas--direct-keymaps'.
-         ;;
-         ;; Also install the post-command-hook.
-         ;;
-         (add-hook 'emulation-mode-map-alists 'yas--direct-keymaps)
-         (add-hook 'post-command-hook 'yas--post-command-handler nil t)
-         ;; Set the `yas--direct-%s' vars for direct keymap expansion
-         ;;
-         (dolist (mode (yas--modes-to-activate))
-           (let ((name (intern (format "yas--direct-%s" mode))))
-             (set-default name nil)
-             (set (make-local-variable name) t)))
-         ;; Perform JIT loads
-         ;;
-         (yas--load-pending-jits))
-        (t
-         ;; Uninstall the direct keymaps and the post-command hook
-         ;;
-         (remove-hook 'post-command-hook 'yas--post-command-handler t)
-         (remove-hook 'emulation-mode-map-alists 'yas--direct-keymaps))))
-
-(defvar yas--dont-activate '(minibufferp)
-  "If non-nil don't let `yas-minor-mode-on' active yas for this buffer.
-
-If a function, then its result is used.
-
-If a list of functions, then all functions must return nil to
-activate yas for this buffer.
-
-`yas-minor-mode-on' is usually called by `yas-global-mode' so
-this effectively lets you define exceptions to the \"global\"
-behaviour. Can also be a function of zero arguments.")
-(make-variable-buffer-local 'yas--dont-activate)
-
-(defun yas-minor-mode-on ()
-  "Turn on YASnippet minor mode.
-
-Do this unless `yas--dont-activate' is truish "
-  (interactive)
-  (unless (cond ((functionp yas--dont-activate)
-                 (funcall yas--dont-activate))
-                ((consp yas--dont-activate)
-                 (some #'funcall yas--dont-activate))
-                (yas--dont-activate))
-    ;; Load all snippets definitions unless we still don't have a
-    ;; root-directory or some snippets have already been loaded.
-    ;;
-    (yas-minor-mode 1)))
-
-;;;###autoload
-(define-globalized-minor-mode yas-global-mode yas-minor-mode yas-minor-mode-on
-  :group 'yasnippet
-  :require 'yasnippet)
-
-(defun yas--global-mode-reload-with-jit-maybe ()
-  (when yas-global-mode (yas-reload-all)))
-
-(add-hook 'yas-global-mode-hook 'yas--global-mode-reload-with-jit-maybe)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Major mode stuff
-;;
-(defvar yas--font-lock-keywords
-  (append '(("^#.*$" . font-lock-comment-face))
-          lisp-font-lock-keywords
-          lisp-font-lock-keywords-1
-          lisp-font-lock-keywords-2
-          '(("$\\([0-9]+\\)"
-             (0 font-lock-keyword-face)
-             (1 font-lock-string-face t))
-            ("${\\([0-9]+\\):?"
-             (0 font-lock-keyword-face)
-             (1 font-lock-warning-face t))
-            ("${" font-lock-keyword-face)
-            ("$[0-9]+?" font-lock-preprocessor-face)
-            ("\\(\\$(\\)" 1 font-lock-preprocessor-face)
-            ("}"
-             (0 font-lock-keyword-face)))))
-
-(defun yas--init-major-keymap ()
-  (let ((map (make-sparse-keymap)))
-    (easy-menu-define nil
-      map
-      "Menu used when snippet-mode is active."
-      (cons "Snippet"
-            (mapcar #'(lambda (ent)
-                        (when (third ent)
-                          (define-key map (third ent) (second ent)))
-                        (vector (first ent) (second ent) t))
-                    (list
-                     (list "Load this snippet" 'yas-load-snippet-buffer 
"\C-c\C-c")
-                     (list "Try out this snippet" 'yas-tryout-snippet 
"\C-c\C-t")))))
-    map))
-
-(defvar snippet-mode-map
-  (yas--init-major-keymap)
-  "The keymap used when `snippet-mode' is active")
-
-
-(define-derived-mode snippet-mode text-mode "Snippet"
-  "A mode for editing yasnippets"
-  (setq font-lock-defaults '(yas--font-lock-keywords))
-  (set (make-local-variable 'require-final-newline) nil)
-  (set (make-local-variable 'comment-start) "#")
-  (set (make-local-variable 'comment-start-skip) "#+[\t ]*"))
-
-
-
-;;; Internal structs for template management
-
-(defstruct (yas--template (:constructor yas--make-blank-template))
-  "A template for a snippet."
-  key
-  content
-  name
-  condition
-  expand-env
-  file
-  keybinding
-  uuid
-  menu-binding-pair
-  group      ;; as dictated by the #group: directive or .yas-make-groups
-  perm-group ;; as dictated by `yas-define-menu'
-  table
-  )
-
-(defun yas--populate-template (template &rest args)
-  "Helper function to populate a template with properties"
-  (let (p v)
-    (while args
-      (aset template
-            (position (intern (substring (symbol-name (car args)) 1))
-                      (mapcar #'car (get 'yas--template 'cl-struct-slots)))
-            (second args))
-      (setq args (cddr args)))
-    template))
-
-(defstruct (yas--table (:constructor yas--make-snippet-table (name)))
-  "A table to store snippets for a particular mode.
-
-Has the following fields:
-
-`yas--table-name'
-
-  A symbol name normally corresponding to a major mode, but can
-  also be a pseudo major-mode to be referenced in
-  `yas-extra-modes', for example.
-
-`yas--table-hash'
-
-  A hash table (KEY . NAMEHASH), known as the \"keyhash\". KEY is
-  a string or a vector, where the former is the snippet's trigger
-  and the latter means it's a direct keybinding. NAMEHASH is yet
-  another hash of (NAME . TEMPLATE) where NAME is the snippet's
-  name and TEMPLATE is a `yas--template' object.
-
-`yas--table-direct-keymap'
-
-  A keymap for the snippets in this table that have direct
-  keybindings. This is kept in sync with the keyhash, i.e., all
-  the elements of the keyhash that are vectors appear here as
-  bindings to `yas-expand-from-keymap'.
-
-`yas--table-uuidhash'
-
-  A hash table mapping snippets uuid's to the same `yas--template'
-  objects. A snippet uuid defaults to the snippet's name.
-"
-  name
-  (hash (make-hash-table :test 'equal))
-  (uuidhash (make-hash-table :test 'equal))
-  (parents nil)
-  (direct-keymap (make-sparse-keymap)))
-
-(defun yas--get-template-by-uuid (mode uuid)
-  "Find the snippet template in MODE by its UUID."
-  (let* ((table (gethash mode yas--tables mode)))
-    (when table
-      (gethash uuid (yas--table-uuidhash table)))))
-
-;; Apropos storing/updating in TABLE, this works in two steps:
-;;
-;; 1. `yas--remove-template-by-uuid' removes any
-;;    keyhash-namehash-template mappings from TABLE, grabing the
-;;    snippet by its uuid. Also removes mappings from TABLE's
-;;    `yas--table-direct-keymap' (FIXME: and should probably take care
-;;    of potentially stale menu bindings right?.)
-;;
-;; 2. `yas--add-template' adds this all over again.
-;;
-;;    Create a new or add to an existing keyhash-namehash mapping.
-;;
-;;  For reference on understanding this, consider three snippet
-;;  definitions:
-;;
-;;  A:   # name: The Foo
-;;       # key: foo
-;;       # binding: C-c M-l
-;;
-;;  B:   # name: Mrs Foo
-;;       # key: foo
-;;
-;;  C:   # name: The Bar
-;;       # binding: C-c M-l
-;;
-;;  D:   # name: Baz
-;;       # key: baz
-;;
-;;  keyhash       namehashes(3)      yas--template structs(4)
-;;  -----------------------------------------------------
-;;                                            __________
-;;                                           /          \
-;;  "foo"      --->  "The Foo" --->  [yas--template A]   |
-;;                   "Mrs Foo" --->  [yas--template B]   |
-;;                                                      |
-;;  [C-c M-l]  --->  "The Foo" -------------------------/
-;;                   "The Bar" --->  [yas--template C]
-;;
-;;  "baz"      --->  "Baz"     --->  [yas--template D]
-;;
-;; Additionally, since uuid defaults to the name, we have a
-;; `yas--table-uuidhash' for TABLE
-;;
-;; uuidhash       yas--template structs
-;; -------------------------------
-;; "The Foo" ---> [yas--template A]
-;; "Mrs Foo" ---> [yas--template B]
-;; "The Bar" ---> [yas--template C]
-;; "Baz"     ---> [yas--template D]
-;;
-;; FIXME: the more I look at this data-structure the more I think I'm
-;; stupid. There has to be an easier way (but beware lots of code
-;; depends on this).
-;;
-(defun yas--remove-template-by-uuid (table uuid)
-  "Remove from TABLE a template identified by UUID."
-  (let ((template (gethash uuid (yas--table-uuidhash table))))
-    (when template
-      (let* ((name                (yas--template-name template))
-             (empty-keys          nil))
-        ;; Remove the name from each of the targeted namehashes
-        ;;
-        (maphash #'(lambda (k v)
-                     (let ((template (gethash name v)))
-                       (when (and template
-                                  (eq uuid (yas--template-uuid template)))
-                         (remhash name v)
-                         (when (zerop (hash-table-count v))
-                           (push k empty-keys)))))
-                 (yas--table-hash table))
-        ;; Remove the namehash themselves if they've become empty
-        ;;
-        (dolist (key empty-keys)
-          (when (vectorp key)
-            (define-key (yas--table-direct-keymap table) key nil))
-          (remhash key (yas--table-hash table)))
-
-        ;; Finally, remove the uuid from the uuidhash
-        ;;
-        (remhash uuid (yas--table-uuidhash table))))))
-
-(defun yas--add-template (table template)
-  "Store in TABLE the snippet template TEMPLATE.
-
-KEY can be a string (trigger key) of a vector (direct
-keybinding)."
-  (let ((name (yas--template-name template))
-        (key (yas--template-key template))
-        (keybinding (yas--template-keybinding template))
-        (menu-binding-pair (yas--template-menu-binding-pair-get-create 
template)))
-    (dolist (k (remove nil (list key keybinding)))
-      (puthash name
-               template
-               (or (gethash k
-                            (yas--table-hash table))
-                   (puthash k
-                            (make-hash-table :test 'equal)
-                            (yas--table-hash table))))
-      (when (vectorp k)
-        (define-key (yas--table-direct-keymap table) k 
'yas-expand-from-keymap)))
-
-    ;; Update TABLE's `yas--table-uuidhash'
-    (puthash (yas--template-uuid template)
-             template
-             (yas--table-uuidhash table))))
-
-(defun yas--update-template (table template)
-  "Add or update TEMPLATE in TABLE.
-
-Also takes care of adding and updating to the associated menu."
-  ;; Remove from table by uuid
-  ;;
-  (yas--remove-template-by-uuid table (yas--template-uuid template))
-  ;; Add to table again
-  ;;
-  (yas--add-template table template)
-  ;; Take care of the menu
-  ;;
-  (when yas-use-menu
-    (yas--update-template-menu table template)))
-
-(defun yas--update-template-menu (table template)
-  "Update every menu-related for TEMPLATE"
-  (let ((menu-binding-pair (yas--template-menu-binding-pair-get-create 
template))
-        (key (yas--template-key template))
-        (keybinding (yas--template-keybinding template)))
-    ;; The snippet might have changed name or keys, so update
-    ;; user-visible strings
-    ;;
-    (unless (eq (cdr menu-binding-pair) :none)
-      ;; the menu item name
-      ;;
-      (setf (cadar menu-binding-pair) (yas--template-name template))
-      ;; the :keys information (also visible to the user)
-      (setf (getf (cdr (car menu-binding-pair)) :keys)
-            (or (and keybinding (key-description keybinding))
-                (and key (concat key yas-trigger-symbol))))))
-  (unless (yas--template-menu-managed-by-yas-define-menu template)
-    (let ((menu-keymap
-           (yas--menu-keymap-get-create (yas--table-mode table)
-                                        (mapcar #'yas--table-mode
-                                                (yas--table-parents table))))
-          (group (yas--template-group template)))
-      ;; Remove from menu keymap
-      ;;
-      (assert menu-keymap)
-      (yas--delete-from-keymap menu-keymap (yas--template-uuid template))
-
-      ;; Add necessary subgroups as necessary.
-      ;;
-      (dolist (subgroup group)
-        (let ((subgroup-keymap (lookup-key menu-keymap (vector (make-symbol 
subgroup)))))
-          (unless (and subgroup-keymap
-                       (keymapp subgroup-keymap))
-            (setq subgroup-keymap (make-sparse-keymap))
-            (define-key menu-keymap (vector (make-symbol subgroup))
-              `(menu-item ,subgroup ,subgroup-keymap)))
-          (setq menu-keymap subgroup-keymap)))
-
-      ;; Add this entry to the keymap
-      ;;
-      (define-key menu-keymap
-        (vector (make-symbol (yas--template-uuid template)))
-        (car (yas--template-menu-binding-pair template))))))
-
-(defun yas--namehash-templates-alist (namehash)
-  (let (alist)
-    (maphash #'(lambda (k v)
-                 (push (cons k v) alist))
-             namehash)
-    alist))
-
-(defun yas--fetch (table key)
-  "Fetch templates in TABLE by KEY.
-
-Return a list of cons (NAME . TEMPLATE) where NAME is a
-string and TEMPLATE is a `yas--template' structure."
-  (let* ((keyhash (yas--table-hash table))
-         (namehash (and keyhash (gethash key keyhash))))
-    (when namehash
-      (yas--filter-templates-by-condition (yas--namehash-templates-alist 
namehash)))))
-
-
-;;; Filtering/condition logic
-
-(defun yas--eval-condition (condition)
-  (condition-case err
-      (save-excursion
-        (save-restriction
-          (save-match-data
-            (eval condition))))
-    (error (progn
-             (yas--message 1 "Error in condition evaluation: %s" 
(error-message-string err))
-             nil))))
-
-
-(defun yas--filter-templates-by-condition (templates)
-  "Filter the templates using the applicable condition.
-
-TEMPLATES is a list of cons (NAME . TEMPLATE) where NAME is a
-string and TEMPLATE is a `yas--template' structure.
-
-This function implements the rules described in
-`yas-buffer-local-condition'.  See that variables documentation."
-  (let ((requirement (yas--require-template-specific-condition-p)))
-    (if (eq requirement 'always)
-        templates
-      (remove-if-not #'(lambda (pair)
-                         (yas--template-can-expand-p
-                          (yas--template-condition (cdr pair)) requirement))
-                     templates))))
-
-(defun yas--require-template-specific-condition-p ()
-  "Decides if this buffer requests/requires snippet-specific
-conditions to filter out potential expansions."
-  (if (eq 'always yas-buffer-local-condition)
-      'always
-    (let ((local-condition (or (and (consp yas-buffer-local-condition)
-                                    (yas--eval-condition 
yas-buffer-local-condition))
-                               yas-buffer-local-condition)))
-      (when local-condition
-        (if (eq local-condition t)
-            t
-          (and (consp local-condition)
-               (eq 'require-snippet-condition (car local-condition))
-               (symbolp (cdr local-condition))
-               (cdr local-condition)))))))
-
-(defun yas--template-can-expand-p (condition requirement)
-  "Evaluates CONDITION and REQUIREMENT and returns a boolean"
-  (let* ((result (or (null condition)
-                     (yas--eval-condition condition))))
-    (cond ((eq requirement t)
-           result)
-          (t
-           (eq requirement result)))))
-
-(defun yas--all-parents (mode)
-  "Returns a list of all parent modes of MODE"
-  (let ((parents (gethash mode yas--parents)))
-    (append parents
-            (mapcan #'yas--all-parents parents))))
-
-(defun yas--table-templates (table)
-  (when table
-    (let ((acc (list)))
-      (maphash #'(lambda (key namehash)
-                   (maphash #'(lambda (name template)
-                                (push (cons name template) acc))
-                            namehash))
-               (yas--table-hash table))
-      (yas--filter-templates-by-condition acc))))
-
-(defun yas--current-key ()
-  "Get the key under current position. A key is used to find
-the template of a snippet in the current snippet-table."
-  (let ((start (point))
-        (end (point))
-        (syntaxes yas-key-syntaxes)
-        syntax
-        done
-        templates)
-    (while (and (not done) syntaxes)
-      (setq syntax (car syntaxes))
-      (setq syntaxes (cdr syntaxes))
-      (save-excursion
-        (skip-syntax-backward syntax)
-        (setq start (point)))
-      (setq templates
-            (mapcan #'(lambda (table)
-                        (yas--fetch table (buffer-substring-no-properties 
start end)))
-                    (yas--get-snippet-tables)))
-      (if templates
-          (setq done t)
-        (setq start end)))
-    (list templates
-          start
-          end)))
-
-
-(defun yas--table-all-keys (table)
-  (when table
-    (let ((acc))
-      (maphash #'(lambda (key namehash)
-                   (when (yas--filter-templates-by-condition 
(yas--namehash-templates-alist namehash))
-                     (push key acc)))
-               (yas--table-hash table))
-      acc)))
-
-(defun yas--table-mode (table)
-  (intern (yas--table-name table)))
-
-
-;;; Internal functions:
-
-(defun yas--real-mode? (mode)
-  "Try to find out if MODE is a real mode. The MODE bound to
-a function (like `c-mode') is considered real mode. Other well
-known mode like `ruby-mode' which is not part of Emacs might
-not bound to a function until it is loaded. So yasnippet keeps
-a list of modes like this to help the judgement."
-  (or (fboundp mode)
-      (find mode yas--known-modes)))
-
-(defun yas--eval-lisp (form)
-  "Evaluate FORM and convert the result to string."
-  (let ((retval (catch 'yas--exception
-                  (condition-case err
-                      (save-excursion
-                        (save-restriction
-                          (save-match-data
-                            (widen)
-                            (let ((result (eval form)))
-                              (when result
-                                (format "%s" result))))))
-                    (error (if yas-good-grace
-                               (yas--format "elisp error! %s" 
(error-message-string err))
-                             (error (yas--format "elisp error: %s"
-                                            (error-message-string err)))))))))
-    (when (and (consp retval)
-               (eq 'yas--exception (car retval)))
-      (error (cdr retval)))
-    retval))
-
-(defun yas--eval-lisp-no-saves (form)
-  (condition-case err
-      (eval form)
-    (error (if yas-good-grace
-               (yas--format "elisp error! %s" (error-message-string err))
-             (error (yas--format "elisp error: %s"
-                            (error-message-string err)))))))
-
-(defun yas--read-lisp (string &optional nil-on-error)
-  "Read STRING as a elisp expression and return it.
-
-In case STRING in an invalid expression and NIL-ON-ERROR is nil,
-return an expression that when evaluated will issue an error."
-  (condition-case err
-      (read string)
-    (error (and (not nil-on-error)
-                `(error (error-message-string ,err))))))
-
-(defun yas--read-keybinding (keybinding)
-  "Read KEYBINDING as a snippet keybinding, return a vector."
-  (when (and keybinding
-             (not (string-match "keybinding" keybinding)))
-    (condition-case err
-        (let ((res (or (and (string-match "^\\[.*\\]$" keybinding)
-                            (read keybinding))
-                       (read-kbd-macro keybinding 'need-vector))))
-          res)
-      (error
-       (yas--message 3 "warning: keybinding \"%s\" invalid since %s."
-                keybinding (error-message-string err))
-       nil))))
-
-(defvar yas-extra-modes nil
-  "If non-nil, also lookup snippets for this/these modes.
-
-Can be a symbol or a list of symbols.
-
-This variable probably makes more sense as buffer-local, so
-ensure your use `make-local-variable' when you set it.")
-(defun yas-extra-modes ()
-  (if (listp yas-extra-modes) yas-extra-modes (list yas-extra-modes)))
-(defvaralias 'yas/mode-symbol 'yas-extra-modes)
-
-(defun yas--table-get-create (mode)
-  "Get or create the snippet table corresponding to MODE."
-  (let ((table (gethash mode
-                        yas--tables)))
-    (unless table
-      (setq table (yas--make-snippet-table (symbol-name mode)))
-      (puthash mode table yas--tables)
-      (push (cons (intern (format "yas--direct-%s" mode))
-                  (yas--table-direct-keymap table))
-            yas--direct-keymaps))
-    table))
-
-(defun yas--get-snippet-tables ()
-  "Get snippet tables for current buffer.
-
-Return a list of `yas--table' objects. The list of modes to
-consider is returned by `yas--modes-to-activate'"
-  (remove nil
-          (mapcar #'(lambda (mode-name)
-                      (gethash mode-name yas--tables))
-                  (yas--modes-to-activate))))
-
-(defun yas--menu-keymap-get-create (mode &optional parents)
-  "Get or create the menu keymap for MODE and its PARENTS.
-
-This may very well create a plethora of menu keymaps and arrange
-them all in `yas--menu-table'"
-  (let* ((menu-keymap (or (gethash mode yas--menu-table)
-                          (puthash mode (make-sparse-keymap) 
yas--menu-table))))
-    (mapc #'yas--menu-keymap-get-create parents)
-    (define-key yas--minor-mode-menu (vector mode)
-        `(menu-item ,(symbol-name mode) ,menu-keymap
-                    :visible (yas--show-menu-p ',mode)))
-    menu-keymap))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Template-related and snippet loading functions
-
-(defun yas--parse-template (&optional file)
-  "Parse the template in the current buffer.
-
-Optional FILE is the absolute file name of the file being
-parsed.
-
-Optional GROUP is the group where the template is to go,
-otherwise we attempt to calculate it from FILE.
-
-Return a snippet-definition, i.e. a list
-
- (KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING UUID)
-
-If the buffer contains a line of \"# --\" then the contents above
-this line are ignored. Directives can set most of these with the syntax:
-
-# directive-name : directive-value
-
-Here's a list of currently recognized directives:
-
- * type
- * name
- * contributor
- * condition
- * group
- * key
- * expand-env
- * binding
- * uuid"
-  (goto-char (point-min))
-  (let* ((type 'snippet)
-         (name (and file
-                    (file-name-nondirectory file)))
-         (key nil)
-         template
-         bound
-         condition
-         (group (and file
-                     (yas--calculate-group file)))
-         expand-env
-         binding
-         uuid)
-    (if (re-search-forward "^# --\n" nil t)
-        (progn (setq template
-                     (buffer-substring-no-properties (point)
-                                                     (point-max)))
-               (setq bound (point))
-               (goto-char (point-min))
-               (while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*\\)$" 
bound t)
-                 (when (string= "uuid" (match-string-no-properties 1))
-                   (setq uuid (match-string-no-properties 2)))
-                 (when (string= "type" (match-string-no-properties 1))
-                   (setq type (if (string= "command" 
(match-string-no-properties 2))
-                                  'command
-                                'snippet)))
-                 (when (string= "key" (match-string-no-properties 1))
-                   (setq key (match-string-no-properties 2)))
-                 (when (string= "name" (match-string-no-properties 1))
-                   (setq name (match-string-no-properties 2)))
-                 (when (string= "condition" (match-string-no-properties 1))
-                   (setq condition (yas--read-lisp (match-string-no-properties 
2))))
-                 (when (string= "group" (match-string-no-properties 1))
-                   (setq group (match-string-no-properties 2)))
-                 (when (string= "expand-env" (match-string-no-properties 1))
-                   (setq expand-env (yas--read-lisp 
(match-string-no-properties 2)
-                                                   'nil-on-error)))
-                 (when (string= "binding" (match-string-no-properties 1))
-                   (setq binding (match-string-no-properties 2)))))
-      (setq template
-            (buffer-substring-no-properties (point-min) (point-max))))
-    (unless (or key binding)
-      (setq key (and file (file-name-nondirectory file))))
-    (when (eq type 'command)
-      (setq template (yas--read-lisp (concat "(progn" template ")"))))
-    (when group
-      (setq group (split-string group "\\.")))
-    (list key template name condition group expand-env file binding uuid)))
-
-(defun yas--calculate-group (file)
-  "Calculate the group for snippet file path FILE."
-  (let* ((dominating-dir (locate-dominating-file file
-                                                 ".yas-make-groups"))
-         (extra-path (and dominating-dir
-                          (replace-regexp-in-string (concat "^"
-                                                            (expand-file-name 
dominating-dir))
-                                                    ""
-                                                    (expand-file-name file))))
-         (extra-dir (and extra-path
-                         (file-name-directory extra-path)))
-         (group (and extra-dir
-                     (replace-regexp-in-string "/"
-                                               "."
-                                               (directory-file-name 
extra-dir)))))
-    group))
-
-(defun yas--subdirs (directory &optional filep)
-  "Return subdirs or files of DIRECTORY according to FILEP."
-  (remove-if (lambda (file)
-               (or (string-match "^\\."
-                                 (file-name-nondirectory file))
-                   (string-match "^#.*#$"
-                                 (file-name-nondirectory file))
-                   (string-match "~$"
-                                 (file-name-nondirectory file))
-                   (if filep
-                       (file-directory-p file)
-                     (not (file-directory-p file)))))
-             (directory-files directory t)))
-
-(defun yas--make-menu-binding (template)
-  (let ((mode (yas--table-mode (yas--template-table template))))
-    `(lambda () (interactive) (yas--expand-or-visit-from-menu ',mode 
,(yas--template-uuid template)))))
-
-(defun yas--expand-or-visit-from-menu (mode uuid)
-  (let* ((table (yas--table-get-create mode))
-         (yas--current-template (and table
-                                    (gethash uuid (yas--table-uuidhash 
table)))))
-    (when yas--current-template
-      (if yas-visit-from-menu
-          (yas--visit-snippet-file-1 yas--current-template)
-        (let ((where (if (region-active-p)
-                         (cons (region-beginning) (region-end))
-                       (cons (point) (point)))))
-          (yas-expand-snippet (yas--template-content yas--current-template)
-                              (car where)
-                              (cdr where)
-                              (yas--template-expand-env 
yas--current-template)))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Popping up for keys and templates
-;;
-(defvar yas--x-pretty-prompt-templates nil
-  "If non-nil, attempt to prompt for templates like TextMate.")
-
-
-(defun yas--prompt-for-template (templates &optional prompt)
-  "Interactively choose a template from the list TEMPLATES.
-
-TEMPLATES is a list of `yas--template'."
-  (when templates
-    (setq templates
-          (sort templates #'(lambda (t1 t2)
-                              (< (length (yas--template-name t1))
-                                 (length (yas--template-name t2))))))
-    (if yas--x-pretty-prompt-templates
-        (yas--x-pretty-prompt-templates "Choose a snippet" templates)
-      (some #'(lambda (fn)
-                (funcall fn (or prompt "Choose a snippet: ")
-                         templates
-                         #'yas--template-name))
-            yas-prompt-functions))))
-
-(defun yas--prompt-for-keys (keys &optional prompt)
-  "Interactively choose a template key from the list KEYS."
-  (when keys
-    (some #'(lambda (fn)
-              (funcall fn (or prompt "Choose a snippet key: ") keys))
-          yas-prompt-functions)))
-
-(defun yas--prompt-for-table (tables &optional prompt)
-  (when tables
-    (some #'(lambda (fn)
-              (funcall fn (or prompt "Choose a snippet table: ")
-                       tables
-                       #'yas--table-name))
-          yas-prompt-functions)))
-
-(defun yas-x-prompt (prompt choices &optional display-fn)
-  "Display choices in a x-window prompt."
-  ;; FIXME: HACK: if we notice that one of the objects in choices is
-  ;; actually a `yas--template', defer to `yas--x-prompt-pretty-templates'
-  ;;
-  ;; This would be better implemented by passing CHOICES as a
-  ;; strucutred tree rather than a list. Modifications would go as far
-  ;; up as `yas--all-templates' I think.
-  ;;
-  (when (and window-system choices)
-    (let ((chosen
-           (let (menu d) ;; d for display
-             (dolist (c choices)
-               (setq d (or (and display-fn (funcall display-fn c))
-                           c))
-               (cond ((stringp d)
-                      (push (cons (concat "   " d) c) menu))
-                     ((listp d)
-                      (push (car d) menu))))
-             (setq menu (list prompt (push "title" menu)))
-             (x-popup-menu (if (fboundp 'posn-at-point)
-                               (let ((x-y (posn-x-y (posn-at-point (point)))))
-                                 (list (list (+ (car x-y) 10)
-                                             (+ (cdr x-y) 20))
-                                       (selected-window)))
-                             t)
-                           menu))))
-      (or chosen
-          (keyboard-quit)))))
-
-(defun yas--x-pretty-prompt-templates (prompt templates)
-  "Display TEMPLATES, grouping neatly by table name."
-  (let ((organized (make-hash-table :test #'equal))
-        menu
-        more-than-one-table
-        prefix)
-    (dolist (tl templates)
-      (puthash (yas--template-table tl)
-               (cons tl
-                     (gethash (yas--template-table tl) organized))
-               organized))
-    (setq more-than-one-table (> (hash-table-count organized) 1))
-    (setq prefix (if more-than-one-table
-                     "   " ""))
-    (if more-than-one-table
-        (maphash #'(lambda (table templates)
-                     (push (yas--table-name table) menu)
-                     (dolist (tl templates)
-                       (push (cons (concat prefix (yas--template-name tl)) tl) 
menu))) organized)
-      (setq menu (mapcar #'(lambda (tl) (cons (concat prefix 
(yas--template-name tl)) tl)) templates)))
-
-    (setq menu (nreverse menu))
-    (or (x-popup-menu (if (fboundp 'posn-at-point)
-                          (let ((x-y (posn-x-y (posn-at-point (point)))))
-                            (list (list (+ (car x-y) 10)
-                                        (+ (cdr x-y) 20))
-                                  (selected-window)))
-                        t)
-                      (list prompt (push "title" menu)))
-        (keyboard-quit))))
-
-(defun yas-ido-prompt (prompt choices &optional display-fn)
-  (when (and (fboundp 'ido-completing-read)
-            (or (>= emacs-major-version 24)
-                ido-mode))
-    (yas-completing-prompt prompt choices display-fn #'ido-completing-read)))
-
-(eval-when-compile (require 'dropdown-list nil t))
-(defun yas-dropdown-prompt (prompt choices &optional display-fn)
-  (when (featurep 'dropdown-list)
-    (let (formatted-choices
-          filtered-choices
-          d
-          n)
-      (dolist (choice choices)
-        (setq d (or (and display-fn (funcall display-fn choice))
-                      choice))
-        (when (stringp d)
-          (push d formatted-choices)
-          (push choice filtered-choices)))
-
-      (setq n (and formatted-choices (dropdown-list formatted-choices)))
-      (if n
-          (nth n filtered-choices)
-        (keyboard-quit)))))
-
-(defun yas-completing-prompt (prompt choices &optional display-fn 
completion-fn)
-  (let (formatted-choices
-        filtered-choices
-        chosen
-        d
-        (completion-fn (or completion-fn
-                           #'completing-read)))
-    (dolist (choice choices)
-      (setq d (or (and display-fn (funcall display-fn choice))
-                    choice))
-      (when (stringp d)
-        (push d formatted-choices)
-        (push choice filtered-choices)))
-    (setq chosen (and formatted-choices
-                      (funcall completion-fn prompt
-                               formatted-choices
-                               nil
-                               'require-match
-                               nil
-                               nil)))
-    (let ((position (or (and chosen
-                             (position chosen formatted-choices :test 
#'string=))
-                        0)))
-      (nth position filtered-choices))))
-
-(defun yas-no-prompt (prompt choices &optional display-fn)
-  (first choices))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Loading snippets from files
-;;
-(defun yas--load-yas-setup-file (file)
-  (load file 'noerror))
-
-(defun yas-load-directory (top-level-dir &optional use-jit)
-  "Load snippets in directory hierarchy TOP-LEVEL-DIR.
-
-Below TOP-LEVEL-DIR each directory should be a mode name.
-
-Optional USE-JIT use jit-loading of snippets."
-  (interactive "DSelect the root directory: ")
-  (unless yas-snippet-dirs
-    (setq yas-snippet-dirs top-level-dir))
-  (dolist (dir (yas--subdirs top-level-dir))
-    (let* ((major-mode-and-parents (yas--compute-major-mode-and-parents
-                                    (concat dir "/dummy")))
-           (mode-sym (car major-mode-and-parents))
-           (parents (cdr major-mode-and-parents)))
-      ;; Attention: The parents and the menus are already defined
-      ;; here, even if the snippets are later jit-loaded.
-      ;;
-      ;; * We need to know the parents at this point since entering a
-      ;;   given mode should jit load for its parents
-      ;;   immediately. This could be reviewed, the parents could be
-      ;;   discovered just-in-time-as well
-      ;;
-      ;; * We need to create the menus here to support the `full'
-      ;;   option to `yas-use-menu' (all known snippet menus are shown to the 
user)
-      ;;
-      (yas--define-parents mode-sym parents)
-      (yas--menu-keymap-get-create mode-sym)
-      (let ((form `(yas--load-directory-1 ,dir
-                                         ',mode-sym
-                                         ',parents)))
-        (if use-jit
-            (yas--schedule-jit mode-sym form)
-            (eval form)))))
-  (when (interactive-p)
-    (yas--message 3 "Loaded snippets from %s." top-level-dir)))
-
-(defun yas--load-directory-1 (directory mode-sym parents &optional 
no-compiled-snippets)
-  "Recursively load snippet templates from DIRECTORY."
-  (unless (file-exists-p (concat directory "/" ".yas-skip"))
-    (if (and (not no-compiled-snippets)
-             (progn (yas--message 2 "Loading compiled snippets from %s" 
directory) t)
-             (load (expand-file-name ".yas-compiled-snippets" directory) 
'noerror (<= yas-verbosity 3)))
-      (yas--message 2 "Loading snippet files from %s" directory)
-      (yas--load-directory-2 directory mode-sym))))
-
-(defun yas--load-directory-2 (directory mode-sym)
-  ;; Load .yas-setup.el files wherever we find them
-  ;;
-  (yas--load-yas-setup-file (expand-file-name ".yas-setup" directory))
-  (let* ((default-directory directory)
-         (snippet-defs nil))
-    ;; load the snippet files
-    ;;
-    (with-temp-buffer
-      (dolist (file (yas--subdirs directory 'no-subdirs-just-files))
-        (when (file-readable-p file)
-          (insert-file-contents file nil nil nil t)
-          (push (yas--parse-template file)
-                snippet-defs))))
-    (when snippet-defs
-      (yas-define-snippets mode-sym
-                           snippet-defs))
-    ;; now recurse to a lower level
-    ;;
-    (dolist (subdir (yas--subdirs directory))
-      (yas--load-directory-2 subdir
-                            mode-sym))))
-
-(defun yas--load-snippet-dirs (&optional nojit)
-  "Reload the directories listed in `yas-snippet-dirs' or
-   prompt the user to select one."
-  (let (errors)
-    (if yas-snippet-dirs
-        (dolist (directory (reverse (yas-snippet-dirs)))
-          (cond ((file-directory-p directory)
-                 (yas-load-directory directory (not nojit))
-                 (if nojit
-                     (yas--message 3 "Loaded %s" directory)
-                   (yas--message 3 "Prepared just-in-time loading for %s" 
directory)))
-                (t
-                 (push (yas--message 0 "Check your `yas-snippet-dirs': %s is 
not a directory" directory) errors))))
-      (call-interactively 'yas-load-directory))
-    errors))
-
-(defun yas-reload-all (&optional interactive)
-  "Reload all snippets and rebuild the YASnippet menu.
-
-When called interactively force immediate reload of all known
-snippets under `yas-snippet-dirs', otherwise use just-in-time
-loading."
-  (interactive "p")
-  (catch 'abort
-    (let ((errors)
-          (snippet-editing-buffers
-           (remove-if-not #'(lambda (buffer)
-                              (with-current-buffer buffer 
yas--editing-template))
-                          (buffer-list))))
-      ;; Warn if there are buffers visiting snippets, since reloading will 
break
-      ;; any on-line editing of those buffers.
-      ;;
-      (when snippet-editing-buffers
-          (if interactive
-              (if (y-or-n-p "Some buffers editing live snippets, close them 
and proceed with reload?")
-                  (mapc #'kill-buffer snippet-editing-buffers)
-                (yas--message 1 "Aborted reload...")
-                (throw 'abort nil))
-            ;; in a non-interactive use, at least set
-            ;; `yas--editing-template' to nil, make it guess it next time 
around
-            (mapc #'(lambda (buffer) (setq yas--editing-template nil)) 
(buffer-list))))
-
-      ;; Empty all snippet tables, parenting info and all menu tables
-      ;;
-      (setq yas--tables (make-hash-table))
-      (setq yas--parents (make-hash-table))
-      (setq yas--menu-table (make-hash-table))
-
-      ;; Cancel all pending 'yas--scheduled-jit-loads'
-      ;;
-      (setq yas--scheduled-jit-loads (make-hash-table))
-
-      ;; Init the `yas-minor-mode-map', taking care not to break the
-      ;; menu....
-      ;;
-      (setcdr yas-minor-mode-map (cdr (yas--init-minor-keymap)))
-
-      ;; Reload the directories listed in `yas-snippet-dirs' or prompt
-      ;; the user to select one.
-      ;;
-      (setq errors (yas--load-snippet-dirs interactive))
-      ;; Reload the direct keybindings
-      ;;
-      (yas-direct-keymaps-reload)
-      ;; Reload the trigger-key (shoudn't be needed, but see issue #237)
-      ;;
-      (yas--trigger-key-reload)
-
-      (yas--message 3 "Reloaded everything%s...%s."
-                   (if interactive "" " (snippets will load just-in-time)")
-                   (if errors " (some errors, check *Messages*)" "")))))
-
-(defun yas--load-pending-jits ()
-  (when yas-minor-mode
-    (dolist (mode (yas--modes-to-activate))
-      (let ((forms (reverse (gethash mode yas--scheduled-jit-loads))))
-        ;; must reverse to maintain coherence with `yas-snippet-dirs'
-        (dolist (form forms)
-          (yas--message  3 "Loading for `%s', just-in-time: %s!" mode form)
-          (eval form))
-        (remhash mode yas--scheduled-jit-loads)))))
-
-;; (when (<= emacs-major-version 22)
-;;   (add-hook 'after-change-major-mode-hook 'yas--load-pending-jits))
-
-(defun yas--quote-string (string)
-  "Escape and quote STRING.
-foo\"bar\\! -> \"foo\\\"bar\\\\!\""
-  (concat "\""
-          (replace-regexp-in-string "[\\\"]"
-                                    "\\\\\\&"
-                                    string
-                                    t)
-          "\""))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Snippet compilation function
-
-(defun yas--initialize ()
-  "For backward compatibility, enable `yas-minor-mode' globally"
-  (yas-global-mode 1))
-
-(defun yas-compile-directory (top-level-dir)
-  "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR.
-
-This works by stubbing a few functions, then calling
-`yas-load-directory'."
-  (interactive "DTop level snippet directory?")
-  (flet ((yas--load-yas-setup-file
-          (file)
-          (let ((elfile (concat file ".el")))
-            (when (file-exists-p elfile)
-              (insert ";;; .yas-setup.el support file if any:\n;;;\n")
-              (insert-file-contents elfile)
-              (end-of-buffer)
-              )))
-         (yas-define-snippets
-          (mode snippets)
-          (insert ";;; Snippet definitions:\n;;;\n")
-          (let ((literal-snippets (list))
-                (print-length nil))
-            (dolist (snippet snippets)
-              (let ((key                    (first   snippet))
-                    (template-content       (second  snippet))
-                    (name                   (third   snippet))
-                    (condition              (fourth  snippet))
-                    (group                  (fifth   snippet))
-                    (expand-env             (sixth   snippet))
-                    (file                   nil) ;; (seventh snippet)) ;; omit 
on purpose
-                    (binding                (eighth  snippet))
-                    (uuid                    (ninth   snippet)))
-                (push `(,key
-                        ,template-content
-                        ,name
-                        ,condition
-                        ,group
-                        ,expand-env
-                        ,file
-                        ,binding
-                        ,uuid)
-                      literal-snippets)))
-            (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
-            (insert "\n\n")))
-         (yas--load-directory-1
-          (dir mode parents &rest ignore)
-          (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
-            (with-temp-file output-file
-              (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
-              (yas--load-directory-2 dir mode)
-              (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
-    (yas-load-directory top-level-dir nil)))
-
-(defun yas-recompile-all ()
-  "Compile every dir in `yas-snippet-dirs'."
-  (interactive)
-  (mapc #'yas-compile-directory (yas-snippet-dirs)))
-
-
-;;; JIT loading
-;;;
-
-(defvar yas--scheduled-jit-loads (make-hash-table)
-  "Alist of mode-symbols to forms to be evaled when `yas-minor-mode' kicks 
in.")
-
-(defun yas--schedule-jit (mode form)
-  (puthash mode
-           (cons form
-                 (gethash mode yas--scheduled-jit-loads))
-           yas--scheduled-jit-loads))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Some user level functions
-;;;
-
-(defun yas-about ()
-  (interactive)
-  (message (concat "yasnippet (version "
-                   yas--version
-                   ") -- pluskid <address@hidden>/joaotavora 
<address@hidden>")))
-
-(defun yas--define-parents (mode parents)
-  "Add PARENTS to the list of MODE's parents"
-  (puthash mode (remove-duplicates
-                 (append parents
-                         (gethash mode yas--parents)))
-           yas--parents))
-
-(defun yas-define-snippets (mode snippets)
-  "Define SNIPPETS for MODE.
-
-SNIPPETS is a list of snippet definitions, each taking the
-following form
-
- (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
-
-Within these, only KEY and TEMPLATE are actually mandatory.
-
-TEMPLATE might be a lisp form or a string, depending on whether
-this is a snippet or a snippet-command.
-
-CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
-been `yas--read-lisp'-ed and will eventually be
-`yas--eval-lisp'-ed.
-
-The remaining elements are strings.
-
-FILE is probably of very little use if you're programatically
-defining snippets.
-
-UUID is the snippets \"unique-id\". Loading a second snippet file
-with the same uuid replaced the previous snippet.
-
-You can use `yas--parse-template' to return such lists based on
-the current buffers contents."
-  (let ((snippet-table (yas--table-get-create mode))
-        (template nil))
-    (dolist (snippet snippets)
-      (setq template (yas-define-snippets-1 snippet
-                                            snippet-table)))
-    template))
-
-(defun yas-define-snippets-1 (snippet snippet-table)
-  "Helper for `yas-define-snippets'."
-  ;; X) Calculate some more defaults on the values returned by
-  ;; `yas--parse-template'.
-  ;;
-  (let* ((file (seventh snippet))
-         (key (car snippet))
-         (name (or (third snippet)
-                   (and file
-                        (file-name-directory file))))
-         (condition (fourth snippet))
-         (group (fifth snippet))
-         (keybinding (yas--read-keybinding (eighth snippet)))
-         (uuid (or (ninth snippet)
-                  name))
-         (template (or (gethash uuid (yas--table-uuidhash snippet-table))
-                       (yas--make-blank-template))))
-    ;; X) populate the template object
-    ;;
-    (yas--populate-template template
-                           :table       snippet-table
-                           :key         key
-                           :content     (second snippet)
-                           :name        (or name key)
-                           :group       group
-                           :condition   condition
-                           :expand-env  (sixth snippet)
-                           :file        (seventh snippet)
-                           :keybinding  keybinding
-                           :uuid         uuid)
-    ;; X) Update this template in the appropriate table. This step
-    ;;    also will take care of adding the key indicators in the
-    ;;    templates menu entry, if any
-    ;;
-    (yas--update-template snippet-table template)
-    ;; X) Return the template
-    ;;
-    ;;
-    template))
-
-
-;;; Apropos snippet menu:
-;;
-;; The snippet menu keymaps are store by mode in hash table called
-;; `yas--menu-table'. They are linked to the main menu in
-;; `yas--menu-keymap-get-create' and are initially created empty,
-;; reflecting the table hierarchy.
-;;
-;; They can be populated in two mutually exclusive ways: (1) by
-;; reading `yas--template-group', which in turn is populated by the "#
-;; group:" directives of the snippets or the ".yas-make-groups" file
-;; or (2) by using a separate `yas-define-menu' call, which declares a
-;; menu structure based on snippets uuids.
-;;
-;; Both situations are handled in `yas--update-template-menu', which
-;; uses the predicate `yas--template-menu-managed-by-yas-define-menu'
-;; that can tell between the two situations.
-;;
-;; Note:
-;;
-;; * if `yas-define-menu' is used it must run before
-;;   `yas-define-snippets' and the UUIDS must match, otherwise we get
-;;   duplicate entries. The `yas--template' objects are created in
-;;   `yas-define-menu', holding nothing but the menu entry,
-;;   represented by a pair of ((menu-item NAME :keys KEYS) TYPE) and
-;;   stored in `yas--template-menu-binding-pair'. The (menu-item ...)
-;;   part is then stored in the menu keymap itself which make the item
-;;   appear to the user. These limitations could probably be revised.
-;;
-;; * The `yas--template-perm-group' slot is only used in
-;;   `yas-describe-tables'.
-;;
-(defun yas--template-menu-binding-pair-get-create (template &optional type)
-  "Get TEMPLATE's menu binding or assign it a new one.
-
-TYPE may be `:stay', signalling this menu binding should be
-static in the menu."
-  (or (yas--template-menu-binding-pair template)
-      (let ((key (yas--template-key template))
-            (keybinding (yas--template-keybinding template)))
-        (setf (yas--template-menu-binding-pair template)
-              (cons `(menu-item ,(or (yas--template-name template)
-                                     (yas--template-uuid template))
-                                ,(yas--make-menu-binding template)
-                                :keys ,nil)
-                    type)))))
-(defun yas--template-menu-managed-by-yas-define-menu (template)
-  "Non-nil if TEMPLATE's menu entry was included in a `yas-define-menu' call."
-  (cdr (yas--template-menu-binding-pair template)))
-
-
-(defun yas--show-menu-p (mode)
-  (cond ((eq yas-use-menu 'abbreviate)
-         (find mode
-               (mapcar #'(lambda (table)
-                           (yas--table-mode table))
-                       (yas--get-snippet-tables))))
-        ((eq yas-use-menu 'full)
-         t)
-        ((eq yas-use-menu t)
-         t)))
-
-(defun yas--delete-from-keymap (keymap uuid)
-  "Recursively delete items with UUID from KEYMAP and its submenus."
-
-  ;; XXX: This used to skip any submenus named \"parent mode\"
-  ;;
-  ;; First of all, recursively enter submenus, i.e. the tree is
-  ;; searched depth first so that stale submenus can be found in the
-  ;; higher passes.
-  ;;
-  (mapc #'(lambda (item)
-            (when (and (listp (cdr item))
-                       (keymapp (third (cdr item))))
-              (yas--delete-from-keymap (third (cdr item)) uuid)))
-        (rest keymap))
-  ;; Set the uuid entry to nil
-  ;;
-  (define-key keymap (vector (make-symbol uuid)) nil)
-  ;; Destructively modify keymap
-  ;;
-  (setcdr keymap (delete-if #'(lambda (item)
-                                (or (null (cdr item))
-                                    (and (keymapp (third (cdr item)))
-                                         (null (cdr (third (cdr item)))))))
-                            (rest keymap))))
-
-(defun yas-define-menu (mode menu &optional omit-items)
-  "Define a snippet menu for MODE according to MENU, ommitting OMIT-ITEMS.
-
-MENU is a list, its elements can be:
-
-- (yas-item UUID) : Creates an entry the snippet identified with
-  UUID. The menu entry for a snippet thus identified is
-  permanent, i.e. it will never move (be reordered) in the menu.
-
-- (yas-separator) : Creates a separator
-
-- (yas-submenu NAME SUBMENU) : Creates a submenu with NAME,
-  SUBMENU has the same form as MENU. NAME is also added to the
-  list of groups of the snippets defined thereafter.
-
-OMIT-ITEMS is a list of snippet uuid's that will always be
-ommited from MODE's menu, even if they're manually loaded.
-
-This function does nothing if `yas-use-menu' is nil.
-"
-  (when yas-use-menu
-    (let* ((table (yas--table-get-create mode))
-           (hash (yas--table-uuidhash table)))
-      (yas--define-menu-1 table
-                          (yas--menu-keymap-get-create mode)
-                          menu
-                          hash)
-      (dolist (uuid omit-items)
-        (let ((template (or (gethash uuid hash)
-                            (yas--populate-template (puthash uuid
-                                                             
(yas--make-blank-template)
-                                                             hash)
-                                                    :table table
-                                                    :uuid uuid))))
-          (setf (yas--template-menu-binding-pair template) (cons nil 
:none)))))))
-
-(defun yas--define-menu-1 (table menu-keymap menu uuidhash &optional 
group-list)
-  (dolist (e (reverse menu))
-    (cond ((eq (first e) 'yas-item)
-           (let ((template (or (gethash (second e) uuidhash)
-                               (yas--populate-template (puthash (second e)
-                                                               
(yas--make-blank-template)
-                                                               uuidhash)
-                                                      :table table
-                                                      :perm-group group-list
-                                                      :uuid (second e)))))
-             (define-key menu-keymap (vector (gensym))
-               (car (yas--template-menu-binding-pair-get-create template 
:stay)))))
-          ((eq (first e) 'yas-submenu)
-           (let ((subkeymap (make-sparse-keymap)))
-             (define-key menu-keymap (vector (gensym))
-               `(menu-item ,(second e) ,subkeymap))
-             (yas--define-menu-1 table
-                                subkeymap
-                                (third e)
-                                uuidhash
-                                (append group-list (list (second e))))))
-          ((eq (first e) 'yas-separator)
-           (define-key menu-keymap (vector (gensym))
-             '(menu-item "----")))
-          (t
-           (yas--message 3 "Don't know anything about menu entry %s" (first 
e))))))
-
-(defun yas--define (mode key template &optional name condition group)
-  "Define a snippet.  Expanding KEY into TEMPLATE.
-
-NAME is a description to this template.  Also update the menu if
-`yas-use-menu' is t.  CONDITION is the condition attached to
-this snippet.  If you attach a condition to a snippet, then it
-will only be expanded when the condition evaluated to non-nil."
-  (yas-define-snippets mode
-                       (list (list key template name condition group))))
-
-(defun yas-hippie-try-expand (first-time?)
-  "Integrate with hippie expand.  Just put this function in
-`hippie-expand-try-functions-list'."
-  (when yas-minor-mode
-    (if (not first-time?)
-        (let ((yas-fallback-behavior 'return-nil))
-          (yas-expand))
-      (undo 1)
-      nil)))
-
-
-;;; Apropos condition-cache:
-;;;
-;;;
-;;;
-;;;
-(defvar yas--condition-cache-timestamp nil)
-(defmacro yas-define-condition-cache (func doc &rest body)
-  "Define a function FUNC with doc DOC and body BODY, BODY is
-executed at most once every snippet expansion attempt, to check
-expansion conditions.
-
-It doesn't make any sense to call FUNC programatically."
-  `(defun ,func () ,(if (and doc
-                             (stringp doc))
-                        (concat doc
-"\n\nFor use in snippets' conditions. Within each
-snippet-expansion routine like `yas-expand', computes actual
-value for the first time then always returns a cached value.")
-                      (setq body (cons doc body))
-                      nil)
-     (let ((timestamp-and-value (get ',func 'yas--condition-cache)))
-       (if (equal (car timestamp-and-value) yas--condition-cache-timestamp)
-           (cdr timestamp-and-value)
-         (let ((new-value (progn
-                            ,@body
-                            )))
-           (put ',func 'yas--condition-cache (cons 
yas--condition-cache-timestamp new-value))
-           new-value)))))
-
-(defalias 'yas-expand 'yas-expand-from-trigger-key)
-(defun yas-expand-from-trigger-key (&optional field)
-  "Expand a snippet before point.
-
-If no snippet expansion is possible, fall back to the behaviour
-defined in `yas-fallback-behavior'.
-
-Optional argument FIELD is for non-interactive use and is an
-object satisfying `yas--field-p' to restrict the expansion to."
-  (interactive)
-  (setq yas--condition-cache-timestamp (current-time))
-  (let (templates-and-pos)
-    (unless (and yas-expand-only-for-last-commands
-                 (not (member last-command yas-expand-only-for-last-commands)))
-      (setq templates-and-pos (if field
-                                  (save-restriction
-                                    (narrow-to-region (yas--field-start field)
-                                                      (yas--field-end field))
-                                    (yas--current-key))
-                                (yas--current-key))))
-    (if (and templates-and-pos
-             (first templates-and-pos))
-        (yas--expand-or-prompt-for-template (first templates-and-pos)
-                                           (second templates-and-pos)
-                                           (third templates-and-pos))
-      (yas--fallback 'trigger-key))))
-
-(defun yas-expand-from-keymap ()
-  "Directly expand some snippets, searching `yas--direct-keymaps'.
-
-If expansion fails, execute the previous binding for this key"
-  (interactive)
-  (setq yas--condition-cache-timestamp (current-time))
-  (let* ((yas--prefix current-prefix-arg)
-         (vec (subseq (this-command-keys-vector) (if current-prefix-arg
-                                                     
universal-argument-num-events
-                                                   0)))
-         (templates (mapcan #'(lambda (table)
-                                (yas--fetch table vec))
-                            (yas--get-snippet-tables))))
-    (if templates
-        (yas--expand-or-prompt-for-template templates)
-      (let ((yas-fallback-behavior 'call-other-command))
-        (yas--fallback)))))
-
-(defun yas--expand-or-prompt-for-template (templates &optional start end)
-  "Expand one of TEMPLATES from START to END.
-
-Prompt the user if TEMPLATES has more than one element, else
-expand immediately. Common gateway for
-`yas-expand-from-trigger-key' and `yas-expand-from-keymap'."
-  (let ((yas--current-template (or (and (rest templates) ;; more than one
-                                       (yas--prompt-for-template (mapcar #'cdr 
templates)))
-                                  (cdar templates))))
-    (when yas--current-template
-      (yas-expand-snippet (yas--template-content yas--current-template)
-                          start
-                          end
-                          (yas--template-expand-env yas--current-template)))))
-
-(defun yas--trigger-key-for-fallback ()
-  ;; When `yas-trigger-key' is <tab> it correctly overrides
-  ;; org-mode's <tab>, for example and searching for fallbacks
-  ;; correctly returns `org-cycle'. However, most other modes bind
-  ;; "TAB" (which is translated from <tab>), and calling
-  ;; (key-binding "TAB") does not place return that command into
-  ;; our command-2 local. So we cheat.
-  ;;
-  (if (string= yas-trigger-key "<tab>")
-      "TAB"
-    yas-trigger-key))
-
-(defun yas--fallback (&optional from-trigger-key-p)
-  "Fallback after expansion has failed.
-
-Common gateway for `yas-expand-from-trigger-key' and
-`yas-expand-from-keymap'."
-  (cond ((eq yas-fallback-behavior 'return-nil)
-         ;; return nil
-         nil)
-        ((eq yas-fallback-behavior 'call-other-command)
-         (let* ((yas-minor-mode nil)
-                (yas--direct-keymaps nil)
-                (yas-trigger-key (yas--trigger-key-for-fallback))
-                (keys-1 (this-command-keys-vector))
-                (keys-2 (and yas-trigger-key
-                             from-trigger-key-p
-                             (stringp yas-trigger-key)
-                             (read-kbd-macro yas-trigger-key)))
-                (command-1 (and keys-1 (key-binding keys-1)))
-                (command-2 (and keys-2 (key-binding keys-2)))
-                ;; An (ugly) safety: prevents infinite recursion of
-                ;; yas-expand* calls.
-                (command (or (and (symbolp command-1)
-                                  (not (string-match "yas-expand" (symbol-name 
command-1)))
-                                  command-1)
-                             (and (symbolp command-2)
-                                  command-2))))
-           (when (and (commandp command)
-                      (not (string-match "yas-expand" (symbol-name command))))
-             (setq this-command command)
-             (call-interactively command))))
-        ((and (listp yas-fallback-behavior)
-              (cdr yas-fallback-behavior)
-              (eq 'apply (car yas-fallback-behavior)))
-         (if (cddr yas-fallback-behavior)
-             (apply (cadr yas-fallback-behavior)
-                    (cddr yas-fallback-behavior))
-           (when (commandp (cadr yas-fallback-behavior))
-             (setq this-command (cadr yas-fallback-behavior))
-             (call-interactively (cadr yas-fallback-behavior)))))
-        (t
-         ;; also return nil if all the other fallbacks have failed
-         nil)))
-
-
-
-;;; Utils for snippet development:
-
-(defun yas--all-templates (tables)
-  "Return all snippet tables applicable for the current buffer.
-
-Honours `yas-choose-tables-first', `yas-choose-keys-first' and
-`yas-buffer-local-condition'"
-  (when yas-choose-tables-first
-    (setq tables (list (yas--prompt-for-table tables))))
-  (mapcar #'cdr
-          (if yas-choose-keys-first
-              (let ((key (yas--prompt-for-keys
-                          (mapcan #'yas--table-all-keys tables))))
-                (when key
-                  (mapcan #'(lambda (table)
-                              (yas--fetch table key))
-                          tables)))
-            (remove-duplicates (mapcan #'yas--table-templates tables)
-                               :test #'equal))))
-
-(defun yas-insert-snippet (&optional no-condition)
-  "Choose a snippet to expand, pop-up a list of choices according
-to `yas--prompt-function'.
-
-With prefix argument NO-CONDITION, bypass filtering of snippets
-by condition."
-  (interactive "P")
-  (setq yas--condition-cache-timestamp (current-time))
-  (let* ((yas-buffer-local-condition (or (and no-condition
-                                              'always)
-                                         yas-buffer-local-condition))
-         (templates (yas--all-templates (yas--get-snippet-tables)))
-         (yas--current-template (and templates
-                                    (or (and (rest templates) ;; more than one 
template for same key
-                                             (yas--prompt-for-template 
templates))
-                                        (car templates))))
-         (where (if (region-active-p)
-                    (cons (region-beginning) (region-end))
-                  (cons (point) (point)))))
-    (if yas--current-template
-        (yas-expand-snippet (yas--template-content yas--current-template)
-                            (car where)
-                            (cdr where)
-                            (yas--template-expand-env yas--current-template))
-      (yas--message 3 "No snippets can be inserted here!"))))
-
-(defun yas-visit-snippet-file ()
-  "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)
-  (let* ((yas-buffer-local-condition 'always)
-         (templates (yas--all-templates (yas--get-snippet-tables)))
-         (yas-prompt-functions '(yas-ido-prompt yas-completing-prompt))
-         (template (and templates
-                        (or (yas--prompt-for-template templates
-                                                     "Choose a snippet 
template to edit: ")
-                            (car templates)))))
-
-    (if template
-        (yas--visit-snippet-file-1 template)
-      (message "No snippets tables active!"))))
-
-(defun yas--visit-snippet-file-1 (template)
-  (let ((file (yas--template-file template)))
-    (cond ((and file (file-readable-p file))
-           (find-file-other-window file)
-           (snippet-mode)
-           (set (make-local-variable 'yas--editing-template) template))
-          (file
-           (message "Original file %s no longer exists!" file))
-          (t
-           (switch-to-buffer (format "*%s*"(yas--template-name template)))
-           (let ((type 'snippet))
-             (when (listp (yas--template-content template))
-               (insert (format "# type: command\n"))
-               (setq type 'command))
-             (insert (format "# key: %s\n" (yas--template-key template)))
-             (insert (format "# name: %s\n" (yas--template-name template)))
-             (when (yas--template-keybinding template)
-               (insert (format "# binding: %s\n" (yas--template-keybinding 
template))))
-             (when (yas--template-expand-env template)
-               (insert (format "# expand-env: %s\n" (yas--template-expand-env 
template))))
-             (when (yas--template-condition template)
-               (insert (format "# condition: %s\n" (yas--template-condition 
template))))
-             (insert "# --\n")
-             (insert (if (eq type 'command)
-                         (pp-to-string (yas--template-content template))
-                       (yas--template-content template))))
-           (snippet-mode)
-           (set (make-local-variable 'yas--editing-template) template)))))
-
-(defun yas--guess-snippet-directories-1 (table)
-  "Guesses possible snippet subdirectories for TABLE."
-  (cons (yas--table-name table)
-        (mapcan #'(lambda (parent)
-                    (yas--guess-snippet-directories-1
-                     parent))
-                (yas--table-parents table))))
-
-(defun yas--guess-snippet-directories (&optional table)
-  "Try to guess suitable directories based on the current active
-tables (or optional TABLE).
-
-Returns a list of elemts (TABLE . DIRS) where TABLE is a
-`yas--table' object and DIRS is a list of all possible directories
-where snippets of table might exist."
-  (let ((main-dir (replace-regexp-in-string
-                   "/+$" ""
-                   (or (first (or (yas-snippet-dirs)
-                                  (setq yas-snippet-dirs 
'("~/.emacs.d/snippets")))))))
-        (tables (or (and table
-                         (list table))
-                    (yas--get-snippet-tables))))
-    ;; HACK! the snippet table created here is actually registered!
-    ;;
-    (unless (or table (gethash major-mode yas--tables))
-      (push (yas--table-get-create major-mode)
-            tables))
-
-    (mapcar #'(lambda (table)
-                (cons table
-                      (mapcar #'(lambda (subdir)
-                                  (concat main-dir "/" subdir))
-                              (yas--guess-snippet-directories-1 table))))
-            tables)))
-
-(defun yas--make-directory-maybe (table-and-dirs &optional main-table-string)
-  "Returns a dir inside  TABLE-AND-DIRS, prompts for creation if none exists."
-  (or (some #'(lambda (dir) (when (file-directory-p dir) dir)) (cdr 
table-and-dirs))
-      (let ((candidate (first (cdr table-and-dirs))))
-        (unless (file-writable-p (file-name-directory candidate))
-          (error (yas--format "%s is not writable." candidate)))
-        (if (y-or-n-p (format "Guessed directory (%s) for%s%s table \"%s\" 
does not exist! Create? "
-                              candidate
-                              (if (gethash (yas--table-mode (car 
table-and-dirs))
-                                           yas--tables)
-                                  ""
-                                " brand new")
-                              (or main-table-string
-                                  "")
-                              (yas--table-name (car table-and-dirs))))
-            (progn
-              (make-directory candidate 'also-make-parents)
-              ;; create the .yas-parents file here...
-              candidate)))))
-
-(defun yas-new-snippet (&optional no-template)
-  "Pops a new buffer for writing a snippet.
-
-Expands a snippet-writing snippet, unless the optional prefix arg
-NO-TEMPLATE is non-nil."
-  (interactive "P")
-  (let ((guessed-directories (yas--guess-snippet-directories)))
-
-    (switch-to-buffer "*new snippet*")
-    (erase-buffer)
-    (kill-all-local-variables)
-    (snippet-mode)
-    (yas-minor-mode 1)
-    (set (make-local-variable 'yas--guessed-modes) (mapcar #'(lambda (d)
-                                                              (yas--table-mode 
(car d)))
-                                                          guessed-directories))
-    (unless no-template (yas-expand-snippet "\
-# -*- mode: snippet -*-
-# name: $1
-# key: ${2:${1:$(replace-regexp-in-string \"\\\\\\\\(\\\\\\\\w+\\\\\\\\).*\" 
\"\\\\\\\\1\" yas-text)}}${3:
-# binding: ${4:direct-keybinding}}${5:
-# expand-env: ((${6:some-var} ${7:some-value}))}${8:
-# type: command}
-# --
-$0"))))
-
-(defun yas--compute-major-mode-and-parents (file)
-  "Given FILE, find the nearest snippet directory for a given
-mode, then return a list (MODE-SYM PARENTS), the mode's symbol and a list
-representing one or more of the mode's parents.
-
-Note that MODE-SYM need not be the symbol of a real major mode,
-neither do the elements of PARENTS."
-  (let* ((file-dir (and file
-                        (directory-file-name (or (some #'(lambda (special)
-                                                           
(locate-dominating-file file special))
-                                                       '(".yas-setup.el"
-                                                         ".yas-make-groups"
-                                                         ".yas-parents"))
-                                                 (directory-file-name 
(file-name-directory file))))))
-         (parents-file-name (concat file-dir "/.yas-parents"))
-         (major-mode-name (and file-dir
-                               (file-name-nondirectory file-dir)))
-         (major-mode-sym (or (and major-mode-name
-                                  (intern major-mode-name))))
-         (parents (when (file-readable-p parents-file-name)
-                         (mapcar #'intern
-                                 (split-string
-                                  (with-temp-buffer
-                                    (insert-file-contents parents-file-name)
-                                    (buffer-substring-no-properties (point-min)
-                                                                    
(point-max))))))))
-    (when major-mode-sym
-      (cons major-mode-sym parents))))
-
-(defvar yas--editing-template nil
-  "Supporting variable for `yas-load-snippet-buffer' and `yas--visit-snippet'")
-
-(defvar yas--current-template nil
-  "Holds the current template being expanded into a snippet.")
-
-(defvar yas--guessed-modes nil
-  "List of guessed modes supporting `yas-load-snippet-buffer'.")
-
-(defun yas--read-table ()
-  "Ask user for a snippet table, help with some guessing."
-  (let ((prompt (if (and (featurep 'ido)
-                         ido-mode)
-                    'ido-completing-read 'completing-read)))
-    (unless yas--guessed-modes
-      (set (make-local-variable 'yas--guessed-modes)
-           (or (yas--compute-major-mode-and-parents buffer-file-name))))
-    (intern
-     (funcall prompt (format "Choose or enter a table (yas guesses %s): "
-                             (if yas--guessed-modes
-                                 (first yas--guessed-modes)
-                               "nothing"))
-              (mapcar #'symbol-name yas--guessed-modes)
-              nil
-              nil
-              nil
-              nil
-              (if (first yas--guessed-modes)
-                  (symbol-name (first yas--guessed-modes)))))))
-
-(defun yas-load-snippet-buffer (table &optional interactive)
-  "Parse and load current buffer's snippet definition into TABLE.
-
-TABLE is a symbol naming a passed to `yas--table-get-create'.
-
-When called interactively, prompt for the table name and
-whether (and where) to save the snippet, then quit the window."
-  (interactive (list (yas--read-table) t))
-  (cond
-   ;;  We have `yas--editing-template', this buffer's content comes from a
-   ;;  template which is already loaded and neatly positioned,...
-   ;;
-   (yas--editing-template
-    (yas-define-snippets-1 (yas--parse-template (yas--template-file 
yas--editing-template))
-                           (yas--template-table yas--editing-template)))
-   ;; Try to use `yas--guessed-modes'. If we don't have that use the
-   ;; value from `yas--compute-major-mode-and-parents'
-   ;;
-   (t
-    (unless yas--guessed-modes
-      (set (make-local-variable 'yas--guessed-modes) (or 
(yas--compute-major-mode-and-parents buffer-file-name))))
-    (let* ((table (yas--table-get-create table)))
-      (set (make-local-variable 'yas--editing-template)
-           (yas-define-snippets-1 (yas--parse-template buffer-file-name)
-                                  table)))))
-
-  (when (and interactive
-             (or
-              ;; Only offer to save this if it looks like a library or new
-              ;; snippet (loaded from elisp, from a dir in `yas-snippet-dirs'
-              ;; which is not the first, or from an unwritable file)
-              ;;
-              (not (yas--template-file yas--editing-template))
-              (not (file-writable-p (yas--template-file 
yas--editing-template)))
-              (and (listp yas-snippet-dirs)
-                   (second yas-snippet-dirs)
-                   (not (string-match (expand-file-name (first 
yas-snippet-dirs))
-                                      (yas--template-file 
yas--editing-template)))))
-             (y-or-n-p (yas--format "Looks like a library or new snippet. Save 
to new file? ")))
-    (let* ((option (first (yas--guess-snippet-directories (yas--template-table 
yas--editing-template))))
-           (chosen (and option
-                        (yas--make-directory-maybe option))))
-      (when chosen
-        (let ((default-file-name (or (and (yas--template-file 
yas--editing-template)
-                                          (file-name-nondirectory 
(yas--template-file yas--editing-template)))
-                                     (yas--template-name 
yas--editing-template))))
-          (write-file (concat chosen "/"
-                              (read-from-minibuffer (format "File name to 
create in %s? " chosen)
-                                                    default-file-name)))
-          (setf (yas--template-file yas--editing-template) 
buffer-file-name)))))
-  (when interactive
-    (quit-window interactive)
-    (yas--message 3 "Snippet \"%s\" loaded for %s."
-                  (yas--template-name yas--editing-template)
-                  (yas--table-name (yas--template-table 
yas--editing-template)))))
-
-
-(defun yas-tryout-snippet (&optional debug)
-  "Test current buffers's snippet template in other buffer."
-  (interactive "P")
-  (let* ((major-mode-and-parent (yas--compute-major-mode-and-parents 
buffer-file-name))
-         (parsed (yas--parse-template))
-         (test-mode (or (and (car major-mode-and-parent)
-                             (fboundp (car major-mode-and-parent))
-                             (car major-mode-and-parent))
-                        (first yas--guessed-modes)
-                        (intern (read-from-minibuffer (yas--format "Please 
input a mode: ")))))
-         (yas--current-template
-          (and parsed
-               (fboundp test-mode)
-               (yas--populate-template (yas--make-blank-template)
-                                      :table       nil ;; no tables for 
ephemeral snippets
-                                      :key         (first parsed)
-                                      :content     (second parsed)
-                                      :name        (third parsed)
-                                      :expand-env  (sixth parsed)))))
-    (cond (yas--current-template
-           (let ((buffer-name (format "*testing snippet: %s*" 
(yas--template-name yas--current-template))))
-             (kill-buffer (get-buffer-create buffer-name))
-             (switch-to-buffer (get-buffer-create buffer-name))
-             (setq buffer-undo-list nil)
-             (condition-case nil (funcall test-mode) (error nil))
-            (yas-minor-mode 1)
-             (setq buffer-read-only nil)
-             (yas-expand-snippet (yas--template-content yas--current-template)
-                                 (point-min)
-                                 (point-max)
-                                 (yas--template-expand-env 
yas--current-template))
-             (when (and debug
-                        (require 'yasnippet-debug nil t))
-               (add-hook 'post-command-hook 'yas-debug-snippet-vars nil t))))
-          (t
-           (yas--message 3 "Cannot test snippet for unknown major mode")))))
-
-(defun yas--template-fine-group (template)
-  (car (last (or (yas--template-group template)
-                 (yas--template-perm-group template)))))
-
-(defun yas-describe-tables (&optional choose)
-  "Display snippets for each table."
-  (interactive "P")
-  (let* ((by-name-hash (and choose
-                            (y-or-n-p "Show by namehash? ")))
-         (buffer (get-buffer-create "*YASnippet tables*"))
-         (active-tables (yas--get-snippet-tables))
-         (remain-tables (let ((all))
-                          (maphash #'(lambda (k v)
-                                       (unless (find v active-tables)
-                                         (push v all)))
-                                   yas--tables)
-                          all))
-         (table-lists (list active-tables remain-tables))
-         (original-buffer (current-buffer))
-         (continue t)
-         (yas--condition-cache-timestamp (current-time)))
-    (with-current-buffer buffer
-      (setq buffer-read-only nil)
-      (erase-buffer)
-      (cond ((not by-name-hash)
-             (insert "YASnippet tables: \n")
-             (while (and table-lists
-                         continue)
-               (dolist (table (car table-lists))
-                 (yas--describe-pretty-table table original-buffer))
-               (setq table-lists (cdr table-lists))
-               (when table-lists
-                 (yas--create-snippet-xrefs)
-                 (display-buffer buffer)
-                 (setq continue (and choose (y-or-n-p "Show also non-active 
tables? ")))))
-             (yas--create-snippet-xrefs)
-             (help-mode)
-             (goto-char 1))
-            (t
-             (insert "\n\nYASnippet tables by NAMEHASH: \n")
-             (dolist (table (append active-tables remain-tables))
-               (insert (format "\nSnippet table `%s':\n\n" (yas--table-name 
table)))
-               (let ((keys))
-                 (maphash #'(lambda (k v)
-                              (push k keys))
-                          (yas--table-hash table))
-                 (dolist (key keys)
-                   (insert (format "   key %s maps snippets: %s\n" key
-                                   (let ((names))
-                                     (maphash #'(lambda (k v)
-                                                  (push k names))
-                                              (gethash key (yas--table-hash 
table)))
-                                     names))))))))
-      (goto-char 1)
-      (setq buffer-read-only t))
-    (display-buffer buffer)))
-
-(defun yas--describe-pretty-table (table &optional original-buffer)
-  (insert (format "\nSnippet table `%s'"
-                  (yas--table-name table)))
-  (if (yas--table-parents table)
-      (insert (format " parents: %s\n"
-                      (mapcar #'yas--table-name
-                              (yas--table-parents table))))
-    (insert "\n"))
-  (insert (make-string 100 ?-) "\n")
-  (insert "group                   state name                                  
  key             binding\n")
-  (let ((groups-hash (make-hash-table :test #'equal)))
-    (maphash #'(lambda (k v)
-                 (let ((group (or (yas--template-fine-group v)
-                                  "(top level)")))
-                   (when (yas--template-name v)
-                     (puthash group
-                              (cons v (gethash group groups-hash))
-                              groups-hash))))
-             (yas--table-uuidhash table))
-    (maphash
-     #'(lambda (group templates)
-         (setq group (truncate-string-to-width group 25 0 ?  "..."))
-         (insert (make-string 100 ?-) "\n")
-         (dolist (p templates)
-           (let ((name (truncate-string-to-width (propertize (format 
"\\\\snippet `%s'" (yas--template-name p))
-                                                             'yasnippet p)
-                                                 50 0 ? "..."))
-                 (group (prog1 group
-                          (setq group (make-string (length group) ? ))))
-                 (condition-string (let ((condition (yas--template-condition 
p)))
-                                     (if (and condition
-                                              original-buffer)
-                                         (with-current-buffer original-buffer
-                                           (if (yas--eval-condition condition)
-                                               "(y)"
-                                             "(s)"))
-                                       "(a)"))))
-             (insert group " ")
-             (insert condition-string " ")
-             (insert name
-                     (if (string-match "\\.\\.\\.$" name)
-                         "'"
-                       " ")
-                     " ")
-             (insert (truncate-string-to-width (or (yas--template-key p) "")
-                                               15 0 ?  "...") " ")
-             (insert (truncate-string-to-width (key-description 
(yas--template-keybinding p))
-                                               15 0 ?  "...") " ")
-             (insert "\n"))))
-     groups-hash)))
-
-
-
-;;; User convenience functions, for using in snippet definitions
-
-(defvar yas-modified-p nil
-  "Non-nil if field has been modified by user or transformation.")
-
-(defvar yas-moving-away-p nil
-  "Non-nil if user is about to exit field.")
-
-(defvar yas-text nil
-  "Contains current field text.")
-
-(defun yas-substr (str pattern &optional subexp)
-  "Search PATTERN in STR and return SUBEXPth match.
-
-If found, the content of subexp group SUBEXP (default 0) is
-  returned, or else the original STR will be returned."
-  (let ((grp (or subexp 0)))
-    (save-match-data
-      (if (string-match pattern str)
-          (match-string-no-properties grp str)
-        str))))
-
-(defun yas-choose-value (&rest possibilities)
-  "Prompt for a string in POSSIBILITIES and return it.
-
-The last element of POSSIBILITIES may be a list of strings."
-  (unless (or yas-moving-away-p
-              yas-modified-p)
-    (setq possibilities (nreverse possibilities))
-    (setq possibilities (if (listp (car possibilities))
-                            (append (reverse (car possibilities)) (rest 
possibilities))
-                                   possibilities))
-    (some #'(lambda (fn)
-              (funcall fn "Choose: " possibilities))
-          yas-prompt-functions)))
-
-(defun yas-key-to-value (alist)
-  "Prompt for a string in the list POSSIBILITIES and return it."
-  (unless (or yas-moving-away-p
-              yas-modified-p)
-    (let ((key (read-key-sequence "")))
-      (when (stringp key)
-        (or (cdr (find key alist :key #'car :test #'string=))
-            key)))))
-
-(defun yas-throw (text)
-  "Throw a yas--exception with TEXT as the reason."
-  (throw 'yas--exception (cons 'yas--exception text)))
-
-(defun yas-verify-value (possibilities)
-  "Verify that the current field value is in POSSIBILITIES
-
-Otherwise throw exception."
-  (when (and yas-moving-away-p (notany #'(lambda (pos) (string= pos yas-text)) 
possibilities))
-    (yas-throw (yas--format "Field only allows %s" possibilities))))
-
-(defun yas-field-value (number)
-  "Get the string for field with NUMBER.
-
-Use this in primary and mirror transformations to tget."
-  (let* ((snippet (car (yas--snippets-at-point)))
-         (field (and snippet
-                     (yas--snippet-find-field snippet number))))
-    (when field
-      (yas--field-text-for-display field))))
-
-(defun yas-text ()
-  "Return `yas-text' if that exists and is non-empty, else nil."
-  (if (and yas-text
-           (not (string= "" yas-text)))
-      yas-text))
-
-(defun yas-selected-text ()
-  "Return `yas-selected-text' if that exists and is non-empty, else nil."
-  (if (and yas-selected-text
-           (not (string= "" yas-selected-text)))
-      yas-selected-text))
-
-(defun yas--get-field-once (number &optional transform-fn)
-  (unless yas-modified-p
-    (if transform-fn
-        (funcall transform-fn (yas-field-value number))
-      (yas-field-value number))))
-
-(defun yas-default-from-field (number)
-  (unless yas-modified-p
-    (yas-field-value number)))
-
-(defun yas-inside-string ()
-  (equal 'font-lock-string-face (get-char-property (1- (point)) 'face)))
-
-(defun yas-unimplemented (&optional missing-feature)
-  (if yas--current-template
-      (if (y-or-n-p (format "This snippet is unimplemented (missing %s) Visit 
the snippet definition? "
-                            (or missing-feature
-                                "something")))
-          (yas--visit-snippet-file-1 yas--current-template))
-    (message "No implementation. Missing %s" (or missing-feature 
"something"))))
-
-
-;;; Snippet expansion and field management
-
-(defvar yas--active-field-overlay nil
-  "Overlays the currently active field.")
-
-(defvar yas--field-protection-overlays nil
-  "Two overlays protect the current active field ")
-
-(defconst yas--prefix nil
-  "A prefix argument for expansion direct from keybindings")
-
-(defvar yas-selected-text nil
-  "The selected region deleted on the last snippet expansion.")
-
-(defvar yas--start-column nil
-  "The column where the snippet expansion started.")
-
-(make-variable-buffer-local 'yas--active-field-overlay)
-(make-variable-buffer-local 'yas--field-protection-overlays)
-(put 'yas--active-field-overlay 'permanent-local t)
-(put 'yas--field-protection-overlays 'permanent-local t)
-
-(defstruct (yas--snippet (:constructor yas--make-snippet ()))
-  "A snippet.
-
-..."
-  (fields '())
-  (exit nil)
-  (id (yas--snippet-next-id) :read-only t)
-  (control-overlay nil)
-  active-field
-  ;; stacked expansion: the `previous-active-field' slot saves the
-  ;; active field where the child expansion took place
-  previous-active-field
-  force-exit)
-
-(defstruct (yas--field (:constructor yas--make-field (number start end 
parent-field)))
-  "A field."
-  number
-  start end
-  parent-field
-  (mirrors '())
-  (transform nil)
-  (modified-p nil)
-  next)
-
-(defstruct (yas--mirror (:constructor yas--make-mirror (start end transform)))
-  "A mirror."
-  start end
-  (transform nil)
-  parent-field
-  next)
-
-(defstruct (yas--exit (:constructor yas--make-exit (marker)))
-  marker
-  next)
-
-(defun yas--apply-transform (field-or-mirror field &optional empty-on-nil-p)
-  "Calculate transformed string for FIELD-OR-MIRROR from FIELD.
-
-If there is no transform for ht field, return nil.
-
-If there is a transform but it returns nil, return the empty
-string iff EMPTY-ON-NIL-P is true."
-  (let* ((yas-text (yas--field-text-for-display field))
-         (text yas-text)
-         (yas-modified-p (yas--field-modified-p field))
-         (yas-moving-away-p nil)
-         (transform (if (yas--mirror-p field-or-mirror)
-                        (yas--mirror-transform field-or-mirror)
-                      (yas--field-transform field-or-mirror)))
-         (start-point (if (yas--mirror-p field-or-mirror)
-                          (yas--mirror-start field-or-mirror)
-                        (yas--field-start field-or-mirror)))
-         (transformed (and transform
-                           (save-excursion
-                             (goto-char start-point)
-                             (let ((ret (yas--eval-lisp transform)))
-                               (or ret (and empty-on-nil-p "")))))))
-    transformed))
-
-(defsubst yas--replace-all (from to &optional text)
-  "Replace all occurance from FROM to TO.
-
-With optional string TEXT do it in that string."
-  (if text
-      (replace-regexp-in-string (regexp-quote from) to text t t)
-    (goto-char (point-min))
-    (while (search-forward from nil t)
-      (replace-match to t t text))))
-
-(defun yas--snippet-find-field (snippet number)
-  (find-if #'(lambda (field)
-               (eq number (yas--field-number field)))
-           (yas--snippet-fields snippet)))
-
-(defun yas--snippet-sort-fields (snippet)
-  "Sort the fields of SNIPPET in navigation order."
-  (setf (yas--snippet-fields snippet)
-        (sort (yas--snippet-fields snippet)
-              #'yas--snippet-field-compare)))
-
-(defun yas--snippet-field-compare (field1 field2)
-  "Compare two fields. The field with a number is sorted first.
-If they both have a number, compare through the number. If neither
-have, compare through the field's start point"
-  (let ((n1 (yas--field-number field1))
-        (n2 (yas--field-number field2)))
-    (if n1
-        (if n2
-            (or (zerop n2) (and (not (zerop n1))
-                                (< n1 n2)))
-          (not (zerop n1)))
-      (if n2
-          (zerop n2)
-        (< (yas--field-start field1)
-           (yas--field-start field2))))))
-
-(defun yas--field-probably-deleted-p (snippet field)
-  "Guess if SNIPPET's FIELD should be skipped."
-  (and
-   ;; field must be zero lentgh
-   ;;
-   (zerop (- (yas--field-start field) (yas--field-end field)))
-   ;; skip if:
-   (or
-    ;;  1) is a nested field and it's been modified
-    ;;
-    (and (yas--field-parent-field field)
-         (yas--field-modified-p field))
-    ;;  2) ends just before the snippet end
-    ;;
-    (and (eq field (car (last (yas--snippet-fields snippet))))
-         (= (yas--field-start field) (overlay-end 
(yas--snippet-control-overlay snippet)))))
-   ;; the field numbered 0, just before the exit marker, should
-   ;; never be skipped
-   ;;
-   (not (zerop (yas--field-number field)))))
-
-(defun yas--snippets-at-point (&optional all-snippets)
-  "Return a sorted list of snippets at point, most recently
-inserted first."
-  (sort
-   (remove nil (remove-duplicates (mapcar #'(lambda (ov)
-                                              (overlay-get ov 'yas--snippet))
-                                          (if all-snippets
-                                              (overlays-in (point-min) 
(point-max))
-                                            (nconc (overlays-at (point)) 
(overlays-at (1- (point))))))))
-   #'(lambda (s1 s2)
-       (<= (yas--snippet-id s2) (yas--snippet-id s1)))))
-
-(defun yas-next-field-or-maybe-expand ()
-  "Try to expand a snippet at a key before point, otherwise
-delegate to `yas-next-field'."
-  (interactive)
-  (if yas-triggers-in-field
-      (let ((yas-fallback-behavior 'return-nil)
-            (active-field (overlay-get yas--active-field-overlay 'yas--field)))
-        (when active-field
-          (unless (yas-expand-from-trigger-key active-field)
-            (yas-next-field))))
-    (yas-next-field)))
-
-(defun yas-next-field (&optional arg)
-  "Navigate to next field.  If there's none, exit the snippet."
-  (interactive)
-  (let* ((arg (or arg
-                  1))
-         (snippet (first (yas--snippets-at-point)))
-         (active-field (overlay-get yas--active-field-overlay 'yas--field))
-         (live-fields (remove-if #'(lambda (field)
-                                     (and (not (eq field active-field))
-                                          (yas--field-probably-deleted-p 
snippet field)))
-                                 (yas--snippet-fields snippet)))
-         (active-field-pos (position active-field live-fields))
-         (target-pos (and active-field-pos (+ arg active-field-pos)))
-         (target-field (and target-pos (nth target-pos live-fields))))
-    ;; First check if we're moving out of a field with a transform
-    ;;
-    (when (and active-field
-               (yas--field-transform active-field))
-      (let* ((yas-moving-away-p t)
-             (yas-text (yas--field-text-for-display active-field))
-             (text yas-text)
-             (yas-modified-p (yas--field-modified-p active-field)))
-        ;; primary field transform: exit call to field-transform
-        (yas--eval-lisp (yas--field-transform active-field))))
-    ;; Now actually move...
-    (cond ((and target-pos (>= target-pos (length live-fields)))
-           (yas-exit-snippet snippet))
-          (target-field
-           (yas--move-to-field snippet target-field))
-          (t
-           nil))))
-
-(defun yas--place-overlays (snippet field)
-  "Correctly place overlays for SNIPPET's FIELD"
-  (yas--make-move-field-protection-overlays snippet field)
-  (yas--make-move-active-field-overlay snippet field))
-
-(defun yas--move-to-field (snippet field)
-  "Update SNIPPET to move to field FIELD.
-
-Also create some protection overlays"
-  (goto-char (yas--field-start field))
-  (yas--place-overlays snippet field)
-  (overlay-put yas--active-field-overlay 'yas--field field)
-  (let ((number (yas--field-number field)))
-    ;; check for the special ${0: ...} field
-    (if (and number (zerop number))
-        (progn
-          (set-mark (yas--field-end field))
-          (setf (yas--snippet-force-exit snippet)
-                (or (yas--field-transform field)
-                    t)))
-      ;; make this field active
-      (setf (yas--snippet-active-field snippet) field)
-      ;; primary field transform: first call to snippet transform
-      (unless (yas--field-modified-p field)
-        (if (yas--field-update-display field snippet)
-            (yas--update-mirrors snippet)
-          (setf (yas--field-modified-p field) nil))))))
-
-(defun yas-prev-field ()
-  "Navigate to prev field.  If there's none, exit the snippet."
-  (interactive)
-  (yas-next-field -1))
-
-(defun yas-abort-snippet (&optional snippet)
-  (interactive)
-  (let ((snippet (or snippet
-                     (car (yas--snippets-at-point)))))
-    (when snippet
-      (setf (yas--snippet-force-exit snippet) t))))
-
-(defun yas-exit-snippet (snippet)
-  "Goto exit-marker of SNIPPET."
-  (interactive (list (first (yas--snippets-at-point))))
-  (when snippet
-    (setf (yas--snippet-force-exit snippet) t)
-    (goto-char (if (yas--snippet-exit snippet)
-                   (yas--exit-marker (yas--snippet-exit snippet))
-                 (overlay-end (yas--snippet-control-overlay snippet))))))
-
-(defun yas-exit-all-snippets ()
-  "Exit all snippets."
-  (interactive)
-  (mapc #'(lambda (snippet)
-            (yas-exit-snippet snippet)
-            (yas--check-commit-snippet))
-        (yas--snippets-at-point 'all-snippets)))
-
-
-;;; Some low level snippet-routines:
-
-(defmacro yas--inhibit-overlay-hooks (&rest body)
-  "Run BODY with `yas--inhibit-overlay-hooks' set to t."
-  (declare (indent 0))
-  `(let ((yas--inhibit-overlay-hooks t))
-     (progn ,@body)))
-
-(defvar yas-snippet-beg nil "Beginning position of the last snippet commited.")
-(defvar yas-snippet-end nil "End position of the last snippet commited.")
-
-(defun yas--commit-snippet (snippet)
-  "Commit SNIPPET, but leave point as it is.  This renders the
-snippet as ordinary text."
-
-  (let ((control-overlay (yas--snippet-control-overlay snippet)))
-    ;;
-    ;; Save the end of the moribund snippet in case we need to revive it
-    ;; its original expansion.
-    ;;
-    (when (and control-overlay
-               (overlay-buffer control-overlay))
-      (setq yas-snippet-beg (overlay-start control-overlay))
-      (setq yas-snippet-end (overlay-end control-overlay))
-      (delete-overlay control-overlay))
-
-    (yas--inhibit-overlay-hooks
-      (when yas--active-field-overlay
-        (delete-overlay yas--active-field-overlay))
-      (when yas--field-protection-overlays
-        (mapc #'delete-overlay yas--field-protection-overlays)))
-
-    ;; stacked expansion: if the original expansion took place from a
-    ;; field, make sure we advance it here at least to
-    ;; `yas-snippet-end'...
-    ;;
-    (let ((previous-field (yas--snippet-previous-active-field snippet)))
-      (when (and yas-snippet-end previous-field)
-        (yas--advance-end-maybe previous-field yas-snippet-end)))
-
-    ;; Convert all markers to points,
-    ;;
-    (yas--markers-to-points snippet)
-
-    ;; Take care of snippet revival
-    ;;
-    (if yas-snippet-revival
-        (push `(apply yas--snippet-revive ,yas-snippet-beg ,yas-snippet-end 
,snippet)
-              buffer-undo-list)
-      ;; Dismember the snippet... this is useful if we get called
-      ;; again from `yas--take-care-of-redo'....
-      (setf (yas--snippet-fields snippet) nil)))
-
-  (yas--message 3 "Snippet %s exited." (yas--snippet-id snippet)))
-
-(defun yas--safely-run-hooks (hook-var)
-  (condition-case error
-      (run-hooks hook-var)
-    (error
-     (yas--message 3 "%s error: %s" hook-var (error-message-string error)))))
-
-
-(defun yas--check-commit-snippet ()
-  "Checks if point exited the currently active field of the
-snippet, if so cleans up the whole snippet up."
-  (let* ((snippets (yas--snippets-at-point 'all-snippets))
-         (snippets-left snippets)
-         (snippet-exit-transform))
-    (dolist (snippet snippets)
-      (let ((active-field (yas--snippet-active-field snippet)))
-        (setq snippet-exit-transform (yas--snippet-force-exit snippet))
-        (cond ((or snippet-exit-transform
-                   (not (and active-field (yas--field-contains-point-p 
active-field))))
-               (setq snippets-left (delete snippet snippets-left))
-               (setf (yas--snippet-force-exit snippet) nil)
-               (yas--commit-snippet snippet))
-              ((and active-field
-                    (or (not yas--active-field-overlay)
-                        (not (overlay-buffer yas--active-field-overlay))))
-               ;;
-               ;; stacked expansion: this case is mainly for recent
-               ;; snippet exits that place us back int the field of
-               ;; another snippet
-               ;;
-               (save-excursion
-                 (yas--move-to-field snippet active-field)
-                 (yas--update-mirrors snippet)))
-              (t
-               nil))))
-    (unless (or (null snippets) snippets-left)
-      (if snippet-exit-transform
-          (yas--eval-lisp-no-saves snippet-exit-transform))
-      (yas--safely-run-hooks 'yas-after-exit-snippet-hook))))
-
-;; Apropos markers-to-points:
-;;
-;; This was found useful for performance reasons, so that an
-;; excessive number of live markers aren't kept around in the
-;; `buffer-undo-list'. However, in `markers-to-points', the
-;; set-to-nil markers can't simply be discarded and replaced with
-;; fresh ones in `points-to-markers'. The original marker that was
-;; just set to nil has to be reused.
-;;
-;; This shouldn't bring horrible problems with undo/redo, but it
-;; you never know
-;;
-(defun yas--markers-to-points (snippet)
-  "Convert all markers in SNIPPET to a cons (POINT . MARKER)
-where POINT is the original position of the marker and MARKER is
-the original marker object with the position set to nil."
-  (dolist (field (yas--snippet-fields snippet))
-    (let ((start (marker-position (yas--field-start field)))
-          (end (marker-position (yas--field-end field))))
-      (set-marker (yas--field-start field) nil)
-      (set-marker (yas--field-end field) nil)
-      (setf (yas--field-start field) (cons start (yas--field-start field)))
-      (setf (yas--field-end field) (cons end (yas--field-end field))))
-    (dolist (mirror (yas--field-mirrors field))
-      (let ((start (marker-position (yas--mirror-start mirror)))
-            (end (marker-position (yas--mirror-end mirror))))
-        (set-marker (yas--mirror-start mirror) nil)
-        (set-marker (yas--mirror-end mirror) nil)
-        (setf (yas--mirror-start mirror) (cons start (yas--mirror-start 
mirror)))
-        (setf (yas--mirror-end mirror) (cons end (yas--mirror-end mirror))))))
-  (let ((snippet-exit (yas--snippet-exit snippet)))
-    (when snippet-exit
-      (let ((exit (marker-position (yas--exit-marker snippet-exit))))
-        (set-marker (yas--exit-marker snippet-exit) nil)
-        (setf (yas--exit-marker snippet-exit) (cons exit (yas--exit-marker 
snippet-exit)))))))
-
-(defun yas--points-to-markers (snippet)
-  "Convert all cons (POINT . MARKER) in SNIPPET to markers. This
-is done by setting MARKER to POINT with `set-marker'."
-  (dolist (field (yas--snippet-fields snippet))
-    (setf (yas--field-start field) (set-marker (cdr (yas--field-start field))
-                                              (car (yas--field-start field))))
-    (setf (yas--field-end field) (set-marker (cdr (yas--field-end field))
-                                            (car (yas--field-end field))))
-    (dolist (mirror (yas--field-mirrors field))
-      (setf (yas--mirror-start mirror) (set-marker (cdr (yas--mirror-start 
mirror))
-                                                  (car (yas--mirror-start 
mirror))))
-      (setf (yas--mirror-end mirror) (set-marker (cdr (yas--mirror-end mirror))
-                                                (car (yas--mirror-end 
mirror))))))
-  (let ((snippet-exit (yas--snippet-exit snippet)))
-    (when snippet-exit
-      (setf (yas--exit-marker snippet-exit) (set-marker (cdr (yas--exit-marker 
snippet-exit))
-                                                       (car (yas--exit-marker 
snippet-exit)))))))
-
-(defun yas--field-contains-point-p (field &optional point)
-  (let ((point (or point
-                   (point))))
-    (and (>= point (yas--field-start field))
-         (<= point (yas--field-end field)))))
-
-(defun yas--field-text-for-display (field)
-  "Return the propertized display text for field FIELD.  "
-  (buffer-substring (yas--field-start field) (yas--field-end field)))
-
-(defun yas--undo-in-progress ()
-  "True if some kind of undo is in progress"
-  (or undo-in-progress
-      (eq this-command 'undo)
-      (eq this-command 'redo)))
-
-(defun yas--make-control-overlay (snippet start end)
-  "Creates the control overlay that surrounds the snippet and
-holds the keymap."
-  (let ((overlay (make-overlay start
-                               end
-                               nil
-                               nil
-                               t)))
-    (overlay-put overlay 'keymap yas-keymap)
-    (overlay-put overlay 'priority 100)
-    (overlay-put overlay 'yas--snippet snippet)
-    overlay))
-
-(defun yas-skip-and-clear-or-delete-char (&optional field)
-  "Clears unmodified field if at field start, skips to next tab.
-
-Otherwise deletes a character normally by calling `delete-char'."
-  (interactive)
-  (let ((field (or field
-                   (and yas--active-field-overlay
-                        (overlay-buffer yas--active-field-overlay)
-                        (overlay-get yas--active-field-overlay 'yas--field)))))
-    (cond ((and field
-                (not (yas--field-modified-p field))
-                (eq (point) (marker-position (yas--field-start field))))
-           (yas--skip-and-clear field)
-           (yas-next-field 1))
-          (t
-           (call-interactively 'delete-char)))))
-
-(defun yas--skip-and-clear (field)
-  "Deletes the region of FIELD and sets it modified state to t"
-  ;; Just before skipping-and-clearing the field, mark its children
-  ;; fields as modified, too. If the childen have mirrors-in-fields
-  ;; this prevents them from updating erroneously (we're skipping and
-  ;; deleting!).
-  ;;
-  (yas--mark-this-and-children-modified field)
-  (delete-region (yas--field-start field) (yas--field-end field)))
-
-(defun yas--mark-this-and-children-modified (field)
-  (setf (yas--field-modified-p field) t)
-  (let ((fom (yas--field-next field)))
-    (while (and fom
-                (yas--fom-parent-field fom))
-      (when (and (eq (yas--fom-parent-field fom) field)
-                 (yas--field-p fom))
-        (yas--mark-this-and-children-modified fom))
-      (setq fom (yas--fom-next fom)))))
-
-(defun yas--make-move-active-field-overlay (snippet field)
-  "Place the active field overlay in SNIPPET's FIELD.
-
-Move the overlay, or create it if it does not exit."
-  (if (and yas--active-field-overlay
-           (overlay-buffer yas--active-field-overlay))
-      (move-overlay yas--active-field-overlay
-                    (yas--field-start field)
-                    (yas--field-end field))
-    (setq yas--active-field-overlay
-          (make-overlay (yas--field-start field)
-                        (yas--field-end field)
-                        nil nil t))
-    (overlay-put yas--active-field-overlay 'priority 100)
-    (overlay-put yas--active-field-overlay 'face 'yas-field-highlight-face)
-    (overlay-put yas--active-field-overlay 'yas--snippet snippet)
-    (overlay-put yas--active-field-overlay 'modification-hooks 
'(yas--on-field-overlay-modification))
-    (overlay-put yas--active-field-overlay 'insert-in-front-hooks
-                 '(yas--on-field-overlay-modification))
-    (overlay-put yas--active-field-overlay 'insert-behind-hooks
-                 '(yas--on-field-overlay-modification))))
-
-(defvar yas--inhibit-overlay-hooks nil
-  "Bind this temporarity to non-nil to prevent running 
`yas--on-*-modification'.")
-
-(defun yas--on-field-overlay-modification (overlay after? beg end &optional 
length)
-  "Clears the field and updates mirrors, conditionally.
-
-Only clears the field if it hasn't been modified and it point it
-at field start. This hook doesn't do anything if an undo is in
-progress."
-  (unless (or yas--inhibit-overlay-hooks
-              (yas--undo-in-progress))
-    (let* ((field (overlay-get overlay 'yas--field))
-           (number (and field (yas--field-number field)))
-           (snippet (overlay-get yas--active-field-overlay 'yas--snippet)))
-      (cond (after?
-             (yas--advance-end-maybe field (overlay-end overlay))
-             (save-excursion
-               (yas--field-update-display field snippet))
-             (yas--update-mirrors snippet))
-            (field
-             (when (and (not after?)
-                        (not (yas--field-modified-p field))
-                        (eq (point) (if (markerp (yas--field-start field))
-                                        (marker-position (yas--field-start 
field))
-                                      (yas--field-start field))))
-               (yas--skip-and-clear field))
-             (setf (yas--field-modified-p field) t))))))
-
-;;; Apropos protection overlays:
-;;
-;; These exist for nasty users who will try to delete parts of the
-;; snippet outside the active field. Actual protection happens in
-;; `yas--on-protection-overlay-modification'.
-;;
-;; Currently this signals an error which inhibits the command. For
-;; commands that move point (like `kill-line'), point is restored in
-;; the `yas--post-command-handler' using a global
-;; `yas--protection-violation' variable.
-;;
-;; Alternatively, I've experimented with an implementation that
-;; commits the snippet before actually calling `this-command'
-;; interactively, and then signals an eror, which is ignored. but
-;; blocks all other million modification hooks. This presented some
-;; problems with stacked expansion.
-;;
-(defun yas--make-move-field-protection-overlays (snippet field)
-  "Place protection overlays surrounding SNIPPET's FIELD.
-
-Move the overlays, or create them if they do not exit."
-  (let ((start (yas--field-start field))
-        (end (yas--field-end field)))
-    ;; First check if the (1+ end) is contained in the buffer,
-    ;; otherwise we'll have to do a bit of cheating and silently
-    ;; insert a newline. the `(1+ (buffer-size))' should prevent this
-    ;; when using stacked expansion
-    ;;
-    (when (< (buffer-size) end)
-      (save-excursion
-        (yas--inhibit-overlay-hooks
-          (goto-char (point-max))
-          (newline))))
-    ;; go on to normal overlay creation/moving
-    ;;
-    (cond ((and yas--field-protection-overlays
-                (every #'overlay-buffer yas--field-protection-overlays))
-           (move-overlay (first yas--field-protection-overlays) (1- start) 
start)
-           (move-overlay (second yas--field-protection-overlays) end (1+ end)))
-          (t
-           (setq yas--field-protection-overlays
-                 (list (make-overlay (1- start) start nil t nil)
-                       (make-overlay end (1+ end) nil t nil)))
-           (dolist (ov yas--field-protection-overlays)
-             (overlay-put ov 'face 'yas--field-debug-face)
-             (overlay-put ov 'yas--snippet snippet)
-             ;; (overlay-put ov 'evaporate t)
-             (overlay-put ov 'modification-hooks 
'(yas--on-protection-overlay-modification)))))))
-
-(defvar yas--protection-violation nil
-  "When non-nil, signals attempts to erronesly exit or modify the snippet.
-
-Functions in the `post-command-hook', for example
-`yas--post-command-handler' can check it and reset its value to
-nil. The variables value is the point where the violation
-originated")
-
-(defun yas--on-protection-overlay-modification (overlay after? beg end 
&optional length)
-  "Signals a snippet violation, then issues error.
-
-The error should be ignored in `debug-ignored-errors'"
-  (unless yas--inhibit-overlay-hooks
-    (cond ((not (or after?
-                    (yas--undo-in-progress)))
-           (setq yas--protection-violation (point))
-           (error "Exit the snippet first!")))))
-
-(add-to-list 'debug-ignored-errors "^Exit the snippet first!$")
-
-
-;; Snippet expansion and "stacked" expansion:
-;;
-;; Stacked expansion is when you try to expand a snippet when already
-;; inside a snippet expansion.
-;;
-;; The parent snippet does not run its fields modification hooks
-;; (`yas--on-field-overlay-modification' and
-;; `yas--on-protection-overlay-modification') while the child snippet
-;; is active. This means, among other things, that the mirrors of the
-;; parent snippet are not updated, this only happening when one exits
-;; the child snippet.
-;;
-;; Unfortunately, this also puts some ugly (and not fully-tested)
-;; bits of code in `yas-expand-snippet' and
-;; `yas--commit-snippet'. I've tried to mark them with "stacked
-;; expansion:".
-;;
-;; This was thought to be safer in in an undo/redo perpective, but
-;; maybe the correct implementation is to make the globals
-;; `yas--active-field-overlay' and `yas--field-protection-overlays' be
-;; snippet-local and be active even while the child snippet is
-;; running. This would mean a lot of overlay modification hooks
-;; running, but if managed correctly (including overlay priorities)
-;; they should account for all situations...
-;;
-(defun yas-expand-snippet (content &optional start end expand-env)
-  "Expand snippet CONTENT at current point.
-
-Text between START and END will be deleted before inserting
-template. EXPAND-ENV is are let-style variable to value bindings
-considered when expanding the snippet."
-  (run-hooks 'yas-before-expand-snippet-hook)
-
-  ;;
-  (let* ((yas-selected-text (or yas-selected-text
-                                (and (region-active-p)
-                                     (buffer-substring-no-properties 
(region-beginning)
-                                                                     
(region-end)))))
-         (start (or start
-                    (and (region-active-p)
-                         (region-beginning))
-                    (point)))
-         (end (or end
-                  (and (region-active-p)
-                       (region-end))
-                  (point)))
-         (to-delete (and start
-                         end
-                         (buffer-substring-no-properties start end)))
-         snippet)
-    (goto-char start)
-    (setq yas--indent-original-column (current-column))
-    ;; Delete the region to delete, this *does* get undo-recorded.
-    ;;
-    (when (and to-delete
-               (> end start))
-      (delete-region start end))
-
-    (cond ((listp content)
-           ;; x) This is a snippet-command
-           ;;
-           (yas--eval-lisp-no-saves content))
-          (t
-           ;; x) This is a snippet-snippet :-)
-           ;;
-           ;;    Narrow the region down to the content, shoosh the
-           ;;    `buffer-undo-list', and create the snippet, the new
-           ;;    snippet updates its mirrors once, so we are left with
-           ;;    some plain text.  The undo action for deleting this
-           ;;    plain text will get recorded at the end.
-           ;;
-           ;;    stacked expansion: also shoosh the overlay modification hooks
-           (save-restriction
-             (narrow-to-region start start)
-             (let ((buffer-undo-list t))
-               ;; snippet creation might evaluate users elisp, which
-               ;; might generate errors, so we have to be ready to catch
-               ;; them mostly to make the undo information
-               ;;
-               (setq yas--start-column (save-restriction (widen) 
(current-column)))
-               (yas--inhibit-overlay-hooks
-                 (setq snippet
-                       (if expand-env
-                           (eval `(let* ,expand-env
-                                    (insert content)
-                                    (yas--snippet-create (point-min) 
(point-max))))
-                         (insert content)
-                         (yas--snippet-create (point-min) (point-max)))))))
-
-           ;; stacked-expansion: This checks for stacked expansion, save the
-           ;; `yas--previous-active-field' and advance its boudary.
-           ;;
-           (let ((existing-field (and yas--active-field-overlay
-                                      (overlay-buffer 
yas--active-field-overlay)
-                                      (overlay-get yas--active-field-overlay 
'yas--field))))
-             (when existing-field
-               (setf (yas--snippet-previous-active-field snippet) 
existing-field)
-               (yas--advance-end-maybe existing-field (overlay-end 
yas--active-field-overlay))))
-
-           ;; Exit the snippet immediately if no fields
-           ;;
-           (unless (yas--snippet-fields snippet)
-             (yas-exit-snippet snippet))
-
-           ;; Push two undo actions: the deletion of the inserted contents of
-           ;; the new snippet (without the "key") followed by an apply of
-           ;; `yas--take-care-of-redo' on the newly inserted snippet boundaries
-           ;;
-           ;; A small exception, if `yas-also-auto-indent-first-line'
-           ;; is t and `yas--indent' decides to indent the line to a
-           ;; point before the actual expansion point, undo would be
-           ;; messed up. We call the early point "newstart"".  case,
-           ;; and attempt to fix undo.
-           ;;
-           (let ((newstart (overlay-start (yas--snippet-control-overlay 
snippet)))
-                 (end (overlay-end (yas--snippet-control-overlay snippet))))
-             (when (< newstart start)
-               (push (cons (make-string (- start newstart) ? ) newstart) 
buffer-undo-list))
-             (push (cons newstart end) buffer-undo-list)
-             (push `(apply yas--take-care-of-redo ,start ,end ,snippet)
-                   buffer-undo-list))
-           ;; Now, schedule a move to the first field
-           ;;
-           (let ((first-field (car (yas--snippet-fields snippet))))
-             (when first-field
-               (sit-for 0) ;; fix issue 125
-               (yas--move-to-field snippet first-field)))
-           (yas--message 3 "snippet expanded.")
-           t))))
-
-(defun yas--take-care-of-redo (beg end snippet)
-  "Commits SNIPPET, which in turn pushes an undo action for
-reviving it.
-
-Meant to exit in the `buffer-undo-list'."
-  ;; slightly optimize: this action is only needed for snippets with
-  ;; at least one field
-  (when (yas--snippet-fields snippet)
-    (yas--commit-snippet snippet)))
-
-(defun yas--snippet-revive (beg end snippet)
-  "Revives the SNIPPET and creates a control overlay from BEG to
-END.
-
-BEG and END are, we hope, the original snippets boudaries. All
-the markers/points exiting existing inside SNIPPET should point
-to their correct locations *at the time the snippet is revived*.
-
-After revival, push the `yas--take-care-of-redo' in the
-`buffer-undo-list'"
-  ;; Reconvert all the points to markers
-  ;;
-  (yas--points-to-markers snippet)
-  ;; When at least one editable field existed in the zombie snippet,
-  ;; try to revive the whole thing...
-  ;;
-  (let ((target-field (or (yas--snippet-active-field snippet)
-                          (car (yas--snippet-fields snippet)))))
-    (when target-field
-      (setf (yas--snippet-control-overlay snippet) (yas--make-control-overlay 
snippet beg end))
-      (overlay-put (yas--snippet-control-overlay snippet) 'yas--snippet 
snippet)
-
-      (yas--move-to-field snippet target-field)
-
-      (push `(apply yas--take-care-of-redo ,beg ,end ,snippet)
-            buffer-undo-list))))
-
-(defun yas--snippet-create (begin end)
-  "Creates a snippet from an template inserted between BEGIN and END.
-
-Returns the newly created snippet."
-  (let ((snippet (yas--make-snippet)))
-    (goto-char begin)
-    (yas--snippet-parse-create snippet)
-
-    ;; Sort and link each field
-    (yas--snippet-sort-fields snippet)
-
-    ;; Create keymap overlay for snippet
-    (setf (yas--snippet-control-overlay snippet)
-          (yas--make-control-overlay snippet (point-min) (point-max)))
-
-    ;; Move to end
-    (goto-char (point-max))
-
-    snippet))
-
-
-;;; Apropos adjacencies and "fom's":
-;;
-;; Once the $-constructs bits like "$n" and "${:n" are deleted in the
-;; recently expanded snippet, we might actually have many fields,
-;; mirrors (and the snippet exit) in the very same position in the
-;; buffer. Therefore we need to single-link the
-;; fields-or-mirrors-or-exit (which I have abbreviated to "fom")
-;; according to their original positions in the buffer.
-;;
-;; Then we have operation `yas--advance-end-maybe' and
-;; `yas--advance-start-maybe', which conditionally push the starts and
-;; ends of these foms down the chain.
-;;
-;; This allows for like the printf with the magic ",":
-;;
-;;   printf ("${1:%s}\\n"${1:$(if (string-match "%" text) "," "\);")}  \
-;;   $2${1:$(if (string-match "%" text) "\);" "")}$0
-;;
-(defun yas--fom-start (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-start fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-start fom))
-        (t
-         (yas--exit-marker fom))))
-
-(defun yas--fom-end (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-end fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-end fom))
-        (t
-         (yas--exit-marker fom))))
-
-(defun yas--fom-next (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-next fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-next fom))
-        (t
-         (yas--exit-next fom))))
-
-(defun yas--fom-parent-field (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-parent-field fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-parent-field fom))
-        (t
-         nil)))
-
-(defun yas--calculate-adjacencies (snippet)
-  "Calculate adjacencies for fields or mirrors of SNIPPET.
-
-This is according to their relative positions in the buffer, and
-has to be called before the $-constructs are deleted."
-  (flet ((yas--fom-set-next-fom (fom nextfom)
-                               (cond ((yas--field-p fom)
-                                      (setf (yas--field-next fom) nextfom))
-                                     ((yas--mirror-p fom)
-                                      (setf (yas--mirror-next fom) nextfom))
-                                     (t
-                                      (setf (yas--exit-next fom) nextfom))))
-         (yas--compare-fom-begs (fom1 fom2)
-                               (if (= (yas--fom-start fom2) (yas--fom-start 
fom1))
-                                   (yas--mirror-p fom2)
-                                 (>= (yas--fom-start fom2) (yas--fom-start 
fom1))))
-         (yas--link-foms (fom1 fom2)
-                        (yas--fom-set-next-fom fom1 fom2)))
-    ;; make some yas--field, yas--mirror and yas--exit soup
-    (let ((soup))
-      (when (yas--snippet-exit snippet)
-        (push (yas--snippet-exit snippet) soup))
-      (dolist (field (yas--snippet-fields snippet))
-        (push field soup)
-        (dolist (mirror (yas--field-mirrors field))
-          (push mirror soup)))
-      (setq soup
-            (sort soup
-                  #'yas--compare-fom-begs))
-      (when soup
-        (reduce #'yas--link-foms soup)))))
-
-(defun yas--calculate-mirrors-in-fields (snippet mirror)
-  "Attempt to assign a parent field of SNIPPET to the mirror MIRROR.
-
-Use the tighest containing field if more than one field contains
-the mirror. Intended to be called *before* the dollar-regions are
-deleted."
-  (let ((min (point-min))
-        (max (point-max)))
-    (dolist (field (yas--snippet-fields snippet))
-      (when (and (<= (yas--field-start field) (yas--mirror-start mirror))
-                 (<= (yas--mirror-end mirror) (yas--field-end field))
-               (< min (yas--field-start field))
-               (< (yas--field-end field) max))
-          (setq min (yas--field-start field)
-                max (yas--field-end field))
-          (setf (yas--mirror-parent-field mirror) field)))))
-
-(defun yas--advance-end-maybe (fom newend)
-  "Maybe advance FOM's end to NEWEND if it needs it.
-
-If it does, also:
-
-* call `yas--advance-start-maybe' on FOM's next fom.
-
-* in case FOM is field call `yas--advance-end-maybe' on its parent
-  field
-
-Also, if FOM is an exit-marker, always call
-`yas--advance-start-maybe' on its next fom. This is beacuse
-exit-marker have identical start and end markers.
-
-"
-  (cond ((and fom (< (yas--fom-end fom) newend))
-         (set-marker (yas--fom-end fom) newend)
-         (yas--advance-start-maybe (yas--fom-next fom) newend)
-         (yas--advance-end-of-parents-maybe (yas--fom-parent-field fom) 
newend))
-        ((yas--exit-p fom)
-         (yas--advance-start-maybe (yas--fom-next fom) newend))))
-
-(defun yas--advance-start-maybe (fom newstart)
-  "Maybe advance FOM's start to NEWSTART if it needs it.
-
-If it does, also call `yas--advance-end-maybe' on FOM."
-  (when (and fom (< (yas--fom-start fom) newstart))
-    (set-marker (yas--fom-start fom) newstart)
-    (yas--advance-end-maybe fom newstart)))
-
-(defun yas--advance-end-of-parents-maybe (field newend)
-  "Like `yas--advance-end-maybe' but for parent fields.
-
-Only works for fields and doesn't care about the start of the
-next FOM. Works its way up recursively for parents of parents."
-  (when (and field
-             (< (yas--field-end field) newend))
-    (set-marker (yas--field-end field) newend)
-    (yas--advance-end-of-parents-maybe (yas--field-parent-field field) 
newend)))
-
-(defvar yas--dollar-regions nil
-  "When expanding the snippet the \"parse-create\" functions add
-  cons cells to this var")
-
-(defvar yas--backquote-markers-and-strings nil
-  "List of (MARKER . STRING) marking where the the values
-  from backquoted lisp expressions should be inserted at the end of
-  expansion" )
-
-(defun yas--snippet-parse-create (snippet)
-  "Parse a recently inserted snippet template, creating all
-necessary fields, mirrors and exit points.
-
-Meant to be called in a narrowed buffer, does various passes"
-  (let ((parse-start (point)))
-    ;; Reset the yas--dollar-regions
-    ;;
-    (setq yas--dollar-regions nil)
-    ;; protect just the backquotes
-    ;;
-    (yas--protect-escapes nil '(?`))
-    ;; replace all backquoted expressions
-    ;;
-    (goto-char parse-start)
-    (yas--save-backquotes)
-    ;; protect escaped characters
-    ;;
-    (yas--protect-escapes)
-    ;; parse fields with {}
-    ;;
-    (goto-char parse-start)
-    (yas--field-parse-create snippet)
-    ;; parse simple mirrors and fields
-    ;;
-    (goto-char parse-start)
-    (yas--simple-mirror-parse-create snippet)
-    ;; parse mirror transforms
-    ;;
-    (goto-char parse-start)
-    (yas--transform-mirror-parse-create snippet)
-    ;; calculate adjacencies of fields and mirrors
-    ;;
-    (yas--calculate-adjacencies snippet)
-    ;; Delete $-constructs
-    ;;
-    (yas--delete-regions yas--dollar-regions)
-    ;; restore backquoted expression values
-    ;;
-    (yas--restore-backquotes)
-    ;; restore escapes
-    ;;
-    (goto-char parse-start)
-    (yas--restore-escapes)
-    ;; update mirrors for the first time
-    ;;
-    (yas--update-mirrors snippet)
-    ;; indent the best we can
-    ;;
-    (goto-char parse-start)
-    (yas--indent snippet)))
-
-(defun yas--indent-according-to-mode (snippet-markers)
-  "Indent current line according to mode, preserving
-SNIPPET-MARKERS."
-  ;;; Apropos indenting problems....
-  ;;
-  ;; `indent-according-to-mode' uses whatever `indent-line-function'
-  ;; is available. Some implementations of these functions delete text
-  ;; before they insert. If there happens to be a marker just after
-  ;; the text being deleted, the insertion actually happens after the
-  ;; marker, which misplaces it.
-  ;;
-  ;; This would also happen if we had used overlays with the
-  ;; `front-advance' property set to nil.
-  ;;
-  ;; This is why I have these `trouble-markers', they are the ones at
-  ;; they are the ones at the first non-whitespace char at the line
-  ;; (i.e. at `yas--real-line-beginning'. After indentation takes place
-  ;; we should be at the correct to restore them to. All other
-  ;; non-trouble-markers have been *pushed* and don't need special
-  ;; attention.
-  ;;
-  (goto-char (yas--real-line-beginning))
-  (let ((trouble-markers (remove-if-not #'(lambda (marker)
-                                            (= marker (point)))
-                                        snippet-markers)))
-    (save-restriction
-      (widen)
-      (condition-case err
-          (indent-according-to-mode)
-        (error (yas--message 3 "Warning: `yas--indent-according-to-mode' 
having problems running %s" indent-line-function)
-               nil)))
-    (mapc #'(lambda (marker)
-              (set-marker marker (point)))
-          trouble-markers)))
-
-(defvar yas--indent-original-column nil)
-(defun yas--indent (snippet)
-  (let ((snippet-markers (yas--collect-snippet-markers snippet)))
-    ;; Look for those $>
-    (save-excursion
-      (while (re-search-forward "$>" nil t)
-        (delete-region (match-beginning 0) (match-end 0))
-        (when (not (eq yas-indent-line 'auto))
-          (yas--indent-according-to-mode snippet-markers))))
-    ;; Now do stuff for 'fixed and 'auto
-    (save-excursion
-      (cond ((eq yas-indent-line 'fixed)
-             (while (and (zerop (forward-line))
-                         (zerop (current-column)))
-               (indent-to-column yas--indent-original-column)))
-            ((eq yas-indent-line 'auto)
-             (let ((end (set-marker (make-marker) (point-max)))
-                   (indent-first-line-p yas-also-auto-indent-first-line))
-               (while (and (zerop (if indent-first-line-p
-                                      (prog1
-                                          (forward-line 0)
-                                        (setq indent-first-line-p nil))
-                                    (forward-line 1)))
-                           (not (eobp))
-                           (<= (point) end))
-                 (yas--indent-according-to-mode snippet-markers))))
-            (t
-             nil)))))
-
-(defun yas--collect-snippet-markers (snippet)
-  "Make a list of all the markers used by SNIPPET."
-  (let (markers)
-    (dolist (field (yas--snippet-fields snippet))
-      (push (yas--field-start field) markers)
-      (push (yas--field-end field) markers)
-      (dolist (mirror (yas--field-mirrors field))
-        (push (yas--mirror-start mirror) markers)
-        (push (yas--mirror-end mirror) markers)))
-    (let ((snippet-exit (yas--snippet-exit snippet)))
-      (when (and snippet-exit
-                 (marker-buffer (yas--exit-marker snippet-exit)))
-        (push (yas--exit-marker snippet-exit) markers)))
-    markers))
-
-(defun yas--real-line-beginning ()
-  (let ((c (char-after (line-beginning-position)))
-        (n (line-beginning-position)))
-    (while (or (eql c ?\ )
-               (eql c ?\t))
-      (incf n)
-      (setq c (char-after n)))
-    n))
-
-(defun yas--escape-string (escaped)
-  (concat "YASESCAPE" (format "%d" escaped) "PROTECTGUARD"))
-
-(defun yas--protect-escapes (&optional text escaped)
-  "Protect all escaped characters with their numeric ASCII value.
-
-With optional string TEXT do it in string instead of buffer."
-  (let ((changed-text text)
-        (text-provided-p text))
-    (mapc #'(lambda (escaped)
-              (setq changed-text
-                    (yas--replace-all (concat "\\" (char-to-string escaped))
-                                     (yas--escape-string escaped)
-                                     (when text-provided-p changed-text))))
-          (or escaped yas--escaped-characters))
-    changed-text))
-
-(defun yas--restore-escapes (&optional text escaped)
-  "Restore all escaped characters from their numeric ASCII value.
-
-With optional string TEXT do it in string instead of the buffer."
-  (let ((changed-text text)
-        (text-provided-p text))
-    (mapc #'(lambda (escaped)
-              (setq changed-text
-                    (yas--replace-all (yas--escape-string escaped)
-                                     (char-to-string escaped)
-                                     (when text-provided-p changed-text))))
-          (or escaped yas--escaped-characters))
-    changed-text))
-
-(defun yas--save-backquotes ()
-  "Save all the \"`(lisp-expression)`\"-style expression
-with their evaluated value into `yas--backquote-markers-and-strings'"
-  (while (re-search-forward yas--backquote-lisp-expression-regexp nil t)
-    (let ((current-string (match-string-no-properties 1)) transformed)
-      (delete-region (match-beginning 0) (match-end 0))
-      (setq transformed (yas--eval-lisp (yas--read-lisp (yas--restore-escapes 
current-string '(?`)))))
-      (goto-char (match-beginning 0))
-      (when transformed
-        (let ((marker (make-marker)))
-          (insert "Y") ;; quite horrendous, I love it :)
-          (set-marker marker (point))
-          (insert "Y")
-          (push (cons marker transformed) 
yas--backquote-markers-and-strings))))))
-
-(defun yas--restore-backquotes ()
-  "Replace all the markers in
-`yas--backquote-markers-and-strings' with their values"
-  (while yas--backquote-markers-and-strings
-    (let* ((marker-and-string (pop yas--backquote-markers-and-strings))
-           (marker (car marker-and-string))
-           (string (cdr marker-and-string)))
-      (save-excursion
-        (goto-char marker)
-        (delete-char -1)
-        (insert string)
-        (delete-char 1)
-        (set-marker marker nil)))))
-
-(defun yas--scan-sexps (from count)
-  (condition-case err
-      (with-syntax-table (standard-syntax-table)
-        (scan-sexps from count))
-    (error
-     nil)))
-
-(defun yas--make-marker (pos)
-  "Create a marker at POS with `nil' `marker-insertion-type'"
-  (let ((marker (set-marker (make-marker) pos)))
-    (set-marker-insertion-type marker nil)
-    marker))
-
-(defun yas--field-parse-create (snippet &optional parent-field)
-  "Parse most field expressions, except for the simple one \"$n\".
-
-The following count as a field:
-
-* \"${n: text}\", for a numbered field with default text, as long as N is not 
0;
-
-* \"${n: text$(expression)}, the same with a lisp expression;
-  this is caught with the curiously named 
`yas--multi-dollar-lisp-expression-regexp'
-
-* the same as above but unnumbered, (no N:) and number is calculated 
automatically.
-
-When multiple expressions are found, only the last one counts."
-  ;;
-  (save-excursion
-    (while (re-search-forward yas--field-regexp nil t)
-      (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
-             (number (and (match-string-no-properties 1)
-                          (string-to-number (match-string-no-properties 1))))
-             (brand-new-field (and real-match-end-0
-                                   ;; break if on "$(" immediately
-                                   ;; after the ":", this will be
-                                   ;; caught as a mirror with
-                                   ;; transform later.
-                                   (not (save-match-data
-                                          (eq (string-match "$[ \t\n]*("
-                                                            
(match-string-no-properties 2)) 0)))
-                                   ;; allow ${0: some exit text}
-                                   ;; (not (and number (zerop number)))
-                                   (yas--make-field number
-                                                   (yas--make-marker 
(match-beginning 2))
-                                                   (yas--make-marker (1- 
real-match-end-0))
-                                                   parent-field))))
-        (when brand-new-field
-          (goto-char real-match-end-0)
-          (push (cons (1- real-match-end-0) real-match-end-0)
-                yas--dollar-regions)
-          (push (cons (match-beginning 0) (match-beginning 2))
-                yas--dollar-regions)
-          (push brand-new-field (yas--snippet-fields snippet))
-          (save-excursion
-            (save-restriction
-              (narrow-to-region (yas--field-start brand-new-field) 
(yas--field-end brand-new-field))
-              (goto-char (point-min))
-              (yas--field-parse-create snippet brand-new-field)))))))
-  ;; if we entered from a parent field, now search for the
-  ;; `yas--multi-dollar-lisp-expression-regexp'. THis is used for
-  ;; primary field transformations
-  ;;
-  (when parent-field
-    (save-excursion
-      (while (re-search-forward yas--multi-dollar-lisp-expression-regexp nil t)
-        (let* ((real-match-end-1 (yas--scan-sexps (match-beginning 1) 1)))
-          ;; commit the primary field transformation if:
-          ;;
-          ;; 1. we don't find it in yas--dollar-regions (a subnested
-          ;; field) might have already caught it.
-          ;;
-          ;; 2. we really make sure we have either two '$' or some
-          ;; text and a '$' after the colon ':'. This is a FIXME: work
-          ;; my regular expressions and end these ugly hacks.
-          ;;
-          (when (and real-match-end-1
-                     (not (member (cons (match-beginning 0)
-                                        real-match-end-1)
-                                  yas--dollar-regions))
-                     (not (eq ?:
-                              (char-before (1- (match-beginning 1))))))
-            (let ((lisp-expression-string (buffer-substring-no-properties 
(match-beginning 1)
-                                                                          
real-match-end-1)))
-              (setf (yas--field-transform parent-field)
-                    (yas--read-lisp (yas--restore-escapes 
lisp-expression-string))))
-            (push (cons (match-beginning 0) real-match-end-1)
-                  yas--dollar-regions)))))))
-
-(defun yas--transform-mirror-parse-create (snippet)
-  "Parse the \"${n:$(lisp-expression)}\" mirror transformations."
-  (while (re-search-forward yas--transform-mirror-regexp nil t)
-    (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
-           (number (string-to-number (match-string-no-properties 1)))
-           (field (and number
-                       (not (zerop number))
-                       (yas--snippet-find-field snippet number)))
-           (brand-new-mirror
-            (and real-match-end-0
-                 field
-                 (yas--make-mirror (yas--make-marker (match-beginning 0))
-                                  (yas--make-marker (match-beginning 0))
-                                  (yas--read-lisp
-                                   (yas--restore-escapes
-                                    (buffer-substring-no-properties 
(match-beginning 2)
-                                                                    (1- 
real-match-end-0))))))))
-      (when brand-new-mirror
-        (push brand-new-mirror
-              (yas--field-mirrors field))
-        (yas--calculate-mirrors-in-fields snippet brand-new-mirror)
-        (push (cons (match-beginning 0) real-match-end-0) 
yas--dollar-regions)))))
-
-(defun yas--simple-mirror-parse-create (snippet)
-  "Parse the simple \"$n\" fields/mirrors/exitmarkers."
-  (while (re-search-forward yas--simple-mirror-regexp nil t)
-    (let ((number (string-to-number (match-string-no-properties 1))))
-      (cond ((zerop number)
-
-             (setf (yas--snippet-exit snippet)
-                   (yas--make-exit (yas--make-marker (match-end 0))))
-             (save-excursion
-               (goto-char (match-beginning 0))
-               (when yas-wrap-around-region
-                 (cond (yas-selected-text
-                        (insert yas-selected-text))
-                       ((and (eq yas-wrap-around-region 'cua)
-                             cua-mode
-                             (get-register ?0))
-                        (insert (prog1 (get-register ?0)
-                                  (set-register ?0 nil))))))
-               (push (cons (point) (yas--exit-marker (yas--snippet-exit 
snippet)))
-                     yas--dollar-regions)))
-            (t
-             (let ((field (yas--snippet-find-field snippet number)))
-               (if field
-                   (let ((brand-new-mirror (yas--make-mirror
-                                            (yas--make-marker (match-beginning 
0))
-                                            (yas--make-marker (match-beginning 
0))
-                                            nil)))
-                     (push brand-new-mirror
-                           (yas--field-mirrors field))
-                     (yas--calculate-mirrors-in-fields snippet 
brand-new-mirror))
-                 (push (yas--make-field number
-                                       (yas--make-marker (match-beginning 0))
-                                       (yas--make-marker (match-beginning 0))
-                                       nil)
-                       (yas--snippet-fields snippet))))
-             (push (cons (match-beginning 0) (match-end 0))
-                   yas--dollar-regions))))))
-
-(defun yas--delete-regions (regions)
-  "Sort disjuct REGIONS by start point, then delete from the back."
-  (mapc #'(lambda (reg)
-            (delete-region (car reg) (cdr reg)))
-        (sort regions
-              #'(lambda (r1 r2)
-                  (>= (car r1) (car r2))))))
-
-(defun yas--update-mirrors (snippet)
-  "Updates all the mirrors of SNIPPET."
-  (save-excursion
-    (let* ((fields (copy-list (yas--snippet-fields snippet)))
-           (field (car fields)))
-      (while field
-        (dolist (mirror (yas--field-mirrors field))
-          (let ((mirror-parent-field (yas--mirror-parent-field mirror)))
-            ;; updatte this mirror
-            ;;
-            (yas--mirror-update-display mirror field)
-            ;; for mirrors-in-fields: schedule a possible
-            ;; parent field for reupdting later on
-            ;;
-            (when mirror-parent-field
-              (add-to-list 'fields mirror-parent-field 'append #'eq))
-            ;; `yas--place-overlays' is needed if the active field and
-            ;; protected overlays have been changed because of insertions
-            ;; in `yas--mirror-update-display'
-            ;;
-            (when (eq field (yas--snippet-active-field snippet))
-              (yas--place-overlays snippet field))))
-        (setq fields (cdr fields))
-        (setq field (car fields))))))
-
-(defun yas--mirror-update-display (mirror field)
-  "Update MIRROR according to FIELD (and mirror transform)."
-
-  (let* ((mirror-parent-field (yas--mirror-parent-field mirror))
-         (reflection (and (not (and mirror-parent-field
-                                    (yas--field-modified-p 
mirror-parent-field)))
-                          (or (yas--apply-transform mirror field 'empty-on-nil)
-                              (yas--field-text-for-display field)))))
-    (when (and reflection
-               (not (string= reflection (buffer-substring-no-properties 
(yas--mirror-start mirror)
-                                                                        
(yas--mirror-end mirror)))))
-      (goto-char (yas--mirror-start mirror))
-      (yas--inhibit-overlay-hooks
-        (insert reflection))
-      (if (> (yas--mirror-end mirror) (point))
-          (delete-region (point) (yas--mirror-end mirror))
-        (set-marker (yas--mirror-end mirror) (point))
-        (yas--advance-start-maybe (yas--mirror-next mirror) (point))
-        ;; super-special advance
-        (yas--advance-end-of-parents-maybe mirror-parent-field (point))))))
-
-(defun yas--field-update-display (field snippet)
-  "Much like `yas--mirror-update-display', but for fields"
-  (when (yas--field-transform field)
-    (let ((transformed (and (not (eq (yas--field-number field) 0))
-                            (yas--apply-transform field field)))
-          (point (point)))
-      (when (and transformed
-                 (not (string= transformed (buffer-substring-no-properties 
(yas--field-start field)
-                                                                           
(yas--field-end field)))))
-        (setf (yas--field-modified-p field) t)
-        (goto-char (yas--field-start field))
-        (yas--inhibit-overlay-hooks
-          (insert transformed)
-          (if (> (yas--field-end field) (point))
-              (delete-region (point) (yas--field-end field))
-            (set-marker (yas--field-end field) (point))
-            (yas--advance-start-maybe (yas--field-next field) (point)))
-          t)))))
-
-
-;;; Post-command hook:
-
-(defun yas--post-command-handler ()
-  "Handles various yasnippet conditions after each command."
-  (cond (yas--protection-violation
-         (goto-char yas--protection-violation)
-         (setq yas--protection-violation nil))
-        ((eq 'undo this-command)
-         ;;
-         ;; After undo revival the correct field is sometimes not
-         ;; restored correctly, this condition handles that
-         ;;
-         (let* ((snippet (car (yas--snippets-at-point)))
-                (target-field (and snippet
-                                   (find-if-not #'(lambda (field)
-                                                    
(yas--field-probably-deleted-p snippet field))
-                                                (remove nil
-                                                        (cons 
(yas--snippet-active-field snippet)
-                                                              
(yas--snippet-fields snippet)))))))
-           (when target-field
-             (yas--move-to-field snippet target-field))))
-        ((not (yas--undo-in-progress))
-         ;; When not in an undo, check if we must commit the snippet
-         ;; (user exited it).
-         (yas--check-commit-snippet))))
-
-;;; Fancy docs:
-;;
-;; The docstrings for some functions are generated dynamically
-;; depending on the context.
-;;
-(put 'yas-expand  'function-documentation
-     '(yas--expand-from-trigger-key-doc))
-(defun yas--expand-from-trigger-key-doc ()
-  "A doc synthethizer for `yas--expand-from-trigger-key-doc'."
-  (let ((fallback-description
-         (cond ((eq yas-fallback-behavior 'call-other-command)
-                (let* ((yas-minor-mode nil)
-                       (fallback (key-binding (read-kbd-macro 
(yas--trigger-key-for-fallback)))))
-                  (or (and fallback
-                           (format " call command `%s'." (pp-to-string 
fallback)))
-                      " do nothing.")))
-               ((eq yas-fallback-behavior 'return-nil)
-                ", do nothing.")
-               (t
-                ", defer to `yas--fallback-behaviour' :-)"))))
-    (concat "Expand a snippet before point. If no snippet
-expansion is possible,"
-            fallback-description
-            "\n\nOptional argument FIELD is for non-interactive use and is an
-object satisfying `yas--field-p' to restrict the expansion to.")))
-
-(put 'yas-expand-from-keymap  'function-documentation 
'(yas--expand-from-keymap-doc))
-(defun yas--expand-from-keymap-doc ()
-  "A doc synthethizer for `yas--expand-from-keymap-doc'."
-  (add-hook 'temp-buffer-show-hook 'yas--snippet-description-finish-runonce)
-  (concat "Expand/run snippets from keymaps, possibly falling back to original 
binding.\n"
-          (when (eq this-command 'describe-key)
-            (let* ((vec (this-single-command-keys))
-                   (templates (mapcan #'(lambda (table)
-                                          (yas--fetch table vec))
-                                      (yas--get-snippet-tables)))
-                   (yas--direct-keymaps nil)
-                   (fallback (key-binding vec)))
-              (concat "In this case, "
-                      (when templates
-                        (concat "these snippets are bound to this key:\n"
-                                (yas--template-pretty-list templates)
-                                "\n\nIf none of these expands, "))
-                      (or (and fallback
-                               (format "fallback `%s' will be called." 
(pp-to-string fallback)))
-                          "no fallback keybinding is called."))))))
-
-(defun yas--template-pretty-list (templates)
-  (let ((acc)
-        (yas-buffer-local-condition 'always))
-    (dolist (plate templates)
-      (setq acc (concat acc "\n*) "
-                        (propertize (concat "\\\\snippet `" (car plate) "'")
-                                    'yasnippet (cdr plate)))))
-    acc))
-
-(define-button-type 'help-snippet-def
-  :supertype 'help-xref
-  'help-function (lambda (template) (yas--visit-snippet-file-1 template))
-  'help-echo (purecopy "mouse-2, RET: find snippets's definition"))
-
-(defun yas--snippet-description-finish-runonce ()
-  "Final adjustments for the help buffer when snippets are concerned."
-  (yas--create-snippet-xrefs)
-  (remove-hook 'temp-buffer-show-hook 
'yas--snippet-description-finish-runonce))
-
-(defun yas--create-snippet-xrefs ()
-  (save-excursion
-    (goto-char (point-min))
-    (while (search-forward-regexp "\\\\\\\\snippet[ \s\t]+`\\([^']+\\)'" nil t)
-      (let ((template (get-text-property (match-beginning 1)
-                                         'yasnippet)))
-        (when template
-          (help-xref-button 1 'help-snippet-def template)
-          (kill-region (match-end 1) (match-end 0))
-          (kill-region (match-beginning 0) (match-beginning 1)))))))
-
-(defun yas--expand-uuid (mode-symbol uuid &optional start end expand-env)
-  "Expand a snippet registered in MODE-SYMBOL's table with UUID.
-
-Remaining args as in `yas-expand-snippet'."
-  (let* ((table (gethash mode-symbol yas--tables))
-         (yas--current-template (and table
-                                    (gethash uuid (yas--table-uuidhash 
table)))))
-    (when yas--current-template
-      (yas-expand-snippet (yas--template-content yas--current-template)))))
-
-;;; Utils
-
-(defvar yas-verbosity 4
-  "Log level for `yas--message' 4 means trace most anything, 0 means nothing.")
-
-(defun yas--message (level message &rest args)
-  (when (> yas-verbosity level)
-    (message (apply #'yas--format message args))))
-
-(defun yas--format (format-control &rest format-args)
-  (apply #'format (concat "[yas] " format-control) format-args))
-
-
-;;; Some hacks:
-;;
-;; The functions
-;;
-;; `locate-dominating-file'
-;; `region-active-p'
-;;
-;; added for compatibility in emacsen < 23
-(unless (>= emacs-major-version 23)
-  (unless (fboundp 'region-active-p)
-    (defun region-active-p ()  (and transient-mark-mode mark-active)))
-
-  (unless (fboundp 'locate-dominating-file)
-    (defvar locate-dominating-stop-dir-regexp
-      "\\`\\(?:[\\/][\\/][^\\/]+[\\/]\\|/\\(?:net\\|afs\\|\\.\\.\\.\\)/\\)\\'"
-      "Regexp of directory names which stop the search in 
`locate-dominating-file'.
-Any directory whose name matches this regexp will be treated like
-a kind of root directory by `locate-dominating-file' which will stop its search
-when it bumps into it.
-The default regexp prevents fruitless and time-consuming attempts to find
-special files in directories in which filenames are interpreted as hostnames,
-or mount points potentially requiring authentication as a different user.")
-
-    (defun locate-dominating-file (file name)
-      "Look up the directory hierarchy from FILE for a file named NAME.
-Stop at the first parent directory containing a file NAME,
-and return the directory.  Return nil if not found."
-      ;; We used to use the above locate-dominating-files code, but the
-      ;; directory-files call is very costly, so we're much better off doing
-      ;; multiple calls using the code in here.
-      ;;
-      ;; Represent /home/luser/foo as ~/foo so that we don't try to look for
-      ;; `name' in /home or in /.
-      (setq file (abbreviate-file-name file))
-      (let ((root nil)
-            (prev-file file)
-            ;; `user' is not initialized outside the loop because
-            ;; `file' may not exist, so we may have to walk up part of the
-            ;; hierarchy before we find the "initial UUID".
-            (user nil)
-            try)
-        (while (not (or root
-                        (null file)
-                        ;; FIXME: Disabled this heuristic because it is 
sometimes
-                        ;; inappropriate.
-                        ;; As a heuristic, we stop looking up the hierarchy of
-                        ;; directories as soon as we find a directory belonging
-                        ;; to another user.  This should save us from looking 
in
-                        ;; things like /net and /afs.  This assumes that all 
the
-                        ;; files inside a project belong to the same user.
-                        ;; (let ((prev-user user))
-                        ;;   (setq user (nth 2 (file-attributes file)))
-                        ;;   (and prev-user (not (equal user prev-user))))
-                        (string-match locate-dominating-stop-dir-regexp file)))
-          (setq try (file-exists-p (expand-file-name name file)))
-          (cond (try (setq root file))
-                ((equal file (setq prev-file file
-                                   file (file-name-directory
-                                         (directory-file-name file))))
-                 (setq file nil))))
-        root))))
-
-;; `c-neutralize-syntax-in-CPP` sometimes fires "End of Buffer" error
-;; (when it execute forward-char) and interrupt the after change
-;; hook. Thus prevent the insert-behind hook of yasnippet to be
-;; invoked. Here's a way to reproduce it:
-
-;; # open a *new* Emacs.
-;; # load yasnippet.
-;; # open a *new* .cpp file.
-;; # input "inc" and press TAB to expand the snippet.
-;; # select the `#include <...>` snippet.
-;; # type inside `<>`
-
-(defadvice c-neutralize-syntax-in-CPP
-  (around yas--mp/c-neutralize-syntax-in-CPP activate)
-  "Adviced `c-neutralize-syntax-in-CPP' to properly
-handle the end-of-buffer error fired in it by calling
-`forward-char' at the end of buffer."
-  (condition-case err
-      ad-do-it
-    (error (message (error-message-string err)))))
-
-;; disable c-electric-* serial command in YAS fields
-(add-hook 'c-mode-common-hook
-          '(lambda ()
-             (dolist (k '(":" ">" ";" "<" "{" "}"))
-               (define-key (symbol-value (make-local-variable 'yas-keymap))
-                 k 'self-insert-command))))
-
-;;; Backward compatibility to to yasnippet <= 0.7
-(defvar yas--exported-syms '(;; `defcustom's
-                             ;;
-                             yas-snippet-dirs
-                             yas-prompt-functions
-                             yas-indent-line
-                             yas-also-auto-indent-first-line
-                             yas-snippet-revival
-                             yas-trigger-key
-                             yas-next-field-key
-                             yas-prev-field-key
-                             yas-skip-and-clear-key
-                             yas-triggers-in-field
-                             yas-fallback-behavior
-                             yas-choose-keys-first
-                             yas-choose-tables-first
-                             yas-use-menu
-                             yas-trigger-symbol
-                             yas-wrap-around-region
-                             yas-good-grace
-                             yas-visit-from-menu
-                             yas-expand-only-for-last-commands
-                             yas-field-highlight-face
-
-                             ;; these vars can be customized as well
-                             ;;
-                             yas-keymap
-                             yas-verbosity
-                             yas-extra-modes
-                             yas-key-syntaxes
-                             yas-after-exit-snippet-hook
-                             yas-before-expand-snippet-hook
-                             yas-buffer-local-condition
-
-                             ;; prompting functions
-                             ;;
-                             yas-x-prompt
-                             yas-ido-prompt
-                             yas-no-prompt
-                             yas-completing-prompt
-                             yas-dropdown-prompt
-
-                             ;; interactive functions
-                             ;;
-                             yas-expand
-                             yas-minor-mode
-                             yas-global-mode
-                             yas-direct-keymaps-reload
-                             yas-minor-mode-on
-                             yas-load-directory
-                             yas-reload-all
-                             yas-compile-directory
-                             yas-recompile-all
-                             yas-about
-                             yas-expand-from-trigger-key
-                             yas-expand-from-keymap
-                             yas-insert-snippet
-                             yas-visit-snippet-file
-                             yas-new-snippet
-                             yas-load-snippet-buffer
-                             yas-tryout-snippet
-                             yas-describe-tables
-                             yas-next-field-or-maybe-expand
-                             yas-next-field
-                             yas-prev-field
-                             yas-abort-snippet
-                             yas-exit-snippet
-                             yas-exit-all-snippets
-                             yas-skip-and-clear-or-delete-char
-
-                             ;; symbols that I "exported" for use
-                             ;; in snippets and hookage
-                             ;;
-                             yas-expand-snippet
-                             yas-define-snippets
-                             yas-define-menu
-                             yas-snippet-beg
-                             yas-snippet-end
-                             yas-modified-p
-                             yas-moving-away-p
-                             yas-text
-                             yas-substr
-                             yas-choose-value
-                             yas-key-to-value
-                             yas-throw
-                             yas-verify-value
-                             yas-field-value
-                             yas-text
-                             yas-selected-text
-                             yas-default-from-field
-                             yas-inside-string
-                             yas-unimplemented
-                             yas-define-condition-cache
-                             yas-hippie-try-expand
-
-                             ;; debug definitions
-                             ;; yas-debug-snippet-vars
-                             ;; yas-exterminate-package
-                             ;; yas-debug-test
-
-                             ;; testing definitions
-                             ;; yas-should-expand
-                             ;; yas-should-not-expand
-                             ;; yas-mock-insert
-                             ;; yas-make-file-or-dirs
-                             ;; yas-variables
-                             ;; yas-saving-variables
-                             ;; yas-call-with-snippet-dirs
-                             ;; yas-with-snippet-dirs
-))
-
-(dolist (sym yas--exported-syms)
-  (let ((backported (intern (replace-regexp-in-string "^yas-" "yas/" 
(symbol-name sym)))))
-    (when (boundp sym)
-      (make-obsolete-variable backported sym "yasnippet 0.8")
-      (defvaralias backported sym))
-    (when (fboundp sym)
-      (make-obsolete backported sym "yasnippet 0.8")
-      (defalias backported sym))))
-
-
-(provide 'yasnippet)
-
-;;; yasnippet.el ends here
-;; Local Variables:
-;; coding: utf-8
-;; End:
+;;; yasnippet.el --- Yet another snippet extension for Emacs.
+
+;; Copyright (C) 2008-2012 Free Software Foundation, Inc.
+;; Authors: pluskid <address@hidden>,  João Távora <address@hidden>
+;; Version: 0.8.0
+;; Package-version: 0.8.0
+;; X-URL: http://github.com/capitaomorte/yasnippet
+;; Keywords: convenience, emulation
+;; URL: http://github.com/capitaomorte/yasnippet
+;; EmacsWiki: YaSnippetMode
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;;   Basic steps to setup:
+;;
+;;    (add-to-list 'load-path
+;;                 "~/path-to-yasnippet")
+;;    (require 'yasnippet)
+;;    (yas-global-mode 1)
+;;
+;;
+;;   Interesting variables are:
+;;
+;;       `yas-snippet-dirs'
+;;
+;;           The directory where user-created snippets are to be
+;;           stored. Can also be a list of directories. In that case,
+;;           when used for bulk (re)loading of snippets (at startup or
+;;           via `yas-reload-all'), directories appearing earlier in
+;;           the list shadow other dir's snippets. Also, the first
+;;           directory is taken as the default for storing the user's
+;;           new snippets.
+;;
+;;           The deprecated `yas/root-directory' aliases this variable
+;;           for backward-compatibility.
+;;
+;;       `yas-extra-modes'
+;;
+;;           A local variable that you can set in a hook to override
+;;           snippet-lookup based on major mode. It is a a symbol (or
+;;           list of symbols) that correspond to subdirectories of
+;;           `yas-snippet-dirs' and is used for deciding which
+;;           snippets to consider for the active buffer.
+;;
+;;           Deprecated `yas/mode-symbol' aliases this variable for
+;;           backward-compatibility.
+;;
+;;   Major commands are:
+;;
+;;       M-x yas-expand
+;;
+;;           Try to expand snippets before point.  In `yas-minor-mode',
+;;           this is bound to `yas-trigger-key' which you can customize.
+;;
+;;       M-x yas-load-directory
+;;
+;;           Prompts you for a directory hierarchy of snippets to load.
+;;
+;;       M-x yas-insert-snippet
+;;
+;;           Prompts you for possible snippet expansion if that is
+;;           possible according to buffer-local and snippet-local
+;;           expansion conditions.  With prefix argument, ignore these
+;;           conditions.
+;;
+;;       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.
+;;
+;;       M-x yas-new-snippet
+;;
+;;           Lets you create a new snippet file in the correct
+;;           subdirectory of `yas-snippet-dirs', according to the
+;;           active major mode.
+;;
+;;       M-x yas-load-snippet-buffer
+;;
+;;           When editing a snippet, this loads the snippet.  This is
+;;           bound to "C-c C-c" while in the `snippet-mode' editing
+;;           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'.
+;;
+;;       M-x yas-describe-tables
+;;
+;;           Lists known snippets in a separate buffer. User is
+;;           prompted as to whether only the currently active tables
+;;           are to be displayed, or all the tables for all major
+;;           modes.
+;;
+;;   The `dropdown-list.el' extension is bundled with YASnippet, you
+;;   can optionally use it the preferred "prompting method", puting in
+;;   your .emacs file, for example:
+;;
+;;       (require 'dropdown-list)
+;;       (setq yas-prompt-functions '(yas-dropdown-prompt
+;;                                    yas-ido-prompt
+;;                                    yas-completing-prompt))
+;;
+;;   Also check out the customization group
+;;
+;;        M-x customize-group RET yasnippet RET
+;;
+;;   If you use the customization group to set variables
+;;   `yas-snippet-dirs' or `yas-global-mode', make sure the path to
+;;   "yasnippet.el" is present in the `load-path' *before* the
+;;   `custom-set-variables' is executed in your .emacs file.
+;;
+;;   For more information and detailed usage, refer to the project page:
+;;      http://github.com/capitaomorte/yasnippet
+
+;;; Code:
+
+(require 'cl)
+(require 'easymenu)
+(require 'help-mode)
+
+
+;;; User customizable variables
+
+(defgroup yasnippet nil
+  "Yet Another Snippet extension"
+  :group 'editing)
+
+(defvar yas--load-file-name load-file-name
+  "Store the filename that yasnippet.el was originally loaded from.")
+
+(defcustom yas-snippet-dirs (remove nil
+                                    (list "~/.emacs.d/snippets"
+                                          (when yas--load-file-name
+                                            (concat (file-name-directory 
yas--load-file-name) "snippets"))))
+  "Directory or list of snippet dirs for each major mode.
+
+The directory where user-created snippets are to be stored. Can
+also be a list of directories. In that case, when used for
+bulk (re)loading of snippets (at startup or via
+`yas-reload-all'), directories appearing earlier in the list
+shadow other dir's snippets. Also, the first directory is taken
+as the default for storing the user's new snippets."
+  :type '(choice (string :tag "Single directory (string)")
+                 (repeat :args (string) :tag "List of directories (strings)"))
+  :group 'yasnippet
+  :require 'yasnippet
+  :set #'(lambda (symbol new)
+           (let ((old (and (boundp symbol)
+                           (symbol-value symbol))))
+             (set-default symbol new)
+             (unless (or (not (fboundp 'yas-reload-all))
+                         (equal old new))
+               (yas-reload-all)))))
+
+(defun yas-snippet-dirs ()
+  "Returns `yas-snippet-dirs' (which see) as a list."
+  (if (listp yas-snippet-dirs) yas-snippet-dirs (list yas-snippet-dirs)))
+
+(defvaralias 'yas/root-directory 'yas-snippet-dirs)
+
+(defcustom yas-prompt-functions '(yas-x-prompt
+                                  yas-dropdown-prompt
+                                  yas-completing-prompt
+                                  yas-ido-prompt
+                                  yas-no-prompt)
+  "Functions to prompt for keys, templates, etc interactively.
+
+These functions are called with the following arguments:
+
+- PROMPT: A string to prompt the user
+
+- CHOICES: a list of strings or objects.
+
+- optional DISPLAY-FN : A function that, when applied to each of
+the objects in CHOICES will return a string.
+
+The return value of any function you put here should be one of
+the objects in CHOICES, properly formatted with DISPLAY-FN (if
+that is passed).
+
+- To signal that your particular style of prompting is
+unavailable at the moment, you can also have the function return
+nil.
+
+- To signal that the user quit the prompting process, you can
+signal `quit' with
+
+  (signal 'quit \"user quit!\")."
+  :type '(repeat function)
+  :group 'yasnippet)
+
+(defcustom yas-indent-line 'auto
+  "Controls indenting applied to a recent snippet expansion.
+
+The following values are possible:
+
+- `fixed' Indent the snippet to the current column;
+
+- `auto' Indent each line of the snippet with `indent-according-to-mode'
+
+Every other value means don't apply any snippet-side indendation
+after expansion (the manual per-line \"$>\" indentation still
+applies)."
+  :type '(choice (const :tag "Nothing"  nothing)
+                 (const :tag "Fixed"    fixed)
+                 (const :tag "Auto"     auto))
+  :group 'yasnippet)
+
+(defcustom yas-also-auto-indent-first-line nil
+  "Non-nil means also auto indent first line according to mode.
+
+Naturally this is only valid when `yas-indent-line' is `auto'"
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-snippet-revival t
+  "Non-nil means re-activate snippet fields after undo/redo."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-trigger-key "<tab>"
+  "The key bound to `yas-expand' when `yas-minor-mode' is active.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'."
+  :type 'string
+  :group 'yasnippet
+  :set #'(lambda (symbol key)
+           (let ((old (and (boundp symbol)
+                           (symbol-value symbol))))
+             (set-default symbol key)
+             ;; On very first loading of this defcustom,
+             ;; `yas-trigger-key' is *not* loaded.
+             (if (fboundp 'yas--trigger-key-reload)
+                 (yas--trigger-key-reload old)))))
+
+(defcustom yas-next-field-key '("TAB" "<tab>")
+  "The key to navigate to next field when a snippet is active.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'.
+
+Can also be a list of strings."
+  :type '(choice (string :tag "String")
+                 (repeat :args (string) :tag "List of strings"))
+  :group 'yasnippet
+  :set #'(lambda (symbol val)
+           (set-default symbol val)
+           (if (fboundp 'yas--init-yas-in-snippet-keymap)
+               (yas--init-yas-in-snippet-keymap))))
+
+
+(defcustom yas-prev-field-key '("<backtab>" "<S-tab>")
+  "The key to navigate to previous field when a snippet is active.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'.
+
+Can also be a list of strings."
+  :type '(choice (string :tag "String")
+                 (repeat :args (string) :tag "List of strings"))
+  :group 'yasnippet
+  :set #'(lambda (symbol val)
+           (set-default symbol val)
+           (if (fboundp 'yas--init-yas-in-snippet-keymap)
+               (yas--init-yas-in-snippet-keymap))))
+
+(defcustom yas-skip-and-clear-key '("C-d" "<delete>" "<deletechar>")
+  "The key to clear the currently active field.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'.
+
+Can also be a list of strings."
+  :type '(choice (string :tag "String")
+                 (repeat :args (string) :tag "List of strings"))
+  :group 'yasnippet
+  :set #'(lambda (symbol val)
+           (set-default symbol val)
+           (if (fboundp 'yas--init-yas-in-snippet-keymap)
+               (yas--init-yas-in-snippet-keymap))))
+
+(defcustom yas-triggers-in-field nil
+  "If non-nil, `yas-next-field-key' can trigger stacked expansions.
+
+Otherwise, `yas-next-field-key' just tries to move on to the next
+field"
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-fallback-behavior 'call-other-command
+  "How to act when `yas-trigger-key' does *not* expand a snippet.
+
+- `call-other-command' means try to temporarily disable YASnippet
+    and call the next command bound to `yas-trigger-key'.
+
+- nil or the symbol `return-nil' mean do nothing. (and
+  `yas-expand' returns nil)
+
+- A lisp form (apply COMMAND . ARGS) means interactively call
+  COMMAND, if ARGS is non-nil, call COMMAND non-interactively
+  with ARGS as arguments."
+  :type '(choice (const :tag "Call previous command"  call-other-command)
+                 (const :tag "Do nothing"             return-nil))
+  :group 'yasnippet)
+
+(defcustom yas-choose-keys-first nil
+  "If non-nil, prompt for snippet key first, then for template.
+
+Otherwise prompts for all possible snippet names.
+
+This affects `yas-insert-snippet' and `yas-visit-snippet-file'."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-choose-tables-first nil
+  "If non-nil, and multiple eligible snippet tables, prompts user for tables 
first.
+
+Otherwise, user chooses between the merging together of all
+eligible tables.
+
+This affects `yas-insert-snippet', `yas-visit-snippet-file'"
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-use-menu 'abbreviate
+  "Display a YASnippet menu in the menu bar.
+
+When non-nil, submenus for each snippet table will be listed
+under the menu \"Yasnippet\".
+
+- If set to `abbreviate', only the current major-mode
+menu and the modes set in `yas-extra-modes' are listed.
+
+- If set to `full', every submenu is listed
+
+- It set to nil, don't display a menu at all (this requires a
+  `yas-reload-all' call if the menu is already visible).
+
+Any other non-nil value, every submenu is listed."
+  :type '(choice (const :tag "Full"  full)
+                 (const :tag "Abbreviate" abbreviate)
+                 (const :tag "No menu" nil))
+  :group 'yasnippet)
+
+(defcustom yas-trigger-symbol (if (eq window-system 'mac)
+                                  (char-to-string ?\x21E5) ;; little ->| sign
+                                  " =>")
+  "The text that will be used in menu to represent the trigger."
+  :type 'string
+  :group 'yasnippet)
+
+(defcustom yas-wrap-around-region nil
+  "If non-nil, snippet expansion wraps around selected region.
+
+The wrapping occurs just before the snippet's exit marker.  This
+can be overriden on a per-snippet basis."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-good-grace t
+  "If non-nil, don't raise errors in inline elisp evaluation.
+
+An error string \"[yas] error\" is returned instead."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-visit-from-menu nil
+  "If non-nil visit snippets's files from menu, instead of expanding them.
+
+This cafn only work when snippets are loaded from files."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-expand-only-for-last-commands nil
+  "List of `last-command' values to restrict tab-triggering to, or nil.
+
+Leave this set at nil (the default) to be able to trigger an
+expansion simply by placing the cursor after a valid tab trigger,
+using whichever commands.
+
+Optionallly, set this to something like '(self-insert-command) if
+you to wish restrict expansion to only happen when the last
+letter of the snippet tab trigger was typed immediately before
+the trigger key itself."
+  :type '(repeat function)
+  :group 'yasnippet)
+
+;; Only two faces, and one of them shouldn't even be used...
+;;
+(defface yas-field-highlight-face
+  '((t (:inherit 'region)))
+  "The face used to highlight the currently active field of a snippet"
+  :group 'yasnippet)
+
+(defface yas--field-debug-face
+  '()
+  "The face used for debugging some overlays normally hidden"
+  :group 'yasnippet)
+
+
+;;; User can also customize the next defvars
+
+(defun yas--define-some-keys (keys keymap definition)
+  "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'."
+  (let ((keys (or (and (listp keys) keys)
+                  (list keys))))
+    (dolist (key keys)
+      (define-key keymap (read-kbd-macro key) definition))))
+
+(defun yas--init-yas-in-snippet-keymap ()
+  (setq yas-keymap
+        (let ((map (make-sparse-keymap)))
+          (mapc #'(lambda (binding)
+                    (yas--define-some-keys (car binding) map (cdr binding)))
+                `((,yas-next-field-key     . yas-next-field-or-maybe-expand)
+                  (,yas-prev-field-key     . yas-prev-field)
+                  ("C-g"                   . yas-abort-snippet)
+                  (,yas-skip-and-clear-key . 
yas-skip-and-clear-or-delete-char)))
+          map)))
+
+(defvar yas-keymap (yas--init-yas-in-snippet-keymap)
+  "The keymap active while a snippet expansion is in progress.")
+
+(defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ")
+  "List of character syntaxes used to find a trigger key before point.
+The list is tried in the order while scanning characters
+backwards from point. For example, if the list is '(\"w\" \"w_\")
+first look for trigger keys which are composed exclusively of
+\"word\"-syntax characters, and then, if that fails, look for
+keys which are either of \"word\" or \"symbol\"
+syntax. Triggering after
+
+foo-bar
+
+will, according to the \"w\" element first try \"bar\". If that
+isn't a trigger key, \"foo-bar\" is tried, respecting a second
+\"w_\" element.")
+
+(defvar yas-after-exit-snippet-hook
+  '()
+  "Hooks to run after a snippet exited.
+
+The hooks will be run in an environment where some variables bound to
+proper values:
+
+`yas-snippet-beg' : The beginning of the region of the snippet.
+
+`yas-snippet-end' : Similar to beg.
+
+Attention: These hooks are not run when exiting nested/stackd snippet 
expansion!")
+
+(defvar yas-before-expand-snippet-hook
+  '()
+  "Hooks to run just before expanding a snippet.")
+
+(defvar yas-buffer-local-condition
+  '(if (and (or (fourth (syntax-ppss))
+                (fifth (syntax-ppss)))
+            (eq (symbol-function this-command) 'yas-expand-from-trigger-key))
+       '(require-snippet-condition . force-in-comment)
+     t)
+  "Snippet expanding condition.
+
+This variable is a lisp form which is evaluated everytime a
+snippet expansion is attemped:
+
+    * If it evaluates to nil, no snippets can be expanded.
+
+    * If it evaluates to the a cons (require-snippet-condition
+      . REQUIREMENT)
+
+       * Snippets bearing no \"# condition:\" directive are not
+         considered
+
+       * Snippets bearing conditions that evaluate to nil (or
+         produce an error) won't be onsidered.
+
+       * If the snippet has a condition that evaluates to non-nil
+         RESULT:
+
+          * If REQUIREMENT is t, the snippet is considered
+
+          * If REQUIREMENT is `eq' RESULT, the snippet is
+            considered
+
+          * Otherwise, the snippet is not considered.
+
+    * If it evaluates to the symbol 'always, all snippets are
+      considered for expansion, regardless of any conditions.
+
+    * If it evaluates to t or some other non-nil value
+
+       * Snippet bearing no conditions, or conditions that
+         evaluate to non-nil, are considered for expansion.
+
+       * Otherwise, the snippet is not considered.
+
+Here's an example preventing snippets from being expanded from
+inside comments, in `python-mode' only, with the exception of
+snippets returning the symbol 'force-in-comment in their
+conditions.
+
+ (add-hook 'python-mode-hook
+           '(lambda ()
+              (setq yas-buffer-local-condition
+                    '(if (python-in-string/comment)
+                         '(require-snippet-condition . force-in-comment)
+                       t))))
+
+The default value is similar, it filters out potential snippet
+expansions inside comments and string literals, unless the
+snippet itself contains a condition that returns the symbol
+`force-in-comment'.")
+
+
+;;; Internal variables
+
+(defvar yas--version "0.8.0 (beta)")
+
+(defvar yas--menu-table (make-hash-table)
+  "A hash table of MAJOR-MODE symbols to menu keymaps.")
+
+(defvar yas--known-modes
+  '(ruby-mode rst-mode markdown-mode)
+  "A list of mode which is well known but not part of emacs.")
+
+(defvar yas--escaped-characters
+  '(?\\ ?` ?\" ?' ?$ ?} ?{ ?\( ?\))
+  "List of characters which *might* need to be escaped.")
+
+(defconst yas--field-regexp
+  "${\\([0-9]+:\\)?\\([^}]*\\)}"
+  "A regexp to *almost* recognize a field.")
+
+(defconst yas--multi-dollar-lisp-expression-regexp
+  "$+[ \t\n]*\\(([^)]*)\\)"
+  "A regexp to *almost* recognize a \"$(...)\" expression.")
+
+(defconst yas--backquote-lisp-expression-regexp
+  "`\\([^`]*\\)`"
+  "A regexp to recognize a \"`lisp-expression`\" expression." )
+
+(defconst yas--transform-mirror-regexp
+  "${\\(?:\\([0-9]+\\):\\)?$\\([ \t\n]*([^}]*\\)"
+  "A regexp to *almost* recognize a mirror with a transform.")
+
+(defconst yas--simple-mirror-regexp
+  "$\\([0-9]+\\)"
+  "A regexp to recognize a simple mirror.")
+
+(defvar yas--snippet-id-seed 0
+  "Contains the next id for a snippet.")
+
+(defun yas--snippet-next-id ()
+  (let ((id yas--snippet-id-seed))
+    (incf yas--snippet-id-seed)
+    id))
+
+
+;;; Minor mode stuff
+
+;; XXX: `last-buffer-undo-list' is somehow needed in Carbon Emacs for MacOSX
+(defvar last-buffer-undo-list nil)
+
+(defvar yas--minor-mode-menu nil
+  "Holds the YASnippet menu")
+
+(defun yas--init-minor-keymap ()
+  (let ((map (make-sparse-keymap)))
+    (when yas-use-menu
+      (easy-menu-define yas--minor-mode-menu
+      map
+      "Menu used when `yas-minor-mode' is active."
+      '("YASnippet"
+        "----"
+        ["Expand trigger" yas-expand
+         :help "Possibly expand tab trigger before point"]
+        ["Insert at point..." yas-insert-snippet
+         :help "Prompt for an expandable snippet and expand it at point"]
+        ["New snippet..." yas-new-snippet
+         :help "Create a new snippet in an appropriate directory"]
+        ["Visit snippet file..." yas-visit-snippet-file
+         :help "Prompt for an expandable snippet and find its file"]
+        "----"
+        ("Snippet menu behaviour"
+         ["Visit snippets" (setq yas-visit-from-menu t)
+          :help "Visit snippets from the menu"
+          :active t :style radio   :selected yas-visit-from-menu]
+         ["Expand snippets" (setq yas-visit-from-menu nil)
+          :help "Expand snippets from the menu"
+          :active t :style radio :selected (not yas-visit-from-menu)]
+         "----"
+         ["Show all known modes" (setq yas-use-menu 'full)
+          :help "Show one snippet submenu for each loaded table"
+          :active t :style radio   :selected (eq yas-use-menu 'full)]
+         ["Abbreviate according to current mode" (setq yas-use-menu 
'abbreviate)
+          :help "Show only snippet submenus for the current active modes"
+          :active t :style radio   :selected (eq yas-use-menu 'abbreviate)])
+        ("Indenting"
+         ["Auto" (setq yas-indent-line 'auto)
+          :help "Indent each line of the snippet with 
`indent-according-to-mode'"
+          :active t :style radio   :selected (eq yas-indent-line 'auto)]
+         ["Fixed" (setq yas-indent-line 'fixed)
+          :help "Indent the snippet to the current column"
+          :active t :style radio   :selected (eq yas-indent-line 'fixed)]
+         ["None" (setq yas-indent-line 'none)
+          :help "Don't apply any particular snippet indentation after 
expansion"
+          :active t :style radio   :selected (not (member yas-indent-line 
'(fixed auto)))]
+         "----"
+         ["Also auto indent first line" (setq yas-also-auto-indent-first-line
+                                              (not 
yas-also-auto-indent-first-line))
+          :help "When auto-indenting also, auto indent the first line menu"
+          :active (eq yas-indent-line 'auto)
+          :style toggle :selected yas-also-auto-indent-first-line]
+         )
+        ("Prompting method"
+         ["System X-widget" (setq yas-prompt-functions
+                                  (cons 'yas-x-prompt
+                                        (remove 'yas-x-prompt
+                                                yas-prompt-functions)))
+          :help "Use your windowing system's (gtk, mac, windows, etc...) 
default menu"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-x-prompt)]
+         ["Dropdown-list" (setq yas-prompt-functions
+                                (cons 'yas-dropdown-prompt
+                                      (remove 'yas-dropdown-prompt
+                                              yas-prompt-functions)))
+          :help "Use a special dropdown list"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-dropdown-prompt)]
+         ["Ido" (setq yas-prompt-functions
+                      (cons 'yas-ido-prompt
+                            (remove 'yas-ido-prompt
+                                    yas-prompt-functions)))
+          :help "Use an ido-style minibuffer prompt"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-ido-prompt)]
+         ["Completing read" (setq yas-prompt-functions
+                                  (cons 'yas-completing-prompt
+                                        (remove 'yas-completing-prompt
+                                                yas-prompt-functions)))
+          :help "Use a normal minibuffer prompt"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-completing-prompt)]
+         )
+        ("Misc"
+         ["Wrap region in exit marker"
+          (setq yas-wrap-around-region
+                (not yas-wrap-around-region))
+          :help "If non-nil automatically wrap the selected text in the $0 
snippet exit"
+          :style toggle :selected yas-wrap-around-region]
+         ["Allow stacked expansions "
+          (setq yas-triggers-in-field
+                (not yas-triggers-in-field))
+          :help "If non-nil allow snippets to be triggered inside other 
snippet fields"
+          :style toggle :selected yas-triggers-in-field]
+         ["Revive snippets on undo "
+          (setq yas-snippet-revival
+                (not yas-snippet-revival))
+          :help "If non-nil allow snippets to become active again after undo"
+          :style toggle :selected yas-snippet-revival]
+         ["Good grace "
+          (setq yas-good-grace
+                (not yas-good-grace))
+          :help "If non-nil don't raise errors in bad embedded eslip in 
snippets"
+          :style toggle :selected yas-good-grace]
+         )
+        "----"
+        ["Load snippets..."  yas-load-directory
+         :help "Load snippets from a specific directory"]
+        ["Reload everything" yas-reload-all
+         :help "Cleanup stuff, reload snippets, rebuild menus"]
+        ["About"            yas-about
+         :help "Display some information about YASsnippet"])))
+
+    ;; Now for the stuff that has direct keybindings
+    ;;
+    (define-key map "\C-c&\C-s" 'yas-insert-snippet)
+    (define-key map "\C-c&\C-n" 'yas-new-snippet)
+    (define-key map "\C-c&\C-v" 'yas-visit-snippet-file)
+    map))
+
+(defvar yas-minor-mode-map (yas--init-minor-keymap)
+  "The keymap used when `yas-minor-mode' is active.")
+
+(defun yas--trigger-key-reload (&optional unbind-key)
+  "Rebind `yas-expand' to the new value of `yas-trigger-key'.
+
+With optional UNBIND-KEY, try to unbind that key from
+`yas-minor-mode-map'."
+  (when (and unbind-key
+             (stringp unbind-key)
+             (not (string= unbind-key "")))
+    (define-key yas-minor-mode-map (read-kbd-macro unbind-key) nil))
+  (when  (and yas-trigger-key
+              (stringp yas-trigger-key)
+              (not (string= yas-trigger-key "")))
+    (define-key yas-minor-mode-map (read-kbd-macro yas-trigger-key) 
'yas-expand)))
+
+(defvar yas--tables (make-hash-table)
+  "A hash table of mode symbols to `yas--table' objects.")
+
+(defvar yas--parents (make-hash-table)
+  "A hash table of mode symbols do lists of direct parent mode symbols.
+
+This list is populated when reading the \".yas-parents\" files
+found when traversing snippet directories with
+`yas-load-directory'.
+
+There might be additionalal parenting information stored in the
+`derived-mode-parent' property of some mode symbols, but that is
+not recorded here.")
+
+(defvar yas--direct-keymaps (list)
+  "Keymap alist supporting direct snippet keybindings.
+
+This variable is is placed in `emulation-mode-map-alists'.
+
+Its elements looks like (TABLE-NAME . KEYMAP). They're
+instantiated on `yas-reload-all' but KEYMAP is added to only when
+loading snippets. `yas--direct-TABLE-NAME' is then a variable set
+buffer-locally when entering `yas-minor-mode'. KEYMAP binds all
+defined direct keybindings to the command
+`yas-expand-from-keymap' which then which snippet to expand.")
+
+(defun yas-direct-keymaps-reload ()
+  "Force reload the direct keybinding for active snippet tables."
+  (interactive)
+  (setq yas--direct-keymaps nil)
+  (maphash #'(lambda (name table)
+               (push (cons (intern (format "yas--direct-%s" name))
+                           (yas--table-direct-keymap table))
+                     yas--direct-keymaps))
+           yas--tables))
+
+(defun yas--modes-to-activate ()
+  "Compute list of mode symbols that are active for `yas-expand'
+and friends."
+  (let ((modes-to-activate (list major-mode))
+        (mode major-mode))
+    (while (setq mode (get mode 'derived-mode-parent))
+      (push mode modes-to-activate))
+    (dolist (mode (yas-extra-modes))
+      (push mode modes-to-activate))
+    (remove-duplicates
+     (append modes-to-activate
+             (mapcan #'(lambda (mode)
+                         (yas--all-parents mode))
+                     modes-to-activate)))))
+
+(defvar yas-minor-mode-hook nil
+  "Hook run when yas-minor-mode is turned on")
+
+;;;###autoload
+(define-minor-mode yas-minor-mode
+  "Toggle YASnippet mode.
+
+When YASnippet mode is enabled, the `yas-trigger-key' key expands
+snippets of code depending on the major mode.
+
+With no argument, this command toggles the mode.
+positive prefix argument turns on the mode.
+Negative prefix argument turns off the mode.
+
+You can customize the key through `yas-trigger-key'.
+
+Key bindings:
+\\{yas-minor-mode-map}"
+  nil
+  ;; The indicator for the mode line.
+  " yas"
+  :group 'yasnippet
+  (cond (yas-minor-mode
+         ;; Reload the trigger key
+         ;;
+         (yas--trigger-key-reload)
+         ;; Install the direct keymaps in `emulation-mode-map-alists'
+         ;; (we use `add-hook' even though it's not technically a hook,
+         ;; but it works). Then define variables named after modes to
+         ;; index `yas--direct-keymaps'.
+         ;;
+         ;; Also install the post-command-hook.
+         ;;
+         (add-hook 'emulation-mode-map-alists 'yas--direct-keymaps)
+         (add-hook 'post-command-hook 'yas--post-command-handler nil t)
+         ;; Set the `yas--direct-%s' vars for direct keymap expansion
+         ;;
+         (dolist (mode (yas--modes-to-activate))
+           (let ((name (intern (format "yas--direct-%s" mode))))
+             (set-default name nil)
+             (set (make-local-variable name) t)))
+         ;; Perform JIT loads
+         ;;
+         (yas--load-pending-jits))
+        (t
+         ;; Uninstall the direct keymaps and the post-command hook
+         ;;
+         (remove-hook 'post-command-hook 'yas--post-command-handler t)
+         (remove-hook 'emulation-mode-map-alists 'yas--direct-keymaps))))
+
+(defvar yas--dont-activate '(minibufferp)
+  "If non-nil don't let `yas-minor-mode-on' active yas for this buffer.
+
+If a function, then its result is used.
+
+If a list of functions, then all functions must return nil to
+activate yas for this buffer.
+
+`yas-minor-mode-on' is usually called by `yas-global-mode' so
+this effectively lets you define exceptions to the \"global\"
+behaviour. Can also be a function of zero arguments.")
+(make-variable-buffer-local 'yas--dont-activate)
+
+(defun yas-minor-mode-on ()
+  "Turn on YASnippet minor mode.
+
+Do this unless `yas--dont-activate' is truish "
+  (interactive)
+  (unless (cond ((functionp yas--dont-activate)
+                 (funcall yas--dont-activate))
+                ((consp yas--dont-activate)
+                 (some #'funcall yas--dont-activate))
+                (yas--dont-activate))
+    ;; Load all snippets definitions unless we still don't have a
+    ;; root-directory or some snippets have already been loaded.
+    ;;
+    (yas-minor-mode 1)))
+
+;;;###autoload
+(define-globalized-minor-mode yas-global-mode yas-minor-mode yas-minor-mode-on
+  :group 'yasnippet
+  :require 'yasnippet)
+
+(defun yas--global-mode-reload-with-jit-maybe ()
+  (when yas-global-mode (yas-reload-all)))
+
+(add-hook 'yas-global-mode-hook 'yas--global-mode-reload-with-jit-maybe)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Major mode stuff
+;;
+(defvar yas--font-lock-keywords
+  (append '(("^#.*$" . font-lock-comment-face))
+          lisp-font-lock-keywords
+          lisp-font-lock-keywords-1
+          lisp-font-lock-keywords-2
+          '(("$\\([0-9]+\\)"
+             (0 font-lock-keyword-face)
+             (1 font-lock-string-face t))
+            ("${\\([0-9]+\\):?"
+             (0 font-lock-keyword-face)
+             (1 font-lock-warning-face t))
+            ("${" font-lock-keyword-face)
+            ("$[0-9]+?" font-lock-preprocessor-face)
+            ("\\(\\$(\\)" 1 font-lock-preprocessor-face)
+            ("}"
+             (0 font-lock-keyword-face)))))
+
+(defun yas--init-major-keymap ()
+  (let ((map (make-sparse-keymap)))
+    (easy-menu-define nil
+      map
+      "Menu used when snippet-mode is active."
+      (cons "Snippet"
+            (mapcar #'(lambda (ent)
+                        (when (third ent)
+                          (define-key map (third ent) (second ent)))
+                        (vector (first ent) (second ent) t))
+                    (list
+                     (list "Load this snippet" 'yas-load-snippet-buffer 
"\C-c\C-c")
+                     (list "Try out this snippet" 'yas-tryout-snippet 
"\C-c\C-t")))))
+    map))
+
+(defvar snippet-mode-map
+  (yas--init-major-keymap)
+  "The keymap used when `snippet-mode' is active")
+
+
+(define-derived-mode snippet-mode text-mode "Snippet"
+  "A mode for editing yasnippets"
+  (setq font-lock-defaults '(yas--font-lock-keywords))
+  (set (make-local-variable 'require-final-newline) nil)
+  (set (make-local-variable 'comment-start) "#")
+  (set (make-local-variable 'comment-start-skip) "#+[\t ]*"))
+
+
+
+;;; Internal structs for template management
+
+(defstruct (yas--template (:constructor yas--make-blank-template))
+  "A template for a snippet."
+  key
+  content
+  name
+  condition
+  expand-env
+  file
+  keybinding
+  uuid
+  menu-binding-pair
+  group      ;; as dictated by the #group: directive or .yas-make-groups
+  perm-group ;; as dictated by `yas-define-menu'
+  table
+  )
+
+(defun yas--populate-template (template &rest args)
+  "Helper function to populate a template with properties"
+  (let (p v)
+    (while args
+      (aset template
+            (position (intern (substring (symbol-name (car args)) 1))
+                      (mapcar #'car (get 'yas--template 'cl-struct-slots)))
+            (second args))
+      (setq args (cddr args)))
+    template))
+
+(defstruct (yas--table (:constructor yas--make-snippet-table (name)))
+  "A table to store snippets for a particular mode.
+
+Has the following fields:
+
+`yas--table-name'
+
+  A symbol name normally corresponding to a major mode, but can
+  also be a pseudo major-mode to be referenced in
+  `yas-extra-modes', for example.
+
+`yas--table-hash'
+
+  A hash table (KEY . NAMEHASH), known as the \"keyhash\". KEY is
+  a string or a vector, where the former is the snippet's trigger
+  and the latter means it's a direct keybinding. NAMEHASH is yet
+  another hash of (NAME . TEMPLATE) where NAME is the snippet's
+  name and TEMPLATE is a `yas--template' object.
+
+`yas--table-direct-keymap'
+
+  A keymap for the snippets in this table that have direct
+  keybindings. This is kept in sync with the keyhash, i.e., all
+  the elements of the keyhash that are vectors appear here as
+  bindings to `yas-expand-from-keymap'.
+
+`yas--table-uuidhash'
+
+  A hash table mapping snippets uuid's to the same `yas--template'
+  objects. A snippet uuid defaults to the snippet's name.
+"
+  name
+  (hash (make-hash-table :test 'equal))
+  (uuidhash (make-hash-table :test 'equal))
+  (parents nil)
+  (direct-keymap (make-sparse-keymap)))
+
+(defun yas--get-template-by-uuid (mode uuid)
+  "Find the snippet template in MODE by its UUID."
+  (let* ((table (gethash mode yas--tables mode)))
+    (when table
+      (gethash uuid (yas--table-uuidhash table)))))
+
+;; Apropos storing/updating in TABLE, this works in two steps:
+;;
+;; 1. `yas--remove-template-by-uuid' removes any
+;;    keyhash-namehash-template mappings from TABLE, grabing the
+;;    snippet by its uuid. Also removes mappings from TABLE's
+;;    `yas--table-direct-keymap' (FIXME: and should probably take care
+;;    of potentially stale menu bindings right?.)
+;;
+;; 2. `yas--add-template' adds this all over again.
+;;
+;;    Create a new or add to an existing keyhash-namehash mapping.
+;;
+;;  For reference on understanding this, consider three snippet
+;;  definitions:
+;;
+;;  A:   # name: The Foo
+;;       # key: foo
+;;       # binding: C-c M-l
+;;
+;;  B:   # name: Mrs Foo
+;;       # key: foo
+;;
+;;  C:   # name: The Bar
+;;       # binding: C-c M-l
+;;
+;;  D:   # name: Baz
+;;       # key: baz
+;;
+;;  keyhash       namehashes(3)      yas--template structs(4)
+;;  -----------------------------------------------------
+;;                                            __________
+;;                                           /          \
+;;  "foo"      --->  "The Foo" --->  [yas--template A]   |
+;;                   "Mrs Foo" --->  [yas--template B]   |
+;;                                                      |
+;;  [C-c M-l]  --->  "The Foo" -------------------------/
+;;                   "The Bar" --->  [yas--template C]
+;;
+;;  "baz"      --->  "Baz"     --->  [yas--template D]
+;;
+;; Additionally, since uuid defaults to the name, we have a
+;; `yas--table-uuidhash' for TABLE
+;;
+;; uuidhash       yas--template structs
+;; -------------------------------
+;; "The Foo" ---> [yas--template A]
+;; "Mrs Foo" ---> [yas--template B]
+;; "The Bar" ---> [yas--template C]
+;; "Baz"     ---> [yas--template D]
+;;
+;; FIXME: the more I look at this data-structure the more I think I'm
+;; stupid. There has to be an easier way (but beware lots of code
+;; depends on this).
+;;
+(defun yas--remove-template-by-uuid (table uuid)
+  "Remove from TABLE a template identified by UUID."
+  (let ((template (gethash uuid (yas--table-uuidhash table))))
+    (when template
+      (let* ((name                (yas--template-name template))
+             (empty-keys          nil))
+        ;; Remove the name from each of the targeted namehashes
+        ;;
+        (maphash #'(lambda (k v)
+                     (let ((template (gethash name v)))
+                       (when (and template
+                                  (eq uuid (yas--template-uuid template)))
+                         (remhash name v)
+                         (when (zerop (hash-table-count v))
+                           (push k empty-keys)))))
+                 (yas--table-hash table))
+        ;; Remove the namehash themselves if they've become empty
+        ;;
+        (dolist (key empty-keys)
+          (when (vectorp key)
+            (define-key (yas--table-direct-keymap table) key nil))
+          (remhash key (yas--table-hash table)))
+
+        ;; Finally, remove the uuid from the uuidhash
+        ;;
+        (remhash uuid (yas--table-uuidhash table))))))
+
+(defun yas--add-template (table template)
+  "Store in TABLE the snippet template TEMPLATE.
+
+KEY can be a string (trigger key) of a vector (direct
+keybinding)."
+  (let ((name (yas--template-name template))
+        (key (yas--template-key template))
+        (keybinding (yas--template-keybinding template))
+        (menu-binding-pair (yas--template-menu-binding-pair-get-create 
template)))
+    (dolist (k (remove nil (list key keybinding)))
+      (puthash name
+               template
+               (or (gethash k
+                            (yas--table-hash table))
+                   (puthash k
+                            (make-hash-table :test 'equal)
+                            (yas--table-hash table))))
+      (when (vectorp k)
+        (define-key (yas--table-direct-keymap table) k 
'yas-expand-from-keymap)))
+
+    ;; Update TABLE's `yas--table-uuidhash'
+    (puthash (yas--template-uuid template)
+             template
+             (yas--table-uuidhash table))))
+
+(defun yas--update-template (table template)
+  "Add or update TEMPLATE in TABLE.
+
+Also takes care of adding and updating to the associated menu."
+  ;; Remove from table by uuid
+  ;;
+  (yas--remove-template-by-uuid table (yas--template-uuid template))
+  ;; Add to table again
+  ;;
+  (yas--add-template table template)
+  ;; Take care of the menu
+  ;;
+  (when yas-use-menu
+    (yas--update-template-menu table template)))
+
+(defun yas--update-template-menu (table template)
+  "Update every menu-related for TEMPLATE"
+  (let ((menu-binding-pair (yas--template-menu-binding-pair-get-create 
template))
+        (key (yas--template-key template))
+        (keybinding (yas--template-keybinding template)))
+    ;; The snippet might have changed name or keys, so update
+    ;; user-visible strings
+    ;;
+    (unless (eq (cdr menu-binding-pair) :none)
+      ;; the menu item name
+      ;;
+      (setf (cadar menu-binding-pair) (yas--template-name template))
+      ;; the :keys information (also visible to the user)
+      (setf (getf (cdr (car menu-binding-pair)) :keys)
+            (or (and keybinding (key-description keybinding))
+                (and key (concat key yas-trigger-symbol))))))
+  (unless (yas--template-menu-managed-by-yas-define-menu template)
+    (let ((menu-keymap
+           (yas--menu-keymap-get-create (yas--table-mode table)
+                                        (mapcar #'yas--table-mode
+                                                (yas--table-parents table))))
+          (group (yas--template-group template)))
+      ;; Remove from menu keymap
+      ;;
+      (assert menu-keymap)
+      (yas--delete-from-keymap menu-keymap (yas--template-uuid template))
+
+      ;; Add necessary subgroups as necessary.
+      ;;
+      (dolist (subgroup group)
+        (let ((subgroup-keymap (lookup-key menu-keymap (vector (make-symbol 
subgroup)))))
+          (unless (and subgroup-keymap
+                       (keymapp subgroup-keymap))
+            (setq subgroup-keymap (make-sparse-keymap))
+            (define-key menu-keymap (vector (make-symbol subgroup))
+              `(menu-item ,subgroup ,subgroup-keymap)))
+          (setq menu-keymap subgroup-keymap)))
+
+      ;; Add this entry to the keymap
+      ;;
+      (define-key menu-keymap
+        (vector (make-symbol (yas--template-uuid template)))
+        (car (yas--template-menu-binding-pair template))))))
+
+(defun yas--namehash-templates-alist (namehash)
+  (let (alist)
+    (maphash #'(lambda (k v)
+                 (push (cons k v) alist))
+             namehash)
+    alist))
+
+(defun yas--fetch (table key)
+  "Fetch templates in TABLE by KEY.
+
+Return a list of cons (NAME . TEMPLATE) where NAME is a
+string and TEMPLATE is a `yas--template' structure."
+  (let* ((keyhash (yas--table-hash table))
+         (namehash (and keyhash (gethash key keyhash))))
+    (when namehash
+      (yas--filter-templates-by-condition (yas--namehash-templates-alist 
namehash)))))
+
+
+;;; Filtering/condition logic
+
+(defun yas--eval-condition (condition)
+  (condition-case err
+      (save-excursion
+        (save-restriction
+          (save-match-data
+            (eval condition))))
+    (error (progn
+             (yas--message 1 "Error in condition evaluation: %s" 
(error-message-string err))
+             nil))))
+
+
+(defun yas--filter-templates-by-condition (templates)
+  "Filter the templates using the applicable condition.
+
+TEMPLATES is a list of cons (NAME . TEMPLATE) where NAME is a
+string and TEMPLATE is a `yas--template' structure.
+
+This function implements the rules described in
+`yas-buffer-local-condition'.  See that variables documentation."
+  (let ((requirement (yas--require-template-specific-condition-p)))
+    (if (eq requirement 'always)
+        templates
+      (remove-if-not #'(lambda (pair)
+                         (yas--template-can-expand-p
+                          (yas--template-condition (cdr pair)) requirement))
+                     templates))))
+
+(defun yas--require-template-specific-condition-p ()
+  "Decides if this buffer requests/requires snippet-specific
+conditions to filter out potential expansions."
+  (if (eq 'always yas-buffer-local-condition)
+      'always
+    (let ((local-condition (or (and (consp yas-buffer-local-condition)
+                                    (yas--eval-condition 
yas-buffer-local-condition))
+                               yas-buffer-local-condition)))
+      (when local-condition
+        (if (eq local-condition t)
+            t
+          (and (consp local-condition)
+               (eq 'require-snippet-condition (car local-condition))
+               (symbolp (cdr local-condition))
+               (cdr local-condition)))))))
+
+(defun yas--template-can-expand-p (condition requirement)
+  "Evaluates CONDITION and REQUIREMENT and returns a boolean"
+  (let* ((result (or (null condition)
+                     (yas--eval-condition condition))))
+    (cond ((eq requirement t)
+           result)
+          (t
+           (eq requirement result)))))
+
+(defun yas--all-parents (mode)
+  "Returns a list of all parent modes of MODE"
+  (let ((parents (gethash mode yas--parents)))
+    (append parents
+            (mapcan #'yas--all-parents parents))))
+
+(defun yas--table-templates (table)
+  (when table
+    (let ((acc (list)))
+      (maphash #'(lambda (key namehash)
+                   (maphash #'(lambda (name template)
+                                (push (cons name template) acc))
+                            namehash))
+               (yas--table-hash table))
+      (yas--filter-templates-by-condition acc))))
+
+(defun yas--current-key ()
+  "Get the key under current position. A key is used to find
+the template of a snippet in the current snippet-table."
+  (let ((start (point))
+        (end (point))
+        (syntaxes yas-key-syntaxes)
+        syntax
+        done
+        templates)
+    (while (and (not done) syntaxes)
+      (setq syntax (car syntaxes))
+      (setq syntaxes (cdr syntaxes))
+      (save-excursion
+        (skip-syntax-backward syntax)
+        (setq start (point)))
+      (setq templates
+            (mapcan #'(lambda (table)
+                        (yas--fetch table (buffer-substring-no-properties 
start end)))
+                    (yas--get-snippet-tables)))
+      (if templates
+          (setq done t)
+        (setq start end)))
+    (list templates
+          start
+          end)))
+
+
+(defun yas--table-all-keys (table)
+  (when table
+    (let ((acc))
+      (maphash #'(lambda (key namehash)
+                   (when (yas--filter-templates-by-condition 
(yas--namehash-templates-alist namehash))
+                     (push key acc)))
+               (yas--table-hash table))
+      acc)))
+
+(defun yas--table-mode (table)
+  (intern (yas--table-name table)))
+
+
+;;; Internal functions:
+
+(defun yas--real-mode? (mode)
+  "Try to find out if MODE is a real mode. The MODE bound to
+a function (like `c-mode') is considered real mode. Other well
+known mode like `ruby-mode' which is not part of Emacs might
+not bound to a function until it is loaded. So yasnippet keeps
+a list of modes like this to help the judgement."
+  (or (fboundp mode)
+      (find mode yas--known-modes)))
+
+(defun yas--eval-lisp (form)
+  "Evaluate FORM and convert the result to string."
+  (let ((retval (catch 'yas--exception
+                  (condition-case err
+                      (save-excursion
+                        (save-restriction
+                          (save-match-data
+                            (widen)
+                            (let ((result (eval form)))
+                              (when result
+                                (format "%s" result))))))
+                    (error (if yas-good-grace
+                               (yas--format "elisp error! %s" 
(error-message-string err))
+                             (error (yas--format "elisp error: %s"
+                                            (error-message-string err)))))))))
+    (when (and (consp retval)
+               (eq 'yas--exception (car retval)))
+      (error (cdr retval)))
+    retval))
+
+(defun yas--eval-lisp-no-saves (form)
+  (condition-case err
+      (eval form)
+    (error (if yas-good-grace
+               (yas--format "elisp error! %s" (error-message-string err))
+             (error (yas--format "elisp error: %s"
+                            (error-message-string err)))))))
+
+(defun yas--read-lisp (string &optional nil-on-error)
+  "Read STRING as a elisp expression and return it.
+
+In case STRING in an invalid expression and NIL-ON-ERROR is nil,
+return an expression that when evaluated will issue an error."
+  (condition-case err
+      (read string)
+    (error (and (not nil-on-error)
+                `(error (error-message-string ,err))))))
+
+(defun yas--read-keybinding (keybinding)
+  "Read KEYBINDING as a snippet keybinding, return a vector."
+  (when (and keybinding
+             (not (string-match "keybinding" keybinding)))
+    (condition-case err
+        (let ((res (or (and (string-match "^\\[.*\\]$" keybinding)
+                            (read keybinding))
+                       (read-kbd-macro keybinding 'need-vector))))
+          res)
+      (error
+       (yas--message 3 "warning: keybinding \"%s\" invalid since %s."
+                keybinding (error-message-string err))
+       nil))))
+
+(defvar yas-extra-modes nil
+  "If non-nil, also lookup snippets for this/these modes.
+
+Can be a symbol or a list of symbols.
+
+This variable probably makes more sense as buffer-local, so
+ensure your use `make-local-variable' when you set it.")
+(defun yas-extra-modes ()
+  (if (listp yas-extra-modes) yas-extra-modes (list yas-extra-modes)))
+(defvaralias 'yas/mode-symbol 'yas-extra-modes)
+
+(defun yas--table-get-create (mode)
+  "Get or create the snippet table corresponding to MODE."
+  (let ((table (gethash mode
+                        yas--tables)))
+    (unless table
+      (setq table (yas--make-snippet-table (symbol-name mode)))
+      (puthash mode table yas--tables)
+      (push (cons (intern (format "yas--direct-%s" mode))
+                  (yas--table-direct-keymap table))
+            yas--direct-keymaps))
+    table))
+
+(defun yas--get-snippet-tables ()
+  "Get snippet tables for current buffer.
+
+Return a list of `yas--table' objects. The list of modes to
+consider is returned by `yas--modes-to-activate'"
+  (remove nil
+          (mapcar #'(lambda (mode-name)
+                      (gethash mode-name yas--tables))
+                  (yas--modes-to-activate))))
+
+(defun yas--menu-keymap-get-create (mode &optional parents)
+  "Get or create the menu keymap for MODE and its PARENTS.
+
+This may very well create a plethora of menu keymaps and arrange
+them all in `yas--menu-table'"
+  (let* ((menu-keymap (or (gethash mode yas--menu-table)
+                          (puthash mode (make-sparse-keymap) 
yas--menu-table))))
+    (mapc #'yas--menu-keymap-get-create parents)
+    (define-key yas--minor-mode-menu (vector mode)
+        `(menu-item ,(symbol-name mode) ,menu-keymap
+                    :visible (yas--show-menu-p ',mode)))
+    menu-keymap))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Template-related and snippet loading functions
+
+(defun yas--parse-template (&optional file)
+  "Parse the template in the current buffer.
+
+Optional FILE is the absolute file name of the file being
+parsed.
+
+Optional GROUP is the group where the template is to go,
+otherwise we attempt to calculate it from FILE.
+
+Return a snippet-definition, i.e. a list
+
+ (KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING UUID)
+
+If the buffer contains a line of \"# --\" then the contents above
+this line are ignored. Directives can set most of these with the syntax:
+
+# directive-name : directive-value
+
+Here's a list of currently recognized directives:
+
+ * type
+ * name
+ * contributor
+ * condition
+ * group
+ * key
+ * expand-env
+ * binding
+ * uuid"
+  (goto-char (point-min))
+  (let* ((type 'snippet)
+         (name (and file
+                    (file-name-nondirectory file)))
+         (key nil)
+         template
+         bound
+         condition
+         (group (and file
+                     (yas--calculate-group file)))
+         expand-env
+         binding
+         uuid)
+    (if (re-search-forward "^# --\n" nil t)
+        (progn (setq template
+                     (buffer-substring-no-properties (point)
+                                                     (point-max)))
+               (setq bound (point))
+               (goto-char (point-min))
+               (while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*\\)$" 
bound t)
+                 (when (string= "uuid" (match-string-no-properties 1))
+                   (setq uuid (match-string-no-properties 2)))
+                 (when (string= "type" (match-string-no-properties 1))
+                   (setq type (if (string= "command" 
(match-string-no-properties 2))
+                                  'command
+                                'snippet)))
+                 (when (string= "key" (match-string-no-properties 1))
+                   (setq key (match-string-no-properties 2)))
+                 (when (string= "name" (match-string-no-properties 1))
+                   (setq name (match-string-no-properties 2)))
+                 (when (string= "condition" (match-string-no-properties 1))
+                   (setq condition (yas--read-lisp (match-string-no-properties 
2))))
+                 (when (string= "group" (match-string-no-properties 1))
+                   (setq group (match-string-no-properties 2)))
+                 (when (string= "expand-env" (match-string-no-properties 1))
+                   (setq expand-env (yas--read-lisp 
(match-string-no-properties 2)
+                                                   'nil-on-error)))
+                 (when (string= "binding" (match-string-no-properties 1))
+                   (setq binding (match-string-no-properties 2)))))
+      (setq template
+            (buffer-substring-no-properties (point-min) (point-max))))
+    (unless (or key binding)
+      (setq key (and file (file-name-nondirectory file))))
+    (when (eq type 'command)
+      (setq template (yas--read-lisp (concat "(progn" template ")"))))
+    (when group
+      (setq group (split-string group "\\.")))
+    (list key template name condition group expand-env file binding uuid)))
+
+(defun yas--calculate-group (file)
+  "Calculate the group for snippet file path FILE."
+  (let* ((dominating-dir (locate-dominating-file file
+                                                 ".yas-make-groups"))
+         (extra-path (and dominating-dir
+                          (replace-regexp-in-string (concat "^"
+                                                            (expand-file-name 
dominating-dir))
+                                                    ""
+                                                    (expand-file-name file))))
+         (extra-dir (and extra-path
+                         (file-name-directory extra-path)))
+         (group (and extra-dir
+                     (replace-regexp-in-string "/"
+                                               "."
+                                               (directory-file-name 
extra-dir)))))
+    group))
+
+(defun yas--subdirs (directory &optional filep)
+  "Return subdirs or files of DIRECTORY according to FILEP."
+  (remove-if (lambda (file)
+               (or (string-match "^\\."
+                                 (file-name-nondirectory file))
+                   (string-match "^#.*#$"
+                                 (file-name-nondirectory file))
+                   (string-match "~$"
+                                 (file-name-nondirectory file))
+                   (if filep
+                       (file-directory-p file)
+                     (not (file-directory-p file)))))
+             (directory-files directory t)))
+
+(defun yas--make-menu-binding (template)
+  (let ((mode (yas--table-mode (yas--template-table template))))
+    `(lambda () (interactive) (yas--expand-or-visit-from-menu ',mode 
,(yas--template-uuid template)))))
+
+(defun yas--expand-or-visit-from-menu (mode uuid)
+  (let* ((table (yas--table-get-create mode))
+         (yas--current-template (and table
+                                    (gethash uuid (yas--table-uuidhash 
table)))))
+    (when yas--current-template
+      (if yas-visit-from-menu
+          (yas--visit-snippet-file-1 yas--current-template)
+        (let ((where (if (region-active-p)
+                         (cons (region-beginning) (region-end))
+                       (cons (point) (point)))))
+          (yas-expand-snippet (yas--template-content yas--current-template)
+                              (car where)
+                              (cdr where)
+                              (yas--template-expand-env 
yas--current-template)))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Popping up for keys and templates
+;;
+(defvar yas--x-pretty-prompt-templates nil
+  "If non-nil, attempt to prompt for templates like TextMate.")
+
+
+(defun yas--prompt-for-template (templates &optional prompt)
+  "Interactively choose a template from the list TEMPLATES.
+
+TEMPLATES is a list of `yas--template'."
+  (when templates
+    (setq templates
+          (sort templates #'(lambda (t1 t2)
+                              (< (length (yas--template-name t1))
+                                 (length (yas--template-name t2))))))
+    (if yas--x-pretty-prompt-templates
+        (yas--x-pretty-prompt-templates "Choose a snippet" templates)
+      (some #'(lambda (fn)
+                (funcall fn (or prompt "Choose a snippet: ")
+                         templates
+                         #'yas--template-name))
+            yas-prompt-functions))))
+
+(defun yas--prompt-for-keys (keys &optional prompt)
+  "Interactively choose a template key from the list KEYS."
+  (when keys
+    (some #'(lambda (fn)
+              (funcall fn (or prompt "Choose a snippet key: ") keys))
+          yas-prompt-functions)))
+
+(defun yas--prompt-for-table (tables &optional prompt)
+  (when tables
+    (some #'(lambda (fn)
+              (funcall fn (or prompt "Choose a snippet table: ")
+                       tables
+                       #'yas--table-name))
+          yas-prompt-functions)))
+
+(defun yas-x-prompt (prompt choices &optional display-fn)
+  "Display choices in a x-window prompt."
+  ;; FIXME: HACK: if we notice that one of the objects in choices is
+  ;; actually a `yas--template', defer to `yas--x-prompt-pretty-templates'
+  ;;
+  ;; This would be better implemented by passing CHOICES as a
+  ;; strucutred tree rather than a list. Modifications would go as far
+  ;; up as `yas--all-templates' I think.
+  ;;
+  (when (and window-system choices)
+    (let ((chosen
+           (let (menu d) ;; d for display
+             (dolist (c choices)
+               (setq d (or (and display-fn (funcall display-fn c))
+                           c))
+               (cond ((stringp d)
+                      (push (cons (concat "   " d) c) menu))
+                     ((listp d)
+                      (push (car d) menu))))
+             (setq menu (list prompt (push "title" menu)))
+             (x-popup-menu (if (fboundp 'posn-at-point)
+                               (let ((x-y (posn-x-y (posn-at-point (point)))))
+                                 (list (list (+ (car x-y) 10)
+                                             (+ (cdr x-y) 20))
+                                       (selected-window)))
+                             t)
+                           menu))))
+      (or chosen
+          (keyboard-quit)))))
+
+(defun yas--x-pretty-prompt-templates (prompt templates)
+  "Display TEMPLATES, grouping neatly by table name."
+  (let ((organized (make-hash-table :test #'equal))
+        menu
+        more-than-one-table
+        prefix)
+    (dolist (tl templates)
+      (puthash (yas--template-table tl)
+               (cons tl
+                     (gethash (yas--template-table tl) organized))
+               organized))
+    (setq more-than-one-table (> (hash-table-count organized) 1))
+    (setq prefix (if more-than-one-table
+                     "   " ""))
+    (if more-than-one-table
+        (maphash #'(lambda (table templates)
+                     (push (yas--table-name table) menu)
+                     (dolist (tl templates)
+                       (push (cons (concat prefix (yas--template-name tl)) tl) 
menu))) organized)
+      (setq menu (mapcar #'(lambda (tl) (cons (concat prefix 
(yas--template-name tl)) tl)) templates)))
+
+    (setq menu (nreverse menu))
+    (or (x-popup-menu (if (fboundp 'posn-at-point)
+                          (let ((x-y (posn-x-y (posn-at-point (point)))))
+                            (list (list (+ (car x-y) 10)
+                                        (+ (cdr x-y) 20))
+                                  (selected-window)))
+                        t)
+                      (list prompt (push "title" menu)))
+        (keyboard-quit))))
+
+(defun yas-ido-prompt (prompt choices &optional display-fn)
+  (when (and (fboundp 'ido-completing-read)
+            (or (>= emacs-major-version 24)
+                ido-mode))
+    (yas-completing-prompt prompt choices display-fn #'ido-completing-read)))
+
+(eval-when-compile (require 'dropdown-list nil t))
+(defun yas-dropdown-prompt (prompt choices &optional display-fn)
+  (when (featurep 'dropdown-list)
+    (let (formatted-choices
+          filtered-choices
+          d
+          n)
+      (dolist (choice choices)
+        (setq d (or (and display-fn (funcall display-fn choice))
+                      choice))
+        (when (stringp d)
+          (push d formatted-choices)
+          (push choice filtered-choices)))
+
+      (setq n (and formatted-choices (dropdown-list formatted-choices)))
+      (if n
+          (nth n filtered-choices)
+        (keyboard-quit)))))
+
+(defun yas-completing-prompt (prompt choices &optional display-fn 
completion-fn)
+  (let (formatted-choices
+        filtered-choices
+        chosen
+        d
+        (completion-fn (or completion-fn
+                           #'completing-read)))
+    (dolist (choice choices)
+      (setq d (or (and display-fn (funcall display-fn choice))
+                    choice))
+      (when (stringp d)
+        (push d formatted-choices)
+        (push choice filtered-choices)))
+    (setq chosen (and formatted-choices
+                      (funcall completion-fn prompt
+                               formatted-choices
+                               nil
+                               'require-match
+                               nil
+                               nil)))
+    (let ((position (or (and chosen
+                             (position chosen formatted-choices :test 
#'string=))
+                        0)))
+      (nth position filtered-choices))))
+
+(defun yas-no-prompt (prompt choices &optional display-fn)
+  (first choices))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Loading snippets from files
+;;
+(defun yas--load-yas-setup-file (file)
+  (load file 'noerror))
+
+(defun yas-load-directory (top-level-dir &optional use-jit)
+  "Load snippets in directory hierarchy TOP-LEVEL-DIR.
+
+Below TOP-LEVEL-DIR each directory should be a mode name.
+
+Optional USE-JIT use jit-loading of snippets."
+  (interactive "DSelect the root directory: ")
+  (unless yas-snippet-dirs
+    (setq yas-snippet-dirs top-level-dir))
+  (dolist (dir (yas--subdirs top-level-dir))
+    (let* ((major-mode-and-parents (yas--compute-major-mode-and-parents
+                                    (concat dir "/dummy")))
+           (mode-sym (car major-mode-and-parents))
+           (parents (cdr major-mode-and-parents)))
+      ;; Attention: The parents and the menus are already defined
+      ;; here, even if the snippets are later jit-loaded.
+      ;;
+      ;; * We need to know the parents at this point since entering a
+      ;;   given mode should jit load for its parents
+      ;;   immediately. This could be reviewed, the parents could be
+      ;;   discovered just-in-time-as well
+      ;;
+      ;; * We need to create the menus here to support the `full'
+      ;;   option to `yas-use-menu' (all known snippet menus are shown to the 
user)
+      ;;
+      (yas--define-parents mode-sym parents)
+      (yas--menu-keymap-get-create mode-sym)
+      (let ((form `(yas--load-directory-1 ,dir
+                                         ',mode-sym
+                                         ',parents)))
+        (if use-jit
+            (yas--schedule-jit mode-sym form)
+            (eval form)))))
+  (when (interactive-p)
+    (yas--message 3 "Loaded snippets from %s." top-level-dir)))
+
+(defun yas--load-directory-1 (directory mode-sym parents &optional 
no-compiled-snippets)
+  "Recursively load snippet templates from DIRECTORY."
+  (unless (file-exists-p (concat directory "/" ".yas-skip"))
+    (if (and (not no-compiled-snippets)
+             (progn (yas--message 2 "Loading compiled snippets from %s" 
directory) t)
+             (load (expand-file-name ".yas-compiled-snippets" directory) 
'noerror (<= yas-verbosity 3)))
+      (yas--message 2 "Loading snippet files from %s" directory)
+      (yas--load-directory-2 directory mode-sym))))
+
+(defun yas--load-directory-2 (directory mode-sym)
+  ;; Load .yas-setup.el files wherever we find them
+  ;;
+  (yas--load-yas-setup-file (expand-file-name ".yas-setup" directory))
+  (let* ((default-directory directory)
+         (snippet-defs nil))
+    ;; load the snippet files
+    ;;
+    (with-temp-buffer
+      (dolist (file (yas--subdirs directory 'no-subdirs-just-files))
+        (when (file-readable-p file)
+          (insert-file-contents file nil nil nil t)
+          (push (yas--parse-template file)
+                snippet-defs))))
+    (when snippet-defs
+      (yas-define-snippets mode-sym
+                           snippet-defs))
+    ;; now recurse to a lower level
+    ;;
+    (dolist (subdir (yas--subdirs directory))
+      (yas--load-directory-2 subdir
+                            mode-sym))))
+
+(defun yas--load-snippet-dirs (&optional nojit)
+  "Reload the directories listed in `yas-snippet-dirs' or
+   prompt the user to select one."
+  (let (errors)
+    (if yas-snippet-dirs
+        (dolist (directory (reverse (yas-snippet-dirs)))
+          (cond ((file-directory-p directory)
+                 (yas-load-directory directory (not nojit))
+                 (if nojit
+                     (yas--message 3 "Loaded %s" directory)
+                   (yas--message 3 "Prepared just-in-time loading for %s" 
directory)))
+                (t
+                 (push (yas--message 0 "Check your `yas-snippet-dirs': %s is 
not a directory" directory) errors))))
+      (call-interactively 'yas-load-directory))
+    errors))
+
+(defun yas-reload-all (&optional interactive)
+  "Reload all snippets and rebuild the YASnippet menu.
+
+When called interactively force immediate reload of all known
+snippets under `yas-snippet-dirs', otherwise use just-in-time
+loading."
+  (interactive "p")
+  (catch 'abort
+    (let ((errors)
+          (snippet-editing-buffers
+           (remove-if-not #'(lambda (buffer)
+                              (with-current-buffer buffer 
yas--editing-template))
+                          (buffer-list))))
+      ;; Warn if there are buffers visiting snippets, since reloading will 
break
+      ;; any on-line editing of those buffers.
+      ;;
+      (when snippet-editing-buffers
+          (if interactive
+              (if (y-or-n-p "Some buffers editing live snippets, close them 
and proceed with reload?")
+                  (mapc #'kill-buffer snippet-editing-buffers)
+                (yas--message 1 "Aborted reload...")
+                (throw 'abort nil))
+            ;; in a non-interactive use, at least set
+            ;; `yas--editing-template' to nil, make it guess it next time 
around
+            (mapc #'(lambda (buffer) (setq yas--editing-template nil)) 
(buffer-list))))
+
+      ;; Empty all snippet tables, parenting info and all menu tables
+      ;;
+      (setq yas--tables (make-hash-table))
+      (setq yas--parents (make-hash-table))
+      (setq yas--menu-table (make-hash-table))
+
+      ;; Cancel all pending 'yas--scheduled-jit-loads'
+      ;;
+      (setq yas--scheduled-jit-loads (make-hash-table))
+
+      ;; Init the `yas-minor-mode-map', taking care not to break the
+      ;; menu....
+      ;;
+      (setcdr yas-minor-mode-map (cdr (yas--init-minor-keymap)))
+
+      ;; Reload the directories listed in `yas-snippet-dirs' or prompt
+      ;; the user to select one.
+      ;;
+      (setq errors (yas--load-snippet-dirs interactive))
+      ;; Reload the direct keybindings
+      ;;
+      (yas-direct-keymaps-reload)
+      ;; Reload the trigger-key (shoudn't be needed, but see issue #237)
+      ;;
+      (yas--trigger-key-reload)
+
+      (yas--message 3 "Reloaded everything%s...%s."
+                   (if interactive "" " (snippets will load just-in-time)")
+                   (if errors " (some errors, check *Messages*)" "")))))
+
+(defun yas--load-pending-jits ()
+  (when yas-minor-mode
+    (dolist (mode (yas--modes-to-activate))
+      (let ((forms (reverse (gethash mode yas--scheduled-jit-loads))))
+        ;; must reverse to maintain coherence with `yas-snippet-dirs'
+        (dolist (form forms)
+          (yas--message  3 "Loading for `%s', just-in-time: %s!" mode form)
+          (eval form))
+        (remhash mode yas--scheduled-jit-loads)))))
+
+;; (when (<= emacs-major-version 22)
+;;   (add-hook 'after-change-major-mode-hook 'yas--load-pending-jits))
+
+(defun yas--quote-string (string)
+  "Escape and quote STRING.
+foo\"bar\\! -> \"foo\\\"bar\\\\!\""
+  (concat "\""
+          (replace-regexp-in-string "[\\\"]"
+                                    "\\\\\\&"
+                                    string
+                                    t)
+          "\""))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Snippet compilation function
+
+(defun yas--initialize ()
+  "For backward compatibility, enable `yas-minor-mode' globally"
+  (yas-global-mode 1))
+
+(defun yas-compile-directory (top-level-dir)
+  "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR.
+
+This works by stubbing a few functions, then calling
+`yas-load-directory'."
+  (interactive "DTop level snippet directory?")
+  (flet ((yas--load-yas-setup-file
+          (file)
+          (let ((elfile (concat file ".el")))
+            (when (file-exists-p elfile)
+              (insert ";;; .yas-setup.el support file if any:\n;;;\n")
+              (insert-file-contents elfile)
+              (end-of-buffer)
+              )))
+         (yas-define-snippets
+          (mode snippets)
+          (insert ";;; Snippet definitions:\n;;;\n")
+          (let ((literal-snippets (list))
+                (print-length nil))
+            (dolist (snippet snippets)
+              (let ((key                    (first   snippet))
+                    (template-content       (second  snippet))
+                    (name                   (third   snippet))
+                    (condition              (fourth  snippet))
+                    (group                  (fifth   snippet))
+                    (expand-env             (sixth   snippet))
+                    (file                   nil) ;; (seventh snippet)) ;; omit 
on purpose
+                    (binding                (eighth  snippet))
+                    (uuid                    (ninth   snippet)))
+                (push `(,key
+                        ,template-content
+                        ,name
+                        ,condition
+                        ,group
+                        ,expand-env
+                        ,file
+                        ,binding
+                        ,uuid)
+                      literal-snippets)))
+            (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
+            (insert "\n\n")))
+         (yas--load-directory-1
+          (dir mode parents &rest ignore)
+          (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
+            (with-temp-file output-file
+              (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
+              (yas--load-directory-2 dir mode)
+              (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
+    (yas-load-directory top-level-dir nil)))
+
+(defun yas-recompile-all ()
+  "Compile every dir in `yas-snippet-dirs'."
+  (interactive)
+  (mapc #'yas-compile-directory (yas-snippet-dirs)))
+
+
+;;; JIT loading
+;;;
+
+(defvar yas--scheduled-jit-loads (make-hash-table)
+  "Alist of mode-symbols to forms to be evaled when `yas-minor-mode' kicks 
in.")
+
+(defun yas--schedule-jit (mode form)
+  (puthash mode
+           (cons form
+                 (gethash mode yas--scheduled-jit-loads))
+           yas--scheduled-jit-loads))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Some user level functions
+;;;
+
+(defun yas-about ()
+  (interactive)
+  (message (concat "yasnippet (version "
+                   yas--version
+                   ") -- pluskid <address@hidden>/joaotavora 
<address@hidden>")))
+
+(defun yas--define-parents (mode parents)
+  "Add PARENTS to the list of MODE's parents"
+  (puthash mode (remove-duplicates
+                 (append parents
+                         (gethash mode yas--parents)))
+           yas--parents))
+
+(defun yas-define-snippets (mode snippets)
+  "Define SNIPPETS for MODE.
+
+SNIPPETS is a list of snippet definitions, each taking the
+following form
+
+ (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
+
+Within these, only KEY and TEMPLATE are actually mandatory.
+
+TEMPLATE might be a lisp form or a string, depending on whether
+this is a snippet or a snippet-command.
+
+CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
+been `yas--read-lisp'-ed and will eventually be
+`yas--eval-lisp'-ed.
+
+The remaining elements are strings.
+
+FILE is probably of very little use if you're programatically
+defining snippets.
+
+UUID is the snippets \"unique-id\". Loading a second snippet file
+with the same uuid replaced the previous snippet.
+
+You can use `yas--parse-template' to return such lists based on
+the current buffers contents."
+  (let ((snippet-table (yas--table-get-create mode))
+        (template nil))
+    (dolist (snippet snippets)
+      (setq template (yas-define-snippets-1 snippet
+                                            snippet-table)))
+    template))
+
+(defun yas-define-snippets-1 (snippet snippet-table)
+  "Helper for `yas-define-snippets'."
+  ;; X) Calculate some more defaults on the values returned by
+  ;; `yas--parse-template'.
+  ;;
+  (let* ((file (seventh snippet))
+         (key (car snippet))
+         (name (or (third snippet)
+                   (and file
+                        (file-name-directory file))))
+         (condition (fourth snippet))
+         (group (fifth snippet))
+         (keybinding (yas--read-keybinding (eighth snippet)))
+         (uuid (or (ninth snippet)
+                  name))
+         (template (or (gethash uuid (yas--table-uuidhash snippet-table))
+                       (yas--make-blank-template))))
+    ;; X) populate the template object
+    ;;
+    (yas--populate-template template
+                           :table       snippet-table
+                           :key         key
+                           :content     (second snippet)
+                           :name        (or name key)
+                           :group       group
+                           :condition   condition
+                           :expand-env  (sixth snippet)
+                           :file        (seventh snippet)
+                           :keybinding  keybinding
+                           :uuid         uuid)
+    ;; X) Update this template in the appropriate table. This step
+    ;;    also will take care of adding the key indicators in the
+    ;;    templates menu entry, if any
+    ;;
+    (yas--update-template snippet-table template)
+    ;; X) Return the template
+    ;;
+    ;;
+    template))
+
+
+;;; Apropos snippet menu:
+;;
+;; The snippet menu keymaps are store by mode in hash table called
+;; `yas--menu-table'. They are linked to the main menu in
+;; `yas--menu-keymap-get-create' and are initially created empty,
+;; reflecting the table hierarchy.
+;;
+;; They can be populated in two mutually exclusive ways: (1) by
+;; reading `yas--template-group', which in turn is populated by the "#
+;; group:" directives of the snippets or the ".yas-make-groups" file
+;; or (2) by using a separate `yas-define-menu' call, which declares a
+;; menu structure based on snippets uuids.
+;;
+;; Both situations are handled in `yas--update-template-menu', which
+;; uses the predicate `yas--template-menu-managed-by-yas-define-menu'
+;; that can tell between the two situations.
+;;
+;; Note:
+;;
+;; * if `yas-define-menu' is used it must run before
+;;   `yas-define-snippets' and the UUIDS must match, otherwise we get
+;;   duplicate entries. The `yas--template' objects are created in
+;;   `yas-define-menu', holding nothing but the menu entry,
+;;   represented by a pair of ((menu-item NAME :keys KEYS) TYPE) and
+;;   stored in `yas--template-menu-binding-pair'. The (menu-item ...)
+;;   part is then stored in the menu keymap itself which make the item
+;;   appear to the user. These limitations could probably be revised.
+;;
+;; * The `yas--template-perm-group' slot is only used in
+;;   `yas-describe-tables'.
+;;
+(defun yas--template-menu-binding-pair-get-create (template &optional type)
+  "Get TEMPLATE's menu binding or assign it a new one.
+
+TYPE may be `:stay', signalling this menu binding should be
+static in the menu."
+  (or (yas--template-menu-binding-pair template)
+      (let ((key (yas--template-key template))
+            (keybinding (yas--template-keybinding template)))
+        (setf (yas--template-menu-binding-pair template)
+              (cons `(menu-item ,(or (yas--template-name template)
+                                     (yas--template-uuid template))
+                                ,(yas--make-menu-binding template)
+                                :keys ,nil)
+                    type)))))
+(defun yas--template-menu-managed-by-yas-define-menu (template)
+  "Non-nil if TEMPLATE's menu entry was included in a `yas-define-menu' call."
+  (cdr (yas--template-menu-binding-pair template)))
+
+
+(defun yas--show-menu-p (mode)
+  (cond ((eq yas-use-menu 'abbreviate)
+         (find mode
+               (mapcar #'(lambda (table)
+                           (yas--table-mode table))
+                       (yas--get-snippet-tables))))
+        ((eq yas-use-menu 'full)
+         t)
+        ((eq yas-use-menu t)
+         t)))
+
+(defun yas--delete-from-keymap (keymap uuid)
+  "Recursively delete items with UUID from KEYMAP and its submenus."
+
+  ;; XXX: This used to skip any submenus named \"parent mode\"
+  ;;
+  ;; First of all, recursively enter submenus, i.e. the tree is
+  ;; searched depth first so that stale submenus can be found in the
+  ;; higher passes.
+  ;;
+  (mapc #'(lambda (item)
+            (when (and (listp (cdr item))
+                       (keymapp (third (cdr item))))
+              (yas--delete-from-keymap (third (cdr item)) uuid)))
+        (rest keymap))
+  ;; Set the uuid entry to nil
+  ;;
+  (define-key keymap (vector (make-symbol uuid)) nil)
+  ;; Destructively modify keymap
+  ;;
+  (setcdr keymap (delete-if #'(lambda (item)
+                                (or (null (cdr item))
+                                    (and (keymapp (third (cdr item)))
+                                         (null (cdr (third (cdr item)))))))
+                            (rest keymap))))
+
+(defun yas-define-menu (mode menu &optional omit-items)
+  "Define a snippet menu for MODE according to MENU, ommitting OMIT-ITEMS.
+
+MENU is a list, its elements can be:
+
+- (yas-item UUID) : Creates an entry the snippet identified with
+  UUID. The menu entry for a snippet thus identified is
+  permanent, i.e. it will never move (be reordered) in the menu.
+
+- (yas-separator) : Creates a separator
+
+- (yas-submenu NAME SUBMENU) : Creates a submenu with NAME,
+  SUBMENU has the same form as MENU. NAME is also added to the
+  list of groups of the snippets defined thereafter.
+
+OMIT-ITEMS is a list of snippet uuid's that will always be
+ommited from MODE's menu, even if they're manually loaded.
+
+This function does nothing if `yas-use-menu' is nil.
+"
+  (when yas-use-menu
+    (let* ((table (yas--table-get-create mode))
+           (hash (yas--table-uuidhash table)))
+      (yas--define-menu-1 table
+                          (yas--menu-keymap-get-create mode)
+                          menu
+                          hash)
+      (dolist (uuid omit-items)
+        (let ((template (or (gethash uuid hash)
+                            (yas--populate-template (puthash uuid
+                                                             
(yas--make-blank-template)
+                                                             hash)
+                                                    :table table
+                                                    :uuid uuid))))
+          (setf (yas--template-menu-binding-pair template) (cons nil 
:none)))))))
+
+(defun yas--define-menu-1 (table menu-keymap menu uuidhash &optional 
group-list)
+  (dolist (e (reverse menu))
+    (cond ((eq (first e) 'yas-item)
+           (let ((template (or (gethash (second e) uuidhash)
+                               (yas--populate-template (puthash (second e)
+                                                               
(yas--make-blank-template)
+                                                               uuidhash)
+                                                      :table table
+                                                      :perm-group group-list
+                                                      :uuid (second e)))))
+             (define-key menu-keymap (vector (gensym))
+               (car (yas--template-menu-binding-pair-get-create template 
:stay)))))
+          ((eq (first e) 'yas-submenu)
+           (let ((subkeymap (make-sparse-keymap)))
+             (define-key menu-keymap (vector (gensym))
+               `(menu-item ,(second e) ,subkeymap))
+             (yas--define-menu-1 table
+                                subkeymap
+                                (third e)
+                                uuidhash
+                                (append group-list (list (second e))))))
+          ((eq (first e) 'yas-separator)
+           (define-key menu-keymap (vector (gensym))
+             '(menu-item "----")))
+          (t
+           (yas--message 3 "Don't know anything about menu entry %s" (first 
e))))))
+
+(defun yas--define (mode key template &optional name condition group)
+  "Define a snippet.  Expanding KEY into TEMPLATE.
+
+NAME is a description to this template.  Also update the menu if
+`yas-use-menu' is t.  CONDITION is the condition attached to
+this snippet.  If you attach a condition to a snippet, then it
+will only be expanded when the condition evaluated to non-nil."
+  (yas-define-snippets mode
+                       (list (list key template name condition group))))
+
+(defun yas-hippie-try-expand (first-time?)
+  "Integrate with hippie expand.  Just put this function in
+`hippie-expand-try-functions-list'."
+  (when yas-minor-mode
+    (if (not first-time?)
+        (let ((yas-fallback-behavior 'return-nil))
+          (yas-expand))
+      (undo 1)
+      nil)))
+
+
+;;; Apropos condition-cache:
+;;;
+;;;
+;;;
+;;;
+(defvar yas--condition-cache-timestamp nil)
+(defmacro yas-define-condition-cache (func doc &rest body)
+  "Define a function FUNC with doc DOC and body BODY, BODY is
+executed at most once every snippet expansion attempt, to check
+expansion conditions.
+
+It doesn't make any sense to call FUNC programatically."
+  `(defun ,func () ,(if (and doc
+                             (stringp doc))
+                        (concat doc
+"\n\nFor use in snippets' conditions. Within each
+snippet-expansion routine like `yas-expand', computes actual
+value for the first time then always returns a cached value.")
+                      (setq body (cons doc body))
+                      nil)
+     (let ((timestamp-and-value (get ',func 'yas--condition-cache)))
+       (if (equal (car timestamp-and-value) yas--condition-cache-timestamp)
+           (cdr timestamp-and-value)
+         (let ((new-value (progn
+                            ,@body
+                            )))
+           (put ',func 'yas--condition-cache (cons 
yas--condition-cache-timestamp new-value))
+           new-value)))))
+
+(defalias 'yas-expand 'yas-expand-from-trigger-key)
+(defun yas-expand-from-trigger-key (&optional field)
+  "Expand a snippet before point.
+
+If no snippet expansion is possible, fall back to the behaviour
+defined in `yas-fallback-behavior'.
+
+Optional argument FIELD is for non-interactive use and is an
+object satisfying `yas--field-p' to restrict the expansion to."
+  (interactive)
+  (setq yas--condition-cache-timestamp (current-time))
+  (let (templates-and-pos)
+    (unless (and yas-expand-only-for-last-commands
+                 (not (member last-command yas-expand-only-for-last-commands)))
+      (setq templates-and-pos (if field
+                                  (save-restriction
+                                    (narrow-to-region (yas--field-start field)
+                                                      (yas--field-end field))
+                                    (yas--current-key))
+                                (yas--current-key))))
+    (if (and templates-and-pos
+             (first templates-and-pos))
+        (yas--expand-or-prompt-for-template (first templates-and-pos)
+                                           (second templates-and-pos)
+                                           (third templates-and-pos))
+      (yas--fallback 'trigger-key))))
+
+(defun yas-expand-from-keymap ()
+  "Directly expand some snippets, searching `yas--direct-keymaps'.
+
+If expansion fails, execute the previous binding for this key"
+  (interactive)
+  (setq yas--condition-cache-timestamp (current-time))
+  (let* ((yas--prefix current-prefix-arg)
+         (vec (subseq (this-command-keys-vector) (if current-prefix-arg
+                                                     
universal-argument-num-events
+                                                   0)))
+         (templates (mapcan #'(lambda (table)
+                                (yas--fetch table vec))
+                            (yas--get-snippet-tables))))
+    (if templates
+        (yas--expand-or-prompt-for-template templates)
+      (let ((yas-fallback-behavior 'call-other-command))
+        (yas--fallback)))))
+
+(defun yas--expand-or-prompt-for-template (templates &optional start end)
+  "Expand one of TEMPLATES from START to END.
+
+Prompt the user if TEMPLATES has more than one element, else
+expand immediately. Common gateway for
+`yas-expand-from-trigger-key' and `yas-expand-from-keymap'."
+  (let ((yas--current-template (or (and (rest templates) ;; more than one
+                                       (yas--prompt-for-template (mapcar #'cdr 
templates)))
+                                  (cdar templates))))
+    (when yas--current-template
+      (yas-expand-snippet (yas--template-content yas--current-template)
+                          start
+                          end
+                          (yas--template-expand-env yas--current-template)))))
+
+(defun yas--trigger-key-for-fallback ()
+  ;; When `yas-trigger-key' is <tab> it correctly overrides
+  ;; org-mode's <tab>, for example and searching for fallbacks
+  ;; correctly returns `org-cycle'. However, most other modes bind
+  ;; "TAB" (which is translated from <tab>), and calling
+  ;; (key-binding "TAB") does not place return that command into
+  ;; our command-2 local. So we cheat.
+  ;;
+  (if (string= yas-trigger-key "<tab>")
+      "TAB"
+    yas-trigger-key))
+
+(defun yas--fallback (&optional from-trigger-key-p)
+  "Fallback after expansion has failed.
+
+Common gateway for `yas-expand-from-trigger-key' and
+`yas-expand-from-keymap'."
+  (cond ((eq yas-fallback-behavior 'return-nil)
+         ;; return nil
+         nil)
+        ((eq yas-fallback-behavior 'call-other-command)
+         (let* ((yas-minor-mode nil)
+                (yas--direct-keymaps nil)
+                (yas-trigger-key (yas--trigger-key-for-fallback))
+                (keys-1 (this-command-keys-vector))
+                (keys-2 (and yas-trigger-key
+                             from-trigger-key-p
+                             (stringp yas-trigger-key)
+                             (read-kbd-macro yas-trigger-key)))
+                (command-1 (and keys-1 (key-binding keys-1)))
+                (command-2 (and keys-2 (key-binding keys-2)))
+                ;; An (ugly) safety: prevents infinite recursion of
+                ;; yas-expand* calls.
+                (command (or (and (symbolp command-1)
+                                  (not (string-match "yas-expand" (symbol-name 
command-1)))
+                                  command-1)
+                             (and (symbolp command-2)
+                                  command-2))))
+           (when (and (commandp command)
+                      (not (string-match "yas-expand" (symbol-name command))))
+             (setq this-command command)
+             (call-interactively command))))
+        ((and (listp yas-fallback-behavior)
+              (cdr yas-fallback-behavior)
+              (eq 'apply (car yas-fallback-behavior)))
+         (if (cddr yas-fallback-behavior)
+             (apply (cadr yas-fallback-behavior)
+                    (cddr yas-fallback-behavior))
+           (when (commandp (cadr yas-fallback-behavior))
+             (setq this-command (cadr yas-fallback-behavior))
+             (call-interactively (cadr yas-fallback-behavior)))))
+        (t
+         ;; also return nil if all the other fallbacks have failed
+         nil)))
+
+
+
+;;; Utils for snippet development:
+
+(defun yas--all-templates (tables)
+  "Return all snippet tables applicable for the current buffer.
+
+Honours `yas-choose-tables-first', `yas-choose-keys-first' and
+`yas-buffer-local-condition'"
+  (when yas-choose-tables-first
+    (setq tables (list (yas--prompt-for-table tables))))
+  (mapcar #'cdr
+          (if yas-choose-keys-first
+              (let ((key (yas--prompt-for-keys
+                          (mapcan #'yas--table-all-keys tables))))
+                (when key
+                  (mapcan #'(lambda (table)
+                              (yas--fetch table key))
+                          tables)))
+            (remove-duplicates (mapcan #'yas--table-templates tables)
+                               :test #'equal))))
+
+(defun yas-insert-snippet (&optional no-condition)
+  "Choose a snippet to expand, pop-up a list of choices according
+to `yas--prompt-function'.
+
+With prefix argument NO-CONDITION, bypass filtering of snippets
+by condition."
+  (interactive "P")
+  (setq yas--condition-cache-timestamp (current-time))
+  (let* ((yas-buffer-local-condition (or (and no-condition
+                                              'always)
+                                         yas-buffer-local-condition))
+         (templates (yas--all-templates (yas--get-snippet-tables)))
+         (yas--current-template (and templates
+                                    (or (and (rest templates) ;; more than one 
template for same key
+                                             (yas--prompt-for-template 
templates))
+                                        (car templates))))
+         (where (if (region-active-p)
+                    (cons (region-beginning) (region-end))
+                  (cons (point) (point)))))
+    (if yas--current-template
+        (yas-expand-snippet (yas--template-content yas--current-template)
+                            (car where)
+                            (cdr where)
+                            (yas--template-expand-env yas--current-template))
+      (yas--message 3 "No snippets can be inserted here!"))))
+
+(defun yas-visit-snippet-file ()
+  "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)
+  (let* ((yas-buffer-local-condition 'always)
+         (templates (yas--all-templates (yas--get-snippet-tables)))
+         (yas-prompt-functions '(yas-ido-prompt yas-completing-prompt))
+         (template (and templates
+                        (or (yas--prompt-for-template templates
+                                                     "Choose a snippet 
template to edit: ")
+                            (car templates)))))
+
+    (if template
+        (yas--visit-snippet-file-1 template)
+      (message "No snippets tables active!"))))
+
+(defun yas--visit-snippet-file-1 (template)
+  (let ((file (yas--template-file template)))
+    (cond ((and file (file-readable-p file))
+           (find-file-other-window file)
+           (snippet-mode)
+           (set (make-local-variable 'yas--editing-template) template))
+          (file
+           (message "Original file %s no longer exists!" file))
+          (t
+           (switch-to-buffer (format "*%s*"(yas--template-name template)))
+           (let ((type 'snippet))
+             (when (listp (yas--template-content template))
+               (insert (format "# type: command\n"))
+               (setq type 'command))
+             (insert (format "# key: %s\n" (yas--template-key template)))
+             (insert (format "# name: %s\n" (yas--template-name template)))
+             (when (yas--template-keybinding template)
+               (insert (format "# binding: %s\n" (yas--template-keybinding 
template))))
+             (when (yas--template-expand-env template)
+               (insert (format "# expand-env: %s\n" (yas--template-expand-env 
template))))
+             (when (yas--template-condition template)
+               (insert (format "# condition: %s\n" (yas--template-condition 
template))))
+             (insert "# --\n")
+             (insert (if (eq type 'command)
+                         (pp-to-string (yas--template-content template))
+                       (yas--template-content template))))
+           (snippet-mode)
+           (set (make-local-variable 'yas--editing-template) template)))))
+
+(defun yas--guess-snippet-directories-1 (table)
+  "Guesses possible snippet subdirectories for TABLE."
+  (cons (yas--table-name table)
+        (mapcan #'(lambda (parent)
+                    (yas--guess-snippet-directories-1
+                     parent))
+                (yas--table-parents table))))
+
+(defun yas--guess-snippet-directories (&optional table)
+  "Try to guess suitable directories based on the current active
+tables (or optional TABLE).
+
+Returns a list of elemts (TABLE . DIRS) where TABLE is a
+`yas--table' object and DIRS is a list of all possible directories
+where snippets of table might exist."
+  (let ((main-dir (replace-regexp-in-string
+                   "/+$" ""
+                   (or (first (or (yas-snippet-dirs)
+                                  (setq yas-snippet-dirs 
'("~/.emacs.d/snippets")))))))
+        (tables (or (and table
+                         (list table))
+                    (yas--get-snippet-tables))))
+    ;; HACK! the snippet table created here is actually registered!
+    ;;
+    (unless (or table (gethash major-mode yas--tables))
+      (push (yas--table-get-create major-mode)
+            tables))
+
+    (mapcar #'(lambda (table)
+                (cons table
+                      (mapcar #'(lambda (subdir)
+                                  (concat main-dir "/" subdir))
+                              (yas--guess-snippet-directories-1 table))))
+            tables)))
+
+(defun yas--make-directory-maybe (table-and-dirs &optional main-table-string)
+  "Returns a dir inside  TABLE-AND-DIRS, prompts for creation if none exists."
+  (or (some #'(lambda (dir) (when (file-directory-p dir) dir)) (cdr 
table-and-dirs))
+      (let ((candidate (first (cdr table-and-dirs))))
+        (unless (file-writable-p (file-name-directory candidate))
+          (error (yas--format "%s is not writable." candidate)))
+        (if (y-or-n-p (format "Guessed directory (%s) for%s%s table \"%s\" 
does not exist! Create? "
+                              candidate
+                              (if (gethash (yas--table-mode (car 
table-and-dirs))
+                                           yas--tables)
+                                  ""
+                                " brand new")
+                              (or main-table-string
+                                  "")
+                              (yas--table-name (car table-and-dirs))))
+            (progn
+              (make-directory candidate 'also-make-parents)
+              ;; create the .yas-parents file here...
+              candidate)))))
+
+(defun yas-new-snippet (&optional no-template)
+  "Pops a new buffer for writing a snippet.
+
+Expands a snippet-writing snippet, unless the optional prefix arg
+NO-TEMPLATE is non-nil."
+  (interactive "P")
+  (let ((guessed-directories (yas--guess-snippet-directories)))
+
+    (switch-to-buffer "*new snippet*")
+    (erase-buffer)
+    (kill-all-local-variables)
+    (snippet-mode)
+    (yas-minor-mode 1)
+    (set (make-local-variable 'yas--guessed-modes) (mapcar #'(lambda (d)
+                                                              (yas--table-mode 
(car d)))
+                                                          guessed-directories))
+    (unless no-template (yas-expand-snippet "\
+# -*- mode: snippet -*-
+# name: $1
+# key: ${2:${1:$(replace-regexp-in-string \"\\\\\\\\(\\\\\\\\w+\\\\\\\\).*\" 
\"\\\\\\\\1\" yas-text)}}${3:
+# binding: ${4:direct-keybinding}}${5:
+# expand-env: ((${6:some-var} ${7:some-value}))}${8:
+# type: command}
+# --
+$0"))))
+
+(defun yas--compute-major-mode-and-parents (file)
+  "Given FILE, find the nearest snippet directory for a given
+mode, then return a list (MODE-SYM PARENTS), the mode's symbol and a list
+representing one or more of the mode's parents.
+
+Note that MODE-SYM need not be the symbol of a real major mode,
+neither do the elements of PARENTS."
+  (let* ((file-dir (and file
+                        (directory-file-name (or (some #'(lambda (special)
+                                                           
(locate-dominating-file file special))
+                                                       '(".yas-setup.el"
+                                                         ".yas-make-groups"
+                                                         ".yas-parents"))
+                                                 (directory-file-name 
(file-name-directory file))))))
+         (parents-file-name (concat file-dir "/.yas-parents"))
+         (major-mode-name (and file-dir
+                               (file-name-nondirectory file-dir)))
+         (major-mode-sym (or (and major-mode-name
+                                  (intern major-mode-name))))
+         (parents (when (file-readable-p parents-file-name)
+                         (mapcar #'intern
+                                 (split-string
+                                  (with-temp-buffer
+                                    (insert-file-contents parents-file-name)
+                                    (buffer-substring-no-properties (point-min)
+                                                                    
(point-max))))))))
+    (when major-mode-sym
+      (cons major-mode-sym parents))))
+
+(defvar yas--editing-template nil
+  "Supporting variable for `yas-load-snippet-buffer' and `yas--visit-snippet'")
+
+(defvar yas--current-template nil
+  "Holds the current template being expanded into a snippet.")
+
+(defvar yas--guessed-modes nil
+  "List of guessed modes supporting `yas-load-snippet-buffer'.")
+
+(defun yas--read-table ()
+  "Ask user for a snippet table, help with some guessing."
+  (let ((prompt (if (and (featurep 'ido)
+                         ido-mode)
+                    'ido-completing-read 'completing-read)))
+    (unless yas--guessed-modes
+      (set (make-local-variable 'yas--guessed-modes)
+           (or (yas--compute-major-mode-and-parents buffer-file-name))))
+    (intern
+     (funcall prompt (format "Choose or enter a table (yas guesses %s): "
+                             (if yas--guessed-modes
+                                 (first yas--guessed-modes)
+                               "nothing"))
+              (mapcar #'symbol-name yas--guessed-modes)
+              nil
+              nil
+              nil
+              nil
+              (if (first yas--guessed-modes)
+                  (symbol-name (first yas--guessed-modes)))))))
+
+(defun yas-load-snippet-buffer (table &optional interactive)
+  "Parse and load current buffer's snippet definition into TABLE.
+
+TABLE is a symbol naming a passed to `yas--table-get-create'.
+
+When called interactively, prompt for the table name and
+whether (and where) to save the snippet, then quit the window."
+  (interactive (list (yas--read-table) t))
+  (cond
+   ;;  We have `yas--editing-template', this buffer's content comes from a
+   ;;  template which is already loaded and neatly positioned,...
+   ;;
+   (yas--editing-template
+    (yas-define-snippets-1 (yas--parse-template (yas--template-file 
yas--editing-template))
+                           (yas--template-table yas--editing-template)))
+   ;; Try to use `yas--guessed-modes'. If we don't have that use the
+   ;; value from `yas--compute-major-mode-and-parents'
+   ;;
+   (t
+    (unless yas--guessed-modes
+      (set (make-local-variable 'yas--guessed-modes) (or 
(yas--compute-major-mode-and-parents buffer-file-name))))
+    (let* ((table (yas--table-get-create table)))
+      (set (make-local-variable 'yas--editing-template)
+           (yas-define-snippets-1 (yas--parse-template buffer-file-name)
+                                  table)))))
+
+  (when (and interactive
+             (or
+              ;; Only offer to save this if it looks like a library or new
+              ;; snippet (loaded from elisp, from a dir in `yas-snippet-dirs'
+              ;; which is not the first, or from an unwritable file)
+              ;;
+              (not (yas--template-file yas--editing-template))
+              (not (file-writable-p (yas--template-file 
yas--editing-template)))
+              (and (listp yas-snippet-dirs)
+                   (second yas-snippet-dirs)
+                   (not (string-match (expand-file-name (first 
yas-snippet-dirs))
+                                      (yas--template-file 
yas--editing-template)))))
+             (y-or-n-p (yas--format "Looks like a library or new snippet. Save 
to new file? ")))
+    (let* ((option (first (yas--guess-snippet-directories (yas--template-table 
yas--editing-template))))
+           (chosen (and option
+                        (yas--make-directory-maybe option))))
+      (when chosen
+        (let ((default-file-name (or (and (yas--template-file 
yas--editing-template)
+                                          (file-name-nondirectory 
(yas--template-file yas--editing-template)))
+                                     (yas--template-name 
yas--editing-template))))
+          (write-file (concat chosen "/"
+                              (read-from-minibuffer (format "File name to 
create in %s? " chosen)
+                                                    default-file-name)))
+          (setf (yas--template-file yas--editing-template) 
buffer-file-name)))))
+  (when interactive
+    (quit-window interactive)
+    (yas--message 3 "Snippet \"%s\" loaded for %s."
+                  (yas--template-name yas--editing-template)
+                  (yas--table-name (yas--template-table 
yas--editing-template)))))
+
+
+(defun yas-tryout-snippet (&optional debug)
+  "Test current buffers's snippet template in other buffer."
+  (interactive "P")
+  (let* ((major-mode-and-parent (yas--compute-major-mode-and-parents 
buffer-file-name))
+         (parsed (yas--parse-template))
+         (test-mode (or (and (car major-mode-and-parent)
+                             (fboundp (car major-mode-and-parent))
+                             (car major-mode-and-parent))
+                        (first yas--guessed-modes)
+                        (intern (read-from-minibuffer (yas--format "Please 
input a mode: ")))))
+         (yas--current-template
+          (and parsed
+               (fboundp test-mode)
+               (yas--populate-template (yas--make-blank-template)
+                                      :table       nil ;; no tables for 
ephemeral snippets
+                                      :key         (first parsed)
+                                      :content     (second parsed)
+                                      :name        (third parsed)
+                                      :expand-env  (sixth parsed)))))
+    (cond (yas--current-template
+           (let ((buffer-name (format "*testing snippet: %s*" 
(yas--template-name yas--current-template))))
+             (kill-buffer (get-buffer-create buffer-name))
+             (switch-to-buffer (get-buffer-create buffer-name))
+             (setq buffer-undo-list nil)
+             (condition-case nil (funcall test-mode) (error nil))
+            (yas-minor-mode 1)
+             (setq buffer-read-only nil)
+             (yas-expand-snippet (yas--template-content yas--current-template)
+                                 (point-min)
+                                 (point-max)
+                                 (yas--template-expand-env 
yas--current-template))
+             (when (and debug
+                        (require 'yasnippet-debug nil t))
+               (add-hook 'post-command-hook 'yas-debug-snippet-vars nil t))))
+          (t
+           (yas--message 3 "Cannot test snippet for unknown major mode")))))
+
+(defun yas--template-fine-group (template)
+  (car (last (or (yas--template-group template)
+                 (yas--template-perm-group template)))))
+
+(defun yas-describe-tables (&optional choose)
+  "Display snippets for each table."
+  (interactive "P")
+  (let* ((by-name-hash (and choose
+                            (y-or-n-p "Show by namehash? ")))
+         (buffer (get-buffer-create "*YASnippet tables*"))
+         (active-tables (yas--get-snippet-tables))
+         (remain-tables (let ((all))
+                          (maphash #'(lambda (k v)
+                                       (unless (find v active-tables)
+                                         (push v all)))
+                                   yas--tables)
+                          all))
+         (table-lists (list active-tables remain-tables))
+         (original-buffer (current-buffer))
+         (continue t)
+         (yas--condition-cache-timestamp (current-time)))
+    (with-current-buffer buffer
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (cond ((not by-name-hash)
+             (insert "YASnippet tables: \n")
+             (while (and table-lists
+                         continue)
+               (dolist (table (car table-lists))
+                 (yas--describe-pretty-table table original-buffer))
+               (setq table-lists (cdr table-lists))
+               (when table-lists
+                 (yas--create-snippet-xrefs)
+                 (display-buffer buffer)
+                 (setq continue (and choose (y-or-n-p "Show also non-active 
tables? ")))))
+             (yas--create-snippet-xrefs)
+             (help-mode)
+             (goto-char 1))
+            (t
+             (insert "\n\nYASnippet tables by NAMEHASH: \n")
+             (dolist (table (append active-tables remain-tables))
+               (insert (format "\nSnippet table `%s':\n\n" (yas--table-name 
table)))
+               (let ((keys))
+                 (maphash #'(lambda (k v)
+                              (push k keys))
+                          (yas--table-hash table))
+                 (dolist (key keys)
+                   (insert (format "   key %s maps snippets: %s\n" key
+                                   (let ((names))
+                                     (maphash #'(lambda (k v)
+                                                  (push k names))
+                                              (gethash key (yas--table-hash 
table)))
+                                     names))))))))
+      (goto-char 1)
+      (setq buffer-read-only t))
+    (display-buffer buffer)))
+
+(defun yas--describe-pretty-table (table &optional original-buffer)
+  (insert (format "\nSnippet table `%s'"
+                  (yas--table-name table)))
+  (if (yas--table-parents table)
+      (insert (format " parents: %s\n"
+                      (mapcar #'yas--table-name
+                              (yas--table-parents table))))
+    (insert "\n"))
+  (insert (make-string 100 ?-) "\n")
+  (insert "group                   state name                                  
  key             binding\n")
+  (let ((groups-hash (make-hash-table :test #'equal)))
+    (maphash #'(lambda (k v)
+                 (let ((group (or (yas--template-fine-group v)
+                                  "(top level)")))
+                   (when (yas--template-name v)
+                     (puthash group
+                              (cons v (gethash group groups-hash))
+                              groups-hash))))
+             (yas--table-uuidhash table))
+    (maphash
+     #'(lambda (group templates)
+         (setq group (truncate-string-to-width group 25 0 ?  "..."))
+         (insert (make-string 100 ?-) "\n")
+         (dolist (p templates)
+           (let ((name (truncate-string-to-width (propertize (format 
"\\\\snippet `%s'" (yas--template-name p))
+                                                             'yasnippet p)
+                                                 50 0 ? "..."))
+                 (group (prog1 group
+                          (setq group (make-string (length group) ? ))))
+                 (condition-string (let ((condition (yas--template-condition 
p)))
+                                     (if (and condition
+                                              original-buffer)
+                                         (with-current-buffer original-buffer
+                                           (if (yas--eval-condition condition)
+                                               "(y)"
+                                             "(s)"))
+                                       "(a)"))))
+             (insert group " ")
+             (insert condition-string " ")
+             (insert name
+                     (if (string-match "\\.\\.\\.$" name)
+                         "'"
+                       " ")
+                     " ")
+             (insert (truncate-string-to-width (or (yas--template-key p) "")
+                                               15 0 ?  "...") " ")
+             (insert (truncate-string-to-width (key-description 
(yas--template-keybinding p))
+                                               15 0 ?  "...") " ")
+             (insert "\n"))))
+     groups-hash)))
+
+
+
+;;; User convenience functions, for using in snippet definitions
+
+(defvar yas-modified-p nil
+  "Non-nil if field has been modified by user or transformation.")
+
+(defvar yas-moving-away-p nil
+  "Non-nil if user is about to exit field.")
+
+(defvar yas-text nil
+  "Contains current field text.")
+
+(defun yas-substr (str pattern &optional subexp)
+  "Search PATTERN in STR and return SUBEXPth match.
+
+If found, the content of subexp group SUBEXP (default 0) is
+  returned, or else the original STR will be returned."
+  (let ((grp (or subexp 0)))
+    (save-match-data
+      (if (string-match pattern str)
+          (match-string-no-properties grp str)
+        str))))
+
+(defun yas-choose-value (&rest possibilities)
+  "Prompt for a string in POSSIBILITIES and return it.
+
+The last element of POSSIBILITIES may be a list of strings."
+  (unless (or yas-moving-away-p
+              yas-modified-p)
+    (setq possibilities (nreverse possibilities))
+    (setq possibilities (if (listp (car possibilities))
+                            (append (reverse (car possibilities)) (rest 
possibilities))
+                                   possibilities))
+    (some #'(lambda (fn)
+              (funcall fn "Choose: " possibilities))
+          yas-prompt-functions)))
+
+(defun yas-key-to-value (alist)
+  "Prompt for a string in the list POSSIBILITIES and return it."
+  (unless (or yas-moving-away-p
+              yas-modified-p)
+    (let ((key (read-key-sequence "")))
+      (when (stringp key)
+        (or (cdr (find key alist :key #'car :test #'string=))
+            key)))))
+
+(defun yas-throw (text)
+  "Throw a yas--exception with TEXT as the reason."
+  (throw 'yas--exception (cons 'yas--exception text)))
+
+(defun yas-verify-value (possibilities)
+  "Verify that the current field value is in POSSIBILITIES
+
+Otherwise throw exception."
+  (when (and yas-moving-away-p (notany #'(lambda (pos) (string= pos yas-text)) 
possibilities))
+    (yas-throw (yas--format "Field only allows %s" possibilities))))
+
+(defun yas-field-value (number)
+  "Get the string for field with NUMBER.
+
+Use this in primary and mirror transformations to tget."
+  (let* ((snippet (car (yas--snippets-at-point)))
+         (field (and snippet
+                     (yas--snippet-find-field snippet number))))
+    (when field
+      (yas--field-text-for-display field))))
+
+(defun yas-text ()
+  "Return `yas-text' if that exists and is non-empty, else nil."
+  (if (and yas-text
+           (not (string= "" yas-text)))
+      yas-text))
+
+(defun yas-selected-text ()
+  "Return `yas-selected-text' if that exists and is non-empty, else nil."
+  (if (and yas-selected-text
+           (not (string= "" yas-selected-text)))
+      yas-selected-text))
+
+(defun yas--get-field-once (number &optional transform-fn)
+  (unless yas-modified-p
+    (if transform-fn
+        (funcall transform-fn (yas-field-value number))
+      (yas-field-value number))))
+
+(defun yas-default-from-field (number)
+  (unless yas-modified-p
+    (yas-field-value number)))
+
+(defun yas-inside-string ()
+  (equal 'font-lock-string-face (get-char-property (1- (point)) 'face)))
+
+(defun yas-unimplemented (&optional missing-feature)
+  (if yas--current-template
+      (if (y-or-n-p (format "This snippet is unimplemented (missing %s) Visit 
the snippet definition? "
+                            (or missing-feature
+                                "something")))
+          (yas--visit-snippet-file-1 yas--current-template))
+    (message "No implementation. Missing %s" (or missing-feature 
"something"))))
+
+
+;;; Snippet expansion and field management
+
+(defvar yas--active-field-overlay nil
+  "Overlays the currently active field.")
+
+(defvar yas--field-protection-overlays nil
+  "Two overlays protect the current active field ")
+
+(defconst yas--prefix nil
+  "A prefix argument for expansion direct from keybindings")
+
+(defvar yas-selected-text nil
+  "The selected region deleted on the last snippet expansion.")
+
+(defvar yas--start-column nil
+  "The column where the snippet expansion started.")
+
+(make-variable-buffer-local 'yas--active-field-overlay)
+(make-variable-buffer-local 'yas--field-protection-overlays)
+(put 'yas--active-field-overlay 'permanent-local t)
+(put 'yas--field-protection-overlays 'permanent-local t)
+
+(defstruct (yas--snippet (:constructor yas--make-snippet ()))
+  "A snippet.
+
+..."
+  (fields '())
+  (exit nil)
+  (id (yas--snippet-next-id) :read-only t)
+  (control-overlay nil)
+  active-field
+  ;; stacked expansion: the `previous-active-field' slot saves the
+  ;; active field where the child expansion took place
+  previous-active-field
+  force-exit)
+
+(defstruct (yas--field (:constructor yas--make-field (number start end 
parent-field)))
+  "A field."
+  number
+  start end
+  parent-field
+  (mirrors '())
+  (transform nil)
+  (modified-p nil)
+  next)
+
+(defstruct (yas--mirror (:constructor yas--make-mirror (start end transform)))
+  "A mirror."
+  start end
+  (transform nil)
+  parent-field
+  next)
+
+(defstruct (yas--exit (:constructor yas--make-exit (marker)))
+  marker
+  next)
+
+(defun yas--apply-transform (field-or-mirror field &optional empty-on-nil-p)
+  "Calculate transformed string for FIELD-OR-MIRROR from FIELD.
+
+If there is no transform for ht field, return nil.
+
+If there is a transform but it returns nil, return the empty
+string iff EMPTY-ON-NIL-P is true."
+  (let* ((yas-text (yas--field-text-for-display field))
+         (text yas-text)
+         (yas-modified-p (yas--field-modified-p field))
+         (yas-moving-away-p nil)
+         (transform (if (yas--mirror-p field-or-mirror)
+                        (yas--mirror-transform field-or-mirror)
+                      (yas--field-transform field-or-mirror)))
+         (start-point (if (yas--mirror-p field-or-mirror)
+                          (yas--mirror-start field-or-mirror)
+                        (yas--field-start field-or-mirror)))
+         (transformed (and transform
+                           (save-excursion
+                             (goto-char start-point)
+                             (let ((ret (yas--eval-lisp transform)))
+                               (or ret (and empty-on-nil-p "")))))))
+    transformed))
+
+(defsubst yas--replace-all (from to &optional text)
+  "Replace all occurance from FROM to TO.
+
+With optional string TEXT do it in that string."
+  (if text
+      (replace-regexp-in-string (regexp-quote from) to text t t)
+    (goto-char (point-min))
+    (while (search-forward from nil t)
+      (replace-match to t t text))))
+
+(defun yas--snippet-find-field (snippet number)
+  (find-if #'(lambda (field)
+               (eq number (yas--field-number field)))
+           (yas--snippet-fields snippet)))
+
+(defun yas--snippet-sort-fields (snippet)
+  "Sort the fields of SNIPPET in navigation order."
+  (setf (yas--snippet-fields snippet)
+        (sort (yas--snippet-fields snippet)
+              #'yas--snippet-field-compare)))
+
+(defun yas--snippet-field-compare (field1 field2)
+  "Compare two fields. The field with a number is sorted first.
+If they both have a number, compare through the number. If neither
+have, compare through the field's start point"
+  (let ((n1 (yas--field-number field1))
+        (n2 (yas--field-number field2)))
+    (if n1
+        (if n2
+            (or (zerop n2) (and (not (zerop n1))
+                                (< n1 n2)))
+          (not (zerop n1)))
+      (if n2
+          (zerop n2)
+        (< (yas--field-start field1)
+           (yas--field-start field2))))))
+
+(defun yas--field-probably-deleted-p (snippet field)
+  "Guess if SNIPPET's FIELD should be skipped."
+  (and
+   ;; field must be zero lentgh
+   ;;
+   (zerop (- (yas--field-start field) (yas--field-end field)))
+   ;; skip if:
+   (or
+    ;;  1) is a nested field and it's been modified
+    ;;
+    (and (yas--field-parent-field field)
+         (yas--field-modified-p field))
+    ;;  2) ends just before the snippet end
+    ;;
+    (and (eq field (car (last (yas--snippet-fields snippet))))
+         (= (yas--field-start field) (overlay-end 
(yas--snippet-control-overlay snippet)))))
+   ;; the field numbered 0, just before the exit marker, should
+   ;; never be skipped
+   ;;
+   (not (zerop (yas--field-number field)))))
+
+(defun yas--snippets-at-point (&optional all-snippets)
+  "Return a sorted list of snippets at point, most recently
+inserted first."
+  (sort
+   (remove nil (remove-duplicates (mapcar #'(lambda (ov)
+                                              (overlay-get ov 'yas--snippet))
+                                          (if all-snippets
+                                              (overlays-in (point-min) 
(point-max))
+                                            (nconc (overlays-at (point)) 
(overlays-at (1- (point))))))))
+   #'(lambda (s1 s2)
+       (<= (yas--snippet-id s2) (yas--snippet-id s1)))))
+
+(defun yas-next-field-or-maybe-expand ()
+  "Try to expand a snippet at a key before point, otherwise
+delegate to `yas-next-field'."
+  (interactive)
+  (if yas-triggers-in-field
+      (let ((yas-fallback-behavior 'return-nil)
+            (active-field (overlay-get yas--active-field-overlay 'yas--field)))
+        (when active-field
+          (unless (yas-expand-from-trigger-key active-field)
+            (yas-next-field))))
+    (yas-next-field)))
+
+(defun yas-next-field (&optional arg)
+  "Navigate to next field.  If there's none, exit the snippet."
+  (interactive)
+  (let* ((arg (or arg
+                  1))
+         (snippet (first (yas--snippets-at-point)))
+         (active-field (overlay-get yas--active-field-overlay 'yas--field))
+         (live-fields (remove-if #'(lambda (field)
+                                     (and (not (eq field active-field))
+                                          (yas--field-probably-deleted-p 
snippet field)))
+                                 (yas--snippet-fields snippet)))
+         (active-field-pos (position active-field live-fields))
+         (target-pos (and active-field-pos (+ arg active-field-pos)))
+         (target-field (and target-pos (nth target-pos live-fields))))
+    ;; First check if we're moving out of a field with a transform
+    ;;
+    (when (and active-field
+               (yas--field-transform active-field))
+      (let* ((yas-moving-away-p t)
+             (yas-text (yas--field-text-for-display active-field))
+             (text yas-text)
+             (yas-modified-p (yas--field-modified-p active-field)))
+        ;; primary field transform: exit call to field-transform
+        (yas--eval-lisp (yas--field-transform active-field))))
+    ;; Now actually move...
+    (cond ((and target-pos (>= target-pos (length live-fields)))
+           (yas-exit-snippet snippet))
+          (target-field
+           (yas--move-to-field snippet target-field))
+          (t
+           nil))))
+
+(defun yas--place-overlays (snippet field)
+  "Correctly place overlays for SNIPPET's FIELD"
+  (yas--make-move-field-protection-overlays snippet field)
+  (yas--make-move-active-field-overlay snippet field))
+
+(defun yas--move-to-field (snippet field)
+  "Update SNIPPET to move to field FIELD.
+
+Also create some protection overlays"
+  (goto-char (yas--field-start field))
+  (yas--place-overlays snippet field)
+  (overlay-put yas--active-field-overlay 'yas--field field)
+  (let ((number (yas--field-number field)))
+    ;; check for the special ${0: ...} field
+    (if (and number (zerop number))
+        (progn
+          (set-mark (yas--field-end field))
+          (setf (yas--snippet-force-exit snippet)
+                (or (yas--field-transform field)
+                    t)))
+      ;; make this field active
+      (setf (yas--snippet-active-field snippet) field)
+      ;; primary field transform: first call to snippet transform
+      (unless (yas--field-modified-p field)
+        (if (yas--field-update-display field snippet)
+            (yas--update-mirrors snippet)
+          (setf (yas--field-modified-p field) nil))))))
+
+(defun yas-prev-field ()
+  "Navigate to prev field.  If there's none, exit the snippet."
+  (interactive)
+  (yas-next-field -1))
+
+(defun yas-abort-snippet (&optional snippet)
+  (interactive)
+  (let ((snippet (or snippet
+                     (car (yas--snippets-at-point)))))
+    (when snippet
+      (setf (yas--snippet-force-exit snippet) t))))
+
+(defun yas-exit-snippet (snippet)
+  "Goto exit-marker of SNIPPET."
+  (interactive (list (first (yas--snippets-at-point))))
+  (when snippet
+    (setf (yas--snippet-force-exit snippet) t)
+    (goto-char (if (yas--snippet-exit snippet)
+                   (yas--exit-marker (yas--snippet-exit snippet))
+                 (overlay-end (yas--snippet-control-overlay snippet))))))
+
+(defun yas-exit-all-snippets ()
+  "Exit all snippets."
+  (interactive)
+  (mapc #'(lambda (snippet)
+            (yas-exit-snippet snippet)
+            (yas--check-commit-snippet))
+        (yas--snippets-at-point 'all-snippets)))
+
+
+;;; Some low level snippet-routines:
+
+(defmacro yas--inhibit-overlay-hooks (&rest body)
+  "Run BODY with `yas--inhibit-overlay-hooks' set to t."
+  (declare (indent 0))
+  `(let ((yas--inhibit-overlay-hooks t))
+     (progn ,@body)))
+
+(defvar yas-snippet-beg nil "Beginning position of the last snippet commited.")
+(defvar yas-snippet-end nil "End position of the last snippet commited.")
+
+(defun yas--commit-snippet (snippet)
+  "Commit SNIPPET, but leave point as it is.  This renders the
+snippet as ordinary text."
+
+  (let ((control-overlay (yas--snippet-control-overlay snippet)))
+    ;;
+    ;; Save the end of the moribund snippet in case we need to revive it
+    ;; its original expansion.
+    ;;
+    (when (and control-overlay
+               (overlay-buffer control-overlay))
+      (setq yas-snippet-beg (overlay-start control-overlay))
+      (setq yas-snippet-end (overlay-end control-overlay))
+      (delete-overlay control-overlay))
+
+    (yas--inhibit-overlay-hooks
+      (when yas--active-field-overlay
+        (delete-overlay yas--active-field-overlay))
+      (when yas--field-protection-overlays
+        (mapc #'delete-overlay yas--field-protection-overlays)))
+
+    ;; stacked expansion: if the original expansion took place from a
+    ;; field, make sure we advance it here at least to
+    ;; `yas-snippet-end'...
+    ;;
+    (let ((previous-field (yas--snippet-previous-active-field snippet)))
+      (when (and yas-snippet-end previous-field)
+        (yas--advance-end-maybe previous-field yas-snippet-end)))
+
+    ;; Convert all markers to points,
+    ;;
+    (yas--markers-to-points snippet)
+
+    ;; Take care of snippet revival
+    ;;
+    (if yas-snippet-revival
+        (push `(apply yas--snippet-revive ,yas-snippet-beg ,yas-snippet-end 
,snippet)
+              buffer-undo-list)
+      ;; Dismember the snippet... this is useful if we get called
+      ;; again from `yas--take-care-of-redo'....
+      (setf (yas--snippet-fields snippet) nil)))
+
+  (yas--message 3 "Snippet %s exited." (yas--snippet-id snippet)))
+
+(defun yas--safely-run-hooks (hook-var)
+  (condition-case error
+      (run-hooks hook-var)
+    (error
+     (yas--message 3 "%s error: %s" hook-var (error-message-string error)))))
+
+
+(defun yas--check-commit-snippet ()
+  "Checks if point exited the currently active field of the
+snippet, if so cleans up the whole snippet up."
+  (let* ((snippets (yas--snippets-at-point 'all-snippets))
+         (snippets-left snippets)
+         (snippet-exit-transform))
+    (dolist (snippet snippets)
+      (let ((active-field (yas--snippet-active-field snippet)))
+        (setq snippet-exit-transform (yas--snippet-force-exit snippet))
+        (cond ((or snippet-exit-transform
+                   (not (and active-field (yas--field-contains-point-p 
active-field))))
+               (setq snippets-left (delete snippet snippets-left))
+               (setf (yas--snippet-force-exit snippet) nil)
+               (yas--commit-snippet snippet))
+              ((and active-field
+                    (or (not yas--active-field-overlay)
+                        (not (overlay-buffer yas--active-field-overlay))))
+               ;;
+               ;; stacked expansion: this case is mainly for recent
+               ;; snippet exits that place us back int the field of
+               ;; another snippet
+               ;;
+               (save-excursion
+                 (yas--move-to-field snippet active-field)
+                 (yas--update-mirrors snippet)))
+              (t
+               nil))))
+    (unless (or (null snippets) snippets-left)
+      (if snippet-exit-transform
+          (yas--eval-lisp-no-saves snippet-exit-transform))
+      (yas--safely-run-hooks 'yas-after-exit-snippet-hook))))
+
+;; Apropos markers-to-points:
+;;
+;; This was found useful for performance reasons, so that an
+;; excessive number of live markers aren't kept around in the
+;; `buffer-undo-list'. However, in `markers-to-points', the
+;; set-to-nil markers can't simply be discarded and replaced with
+;; fresh ones in `points-to-markers'. The original marker that was
+;; just set to nil has to be reused.
+;;
+;; This shouldn't bring horrible problems with undo/redo, but it
+;; you never know
+;;
+(defun yas--markers-to-points (snippet)
+  "Convert all markers in SNIPPET to a cons (POINT . MARKER)
+where POINT is the original position of the marker and MARKER is
+the original marker object with the position set to nil."
+  (dolist (field (yas--snippet-fields snippet))
+    (let ((start (marker-position (yas--field-start field)))
+          (end (marker-position (yas--field-end field))))
+      (set-marker (yas--field-start field) nil)
+      (set-marker (yas--field-end field) nil)
+      (setf (yas--field-start field) (cons start (yas--field-start field)))
+      (setf (yas--field-end field) (cons end (yas--field-end field))))
+    (dolist (mirror (yas--field-mirrors field))
+      (let ((start (marker-position (yas--mirror-start mirror)))
+            (end (marker-position (yas--mirror-end mirror))))
+        (set-marker (yas--mirror-start mirror) nil)
+        (set-marker (yas--mirror-end mirror) nil)
+        (setf (yas--mirror-start mirror) (cons start (yas--mirror-start 
mirror)))
+        (setf (yas--mirror-end mirror) (cons end (yas--mirror-end mirror))))))
+  (let ((snippet-exit (yas--snippet-exit snippet)))
+    (when snippet-exit
+      (let ((exit (marker-position (yas--exit-marker snippet-exit))))
+        (set-marker (yas--exit-marker snippet-exit) nil)
+        (setf (yas--exit-marker snippet-exit) (cons exit (yas--exit-marker 
snippet-exit)))))))
+
+(defun yas--points-to-markers (snippet)
+  "Convert all cons (POINT . MARKER) in SNIPPET to markers. This
+is done by setting MARKER to POINT with `set-marker'."
+  (dolist (field (yas--snippet-fields snippet))
+    (setf (yas--field-start field) (set-marker (cdr (yas--field-start field))
+                                              (car (yas--field-start field))))
+    (setf (yas--field-end field) (set-marker (cdr (yas--field-end field))
+                                            (car (yas--field-end field))))
+    (dolist (mirror (yas--field-mirrors field))
+      (setf (yas--mirror-start mirror) (set-marker (cdr (yas--mirror-start 
mirror))
+                                                  (car (yas--mirror-start 
mirror))))
+      (setf (yas--mirror-end mirror) (set-marker (cdr (yas--mirror-end mirror))
+                                                (car (yas--mirror-end 
mirror))))))
+  (let ((snippet-exit (yas--snippet-exit snippet)))
+    (when snippet-exit
+      (setf (yas--exit-marker snippet-exit) (set-marker (cdr (yas--exit-marker 
snippet-exit))
+                                                       (car (yas--exit-marker 
snippet-exit)))))))
+
+(defun yas--field-contains-point-p (field &optional point)
+  (let ((point (or point
+                   (point))))
+    (and (>= point (yas--field-start field))
+         (<= point (yas--field-end field)))))
+
+(defun yas--field-text-for-display (field)
+  "Return the propertized display text for field FIELD.  "
+  (buffer-substring (yas--field-start field) (yas--field-end field)))
+
+(defun yas--undo-in-progress ()
+  "True if some kind of undo is in progress"
+  (or undo-in-progress
+      (eq this-command 'undo)
+      (eq this-command 'redo)))
+
+(defun yas--make-control-overlay (snippet start end)
+  "Creates the control overlay that surrounds the snippet and
+holds the keymap."
+  (let ((overlay (make-overlay start
+                               end
+                               nil
+                               nil
+                               t)))
+    (overlay-put overlay 'keymap yas-keymap)
+    (overlay-put overlay 'priority 100)
+    (overlay-put overlay 'yas--snippet snippet)
+    overlay))
+
+(defun yas-skip-and-clear-or-delete-char (&optional field)
+  "Clears unmodified field if at field start, skips to next tab.
+
+Otherwise deletes a character normally by calling `delete-char'."
+  (interactive)
+  (let ((field (or field
+                   (and yas--active-field-overlay
+                        (overlay-buffer yas--active-field-overlay)
+                        (overlay-get yas--active-field-overlay 'yas--field)))))
+    (cond ((and field
+                (not (yas--field-modified-p field))
+                (eq (point) (marker-position (yas--field-start field))))
+           (yas--skip-and-clear field)
+           (yas-next-field 1))
+          (t
+           (call-interactively 'delete-char)))))
+
+(defun yas--skip-and-clear (field)
+  "Deletes the region of FIELD and sets it modified state to t"
+  ;; Just before skipping-and-clearing the field, mark its children
+  ;; fields as modified, too. If the childen have mirrors-in-fields
+  ;; this prevents them from updating erroneously (we're skipping and
+  ;; deleting!).
+  ;;
+  (yas--mark-this-and-children-modified field)
+  (delete-region (yas--field-start field) (yas--field-end field)))
+
+(defun yas--mark-this-and-children-modified (field)
+  (setf (yas--field-modified-p field) t)
+  (let ((fom (yas--field-next field)))
+    (while (and fom
+                (yas--fom-parent-field fom))
+      (when (and (eq (yas--fom-parent-field fom) field)
+                 (yas--field-p fom))
+        (yas--mark-this-and-children-modified fom))
+      (setq fom (yas--fom-next fom)))))
+
+(defun yas--make-move-active-field-overlay (snippet field)
+  "Place the active field overlay in SNIPPET's FIELD.
+
+Move the overlay, or create it if it does not exit."
+  (if (and yas--active-field-overlay
+           (overlay-buffer yas--active-field-overlay))
+      (move-overlay yas--active-field-overlay
+                    (yas--field-start field)
+                    (yas--field-end field))
+    (setq yas--active-field-overlay
+          (make-overlay (yas--field-start field)
+                        (yas--field-end field)
+                        nil nil t))
+    (overlay-put yas--active-field-overlay 'priority 100)
+    (overlay-put yas--active-field-overlay 'face 'yas-field-highlight-face)
+    (overlay-put yas--active-field-overlay 'yas--snippet snippet)
+    (overlay-put yas--active-field-overlay 'modification-hooks 
'(yas--on-field-overlay-modification))
+    (overlay-put yas--active-field-overlay 'insert-in-front-hooks
+                 '(yas--on-field-overlay-modification))
+    (overlay-put yas--active-field-overlay 'insert-behind-hooks
+                 '(yas--on-field-overlay-modification))))
+
+(defvar yas--inhibit-overlay-hooks nil
+  "Bind this temporarity to non-nil to prevent running 
`yas--on-*-modification'.")
+
+(defun yas--on-field-overlay-modification (overlay after? beg end &optional 
length)
+  "Clears the field and updates mirrors, conditionally.
+
+Only clears the field if it hasn't been modified and it point it
+at field start. This hook doesn't do anything if an undo is in
+progress."
+  (unless (or yas--inhibit-overlay-hooks
+              (yas--undo-in-progress))
+    (let* ((field (overlay-get overlay 'yas--field))
+           (number (and field (yas--field-number field)))
+           (snippet (overlay-get yas--active-field-overlay 'yas--snippet)))
+      (cond (after?
+             (yas--advance-end-maybe field (overlay-end overlay))
+             (save-excursion
+               (yas--field-update-display field snippet))
+             (yas--update-mirrors snippet))
+            (field
+             (when (and (not after?)
+                        (not (yas--field-modified-p field))
+                        (eq (point) (if (markerp (yas--field-start field))
+                                        (marker-position (yas--field-start 
field))
+                                      (yas--field-start field))))
+               (yas--skip-and-clear field))
+             (setf (yas--field-modified-p field) t))))))
+
+;;; Apropos protection overlays:
+;;
+;; These exist for nasty users who will try to delete parts of the
+;; snippet outside the active field. Actual protection happens in
+;; `yas--on-protection-overlay-modification'.
+;;
+;; Currently this signals an error which inhibits the command. For
+;; commands that move point (like `kill-line'), point is restored in
+;; the `yas--post-command-handler' using a global
+;; `yas--protection-violation' variable.
+;;
+;; Alternatively, I've experimented with an implementation that
+;; commits the snippet before actually calling `this-command'
+;; interactively, and then signals an eror, which is ignored. but
+;; blocks all other million modification hooks. This presented some
+;; problems with stacked expansion.
+;;
+(defun yas--make-move-field-protection-overlays (snippet field)
+  "Place protection overlays surrounding SNIPPET's FIELD.
+
+Move the overlays, or create them if they do not exit."
+  (let ((start (yas--field-start field))
+        (end (yas--field-end field)))
+    ;; First check if the (1+ end) is contained in the buffer,
+    ;; otherwise we'll have to do a bit of cheating and silently
+    ;; insert a newline. the `(1+ (buffer-size))' should prevent this
+    ;; when using stacked expansion
+    ;;
+    (when (< (buffer-size) end)
+      (save-excursion
+        (yas--inhibit-overlay-hooks
+          (goto-char (point-max))
+          (newline))))
+    ;; go on to normal overlay creation/moving
+    ;;
+    (cond ((and yas--field-protection-overlays
+                (every #'overlay-buffer yas--field-protection-overlays))
+           (move-overlay (first yas--field-protection-overlays) (1- start) 
start)
+           (move-overlay (second yas--field-protection-overlays) end (1+ end)))
+          (t
+           (setq yas--field-protection-overlays
+                 (list (make-overlay (1- start) start nil t nil)
+                       (make-overlay end (1+ end) nil t nil)))
+           (dolist (ov yas--field-protection-overlays)
+             (overlay-put ov 'face 'yas--field-debug-face)
+             (overlay-put ov 'yas--snippet snippet)
+             ;; (overlay-put ov 'evaporate t)
+             (overlay-put ov 'modification-hooks 
'(yas--on-protection-overlay-modification)))))))
+
+(defvar yas--protection-violation nil
+  "When non-nil, signals attempts to erronesly exit or modify the snippet.
+
+Functions in the `post-command-hook', for example
+`yas--post-command-handler' can check it and reset its value to
+nil. The variables value is the point where the violation
+originated")
+
+(defun yas--on-protection-overlay-modification (overlay after? beg end 
&optional length)
+  "Signals a snippet violation, then issues error.
+
+The error should be ignored in `debug-ignored-errors'"
+  (unless yas--inhibit-overlay-hooks
+    (cond ((not (or after?
+                    (yas--undo-in-progress)))
+           (setq yas--protection-violation (point))
+           (error "Exit the snippet first!")))))
+
+(add-to-list 'debug-ignored-errors "^Exit the snippet first!$")
+
+
+;; Snippet expansion and "stacked" expansion:
+;;
+;; Stacked expansion is when you try to expand a snippet when already
+;; inside a snippet expansion.
+;;
+;; The parent snippet does not run its fields modification hooks
+;; (`yas--on-field-overlay-modification' and
+;; `yas--on-protection-overlay-modification') while the child snippet
+;; is active. This means, among other things, that the mirrors of the
+;; parent snippet are not updated, this only happening when one exits
+;; the child snippet.
+;;
+;; Unfortunately, this also puts some ugly (and not fully-tested)
+;; bits of code in `yas-expand-snippet' and
+;; `yas--commit-snippet'. I've tried to mark them with "stacked
+;; expansion:".
+;;
+;; This was thought to be safer in in an undo/redo perpective, but
+;; maybe the correct implementation is to make the globals
+;; `yas--active-field-overlay' and `yas--field-protection-overlays' be
+;; snippet-local and be active even while the child snippet is
+;; running. This would mean a lot of overlay modification hooks
+;; running, but if managed correctly (including overlay priorities)
+;; they should account for all situations...
+;;
+(defun yas-expand-snippet (content &optional start end expand-env)
+  "Expand snippet CONTENT at current point.
+
+Text between START and END will be deleted before inserting
+template. EXPAND-ENV is are let-style variable to value bindings
+considered when expanding the snippet."
+  (run-hooks 'yas-before-expand-snippet-hook)
+
+  ;;
+  (let* ((yas-selected-text (or yas-selected-text
+                                (and (region-active-p)
+                                     (buffer-substring-no-properties 
(region-beginning)
+                                                                     
(region-end)))))
+         (start (or start
+                    (and (region-active-p)
+                         (region-beginning))
+                    (point)))
+         (end (or end
+                  (and (region-active-p)
+                       (region-end))
+                  (point)))
+         (to-delete (and start
+                         end
+                         (buffer-substring-no-properties start end)))
+         snippet)
+    (goto-char start)
+    (setq yas--indent-original-column (current-column))
+    ;; Delete the region to delete, this *does* get undo-recorded.
+    ;;
+    (when (and to-delete
+               (> end start))
+      (delete-region start end))
+
+    (cond ((listp content)
+           ;; x) This is a snippet-command
+           ;;
+           (yas--eval-lisp-no-saves content))
+          (t
+           ;; x) This is a snippet-snippet :-)
+           ;;
+           ;;    Narrow the region down to the content, shoosh the
+           ;;    `buffer-undo-list', and create the snippet, the new
+           ;;    snippet updates its mirrors once, so we are left with
+           ;;    some plain text.  The undo action for deleting this
+           ;;    plain text will get recorded at the end.
+           ;;
+           ;;    stacked expansion: also shoosh the overlay modification hooks
+           (save-restriction
+             (narrow-to-region start start)
+             (let ((buffer-undo-list t))
+               ;; snippet creation might evaluate users elisp, which
+               ;; might generate errors, so we have to be ready to catch
+               ;; them mostly to make the undo information
+               ;;
+               (setq yas--start-column (save-restriction (widen) 
(current-column)))
+               (yas--inhibit-overlay-hooks
+                 (setq snippet
+                       (if expand-env
+                           (eval `(let* ,expand-env
+                                    (insert content)
+                                    (yas--snippet-create (point-min) 
(point-max))))
+                         (insert content)
+                         (yas--snippet-create (point-min) (point-max)))))))
+
+           ;; stacked-expansion: This checks for stacked expansion, save the
+           ;; `yas--previous-active-field' and advance its boudary.
+           ;;
+           (let ((existing-field (and yas--active-field-overlay
+                                      (overlay-buffer 
yas--active-field-overlay)
+                                      (overlay-get yas--active-field-overlay 
'yas--field))))
+             (when existing-field
+               (setf (yas--snippet-previous-active-field snippet) 
existing-field)
+               (yas--advance-end-maybe existing-field (overlay-end 
yas--active-field-overlay))))
+
+           ;; Exit the snippet immediately if no fields
+           ;;
+           (unless (yas--snippet-fields snippet)
+             (yas-exit-snippet snippet))
+
+           ;; Push two undo actions: the deletion of the inserted contents of
+           ;; the new snippet (without the "key") followed by an apply of
+           ;; `yas--take-care-of-redo' on the newly inserted snippet boundaries
+           ;;
+           ;; A small exception, if `yas-also-auto-indent-first-line'
+           ;; is t and `yas--indent' decides to indent the line to a
+           ;; point before the actual expansion point, undo would be
+           ;; messed up. We call the early point "newstart"".  case,
+           ;; and attempt to fix undo.
+           ;;
+           (let ((newstart (overlay-start (yas--snippet-control-overlay 
snippet)))
+                 (end (overlay-end (yas--snippet-control-overlay snippet))))
+             (when (< newstart start)
+               (push (cons (make-string (- start newstart) ? ) newstart) 
buffer-undo-list))
+             (push (cons newstart end) buffer-undo-list)
+             (push `(apply yas--take-care-of-redo ,start ,end ,snippet)
+                   buffer-undo-list))
+           ;; Now, schedule a move to the first field
+           ;;
+           (let ((first-field (car (yas--snippet-fields snippet))))
+             (when first-field
+               (sit-for 0) ;; fix issue 125
+               (yas--move-to-field snippet first-field)))
+           (yas--message 3 "snippet expanded.")
+           t))))
+
+(defun yas--take-care-of-redo (beg end snippet)
+  "Commits SNIPPET, which in turn pushes an undo action for
+reviving it.
+
+Meant to exit in the `buffer-undo-list'."
+  ;; slightly optimize: this action is only needed for snippets with
+  ;; at least one field
+  (when (yas--snippet-fields snippet)
+    (yas--commit-snippet snippet)))
+
+(defun yas--snippet-revive (beg end snippet)
+  "Revives the SNIPPET and creates a control overlay from BEG to
+END.
+
+BEG and END are, we hope, the original snippets boudaries. All
+the markers/points exiting existing inside SNIPPET should point
+to their correct locations *at the time the snippet is revived*.
+
+After revival, push the `yas--take-care-of-redo' in the
+`buffer-undo-list'"
+  ;; Reconvert all the points to markers
+  ;;
+  (yas--points-to-markers snippet)
+  ;; When at least one editable field existed in the zombie snippet,
+  ;; try to revive the whole thing...
+  ;;
+  (let ((target-field (or (yas--snippet-active-field snippet)
+                          (car (yas--snippet-fields snippet)))))
+    (when target-field
+      (setf (yas--snippet-control-overlay snippet) (yas--make-control-overlay 
snippet beg end))
+      (overlay-put (yas--snippet-control-overlay snippet) 'yas--snippet 
snippet)
+
+      (yas--move-to-field snippet target-field)
+
+      (push `(apply yas--take-care-of-redo ,beg ,end ,snippet)
+            buffer-undo-list))))
+
+(defun yas--snippet-create (begin end)
+  "Creates a snippet from an template inserted between BEGIN and END.
+
+Returns the newly created snippet."
+  (let ((snippet (yas--make-snippet)))
+    (goto-char begin)
+    (yas--snippet-parse-create snippet)
+
+    ;; Sort and link each field
+    (yas--snippet-sort-fields snippet)
+
+    ;; Create keymap overlay for snippet
+    (setf (yas--snippet-control-overlay snippet)
+          (yas--make-control-overlay snippet (point-min) (point-max)))
+
+    ;; Move to end
+    (goto-char (point-max))
+
+    snippet))
+
+
+;;; Apropos adjacencies and "fom's":
+;;
+;; Once the $-constructs bits like "$n" and "${:n" are deleted in the
+;; recently expanded snippet, we might actually have many fields,
+;; mirrors (and the snippet exit) in the very same position in the
+;; buffer. Therefore we need to single-link the
+;; fields-or-mirrors-or-exit (which I have abbreviated to "fom")
+;; according to their original positions in the buffer.
+;;
+;; Then we have operation `yas--advance-end-maybe' and
+;; `yas--advance-start-maybe', which conditionally push the starts and
+;; ends of these foms down the chain.
+;;
+;; This allows for like the printf with the magic ",":
+;;
+;;   printf ("${1:%s}\\n"${1:$(if (string-match "%" text) "," "\);")}  \
+;;   $2${1:$(if (string-match "%" text) "\);" "")}$0
+;;
+(defun yas--fom-start (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-start fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-start fom))
+        (t
+         (yas--exit-marker fom))))
+
+(defun yas--fom-end (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-end fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-end fom))
+        (t
+         (yas--exit-marker fom))))
+
+(defun yas--fom-next (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-next fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-next fom))
+        (t
+         (yas--exit-next fom))))
+
+(defun yas--fom-parent-field (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-parent-field fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-parent-field fom))
+        (t
+         nil)))
+
+(defun yas--calculate-adjacencies (snippet)
+  "Calculate adjacencies for fields or mirrors of SNIPPET.
+
+This is according to their relative positions in the buffer, and
+has to be called before the $-constructs are deleted."
+  (flet ((yas--fom-set-next-fom (fom nextfom)
+                               (cond ((yas--field-p fom)
+                                      (setf (yas--field-next fom) nextfom))
+                                     ((yas--mirror-p fom)
+                                      (setf (yas--mirror-next fom) nextfom))
+                                     (t
+                                      (setf (yas--exit-next fom) nextfom))))
+         (yas--compare-fom-begs (fom1 fom2)
+                               (if (= (yas--fom-start fom2) (yas--fom-start 
fom1))
+                                   (yas--mirror-p fom2)
+                                 (>= (yas--fom-start fom2) (yas--fom-start 
fom1))))
+         (yas--link-foms (fom1 fom2)
+                        (yas--fom-set-next-fom fom1 fom2)))
+    ;; make some yas--field, yas--mirror and yas--exit soup
+    (let ((soup))
+      (when (yas--snippet-exit snippet)
+        (push (yas--snippet-exit snippet) soup))
+      (dolist (field (yas--snippet-fields snippet))
+        (push field soup)
+        (dolist (mirror (yas--field-mirrors field))
+          (push mirror soup)))
+      (setq soup
+            (sort soup
+                  #'yas--compare-fom-begs))
+      (when soup
+        (reduce #'yas--link-foms soup)))))
+
+(defun yas--calculate-mirrors-in-fields (snippet mirror)
+  "Attempt to assign a parent field of SNIPPET to the mirror MIRROR.
+
+Use the tighest containing field if more than one field contains
+the mirror. Intended to be called *before* the dollar-regions are
+deleted."
+  (let ((min (point-min))
+        (max (point-max)))
+    (dolist (field (yas--snippet-fields snippet))
+      (when (and (<= (yas--field-start field) (yas--mirror-start mirror))
+                 (<= (yas--mirror-end mirror) (yas--field-end field))
+               (< min (yas--field-start field))
+               (< (yas--field-end field) max))
+          (setq min (yas--field-start field)
+                max (yas--field-end field))
+          (setf (yas--mirror-parent-field mirror) field)))))
+
+(defun yas--advance-end-maybe (fom newend)
+  "Maybe advance FOM's end to NEWEND if it needs it.
+
+If it does, also:
+
+* call `yas--advance-start-maybe' on FOM's next fom.
+
+* in case FOM is field call `yas--advance-end-maybe' on its parent
+  field
+
+Also, if FOM is an exit-marker, always call
+`yas--advance-start-maybe' on its next fom. This is beacuse
+exit-marker have identical start and end markers.
+
+"
+  (cond ((and fom (< (yas--fom-end fom) newend))
+         (set-marker (yas--fom-end fom) newend)
+         (yas--advance-start-maybe (yas--fom-next fom) newend)
+         (yas--advance-end-of-parents-maybe (yas--fom-parent-field fom) 
newend))
+        ((yas--exit-p fom)
+         (yas--advance-start-maybe (yas--fom-next fom) newend))))
+
+(defun yas--advance-start-maybe (fom newstart)
+  "Maybe advance FOM's start to NEWSTART if it needs it.
+
+If it does, also call `yas--advance-end-maybe' on FOM."
+  (when (and fom (< (yas--fom-start fom) newstart))
+    (set-marker (yas--fom-start fom) newstart)
+    (yas--advance-end-maybe fom newstart)))
+
+(defun yas--advance-end-of-parents-maybe (field newend)
+  "Like `yas--advance-end-maybe' but for parent fields.
+
+Only works for fields and doesn't care about the start of the
+next FOM. Works its way up recursively for parents of parents."
+  (when (and field
+             (< (yas--field-end field) newend))
+    (set-marker (yas--field-end field) newend)
+    (yas--advance-end-of-parents-maybe (yas--field-parent-field field) 
newend)))
+
+(defvar yas--dollar-regions nil
+  "When expanding the snippet the \"parse-create\" functions add
+  cons cells to this var")
+
+(defvar yas--backquote-markers-and-strings nil
+  "List of (MARKER . STRING) marking where the the values
+  from backquoted lisp expressions should be inserted at the end of
+  expansion" )
+
+(defun yas--snippet-parse-create (snippet)
+  "Parse a recently inserted snippet template, creating all
+necessary fields, mirrors and exit points.
+
+Meant to be called in a narrowed buffer, does various passes"
+  (let ((parse-start (point)))
+    ;; Reset the yas--dollar-regions
+    ;;
+    (setq yas--dollar-regions nil)
+    ;; protect just the backquotes
+    ;;
+    (yas--protect-escapes nil '(?`))
+    ;; replace all backquoted expressions
+    ;;
+    (goto-char parse-start)
+    (yas--save-backquotes)
+    ;; protect escaped characters
+    ;;
+    (yas--protect-escapes)
+    ;; parse fields with {}
+    ;;
+    (goto-char parse-start)
+    (yas--field-parse-create snippet)
+    ;; parse simple mirrors and fields
+    ;;
+    (goto-char parse-start)
+    (yas--simple-mirror-parse-create snippet)
+    ;; parse mirror transforms
+    ;;
+    (goto-char parse-start)
+    (yas--transform-mirror-parse-create snippet)
+    ;; calculate adjacencies of fields and mirrors
+    ;;
+    (yas--calculate-adjacencies snippet)
+    ;; Delete $-constructs
+    ;;
+    (yas--delete-regions yas--dollar-regions)
+    ;; restore backquoted expression values
+    ;;
+    (yas--restore-backquotes)
+    ;; restore escapes
+    ;;
+    (goto-char parse-start)
+    (yas--restore-escapes)
+    ;; update mirrors for the first time
+    ;;
+    (yas--update-mirrors snippet)
+    ;; indent the best we can
+    ;;
+    (goto-char parse-start)
+    (yas--indent snippet)))
+
+(defun yas--indent-according-to-mode (snippet-markers)
+  "Indent current line according to mode, preserving
+SNIPPET-MARKERS."
+  ;;; Apropos indenting problems....
+  ;;
+  ;; `indent-according-to-mode' uses whatever `indent-line-function'
+  ;; is available. Some implementations of these functions delete text
+  ;; before they insert. If there happens to be a marker just after
+  ;; the text being deleted, the insertion actually happens after the
+  ;; marker, which misplaces it.
+  ;;
+  ;; This would also happen if we had used overlays with the
+  ;; `front-advance' property set to nil.
+  ;;
+  ;; This is why I have these `trouble-markers', they are the ones at
+  ;; they are the ones at the first non-whitespace char at the line
+  ;; (i.e. at `yas--real-line-beginning'. After indentation takes place
+  ;; we should be at the correct to restore them to. All other
+  ;; non-trouble-markers have been *pushed* and don't need special
+  ;; attention.
+  ;;
+  (goto-char (yas--real-line-beginning))
+  (let ((trouble-markers (remove-if-not #'(lambda (marker)
+                                            (= marker (point)))
+                                        snippet-markers)))
+    (save-restriction
+      (widen)
+      (condition-case err
+          (indent-according-to-mode)
+        (error (yas--message 3 "Warning: `yas--indent-according-to-mode' 
having problems running %s" indent-line-function)
+               nil)))
+    (mapc #'(lambda (marker)
+              (set-marker marker (point)))
+          trouble-markers)))
+
+(defvar yas--indent-original-column nil)
+(defun yas--indent (snippet)
+  (let ((snippet-markers (yas--collect-snippet-markers snippet)))
+    ;; Look for those $>
+    (save-excursion
+      (while (re-search-forward "$>" nil t)
+        (delete-region (match-beginning 0) (match-end 0))
+        (when (not (eq yas-indent-line 'auto))
+          (yas--indent-according-to-mode snippet-markers))))
+    ;; Now do stuff for 'fixed and 'auto
+    (save-excursion
+      (cond ((eq yas-indent-line 'fixed)
+             (while (and (zerop (forward-line))
+                         (zerop (current-column)))
+               (indent-to-column yas--indent-original-column)))
+            ((eq yas-indent-line 'auto)
+             (let ((end (set-marker (make-marker) (point-max)))
+                   (indent-first-line-p yas-also-auto-indent-first-line))
+               (while (and (zerop (if indent-first-line-p
+                                      (prog1
+                                          (forward-line 0)
+                                        (setq indent-first-line-p nil))
+                                    (forward-line 1)))
+                           (not (eobp))
+                           (<= (point) end))
+                 (yas--indent-according-to-mode snippet-markers))))
+            (t
+             nil)))))
+
+(defun yas--collect-snippet-markers (snippet)
+  "Make a list of all the markers used by SNIPPET."
+  (let (markers)
+    (dolist (field (yas--snippet-fields snippet))
+      (push (yas--field-start field) markers)
+      (push (yas--field-end field) markers)
+      (dolist (mirror (yas--field-mirrors field))
+        (push (yas--mirror-start mirror) markers)
+        (push (yas--mirror-end mirror) markers)))
+    (let ((snippet-exit (yas--snippet-exit snippet)))
+      (when (and snippet-exit
+                 (marker-buffer (yas--exit-marker snippet-exit)))
+        (push (yas--exit-marker snippet-exit) markers)))
+    markers))
+
+(defun yas--real-line-beginning ()
+  (let ((c (char-after (line-beginning-position)))
+        (n (line-beginning-position)))
+    (while (or (eql c ?\ )
+               (eql c ?\t))
+      (incf n)
+      (setq c (char-after n)))
+    n))
+
+(defun yas--escape-string (escaped)
+  (concat "YASESCAPE" (format "%d" escaped) "PROTECTGUARD"))
+
+(defun yas--protect-escapes (&optional text escaped)
+  "Protect all escaped characters with their numeric ASCII value.
+
+With optional string TEXT do it in string instead of buffer."
+  (let ((changed-text text)
+        (text-provided-p text))
+    (mapc #'(lambda (escaped)
+              (setq changed-text
+                    (yas--replace-all (concat "\\" (char-to-string escaped))
+                                     (yas--escape-string escaped)
+                                     (when text-provided-p changed-text))))
+          (or escaped yas--escaped-characters))
+    changed-text))
+
+(defun yas--restore-escapes (&optional text escaped)
+  "Restore all escaped characters from their numeric ASCII value.
+
+With optional string TEXT do it in string instead of the buffer."
+  (let ((changed-text text)
+        (text-provided-p text))
+    (mapc #'(lambda (escaped)
+              (setq changed-text
+                    (yas--replace-all (yas--escape-string escaped)
+                                     (char-to-string escaped)
+                                     (when text-provided-p changed-text))))
+          (or escaped yas--escaped-characters))
+    changed-text))
+
+(defun yas--save-backquotes ()
+  "Save all the \"`(lisp-expression)`\"-style expression
+with their evaluated value into `yas--backquote-markers-and-strings'"
+  (while (re-search-forward yas--backquote-lisp-expression-regexp nil t)
+    (let ((current-string (match-string-no-properties 1)) transformed)
+      (delete-region (match-beginning 0) (match-end 0))
+      (setq transformed (yas--eval-lisp (yas--read-lisp (yas--restore-escapes 
current-string '(?`)))))
+      (goto-char (match-beginning 0))
+      (when transformed
+        (let ((marker (make-marker)))
+          (insert "Y") ;; quite horrendous, I love it :)
+          (set-marker marker (point))
+          (insert "Y")
+          (push (cons marker transformed) 
yas--backquote-markers-and-strings))))))
+
+(defun yas--restore-backquotes ()
+  "Replace all the markers in
+`yas--backquote-markers-and-strings' with their values"
+  (while yas--backquote-markers-and-strings
+    (let* ((marker-and-string (pop yas--backquote-markers-and-strings))
+           (marker (car marker-and-string))
+           (string (cdr marker-and-string)))
+      (save-excursion
+        (goto-char marker)
+        (delete-char -1)
+        (insert string)
+        (delete-char 1)
+        (set-marker marker nil)))))
+
+(defun yas--scan-sexps (from count)
+  (condition-case err
+      (with-syntax-table (standard-syntax-table)
+        (scan-sexps from count))
+    (error
+     nil)))
+
+(defun yas--make-marker (pos)
+  "Create a marker at POS with `nil' `marker-insertion-type'"
+  (let ((marker (set-marker (make-marker) pos)))
+    (set-marker-insertion-type marker nil)
+    marker))
+
+(defun yas--field-parse-create (snippet &optional parent-field)
+  "Parse most field expressions, except for the simple one \"$n\".
+
+The following count as a field:
+
+* \"${n: text}\", for a numbered field with default text, as long as N is not 
0;
+
+* \"${n: text$(expression)}, the same with a lisp expression;
+  this is caught with the curiously named 
`yas--multi-dollar-lisp-expression-regexp'
+
+* the same as above but unnumbered, (no N:) and number is calculated 
automatically.
+
+When multiple expressions are found, only the last one counts."
+  ;;
+  (save-excursion
+    (while (re-search-forward yas--field-regexp nil t)
+      (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
+             (number (and (match-string-no-properties 1)
+                          (string-to-number (match-string-no-properties 1))))
+             (brand-new-field (and real-match-end-0
+                                   ;; break if on "$(" immediately
+                                   ;; after the ":", this will be
+                                   ;; caught as a mirror with
+                                   ;; transform later.
+                                   (not (save-match-data
+                                          (eq (string-match "$[ \t\n]*("
+                                                            
(match-string-no-properties 2)) 0)))
+                                   ;; allow ${0: some exit text}
+                                   ;; (not (and number (zerop number)))
+                                   (yas--make-field number
+                                                   (yas--make-marker 
(match-beginning 2))
+                                                   (yas--make-marker (1- 
real-match-end-0))
+                                                   parent-field))))
+        (when brand-new-field
+          (goto-char real-match-end-0)
+          (push (cons (1- real-match-end-0) real-match-end-0)
+                yas--dollar-regions)
+          (push (cons (match-beginning 0) (match-beginning 2))
+                yas--dollar-regions)
+          (push brand-new-field (yas--snippet-fields snippet))
+          (save-excursion
+            (save-restriction
+              (narrow-to-region (yas--field-start brand-new-field) 
(yas--field-end brand-new-field))
+              (goto-char (point-min))
+              (yas--field-parse-create snippet brand-new-field)))))))
+  ;; if we entered from a parent field, now search for the
+  ;; `yas--multi-dollar-lisp-expression-regexp'. THis is used for
+  ;; primary field transformations
+  ;;
+  (when parent-field
+    (save-excursion
+      (while (re-search-forward yas--multi-dollar-lisp-expression-regexp nil t)
+        (let* ((real-match-end-1 (yas--scan-sexps (match-beginning 1) 1)))
+          ;; commit the primary field transformation if:
+          ;;
+          ;; 1. we don't find it in yas--dollar-regions (a subnested
+          ;; field) might have already caught it.
+          ;;
+          ;; 2. we really make sure we have either two '$' or some
+          ;; text and a '$' after the colon ':'. This is a FIXME: work
+          ;; my regular expressions and end these ugly hacks.
+          ;;
+          (when (and real-match-end-1
+                     (not (member (cons (match-beginning 0)
+                                        real-match-end-1)
+                                  yas--dollar-regions))
+                     (not (eq ?:
+                              (char-before (1- (match-beginning 1))))))
+            (let ((lisp-expression-string (buffer-substring-no-properties 
(match-beginning 1)
+                                                                          
real-match-end-1)))
+              (setf (yas--field-transform parent-field)
+                    (yas--read-lisp (yas--restore-escapes 
lisp-expression-string))))
+            (push (cons (match-beginning 0) real-match-end-1)
+                  yas--dollar-regions)))))))
+
+(defun yas--transform-mirror-parse-create (snippet)
+  "Parse the \"${n:$(lisp-expression)}\" mirror transformations."
+  (while (re-search-forward yas--transform-mirror-regexp nil t)
+    (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
+           (number (string-to-number (match-string-no-properties 1)))
+           (field (and number
+                       (not (zerop number))
+                       (yas--snippet-find-field snippet number)))
+           (brand-new-mirror
+            (and real-match-end-0
+                 field
+                 (yas--make-mirror (yas--make-marker (match-beginning 0))
+                                  (yas--make-marker (match-beginning 0))
+                                  (yas--read-lisp
+                                   (yas--restore-escapes
+                                    (buffer-substring-no-properties 
(match-beginning 2)
+                                                                    (1- 
real-match-end-0))))))))
+      (when brand-new-mirror
+        (push brand-new-mirror
+              (yas--field-mirrors field))
+        (yas--calculate-mirrors-in-fields snippet brand-new-mirror)
+        (push (cons (match-beginning 0) real-match-end-0) 
yas--dollar-regions)))))
+
+(defun yas--simple-mirror-parse-create (snippet)
+  "Parse the simple \"$n\" fields/mirrors/exitmarkers."
+  (while (re-search-forward yas--simple-mirror-regexp nil t)
+    (let ((number (string-to-number (match-string-no-properties 1))))
+      (cond ((zerop number)
+
+             (setf (yas--snippet-exit snippet)
+                   (yas--make-exit (yas--make-marker (match-end 0))))
+             (save-excursion
+               (goto-char (match-beginning 0))
+               (when yas-wrap-around-region
+                 (cond (yas-selected-text
+                        (insert yas-selected-text))
+                       ((and (eq yas-wrap-around-region 'cua)
+                             cua-mode
+                             (get-register ?0))
+                        (insert (prog1 (get-register ?0)
+                                  (set-register ?0 nil))))))
+               (push (cons (point) (yas--exit-marker (yas--snippet-exit 
snippet)))
+                     yas--dollar-regions)))
+            (t
+             (let ((field (yas--snippet-find-field snippet number)))
+               (if field
+                   (let ((brand-new-mirror (yas--make-mirror
+                                            (yas--make-marker (match-beginning 
0))
+                                            (yas--make-marker (match-beginning 
0))
+                                            nil)))
+                     (push brand-new-mirror
+                           (yas--field-mirrors field))
+                     (yas--calculate-mirrors-in-fields snippet 
brand-new-mirror))
+                 (push (yas--make-field number
+                                       (yas--make-marker (match-beginning 0))
+                                       (yas--make-marker (match-beginning 0))
+                                       nil)
+                       (yas--snippet-fields snippet))))
+             (push (cons (match-beginning 0) (match-end 0))
+                   yas--dollar-regions))))))
+
+(defun yas--delete-regions (regions)
+  "Sort disjuct REGIONS by start point, then delete from the back."
+  (mapc #'(lambda (reg)
+            (delete-region (car reg) (cdr reg)))
+        (sort regions
+              #'(lambda (r1 r2)
+                  (>= (car r1) (car r2))))))
+
+(defun yas--update-mirrors (snippet)
+  "Updates all the mirrors of SNIPPET."
+  (save-excursion
+    (let* ((fields (copy-list (yas--snippet-fields snippet)))
+           (field (car fields)))
+      (while field
+        (dolist (mirror (yas--field-mirrors field))
+          (let ((mirror-parent-field (yas--mirror-parent-field mirror)))
+            ;; updatte this mirror
+            ;;
+            (yas--mirror-update-display mirror field)
+            ;; for mirrors-in-fields: schedule a possible
+            ;; parent field for reupdting later on
+            ;;
+            (when mirror-parent-field
+              (add-to-list 'fields mirror-parent-field 'append #'eq))
+            ;; `yas--place-overlays' is needed if the active field and
+            ;; protected overlays have been changed because of insertions
+            ;; in `yas--mirror-update-display'
+            ;;
+            (when (eq field (yas--snippet-active-field snippet))
+              (yas--place-overlays snippet field))))
+        (setq fields (cdr fields))
+        (setq field (car fields))))))
+
+(defun yas--mirror-update-display (mirror field)
+  "Update MIRROR according to FIELD (and mirror transform)."
+
+  (let* ((mirror-parent-field (yas--mirror-parent-field mirror))
+         (reflection (and (not (and mirror-parent-field
+                                    (yas--field-modified-p 
mirror-parent-field)))
+                          (or (yas--apply-transform mirror field 'empty-on-nil)
+                              (yas--field-text-for-display field)))))
+    (when (and reflection
+               (not (string= reflection (buffer-substring-no-properties 
(yas--mirror-start mirror)
+                                                                        
(yas--mirror-end mirror)))))
+      (goto-char (yas--mirror-start mirror))
+      (yas--inhibit-overlay-hooks
+        (insert reflection))
+      (if (> (yas--mirror-end mirror) (point))
+          (delete-region (point) (yas--mirror-end mirror))
+        (set-marker (yas--mirror-end mirror) (point))
+        (yas--advance-start-maybe (yas--mirror-next mirror) (point))
+        ;; super-special advance
+        (yas--advance-end-of-parents-maybe mirror-parent-field (point))))))
+
+(defun yas--field-update-display (field snippet)
+  "Much like `yas--mirror-update-display', but for fields"
+  (when (yas--field-transform field)
+    (let ((transformed (and (not (eq (yas--field-number field) 0))
+                            (yas--apply-transform field field)))
+          (point (point)))
+      (when (and transformed
+                 (not (string= transformed (buffer-substring-no-properties 
(yas--field-start field)
+                                                                           
(yas--field-end field)))))
+        (setf (yas--field-modified-p field) t)
+        (goto-char (yas--field-start field))
+        (yas--inhibit-overlay-hooks
+          (insert transformed)
+          (if (> (yas--field-end field) (point))
+              (delete-region (point) (yas--field-end field))
+            (set-marker (yas--field-end field) (point))
+            (yas--advance-start-maybe (yas--field-next field) (point)))
+          t)))))
+
+
+;;; Post-command hook:
+
+(defun yas--post-command-handler ()
+  "Handles various yasnippet conditions after each command."
+  (cond (yas--protection-violation
+         (goto-char yas--protection-violation)
+         (setq yas--protection-violation nil))
+        ((eq 'undo this-command)
+         ;;
+         ;; After undo revival the correct field is sometimes not
+         ;; restored correctly, this condition handles that
+         ;;
+         (let* ((snippet (car (yas--snippets-at-point)))
+                (target-field (and snippet
+                                   (find-if-not #'(lambda (field)
+                                                    
(yas--field-probably-deleted-p snippet field))
+                                                (remove nil
+                                                        (cons 
(yas--snippet-active-field snippet)
+                                                              
(yas--snippet-fields snippet)))))))
+           (when target-field
+             (yas--move-to-field snippet target-field))))
+        ((not (yas--undo-in-progress))
+         ;; When not in an undo, check if we must commit the snippet
+         ;; (user exited it).
+         (yas--check-commit-snippet))))
+
+;;; Fancy docs:
+;;
+;; The docstrings for some functions are generated dynamically
+;; depending on the context.
+;;
+(put 'yas-expand  'function-documentation
+     '(yas--expand-from-trigger-key-doc))
+(defun yas--expand-from-trigger-key-doc ()
+  "A doc synthethizer for `yas--expand-from-trigger-key-doc'."
+  (let ((fallback-description
+         (cond ((eq yas-fallback-behavior 'call-other-command)
+                (let* ((yas-minor-mode nil)
+                       (fallback (key-binding (read-kbd-macro 
(yas--trigger-key-for-fallback)))))
+                  (or (and fallback
+                           (format " call command `%s'." (pp-to-string 
fallback)))
+                      " do nothing.")))
+               ((eq yas-fallback-behavior 'return-nil)
+                ", do nothing.")
+               (t
+                ", defer to `yas--fallback-behaviour' :-)"))))
+    (concat "Expand a snippet before point. If no snippet
+expansion is possible,"
+            fallback-description
+            "\n\nOptional argument FIELD is for non-interactive use and is an
+object satisfying `yas--field-p' to restrict the expansion to.")))
+
+(put 'yas-expand-from-keymap  'function-documentation 
'(yas--expand-from-keymap-doc))
+(defun yas--expand-from-keymap-doc ()
+  "A doc synthethizer for `yas--expand-from-keymap-doc'."
+  (add-hook 'temp-buffer-show-hook 'yas--snippet-description-finish-runonce)
+  (concat "Expand/run snippets from keymaps, possibly falling back to original 
binding.\n"
+          (when (eq this-command 'describe-key)
+            (let* ((vec (this-single-command-keys))
+                   (templates (mapcan #'(lambda (table)
+                                          (yas--fetch table vec))
+                                      (yas--get-snippet-tables)))
+                   (yas--direct-keymaps nil)
+                   (fallback (key-binding vec)))
+              (concat "In this case, "
+                      (when templates
+                        (concat "these snippets are bound to this key:\n"
+                                (yas--template-pretty-list templates)
+                                "\n\nIf none of these expands, "))
+                      (or (and fallback
+                               (format "fallback `%s' will be called." 
(pp-to-string fallback)))
+                          "no fallback keybinding is called."))))))
+
+(defun yas--template-pretty-list (templates)
+  (let ((acc)
+        (yas-buffer-local-condition 'always))
+    (dolist (plate templates)
+      (setq acc (concat acc "\n*) "
+                        (propertize (concat "\\\\snippet `" (car plate) "'")
+                                    'yasnippet (cdr plate)))))
+    acc))
+
+(define-button-type 'help-snippet-def
+  :supertype 'help-xref
+  'help-function (lambda (template) (yas--visit-snippet-file-1 template))
+  'help-echo (purecopy "mouse-2, RET: find snippets's definition"))
+
+(defun yas--snippet-description-finish-runonce ()
+  "Final adjustments for the help buffer when snippets are concerned."
+  (yas--create-snippet-xrefs)
+  (remove-hook 'temp-buffer-show-hook 
'yas--snippet-description-finish-runonce))
+
+(defun yas--create-snippet-xrefs ()
+  (save-excursion
+    (goto-char (point-min))
+    (while (search-forward-regexp "\\\\\\\\snippet[ \s\t]+`\\([^']+\\)'" nil t)
+      (let ((template (get-text-property (match-beginning 1)
+                                         'yasnippet)))
+        (when template
+          (help-xref-button 1 'help-snippet-def template)
+          (kill-region (match-end 1) (match-end 0))
+          (kill-region (match-beginning 0) (match-beginning 1)))))))
+
+(defun yas--expand-uuid (mode-symbol uuid &optional start end expand-env)
+  "Expand a snippet registered in MODE-SYMBOL's table with UUID.
+
+Remaining args as in `yas-expand-snippet'."
+  (let* ((table (gethash mode-symbol yas--tables))
+         (yas--current-template (and table
+                                    (gethash uuid (yas--table-uuidhash 
table)))))
+    (when yas--current-template
+      (yas-expand-snippet (yas--template-content yas--current-template)))))
+
+;;; Utils
+
+(defvar yas-verbosity 4
+  "Log level for `yas--message' 4 means trace most anything, 0 means nothing.")
+
+(defun yas--message (level message &rest args)
+  (when (> yas-verbosity level)
+    (message (apply #'yas--format message args))))
+
+(defun yas--format (format-control &rest format-args)
+  (apply #'format (concat "[yas] " format-control) format-args))
+
+
+;;; Some hacks:
+;;
+;; The functions
+;;
+;; `locate-dominating-file'
+;; `region-active-p'
+;;
+;; added for compatibility in emacsen < 23
+(unless (>= emacs-major-version 23)
+  (unless (fboundp 'region-active-p)
+    (defun region-active-p ()  (and transient-mark-mode mark-active)))
+
+  (unless (fboundp 'locate-dominating-file)
+    (defvar locate-dominating-stop-dir-regexp
+      "\\`\\(?:[\\/][\\/][^\\/]+[\\/]\\|/\\(?:net\\|afs\\|\\.\\.\\.\\)/\\)\\'"
+      "Regexp of directory names which stop the search in 
`locate-dominating-file'.
+Any directory whose name matches this regexp will be treated like
+a kind of root directory by `locate-dominating-file' which will stop its search
+when it bumps into it.
+The default regexp prevents fruitless and time-consuming attempts to find
+special files in directories in which filenames are interpreted as hostnames,
+or mount points potentially requiring authentication as a different user.")
+
+    (defun locate-dominating-file (file name)
+      "Look up the directory hierarchy from FILE for a file named NAME.
+Stop at the first parent directory containing a file NAME,
+and return the directory.  Return nil if not found."
+      ;; We used to use the above locate-dominating-files code, but the
+      ;; directory-files call is very costly, so we're much better off doing
+      ;; multiple calls using the code in here.
+      ;;
+      ;; Represent /home/luser/foo as ~/foo so that we don't try to look for
+      ;; `name' in /home or in /.
+      (setq file (abbreviate-file-name file))
+      (let ((root nil)
+            (prev-file file)
+            ;; `user' is not initialized outside the loop because
+            ;; `file' may not exist, so we may have to walk up part of the
+            ;; hierarchy before we find the "initial UUID".
+            (user nil)
+            try)
+        (while (not (or root
+                        (null file)
+                        ;; FIXME: Disabled this heuristic because it is 
sometimes
+                        ;; inappropriate.
+                        ;; As a heuristic, we stop looking up the hierarchy of
+                        ;; directories as soon as we find a directory belonging
+                        ;; to another user.  This should save us from looking 
in
+                        ;; things like /net and /afs.  This assumes that all 
the
+                        ;; files inside a project belong to the same user.
+                        ;; (let ((prev-user user))
+                        ;;   (setq user (nth 2 (file-attributes file)))
+                        ;;   (and prev-user (not (equal user prev-user))))
+                        (string-match locate-dominating-stop-dir-regexp file)))
+          (setq try (file-exists-p (expand-file-name name file)))
+          (cond (try (setq root file))
+                ((equal file (setq prev-file file
+                                   file (file-name-directory
+                                         (directory-file-name file))))
+                 (setq file nil))))
+        root))))
+
+;; `c-neutralize-syntax-in-CPP` sometimes fires "End of Buffer" error
+;; (when it execute forward-char) and interrupt the after change
+;; hook. Thus prevent the insert-behind hook of yasnippet to be
+;; invoked. Here's a way to reproduce it:
+
+;; # open a *new* Emacs.
+;; # load yasnippet.
+;; # open a *new* .cpp file.
+;; # input "inc" and press TAB to expand the snippet.
+;; # select the `#include <...>` snippet.
+;; # type inside `<>`
+
+(defadvice c-neutralize-syntax-in-CPP
+  (around yas--mp/c-neutralize-syntax-in-CPP activate)
+  "Adviced `c-neutralize-syntax-in-CPP' to properly
+handle the end-of-buffer error fired in it by calling
+`forward-char' at the end of buffer."
+  (condition-case err
+      ad-do-it
+    (error (message (error-message-string err)))))
+
+;; disable c-electric-* serial command in YAS fields
+(add-hook 'c-mode-common-hook
+          '(lambda ()
+             (dolist (k '(":" ">" ";" "<" "{" "}"))
+               (define-key (symbol-value (make-local-variable 'yas-keymap))
+                 k 'self-insert-command))))
+
+;;; Backward compatibility to to yasnippet <= 0.7
+(defvar yas--exported-syms '(;; `defcustom's
+                             ;;
+                             yas-snippet-dirs
+                             yas-prompt-functions
+                             yas-indent-line
+                             yas-also-auto-indent-first-line
+                             yas-snippet-revival
+                             yas-trigger-key
+                             yas-next-field-key
+                             yas-prev-field-key
+                             yas-skip-and-clear-key
+                             yas-triggers-in-field
+                             yas-fallback-behavior
+                             yas-choose-keys-first
+                             yas-choose-tables-first
+                             yas-use-menu
+                             yas-trigger-symbol
+                             yas-wrap-around-region
+                             yas-good-grace
+                             yas-visit-from-menu
+                             yas-expand-only-for-last-commands
+                             yas-field-highlight-face
+
+                             ;; these vars can be customized as well
+                             ;;
+                             yas-keymap
+                             yas-verbosity
+                             yas-extra-modes
+                             yas-key-syntaxes
+                             yas-after-exit-snippet-hook
+                             yas-before-expand-snippet-hook
+                             yas-buffer-local-condition
+
+                             ;; prompting functions
+                             ;;
+                             yas-x-prompt
+                             yas-ido-prompt
+                             yas-no-prompt
+                             yas-completing-prompt
+                             yas-dropdown-prompt
+
+                             ;; interactive functions
+                             ;;
+                             yas-expand
+                             yas-minor-mode
+                             yas-global-mode
+                             yas-direct-keymaps-reload
+                             yas-minor-mode-on
+                             yas-load-directory
+                             yas-reload-all
+                             yas-compile-directory
+                             yas-recompile-all
+                             yas-about
+                             yas-expand-from-trigger-key
+                             yas-expand-from-keymap
+                             yas-insert-snippet
+                             yas-visit-snippet-file
+                             yas-new-snippet
+                             yas-load-snippet-buffer
+                             yas-tryout-snippet
+                             yas-describe-tables
+                             yas-next-field-or-maybe-expand
+                             yas-next-field
+                             yas-prev-field
+                             yas-abort-snippet
+                             yas-exit-snippet
+                             yas-exit-all-snippets
+                             yas-skip-and-clear-or-delete-char
+
+                             ;; symbols that I "exported" for use
+                             ;; in snippets and hookage
+                             ;;
+                             yas-expand-snippet
+                             yas-define-snippets
+                             yas-define-menu
+                             yas-snippet-beg
+                             yas-snippet-end
+                             yas-modified-p
+                             yas-moving-away-p
+                             yas-text
+                             yas-substr
+                             yas-choose-value
+                             yas-key-to-value
+                             yas-throw
+                             yas-verify-value
+                             yas-field-value
+                             yas-text
+                             yas-selected-text
+                             yas-default-from-field
+                             yas-inside-string
+                             yas-unimplemented
+                             yas-define-condition-cache
+                             yas-hippie-try-expand
+
+                             ;; debug definitions
+                             ;; yas-debug-snippet-vars
+                             ;; yas-exterminate-package
+                             ;; yas-debug-test
+
+                             ;; testing definitions
+                             ;; yas-should-expand
+                             ;; yas-should-not-expand
+                             ;; yas-mock-insert
+                             ;; yas-make-file-or-dirs
+                             ;; yas-variables
+                             ;; yas-saving-variables
+                             ;; yas-call-with-snippet-dirs
+                             ;; yas-with-snippet-dirs
+))
+
+(dolist (sym yas--exported-syms)
+  (let ((backported (intern (replace-regexp-in-string "^yas-" "yas/" 
(symbol-name sym)))))
+    (when (boundp sym)
+      (make-obsolete-variable backported sym "yasnippet 0.8")
+      (defvaralias backported sym))
+    (when (fboundp sym)
+      (make-obsolete backported sym "yasnippet 0.8")
+      (defalias backported sym))))
+
+
+(provide 'yasnippet)
+
+;;; yasnippet.el ends here
+;; Local Variables:
+;; coding: utf-8
+;; End:

commit 38c4b734c9b02c036818d5c99083c5ebdf704ece
Author: Joao Tavora <address@hidden>
Date:   Thu Aug 16 10:45:33 2012 +0100

    Closes #285: fix typo introduced in 71c8e0ea469c2992a31d17b0722ebdeb789fd1bf

diff --git a/yasnippet.el b/yasnippet.el
index 17e6f91..7c763f4 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -1,4542 +1,4542 @@
-;;; yasnippet.el --- Yet another snippet extension for Emacs.
-
-;; Copyright (C) 2008-2012 Free Software Foundation, Inc.
-;; Authors: pluskid <address@hidden>,  João Távora <address@hidden>
-;; Version: 0.8.0
-;; Package-version: 0.8.0
-;; X-URL: http://github.com/capitaomorte/yasnippet
-;; Keywords: convenience, emulation
-;; URL: http://github.com/capitaomorte/yasnippet
-;; EmacsWiki: YaSnippetMode
-
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;;   Basic steps to setup:
-;;
-;;    (add-to-list 'load-path
-;;                 "~/path-to-yasnippet")
-;;    (require 'yasnippet)
-;;    (yas-global-mode 1)
-;;
-;;
-;;   Interesting variables are:
-;;
-;;       `yas-snippet-dirs'
-;;
-;;           The directory where user-created snippets are to be
-;;           stored. Can also be a list of directories. In that case,
-;;           when used for bulk (re)loading of snippets (at startup or
-;;           via `yas-reload-all'), directories appearing earlier in
-;;           the list shadow other dir's snippets. Also, the first
-;;           directory is taken as the default for storing the user's
-;;           new snippets.
-;;
-;;           The deprecated `yas/root-directory' aliases this variable
-;;           for backward-compatibility.
-;;
-;;       `yas-extra-modes'
-;;
-;;           A local variable that you can set in a hook to override
-;;           snippet-lookup based on major mode. It is a a symbol (or
-;;           list of symbols) that correspond to subdirectories of
-;;           `yas-snippet-dirs' and is used for deciding which
-;;           snippets to consider for the active buffer.
-;;
-;;           Deprecated `yas/mode-symbol' aliases this variable for
-;;           backward-compatibility.
-;;
-;;   Major commands are:
-;;
-;;       M-x yas-expand
-;;
-;;           Try to expand snippets before point.  In `yas-minor-mode',
-;;           this is bound to `yas-trigger-key' which you can customize.
-;;
-;;       M-x yas-load-directory
-;;
-;;           Prompts you for a directory hierarchy of snippets to load.
-;;
-;;       M-x yas-insert-snippet
-;;
-;;           Prompts you for possible snippet expansion if that is
-;;           possible according to buffer-local and snippet-local
-;;           expansion conditions.  With prefix argument, ignore these
-;;           conditions.
-;;
-;;       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.
-;;
-;;       M-x yas-new-snippet
-;;
-;;           Lets you create a new snippet file in the correct
-;;           subdirectory of `yas-snippet-dirs', according to the
-;;           active major mode.
-;;
-;;       M-x yas-load-snippet-buffer
-;;
-;;           When editing a snippet, this loads the snippet.  This is
-;;           bound to "C-c C-c" while in the `snippet-mode' editing
-;;           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'.
-;;
-;;       M-x yas-describe-tables
-;;
-;;           Lists known snippets in a separate buffer. User is
-;;           prompted as to whether only the currently active tables
-;;           are to be displayed, or all the tables for all major
-;;           modes.
-;;
-;;   The `dropdown-list.el' extension is bundled with YASnippet, you
-;;   can optionally use it the preferred "prompting method", puting in
-;;   your .emacs file, for example:
-;;
-;;       (require 'dropdown-list)
-;;       (setq yas-prompt-functions '(yas-dropdown-prompt
-;;                                    yas-ido-prompt
-;;                                    yas-completing-prompt))
-;;
-;;   Also check out the customization group
-;;
-;;        M-x customize-group RET yasnippet RET
-;;
-;;   If you use the customization group to set variables
-;;   `yas-snippet-dirs' or `yas-global-mode', make sure the path to
-;;   "yasnippet.el" is present in the `load-path' *before* the
-;;   `custom-set-variables' is executed in your .emacs file.
-;;
-;;   For more information and detailed usage, refer to the project page:
-;;      http://github.com/capitaomorte/yasnippet
-
-;;; Code:
-
-(require 'cl)
-(require 'easymenu)
-(require 'help-mode)
-
-
-;;; User customizable variables
-
-(defgroup yasnippet nil
-  "Yet Another Snippet extension"
-  :group 'editing)
-
-(defvar yas--load-file-name load-file-name
-  "Store the filename that yasnippet.el was originally loaded from.")
-
-(defcustom yas-snippet-dirs (remove nil
-                                    (list "~/.emacs.d/snippets"
-                                          (when yas--load-file-name
-                                            (concat (file-name-directory 
yas--load-file-name) "snippets"))))
-  "Directory or list of snippet dirs for each major mode.
-
-The directory where user-created snippets are to be stored. Can
-also be a list of directories. In that case, when used for
-bulk (re)loading of snippets (at startup or via
-`yas-reload-all'), directories appearing earlier in the list
-shadow other dir's snippets. Also, the first directory is taken
-as the default for storing the user's new snippets."
-  :type '(choice (string :tag "Single directory (string)")
-                 (repeat :args (string) :tag "List of directories (strings)"))
-  :group 'yasnippet
-  :require 'yasnippet
-  :set #'(lambda (symbol new)
-           (let ((old (and (boundp symbol)
-                           (symbol-value symbol))))
-             (set-default symbol new)
-             (unless (or (not (fboundp 'yas-reload-all))
-                         (equal old new))
-               (yas-reload-all)))))
-
-(defun yas-snippet-dirs ()
-  "Returns `yas-snippet-dirs' (which see) as a list."
-  (if (listp yas-snippet-dirs) yas-snippet-dirs (list yas-snippet-dirs)))
-
-(defvaralias 'yas/root-directory 'yas-snippet-dirs)
-
-(defcustom yas-prompt-functions '(yas-x-prompt
-                                  yas-dropdown-prompt
-                                  yas-completing-prompt
-                                  yas-ido-prompt
-                                  yas-no-prompt)
-  "Functions to prompt for keys, templates, etc interactively.
-
-These functions are called with the following arguments:
-
-- PROMPT: A string to prompt the user
-
-- CHOICES: a list of strings or objects.
-
-- optional DISPLAY-FN : A function that, when applied to each of
-the objects in CHOICES will return a string.
-
-The return value of any function you put here should be one of
-the objects in CHOICES, properly formatted with DISPLAY-FN (if
-that is passed).
-
-- To signal that your particular style of prompting is
-unavailable at the moment, you can also have the function return
-nil.
-
-- To signal that the user quit the prompting process, you can
-signal `quit' with
-
-  (signal 'quit \"user quit!\")."
-  :type '(repeat function)
-  :group 'yasnippet)
-
-(defcustom yas-indent-line 'auto
-  "Controls indenting applied to a recent snippet expansion.
-
-The following values are possible:
-
-- `fixed' Indent the snippet to the current column;
-
-- `auto' Indent each line of the snippet with `indent-according-to-mode'
-
-Every other value means don't apply any snippet-side indendation
-after expansion (the manual per-line \"$>\" indentation still
-applies)."
-  :type '(choice (const :tag "Nothing"  nothing)
-                 (const :tag "Fixed"    fixed)
-                 (const :tag "Auto"     auto))
-  :group 'yasnippet)
-
-(defcustom yas-also-auto-indent-first-line nil
-  "Non-nil means also auto indent first line according to mode.
-
-Naturally this is only valid when `yas-indent-line' is `auto'"
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-snippet-revival t
-  "Non-nil means re-activate snippet fields after undo/redo."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-trigger-key "<tab>"
-  "The key bound to `yas-expand' when `yas-minor-mode' is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'."
-  :type 'string
-  :group 'yasnippet
-  :set #'(lambda (symbol key)
-           (let ((old (and (boundp symbol)
-                           (symbol-value symbol))))
-             (set-default symbol key)
-             ;; On very first loading of this defcustom,
-             ;; `yas-trigger-key' is *not* loaded.
-             (if (fboundp 'yas--trigger-key-reload)
-                 (yas--trigger-key-reload old)))))
-
-(defcustom yas-next-field-key '("TAB" "<tab>")
-  "The key to navigate to next field when a snippet is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-
-(defcustom yas-prev-field-key '("<backtab>" "<S-tab>")
-  "The key to navigate to previous field when a snippet is active.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-(defcustom yas-skip-and-clear-key '("C-d" "<delete>" "<deletechar>")
-  "The key to clear the currently active field.
-
-Value is a string that is converted to the internal Emacs key
-representation using `read-kbd-macro'.
-
-Can also be a list of strings."
-  :type '(choice (string :tag "String")
-                 (repeat :args (string) :tag "List of strings"))
-  :group 'yasnippet
-  :set #'(lambda (symbol val)
-           (set-default symbol val)
-           (if (fboundp 'yas--init-yas-in-snippet-keymap)
-               (yas--init-yas-in-snippet-keymap))))
-
-(defcustom yas-triggers-in-field nil
-  "If non-nil, `yas-next-field-key' can trigger stacked expansions.
-
-Otherwise, `yas-next-field-key' just tries to move on to the next
-field"
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-fallback-behavior 'call-other-command
-  "How to act when `yas-trigger-key' does *not* expand a snippet.
-
-- `call-other-command' means try to temporarily disable YASnippet
-    and call the next command bound to `yas-trigger-key'.
-
-- nil or the symbol `return-nil' mean do nothing. (and
-  `yas-expand' returns nil)
-
-- A lisp form (apply COMMAND . ARGS) means interactively call
-  COMMAND, if ARGS is non-nil, call COMMAND non-interactively
-  with ARGS as arguments."
-  :type '(choice (const :tag "Call previous command"  call-other-command)
-                 (const :tag "Do nothing"             return-nil))
-  :group 'yasnippet)
-
-(defcustom yas-choose-keys-first nil
-  "If non-nil, prompt for snippet key first, then for template.
-
-Otherwise prompts for all possible snippet names.
-
-This affects `yas-insert-snippet' and `yas-visit-snippet-file'."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-choose-tables-first nil
-  "If non-nil, and multiple eligible snippet tables, prompts user for tables 
first.
-
-Otherwise, user chooses between the merging together of all
-eligible tables.
-
-This affects `yas-insert-snippet', `yas-visit-snippet-file'"
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-use-menu 'abbreviate
-  "Display a YASnippet menu in the menu bar.
-
-When non-nil, submenus for each snippet table will be listed
-under the menu \"Yasnippet\".
-
-- If set to `abbreviate', only the current major-mode
-menu and the modes set in `yas-extra-modes' are listed.
-
-- If set to `full', every submenu is listed
-
-- It set to nil, don't display a menu at all (this requires a
-  `yas-reload-all' call if the menu is already visible).
-
-Any other non-nil value, every submenu is listed."
-  :type '(choice (const :tag "Full"  full)
-                 (const :tag "Abbreviate" abbreviate)
-                 (const :tag "No menu" nil))
-  :group 'yasnippet)
-
-(defcustom yas-trigger-symbol (if (eq window-system 'mac)
-                                  (char-to-string ?\x21E5) ;; little ->| sign
-                                  " =>")
-  "The text that will be used in menu to represent the trigger."
-  :type 'string
-  :group 'yasnippet)
-
-(defcustom yas-wrap-around-region nil
-  "If non-nil, snippet expansion wraps around selected region.
-
-The wrapping occurs just before the snippet's exit marker.  This
-can be overriden on a per-snippet basis."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-good-grace t
-  "If non-nil, don't raise errors in inline elisp evaluation.
-
-An error string \"[yas] error\" is returned instead."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-visit-from-menu nil
-  "If non-nil visit snippets's files from menu, instead of expanding them.
-
-This cafn only work when snippets are loaded from files."
-  :type 'boolean
-  :group 'yasnippet)
-
-(defcustom yas-expand-only-for-last-commands nil
-  "List of `last-command' values to restrict tab-triggering to, or nil.
-
-Leave this set at nil (the default) to be able to trigger an
-expansion simply by placing the cursor after a valid tab trigger,
-using whichever commands.
-
-Optionallly, set this to something like '(self-insert-command) if
-you to wish restrict expansion to only happen when the last
-letter of the snippet tab trigger was typed immediately before
-the trigger key itself."
-  :type '(repeat function)
-  :group 'yasnippet)
-
-;; Only two faces, and one of them shouldn't even be used...
-;;
-(defface yas-field-highlight-face
-  '((t (:inherit 'region)))
-  "The face used to highlight the currently active field of a snippet"
-  :group 'yasnippet)
-
-(defface yas--field-debug-face
-  '()
-  "The face used for debugging some overlays normally hidden"
-  :group 'yasnippet)
-
-
-;;; User can also customize the next defvars
-
-(defun yas--define-some-keys (keys keymap definition)
-  "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'."
-  (let ((keys (or (and (listp keys) keys)
-                  (list keys))))
-    (dolist (key keys)
-      (define-key keymap (read-kbd-macro key) definition))))
-
-(defun yas--init-yas-in-snippet-keymap ()
-  (setq yas-keymap
-        (let ((map (make-sparse-keymap)))
-          (mapc #'(lambda (binding)
-                    (yas--define-some-keys (car binding) map (cdr binding)))
-                `((,yas-next-field-key     . yas-next-field-or-maybe-expand)
-                  (,yas-prev-field-key     . yas-prev-field)
-                  ("C-g"                   . yas-abort-snippet)
-                  (,yas-skip-and-clear-key . 
yas-skip-and-clear-or-delete-char)))
-          map)))
-
-(defvar yas-keymap (yas--init-yas-in-snippet-keymap)
-  "The keymap active while a snippet expansion is in progress.")
-
-(defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ")
-  "List of character syntaxes used to find a trigger key before point.
-The list is tried in the order while scanning characters
-backwards from point. For example, if the list is '(\"w\" \"w_\")
-first look for trigger keys which are composed exclusively of
-\"word\"-syntax characters, and then, if that fails, look for
-keys which are either of \"word\" or \"symbol\"
-syntax. Triggering after
-
-foo-bar
-
-will, according to the \"w\" element first try \"bar\". If that
-isn't a trigger key, \"foo-bar\" is tried, respecting a second
-\"w_\" element.")
-
-(defvar yas-after-exit-snippet-hook
-  '()
-  "Hooks to run after a snippet exited.
-
-The hooks will be run in an environment where some variables bound to
-proper values:
-
-`yas-snippet-beg' : The beginning of the region of the snippet.
-
-`yas-snippet-end' : Similar to beg.
-
-Attention: These hooks are not run when exiting nested/stackd snippet 
expansion!")
-
-(defvar yas-before-expand-snippet-hook
-  '()
-  "Hooks to run just before expanding a snippet.")
-
-(defvar yas-buffer-local-condition
-  '(if (and (or (fourth (syntax-ppss))
-                (fifth (syntax-ppss)))
-            (eq (symbol-function this-command) 'yas-expand-from-trigger-key))
-       '(require-snippet-condition . force-in-comment)
-     t)
-  "Snippet expanding condition.
-
-This variable is a lisp form which is evaluated everytime a
-snippet expansion is attemped:
-
-    * If it evaluates to nil, no snippets can be expanded.
-
-    * If it evaluates to the a cons (require-snippet-condition
-      . REQUIREMENT)
-
-       * Snippets bearing no \"# condition:\" directive are not
-         considered
-
-       * Snippets bearing conditions that evaluate to nil (or
-         produce an error) won't be onsidered.
-
-       * If the snippet has a condition that evaluates to non-nil
-         RESULT:
-
-          * If REQUIREMENT is t, the snippet is considered
-
-          * If REQUIREMENT is `eq' RESULT, the snippet is
-            considered
-
-          * Otherwise, the snippet is not considered.
-
-    * If it evaluates to the symbol 'always, all snippets are
-      considered for expansion, regardless of any conditions.
-
-    * If it evaluates to t or some other non-nil value
-
-       * Snippet bearing no conditions, or conditions that
-         evaluate to non-nil, are considered for expansion.
-
-       * Otherwise, the snippet is not considered.
-
-Here's an example preventing snippets from being expanded from
-inside comments, in `python-mode' only, with the exception of
-snippets returning the symbol 'force-in-comment in their
-conditions.
-
- (add-hook 'python-mode-hook
-           '(lambda ()
-              (setq yas-buffer-local-condition
-                    '(if (python-in-string/comment)
-                         '(require-snippet-condition . force-in-comment)
-                       t))))
-
-The default value is similar, it filters out potential snippet
-expansions inside comments and string literals, unless the
-snippet itself contains a condition that returns the symbol
-`force-in-comment'.")
-
-
-;;; Internal variables
-
-(defvar yas--version "0.8.0 (beta)")
-
-(defvar yas--menu-table (make-hash-table)
-  "A hash table of MAJOR-MODE symbols to menu keymaps.")
-
-(defvar yas--known-modes
-  '(ruby-mode rst-mode markdown-mode)
-  "A list of mode which is well known but not part of emacs.")
-
-(defvar yas--escaped-characters
-  '(?\\ ?` ?\" ?' ?$ ?} ?{ ?\( ?\))
-  "List of characters which *might* need to be escaped.")
-
-(defconst yas--field-regexp
-  "${\\([0-9]+:\\)?\\([^}]*\\)}"
-  "A regexp to *almost* recognize a field.")
-
-(defconst yas--multi-dollar-lisp-expression-regexp
-  "$+[ \t\n]*\\(([^)]*)\\)"
-  "A regexp to *almost* recognize a \"$(...)\" expression.")
-
-(defconst yas--backquote-lisp-expression-regexp
-  "`\\([^`]*\\)`"
-  "A regexp to recognize a \"`lisp-expression`\" expression." )
-
-(defconst yas--transform-mirror-regexp
-  "${\\(?:\\([0-9]+\\):\\)?$\\([ \t\n]*([^}]*\\)"
-  "A regexp to *almost* recognize a mirror with a transform.")
-
-(defconst yas--simple-mirror-regexp
-  "$\\([0-9]+\\)"
-  "A regexp to recognize a simple mirror.")
-
-(defvar yas--snippet-id-seed 0
-  "Contains the next id for a snippet.")
-
-(defun yas--snippet-next-id ()
-  (let ((id yas--snippet-id-seed))
-    (incf yas--snippet-id-seed)
-    id))
-
-
-;;; Minor mode stuff
-
-;; XXX: `last-buffer-undo-list' is somehow needed in Carbon Emacs for MacOSX
-(defvar last-buffer-undo-list nil)
-
-(defvar yas--minor-mode-menu nil
-  "Holds the YASnippet menu")
-
-(defun yas--init-minor-keymap ()
-  (let ((map (make-sparse-keymap)))
-    (when yas-use-menu
-      (easy-menu-define yas--minor-mode-menu
-      map
-      "Menu used when `yas-minor-mode' is active."
-      '("YASnippet"
-        "----"
-        ["Expand trigger" yas-expand
-         :help "Possibly expand tab trigger before point"]
-        ["Insert at point..." yas-insert-snippet
-         :help "Prompt for an expandable snippet and expand it at point"]
-        ["New snippet..." yas-new-snippet
-         :help "Create a new snippet in an appropriate directory"]
-        ["Visit snippet file..." yas-visit-snippet-file
-         :help "Prompt for an expandable snippet and find its file"]
-        "----"
-        ("Snippet menu behaviour"
-         ["Visit snippets" (setq yas-visit-from-menu t)
-          :help "Visit snippets from the menu"
-          :active t :style radio   :selected yas-visit-from-menu]
-         ["Expand snippets" (setq yas-visit-from-menu nil)
-          :help "Expand snippets from the menu"
-          :active t :style radio :selected (not yas-visit-from-menu)]
-         "----"
-         ["Show all known modes" (setq yas-use-menu 'full)
-          :help "Show one snippet submenu for each loaded table"
-          :active t :style radio   :selected (eq yas-use-menu 'full)]
-         ["Abbreviate according to current mode" (setq yas-use-menu 
'abbreviate)
-          :help "Show only snippet submenus for the current active modes"
-          :active t :style radio   :selected (eq yas-use-menu 'abbreviate)])
-        ("Indenting"
-         ["Auto" (setq yas-indent-line 'auto)
-          :help "Indent each line of the snippet with 
`indent-according-to-mode'"
-          :active t :style radio   :selected (eq yas-indent-line 'auto)]
-         ["Fixed" (setq yas-indent-line 'fixed)
-          :help "Indent the snippet to the current column"
-          :active t :style radio   :selected (eq yas-indent-line 'fixed)]
-         ["None" (setq yas-indent-line 'none)
-          :help "Don't apply any particular snippet indentation after 
expansion"
-          :active t :style radio   :selected (not (member yas-indent-line 
'(fixed auto)))]
-         "----"
-         ["Also auto indent first line" (setq yas-also-auto-indent-first-line
-                                              (not 
yas-also-auto-indent-first-line))
-          :help "When auto-indenting also, auto indent the first line menu"
-          :active (eq yas-indent-line 'auto)
-          :style toggle :selected yas-also-auto-indent-first-line]
-         )
-        ("Prompting method"
-         ["System X-widget" (setq yas-prompt-functions
-                                  (cons 'yas-x-prompt
-                                        (remove 'yas-x-prompt
-                                                yas-prompt-functions)))
-          :help "Use your windowing system's (gtk, mac, windows, etc...) 
default menu"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-x-prompt)]
-         ["Dropdown-list" (setq yas-prompt-functions
-                                (cons 'yas-dropdown-prompt
-                                      (remove 'yas-dropdown-prompt
-                                              yas-prompt-functions)))
-          :help "Use a special dropdown list"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-dropdown-prompt)]
-         ["Ido" (setq yas-prompt-functions
-                      (cons 'yas-ido-prompt
-                            (remove 'yas-ido-prompt
-                                    yas-prompt-functions)))
-          :help "Use an ido-style minibuffer prompt"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-ido-prompt)]
-         ["Completing read" (setq yas-prompt-functions
-                                  (cons 'yas-completing-prompt
-                                        (remove 'yas-completing-prompt
-                                                yas-prompt-functions)))
-          :help "Use a normal minibuffer prompt"
-          :active t :style radio   :selected (eq (car yas-prompt-functions)
-                                                 'yas-completing-prompt)]
-         )
-        ("Misc"
-         ["Wrap region in exit marker"
-          (setq yas-wrap-around-region
-                (not yas-wrap-around-region))
-          :help "If non-nil automatically wrap the selected text in the $0 
snippet exit"
-          :style toggle :selected yas-wrap-around-region]
-         ["Allow stacked expansions "
-          (setq yas-triggers-in-field
-                (not yas-triggers-in-field))
-          :help "If non-nil allow snippets to be triggered inside other 
snippet fields"
-          :style toggle :selected yas-triggers-in-field]
-         ["Revive snippets on undo "
-          (setq yas-snippet-revival
-                (not yas-snippet-revival))
-          :help "If non-nil allow snippets to become active again after undo"
-          :style toggle :selected yas-snippet-revival]
-         ["Good grace "
-          (setq yas-good-grace
-                (not yas-good-grace))
-          :help "If non-nil don't raise errors in bad embedded eslip in 
snippets"
-          :style toggle :selected yas-good-grace]
-         )
-        "----"
-        ["Load snippets..."  yas-load-directory
-         :help "Load snippets from a specific directory"]
-        ["Reload everything" yas-reload-all
-         :help "Cleanup stuff, reload snippets, rebuild menus"]
-        ["About"            yas-about
-         :help "Display some information about YASsnippet"])))
-
-    ;; Now for the stuff that has direct keybindings
-    ;;
-    (define-key map "\C-c&\C-s" 'yas-insert-snippet)
-    (define-key map "\C-c&\C-n" 'yas-new-snippet)
-    (define-key map "\C-c&\C-v" 'yas-visit-snippet-file)
-    map))
-
-(defvar yas-minor-mode-map (yas--init-minor-keymap)
-  "The keymap used when `yas-minor-mode' is active.")
-
-(defun yas--trigger-key-reload (&optional unbind-key)
-  "Rebind `yas-expand' to the new value of `yas-trigger-key'.
-
-With optional UNBIND-KEY, try to unbind that key from
-`yas-minor-mode-map'."
-  (when (and unbind-key
-             (stringp unbind-key)
-             (not (string= unbind-key "")))
-    (define-key yas-minor-mode-map (read-kbd-macro unbind-key) nil))
-  (when  (and yas-trigger-key
-              (stringp yas-trigger-key)
-              (not (string= yas-trigger-key "")))
-    (define-key yas-minor-mode-map (read-kbd-macro yas-trigger-key) 
'yas-expand)))
-
-(defvar yas--tables (make-hash-table)
-  "A hash table of mode symbols to `yas--table' objects.")
-
-(defvar yas--parents (make-hash-table)
-  "A hash table of mode symbols do lists of direct parent mode symbols.
-
-This list is populated when reading the \".yas-parents\" files
-found when traversing snippet directories with
-`yas-load-directory'.
-
-There might be additionalal parenting information stored in the
-`derived-mode-parent' property of some mode symbols, but that is
-not recorded here.")
-
-(defvar yas--direct-keymaps (list)
-  "Keymap alist supporting direct snippet keybindings.
-
-This variable is is placed in `emulation-mode-map-alists'.
-
-Its elements looks like (TABLE-NAME . KEYMAP). They're
-instantiated on `yas-reload-all' but KEYMAP is added to only when
-loading snippets. `yas--direct-TABLE-NAME' is then a variable set
-buffer-locally when entering `yas-minor-mode'. KEYMAP binds all
-defined direct keybindings to the command
-`yas-expand-from-keymap' which then which snippet to expand.")
-
-(defun yas-direct-keymaps-reload ()
-  "Force reload the direct keybinding for active snippet tables."
-  (interactive)
-  (setq yas--direct-keymaps nil)
-  (maphash #'(lambda (name table)
-               (push (cons (intern (format "yas--direct-%s" name))
-                           (yas--table-direct-keymap table))
-                     yas--direct-keymaps))
-           yas--tables))
-
-(defun yas--modes-to-activate ()
-  "Compute list of mode symbols that are active for `yas-expand'
-and friends."
-  (let ((modes-to-activate (list major-mode))
-        (mode major-mode))
-    (while (setq mode (get mode 'derived-mode-parent))
-      (push mode modes-to-activate))
-    (dolist (mode (yas-extra-modes))
-      (push mode modes-to-activate))
-    (remove-duplicates
-     (append modes-to-activate
-             (mapcan #'(lambda (mode)
-                         (yas--all-parents mode))
-                     modes-to-activate)))))
-
-(defvar yas-minor-mode-hook nil
-  "Hook run when yas-minor-mode is turned on")
-
-;;;###autoload
-(define-minor-mode yas-minor-mode
-  "Toggle YASnippet mode.
-
-When YASnippet mode is enabled, the `yas-trigger-key' key expands
-snippets of code depending on the major mode.
-
-With no argument, this command toggles the mode.
-positive prefix argument turns on the mode.
-Negative prefix argument turns off the mode.
-
-You can customize the key through `yas-trigger-key'.
-
-Key bindings:
-\\{yas-minor-mode-map}"
-  nil
-  ;; The indicator for the mode line.
-  " yas"
-  :group 'yasnippet
-  (cond (yas-minor-mode
-         ;; Reload the trigger key
-         ;;
-         (yas--trigger-key-reload)
-         ;; Install the direct keymaps in `emulation-mode-map-alists'
-         ;; (we use `add-hook' even though it's not technically a hook,
-         ;; but it works). Then define variables named after modes to
-         ;; index `yas--direct-keymaps'.
-         ;;
-         ;; Also install the post-command-hook.
-         ;;
-         (add-hook 'emulation-mode-map-alists 'yas--direct-keymaps)
-         (add-hook 'post-command-hook 'yas--post-command-handler nil t)
-         ;; Set the `yas--direct-%s' vars for direct keymap expansion
-         ;;
-         (dolist (mode (yas--modes-to-activate))
-           (let ((name (intern (format "yas--direct-%s" mode))))
-             (set-default name nil)
-             (set (make-local-variable name) t)))
-         ;; Perform JIT loads
-         ;;
-         (yas--load-pending-jits))
-        (t
-         ;; Uninstall the direct keymaps and the post-command hook
-         ;;
-         (remove-hook 'post-command-hook 'yas--post-command-handler t)
-         (remove-hook 'emulation-mode-map-alists 'yas--direct-keymaps))))
-
-(defvar yas--dont-activate '(minibufferp)
-  "If non-nil don't let `yas-minor-mode-on' active yas for this buffer.
-
-If a function, then its result is used.
-
-If a list of functions, then all functions must return nil to
-activate yas for this buffer.
-
-`yas-minor-mode-on' is usually called by `yas-global-mode' so
-this effectively lets you define exceptions to the \"global\"
-behaviour. Can also be a function of zero arguments.")
-(make-variable-buffer-local 'yas--dont-activate)
-
-(defun yas-minor-mode-on ()
-  "Turn on YASnippet minor mode.
-
-Do this unless `yas--dont-activate' is truish "
-  (interactive)
-  (unless (cond ((functionp yas--dont-activate)
-                 (funcall yas--dont-activate))
-                ((consp yas--dont-activate)
-                 (some #'funcall yas--dont-activate))
-                (yas--dont-activate))
-    ;; Load all snippets definitions unless we still don't have a
-    ;; root-directory or some snippets have already been loaded.
-    ;;
-    (yas-minor-mode 1)))
-
-;;;###autoload
-(define-globalized-minor-mode yas-global-mode yas-minor-mode yas-minor-mode-on
-  :group 'yasnippet
-  :require 'yasnippet)
-
-(defun yas--global-mode-reload-with-jit-maybe ()
-  (when yas-global-mode (yas-reload-all)))
-
-(add-hook 'yas-global-mode-hook 'yas--global-mode-reload-with-jit-maybe)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Major mode stuff
-;;
-(defvar yas--font-lock-keywords
-  (append '(("^#.*$" . font-lock-comment-face))
-          lisp-font-lock-keywords
-          lisp-font-lock-keywords-1
-          lisp-font-lock-keywords-2
-          '(("$\\([0-9]+\\)"
-             (0 font-lock-keyword-face)
-             (1 font-lock-string-face t))
-            ("${\\([0-9]+\\):?"
-             (0 font-lock-keyword-face)
-             (1 font-lock-warning-face t))
-            ("${" font-lock-keyword-face)
-            ("$[0-9]+?" font-lock-preprocessor-face)
-            ("\\(\\$(\\)" 1 font-lock-preprocessor-face)
-            ("}"
-             (0 font-lock-keyword-face)))))
-
-(defun yas--init-major-keymap ()
-  (let ((map (make-sparse-keymap)))
-    (easy-menu-define nil
-      map
-      "Menu used when snippet-mode is active."
-      (cons "Snippet"
-            (mapcar #'(lambda (ent)
-                        (when (third ent)
-                          (define-key map (third ent) (second ent)))
-                        (vector (first ent) (second ent) t))
-                    (list
-                     (list "Load this snippet" 'yas-load-snippet-buffer 
"\C-c\C-c")
-                     (list "Try out this snippet" 'yas-tryout-snippet 
"\C-c\C-t")))))
-    map))
-
-(defvar snippet-mode-map
-  (yas--init-major-keymap)
-  "The keymap used when `snippet-mode' is active")
-
-
-(define-derived-mode snippet-mode text-mode "Snippet"
-  "A mode for editing yasnippets"
-  (setq font-lock-defaults '(yas--font-lock-keywords))
-  (set (make-local-variable 'require-final-newline) nil)
-  (set (make-local-variable 'comment-start) "#")
-  (set (make-local-variable 'comment-start-skip) "#+[\t ]*"))
-
-
-
-;;; Internal structs for template management
-
-(defstruct (yas--template (:constructor yas--make-blank-template))
-  "A template for a snippet."
-  key
-  content
-  name
-  condition
-  expand-env
-  file
-  keybinding
-  uuid
-  menu-binding-pair
-  group      ;; as dictated by the #group: directive or .yas-make-groups
-  perm-group ;; as dictated by `yas-define-menu'
-  table
-  )
-
-(defun yas--populate-template (template &rest args)
-  "Helper function to populate a template with properties"
-  (let (p v)
-    (while args
-      (aset template
-            (position (intern (substring (symbol-name (car args)) 1))
-                      (mapcar #'car (get 'yas--template 'cl-struct-slots)))
-            (second args))
-      (setq args (cddr args)))
-    template))
-
-(defstruct (yas--table (:constructor yas--make-snippet-table (name)))
-  "A table to store snippets for a particular mode.
-
-Has the following fields:
-
-`yas--table-name'
-
-  A symbol name normally corresponding to a major mode, but can
-  also be a pseudo major-mode to be referenced in
-  `yas-extra-modes', for example.
-
-`yas--table-hash'
-
-  A hash table (KEY . NAMEHASH), known as the \"keyhash\". KEY is
-  a string or a vector, where the former is the snippet's trigger
-  and the latter means it's a direct keybinding. NAMEHASH is yet
-  another hash of (NAME . TEMPLATE) where NAME is the snippet's
-  name and TEMPLATE is a `yas--template' object.
-
-`yas--table-direct-keymap'
-
-  A keymap for the snippets in this table that have direct
-  keybindings. This is kept in sync with the keyhash, i.e., all
-  the elements of the keyhash that are vectors appear here as
-  bindings to `yas-expand-from-keymap'.
-
-`yas--table-uuidhash'
-
-  A hash table mapping snippets uuid's to the same `yas--template'
-  objects. A snippet uuid defaults to the snippet's name.
-"
-  name
-  (hash (make-hash-table :test 'equal))
-  (uuidhash (make-hash-table :test 'equal))
-  (parents nil)
-  (direct-keymap (make-sparse-keymap)))
-
-(defun yas--get-template-by-uuid (mode uuid)
-  "Find the snippet template in MODE by its UUID."
-  (let* ((table (gethash mode yas--tables mode)))
-    (when table
-      (gethash uuid (yas--table-uuidhash table)))))
-
-;; Apropos storing/updating in TABLE, this works in two steps:
-;;
-;; 1. `yas--remove-template-by-uuid' removes any
-;;    keyhash-namehash-template mappings from TABLE, grabing the
-;;    snippet by its uuid. Also removes mappings from TABLE's
-;;    `yas--table-direct-keymap' (FIXME: and should probably take care
-;;    of potentially stale menu bindings right?.)
-;;
-;; 2. `yas--add-template' adds this all over again.
-;;
-;;    Create a new or add to an existing keyhash-namehash mapping.
-;;
-;;  For reference on understanding this, consider three snippet
-;;  definitions:
-;;
-;;  A:   # name: The Foo
-;;       # key: foo
-;;       # binding: C-c M-l
-;;
-;;  B:   # name: Mrs Foo
-;;       # key: foo
-;;
-;;  C:   # name: The Bar
-;;       # binding: C-c M-l
-;;
-;;  D:   # name: Baz
-;;       # key: baz
-;;
-;;  keyhash       namehashes(3)      yas--template structs(4)
-;;  -----------------------------------------------------
-;;                                            __________
-;;                                           /          \
-;;  "foo"      --->  "The Foo" --->  [yas--template A]   |
-;;                   "Mrs Foo" --->  [yas--template B]   |
-;;                                                      |
-;;  [C-c M-l]  --->  "The Foo" -------------------------/
-;;                   "The Bar" --->  [yas--template C]
-;;
-;;  "baz"      --->  "Baz"     --->  [yas--template D]
-;;
-;; Additionally, since uuid defaults to the name, we have a
-;; `yas--table-uuidhash' for TABLE
-;;
-;; uuidhash       yas--template structs
-;; -------------------------------
-;; "The Foo" ---> [yas--template A]
-;; "Mrs Foo" ---> [yas--template B]
-;; "The Bar" ---> [yas--template C]
-;; "Baz"     ---> [yas--template D]
-;;
-;; FIXME: the more I look at this data-structure the more I think I'm
-;; stupid. There has to be an easier way (but beware lots of code
-;; depends on this).
-;;
-(defun yas--remove-template-by-uuid (table uuid)
-  "Remove from TABLE a template identified by UUID."
-  (let ((template (gethash uuid (yas--table-uuidhash table))))
-    (when template
-      (let* ((name                (yas--template-name template))
-             (empty-keys          nil))
-        ;; Remove the name from each of the targeted namehashes
-        ;;
-        (maphash #'(lambda (k v)
-                     (let ((template (gethash name v)))
-                       (when (and template
-                                  (eq uuid (yas--template-uuid template)))
-                         (remhash name v)
-                         (when (zerop (hash-table-count v))
-                           (push k empty-keys)))))
-                 (yas--table-hash table))
-        ;; Remove the namehash themselves if they've become empty
-        ;;
-        (dolist (key empty-keys)
-          (when (vectorp key)
-            (define-key (yas--table-direct-keymap table) key nil))
-          (remhash key (yas--table-hash table)))
-
-        ;; Finally, remove the uuid from the uuidhash
-        ;;
-        (remhash uuid (yas--table-uuidhash table))))))
-
-(defun yas--add-template (table template)
-  "Store in TABLE the snippet template TEMPLATE.
-
-KEY can be a string (trigger key) of a vector (direct
-keybinding)."
-  (let ((name (yas--template-name template))
-        (key (yas--template-key template))
-        (keybinding (yas--template-keybinding template))
-        (menu-binding-pair (yas--template-menu-binding-pair-get-create 
template)))
-    (dolist (k (remove nil (list key keybinding)))
-      (puthash name
-               template
-               (or (gethash k
-                            (yas--table-hash table))
-                   (puthash k
-                            (make-hash-table :test 'equal)
-                            (yas--table-hash table))))
-      (when (vectorp k)
-        (define-key (yas--table-direct-keymap table) k 
'yas-expand-from-keymap)))
-
-    ;; Update TABLE's `yas--table-uuidhash'
-    (puthash (yas--template-uuid template)
-             template
-             (yas--table-uuidhash table))))
-
-(defun yas--update-template (table template)
-  "Add or update TEMPLATE in TABLE.
-
-Also takes care of adding and updating to the associated menu."
-  ;; Remove from table by uuid
-  ;;
-  (yas--remove-template-by-uuid table (yas--template-uuid template))
-  ;; Add to table again
-  ;;
-  (yas--add-template table template)
-  ;; Take care of the menu
-  ;;
-  (when yas-use-menu
-    (yas--update-template-menu table template)))
-
-(defun yas--update-template-menu (table template)
-  "Update every menu-related for TEMPLATE"
-  (let ((menu-binding-pair (yas--template-menu-binding-pair-get-create 
template))
-        (key (yas--template-key template))
-        (keybinding (yas--template-keybinding template)))
-    ;; The snippet might have changed name or keys, so update
-    ;; user-visible strings
-    ;;
-    (unless (eq (cdr menu-binding-pair) :none)
-      ;; the menu item name
-      ;;
-      (setf (cadar menu-binding-pair) (yas--template-name template))
-      ;; the :keys information (also visible to the user)
-      (setf (getf (cdr (car menu-binding-pair)) :keys)
-            (or (and keybinding (key-description keybinding))
-                (and key (concat key yas-trigger-symbol))))))
-  (unless (yas--template-menu-managed-by-yas-define-menu template)
-    (let ((menu-keymap
-           (yas--menu-keymap-get-create (yas--table-mode table)
-                                        (mapcar #'yas--table-mode
-                                                (yas--table-parents table))))
-          (group (yas--template-group template)))
-      ;; Remove from menu keymap
-      ;;
-      (assert menu-keymap)
-      (yas--delete-from-keymap menu-keymap (yas--template-uuid template))
-
-      ;; Add necessary subgroups as necessary.
-      ;;
-      (dolist (subgroup group)
-        (let ((subgroup-keymap (lookup-key menu-keymap (vector (make-symbol 
subgroup)))))
-          (unless (and subgroup-keymap
-                       (keymapp subgroup-keymap))
-            (setq subgroup-keymap (make-sparse-keymap))
-            (define-key menu-keymap (vector (make-symbol subgroup))
-              `(menu-item ,subgroup ,subgroup-keymap)))
-          (setq menu-keymap subgroup-keymap)))
-
-      ;; Add this entry to the keymap
-      ;;
-      (define-key menu-keymap
-        (vector (make-symbol (yas--template-uuid template)))
-        (car (yas--template-menu-binding-pair template))))))
-
-(defun yas--namehash-templates-alist (namehash)
-  (let (alist)
-    (maphash #'(lambda (k v)
-                 (push (cons k v) alist))
-             namehash)
-    alist))
-
-(defun yas--fetch (table key)
-  "Fetch templates in TABLE by KEY.
-
-Return a list of cons (NAME . TEMPLATE) where NAME is a
-string and TEMPLATE is a `yas--template' structure."
-  (let* ((keyhash (yas--table-hash table))
-         (namehash (and keyhash (gethash key keyhash))))
-    (when namehash
-      (yas--filter-templates-by-condition (yas--namehash-templates-alist 
namehash)))))
-
-
-;;; Filtering/condition logic
-
-(defun yas--eval-condition (condition)
-  (condition-case err
-      (save-excursion
-        (save-restriction
-          (save-match-data
-            (eval condition))))
-    (error (progn
-             (yas--message 1 "Error in condition evaluation: %s" 
(error-message-string err))
-             nil))))
-
-
-(defun yas--filter-templates-by-condition (templates)
-  "Filter the templates using the applicable condition.
-
-TEMPLATES is a list of cons (NAME . TEMPLATE) where NAME is a
-string and TEMPLATE is a `yas--template' structure.
-
-This function implements the rules described in
-`yas-buffer-local-condition'.  See that variables documentation."
-  (let ((requirement (yas--require-template-specific-condition-p)))
-    (if (eq requirement 'always)
-        templates
-      (remove-if-not #'(lambda (pair)
-                         (yas--template-can-expand-p
-                          (yas--template-condition (cdr pair)) requirement))
-                     templates))))
-
-(defun yas--require-template-specific-condition-p ()
-  "Decides if this buffer requests/requires snippet-specific
-conditions to filter out potential expansions."
-  (if (eq 'always yas-buffer-local-condition)
-      'always
-    (let ((local-condition (or (and (consp yas-buffer-local-condition)
-                                    (yas--eval-condition 
yas-buffer-local-condition))
-                               yas-buffer-local-condition)))
-      (when local-condition
-        (if (eq local-condition t)
-            t
-          (and (consp local-condition)
-               (eq 'require-snippet-condition (car local-condition))
-               (symbolp (cdr local-condition))
-               (cdr local-condition)))))))
-
-(defun yas--template-can-expand-p (condition requirement)
-  "Evaluates CONDITION and REQUIREMENT and returns a boolean"
-  (let* ((result (or (null condition)
-                     (yas--eval-condition condition))))
-    (cond ((eq requirement t)
-           result)
-          (t
-           (eq requirement result)))))
-
-(defun yas--all-parents (mode)
-  "Returns a list of all parent modes of MODE"
-  (let ((parents (gethash mode yas--parents)))
-    (append parents
-            (mapcan #'yas--all-parents parents))))
-
-(defun yas--table-templates (table)
-  (when table
-    (let ((acc (list)))
-      (maphash #'(lambda (key namehash)
-                   (maphash #'(lambda (name template)
-                                (push (cons name template) acc))
-                            namehash))
-               (yas--table-hash table))
-      (yas--filter-templates-by-condition acc))))
-
-(defun yas--current-key ()
-  "Get the key under current position. A key is used to find
-the template of a snippet in the current snippet-table."
-  (let ((start (point))
-        (end (point))
-        (syntaxes yas-key-syntaxes)
-        syntax
-        done
-        templates)
-    (while (and (not done) syntaxes)
-      (setq syntax (car syntaxes))
-      (setq syntaxes (cdr syntaxes))
-      (save-excursion
-        (skip-syntax-backward syntax)
-        (setq start (point)))
-      (setq templates
-            (mapcan #'(lambda (table)
-                        (yas--fetch table (buffer-substring-no-properties 
start end)))
-                    (yas--get-snippet-tables)))
-      (if templates
-          (setq done t)
-        (setq start end)))
-    (list templates
-          start
-          end)))
-
-
-(defun yas--table-all-keys (table)
-  (when table
-    (let ((acc))
-      (maphash #'(lambda (key namehash)
-                   (when (yas--filter-templates-by-condition 
(yas--namehash-templates-alist namehash))
-                     (push key acc)))
-               (yas--table-hash table))
-      acc)))
-
-(defun yas--table-mode (table)
-  (intern (yas--table-name table)))
-
-
-;;; Internal functions:
-
-(defun yas--real-mode? (mode)
-  "Try to find out if MODE is a real mode. The MODE bound to
-a function (like `c-mode') is considered real mode. Other well
-known mode like `ruby-mode' which is not part of Emacs might
-not bound to a function until it is loaded. So yasnippet keeps
-a list of modes like this to help the judgement."
-  (or (fboundp mode)
-      (find mode yas--known-modes)))
-
-(defun yas--eval-lisp (form)
-  "Evaluate FORM and convert the result to string."
-  (let ((retval (catch 'yas--exception
-                  (condition-case err
-                      (save-excursion
-                        (save-restriction
-                          (save-match-data
-                            (widen)
-                            (let ((result (eval form)))
-                              (when result
-                                (format "%s" result))))))
-                    (error (if yas-good-grace
-                               (yas--format "elisp error! %s" 
(error-message-string err))
-                             (error (yas--format "elisp error: %s"
-                                            (error-message-string err)))))))))
-    (when (and (consp retval)
-               (eq 'yas--exception (car retval)))
-      (error (cdr retval)))
-    retval))
-
-(defun yas--eval-lisp-no-saves (form)
-  (condition-case err
-      (eval form)
-    (error (if yas-good-grace
-               (yas--format "elisp error! %s" (error-message-string err))
-             (error (yas--format "elisp error: %s"
-                            (error-message-string err)))))))
-
-(defun yas--read-lisp (string &optional nil-on-error)
-  "Read STRING as a elisp expression and return it.
-
-In case STRING in an invalid expression and NIL-ON-ERROR is nil,
-return an expression that when evaluated will issue an error."
-  (condition-case err
-      (read string)
-    (error (and (not nil-on-error)
-                `(error (error-message-string ,err))))))
-
-(defun yas--read-keybinding (keybinding)
-  "Read KEYBINDING as a snippet keybinding, return a vector."
-  (when (and keybinding
-             (not (string-match "keybinding" keybinding)))
-    (condition-case err
-        (let ((res (or (and (string-match "^\\[.*\\]$" keybinding)
-                            (read keybinding))
-                       (read-kbd-macro keybinding 'need-vector))))
-          res)
-      (error
-       (yas--message 3 "warning: keybinding \"%s\" invalid since %s."
-                keybinding (error-message-string err))
-       nil))))
-
-(defvar yas-extra-modes nil
-  "If non-nil, also lookup snippets for this/these modes.
-
-Can be a symbol or a list of symbols.
-
-This variable probably makes more sense as buffer-local, so
-ensure your use `make-local-variable' when you set it.")
-(defun yas-extra-modes ()
-  (if (listp yas-extra-modes) yas-extra-modes (list yas-extra-modes)))
-(defvaralias 'yas/mode-symbol 'yas-extra-modes)
-
-(defun yas--table-get-create (mode)
-  "Get or create the snippet table corresponding to MODE."
-  (let ((table (gethash mode
-                        yas--tables)))
-    (unless table
-      (setq table (yas--make-snippet-table (symbol-name mode)))
-      (puthash mode table yas--tables)
-      (push (cons (intern (format "yas--direct-%s" mode))
-                  (yas--table-direct-keymap table))
-            yas--direct-keymaps))
-    table))
-
-(defun yas--get-snippet-tables ()
-  "Get snippet tables for current buffer.
-
-Return a list of `yas--table' objects. The list of modes to
-consider is returned by `yas--modes-to-activate'"
-  (remove nil
-          (mapcar #'(lambda (mode-name)
-                      (gethash mode-name yas--tables))
-                  (yas--modes-to-activate))))
-
-(defun yas--menu-keymap-get-create (mode &optional parents)
-  "Get or create the menu keymap for MODE and its PARENTS.
-
-This may very well create a plethora of menu keymaps and arrange
-them all in `yas--menu-table'"
-  (let* ((menu-keymap (or (gethash mode yas--menu-table)
-                          (puthash mode (make-sparse-keymap) 
yas--menu-table))))
-    (mapc #'yas--menu-keymap-get-create parents)
-    (define-key yas--minor-mode-menu (vector mode)
-        `(menu-item ,(symbol-name mode) ,menu-keymap
-                    :visible (yas--show-menu-p ',mode)))
-    menu-keymap))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Template-related and snippet loading functions
-
-(defun yas--parse-template (&optional file)
-  "Parse the template in the current buffer.
-
-Optional FILE is the absolute file name of the file being
-parsed.
-
-Optional GROUP is the group where the template is to go,
-otherwise we attempt to calculate it from FILE.
-
-Return a snippet-definition, i.e. a list
-
- (KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING UUID)
-
-If the buffer contains a line of \"# --\" then the contents above
-this line are ignored. Directives can set most of these with the syntax:
-
-# directive-name : directive-value
-
-Here's a list of currently recognized directives:
-
- * type
- * name
- * contributor
- * condition
- * group
- * key
- * expand-env
- * binding
- * uuid"
-  (goto-char (point-min))
-  (let* ((type 'snippet)
-         (name (and file
-                    (file-name-nondirectory file)))
-         (key nil)
-         template
-         bound
-         condition
-         (group (and file
-                     (yas--calculate-group file)))
-         expand-env
-         binding
-         uuid)
-    (if (re-search-forward "^# --\n" nil t)
-        (progn (setq template
-                     (buffer-substring-no-properties (point)
-                                                     (point-max)))
-               (setq bound (point))
-               (goto-char (point-min))
-               (while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*\\)$" 
bound t)
-                 (when (string= "uuid" (match-string-no-properties 1))
-                   (setq uuid (match-string-no-properties 2)))
-                 (when (string= "type" (match-string-no-properties 1))
-                   (setq type (if (string= "command" 
(match-string-no-properties 2))
-                                  'command
-                                'snippet)))
-                 (when (string= "key" (match-string-no-properties 1))
-                   (setq key (match-string-no-properties 2)))
-                 (when (string= "name" (match-string-no-properties 1))
-                   (setq name (match-string-no-properties 2)))
-                 (when (string= "condition" (match-string-no-properties 1))
-                   (setq condition (yas--read-lisp (match-string-no-properties 
2))))
-                 (when (string= "group" (match-string-no-properties 1))
-                   (setq group (match-string-no-properties 2)))
-                 (when (string= "expand-env" (match-string-no-properties 1))
-                   (setq expand-env (yas--read-lisp 
(match-string-no-properties 2)
-                                                   'nil-on-error)))
-                 (when (string= "binding" (match-string-no-properties 1))
-                   (setq binding (match-string-no-properties 2)))))
-      (setq template
-            (buffer-substring-no-properties (point-min) (point-max))))
-    (unless (or key binding)
-      (setq key (and file (file-name-nondirectory file))))
-    (when (eq type 'command)
-      (setq template (yas--read-lisp (concat "(progn" template ")"))))
-    (when group
-      (setq group (split-string group "\\.")))
-    (list key template name condition group expand-env file binding uuid)))
-
-(defun yas--calculate-group (file)
-  "Calculate the group for snippet file path FILE."
-  (let* ((dominating-dir (locate-dominating-file file
-                                                 ".yas-make-groups"))
-         (extra-path (and dominating-dir
-                          (replace-regexp-in-string (concat "^"
-                                                            (expand-file-name 
dominating-dir))
-                                                    ""
-                                                    (expand-file-name file))))
-         (extra-dir (and extra-path
-                         (file-name-directory extra-path)))
-         (group (and extra-dir
-                     (replace-regexp-in-string "/"
-                                               "."
-                                               (directory-file-name 
extra-dir)))))
-    group))
-
-(defun yas--subdirs (directory &optional filep)
-  "Return subdirs or files of DIRECTORY according to FILEP."
-  (remove-if (lambda (file)
-               (or (string-match "^\\."
-                                 (file-name-nondirectory file))
-                   (string-match "^#.*#$"
-                                 (file-name-nondirectory file))
-                   (string-match "~$"
-                                 (file-name-nondirectory file))
-                   (if filep
-                       (file-directory-p file)
-                     (not (file-directory-p file)))))
-             (directory-files directory t)))
-
-(defun yas--make-menu-binding (template)
-  (let ((mode (yas--table-mode (yas--template-table template))))
-    `(lambda () (interactive) (yas--expand-or-visit-from-menu ',mode 
,(yas--template-uuid template)))))
-
-(defun yas--expand-or-visit-from-menu (mode uuid)
-  (let* ((table (yas--table-get-create mode))
-         (yas--current-template (and table
-                                    (gethash uuid (yas--table-uuidhash 
table)))))
-    (when yas--current-template
-      (if yas-visit-from-menu
-          (yas--visit-snippet-file-1 yas--current-template)
-        (let ((where (if (region-active-p)
-                         (cons (region-beginning) (region-end))
-                       (cons (point) (point)))))
-          (yas-expand-snippet (yas--template-content yas--current-template)
-                              (car where)
-                              (cdr where)
-                              (yas--template-expand-env 
yas--current-template)))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Popping up for keys and templates
-;;
-(defvar yas--x-pretty-prompt-templates nil
-  "If non-nil, attempt to prompt for templates like TextMate.")
-
-
-(defun yas--prompt-for-template (templates &optional prompt)
-  "Interactively choose a template from the list TEMPLATES.
-
-TEMPLATES is a list of `yas--template'."
-  (when templates
-    (setq templates
-          (sort templates #'(lambda (t1 t2)
-                              (< (length (yas--template-name t1))
-                                 (length (yas--template-name t2))))))
-    (if yas--x-pretty-prompt-templates
-        (yas--x-pretty-prompt-templates "Choose a snippet" templates)
-      (some #'(lambda (fn)
-                (funcall fn (or prompt "Choose a snippet: ")
-                         templates
-                         #'yas--template-name))
-            yas-prompt-functions))))
-
-(defun yas--prompt-for-keys (keys &optional prompt)
-  "Interactively choose a template key from the list KEYS."
-  (when keys
-    (some #'(lambda (fn)
-              (funcall fn (or prompt "Choose a snippet key: ") keys))
-          yas-prompt-functions)))
-
-(defun yas--prompt-for-table (tables &optional prompt)
-  (when tables
-    (some #'(lambda (fn)
-              (funcall fn (or prompt "Choose a snippet table: ")
-                       tables
-                       #'yas--table-name))
-          yas-prompt-functions)))
-
-(defun yas-x-prompt (prompt choices &optional display-fn)
-  "Display choices in a x-window prompt."
-  ;; FIXME: HACK: if we notice that one of the objects in choices is
-  ;; actually a `yas--template', defer to `yas--x-prompt-pretty-templates'
-  ;;
-  ;; This would be better implemented by passing CHOICES as a
-  ;; strucutred tree rather than a list. Modifications would go as far
-  ;; up as `yas--all-templates' I think.
-  ;;
-  (when (and window-system choices)
-    (let ((chosen
-           (let (menu d) ;; d for display
-             (dolist (c choices)
-               (setq d (or (and display-fn (funcall display-fn c))
-                           c))
-               (cond ((stringp d)
-                      (push (cons (concat "   " d) c) menu))
-                     ((listp d)
-                      (push (car d) menu))))
-             (setq menu (list prompt (push "title" menu)))
-             (x-popup-menu (if (fboundp 'posn-at-point)
-                               (let ((x-y (posn-x-y (posn-at-point (point)))))
-                                 (list (list (+ (car x-y) 10)
-                                             (+ (cdr x-y) 20))
-                                       (selected-window)))
-                             t)
-                           menu))))
-      (or chosen
-          (keyboard-quit)))))
-
-(defun yas--x-pretty-prompt-templates (prompt templates)
-  "Display TEMPLATES, grouping neatly by table name."
-  (let ((organized (make-hash-table :test #'equal))
-        menu
-        more-than-one-table
-        prefix)
-    (dolist (tl templates)
-      (puthash (yas--template-table tl)
-               (cons tl
-                     (gethash (yas--template-table tl) organized))
-               organized))
-    (setq more-than-one-table (> (hash-table-count organized) 1))
-    (setq prefix (if more-than-one-table
-                     "   " ""))
-    (if more-than-one-table
-        (maphash #'(lambda (table templates)
-                     (push (yas--table-name table) menu)
-                     (dolist (tl templates)
-                       (push (cons (concat prefix (yas--template-name tl)) tl) 
menu))) organized)
-      (setq menu (mapcar #'(lambda (tl) (cons (concat prefix 
(yas--template-name tl)) tl)) templates)))
-
-    (setq menu (nreverse menu))
-    (or (x-popup-menu (if (fboundp 'posn-at-point)
-                          (let ((x-y (posn-x-y (posn-at-point (point)))))
-                            (list (list (+ (car x-y) 10)
-                                        (+ (cdr x-y) 20))
-                                  (selected-window)))
-                        t)
-                      (list prompt (push "title" menu)))
-        (keyboard-quit))))
-
-(defun yas-ido-prompt (prompt choices &optional display-fn)
-  (when (and (fboundp 'ido-completing-read)
-            (or (>= emacs-major-version 24)
-                ido-mode))
-    (yas-completing-prompt prompt choices display-fn #'ido-completing-read)))
-
-(eval-when-compile (require 'dropdown-list nil t))
-(defun yas-dropdown-prompt (prompt choices &optional display-fn)
-  (when (featurep 'dropdown-list)
-    (let (formatted-choices
-          filtered-choices
-          d
-          n)
-      (dolist (choice choices)
-        (setq d (or (and display-fn (funcall display-fn choice))
-                      choice))
-        (when (stringp d)
-          (push d formatted-choices)
-          (push choice filtered-choices)))
-
-      (setq n (and formatted-choices (dropdown-list formatted-choices)))
-      (if n
-          (nth n filtered-choices)
-        (keyboard-quit)))))
-
-(defun yas-completing-prompt (prompt choices &optional display-fn 
completion-fn)
-  (let (formatted-choices
-        filtered-choices
-        chosen
-        d
-        (completion-fn (or completion-fn
-                           #'completing-read)))
-    (dolist (choice choices)
-      (setq d (or (and display-fn (funcall display-fn choice))
-                    choice))
-      (when (stringp d)
-        (push d formatted-choices)
-        (push choice filtered-choices)))
-    (setq chosen (and formatted-choices
-                      (funcall completion-fn prompt
-                               formatted-choices
-                               nil
-                               'require-match
-                               nil
-                               nil)))
-    (let ((position (or (and chosen
-                             (position chosen formatted-choices :test 
#'string=))
-                        0)))
-      (nth position filtered-choices))))
-
-(defun yas-no-prompt (prompt choices &optional display-fn)
-  (first choices))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Loading snippets from files
-;;
-(defun yas--load-yas-setup-file (file)
-  (load file 'noerror))
-
-(defun yas-load-directory (top-level-dir &optional use-jit)
-  "Load snippets in directory hierarchy TOP-LEVEL-DIR.
-
-Below TOP-LEVEL-DIR each directory should be a mode name.
-
-Optional USE-JIT use jit-loading of snippets."
-  (interactive "DSelect the root directory: ")
-  (unless yas-snippet-dirs
-    (setq yas-snippet-dirs top-level-dir))
-  (dolist (dir (yas--subdirs top-level-dir))
-    (let* ((major-mode-and-parents (yas--compute-major-mode-and-parents
-                                    (concat dir "/dummy")))
-           (mode-sym (car major-mode-and-parents))
-           (parents (cdr major-mode-and-parents)))
-      ;; Attention: The parents and the menus are already defined
-      ;; here, even if the snippets are later jit-loaded.
-      ;;
-      ;; * We need to know the parents at this point since entering a
-      ;;   given mode should jit load for its parents
-      ;;   immediately. This could be reviewed, the parents could be
-      ;;   discovered just-in-time-as well
-      ;;
-      ;; * We need to create the menus here to support the `full'
-      ;;   option to `yas-use-menu' (all known snippet menus are shown to the 
user)
-      ;;
-      (yas--define-parents mode-sym parents)
-      (yas--menu-keymap-get-create mode-sym)
-      (let ((form `(yas--load-directory-1 ,dir
-                                         ',mode-sym
-                                         ',parents)))
-        (if use-jit
-            (yas--schedule-jit mode-sym form)
-            (eval form)))))
-  (when (interactive-p)
-    (yas--message 3 "Loaded snippets from %s." top-level-dir)))
-
-(defun yas--load-directory-1 (directory mode-sym parents &optional 
no-compiled-snippets)
-  "Recursively load snippet templates from DIRECTORY."
-  (unless (file-exists-p (concat directory "/" ".yas-skip"))
-    (if (and (not no-compiled-snippets)
-             (progn (yas--message 2 "Loading compiled snippets from %s" 
directory) t)
-             (load (expand-file-name ".yas-compiled-snippets" directory) 
'noerror (<= yas-verbosity 3)))
-      (yas--message 2 "Loading snippet files from %s" directory)
-      (yas--load-directory-2 directory mode-sym))))
-
-(defun yas--load-directory-2 (directory mode-sym)
-  ;; Load .yas-setup.el files wherever we find them
-  ;;
-  (yas--load-yas-setup-file (expand-file-name ".yas-setup" directory))
-  (let* ((default-directory directory)
-         (snippet-defs nil))
-    ;; load the snippet files
-    ;;
-    (with-temp-buffer
-      (dolist (file (yas--subdirs directory 'no-subdirs-just-files))
-        (when (file-readable-p file)
-          (insert-file-contents file nil nil nil t)
-          (push (yas--parse-template file)
-                snippet-defs))))
-    (when snippet-defs
-      (yas-define-snippets mode-sym
-                           snippet-defs))
-    ;; now recurse to a lower level
-    ;;
-    (dolist (subdir (yas--subdirs directory))
-      (yas--load-directory-2 subdir
-                            mode-sym))))
-
-(defun yas--load-snippet-dirs (&optional nojit)
-  "Reload the directories listed in `yas-snippet-dirs' or
-   prompt the user to select one."
-  (let (errors)
-    (if yas-snippet-dirs
-        (dolist (directory (reverse (yas-snippet-dirs)))
-          (cond ((file-directory-p directory)
-                 (yas-load-directory directory (not nojit))
-                 (if nojit
-                     (yas--message 3 "Loaded %s" directory)
-                   (yas--message 3 "Prepared just-in-time loading for %s" 
directory)))
-                (t
-                 (push (yas--message 0 "Check your `yas-snippet-dirs': %s is 
not a directory" directory) errors))))
-      (call-interactively 'yas-load-directory))
-    errors))
-
-(defun yas-reload-all (&optional interactive)
-  "Reload all snippets and rebuild the YASnippet menu.
-
-When called interactively force immediate reload of all known
-snippets under `yas-snippet-dirs', otherwise use just-in-time
-loading."
-  (interactive "p")
-  (catch 'abort
-    (let ((errors)
-          (snippet-editing-buffers
-           (remove-if-not #'(lambda (buffer)
-                              (with-current-buffer buffer 
yas--editing-template))
-                          (buffer-list))))
-      ;; Warn if there are buffers visiting snippets, since reloading will 
break
-      ;; any on-line editing of those buffers.
-      ;;
-      (when snippet-editing-buffers
-          (if interactive
-              (if (y-or-n-p "Some buffers editing live snippets, close them 
and proceed with reload?")
-                  (mapc #'kill-buffer snippet-editing-buffers)
-                (yas--message 1 "Aborted reload...")
-                (throw 'abort nil))
-            ;; in a non-interactive use, at least set
-            ;; `yas--editing-template' to nil, make it guess it next time 
around
-            (mapc #'(lambda (buffer) (setq yas--editing-template nil)) 
(buffer-list))))
-
-      ;; Empty all snippet tables, parenting info and all menu tables
-      ;;
-      (setq yas--tables (make-hash-table))
-      (setq yas--parents (make-hash-table))
-      (setq yas--menu-table (make-hash-table))
-
-      ;; Cancel all pending 'yas--scheduled-jit-loads'
-      ;;
-      (setq yas--scheduled-jit-loads (make-hash-table))
-
-      ;; Init the `yas-minor-mode-map', taking care not to break the
-      ;; menu....
-      ;;
-      (setcdr yas-minor-mode-map (cdr (yas--init-minor-keymap)))
-
-      ;; Reload the directories listed in `yas-snippet-dirs' or prompt
-      ;; the user to select one.
-      ;;
-      (setq errors (yas--load-snippet-dirs interactive))
-      ;; Reload the direct keybindings
-      ;;
-      (yas-direct-keymaps-reload)
-      ;; Reload the trigger-key (shoudn't be needed, but see issue #237)
-      ;;
-      (yas--trigger-key-reload)
-
-      (yas--message 3 "Reloaded everything%s...%s."
-                   (if interactive "" " (snippets will load just-in-time)")
-                   (if errors " (some errors, check *Messages*)" "")))))
-
-(defun yas--load-pending-jits ()
-  (when yas-minor-mode
-    (dolist (mode (yas--modes-to-activate))
-      (let ((forms (reverse (gethash mode yas--scheduled-jit-loads))))
-        ;; must reverse to maintain coherence with `yas-snippet-dirs'
-        (dolist (form forms)
-          (yas--message  3 "Loading for `%s', just-in-time: %s!" mode form)
-          (eval form))
-        (remhash mode yas--scheduled-jit-loads)))))
-
-;; (when (<= emacs-major-version 22)
-;;   (add-hook 'after-change-major-mode-hook 'yas--load-pending-jits))
-
-(defun yas--quote-string (string)
-  "Escape and quote STRING.
-foo\"bar\\! -> \"foo\\\"bar\\\\!\""
-  (concat "\""
-          (replace-regexp-in-string "[\\\"]"
-                                    "\\\\\\&"
-                                    string
-                                    t)
-          "\""))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Snippet compilation function
-
-(defun yas--initialize ()
-  "For backward compatibility, enable `yas-minor-mode' globally"
-  (yas-global-mode 1))
-
-(defun yas-compile-directory (top-level-dir)
-  "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR.
-
-This works by stubbing a few functions, then calling
-`yas-load-directory'."
-  (interactive "DTop level snippet directory?")
-  (flet ((yas--load-yas-setup-file
-          (file)
-          (let ((elfile (concat file ".el")))
-            (when (file-exists-p elfile)
-              (insert ";;; .yas-setup.el support file if any:\n;;;\n")
-              (insert-file-contents elfile)
-              (end-of-buffer)
-              )))
-         (yas-define-snippets
-          (mode snippets)
-          (insert ";;; Snippet definitions:\n;;;\n")
-          (let ((literal-snippets (list))
-                (print-length nil))
-            (dolist (snippet snippets)
-              (let ((key                    (first   snippet))
-                    (template-content       (second  snippet))
-                    (name                   (third   snippet))
-                    (condition              (fourth  snippet))
-                    (group                  (fifth   snippet))
-                    (expand-env             (sixth   snippet))
-                    (file                   nil) ;; (seventh snippet)) ;; omit 
on purpose
-                    (binding                (eighth  snippet))
-                    (uuid                    (ninth   snippet)))
-                (push `(,key
-                        ,template-content
-                        ,name
-                        ,condition
-                        ,group
-                        ,expand-env
-                        ,file
-                        ,binding
-                        ,uuid)
-                      literal-snippets)))
-            (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
-            (insert "\n\n")))
-         (yas--load-directory-1
-          (dir mode parents &rest ignore)
-          (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
-            (with-temp-file output-file
-              (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
-              (yas--load-directory-2 dir mode)
-              (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
-    (yas-load-directory top-level-dir nil)))
-
-(defun yas-recompile-all ()
-  "Compile every dir in `yas-snippet-dirs'."
-  (interactive)
-  (mapc #'yas-compile-directory (yas-snippet-dirs)))
-
-
-;;; JIT loading
-;;;
-
-(defvar yas--scheduled-jit-loads (make-hash-table)
-  "Alist of mode-symbols to forms to be evaled when `yas-minor-mode' kicks 
in.")
-
-(defun yas--schedule-jit (mode form)
-  (puthash mode
-           (cons form
-                 (gethash mode yas--scheduled-jit-loads))
-           yas--scheduled-jit-loads))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Some user level functions
-;;;
-
-(defun yas-about ()
-  (interactive)
-  (message (concat "yasnippet (version "
-                   yas--version
-                   ") -- pluskid <address@hidden>/joaotavora 
<address@hidden>")))
-
-(defun yas--define-parents (mode parents)
-  "Add PARENTS to the list of MODE's parents"
-  (puthash mode (remove-duplicates
-                 (append parents
-                         (gethash mode yas--parents)))
-           yas--parents))
-
-(defun yas-define-snippets (mode snippets)
-  "Define SNIPPETS for MODE.
-
-SNIPPETS is a list of snippet definitions, each taking the
-following form
-
- (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
-
-Within these, only KEY and TEMPLATE are actually mandatory.
-
-TEMPLATE might be a lisp form or a string, depending on whether
-this is a snippet or a snippet-command.
-
-CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
-been `yas--read-lisp'-ed and will eventually be
-`yas--eval-lisp'-ed.
-
-The remaining elements are strings.
-
-FILE is probably of very little use if you're programatically
-defining snippets.
-
-UUID is the snippets \"unique-id\". Loading a second snippet file
-with the same uuid replaced the previous snippet.
-
-You can use `yas--parse-template' to return such lists based on
-the current buffers contents."
-  (let ((snippet-table (yas--table-get-create mode))
-        (template nil))
-    (dolist (snippet snippets)
-      (setq template (yas-define-snippets-1 snippet
-                                            snippet-table)))
-    template))
-
-(defun yas-define-snippets-1 (snippet snippet-table)
-  "Helper for `yas-define-snippets'."
-  ;; X) Calculate some more defaults on the values returned by
-  ;; `yas--parse-template'.
-  ;;
-  (let* ((file (seventh snippet))
-         (key (car snippet))
-         (name (or (third snippet)
-                   (and file
-                        (file-name-directory file))))
-         (condition (fourth snippet))
-         (group (fifth snippet))
-         (keybinding (yas--read-keybinding (eighth snippet)))
-         (uuid (or (ninth snippet)
-                  name))
-         (template (or (gethash uuid (yas--table-uuidhash snippet-table))
-                       (yas--make-blank-template))))
-    ;; X) populate the template object
-    ;;
-    (yas--populate-template template
-                           :table       snippet-table
-                           :key         key
-                           :content     (second snippet)
-                           :name        (or name key)
-                           :group       group
-                           :condition   condition
-                           :expand-env  (sixth snippet)
-                           :file        (seventh snippet)
-                           :keybinding  keybinding
-                           :uuid         uuid)
-    ;; X) Update this template in the appropriate table. This step
-    ;;    also will take care of adding the key indicators in the
-    ;;    templates menu entry, if any
-    ;;
-    (yas--update-template snippet-table template)
-    ;; X) Return the template
-    ;;
-    ;;
-    template))
-
-
-;;; Apropos snippet menu:
-;;
-;; The snippet menu keymaps are store by mode in hash table called
-;; `yas--menu-table'. They are linked to the main menu in
-;; `yas--menu-keymap-get-create' and are initially created empty,
-;; reflecting the table hierarchy.
-;;
-;; They can be populated in two mutually exclusive ways: (1) by
-;; reading `yas--template-group', which in turn is populated by the "#
-;; group:" directives of the snippets or the ".yas-make-groups" file
-;; or (2) by using a separate `yas-define-menu' call, which declares a
-;; menu structure based on snippets uuids.
-;;
-;; Both situations are handled in `yas--update-template-menu', which
-;; uses the predicate `yas--template-menu-managed-by-yas-define-menu'
-;; that can tell between the two situations.
-;;
-;; Note:
-;;
-;; * if `yas-define-menu' is used it must run before
-;;   `yas-define-snippets' and the UUIDS must match, otherwise we get
-;;   duplicate entries. The `yas--template' objects are created in
-;;   `yas-define-menu', holding nothing but the menu entry,
-;;   represented by a pair of ((menu-item NAME :keys KEYS) TYPE) and
-;;   stored in `yas--template-menu-binding-pair'. The (menu-item ...)
-;;   part is then stored in the menu keymap itself which make the item
-;;   appear to the user. These limitations could probably be revised.
-;;
-;; * The `yas--template-perm-group' slot is only used in
-;;   `yas-describe-tables'.
-;;
-(defun yas--template-menu-binding-pair-get-create (template &optional type)
-  "Get TEMPLATE's menu binding or assign it a new one.
-
-TYPE may be `:stay', signalling this menu binding should be
-static in the menu."
-  (or (yas--template-menu-binding-pair template)
-      (let ((key (yas--template-key template))
-            (keybinding (yas--template-keybinding template)))
-        (setf (yas--template-menu-binding-pair template)
-              (cons `(menu-item ,(or (yas--template-name template)
-                                     (yas--template-uuid template))
-                                ,(yas--make-menu-binding template)
-                                :keys ,nil)
-                    type)))))
-(defun yas--template-menu-managed-by-yas-define-menu (template)
-  "Non-nil if TEMPLATE's menu entry was included in a `yas-define-menu' call."
-  (cdr (yas--template-menu-binding-pair template)))
-
-
-(defun yas--show-menu-p (mode)
-  (cond ((eq yas-use-menu 'abbreviate)
-         (find mode
-               (mapcar #'(lambda (table)
-                           (yas--table-mode table))
-                       (yas--get-snippet-tables))))
-        ((eq yas-use-menu 'full)
-         t)
-        ((eq yas-use-menu t)
-         t)))
-
-(defun yas--delete-from-keymap (keymap uuid)
-  "Recursively delete items with UUID from KEYMAP and its submenus."
-
-  ;; XXX: This used to skip any submenus named \"parent mode\"
-  ;;
-  ;; First of all, recursively enter submenus, i.e. the tree is
-  ;; searched depth first so that stale submenus can be found in the
-  ;; higher passes.
-  ;;
-  (mapc #'(lambda (item)
-            (when (and (listp (cdr item))
-                       (keymapp (third (cdr item))))
-              (yas--delete-from-keymap (third (cdr item)) uuid)))
-        (rest keymap))
-  ;; Set the uuid entry to nil
-  ;;
-  (define-key keymap (vector (make-symbol uuid)) nil)
-  ;; Destructively modify keymap
-  ;;
-  (setcdr keymap (delete-if #'(lambda (item)
-                                (or (null (cdr item))
-                                    (and (keymapp (third (cdr item)))
-                                         (null (cdr (third (cdr item)))))))
-                            (rest keymap))))
-
-(defun yas-define-menu (mode menu &optional omit-items)
-  "Define a snippet menu for MODE according to MENU, ommitting OMIT-ITEMS.
-
-MENU is a list, its elements can be:
-
-- (yas-item UUID) : Creates an entry the snippet identified with
-  UUID. The menu entry for a snippet thus identified is
-  permanent, i.e. it will never move (be reordered) in the menu.
-
-- (yas-separator) : Creates a separator
-
-- (yas-submenu NAME SUBMENU) : Creates a submenu with NAME,
-  SUBMENU has the same form as MENU. NAME is also added to the
-  list of groups of the snippets defined thereafter.
-
-OMIT-ITEMS is a list of snippet uuid's that will always be
-ommited from MODE's menu, even if they're manually loaded.
-
-This function does nothing if `yas-use-menu' is nil.
-"
-  (when yas-use-menu
-    (let* ((table (yas--table-get-create mode))
-           (hash (yas--table-uuidhash table)))
-      (yas--define-menu-1 table
-                          (yas--menu-keymap-get-create mode)
-                          menu
-                          hash)
-      (dolist (uuid omit-items)
-        (let ((template (or (gethash uuid hash)
-                            (yas--populate-template (puthash uuid
-                                                             
(yas--make-blank-template)
-                                                             hash)
-                                                    :table table
-                                                    :uuid uuid))))
-          (setf (yas--template-menu-binding-pair template) (cons nil 
:none)))))))
-
-(defun yas--define-menu-1 (table menu-keymap menu uuidhash &optional 
group-list)
-  (dolist (e (reverse menu))
-    (cond ((eq (first e) 'yas-item)
-           (let ((template (or (gethash (second e) uuidhash)
-                               (yas--populate-template (puthash (second e)
-                                                               
(yas--make-blank-template)
-                                                               uuidhash)
-                                                      :table table
-                                                      :perm-group group-list
-                                                      :uuid (second e)))))
-             (define-key menu-keymap (vector (gensym))
-               (car (yas--template-menu-binding-pair-get-create template 
:stay)))))
-          ((eq (first e) 'yas-submenu)
-           (let ((subkeymap (make-sparse-keymap)))
-             (define-key menu-keymap (vector (gensym))
-               `(menu-item ,(second e) ,subkeymap))
-             (yas--define-menu-1 table
-                                subkeymap
-                                (third e)
-                                uuidhash
-                                (append group-list (list (second e))))))
-          ((eq (first e) 'yas-separator)
-           (define-key menu-keymap (vector (gensym))
-             '(menu-item "----")))
-          (t
-           (yas--message 3 "Don't know anything about menu entry %s" (first 
e))))))
-
-(defun yas--define (mode key template &optional name condition group)
-  "Define a snippet.  Expanding KEY into TEMPLATE.
-
-NAME is a description to this template.  Also update the menu if
-`yas-use-menu' is t.  CONDITION is the condition attached to
-this snippet.  If you attach a condition to a snippet, then it
-will only be expanded when the condition evaluated to non-nil."
-  (yas-define-snippets mode
-                       (list (list key template name condition group))))
-
-(defun yas-hippie-try-expand (first-time?)
-  "Integrate with hippie expand.  Just put this function in
-`hippie-expand-try-functions-list'."
-  (when yas-minor-mode
-    (if (not first-time?)
-        (let ((yas-fallback-behavior 'return-nil))
-          (yas-expand))
-      (undo 1)
-      nil)))
-
-
-;;; Apropos condition-cache:
-;;;
-;;;
-;;;
-;;;
-(defvar yas--condition-cache-timestamp nil)
-(defmacro yas-define-condition-cache (func doc &rest body)
-  "Define a function FUNC with doc DOC and body BODY, BODY is
-executed at most once every snippet expansion attempt, to check
-expansion conditions.
-
-It doesn't make any sense to call FUNC programatically."
-  `(defun ,func () ,(if (and doc
-                             (stringp doc))
-                        (concat doc
-"\n\nFor use in snippets' conditions. Within each
-snippet-expansion routine like `yas-expand', computes actual
-value for the first time then always returns a cached value.")
-                      (setq body (cons doc body))
-                      nil)
-     (let ((timestamp-and-value (get ',func 'yas--condition-cache)))
-       (if (equal (car timestamp-and-value) yas--condition-cache-timestamp)
-           (cdr timestamp-and-value)
-         (let ((new-value (progn
-                            ,@body
-                            )))
-           (put ',func 'yas--condition-cache (cons 
yas--condition-cache-timestamp new-value))
-           new-value)))))
-
-(defalias 'yas-expand 'yas-expand-from-trigger-key)
-(defun yas-expand-from-trigger-key (&optional field)
-  "Expand a snippet before point.
-
-If no snippet expansion is possible, fall back to the behaviour
-defined in `yas-fallback-behavior'.
-
-Optional argument FIELD is for non-interactive use and is an
-object satisfying `yas--field-p' to restrict the expansion to."
-  (interactive)
-  (setq yas--condition-cache-timestamp (current-time))
-  (let (templates-and-pos)
-    (unless (and yas-expand-only-for-last-commands
-                 (not (member last-command yas-expand-only-for-last-commands)))
-      (setq templates-and-pos (if field
-                                  (save-restriction
-                                    (narrow-to-region (yas--field-start field)
-                                                      (yas--field-end field))
-                                    (yas--current-key))
-                                (yas--current-key))))
-    (if (and templates-and-pos
-             (first templates-and-pos))
-        (yas--expand-or-prompt-for-template (first templates-and-pos)
-                                           (second templates-and-pos)
-                                           (third templates-and-pos))
-      (yas--fallback 'trigger-key))))
-
-(defun yas-expand-from-keymap ()
-  "Directly expand some snippets, searching `yas--direct-keymaps'.
-
-If expansion fails, execute the previous binding for this key"
-  (interactive)
-  (setq yas--condition-cache-timestamp (current-time))
-  (let* ((yas--prefix current-prefix-arg)
-         (vec (subseq (this-command-keys-vector) (if current-prefix-arg
-                                                     
universal-argument-num-events
-                                                   0)))
-         (templates (mapcan #'(lambda (table)
-                                (yas--fetch table vec))
-                            (yas--get-snippet-tables))))
-    (if templates
-        (yas--expand-or-prompt-for-template templates)
-      (let ((yas-fallback-behavior 'call-other-command))
-        (yas--fallback)))))
-
-(defun yas--expand-or-prompt-for-template (templates &optional start end)
-  "Expand one of TEMPLATES from START to END.
-
-Prompt the user if TEMPLATES has more than one element, else
-expand immediately. Common gateway for
-`yas-expand-from-trigger-key' and `yas-expand-from-keymap'."
-  (let ((yas--current-template (or (and (rest templates) ;; more than one
-                                       (yas--prompt-for-template (mapcar #'cdr 
templates)))
-                                  (cdar templates))))
-    (when yas--current-template
-      (yas-expand-snippet (yas--template-content yas--current-template)
-                          start
-                          end
-                          (yas--template-expand-env yas--current-template)))))
-
-(defun yas--trigger-key-for-fallback ()
-  ;; When `yas-trigger-key' is <tab> it correctly overrides
-  ;; org-mode's <tab>, for example and searching for fallbacks
-  ;; correctly returns `org-cycle'. However, most other modes bind
-  ;; "TAB" (which is translated from <tab>), and calling
-  ;; (key-binding "TAB") does not place return that command into
-  ;; our command-2 local. So we cheat.
-  ;;
-  (if (string= yas-trigger-key "<tab>")
-      "TAB"
-    yas-trigger-key))
-
-(defun yas--fallback (&optional from-trigger-key-p)
-  "Fallback after expansion has failed.
-
-Common gateway for `yas-expand-from-trigger-key' and
-`yas-expand-from-keymap'."
-  (cond ((eq yas-fallback-behavior 'return-nil)
-         ;; return nil
-         nil)
-        ((eq yas-fallback-behavior 'call-other-command)
-         (let* ((yas-minor-mode nil)
-                (yas--direct-keymaps nil)
-                (yas-trigger-key (yas--trigger-key-for-fallback))
-                (keys-1 (this-command-keys-vector))
-                (keys-2 (and yas-trigger-key
-                             from-trigger-key-p
-                             (stringp yas-trigger-key)
-                             (read-kbd-macro yas-trigger-key)))
-                (command-1 (and keys-1 (key-binding keys-1)))
-                (command-2 (and keys-2 (key-binding keys-2)))
-                ;; An (ugly) safety: prevents infinite recursion of
-                ;; yas-expand* calls.
-                (command (or (and (symbolp command-1)
-                                  (not (string-match "yas-expand" (symbol-name 
command-1)))
-                                  command-1)
-                             (and (symbolp command-2)
-                                  command-2))))
-           (when (and (commandp command)
-                      (not (string-match "yas-expand" (symbol-name command))))
-             (setq this-command command)
-             (call-interactively command))))
-        ((and (listp yas-fallback-behavior)
-              (cdr yas-fallback-behavior)
-              (eq 'apply (car yas-fallback-behavior)))
-         (if (cddr yas-fallback-behavior)
-             (apply (cadr yas-fallback-behavior)
-                    (cddr yas-fallback-behavior))
-           (when (commandp (cadr yas-fallback-behavior))
-             (setq this-command (cadr yas-fallback-behavior))
-             (call-interactively (cadr yas-fallback-behavior)))))
-        (t
-         ;; also return nil if all the other fallbacks have failed
-         nil)))
-
-
-
-;;; Utils for snippet development:
-
-(defun yas--all-templates (tables)
-  "Return all snippet tables applicable for the current buffer.
-
-Honours `yas-choose-tables-first', `yas-choose-keys-first' and
-`yas-buffer-local-condition'"
-  (when yas-choose-tables-first
-    (setq tables (list (yas--prompt-for-table tables))))
-  (mapcar #'cdr
-          (if yas-choose-keys-first
-              (let ((key (yas--prompt-for-keys
-                          (mapcan #'yas--table-all-keys tables))))
-                (when key
-                  (mapcan #'(lambda (table)
-                              (yas--fetch table key))
-                          tables)))
-            (remove-duplicates (mapcan #'yas--table-templates tables)
-                               :test #'equal))))
-
-(defun yas-insert-snippet (&optional no-condition)
-  "Choose a snippet to expand, pop-up a list of choices according
-to `yas--prompt-function'.
-
-With prefix argument NO-CONDITION, bypass filtering of snippets
-by condition."
-  (interactive "P")
-  (setq yas--condition-cache-timestamp (current-time))
-  (let* ((yas-buffer-local-condition (or (and no-condition
-                                              'always)
-                                         yas-buffer-local-condition))
-         (templates (yas--all-templates (yas--get-snippet-tables)))
-         (yas--current-template (and templates
-                                    (or (and (rest templates) ;; more than one 
template for same key
-                                             (yas--prompt-for-template 
templates))
-                                        (car templates))))
-         (where (if (region-active-p)
-                    (cons (region-beginning) (region-end))
-                  (cons (point) (point)))))
-    (if yas--current-template
-        (yas-expand-snippet (yas--template-content yas--current-template)
-                            (car where)
-                            (cdr where)
-                            (yas--template-expand-env yas--current-template))
-      (yas--message 3 "No snippets can be inserted here!"))))
-
-(defun yas-visit-snippet-file ()
-  "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)
-  (let* ((yas-buffer-local-condition 'always)
-         (templates (yas--all-templates (yas--get-snippet-tables)))
-         (yas-prompt-functions '(yas-ido-prompt yas-completing-prompt))
-         (template (and templates
-                        (or (yas--prompt-for-template templates
-                                                     "Choose a snippet 
template to edit: ")
-                            (car templates)))))
-
-    (if template
-        (yas--visit-snippet-file-1 template)
-      (message "No snippets tables active!"))))
-
-(defun yas--visit-snippet-file-1 (template)
-  (let ((file (yas--template-file template)))
-    (cond ((and file (file-readable-p file))
-           (find-file-other-window file)
-           (snippet-mode)
-           (set (make-local-variable 'yas--editing-template) template))
-          (file
-           (message "Original file %s no longer exists!" file))
-          (t
-           (switch-to-buffer (format "*%s*"(yas--template-name template)))
-           (let ((type 'snippet))
-             (when (listp (yas--template-content template))
-               (insert (format "# type: command\n"))
-               (setq type 'command))
-             (insert (format "# key: %s\n" (yas--template-key template)))
-             (insert (format "# name: %s\n" (yas--template-name template)))
-             (when (yas--template-keybinding template)
-               (insert (format "# binding: %s\n" (yas--template-keybinding 
template))))
-             (when (yas--template-expand-env template)
-               (insert (format "# expand-env: %s\n" (yas--template-expand-env 
template))))
-             (when (yas--template-condition template)
-               (insert (format "# condition: %s\n" (yas--template-condition 
template))))
-             (insert "# --\n")
-             (insert (if (eq type 'command)
-                         (pp-to-string (yas--template-content template))
-                       (yas--template-content template))))
-           (snippet-mode)
-           (set (make-local-variable 'yas--editing-template) template)))))
-
-(defun yas--guess-snippet-directories-1 (table)
-  "Guesses possible snippet subdirectories for TABLE."
-  (cons (yas--table-name table)
-        (mapcan #'(lambda (parent)
-                    (yas--guess-snippet-directories-1
-                     parent))
-                (yas--table-parents table))))
-
-(defun yas--guess-snippet-directories (&optional table)
-  "Try to guess suitable directories based on the current active
-tables (or optional TABLE).
-
-Returns a list of elemts (TABLE . DIRS) where TABLE is a
-`yas--table' object and DIRS is a list of all possible directories
-where snippets of table might exist."
-  (let ((main-dir (replace-regexp-in-string
-                   "/+$" ""
-                   (or (first (or (yas-snippet-dirs)
-                                  (setq yas-snippet-dirs 
'("~/.emacs.d/snippets")))))))
-        (tables (or (and table
-                         (list table))
-                    (yas--get-snippet-tables))))
-    ;; HACK! the snippet table created here is actually registered!
-    ;;
-    (unless (or table (gethash major-mode yas--tables))
-      (push (yas--table-get-create major-mode)
-            tables))
-
-    (mapcar #'(lambda (table)
-                (cons table
-                      (mapcar #'(lambda (subdir)
-                                  (concat main-dir "/" subdir))
-                              (yas--guess-snippet-directories-1 table))))
-            tables)))
-
-(defun yas--make-directory-maybe (table-and-dirs &optional main-table-string)
-  "Returns a dir inside  TABLE-AND-DIRS, prompts for creation if none exists."
-  (or (some #'(lambda (dir) (when (file-directory-p dir) dir)) (cdr 
table-and-dirs))
-      (let ((candidate (first (cdr table-and-dirs))))
-        (unless (file-writable-p (file-name-directory candidate))
-          (error (yas--format "%s is not writable." candidate)))
-        (if (y-or-n-p (format "Guessed directory (%s) for%s%s table \"%s\" 
does not exist! Create? "
-                              candidate
-                              (if (gethash (yas--table-mode (car 
table-and-dirs))
-                                           yas--tables)
-                                  ""
-                                " brand new")
-                              (or main-table-string
-                                  "")
-                              (yas--table-name (car table-and-dirs))))
-            (progn
-              (make-directory candidate 'also-make-parents)
-              ;; create the .yas-parents file here...
-              candidate)))))
-
-(defun yas-new-snippet (&optional no-template)
-  "Pops a new buffer for writing a snippet.
-
-Expands a snippet-writing snippet, unless the optional prefix arg
-NO-TEMPLATE is non-nil."
-  (interactive "P")
-  (let ((guessed-directories (yas--guess-snippet-directories)))
-
-    (switch-to-buffer "*new snippet*")
-    (erase-buffer)
-    (kill-all-local-variables)
-    (snippet-mode)
-    (yas-minor-mode 1)
-    (set (make-local-variable 'yas--guessed-modes) (mapcar #'(lambda (d)
-                                                              (yas--table-mode 
(car d)))
-                                                          guessed-directories))
-    (unless no-template (yas-expand-snippet "\
-# -*- mode: snippet -*-
-# name: $1
-# key: ${2:${1:$(replace-regexp-in-string \"\\\\\\\\(\\\\\\\\w+\\\\\\\\).*\" 
\"\\\\\\\\1\" yas-text)}}${3:
-# binding: ${4:direct-keybinding}}${5:
-# expand-env: ((${6:some-var} ${7:some-value}))}${8:
-# type: command}
-# --
-$0"))))
-
-(defun yas--compute-major-mode-and-parents (file)
-  "Given FILE, find the nearest snippet directory for a given
-mode, then return a list (MODE-SYM PARENTS), the mode's symbol and a list
-representing one or more of the mode's parents.
-
-Note that MODE-SYM need not be the symbol of a real major mode,
-neither do the elements of PARENTS."
-  (let* ((file-dir (and file
-                        (directory-file-name (or (some #'(lambda (special)
-                                                           
(locate-dominating-file file special))
-                                                       '(".yas-setup.el"
-                                                         ".yas-make-groups"
-                                                         ".yas-parents"))
-                                                 (directory-file-name 
(file-name-directory file))))))
-         (parents-file-name (concat file-dir "/.yas-parents"))
-         (major-mode-name (and file-dir
-                               (file-name-nondirectory file-dir)))
-         (major-mode-sym (or (and major-mode-name
-                                  (intern major-mode-name))))
-         (parents (when (file-readable-p parents-file-name)
-                         (mapcar #'intern
-                                 (split-string
-                                  (with-temp-buffer
-                                    (insert-file-contents parents-file-name)
-                                    (buffer-substring-no-properties (point-min)
-                                                                    
(point-max))))))))
-    (when major-mode-sym
-      (cons major-mode-sym parents))))
-
-(defvar yas--editing-template nil
-  "Supporting variable for `yas-load-snippet-buffer' and `yas--visit-snippet'")
-
-(defvar yas--current-template nil
-  "Holds the current template being expanded into a snippet.")
-
-(defvar yas--guessed-modes nil
-  "List of guessed modes supporting `yas-load-snippet-buffer'.")
-
-(defun yas--read-table ()
-  "Ask user for a snippet table, help with some guessing."
-  (let ((prompt (if (and (featurep 'ido)
-                         ido-mode)
-                    'ido-completing-read 'completing-read)))
-    (unless yas--guessed-modes
-      (set (make-local-variable 'yas--guessed-modes)
-           (or (yas--compute-major-mode-and-parents buffer-file-name))))
-    (intern
-     (funcall prompt (format "Choose or enter a table (yas guesses %s): "
-                             (if yas--guessed-modes
-                                 (first yas--guessed-modes)
-                               "nothing"))
-              (mapcar #'symbol-name yas--guessed-modes)
-              nil
-              nil
-              nil
-              nil
-              (if (first yas--guessed-modes)
-                  (symbol-name (first yas--guessed-modes)))))))
-
-(defun yas-load-snippet-buffer (table &optional interactive)
-  "Parse and load current buffer's snippet definition into TABLE.
-
-TABLE is a symbol naming a passed to `yas--table-get-create'.
-
-When called interactively, prompt for the table name and
-whether (and where) to save the snippet, then quit the window."
-  (interactive (list (yas--read-table) t))
-  (cond
-   ;;  We have `yas--editing-template', this buffer's content comes from a
-   ;;  template which is already loaded and neatly positioned,...
-   ;;
-   (yas--editing-template
-    (yas-define-snippets-1 (yas--parse-template (yas--template-file 
yas--editing-template))
-                           (yas--template-table yas--editing-template)))
-   ;; Try to use `yas--guessed-modes'. If we don't have that use the
-   ;; value from `yas--compute-major-mode-and-parents'
-   ;;
-   (t
-    (unless yas--guessed-modes
-      (set (make-local-variable 'yas--guessed-modes) (or 
(yas--compute-major-mode-and-parents buffer-file-name))))
-    (let* ((table (yas--table-get-create table)))
-      (set (make-local-variable 'yas--editing-template)
-           (yas-define-snippets-1 (yas--parse-template buffer-file-name)
-                                  table)))))
-
-  (when (and interactive
-             (or
-              ;; Only offer to save this if it looks like a library or new
-              ;; snippet (loaded from elisp, from a dir in `yas-snippet-dirs'
-              ;; which is not the first, or from an unwritable file)
-              ;;
-              (not (yas--template-file yas--editing-template))
-              (not (file-writable-p (yas--template-file 
yas--editing-template)))
-              (and (listp yas-snippet-dirs)
-                   (second yas-snippet-dirs)
-                   (not (string-match (expand-file-name (first 
yas-snippet-dirs))
-                                      (yas--template-file 
yas--editing-template)))))
-             (y-or-n-p (yas--format "Looks like a library or new snippet. Save 
to new file? ")))
-    (let* ((option (first (yas--guess-snippet-directories (yas--template-table 
yas--editing-template))))
-           (chosen (and option
-                        (yas--make-directory-maybe option))))
-      (when chosen
-        (let ((default-file-name (or (and (yas--template-file 
yas--editing-template)
-                                          (file-name-nondirectory 
(yas--template-file yas--editing-template)))
-                                     (yas--template-name 
yas--editing-template))))
-          (write-file (concat chosen "/"
-                              (read-from-minibuffer (format "File name to 
create in %s? " chosen)
-                                                    default-file-name)))
-          (setf (yas--template-file yas--editing-template) 
buffer-file-name)))))
-  (when interactive
-    (quit-window interactive)
-    (yas--message 3 "Snippet \"%s\" loaded for %s."
-                  (yas--template-name yas--editing-template)
-                  (yas--table-name (yas--template-table 
yas--editing-template)))))
-
-
-(defun yas-tryout-snippet (&optional debug)
-  "Test current buffers's snippet template in other buffer."
-  (interactive "P")
-  (let* ((major-mode-and-parent (yas--compute-major-mode-and-parents 
buffer-file-name))
-         (parsed (yas--parse-template))
-         (test-mode (or (and (car major-mode-and-parent)
-                             (fboundp (car major-mode-and-parent))
-                             (car major-mode-and-parent))
-                        (first yas--guessed-modes)
-                        (intern (read-from-minibuffer (yas--format "Please 
input a mode: ")))))
-         (yas--current-template
-          (and parsed
-               (fboundp test-mode)
-               (yas--populate-template (yas--make-blank-template)
-                                      :table       nil ;; no tables for 
ephemeral snippets
-                                      :key         (first parsed)
-                                      :content     (second parsed)
-                                      :name        (third parsed)
-                                      :expand-env  (sixth parsed)))))
-    (cond (yas--current-template
-           (let ((buffer-name (format "*testing snippet: %s*" 
(yas--template-name yas--current-template))))
-             (kill-buffer (get-buffer-create buffer-name))
-             (switch-to-buffer (get-buffer-create buffer-name))
-             (setq buffer-undo-list nil)
-             (condition-case nil (funcall test-mode) (error nil))
-            (yas-minor-mode 1)
-             (setq buffer-read-only nil)
-             (yas-expand-snippet (yas--template-content yas--current-template)
-                                 (point-min)
-                                 (point-max)
-                                 (yas--template-expand-env 
yas--current-template))
-             (when (and debug
-                        (require 'yasnippet-debug nil t))
-               (add-hook 'post-command-hook 'yas-debug-snippet-vars nil t))))
-          (t
-           (yas--message 3 "Cannot test snippet for unknown major mode")))))
-
-(defun yas--template-fine-group (template)
-  (car (last (or (yas--template-group template)
-                 (yas--template-perm-group template)))))
-
-(defun yas-describe-tables (&optional choose)
-  "Display snippets for each table."
-  (interactive "P")
-  (let* ((by-name-hash (and choose
-                            (y-or-n-p "Show by namehash? ")))
-         (buffer (get-buffer-create "*YASnippet tables*"))
-         (active-tables (yas--get-snippet-tables))
-         (remain-tables (let ((all))
-                          (maphash #'(lambda (k v)
-                                       (unless (find v active-tables)
-                                         (push v all)))
-                                   yas--tables)
-                          all))
-         (table-lists (list active-tables remain-tables))
-         (original-buffer (current-buffer))
-         (continue t)
-         (yas--condition-cache-timestamp (current-time)))
-    (with-current-buffer buffer
-      (setq buffer-read-only nil)
-      (erase-buffer)
-      (cond ((not by-name-hash)
-             (insert "YASnippet tables: \n")
-             (while (and table-lists
-                         continue)
-               (dolist (table (car table-lists))
-                 (yas--describe-pretty-table table original-buffer))
-               (setq table-lists (cdr table-lists))
-               (when table-lists
-                 (yas--create-snippet-xrefs)
-                 (display-buffer buffer)
-                 (setq continue (and choose (y-or-n-p "Show also non-active 
tables? ")))))
-             (yas--create-snippet-xrefs)
-             (help-mode)
-             (goto-char 1))
-            (t
-             (insert "\n\nYASnippet tables by NAMEHASH: \n")
-             (dolist (table (append active-tables remain-tables))
-               (insert (format "\nSnippet table `%s':\n\n" (yas--table-name 
table)))
-               (let ((keys))
-                 (maphash #'(lambda (k v)
-                              (push k keys))
-                          (yas--table-hash table))
-                 (dolist (key keys)
-                   (insert (format "   key %s maps snippets: %s\n" key
-                                   (let ((names))
-                                     (maphash #'(lambda (k v)
-                                                  (push k names))
-                                              (gethash key (yas--table-hash 
table)))
-                                     names))))))))
-      (goto-char 1)
-      (setq buffer-read-only t))
-    (display-buffer buffer)))
-
-(defun yas--describe-pretty-table (table &optional original-buffer)
-  (insert (format "\nSnippet table `%s'"
-                  (yas--table-name table)))
-  (if (yas--table-parents table)
-      (insert (format " parents: %s\n"
-                      (mapcar #'yas--table-name
-                              (yas--table-parents table))))
-    (insert "\n"))
-  (insert (make-string 100 ?-) "\n")
-  (insert "group                   state name                                  
  key             binding\n")
-  (let ((groups-hash (make-hash-table :test #'equal)))
-    (maphash #'(lambda (k v)
-                 (let ((group (or (yas--template-fine-group v)
-                                  "(top level)")))
-                   (when (yas--template-name v)
-                     (puthash group
-                              (cons v (gethash group groups-hash))
-                              groups-hash))))
-             (yas--table-uuidhash table))
-    (maphash
-     #'(lambda (group templates)
-         (setq group (truncate-string-to-width group 25 0 ?  "..."))
-         (insert (make-string 100 ?-) "\n")
-         (dolist (p templates)
-           (let ((name (truncate-string-to-width (propertize (format 
"\\\\snippet `%s'" (yas--template-name p))
-                                                             'yasnippet p)
-                                                 50 0 ? "..."))
-                 (group (prog1 group
-                          (setq group (make-string (length group) ? ))))
-                 (condition-string (let ((condition (yas--template-condition 
p)))
-                                     (if (and condition
-                                              original-buffer)
-                                         (with-current-buffer original-buffer
-                                           (if (yas--eval-condition condition)
-                                               "(y)"
-                                             "(s)"))
-                                       "(a)"))))
-             (insert group " ")
-             (insert condition-string " ")
-             (insert name
-                     (if (string-match "\\.\\.\\.$" name)
-                         "'"
-                       " ")
-                     " ")
-             (insert (truncate-string-to-width (or (yas--template-key p) "")
-                                               15 0 ?  "...") " ")
-             (insert (truncate-string-to-width (key-description 
(yas--template-keybinding p))
-                                               15 0 ?  "...") " ")
-             (insert "\n"))))
-     groups-hash)))
-
-
-
-;;; User convenience functions, for using in snippet definitions
-
-(defvar yas-modified-p nil
-  "Non-nil if field has been modified by user or transformation.")
-
-(defvar yas-moving-away-p nil
-  "Non-nil if user is about to exit field.")
-
-(defvar yas-text nil
-  "Contains current field text.")
-
-(defun yas-substr (str pattern &optional subexp)
-  "Search PATTERN in STR and return SUBEXPth match.
-
-If found, the content of subexp group SUBEXP (default 0) is
-  returned, or else the original STR will be returned."
-  (let ((grp (or subexp 0)))
-    (save-match-data
-      (if (string-match pattern str)
-          (match-string-no-properties grp str)
-        str))))
-
-(defun yas-choose-avalue (&rest possibilities)
-  "Prompt for a string in POSSIBILITIES and return it.
-
-The last element of POSSIBILITIES may be a list of strings."
-  (unless (or yas-moving-away-p
-              yas-modified-p)
-    (setq possibilities (nreverse possibilities))
-    (setq possibilities (if (listp (car possibilities))
-                            (append (reverse (car possibilities)) (rest 
possibilities))
-                                   possibilities))
-    (some #'(lambda (fn)
-              (funcall fn "Choose: " possibilities))
-          yas-prompt-functions)))
-
-(defun yas-key-to-value (alist)
-  "Prompt for a string in the list POSSIBILITIES and return it."
-  (unless (or yas-moving-away-p
-              yas-modified-p)
-    (let ((key (read-key-sequence "")))
-      (when (stringp key)
-        (or (cdr (find key alist :key #'car :test #'string=))
-            key)))))
-
-(defun yas-throw (text)
-  "Throw a yas--exception with TEXT as the reason."
-  (throw 'yas--exception (cons 'yas--exception text)))
-
-(defun yas-verify-value (possibilities)
-  "Verify that the current field value is in POSSIBILITIES
-
-Otherwise throw exception."
-  (when (and yas-moving-away-p (notany #'(lambda (pos) (string= pos yas-text)) 
possibilities))
-    (yas-throw (yas--format "Field only allows %s" possibilities))))
-
-(defun yas-field-value (number)
-  "Get the string for field with NUMBER.
-
-Use this in primary and mirror transformations to tget."
-  (let* ((snippet (car (yas--snippets-at-point)))
-         (field (and snippet
-                     (yas--snippet-find-field snippet number))))
-    (when field
-      (yas--field-text-for-display field))))
-
-(defun yas-text ()
-  "Return `yas-text' if that exists and is non-empty, else nil."
-  (if (and yas-text
-           (not (string= "" yas-text)))
-      yas-text))
-
-(defun yas-selected-text ()
-  "Return `yas-selected-text' if that exists and is non-empty, else nil."
-  (if (and yas-selected-text
-           (not (string= "" yas-selected-text)))
-      yas-selected-text))
-
-(defun yas--get-field-once (number &optional transform-fn)
-  (unless yas-modified-p
-    (if transform-fn
-        (funcall transform-fn (yas-field-value number))
-      (yas-field-value number))))
-
-(defun yas-default-from-field (number)
-  (unless yas-modified-p
-    (yas-field-value number)))
-
-(defun yas-inside-string ()
-  (equal 'font-lock-string-face (get-char-property (1- (point)) 'face)))
-
-(defun yas-unimplemented (&optional missing-feature)
-  (if yas--current-template
-      (if (y-or-n-p (format "This snippet is unimplemented (missing %s) Visit 
the snippet definition? "
-                            (or missing-feature
-                                "something")))
-          (yas--visit-snippet-file-1 yas--current-template))
-    (message "No implementation. Missing %s" (or missing-feature 
"something"))))
-
-
-;;; Snippet expansion and field management
-
-(defvar yas--active-field-overlay nil
-  "Overlays the currently active field.")
-
-(defvar yas--field-protection-overlays nil
-  "Two overlays protect the current active field ")
-
-(defconst yas--prefix nil
-  "A prefix argument for expansion direct from keybindings")
-
-(defvar yas-selected-text nil
-  "The selected region deleted on the last snippet expansion.")
-
-(defvar yas--start-column nil
-  "The column where the snippet expansion started.")
-
-(make-variable-buffer-local 'yas--active-field-overlay)
-(make-variable-buffer-local 'yas--field-protection-overlays)
-(put 'yas--active-field-overlay 'permanent-local t)
-(put 'yas--field-protection-overlays 'permanent-local t)
-
-(defstruct (yas--snippet (:constructor yas--make-snippet ()))
-  "A snippet.
-
-..."
-  (fields '())
-  (exit nil)
-  (id (yas--snippet-next-id) :read-only t)
-  (control-overlay nil)
-  active-field
-  ;; stacked expansion: the `previous-active-field' slot saves the
-  ;; active field where the child expansion took place
-  previous-active-field
-  force-exit)
-
-(defstruct (yas--field (:constructor yas--make-field (number start end 
parent-field)))
-  "A field."
-  number
-  start end
-  parent-field
-  (mirrors '())
-  (transform nil)
-  (modified-p nil)
-  next)
-
-(defstruct (yas--mirror (:constructor yas--make-mirror (start end transform)))
-  "A mirror."
-  start end
-  (transform nil)
-  parent-field
-  next)
-
-(defstruct (yas--exit (:constructor yas--make-exit (marker)))
-  marker
-  next)
-
-(defun yas--apply-transform (field-or-mirror field &optional empty-on-nil-p)
-  "Calculate transformed string for FIELD-OR-MIRROR from FIELD.
-
-If there is no transform for ht field, return nil.
-
-If there is a transform but it returns nil, return the empty
-string iff EMPTY-ON-NIL-P is true."
-  (let* ((yas-text (yas--field-text-for-display field))
-         (text yas-text)
-         (yas-modified-p (yas--field-modified-p field))
-         (yas-moving-away-p nil)
-         (transform (if (yas--mirror-p field-or-mirror)
-                        (yas--mirror-transform field-or-mirror)
-                      (yas--field-transform field-or-mirror)))
-         (start-point (if (yas--mirror-p field-or-mirror)
-                          (yas--mirror-start field-or-mirror)
-                        (yas--field-start field-or-mirror)))
-         (transformed (and transform
-                           (save-excursion
-                             (goto-char start-point)
-                             (let ((ret (yas--eval-lisp transform)))
-                               (or ret (and empty-on-nil-p "")))))))
-    transformed))
-
-(defsubst yas--replace-all (from to &optional text)
-  "Replace all occurance from FROM to TO.
-
-With optional string TEXT do it in that string."
-  (if text
-      (replace-regexp-in-string (regexp-quote from) to text t t)
-    (goto-char (point-min))
-    (while (search-forward from nil t)
-      (replace-match to t t text))))
-
-(defun yas--snippet-find-field (snippet number)
-  (find-if #'(lambda (field)
-               (eq number (yas--field-number field)))
-           (yas--snippet-fields snippet)))
-
-(defun yas--snippet-sort-fields (snippet)
-  "Sort the fields of SNIPPET in navigation order."
-  (setf (yas--snippet-fields snippet)
-        (sort (yas--snippet-fields snippet)
-              #'yas--snippet-field-compare)))
-
-(defun yas--snippet-field-compare (field1 field2)
-  "Compare two fields. The field with a number is sorted first.
-If they both have a number, compare through the number. If neither
-have, compare through the field's start point"
-  (let ((n1 (yas--field-number field1))
-        (n2 (yas--field-number field2)))
-    (if n1
-        (if n2
-            (or (zerop n2) (and (not (zerop n1))
-                                (< n1 n2)))
-          (not (zerop n1)))
-      (if n2
-          (zerop n2)
-        (< (yas--field-start field1)
-           (yas--field-start field2))))))
-
-(defun yas--field-probably-deleted-p (snippet field)
-  "Guess if SNIPPET's FIELD should be skipped."
-  (and
-   ;; field must be zero lentgh
-   ;;
-   (zerop (- (yas--field-start field) (yas--field-end field)))
-   ;; skip if:
-   (or
-    ;;  1) is a nested field and it's been modified
-    ;;
-    (and (yas--field-parent-field field)
-         (yas--field-modified-p field))
-    ;;  2) ends just before the snippet end
-    ;;
-    (and (eq field (car (last (yas--snippet-fields snippet))))
-         (= (yas--field-start field) (overlay-end 
(yas--snippet-control-overlay snippet)))))
-   ;; the field numbered 0, just before the exit marker, should
-   ;; never be skipped
-   ;;
-   (not (zerop (yas--field-number field)))))
-
-(defun yas--snippets-at-point (&optional all-snippets)
-  "Return a sorted list of snippets at point, most recently
-inserted first."
-  (sort
-   (remove nil (remove-duplicates (mapcar #'(lambda (ov)
-                                              (overlay-get ov 'yas--snippet))
-                                          (if all-snippets
-                                              (overlays-in (point-min) 
(point-max))
-                                            (nconc (overlays-at (point)) 
(overlays-at (1- (point))))))))
-   #'(lambda (s1 s2)
-       (<= (yas--snippet-id s2) (yas--snippet-id s1)))))
-
-(defun yas-next-field-or-maybe-expand ()
-  "Try to expand a snippet at a key before point, otherwise
-delegate to `yas-next-field'."
-  (interactive)
-  (if yas-triggers-in-field
-      (let ((yas-fallback-behavior 'return-nil)
-            (active-field (overlay-get yas--active-field-overlay 'yas--field)))
-        (when active-field
-          (unless (yas-expand-from-trigger-key active-field)
-            (yas-next-field))))
-    (yas-next-field)))
-
-(defun yas-next-field (&optional arg)
-  "Navigate to next field.  If there's none, exit the snippet."
-  (interactive)
-  (let* ((arg (or arg
-                  1))
-         (snippet (first (yas--snippets-at-point)))
-         (active-field (overlay-get yas--active-field-overlay 'yas--field))
-         (live-fields (remove-if #'(lambda (field)
-                                     (and (not (eq field active-field))
-                                          (yas--field-probably-deleted-p 
snippet field)))
-                                 (yas--snippet-fields snippet)))
-         (active-field-pos (position active-field live-fields))
-         (target-pos (and active-field-pos (+ arg active-field-pos)))
-         (target-field (and target-pos (nth target-pos live-fields))))
-    ;; First check if we're moving out of a field with a transform
-    ;;
-    (when (and active-field
-               (yas--field-transform active-field))
-      (let* ((yas-moving-away-p t)
-             (yas-text (yas--field-text-for-display active-field))
-             (text yas-text)
-             (yas-modified-p (yas--field-modified-p active-field)))
-        ;; primary field transform: exit call to field-transform
-        (yas--eval-lisp (yas--field-transform active-field))))
-    ;; Now actually move...
-    (cond ((and target-pos (>= target-pos (length live-fields)))
-           (yas-exit-snippet snippet))
-          (target-field
-           (yas--move-to-field snippet target-field))
-          (t
-           nil))))
-
-(defun yas--place-overlays (snippet field)
-  "Correctly place overlays for SNIPPET's FIELD"
-  (yas--make-move-field-protection-overlays snippet field)
-  (yas--make-move-active-field-overlay snippet field))
-
-(defun yas--move-to-field (snippet field)
-  "Update SNIPPET to move to field FIELD.
-
-Also create some protection overlays"
-  (goto-char (yas--field-start field))
-  (yas--place-overlays snippet field)
-  (overlay-put yas--active-field-overlay 'yas--field field)
-  (let ((number (yas--field-number field)))
-    ;; check for the special ${0: ...} field
-    (if (and number (zerop number))
-        (progn
-          (set-mark (yas--field-end field))
-          (setf (yas--snippet-force-exit snippet)
-                (or (yas--field-transform field)
-                    t)))
-      ;; make this field active
-      (setf (yas--snippet-active-field snippet) field)
-      ;; primary field transform: first call to snippet transform
-      (unless (yas--field-modified-p field)
-        (if (yas--field-update-display field snippet)
-            (yas--update-mirrors snippet)
-          (setf (yas--field-modified-p field) nil))))))
-
-(defun yas-prev-field ()
-  "Navigate to prev field.  If there's none, exit the snippet."
-  (interactive)
-  (yas-next-field -1))
-
-(defun yas-abort-snippet (&optional snippet)
-  (interactive)
-  (let ((snippet (or snippet
-                     (car (yas--snippets-at-point)))))
-    (when snippet
-      (setf (yas--snippet-force-exit snippet) t))))
-
-(defun yas-exit-snippet (snippet)
-  "Goto exit-marker of SNIPPET."
-  (interactive (list (first (yas--snippets-at-point))))
-  (when snippet
-    (setf (yas--snippet-force-exit snippet) t)
-    (goto-char (if (yas--snippet-exit snippet)
-                   (yas--exit-marker (yas--snippet-exit snippet))
-                 (overlay-end (yas--snippet-control-overlay snippet))))))
-
-(defun yas-exit-all-snippets ()
-  "Exit all snippets."
-  (interactive)
-  (mapc #'(lambda (snippet)
-            (yas-exit-snippet snippet)
-            (yas--check-commit-snippet))
-        (yas--snippets-at-point 'all-snippets)))
-
-
-;;; Some low level snippet-routines:
-
-(defmacro yas--inhibit-overlay-hooks (&rest body)
-  "Run BODY with `yas--inhibit-overlay-hooks' set to t."
-  (declare (indent 0))
-  `(let ((yas--inhibit-overlay-hooks t))
-     (progn ,@body)))
-
-(defvar yas-snippet-beg nil "Beginning position of the last snippet commited.")
-(defvar yas-snippet-end nil "End position of the last snippet commited.")
-
-(defun yas--commit-snippet (snippet)
-  "Commit SNIPPET, but leave point as it is.  This renders the
-snippet as ordinary text."
-
-  (let ((control-overlay (yas--snippet-control-overlay snippet)))
-    ;;
-    ;; Save the end of the moribund snippet in case we need to revive it
-    ;; its original expansion.
-    ;;
-    (when (and control-overlay
-               (overlay-buffer control-overlay))
-      (setq yas-snippet-beg (overlay-start control-overlay))
-      (setq yas-snippet-end (overlay-end control-overlay))
-      (delete-overlay control-overlay))
-
-    (yas--inhibit-overlay-hooks
-      (when yas--active-field-overlay
-        (delete-overlay yas--active-field-overlay))
-      (when yas--field-protection-overlays
-        (mapc #'delete-overlay yas--field-protection-overlays)))
-
-    ;; stacked expansion: if the original expansion took place from a
-    ;; field, make sure we advance it here at least to
-    ;; `yas-snippet-end'...
-    ;;
-    (let ((previous-field (yas--snippet-previous-active-field snippet)))
-      (when (and yas-snippet-end previous-field)
-        (yas--advance-end-maybe previous-field yas-snippet-end)))
-
-    ;; Convert all markers to points,
-    ;;
-    (yas--markers-to-points snippet)
-
-    ;; Take care of snippet revival
-    ;;
-    (if yas-snippet-revival
-        (push `(apply yas--snippet-revive ,yas-snippet-beg ,yas-snippet-end 
,snippet)
-              buffer-undo-list)
-      ;; Dismember the snippet... this is useful if we get called
-      ;; again from `yas--take-care-of-redo'....
-      (setf (yas--snippet-fields snippet) nil)))
-
-  (yas--message 3 "Snippet %s exited." (yas--snippet-id snippet)))
-
-(defun yas--safely-run-hooks (hook-var)
-  (condition-case error
-      (run-hooks hook-var)
-    (error
-     (yas--message 3 "%s error: %s" hook-var (error-message-string error)))))
-
-
-(defun yas--check-commit-snippet ()
-  "Checks if point exited the currently active field of the
-snippet, if so cleans up the whole snippet up."
-  (let* ((snippets (yas--snippets-at-point 'all-snippets))
-         (snippets-left snippets)
-         (snippet-exit-transform))
-    (dolist (snippet snippets)
-      (let ((active-field (yas--snippet-active-field snippet)))
-        (setq snippet-exit-transform (yas--snippet-force-exit snippet))
-        (cond ((or snippet-exit-transform
-                   (not (and active-field (yas--field-contains-point-p 
active-field))))
-               (setq snippets-left (delete snippet snippets-left))
-               (setf (yas--snippet-force-exit snippet) nil)
-               (yas--commit-snippet snippet))
-              ((and active-field
-                    (or (not yas--active-field-overlay)
-                        (not (overlay-buffer yas--active-field-overlay))))
-               ;;
-               ;; stacked expansion: this case is mainly for recent
-               ;; snippet exits that place us back int the field of
-               ;; another snippet
-               ;;
-               (save-excursion
-                 (yas--move-to-field snippet active-field)
-                 (yas--update-mirrors snippet)))
-              (t
-               nil))))
-    (unless (or (null snippets) snippets-left)
-      (if snippet-exit-transform
-          (yas--eval-lisp-no-saves snippet-exit-transform))
-      (yas--safely-run-hooks 'yas-after-exit-snippet-hook))))
-
-;; Apropos markers-to-points:
-;;
-;; This was found useful for performance reasons, so that an
-;; excessive number of live markers aren't kept around in the
-;; `buffer-undo-list'. However, in `markers-to-points', the
-;; set-to-nil markers can't simply be discarded and replaced with
-;; fresh ones in `points-to-markers'. The original marker that was
-;; just set to nil has to be reused.
-;;
-;; This shouldn't bring horrible problems with undo/redo, but it
-;; you never know
-;;
-(defun yas--markers-to-points (snippet)
-  "Convert all markers in SNIPPET to a cons (POINT . MARKER)
-where POINT is the original position of the marker and MARKER is
-the original marker object with the position set to nil."
-  (dolist (field (yas--snippet-fields snippet))
-    (let ((start (marker-position (yas--field-start field)))
-          (end (marker-position (yas--field-end field))))
-      (set-marker (yas--field-start field) nil)
-      (set-marker (yas--field-end field) nil)
-      (setf (yas--field-start field) (cons start (yas--field-start field)))
-      (setf (yas--field-end field) (cons end (yas--field-end field))))
-    (dolist (mirror (yas--field-mirrors field))
-      (let ((start (marker-position (yas--mirror-start mirror)))
-            (end (marker-position (yas--mirror-end mirror))))
-        (set-marker (yas--mirror-start mirror) nil)
-        (set-marker (yas--mirror-end mirror) nil)
-        (setf (yas--mirror-start mirror) (cons start (yas--mirror-start 
mirror)))
-        (setf (yas--mirror-end mirror) (cons end (yas--mirror-end mirror))))))
-  (let ((snippet-exit (yas--snippet-exit snippet)))
-    (when snippet-exit
-      (let ((exit (marker-position (yas--exit-marker snippet-exit))))
-        (set-marker (yas--exit-marker snippet-exit) nil)
-        (setf (yas--exit-marker snippet-exit) (cons exit (yas--exit-marker 
snippet-exit)))))))
-
-(defun yas--points-to-markers (snippet)
-  "Convert all cons (POINT . MARKER) in SNIPPET to markers. This
-is done by setting MARKER to POINT with `set-marker'."
-  (dolist (field (yas--snippet-fields snippet))
-    (setf (yas--field-start field) (set-marker (cdr (yas--field-start field))
-                                              (car (yas--field-start field))))
-    (setf (yas--field-end field) (set-marker (cdr (yas--field-end field))
-                                            (car (yas--field-end field))))
-    (dolist (mirror (yas--field-mirrors field))
-      (setf (yas--mirror-start mirror) (set-marker (cdr (yas--mirror-start 
mirror))
-                                                  (car (yas--mirror-start 
mirror))))
-      (setf (yas--mirror-end mirror) (set-marker (cdr (yas--mirror-end mirror))
-                                                (car (yas--mirror-end 
mirror))))))
-  (let ((snippet-exit (yas--snippet-exit snippet)))
-    (when snippet-exit
-      (setf (yas--exit-marker snippet-exit) (set-marker (cdr (yas--exit-marker 
snippet-exit))
-                                                       (car (yas--exit-marker 
snippet-exit)))))))
-
-(defun yas--field-contains-point-p (field &optional point)
-  (let ((point (or point
-                   (point))))
-    (and (>= point (yas--field-start field))
-         (<= point (yas--field-end field)))))
-
-(defun yas--field-text-for-display (field)
-  "Return the propertized display text for field FIELD.  "
-  (buffer-substring (yas--field-start field) (yas--field-end field)))
-
-(defun yas--undo-in-progress ()
-  "True if some kind of undo is in progress"
-  (or undo-in-progress
-      (eq this-command 'undo)
-      (eq this-command 'redo)))
-
-(defun yas--make-control-overlay (snippet start end)
-  "Creates the control overlay that surrounds the snippet and
-holds the keymap."
-  (let ((overlay (make-overlay start
-                               end
-                               nil
-                               nil
-                               t)))
-    (overlay-put overlay 'keymap yas-keymap)
-    (overlay-put overlay 'priority 100)
-    (overlay-put overlay 'yas--snippet snippet)
-    overlay))
-
-(defun yas-skip-and-clear-or-delete-char (&optional field)
-  "Clears unmodified field if at field start, skips to next tab.
-
-Otherwise deletes a character normally by calling `delete-char'."
-  (interactive)
-  (let ((field (or field
-                   (and yas--active-field-overlay
-                        (overlay-buffer yas--active-field-overlay)
-                        (overlay-get yas--active-field-overlay 'yas--field)))))
-    (cond ((and field
-                (not (yas--field-modified-p field))
-                (eq (point) (marker-position (yas--field-start field))))
-           (yas--skip-and-clear field)
-           (yas-next-field 1))
-          (t
-           (call-interactively 'delete-char)))))
-
-(defun yas--skip-and-clear (field)
-  "Deletes the region of FIELD and sets it modified state to t"
-  ;; Just before skipping-and-clearing the field, mark its children
-  ;; fields as modified, too. If the childen have mirrors-in-fields
-  ;; this prevents them from updating erroneously (we're skipping and
-  ;; deleting!).
-  ;;
-  (yas--mark-this-and-children-modified field)
-  (delete-region (yas--field-start field) (yas--field-end field)))
-
-(defun yas--mark-this-and-children-modified (field)
-  (setf (yas--field-modified-p field) t)
-  (let ((fom (yas--field-next field)))
-    (while (and fom
-                (yas--fom-parent-field fom))
-      (when (and (eq (yas--fom-parent-field fom) field)
-                 (yas--field-p fom))
-        (yas--mark-this-and-children-modified fom))
-      (setq fom (yas--fom-next fom)))))
-
-(defun yas--make-move-active-field-overlay (snippet field)
-  "Place the active field overlay in SNIPPET's FIELD.
-
-Move the overlay, or create it if it does not exit."
-  (if (and yas--active-field-overlay
-           (overlay-buffer yas--active-field-overlay))
-      (move-overlay yas--active-field-overlay
-                    (yas--field-start field)
-                    (yas--field-end field))
-    (setq yas--active-field-overlay
-          (make-overlay (yas--field-start field)
-                        (yas--field-end field)
-                        nil nil t))
-    (overlay-put yas--active-field-overlay 'priority 100)
-    (overlay-put yas--active-field-overlay 'face 'yas-field-highlight-face)
-    (overlay-put yas--active-field-overlay 'yas--snippet snippet)
-    (overlay-put yas--active-field-overlay 'modification-hooks 
'(yas--on-field-overlay-modification))
-    (overlay-put yas--active-field-overlay 'insert-in-front-hooks
-                 '(yas--on-field-overlay-modification))
-    (overlay-put yas--active-field-overlay 'insert-behind-hooks
-                 '(yas--on-field-overlay-modification))))
-
-(defvar yas--inhibit-overlay-hooks nil
-  "Bind this temporarity to non-nil to prevent running 
`yas--on-*-modification'.")
-
-(defun yas--on-field-overlay-modification (overlay after? beg end &optional 
length)
-  "Clears the field and updates mirrors, conditionally.
-
-Only clears the field if it hasn't been modified and it point it
-at field start. This hook doesn't do anything if an undo is in
-progress."
-  (unless (or yas--inhibit-overlay-hooks
-              (yas--undo-in-progress))
-    (let* ((field (overlay-get overlay 'yas--field))
-           (number (and field (yas--field-number field)))
-           (snippet (overlay-get yas--active-field-overlay 'yas--snippet)))
-      (cond (after?
-             (yas--advance-end-maybe field (overlay-end overlay))
-             (save-excursion
-               (yas--field-update-display field snippet))
-             (yas--update-mirrors snippet))
-            (field
-             (when (and (not after?)
-                        (not (yas--field-modified-p field))
-                        (eq (point) (if (markerp (yas--field-start field))
-                                        (marker-position (yas--field-start 
field))
-                                      (yas--field-start field))))
-               (yas--skip-and-clear field))
-             (setf (yas--field-modified-p field) t))))))
-
-;;; Apropos protection overlays:
-;;
-;; These exist for nasty users who will try to delete parts of the
-;; snippet outside the active field. Actual protection happens in
-;; `yas--on-protection-overlay-modification'.
-;;
-;; Currently this signals an error which inhibits the command. For
-;; commands that move point (like `kill-line'), point is restored in
-;; the `yas--post-command-handler' using a global
-;; `yas--protection-violation' variable.
-;;
-;; Alternatively, I've experimented with an implementation that
-;; commits the snippet before actually calling `this-command'
-;; interactively, and then signals an eror, which is ignored. but
-;; blocks all other million modification hooks. This presented some
-;; problems with stacked expansion.
-;;
-(defun yas--make-move-field-protection-overlays (snippet field)
-  "Place protection overlays surrounding SNIPPET's FIELD.
-
-Move the overlays, or create them if they do not exit."
-  (let ((start (yas--field-start field))
-        (end (yas--field-end field)))
-    ;; First check if the (1+ end) is contained in the buffer,
-    ;; otherwise we'll have to do a bit of cheating and silently
-    ;; insert a newline. the `(1+ (buffer-size))' should prevent this
-    ;; when using stacked expansion
-    ;;
-    (when (< (buffer-size) end)
-      (save-excursion
-        (yas--inhibit-overlay-hooks
-          (goto-char (point-max))
-          (newline))))
-    ;; go on to normal overlay creation/moving
-    ;;
-    (cond ((and yas--field-protection-overlays
-                (every #'overlay-buffer yas--field-protection-overlays))
-           (move-overlay (first yas--field-protection-overlays) (1- start) 
start)
-           (move-overlay (second yas--field-protection-overlays) end (1+ end)))
-          (t
-           (setq yas--field-protection-overlays
-                 (list (make-overlay (1- start) start nil t nil)
-                       (make-overlay end (1+ end) nil t nil)))
-           (dolist (ov yas--field-protection-overlays)
-             (overlay-put ov 'face 'yas--field-debug-face)
-             (overlay-put ov 'yas--snippet snippet)
-             ;; (overlay-put ov 'evaporate t)
-             (overlay-put ov 'modification-hooks 
'(yas--on-protection-overlay-modification)))))))
-
-(defvar yas--protection-violation nil
-  "When non-nil, signals attempts to erronesly exit or modify the snippet.
-
-Functions in the `post-command-hook', for example
-`yas--post-command-handler' can check it and reset its value to
-nil. The variables value is the point where the violation
-originated")
-
-(defun yas--on-protection-overlay-modification (overlay after? beg end 
&optional length)
-  "Signals a snippet violation, then issues error.
-
-The error should be ignored in `debug-ignored-errors'"
-  (unless yas--inhibit-overlay-hooks
-    (cond ((not (or after?
-                    (yas--undo-in-progress)))
-           (setq yas--protection-violation (point))
-           (error "Exit the snippet first!")))))
-
-(add-to-list 'debug-ignored-errors "^Exit the snippet first!$")
-
-
-;; Snippet expansion and "stacked" expansion:
-;;
-;; Stacked expansion is when you try to expand a snippet when already
-;; inside a snippet expansion.
-;;
-;; The parent snippet does not run its fields modification hooks
-;; (`yas--on-field-overlay-modification' and
-;; `yas--on-protection-overlay-modification') while the child snippet
-;; is active. This means, among other things, that the mirrors of the
-;; parent snippet are not updated, this only happening when one exits
-;; the child snippet.
-;;
-;; Unfortunately, this also puts some ugly (and not fully-tested)
-;; bits of code in `yas-expand-snippet' and
-;; `yas--commit-snippet'. I've tried to mark them with "stacked
-;; expansion:".
-;;
-;; This was thought to be safer in in an undo/redo perpective, but
-;; maybe the correct implementation is to make the globals
-;; `yas--active-field-overlay' and `yas--field-protection-overlays' be
-;; snippet-local and be active even while the child snippet is
-;; running. This would mean a lot of overlay modification hooks
-;; running, but if managed correctly (including overlay priorities)
-;; they should account for all situations...
-;;
-(defun yas-expand-snippet (content &optional start end expand-env)
-  "Expand snippet CONTENT at current point.
-
-Text between START and END will be deleted before inserting
-template. EXPAND-ENV is are let-style variable to value bindings
-considered when expanding the snippet."
-  (run-hooks 'yas-before-expand-snippet-hook)
-
-  ;;
-  (let* ((yas-selected-text (or yas-selected-text
-                                (and (region-active-p)
-                                     (buffer-substring-no-properties 
(region-beginning)
-                                                                     
(region-end)))))
-         (start (or start
-                    (and (region-active-p)
-                         (region-beginning))
-                    (point)))
-         (end (or end
-                  (and (region-active-p)
-                       (region-end))
-                  (point)))
-         (to-delete (and start
-                         end
-                         (buffer-substring-no-properties start end)))
-         snippet)
-    (goto-char start)
-    (setq yas--indent-original-column (current-column))
-    ;; Delete the region to delete, this *does* get undo-recorded.
-    ;;
-    (when (and to-delete
-               (> end start))
-      (delete-region start end))
-
-    (cond ((listp content)
-           ;; x) This is a snippet-command
-           ;;
-           (yas--eval-lisp-no-saves content))
-          (t
-           ;; x) This is a snippet-snippet :-)
-           ;;
-           ;;    Narrow the region down to the content, shoosh the
-           ;;    `buffer-undo-list', and create the snippet, the new
-           ;;    snippet updates its mirrors once, so we are left with
-           ;;    some plain text.  The undo action for deleting this
-           ;;    plain text will get recorded at the end.
-           ;;
-           ;;    stacked expansion: also shoosh the overlay modification hooks
-           (save-restriction
-             (narrow-to-region start start)
-             (let ((buffer-undo-list t))
-               ;; snippet creation might evaluate users elisp, which
-               ;; might generate errors, so we have to be ready to catch
-               ;; them mostly to make the undo information
-               ;;
-               (setq yas--start-column (save-restriction (widen) 
(current-column)))
-               (yas--inhibit-overlay-hooks
-                 (setq snippet
-                       (if expand-env
-                           (eval `(let* ,expand-env
-                                    (insert content)
-                                    (yas--snippet-create (point-min) 
(point-max))))
-                         (insert content)
-                         (yas--snippet-create (point-min) (point-max)))))))
-
-           ;; stacked-expansion: This checks for stacked expansion, save the
-           ;; `yas--previous-active-field' and advance its boudary.
-           ;;
-           (let ((existing-field (and yas--active-field-overlay
-                                      (overlay-buffer 
yas--active-field-overlay)
-                                      (overlay-get yas--active-field-overlay 
'yas--field))))
-             (when existing-field
-               (setf (yas--snippet-previous-active-field snippet) 
existing-field)
-               (yas--advance-end-maybe existing-field (overlay-end 
yas--active-field-overlay))))
-
-           ;; Exit the snippet immediately if no fields
-           ;;
-           (unless (yas--snippet-fields snippet)
-             (yas-exit-snippet snippet))
-
-           ;; Push two undo actions: the deletion of the inserted contents of
-           ;; the new snippet (without the "key") followed by an apply of
-           ;; `yas--take-care-of-redo' on the newly inserted snippet boundaries
-           ;;
-           ;; A small exception, if `yas-also-auto-indent-first-line'
-           ;; is t and `yas--indent' decides to indent the line to a
-           ;; point before the actual expansion point, undo would be
-           ;; messed up. We call the early point "newstart"".  case,
-           ;; and attempt to fix undo.
-           ;;
-           (let ((newstart (overlay-start (yas--snippet-control-overlay 
snippet)))
-                 (end (overlay-end (yas--snippet-control-overlay snippet))))
-             (when (< newstart start)
-               (push (cons (make-string (- start newstart) ? ) newstart) 
buffer-undo-list))
-             (push (cons newstart end) buffer-undo-list)
-             (push `(apply yas--take-care-of-redo ,start ,end ,snippet)
-                   buffer-undo-list))
-           ;; Now, schedule a move to the first field
-           ;;
-           (let ((first-field (car (yas--snippet-fields snippet))))
-             (when first-field
-               (sit-for 0) ;; fix issue 125
-               (yas--move-to-field snippet first-field)))
-           (yas--message 3 "snippet expanded.")
-           t))))
-
-(defun yas--take-care-of-redo (beg end snippet)
-  "Commits SNIPPET, which in turn pushes an undo action for
-reviving it.
-
-Meant to exit in the `buffer-undo-list'."
-  ;; slightly optimize: this action is only needed for snippets with
-  ;; at least one field
-  (when (yas--snippet-fields snippet)
-    (yas--commit-snippet snippet)))
-
-(defun yas--snippet-revive (beg end snippet)
-  "Revives the SNIPPET and creates a control overlay from BEG to
-END.
-
-BEG and END are, we hope, the original snippets boudaries. All
-the markers/points exiting existing inside SNIPPET should point
-to their correct locations *at the time the snippet is revived*.
-
-After revival, push the `yas--take-care-of-redo' in the
-`buffer-undo-list'"
-  ;; Reconvert all the points to markers
-  ;;
-  (yas--points-to-markers snippet)
-  ;; When at least one editable field existed in the zombie snippet,
-  ;; try to revive the whole thing...
-  ;;
-  (let ((target-field (or (yas--snippet-active-field snippet)
-                          (car (yas--snippet-fields snippet)))))
-    (when target-field
-      (setf (yas--snippet-control-overlay snippet) (yas--make-control-overlay 
snippet beg end))
-      (overlay-put (yas--snippet-control-overlay snippet) 'yas--snippet 
snippet)
-
-      (yas--move-to-field snippet target-field)
-
-      (push `(apply yas--take-care-of-redo ,beg ,end ,snippet)
-            buffer-undo-list))))
-
-(defun yas--snippet-create (begin end)
-  "Creates a snippet from an template inserted between BEGIN and END.
-
-Returns the newly created snippet."
-  (let ((snippet (yas--make-snippet)))
-    (goto-char begin)
-    (yas--snippet-parse-create snippet)
-
-    ;; Sort and link each field
-    (yas--snippet-sort-fields snippet)
-
-    ;; Create keymap overlay for snippet
-    (setf (yas--snippet-control-overlay snippet)
-          (yas--make-control-overlay snippet (point-min) (point-max)))
-
-    ;; Move to end
-    (goto-char (point-max))
-
-    snippet))
-
-
-;;; Apropos adjacencies and "fom's":
-;;
-;; Once the $-constructs bits like "$n" and "${:n" are deleted in the
-;; recently expanded snippet, we might actually have many fields,
-;; mirrors (and the snippet exit) in the very same position in the
-;; buffer. Therefore we need to single-link the
-;; fields-or-mirrors-or-exit (which I have abbreviated to "fom")
-;; according to their original positions in the buffer.
-;;
-;; Then we have operation `yas--advance-end-maybe' and
-;; `yas--advance-start-maybe', which conditionally push the starts and
-;; ends of these foms down the chain.
-;;
-;; This allows for like the printf with the magic ",":
-;;
-;;   printf ("${1:%s}\\n"${1:$(if (string-match "%" text) "," "\);")}  \
-;;   $2${1:$(if (string-match "%" text) "\);" "")}$0
-;;
-(defun yas--fom-start (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-start fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-start fom))
-        (t
-         (yas--exit-marker fom))))
-
-(defun yas--fom-end (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-end fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-end fom))
-        (t
-         (yas--exit-marker fom))))
-
-(defun yas--fom-next (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-next fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-next fom))
-        (t
-         (yas--exit-next fom))))
-
-(defun yas--fom-parent-field (fom)
-  (cond ((yas--field-p fom)
-         (yas--field-parent-field fom))
-        ((yas--mirror-p fom)
-         (yas--mirror-parent-field fom))
-        (t
-         nil)))
-
-(defun yas--calculate-adjacencies (snippet)
-  "Calculate adjacencies for fields or mirrors of SNIPPET.
-
-This is according to their relative positions in the buffer, and
-has to be called before the $-constructs are deleted."
-  (flet ((yas--fom-set-next-fom (fom nextfom)
-                               (cond ((yas--field-p fom)
-                                      (setf (yas--field-next fom) nextfom))
-                                     ((yas--mirror-p fom)
-                                      (setf (yas--mirror-next fom) nextfom))
-                                     (t
-                                      (setf (yas--exit-next fom) nextfom))))
-         (yas--compare-fom-begs (fom1 fom2)
-                               (if (= (yas--fom-start fom2) (yas--fom-start 
fom1))
-                                   (yas--mirror-p fom2)
-                                 (>= (yas--fom-start fom2) (yas--fom-start 
fom1))))
-         (yas--link-foms (fom1 fom2)
-                        (yas--fom-set-next-fom fom1 fom2)))
-    ;; make some yas--field, yas--mirror and yas--exit soup
-    (let ((soup))
-      (when (yas--snippet-exit snippet)
-        (push (yas--snippet-exit snippet) soup))
-      (dolist (field (yas--snippet-fields snippet))
-        (push field soup)
-        (dolist (mirror (yas--field-mirrors field))
-          (push mirror soup)))
-      (setq soup
-            (sort soup
-                  #'yas--compare-fom-begs))
-      (when soup
-        (reduce #'yas--link-foms soup)))))
-
-(defun yas--calculate-mirrors-in-fields (snippet mirror)
-  "Attempt to assign a parent field of SNIPPET to the mirror MIRROR.
-
-Use the tighest containing field if more than one field contains
-the mirror. Intended to be called *before* the dollar-regions are
-deleted."
-  (let ((min (point-min))
-        (max (point-max)))
-    (dolist (field (yas--snippet-fields snippet))
-      (when (and (<= (yas--field-start field) (yas--mirror-start mirror))
-                 (<= (yas--mirror-end mirror) (yas--field-end field))
-               (< min (yas--field-start field))
-               (< (yas--field-end field) max))
-          (setq min (yas--field-start field)
-                max (yas--field-end field))
-          (setf (yas--mirror-parent-field mirror) field)))))
-
-(defun yas--advance-end-maybe (fom newend)
-  "Maybe advance FOM's end to NEWEND if it needs it.
-
-If it does, also:
-
-* call `yas--advance-start-maybe' on FOM's next fom.
-
-* in case FOM is field call `yas--advance-end-maybe' on its parent
-  field
-
-Also, if FOM is an exit-marker, always call
-`yas--advance-start-maybe' on its next fom. This is beacuse
-exit-marker have identical start and end markers.
-
-"
-  (cond ((and fom (< (yas--fom-end fom) newend))
-         (set-marker (yas--fom-end fom) newend)
-         (yas--advance-start-maybe (yas--fom-next fom) newend)
-         (yas--advance-end-of-parents-maybe (yas--fom-parent-field fom) 
newend))
-        ((yas--exit-p fom)
-         (yas--advance-start-maybe (yas--fom-next fom) newend))))
-
-(defun yas--advance-start-maybe (fom newstart)
-  "Maybe advance FOM's start to NEWSTART if it needs it.
-
-If it does, also call `yas--advance-end-maybe' on FOM."
-  (when (and fom (< (yas--fom-start fom) newstart))
-    (set-marker (yas--fom-start fom) newstart)
-    (yas--advance-end-maybe fom newstart)))
-
-(defun yas--advance-end-of-parents-maybe (field newend)
-  "Like `yas--advance-end-maybe' but for parent fields.
-
-Only works for fields and doesn't care about the start of the
-next FOM. Works its way up recursively for parents of parents."
-  (when (and field
-             (< (yas--field-end field) newend))
-    (set-marker (yas--field-end field) newend)
-    (yas--advance-end-of-parents-maybe (yas--field-parent-field field) 
newend)))
-
-(defvar yas--dollar-regions nil
-  "When expanding the snippet the \"parse-create\" functions add
-  cons cells to this var")
-
-(defvar yas--backquote-markers-and-strings nil
-  "List of (MARKER . STRING) marking where the the values
-  from backquoted lisp expressions should be inserted at the end of
-  expansion" )
-
-(defun yas--snippet-parse-create (snippet)
-  "Parse a recently inserted snippet template, creating all
-necessary fields, mirrors and exit points.
-
-Meant to be called in a narrowed buffer, does various passes"
-  (let ((parse-start (point)))
-    ;; Reset the yas--dollar-regions
-    ;;
-    (setq yas--dollar-regions nil)
-    ;; protect just the backquotes
-    ;;
-    (yas--protect-escapes nil '(?`))
-    ;; replace all backquoted expressions
-    ;;
-    (goto-char parse-start)
-    (yas--save-backquotes)
-    ;; protect escaped characters
-    ;;
-    (yas--protect-escapes)
-    ;; parse fields with {}
-    ;;
-    (goto-char parse-start)
-    (yas--field-parse-create snippet)
-    ;; parse simple mirrors and fields
-    ;;
-    (goto-char parse-start)
-    (yas--simple-mirror-parse-create snippet)
-    ;; parse mirror transforms
-    ;;
-    (goto-char parse-start)
-    (yas--transform-mirror-parse-create snippet)
-    ;; calculate adjacencies of fields and mirrors
-    ;;
-    (yas--calculate-adjacencies snippet)
-    ;; Delete $-constructs
-    ;;
-    (yas--delete-regions yas--dollar-regions)
-    ;; restore backquoted expression values
-    ;;
-    (yas--restore-backquotes)
-    ;; restore escapes
-    ;;
-    (goto-char parse-start)
-    (yas--restore-escapes)
-    ;; update mirrors for the first time
-    ;;
-    (yas--update-mirrors snippet)
-    ;; indent the best we can
-    ;;
-    (goto-char parse-start)
-    (yas--indent snippet)))
-
-(defun yas--indent-according-to-mode (snippet-markers)
-  "Indent current line according to mode, preserving
-SNIPPET-MARKERS."
-  ;;; Apropos indenting problems....
-  ;;
-  ;; `indent-according-to-mode' uses whatever `indent-line-function'
-  ;; is available. Some implementations of these functions delete text
-  ;; before they insert. If there happens to be a marker just after
-  ;; the text being deleted, the insertion actually happens after the
-  ;; marker, which misplaces it.
-  ;;
-  ;; This would also happen if we had used overlays with the
-  ;; `front-advance' property set to nil.
-  ;;
-  ;; This is why I have these `trouble-markers', they are the ones at
-  ;; they are the ones at the first non-whitespace char at the line
-  ;; (i.e. at `yas--real-line-beginning'. After indentation takes place
-  ;; we should be at the correct to restore them to. All other
-  ;; non-trouble-markers have been *pushed* and don't need special
-  ;; attention.
-  ;;
-  (goto-char (yas--real-line-beginning))
-  (let ((trouble-markers (remove-if-not #'(lambda (marker)
-                                            (= marker (point)))
-                                        snippet-markers)))
-    (save-restriction
-      (widen)
-      (condition-case err
-          (indent-according-to-mode)
-        (error (yas--message 3 "Warning: `yas--indent-according-to-mode' 
having problems running %s" indent-line-function)
-               nil)))
-    (mapc #'(lambda (marker)
-              (set-marker marker (point)))
-          trouble-markers)))
-
-(defvar yas--indent-original-column nil)
-(defun yas--indent (snippet)
-  (let ((snippet-markers (yas--collect-snippet-markers snippet)))
-    ;; Look for those $>
-    (save-excursion
-      (while (re-search-forward "$>" nil t)
-        (delete-region (match-beginning 0) (match-end 0))
-        (when (not (eq yas-indent-line 'auto))
-          (yas--indent-according-to-mode snippet-markers))))
-    ;; Now do stuff for 'fixed and 'auto
-    (save-excursion
-      (cond ((eq yas-indent-line 'fixed)
-             (while (and (zerop (forward-line))
-                         (zerop (current-column)))
-               (indent-to-column yas--indent-original-column)))
-            ((eq yas-indent-line 'auto)
-             (let ((end (set-marker (make-marker) (point-max)))
-                   (indent-first-line-p yas-also-auto-indent-first-line))
-               (while (and (zerop (if indent-first-line-p
-                                      (prog1
-                                          (forward-line 0)
-                                        (setq indent-first-line-p nil))
-                                    (forward-line 1)))
-                           (not (eobp))
-                           (<= (point) end))
-                 (yas--indent-according-to-mode snippet-markers))))
-            (t
-             nil)))))
-
-(defun yas--collect-snippet-markers (snippet)
-  "Make a list of all the markers used by SNIPPET."
-  (let (markers)
-    (dolist (field (yas--snippet-fields snippet))
-      (push (yas--field-start field) markers)
-      (push (yas--field-end field) markers)
-      (dolist (mirror (yas--field-mirrors field))
-        (push (yas--mirror-start mirror) markers)
-        (push (yas--mirror-end mirror) markers)))
-    (let ((snippet-exit (yas--snippet-exit snippet)))
-      (when (and snippet-exit
-                 (marker-buffer (yas--exit-marker snippet-exit)))
-        (push (yas--exit-marker snippet-exit) markers)))
-    markers))
-
-(defun yas--real-line-beginning ()
-  (let ((c (char-after (line-beginning-position)))
-        (n (line-beginning-position)))
-    (while (or (eql c ?\ )
-               (eql c ?\t))
-      (incf n)
-      (setq c (char-after n)))
-    n))
-
-(defun yas--escape-string (escaped)
-  (concat "YASESCAPE" (format "%d" escaped) "PROTECTGUARD"))
-
-(defun yas--protect-escapes (&optional text escaped)
-  "Protect all escaped characters with their numeric ASCII value.
-
-With optional string TEXT do it in string instead of buffer."
-  (let ((changed-text text)
-        (text-provided-p text))
-    (mapc #'(lambda (escaped)
-              (setq changed-text
-                    (yas--replace-all (concat "\\" (char-to-string escaped))
-                                     (yas--escape-string escaped)
-                                     (when text-provided-p changed-text))))
-          (or escaped yas--escaped-characters))
-    changed-text))
-
-(defun yas--restore-escapes (&optional text escaped)
-  "Restore all escaped characters from their numeric ASCII value.
-
-With optional string TEXT do it in string instead of the buffer."
-  (let ((changed-text text)
-        (text-provided-p text))
-    (mapc #'(lambda (escaped)
-              (setq changed-text
-                    (yas--replace-all (yas--escape-string escaped)
-                                     (char-to-string escaped)
-                                     (when text-provided-p changed-text))))
-          (or escaped yas--escaped-characters))
-    changed-text))
-
-(defun yas--save-backquotes ()
-  "Save all the \"`(lisp-expression)`\"-style expression
-with their evaluated value into `yas--backquote-markers-and-strings'"
-  (while (re-search-forward yas--backquote-lisp-expression-regexp nil t)
-    (let ((current-string (match-string-no-properties 1)) transformed)
-      (delete-region (match-beginning 0) (match-end 0))
-      (setq transformed (yas--eval-lisp (yas--read-lisp (yas--restore-escapes 
current-string '(?`)))))
-      (goto-char (match-beginning 0))
-      (when transformed
-        (let ((marker (make-marker)))
-          (insert "Y") ;; quite horrendous, I love it :)
-          (set-marker marker (point))
-          (insert "Y")
-          (push (cons marker transformed) 
yas--backquote-markers-and-strings))))))
-
-(defun yas--restore-backquotes ()
-  "Replace all the markers in
-`yas--backquote-markers-and-strings' with their values"
-  (while yas--backquote-markers-and-strings
-    (let* ((marker-and-string (pop yas--backquote-markers-and-strings))
-           (marker (car marker-and-string))
-           (string (cdr marker-and-string)))
-      (save-excursion
-        (goto-char marker)
-        (delete-char -1)
-        (insert string)
-        (delete-char 1)
-        (set-marker marker nil)))))
-
-(defun yas--scan-sexps (from count)
-  (condition-case err
-      (with-syntax-table (standard-syntax-table)
-        (scan-sexps from count))
-    (error
-     nil)))
-
-(defun yas--make-marker (pos)
-  "Create a marker at POS with `nil' `marker-insertion-type'"
-  (let ((marker (set-marker (make-marker) pos)))
-    (set-marker-insertion-type marker nil)
-    marker))
-
-(defun yas--field-parse-create (snippet &optional parent-field)
-  "Parse most field expressions, except for the simple one \"$n\".
-
-The following count as a field:
-
-* \"${n: text}\", for a numbered field with default text, as long as N is not 
0;
-
-* \"${n: text$(expression)}, the same with a lisp expression;
-  this is caught with the curiously named 
`yas--multi-dollar-lisp-expression-regexp'
-
-* the same as above but unnumbered, (no N:) and number is calculated 
automatically.
-
-When multiple expressions are found, only the last one counts."
-  ;;
-  (save-excursion
-    (while (re-search-forward yas--field-regexp nil t)
-      (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
-             (number (and (match-string-no-properties 1)
-                          (string-to-number (match-string-no-properties 1))))
-             (brand-new-field (and real-match-end-0
-                                   ;; break if on "$(" immediately
-                                   ;; after the ":", this will be
-                                   ;; caught as a mirror with
-                                   ;; transform later.
-                                   (not (save-match-data
-                                          (eq (string-match "$[ \t\n]*("
-                                                            
(match-string-no-properties 2)) 0)))
-                                   ;; allow ${0: some exit text}
-                                   ;; (not (and number (zerop number)))
-                                   (yas--make-field number
-                                                   (yas--make-marker 
(match-beginning 2))
-                                                   (yas--make-marker (1- 
real-match-end-0))
-                                                   parent-field))))
-        (when brand-new-field
-          (goto-char real-match-end-0)
-          (push (cons (1- real-match-end-0) real-match-end-0)
-                yas--dollar-regions)
-          (push (cons (match-beginning 0) (match-beginning 2))
-                yas--dollar-regions)
-          (push brand-new-field (yas--snippet-fields snippet))
-          (save-excursion
-            (save-restriction
-              (narrow-to-region (yas--field-start brand-new-field) 
(yas--field-end brand-new-field))
-              (goto-char (point-min))
-              (yas--field-parse-create snippet brand-new-field)))))))
-  ;; if we entered from a parent field, now search for the
-  ;; `yas--multi-dollar-lisp-expression-regexp'. THis is used for
-  ;; primary field transformations
-  ;;
-  (when parent-field
-    (save-excursion
-      (while (re-search-forward yas--multi-dollar-lisp-expression-regexp nil t)
-        (let* ((real-match-end-1 (yas--scan-sexps (match-beginning 1) 1)))
-          ;; commit the primary field transformation if:
-          ;;
-          ;; 1. we don't find it in yas--dollar-regions (a subnested
-          ;; field) might have already caught it.
-          ;;
-          ;; 2. we really make sure we have either two '$' or some
-          ;; text and a '$' after the colon ':'. This is a FIXME: work
-          ;; my regular expressions and end these ugly hacks.
-          ;;
-          (when (and real-match-end-1
-                     (not (member (cons (match-beginning 0)
-                                        real-match-end-1)
-                                  yas--dollar-regions))
-                     (not (eq ?:
-                              (char-before (1- (match-beginning 1))))))
-            (let ((lisp-expression-string (buffer-substring-no-properties 
(match-beginning 1)
-                                                                          
real-match-end-1)))
-              (setf (yas--field-transform parent-field)
-                    (yas--read-lisp (yas--restore-escapes 
lisp-expression-string))))
-            (push (cons (match-beginning 0) real-match-end-1)
-                  yas--dollar-regions)))))))
-
-(defun yas--transform-mirror-parse-create (snippet)
-  "Parse the \"${n:$(lisp-expression)}\" mirror transformations."
-  (while (re-search-forward yas--transform-mirror-regexp nil t)
-    (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
-           (number (string-to-number (match-string-no-properties 1)))
-           (field (and number
-                       (not (zerop number))
-                       (yas--snippet-find-field snippet number)))
-           (brand-new-mirror
-            (and real-match-end-0
-                 field
-                 (yas--make-mirror (yas--make-marker (match-beginning 0))
-                                  (yas--make-marker (match-beginning 0))
-                                  (yas--read-lisp
-                                   (yas--restore-escapes
-                                    (buffer-substring-no-properties 
(match-beginning 2)
-                                                                    (1- 
real-match-end-0))))))))
-      (when brand-new-mirror
-        (push brand-new-mirror
-              (yas--field-mirrors field))
-        (yas--calculate-mirrors-in-fields snippet brand-new-mirror)
-        (push (cons (match-beginning 0) real-match-end-0) 
yas--dollar-regions)))))
-
-(defun yas--simple-mirror-parse-create (snippet)
-  "Parse the simple \"$n\" fields/mirrors/exitmarkers."
-  (while (re-search-forward yas--simple-mirror-regexp nil t)
-    (let ((number (string-to-number (match-string-no-properties 1))))
-      (cond ((zerop number)
-
-             (setf (yas--snippet-exit snippet)
-                   (yas--make-exit (yas--make-marker (match-end 0))))
-             (save-excursion
-               (goto-char (match-beginning 0))
-               (when yas-wrap-around-region
-                 (cond (yas-selected-text
-                        (insert yas-selected-text))
-                       ((and (eq yas-wrap-around-region 'cua)
-                             cua-mode
-                             (get-register ?0))
-                        (insert (prog1 (get-register ?0)
-                                  (set-register ?0 nil))))))
-               (push (cons (point) (yas--exit-marker (yas--snippet-exit 
snippet)))
-                     yas--dollar-regions)))
-            (t
-             (let ((field (yas--snippet-find-field snippet number)))
-               (if field
-                   (let ((brand-new-mirror (yas--make-mirror
-                                            (yas--make-marker (match-beginning 
0))
-                                            (yas--make-marker (match-beginning 
0))
-                                            nil)))
-                     (push brand-new-mirror
-                           (yas--field-mirrors field))
-                     (yas--calculate-mirrors-in-fields snippet 
brand-new-mirror))
-                 (push (yas--make-field number
-                                       (yas--make-marker (match-beginning 0))
-                                       (yas--make-marker (match-beginning 0))
-                                       nil)
-                       (yas--snippet-fields snippet))))
-             (push (cons (match-beginning 0) (match-end 0))
-                   yas--dollar-regions))))))
-
-(defun yas--delete-regions (regions)
-  "Sort disjuct REGIONS by start point, then delete from the back."
-  (mapc #'(lambda (reg)
-            (delete-region (car reg) (cdr reg)))
-        (sort regions
-              #'(lambda (r1 r2)
-                  (>= (car r1) (car r2))))))
-
-(defun yas--update-mirrors (snippet)
-  "Updates all the mirrors of SNIPPET."
-  (save-excursion
-    (let* ((fields (copy-list (yas--snippet-fields snippet)))
-           (field (car fields)))
-      (while field
-        (dolist (mirror (yas--field-mirrors field))
-          (let ((mirror-parent-field (yas--mirror-parent-field mirror)))
-            ;; updatte this mirror
-            ;;
-            (yas--mirror-update-display mirror field)
-            ;; for mirrors-in-fields: schedule a possible
-            ;; parent field for reupdting later on
-            ;;
-            (when mirror-parent-field
-              (add-to-list 'fields mirror-parent-field 'append #'eq))
-            ;; `yas--place-overlays' is needed if the active field and
-            ;; protected overlays have been changed because of insertions
-            ;; in `yas--mirror-update-display'
-            ;;
-            (when (eq field (yas--snippet-active-field snippet))
-              (yas--place-overlays snippet field))))
-        (setq fields (cdr fields))
-        (setq field (car fields))))))
-
-(defun yas--mirror-update-display (mirror field)
-  "Update MIRROR according to FIELD (and mirror transform)."
-
-  (let* ((mirror-parent-field (yas--mirror-parent-field mirror))
-         (reflection (and (not (and mirror-parent-field
-                                    (yas--field-modified-p 
mirror-parent-field)))
-                          (or (yas--apply-transform mirror field 'empty-on-nil)
-                              (yas--field-text-for-display field)))))
-    (when (and reflection
-               (not (string= reflection (buffer-substring-no-properties 
(yas--mirror-start mirror)
-                                                                        
(yas--mirror-end mirror)))))
-      (goto-char (yas--mirror-start mirror))
-      (yas--inhibit-overlay-hooks
-        (insert reflection))
-      (if (> (yas--mirror-end mirror) (point))
-          (delete-region (point) (yas--mirror-end mirror))
-        (set-marker (yas--mirror-end mirror) (point))
-        (yas--advance-start-maybe (yas--mirror-next mirror) (point))
-        ;; super-special advance
-        (yas--advance-end-of-parents-maybe mirror-parent-field (point))))))
-
-(defun yas--field-update-display (field snippet)
-  "Much like `yas--mirror-update-display', but for fields"
-  (when (yas--field-transform field)
-    (let ((transformed (and (not (eq (yas--field-number field) 0))
-                            (yas--apply-transform field field)))
-          (point (point)))
-      (when (and transformed
-                 (not (string= transformed (buffer-substring-no-properties 
(yas--field-start field)
-                                                                           
(yas--field-end field)))))
-        (setf (yas--field-modified-p field) t)
-        (goto-char (yas--field-start field))
-        (yas--inhibit-overlay-hooks
-          (insert transformed)
-          (if (> (yas--field-end field) (point))
-              (delete-region (point) (yas--field-end field))
-            (set-marker (yas--field-end field) (point))
-            (yas--advance-start-maybe (yas--field-next field) (point)))
-          t)))))
-
-
-;;; Post-command hook:
-
-(defun yas--post-command-handler ()
-  "Handles various yasnippet conditions after each command."
-  (cond (yas--protection-violation
-         (goto-char yas--protection-violation)
-         (setq yas--protection-violation nil))
-        ((eq 'undo this-command)
-         ;;
-         ;; After undo revival the correct field is sometimes not
-         ;; restored correctly, this condition handles that
-         ;;
-         (let* ((snippet (car (yas--snippets-at-point)))
-                (target-field (and snippet
-                                   (find-if-not #'(lambda (field)
-                                                    
(yas--field-probably-deleted-p snippet field))
-                                                (remove nil
-                                                        (cons 
(yas--snippet-active-field snippet)
-                                                              
(yas--snippet-fields snippet)))))))
-           (when target-field
-             (yas--move-to-field snippet target-field))))
-        ((not (yas--undo-in-progress))
-         ;; When not in an undo, check if we must commit the snippet
-         ;; (user exited it).
-         (yas--check-commit-snippet))))
-
-;;; Fancy docs:
-;;
-;; The docstrings for some functions are generated dynamically
-;; depending on the context.
-;;
-(put 'yas-expand  'function-documentation
-     '(yas--expand-from-trigger-key-doc))
-(defun yas--expand-from-trigger-key-doc ()
-  "A doc synthethizer for `yas--expand-from-trigger-key-doc'."
-  (let ((fallback-description
-         (cond ((eq yas-fallback-behavior 'call-other-command)
-                (let* ((yas-minor-mode nil)
-                       (fallback (key-binding (read-kbd-macro 
(yas--trigger-key-for-fallback)))))
-                  (or (and fallback
-                           (format " call command `%s'." (pp-to-string 
fallback)))
-                      " do nothing.")))
-               ((eq yas-fallback-behavior 'return-nil)
-                ", do nothing.")
-               (t
-                ", defer to `yas--fallback-behaviour' :-)"))))
-    (concat "Expand a snippet before point. If no snippet
-expansion is possible,"
-            fallback-description
-            "\n\nOptional argument FIELD is for non-interactive use and is an
-object satisfying `yas--field-p' to restrict the expansion to.")))
-
-(put 'yas-expand-from-keymap  'function-documentation 
'(yas--expand-from-keymap-doc))
-(defun yas--expand-from-keymap-doc ()
-  "A doc synthethizer for `yas--expand-from-keymap-doc'."
-  (add-hook 'temp-buffer-show-hook 'yas--snippet-description-finish-runonce)
-  (concat "Expand/run snippets from keymaps, possibly falling back to original 
binding.\n"
-          (when (eq this-command 'describe-key)
-            (let* ((vec (this-single-command-keys))
-                   (templates (mapcan #'(lambda (table)
-                                          (yas--fetch table vec))
-                                      (yas--get-snippet-tables)))
-                   (yas--direct-keymaps nil)
-                   (fallback (key-binding vec)))
-              (concat "In this case, "
-                      (when templates
-                        (concat "these snippets are bound to this key:\n"
-                                (yas--template-pretty-list templates)
-                                "\n\nIf none of these expands, "))
-                      (or (and fallback
-                               (format "fallback `%s' will be called." 
(pp-to-string fallback)))
-                          "no fallback keybinding is called."))))))
-
-(defun yas--template-pretty-list (templates)
-  (let ((acc)
-        (yas-buffer-local-condition 'always))
-    (dolist (plate templates)
-      (setq acc (concat acc "\n*) "
-                        (propertize (concat "\\\\snippet `" (car plate) "'")
-                                    'yasnippet (cdr plate)))))
-    acc))
-
-(define-button-type 'help-snippet-def
-  :supertype 'help-xref
-  'help-function (lambda (template) (yas--visit-snippet-file-1 template))
-  'help-echo (purecopy "mouse-2, RET: find snippets's definition"))
-
-(defun yas--snippet-description-finish-runonce ()
-  "Final adjustments for the help buffer when snippets are concerned."
-  (yas--create-snippet-xrefs)
-  (remove-hook 'temp-buffer-show-hook 
'yas--snippet-description-finish-runonce))
-
-(defun yas--create-snippet-xrefs ()
-  (save-excursion
-    (goto-char (point-min))
-    (while (search-forward-regexp "\\\\\\\\snippet[ \s\t]+`\\([^']+\\)'" nil t)
-      (let ((template (get-text-property (match-beginning 1)
-                                         'yasnippet)))
-        (when template
-          (help-xref-button 1 'help-snippet-def template)
-          (kill-region (match-end 1) (match-end 0))
-          (kill-region (match-beginning 0) (match-beginning 1)))))))
-
-(defun yas--expand-uuid (mode-symbol uuid &optional start end expand-env)
-  "Expand a snippet registered in MODE-SYMBOL's table with UUID.
-
-Remaining args as in `yas-expand-snippet'."
-  (let* ((table (gethash mode-symbol yas--tables))
-         (yas--current-template (and table
-                                    (gethash uuid (yas--table-uuidhash 
table)))))
-    (when yas--current-template
-      (yas-expand-snippet (yas--template-content yas--current-template)))))
-
-;;; Utils
-
-(defvar yas-verbosity 4
-  "Log level for `yas--message' 4 means trace most anything, 0 means nothing.")
-
-(defun yas--message (level message &rest args)
-  (when (> yas-verbosity level)
-    (message (apply #'yas--format message args))))
-
-(defun yas--format (format-control &rest format-args)
-  (apply #'format (concat "[yas] " format-control) format-args))
-
-
-;;; Some hacks:
-;;
-;; The functions
-;;
-;; `locate-dominating-file'
-;; `region-active-p'
-;;
-;; added for compatibility in emacsen < 23
-(unless (>= emacs-major-version 23)
-  (unless (fboundp 'region-active-p)
-    (defun region-active-p ()  (and transient-mark-mode mark-active)))
-
-  (unless (fboundp 'locate-dominating-file)
-    (defvar locate-dominating-stop-dir-regexp
-      "\\`\\(?:[\\/][\\/][^\\/]+[\\/]\\|/\\(?:net\\|afs\\|\\.\\.\\.\\)/\\)\\'"
-      "Regexp of directory names which stop the search in 
`locate-dominating-file'.
-Any directory whose name matches this regexp will be treated like
-a kind of root directory by `locate-dominating-file' which will stop its search
-when it bumps into it.
-The default regexp prevents fruitless and time-consuming attempts to find
-special files in directories in which filenames are interpreted as hostnames,
-or mount points potentially requiring authentication as a different user.")
-
-    (defun locate-dominating-file (file name)
-      "Look up the directory hierarchy from FILE for a file named NAME.
-Stop at the first parent directory containing a file NAME,
-and return the directory.  Return nil if not found."
-      ;; We used to use the above locate-dominating-files code, but the
-      ;; directory-files call is very costly, so we're much better off doing
-      ;; multiple calls using the code in here.
-      ;;
-      ;; Represent /home/luser/foo as ~/foo so that we don't try to look for
-      ;; `name' in /home or in /.
-      (setq file (abbreviate-file-name file))
-      (let ((root nil)
-            (prev-file file)
-            ;; `user' is not initialized outside the loop because
-            ;; `file' may not exist, so we may have to walk up part of the
-            ;; hierarchy before we find the "initial UUID".
-            (user nil)
-            try)
-        (while (not (or root
-                        (null file)
-                        ;; FIXME: Disabled this heuristic because it is 
sometimes
-                        ;; inappropriate.
-                        ;; As a heuristic, we stop looking up the hierarchy of
-                        ;; directories as soon as we find a directory belonging
-                        ;; to another user.  This should save us from looking 
in
-                        ;; things like /net and /afs.  This assumes that all 
the
-                        ;; files inside a project belong to the same user.
-                        ;; (let ((prev-user user))
-                        ;;   (setq user (nth 2 (file-attributes file)))
-                        ;;   (and prev-user (not (equal user prev-user))))
-                        (string-match locate-dominating-stop-dir-regexp file)))
-          (setq try (file-exists-p (expand-file-name name file)))
-          (cond (try (setq root file))
-                ((equal file (setq prev-file file
-                                   file (file-name-directory
-                                         (directory-file-name file))))
-                 (setq file nil))))
-        root))))
-
-;; `c-neutralize-syntax-in-CPP` sometimes fires "End of Buffer" error
-;; (when it execute forward-char) and interrupt the after change
-;; hook. Thus prevent the insert-behind hook of yasnippet to be
-;; invoked. Here's a way to reproduce it:
-
-;; # open a *new* Emacs.
-;; # load yasnippet.
-;; # open a *new* .cpp file.
-;; # input "inc" and press TAB to expand the snippet.
-;; # select the `#include <...>` snippet.
-;; # type inside `<>`
-
-(defadvice c-neutralize-syntax-in-CPP
-  (around yas--mp/c-neutralize-syntax-in-CPP activate)
-  "Adviced `c-neutralize-syntax-in-CPP' to properly
-handle the end-of-buffer error fired in it by calling
-`forward-char' at the end of buffer."
-  (condition-case err
-      ad-do-it
-    (error (message (error-message-string err)))))
-
-;; disable c-electric-* serial command in YAS fields
-(add-hook 'c-mode-common-hook
-          '(lambda ()
-             (dolist (k '(":" ">" ";" "<" "{" "}"))
-               (define-key (symbol-value (make-local-variable 'yas-keymap))
-                 k 'self-insert-command))))
-
-;;; Backward compatibility to to yasnippet <= 0.7
-(defvar yas--exported-syms '(;; `defcustom's
-                             ;;
-                             yas-snippet-dirs
-                             yas-prompt-functions
-                             yas-indent-line
-                             yas-also-auto-indent-first-line
-                             yas-snippet-revival
-                             yas-trigger-key
-                             yas-next-field-key
-                             yas-prev-field-key
-                             yas-skip-and-clear-key
-                             yas-triggers-in-field
-                             yas-fallback-behavior
-                             yas-choose-keys-first
-                             yas-choose-tables-first
-                             yas-use-menu
-                             yas-trigger-symbol
-                             yas-wrap-around-region
-                             yas-good-grace
-                             yas-visit-from-menu
-                             yas-expand-only-for-last-commands
-                             yas-field-highlight-face
-
-                             ;; these vars can be customized as well
-                             ;;
-                             yas-keymap
-                             yas-verbosity
-                             yas-extra-modes
-                             yas-key-syntaxes
-                             yas-after-exit-snippet-hook
-                             yas-before-expand-snippet-hook
-                             yas-buffer-local-condition
-
-                             ;; prompting functions
-                             ;;
-                             yas-x-prompt
-                             yas-ido-prompt
-                             yas-no-prompt
-                             yas-completing-prompt
-                             yas-dropdown-prompt
-
-                             ;; interactive functions
-                             ;;
-                             yas-expand
-                             yas-minor-mode
-                             yas-global-mode
-                             yas-direct-keymaps-reload
-                             yas-minor-mode-on
-                             yas-load-directory
-                             yas-reload-all
-                             yas-compile-directory
-                             yas-recompile-all
-                             yas-about
-                             yas-expand-from-trigger-key
-                             yas-expand-from-keymap
-                             yas-insert-snippet
-                             yas-visit-snippet-file
-                             yas-new-snippet
-                             yas-load-snippet-buffer
-                             yas-tryout-snippet
-                             yas-describe-tables
-                             yas-next-field-or-maybe-expand
-                             yas-next-field
-                             yas-prev-field
-                             yas-abort-snippet
-                             yas-exit-snippet
-                             yas-exit-all-snippets
-                             yas-skip-and-clear-or-delete-char
-
-                             ;; symbols that I "exported" for use
-                             ;; in snippets and hookage
-                             ;;
-                             yas-expand-snippet
-                             yas-define-snippets
-                             yas-define-menu
-                             yas-snippet-beg
-                             yas-snippet-end
-                             yas-modified-p
-                             yas-moving-away-p
-                             yas-text
-                             yas-substr
-                             yas-choose-value
-                             yas-key-to-value
-                             yas-throw
-                             yas-verify-value
-                             yas-field-value
-                             yas-text
-                             yas-selected-text
-                             yas-default-from-field
-                             yas-inside-string
-                             yas-unimplemented
-                             yas-define-condition-cache
-                             yas-hippie-try-expand
-
-                             ;; debug definitions
-                             ;; yas-debug-snippet-vars
-                             ;; yas-exterminate-package
-                             ;; yas-debug-test
-
-                             ;; testing definitions
-                             ;; yas-should-expand
-                             ;; yas-should-not-expand
-                             ;; yas-mock-insert
-                             ;; yas-make-file-or-dirs
-                             ;; yas-variables
-                             ;; yas-saving-variables
-                             ;; yas-call-with-snippet-dirs
-                             ;; yas-with-snippet-dirs
-))
-
-(dolist (sym yas--exported-syms)
-  (let ((backported (intern (replace-regexp-in-string "^yas-" "yas/" 
(symbol-name sym)))))
-    (when (boundp sym)
-      (make-obsolete-variable backported sym "yasnippet 0.8")
-      (defvaralias backported sym))
-    (when (fboundp sym)
-      (make-obsolete backported sym "yasnippet 0.8")
-      (defalias backported sym))))
-
-
-(provide 'yasnippet)
-
-;;; yasnippet.el ends here
-;; Local Variables:
-;; coding: utf-8
-;; End:
+;;; yasnippet.el --- Yet another snippet extension for Emacs.
+
+;; Copyright (C) 2008-2012 Free Software Foundation, Inc.
+;; Authors: pluskid <address@hidden>,  João Távora <address@hidden>
+;; Version: 0.8.0
+;; Package-version: 0.8.0
+;; X-URL: http://github.com/capitaomorte/yasnippet
+;; Keywords: convenience, emulation
+;; URL: http://github.com/capitaomorte/yasnippet
+;; EmacsWiki: YaSnippetMode
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;;   Basic steps to setup:
+;;
+;;    (add-to-list 'load-path
+;;                 "~/path-to-yasnippet")
+;;    (require 'yasnippet)
+;;    (yas-global-mode 1)
+;;
+;;
+;;   Interesting variables are:
+;;
+;;       `yas-snippet-dirs'
+;;
+;;           The directory where user-created snippets are to be
+;;           stored. Can also be a list of directories. In that case,
+;;           when used for bulk (re)loading of snippets (at startup or
+;;           via `yas-reload-all'), directories appearing earlier in
+;;           the list shadow other dir's snippets. Also, the first
+;;           directory is taken as the default for storing the user's
+;;           new snippets.
+;;
+;;           The deprecated `yas/root-directory' aliases this variable
+;;           for backward-compatibility.
+;;
+;;       `yas-extra-modes'
+;;
+;;           A local variable that you can set in a hook to override
+;;           snippet-lookup based on major mode. It is a a symbol (or
+;;           list of symbols) that correspond to subdirectories of
+;;           `yas-snippet-dirs' and is used for deciding which
+;;           snippets to consider for the active buffer.
+;;
+;;           Deprecated `yas/mode-symbol' aliases this variable for
+;;           backward-compatibility.
+;;
+;;   Major commands are:
+;;
+;;       M-x yas-expand
+;;
+;;           Try to expand snippets before point.  In `yas-minor-mode',
+;;           this is bound to `yas-trigger-key' which you can customize.
+;;
+;;       M-x yas-load-directory
+;;
+;;           Prompts you for a directory hierarchy of snippets to load.
+;;
+;;       M-x yas-insert-snippet
+;;
+;;           Prompts you for possible snippet expansion if that is
+;;           possible according to buffer-local and snippet-local
+;;           expansion conditions.  With prefix argument, ignore these
+;;           conditions.
+;;
+;;       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.
+;;
+;;       M-x yas-new-snippet
+;;
+;;           Lets you create a new snippet file in the correct
+;;           subdirectory of `yas-snippet-dirs', according to the
+;;           active major mode.
+;;
+;;       M-x yas-load-snippet-buffer
+;;
+;;           When editing a snippet, this loads the snippet.  This is
+;;           bound to "C-c C-c" while in the `snippet-mode' editing
+;;           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'.
+;;
+;;       M-x yas-describe-tables
+;;
+;;           Lists known snippets in a separate buffer. User is
+;;           prompted as to whether only the currently active tables
+;;           are to be displayed, or all the tables for all major
+;;           modes.
+;;
+;;   The `dropdown-list.el' extension is bundled with YASnippet, you
+;;   can optionally use it the preferred "prompting method", puting in
+;;   your .emacs file, for example:
+;;
+;;       (require 'dropdown-list)
+;;       (setq yas-prompt-functions '(yas-dropdown-prompt
+;;                                    yas-ido-prompt
+;;                                    yas-completing-prompt))
+;;
+;;   Also check out the customization group
+;;
+;;        M-x customize-group RET yasnippet RET
+;;
+;;   If you use the customization group to set variables
+;;   `yas-snippet-dirs' or `yas-global-mode', make sure the path to
+;;   "yasnippet.el" is present in the `load-path' *before* the
+;;   `custom-set-variables' is executed in your .emacs file.
+;;
+;;   For more information and detailed usage, refer to the project page:
+;;      http://github.com/capitaomorte/yasnippet
+
+;;; Code:
+
+(require 'cl)
+(require 'easymenu)
+(require 'help-mode)
+
+
+;;; User customizable variables
+
+(defgroup yasnippet nil
+  "Yet Another Snippet extension"
+  :group 'editing)
+
+(defvar yas--load-file-name load-file-name
+  "Store the filename that yasnippet.el was originally loaded from.")
+
+(defcustom yas-snippet-dirs (remove nil
+                                    (list "~/.emacs.d/snippets"
+                                          (when yas--load-file-name
+                                            (concat (file-name-directory 
yas--load-file-name) "snippets"))))
+  "Directory or list of snippet dirs for each major mode.
+
+The directory where user-created snippets are to be stored. Can
+also be a list of directories. In that case, when used for
+bulk (re)loading of snippets (at startup or via
+`yas-reload-all'), directories appearing earlier in the list
+shadow other dir's snippets. Also, the first directory is taken
+as the default for storing the user's new snippets."
+  :type '(choice (string :tag "Single directory (string)")
+                 (repeat :args (string) :tag "List of directories (strings)"))
+  :group 'yasnippet
+  :require 'yasnippet
+  :set #'(lambda (symbol new)
+           (let ((old (and (boundp symbol)
+                           (symbol-value symbol))))
+             (set-default symbol new)
+             (unless (or (not (fboundp 'yas-reload-all))
+                         (equal old new))
+               (yas-reload-all)))))
+
+(defun yas-snippet-dirs ()
+  "Returns `yas-snippet-dirs' (which see) as a list."
+  (if (listp yas-snippet-dirs) yas-snippet-dirs (list yas-snippet-dirs)))
+
+(defvaralias 'yas/root-directory 'yas-snippet-dirs)
+
+(defcustom yas-prompt-functions '(yas-x-prompt
+                                  yas-dropdown-prompt
+                                  yas-completing-prompt
+                                  yas-ido-prompt
+                                  yas-no-prompt)
+  "Functions to prompt for keys, templates, etc interactively.
+
+These functions are called with the following arguments:
+
+- PROMPT: A string to prompt the user
+
+- CHOICES: a list of strings or objects.
+
+- optional DISPLAY-FN : A function that, when applied to each of
+the objects in CHOICES will return a string.
+
+The return value of any function you put here should be one of
+the objects in CHOICES, properly formatted with DISPLAY-FN (if
+that is passed).
+
+- To signal that your particular style of prompting is
+unavailable at the moment, you can also have the function return
+nil.
+
+- To signal that the user quit the prompting process, you can
+signal `quit' with
+
+  (signal 'quit \"user quit!\")."
+  :type '(repeat function)
+  :group 'yasnippet)
+
+(defcustom yas-indent-line 'auto
+  "Controls indenting applied to a recent snippet expansion.
+
+The following values are possible:
+
+- `fixed' Indent the snippet to the current column;
+
+- `auto' Indent each line of the snippet with `indent-according-to-mode'
+
+Every other value means don't apply any snippet-side indendation
+after expansion (the manual per-line \"$>\" indentation still
+applies)."
+  :type '(choice (const :tag "Nothing"  nothing)
+                 (const :tag "Fixed"    fixed)
+                 (const :tag "Auto"     auto))
+  :group 'yasnippet)
+
+(defcustom yas-also-auto-indent-first-line nil
+  "Non-nil means also auto indent first line according to mode.
+
+Naturally this is only valid when `yas-indent-line' is `auto'"
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-snippet-revival t
+  "Non-nil means re-activate snippet fields after undo/redo."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-trigger-key "<tab>"
+  "The key bound to `yas-expand' when `yas-minor-mode' is active.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'."
+  :type 'string
+  :group 'yasnippet
+  :set #'(lambda (symbol key)
+           (let ((old (and (boundp symbol)
+                           (symbol-value symbol))))
+             (set-default symbol key)
+             ;; On very first loading of this defcustom,
+             ;; `yas-trigger-key' is *not* loaded.
+             (if (fboundp 'yas--trigger-key-reload)
+                 (yas--trigger-key-reload old)))))
+
+(defcustom yas-next-field-key '("TAB" "<tab>")
+  "The key to navigate to next field when a snippet is active.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'.
+
+Can also be a list of strings."
+  :type '(choice (string :tag "String")
+                 (repeat :args (string) :tag "List of strings"))
+  :group 'yasnippet
+  :set #'(lambda (symbol val)
+           (set-default symbol val)
+           (if (fboundp 'yas--init-yas-in-snippet-keymap)
+               (yas--init-yas-in-snippet-keymap))))
+
+
+(defcustom yas-prev-field-key '("<backtab>" "<S-tab>")
+  "The key to navigate to previous field when a snippet is active.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'.
+
+Can also be a list of strings."
+  :type '(choice (string :tag "String")
+                 (repeat :args (string) :tag "List of strings"))
+  :group 'yasnippet
+  :set #'(lambda (symbol val)
+           (set-default symbol val)
+           (if (fboundp 'yas--init-yas-in-snippet-keymap)
+               (yas--init-yas-in-snippet-keymap))))
+
+(defcustom yas-skip-and-clear-key '("C-d" "<delete>" "<deletechar>")
+  "The key to clear the currently active field.
+
+Value is a string that is converted to the internal Emacs key
+representation using `read-kbd-macro'.
+
+Can also be a list of strings."
+  :type '(choice (string :tag "String")
+                 (repeat :args (string) :tag "List of strings"))
+  :group 'yasnippet
+  :set #'(lambda (symbol val)
+           (set-default symbol val)
+           (if (fboundp 'yas--init-yas-in-snippet-keymap)
+               (yas--init-yas-in-snippet-keymap))))
+
+(defcustom yas-triggers-in-field nil
+  "If non-nil, `yas-next-field-key' can trigger stacked expansions.
+
+Otherwise, `yas-next-field-key' just tries to move on to the next
+field"
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-fallback-behavior 'call-other-command
+  "How to act when `yas-trigger-key' does *not* expand a snippet.
+
+- `call-other-command' means try to temporarily disable YASnippet
+    and call the next command bound to `yas-trigger-key'.
+
+- nil or the symbol `return-nil' mean do nothing. (and
+  `yas-expand' returns nil)
+
+- A lisp form (apply COMMAND . ARGS) means interactively call
+  COMMAND, if ARGS is non-nil, call COMMAND non-interactively
+  with ARGS as arguments."
+  :type '(choice (const :tag "Call previous command"  call-other-command)
+                 (const :tag "Do nothing"             return-nil))
+  :group 'yasnippet)
+
+(defcustom yas-choose-keys-first nil
+  "If non-nil, prompt for snippet key first, then for template.
+
+Otherwise prompts for all possible snippet names.
+
+This affects `yas-insert-snippet' and `yas-visit-snippet-file'."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-choose-tables-first nil
+  "If non-nil, and multiple eligible snippet tables, prompts user for tables 
first.
+
+Otherwise, user chooses between the merging together of all
+eligible tables.
+
+This affects `yas-insert-snippet', `yas-visit-snippet-file'"
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-use-menu 'abbreviate
+  "Display a YASnippet menu in the menu bar.
+
+When non-nil, submenus for each snippet table will be listed
+under the menu \"Yasnippet\".
+
+- If set to `abbreviate', only the current major-mode
+menu and the modes set in `yas-extra-modes' are listed.
+
+- If set to `full', every submenu is listed
+
+- It set to nil, don't display a menu at all (this requires a
+  `yas-reload-all' call if the menu is already visible).
+
+Any other non-nil value, every submenu is listed."
+  :type '(choice (const :tag "Full"  full)
+                 (const :tag "Abbreviate" abbreviate)
+                 (const :tag "No menu" nil))
+  :group 'yasnippet)
+
+(defcustom yas-trigger-symbol (if (eq window-system 'mac)
+                                  (char-to-string ?\x21E5) ;; little ->| sign
+                                  " =>")
+  "The text that will be used in menu to represent the trigger."
+  :type 'string
+  :group 'yasnippet)
+
+(defcustom yas-wrap-around-region nil
+  "If non-nil, snippet expansion wraps around selected region.
+
+The wrapping occurs just before the snippet's exit marker.  This
+can be overriden on a per-snippet basis."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-good-grace t
+  "If non-nil, don't raise errors in inline elisp evaluation.
+
+An error string \"[yas] error\" is returned instead."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-visit-from-menu nil
+  "If non-nil visit snippets's files from menu, instead of expanding them.
+
+This cafn only work when snippets are loaded from files."
+  :type 'boolean
+  :group 'yasnippet)
+
+(defcustom yas-expand-only-for-last-commands nil
+  "List of `last-command' values to restrict tab-triggering to, or nil.
+
+Leave this set at nil (the default) to be able to trigger an
+expansion simply by placing the cursor after a valid tab trigger,
+using whichever commands.
+
+Optionallly, set this to something like '(self-insert-command) if
+you to wish restrict expansion to only happen when the last
+letter of the snippet tab trigger was typed immediately before
+the trigger key itself."
+  :type '(repeat function)
+  :group 'yasnippet)
+
+;; Only two faces, and one of them shouldn't even be used...
+;;
+(defface yas-field-highlight-face
+  '((t (:inherit 'region)))
+  "The face used to highlight the currently active field of a snippet"
+  :group 'yasnippet)
+
+(defface yas--field-debug-face
+  '()
+  "The face used for debugging some overlays normally hidden"
+  :group 'yasnippet)
+
+
+;;; User can also customize the next defvars
+
+(defun yas--define-some-keys (keys keymap definition)
+  "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'."
+  (let ((keys (or (and (listp keys) keys)
+                  (list keys))))
+    (dolist (key keys)
+      (define-key keymap (read-kbd-macro key) definition))))
+
+(defun yas--init-yas-in-snippet-keymap ()
+  (setq yas-keymap
+        (let ((map (make-sparse-keymap)))
+          (mapc #'(lambda (binding)
+                    (yas--define-some-keys (car binding) map (cdr binding)))
+                `((,yas-next-field-key     . yas-next-field-or-maybe-expand)
+                  (,yas-prev-field-key     . yas-prev-field)
+                  ("C-g"                   . yas-abort-snippet)
+                  (,yas-skip-and-clear-key . 
yas-skip-and-clear-or-delete-char)))
+          map)))
+
+(defvar yas-keymap (yas--init-yas-in-snippet-keymap)
+  "The keymap active while a snippet expansion is in progress.")
+
+(defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()" "^ ")
+  "List of character syntaxes used to find a trigger key before point.
+The list is tried in the order while scanning characters
+backwards from point. For example, if the list is '(\"w\" \"w_\")
+first look for trigger keys which are composed exclusively of
+\"word\"-syntax characters, and then, if that fails, look for
+keys which are either of \"word\" or \"symbol\"
+syntax. Triggering after
+
+foo-bar
+
+will, according to the \"w\" element first try \"bar\". If that
+isn't a trigger key, \"foo-bar\" is tried, respecting a second
+\"w_\" element.")
+
+(defvar yas-after-exit-snippet-hook
+  '()
+  "Hooks to run after a snippet exited.
+
+The hooks will be run in an environment where some variables bound to
+proper values:
+
+`yas-snippet-beg' : The beginning of the region of the snippet.
+
+`yas-snippet-end' : Similar to beg.
+
+Attention: These hooks are not run when exiting nested/stackd snippet 
expansion!")
+
+(defvar yas-before-expand-snippet-hook
+  '()
+  "Hooks to run just before expanding a snippet.")
+
+(defvar yas-buffer-local-condition
+  '(if (and (or (fourth (syntax-ppss))
+                (fifth (syntax-ppss)))
+            (eq (symbol-function this-command) 'yas-expand-from-trigger-key))
+       '(require-snippet-condition . force-in-comment)
+     t)
+  "Snippet expanding condition.
+
+This variable is a lisp form which is evaluated everytime a
+snippet expansion is attemped:
+
+    * If it evaluates to nil, no snippets can be expanded.
+
+    * If it evaluates to the a cons (require-snippet-condition
+      . REQUIREMENT)
+
+       * Snippets bearing no \"# condition:\" directive are not
+         considered
+
+       * Snippets bearing conditions that evaluate to nil (or
+         produce an error) won't be onsidered.
+
+       * If the snippet has a condition that evaluates to non-nil
+         RESULT:
+
+          * If REQUIREMENT is t, the snippet is considered
+
+          * If REQUIREMENT is `eq' RESULT, the snippet is
+            considered
+
+          * Otherwise, the snippet is not considered.
+
+    * If it evaluates to the symbol 'always, all snippets are
+      considered for expansion, regardless of any conditions.
+
+    * If it evaluates to t or some other non-nil value
+
+       * Snippet bearing no conditions, or conditions that
+         evaluate to non-nil, are considered for expansion.
+
+       * Otherwise, the snippet is not considered.
+
+Here's an example preventing snippets from being expanded from
+inside comments, in `python-mode' only, with the exception of
+snippets returning the symbol 'force-in-comment in their
+conditions.
+
+ (add-hook 'python-mode-hook
+           '(lambda ()
+              (setq yas-buffer-local-condition
+                    '(if (python-in-string/comment)
+                         '(require-snippet-condition . force-in-comment)
+                       t))))
+
+The default value is similar, it filters out potential snippet
+expansions inside comments and string literals, unless the
+snippet itself contains a condition that returns the symbol
+`force-in-comment'.")
+
+
+;;; Internal variables
+
+(defvar yas--version "0.8.0 (beta)")
+
+(defvar yas--menu-table (make-hash-table)
+  "A hash table of MAJOR-MODE symbols to menu keymaps.")
+
+(defvar yas--known-modes
+  '(ruby-mode rst-mode markdown-mode)
+  "A list of mode which is well known but not part of emacs.")
+
+(defvar yas--escaped-characters
+  '(?\\ ?` ?\" ?' ?$ ?} ?{ ?\( ?\))
+  "List of characters which *might* need to be escaped.")
+
+(defconst yas--field-regexp
+  "${\\([0-9]+:\\)?\\([^}]*\\)}"
+  "A regexp to *almost* recognize a field.")
+
+(defconst yas--multi-dollar-lisp-expression-regexp
+  "$+[ \t\n]*\\(([^)]*)\\)"
+  "A regexp to *almost* recognize a \"$(...)\" expression.")
+
+(defconst yas--backquote-lisp-expression-regexp
+  "`\\([^`]*\\)`"
+  "A regexp to recognize a \"`lisp-expression`\" expression." )
+
+(defconst yas--transform-mirror-regexp
+  "${\\(?:\\([0-9]+\\):\\)?$\\([ \t\n]*([^}]*\\)"
+  "A regexp to *almost* recognize a mirror with a transform.")
+
+(defconst yas--simple-mirror-regexp
+  "$\\([0-9]+\\)"
+  "A regexp to recognize a simple mirror.")
+
+(defvar yas--snippet-id-seed 0
+  "Contains the next id for a snippet.")
+
+(defun yas--snippet-next-id ()
+  (let ((id yas--snippet-id-seed))
+    (incf yas--snippet-id-seed)
+    id))
+
+
+;;; Minor mode stuff
+
+;; XXX: `last-buffer-undo-list' is somehow needed in Carbon Emacs for MacOSX
+(defvar last-buffer-undo-list nil)
+
+(defvar yas--minor-mode-menu nil
+  "Holds the YASnippet menu")
+
+(defun yas--init-minor-keymap ()
+  (let ((map (make-sparse-keymap)))
+    (when yas-use-menu
+      (easy-menu-define yas--minor-mode-menu
+      map
+      "Menu used when `yas-minor-mode' is active."
+      '("YASnippet"
+        "----"
+        ["Expand trigger" yas-expand
+         :help "Possibly expand tab trigger before point"]
+        ["Insert at point..." yas-insert-snippet
+         :help "Prompt for an expandable snippet and expand it at point"]
+        ["New snippet..." yas-new-snippet
+         :help "Create a new snippet in an appropriate directory"]
+        ["Visit snippet file..." yas-visit-snippet-file
+         :help "Prompt for an expandable snippet and find its file"]
+        "----"
+        ("Snippet menu behaviour"
+         ["Visit snippets" (setq yas-visit-from-menu t)
+          :help "Visit snippets from the menu"
+          :active t :style radio   :selected yas-visit-from-menu]
+         ["Expand snippets" (setq yas-visit-from-menu nil)
+          :help "Expand snippets from the menu"
+          :active t :style radio :selected (not yas-visit-from-menu)]
+         "----"
+         ["Show all known modes" (setq yas-use-menu 'full)
+          :help "Show one snippet submenu for each loaded table"
+          :active t :style radio   :selected (eq yas-use-menu 'full)]
+         ["Abbreviate according to current mode" (setq yas-use-menu 
'abbreviate)
+          :help "Show only snippet submenus for the current active modes"
+          :active t :style radio   :selected (eq yas-use-menu 'abbreviate)])
+        ("Indenting"
+         ["Auto" (setq yas-indent-line 'auto)
+          :help "Indent each line of the snippet with 
`indent-according-to-mode'"
+          :active t :style radio   :selected (eq yas-indent-line 'auto)]
+         ["Fixed" (setq yas-indent-line 'fixed)
+          :help "Indent the snippet to the current column"
+          :active t :style radio   :selected (eq yas-indent-line 'fixed)]
+         ["None" (setq yas-indent-line 'none)
+          :help "Don't apply any particular snippet indentation after 
expansion"
+          :active t :style radio   :selected (not (member yas-indent-line 
'(fixed auto)))]
+         "----"
+         ["Also auto indent first line" (setq yas-also-auto-indent-first-line
+                                              (not 
yas-also-auto-indent-first-line))
+          :help "When auto-indenting also, auto indent the first line menu"
+          :active (eq yas-indent-line 'auto)
+          :style toggle :selected yas-also-auto-indent-first-line]
+         )
+        ("Prompting method"
+         ["System X-widget" (setq yas-prompt-functions
+                                  (cons 'yas-x-prompt
+                                        (remove 'yas-x-prompt
+                                                yas-prompt-functions)))
+          :help "Use your windowing system's (gtk, mac, windows, etc...) 
default menu"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-x-prompt)]
+         ["Dropdown-list" (setq yas-prompt-functions
+                                (cons 'yas-dropdown-prompt
+                                      (remove 'yas-dropdown-prompt
+                                              yas-prompt-functions)))
+          :help "Use a special dropdown list"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-dropdown-prompt)]
+         ["Ido" (setq yas-prompt-functions
+                      (cons 'yas-ido-prompt
+                            (remove 'yas-ido-prompt
+                                    yas-prompt-functions)))
+          :help "Use an ido-style minibuffer prompt"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-ido-prompt)]
+         ["Completing read" (setq yas-prompt-functions
+                                  (cons 'yas-completing-prompt
+                                        (remove 'yas-completing-prompt
+                                                yas-prompt-functions)))
+          :help "Use a normal minibuffer prompt"
+          :active t :style radio   :selected (eq (car yas-prompt-functions)
+                                                 'yas-completing-prompt)]
+         )
+        ("Misc"
+         ["Wrap region in exit marker"
+          (setq yas-wrap-around-region
+                (not yas-wrap-around-region))
+          :help "If non-nil automatically wrap the selected text in the $0 
snippet exit"
+          :style toggle :selected yas-wrap-around-region]
+         ["Allow stacked expansions "
+          (setq yas-triggers-in-field
+                (not yas-triggers-in-field))
+          :help "If non-nil allow snippets to be triggered inside other 
snippet fields"
+          :style toggle :selected yas-triggers-in-field]
+         ["Revive snippets on undo "
+          (setq yas-snippet-revival
+                (not yas-snippet-revival))
+          :help "If non-nil allow snippets to become active again after undo"
+          :style toggle :selected yas-snippet-revival]
+         ["Good grace "
+          (setq yas-good-grace
+                (not yas-good-grace))
+          :help "If non-nil don't raise errors in bad embedded eslip in 
snippets"
+          :style toggle :selected yas-good-grace]
+         )
+        "----"
+        ["Load snippets..."  yas-load-directory
+         :help "Load snippets from a specific directory"]
+        ["Reload everything" yas-reload-all
+         :help "Cleanup stuff, reload snippets, rebuild menus"]
+        ["About"            yas-about
+         :help "Display some information about YASsnippet"])))
+
+    ;; Now for the stuff that has direct keybindings
+    ;;
+    (define-key map "\C-c&\C-s" 'yas-insert-snippet)
+    (define-key map "\C-c&\C-n" 'yas-new-snippet)
+    (define-key map "\C-c&\C-v" 'yas-visit-snippet-file)
+    map))
+
+(defvar yas-minor-mode-map (yas--init-minor-keymap)
+  "The keymap used when `yas-minor-mode' is active.")
+
+(defun yas--trigger-key-reload (&optional unbind-key)
+  "Rebind `yas-expand' to the new value of `yas-trigger-key'.
+
+With optional UNBIND-KEY, try to unbind that key from
+`yas-minor-mode-map'."
+  (when (and unbind-key
+             (stringp unbind-key)
+             (not (string= unbind-key "")))
+    (define-key yas-minor-mode-map (read-kbd-macro unbind-key) nil))
+  (when  (and yas-trigger-key
+              (stringp yas-trigger-key)
+              (not (string= yas-trigger-key "")))
+    (define-key yas-minor-mode-map (read-kbd-macro yas-trigger-key) 
'yas-expand)))
+
+(defvar yas--tables (make-hash-table)
+  "A hash table of mode symbols to `yas--table' objects.")
+
+(defvar yas--parents (make-hash-table)
+  "A hash table of mode symbols do lists of direct parent mode symbols.
+
+This list is populated when reading the \".yas-parents\" files
+found when traversing snippet directories with
+`yas-load-directory'.
+
+There might be additionalal parenting information stored in the
+`derived-mode-parent' property of some mode symbols, but that is
+not recorded here.")
+
+(defvar yas--direct-keymaps (list)
+  "Keymap alist supporting direct snippet keybindings.
+
+This variable is is placed in `emulation-mode-map-alists'.
+
+Its elements looks like (TABLE-NAME . KEYMAP). They're
+instantiated on `yas-reload-all' but KEYMAP is added to only when
+loading snippets. `yas--direct-TABLE-NAME' is then a variable set
+buffer-locally when entering `yas-minor-mode'. KEYMAP binds all
+defined direct keybindings to the command
+`yas-expand-from-keymap' which then which snippet to expand.")
+
+(defun yas-direct-keymaps-reload ()
+  "Force reload the direct keybinding for active snippet tables."
+  (interactive)
+  (setq yas--direct-keymaps nil)
+  (maphash #'(lambda (name table)
+               (push (cons (intern (format "yas--direct-%s" name))
+                           (yas--table-direct-keymap table))
+                     yas--direct-keymaps))
+           yas--tables))
+
+(defun yas--modes-to-activate ()
+  "Compute list of mode symbols that are active for `yas-expand'
+and friends."
+  (let ((modes-to-activate (list major-mode))
+        (mode major-mode))
+    (while (setq mode (get mode 'derived-mode-parent))
+      (push mode modes-to-activate))
+    (dolist (mode (yas-extra-modes))
+      (push mode modes-to-activate))
+    (remove-duplicates
+     (append modes-to-activate
+             (mapcan #'(lambda (mode)
+                         (yas--all-parents mode))
+                     modes-to-activate)))))
+
+(defvar yas-minor-mode-hook nil
+  "Hook run when yas-minor-mode is turned on")
+
+;;;###autoload
+(define-minor-mode yas-minor-mode
+  "Toggle YASnippet mode.
+
+When YASnippet mode is enabled, the `yas-trigger-key' key expands
+snippets of code depending on the major mode.
+
+With no argument, this command toggles the mode.
+positive prefix argument turns on the mode.
+Negative prefix argument turns off the mode.
+
+You can customize the key through `yas-trigger-key'.
+
+Key bindings:
+\\{yas-minor-mode-map}"
+  nil
+  ;; The indicator for the mode line.
+  " yas"
+  :group 'yasnippet
+  (cond (yas-minor-mode
+         ;; Reload the trigger key
+         ;;
+         (yas--trigger-key-reload)
+         ;; Install the direct keymaps in `emulation-mode-map-alists'
+         ;; (we use `add-hook' even though it's not technically a hook,
+         ;; but it works). Then define variables named after modes to
+         ;; index `yas--direct-keymaps'.
+         ;;
+         ;; Also install the post-command-hook.
+         ;;
+         (add-hook 'emulation-mode-map-alists 'yas--direct-keymaps)
+         (add-hook 'post-command-hook 'yas--post-command-handler nil t)
+         ;; Set the `yas--direct-%s' vars for direct keymap expansion
+         ;;
+         (dolist (mode (yas--modes-to-activate))
+           (let ((name (intern (format "yas--direct-%s" mode))))
+             (set-default name nil)
+             (set (make-local-variable name) t)))
+         ;; Perform JIT loads
+         ;;
+         (yas--load-pending-jits))
+        (t
+         ;; Uninstall the direct keymaps and the post-command hook
+         ;;
+         (remove-hook 'post-command-hook 'yas--post-command-handler t)
+         (remove-hook 'emulation-mode-map-alists 'yas--direct-keymaps))))
+
+(defvar yas--dont-activate '(minibufferp)
+  "If non-nil don't let `yas-minor-mode-on' active yas for this buffer.
+
+If a function, then its result is used.
+
+If a list of functions, then all functions must return nil to
+activate yas for this buffer.
+
+`yas-minor-mode-on' is usually called by `yas-global-mode' so
+this effectively lets you define exceptions to the \"global\"
+behaviour. Can also be a function of zero arguments.")
+(make-variable-buffer-local 'yas--dont-activate)
+
+(defun yas-minor-mode-on ()
+  "Turn on YASnippet minor mode.
+
+Do this unless `yas--dont-activate' is truish "
+  (interactive)
+  (unless (cond ((functionp yas--dont-activate)
+                 (funcall yas--dont-activate))
+                ((consp yas--dont-activate)
+                 (some #'funcall yas--dont-activate))
+                (yas--dont-activate))
+    ;; Load all snippets definitions unless we still don't have a
+    ;; root-directory or some snippets have already been loaded.
+    ;;
+    (yas-minor-mode 1)))
+
+;;;###autoload
+(define-globalized-minor-mode yas-global-mode yas-minor-mode yas-minor-mode-on
+  :group 'yasnippet
+  :require 'yasnippet)
+
+(defun yas--global-mode-reload-with-jit-maybe ()
+  (when yas-global-mode (yas-reload-all)))
+
+(add-hook 'yas-global-mode-hook 'yas--global-mode-reload-with-jit-maybe)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Major mode stuff
+;;
+(defvar yas--font-lock-keywords
+  (append '(("^#.*$" . font-lock-comment-face))
+          lisp-font-lock-keywords
+          lisp-font-lock-keywords-1
+          lisp-font-lock-keywords-2
+          '(("$\\([0-9]+\\)"
+             (0 font-lock-keyword-face)
+             (1 font-lock-string-face t))
+            ("${\\([0-9]+\\):?"
+             (0 font-lock-keyword-face)
+             (1 font-lock-warning-face t))
+            ("${" font-lock-keyword-face)
+            ("$[0-9]+?" font-lock-preprocessor-face)
+            ("\\(\\$(\\)" 1 font-lock-preprocessor-face)
+            ("}"
+             (0 font-lock-keyword-face)))))
+
+(defun yas--init-major-keymap ()
+  (let ((map (make-sparse-keymap)))
+    (easy-menu-define nil
+      map
+      "Menu used when snippet-mode is active."
+      (cons "Snippet"
+            (mapcar #'(lambda (ent)
+                        (when (third ent)
+                          (define-key map (third ent) (second ent)))
+                        (vector (first ent) (second ent) t))
+                    (list
+                     (list "Load this snippet" 'yas-load-snippet-buffer 
"\C-c\C-c")
+                     (list "Try out this snippet" 'yas-tryout-snippet 
"\C-c\C-t")))))
+    map))
+
+(defvar snippet-mode-map
+  (yas--init-major-keymap)
+  "The keymap used when `snippet-mode' is active")
+
+
+(define-derived-mode snippet-mode text-mode "Snippet"
+  "A mode for editing yasnippets"
+  (setq font-lock-defaults '(yas--font-lock-keywords))
+  (set (make-local-variable 'require-final-newline) nil)
+  (set (make-local-variable 'comment-start) "#")
+  (set (make-local-variable 'comment-start-skip) "#+[\t ]*"))
+
+
+
+;;; Internal structs for template management
+
+(defstruct (yas--template (:constructor yas--make-blank-template))
+  "A template for a snippet."
+  key
+  content
+  name
+  condition
+  expand-env
+  file
+  keybinding
+  uuid
+  menu-binding-pair
+  group      ;; as dictated by the #group: directive or .yas-make-groups
+  perm-group ;; as dictated by `yas-define-menu'
+  table
+  )
+
+(defun yas--populate-template (template &rest args)
+  "Helper function to populate a template with properties"
+  (let (p v)
+    (while args
+      (aset template
+            (position (intern (substring (symbol-name (car args)) 1))
+                      (mapcar #'car (get 'yas--template 'cl-struct-slots)))
+            (second args))
+      (setq args (cddr args)))
+    template))
+
+(defstruct (yas--table (:constructor yas--make-snippet-table (name)))
+  "A table to store snippets for a particular mode.
+
+Has the following fields:
+
+`yas--table-name'
+
+  A symbol name normally corresponding to a major mode, but can
+  also be a pseudo major-mode to be referenced in
+  `yas-extra-modes', for example.
+
+`yas--table-hash'
+
+  A hash table (KEY . NAMEHASH), known as the \"keyhash\". KEY is
+  a string or a vector, where the former is the snippet's trigger
+  and the latter means it's a direct keybinding. NAMEHASH is yet
+  another hash of (NAME . TEMPLATE) where NAME is the snippet's
+  name and TEMPLATE is a `yas--template' object.
+
+`yas--table-direct-keymap'
+
+  A keymap for the snippets in this table that have direct
+  keybindings. This is kept in sync with the keyhash, i.e., all
+  the elements of the keyhash that are vectors appear here as
+  bindings to `yas-expand-from-keymap'.
+
+`yas--table-uuidhash'
+
+  A hash table mapping snippets uuid's to the same `yas--template'
+  objects. A snippet uuid defaults to the snippet's name.
+"
+  name
+  (hash (make-hash-table :test 'equal))
+  (uuidhash (make-hash-table :test 'equal))
+  (parents nil)
+  (direct-keymap (make-sparse-keymap)))
+
+(defun yas--get-template-by-uuid (mode uuid)
+  "Find the snippet template in MODE by its UUID."
+  (let* ((table (gethash mode yas--tables mode)))
+    (when table
+      (gethash uuid (yas--table-uuidhash table)))))
+
+;; Apropos storing/updating in TABLE, this works in two steps:
+;;
+;; 1. `yas--remove-template-by-uuid' removes any
+;;    keyhash-namehash-template mappings from TABLE, grabing the
+;;    snippet by its uuid. Also removes mappings from TABLE's
+;;    `yas--table-direct-keymap' (FIXME: and should probably take care
+;;    of potentially stale menu bindings right?.)
+;;
+;; 2. `yas--add-template' adds this all over again.
+;;
+;;    Create a new or add to an existing keyhash-namehash mapping.
+;;
+;;  For reference on understanding this, consider three snippet
+;;  definitions:
+;;
+;;  A:   # name: The Foo
+;;       # key: foo
+;;       # binding: C-c M-l
+;;
+;;  B:   # name: Mrs Foo
+;;       # key: foo
+;;
+;;  C:   # name: The Bar
+;;       # binding: C-c M-l
+;;
+;;  D:   # name: Baz
+;;       # key: baz
+;;
+;;  keyhash       namehashes(3)      yas--template structs(4)
+;;  -----------------------------------------------------
+;;                                            __________
+;;                                           /          \
+;;  "foo"      --->  "The Foo" --->  [yas--template A]   |
+;;                   "Mrs Foo" --->  [yas--template B]   |
+;;                                                      |
+;;  [C-c M-l]  --->  "The Foo" -------------------------/
+;;                   "The Bar" --->  [yas--template C]
+;;
+;;  "baz"      --->  "Baz"     --->  [yas--template D]
+;;
+;; Additionally, since uuid defaults to the name, we have a
+;; `yas--table-uuidhash' for TABLE
+;;
+;; uuidhash       yas--template structs
+;; -------------------------------
+;; "The Foo" ---> [yas--template A]
+;; "Mrs Foo" ---> [yas--template B]
+;; "The Bar" ---> [yas--template C]
+;; "Baz"     ---> [yas--template D]
+;;
+;; FIXME: the more I look at this data-structure the more I think I'm
+;; stupid. There has to be an easier way (but beware lots of code
+;; depends on this).
+;;
+(defun yas--remove-template-by-uuid (table uuid)
+  "Remove from TABLE a template identified by UUID."
+  (let ((template (gethash uuid (yas--table-uuidhash table))))
+    (when template
+      (let* ((name                (yas--template-name template))
+             (empty-keys          nil))
+        ;; Remove the name from each of the targeted namehashes
+        ;;
+        (maphash #'(lambda (k v)
+                     (let ((template (gethash name v)))
+                       (when (and template
+                                  (eq uuid (yas--template-uuid template)))
+                         (remhash name v)
+                         (when (zerop (hash-table-count v))
+                           (push k empty-keys)))))
+                 (yas--table-hash table))
+        ;; Remove the namehash themselves if they've become empty
+        ;;
+        (dolist (key empty-keys)
+          (when (vectorp key)
+            (define-key (yas--table-direct-keymap table) key nil))
+          (remhash key (yas--table-hash table)))
+
+        ;; Finally, remove the uuid from the uuidhash
+        ;;
+        (remhash uuid (yas--table-uuidhash table))))))
+
+(defun yas--add-template (table template)
+  "Store in TABLE the snippet template TEMPLATE.
+
+KEY can be a string (trigger key) of a vector (direct
+keybinding)."
+  (let ((name (yas--template-name template))
+        (key (yas--template-key template))
+        (keybinding (yas--template-keybinding template))
+        (menu-binding-pair (yas--template-menu-binding-pair-get-create 
template)))
+    (dolist (k (remove nil (list key keybinding)))
+      (puthash name
+               template
+               (or (gethash k
+                            (yas--table-hash table))
+                   (puthash k
+                            (make-hash-table :test 'equal)
+                            (yas--table-hash table))))
+      (when (vectorp k)
+        (define-key (yas--table-direct-keymap table) k 
'yas-expand-from-keymap)))
+
+    ;; Update TABLE's `yas--table-uuidhash'
+    (puthash (yas--template-uuid template)
+             template
+             (yas--table-uuidhash table))))
+
+(defun yas--update-template (table template)
+  "Add or update TEMPLATE in TABLE.
+
+Also takes care of adding and updating to the associated menu."
+  ;; Remove from table by uuid
+  ;;
+  (yas--remove-template-by-uuid table (yas--template-uuid template))
+  ;; Add to table again
+  ;;
+  (yas--add-template table template)
+  ;; Take care of the menu
+  ;;
+  (when yas-use-menu
+    (yas--update-template-menu table template)))
+
+(defun yas--update-template-menu (table template)
+  "Update every menu-related for TEMPLATE"
+  (let ((menu-binding-pair (yas--template-menu-binding-pair-get-create 
template))
+        (key (yas--template-key template))
+        (keybinding (yas--template-keybinding template)))
+    ;; The snippet might have changed name or keys, so update
+    ;; user-visible strings
+    ;;
+    (unless (eq (cdr menu-binding-pair) :none)
+      ;; the menu item name
+      ;;
+      (setf (cadar menu-binding-pair) (yas--template-name template))
+      ;; the :keys information (also visible to the user)
+      (setf (getf (cdr (car menu-binding-pair)) :keys)
+            (or (and keybinding (key-description keybinding))
+                (and key (concat key yas-trigger-symbol))))))
+  (unless (yas--template-menu-managed-by-yas-define-menu template)
+    (let ((menu-keymap
+           (yas--menu-keymap-get-create (yas--table-mode table)
+                                        (mapcar #'yas--table-mode
+                                                (yas--table-parents table))))
+          (group (yas--template-group template)))
+      ;; Remove from menu keymap
+      ;;
+      (assert menu-keymap)
+      (yas--delete-from-keymap menu-keymap (yas--template-uuid template))
+
+      ;; Add necessary subgroups as necessary.
+      ;;
+      (dolist (subgroup group)
+        (let ((subgroup-keymap (lookup-key menu-keymap (vector (make-symbol 
subgroup)))))
+          (unless (and subgroup-keymap
+                       (keymapp subgroup-keymap))
+            (setq subgroup-keymap (make-sparse-keymap))
+            (define-key menu-keymap (vector (make-symbol subgroup))
+              `(menu-item ,subgroup ,subgroup-keymap)))
+          (setq menu-keymap subgroup-keymap)))
+
+      ;; Add this entry to the keymap
+      ;;
+      (define-key menu-keymap
+        (vector (make-symbol (yas--template-uuid template)))
+        (car (yas--template-menu-binding-pair template))))))
+
+(defun yas--namehash-templates-alist (namehash)
+  (let (alist)
+    (maphash #'(lambda (k v)
+                 (push (cons k v) alist))
+             namehash)
+    alist))
+
+(defun yas--fetch (table key)
+  "Fetch templates in TABLE by KEY.
+
+Return a list of cons (NAME . TEMPLATE) where NAME is a
+string and TEMPLATE is a `yas--template' structure."
+  (let* ((keyhash (yas--table-hash table))
+         (namehash (and keyhash (gethash key keyhash))))
+    (when namehash
+      (yas--filter-templates-by-condition (yas--namehash-templates-alist 
namehash)))))
+
+
+;;; Filtering/condition logic
+
+(defun yas--eval-condition (condition)
+  (condition-case err
+      (save-excursion
+        (save-restriction
+          (save-match-data
+            (eval condition))))
+    (error (progn
+             (yas--message 1 "Error in condition evaluation: %s" 
(error-message-string err))
+             nil))))
+
+
+(defun yas--filter-templates-by-condition (templates)
+  "Filter the templates using the applicable condition.
+
+TEMPLATES is a list of cons (NAME . TEMPLATE) where NAME is a
+string and TEMPLATE is a `yas--template' structure.
+
+This function implements the rules described in
+`yas-buffer-local-condition'.  See that variables documentation."
+  (let ((requirement (yas--require-template-specific-condition-p)))
+    (if (eq requirement 'always)
+        templates
+      (remove-if-not #'(lambda (pair)
+                         (yas--template-can-expand-p
+                          (yas--template-condition (cdr pair)) requirement))
+                     templates))))
+
+(defun yas--require-template-specific-condition-p ()
+  "Decides if this buffer requests/requires snippet-specific
+conditions to filter out potential expansions."
+  (if (eq 'always yas-buffer-local-condition)
+      'always
+    (let ((local-condition (or (and (consp yas-buffer-local-condition)
+                                    (yas--eval-condition 
yas-buffer-local-condition))
+                               yas-buffer-local-condition)))
+      (when local-condition
+        (if (eq local-condition t)
+            t
+          (and (consp local-condition)
+               (eq 'require-snippet-condition (car local-condition))
+               (symbolp (cdr local-condition))
+               (cdr local-condition)))))))
+
+(defun yas--template-can-expand-p (condition requirement)
+  "Evaluates CONDITION and REQUIREMENT and returns a boolean"
+  (let* ((result (or (null condition)
+                     (yas--eval-condition condition))))
+    (cond ((eq requirement t)
+           result)
+          (t
+           (eq requirement result)))))
+
+(defun yas--all-parents (mode)
+  "Returns a list of all parent modes of MODE"
+  (let ((parents (gethash mode yas--parents)))
+    (append parents
+            (mapcan #'yas--all-parents parents))))
+
+(defun yas--table-templates (table)
+  (when table
+    (let ((acc (list)))
+      (maphash #'(lambda (key namehash)
+                   (maphash #'(lambda (name template)
+                                (push (cons name template) acc))
+                            namehash))
+               (yas--table-hash table))
+      (yas--filter-templates-by-condition acc))))
+
+(defun yas--current-key ()
+  "Get the key under current position. A key is used to find
+the template of a snippet in the current snippet-table."
+  (let ((start (point))
+        (end (point))
+        (syntaxes yas-key-syntaxes)
+        syntax
+        done
+        templates)
+    (while (and (not done) syntaxes)
+      (setq syntax (car syntaxes))
+      (setq syntaxes (cdr syntaxes))
+      (save-excursion
+        (skip-syntax-backward syntax)
+        (setq start (point)))
+      (setq templates
+            (mapcan #'(lambda (table)
+                        (yas--fetch table (buffer-substring-no-properties 
start end)))
+                    (yas--get-snippet-tables)))
+      (if templates
+          (setq done t)
+        (setq start end)))
+    (list templates
+          start
+          end)))
+
+
+(defun yas--table-all-keys (table)
+  (when table
+    (let ((acc))
+      (maphash #'(lambda (key namehash)
+                   (when (yas--filter-templates-by-condition 
(yas--namehash-templates-alist namehash))
+                     (push key acc)))
+               (yas--table-hash table))
+      acc)))
+
+(defun yas--table-mode (table)
+  (intern (yas--table-name table)))
+
+
+;;; Internal functions:
+
+(defun yas--real-mode? (mode)
+  "Try to find out if MODE is a real mode. The MODE bound to
+a function (like `c-mode') is considered real mode. Other well
+known mode like `ruby-mode' which is not part of Emacs might
+not bound to a function until it is loaded. So yasnippet keeps
+a list of modes like this to help the judgement."
+  (or (fboundp mode)
+      (find mode yas--known-modes)))
+
+(defun yas--eval-lisp (form)
+  "Evaluate FORM and convert the result to string."
+  (let ((retval (catch 'yas--exception
+                  (condition-case err
+                      (save-excursion
+                        (save-restriction
+                          (save-match-data
+                            (widen)
+                            (let ((result (eval form)))
+                              (when result
+                                (format "%s" result))))))
+                    (error (if yas-good-grace
+                               (yas--format "elisp error! %s" 
(error-message-string err))
+                             (error (yas--format "elisp error: %s"
+                                            (error-message-string err)))))))))
+    (when (and (consp retval)
+               (eq 'yas--exception (car retval)))
+      (error (cdr retval)))
+    retval))
+
+(defun yas--eval-lisp-no-saves (form)
+  (condition-case err
+      (eval form)
+    (error (if yas-good-grace
+               (yas--format "elisp error! %s" (error-message-string err))
+             (error (yas--format "elisp error: %s"
+                            (error-message-string err)))))))
+
+(defun yas--read-lisp (string &optional nil-on-error)
+  "Read STRING as a elisp expression and return it.
+
+In case STRING in an invalid expression and NIL-ON-ERROR is nil,
+return an expression that when evaluated will issue an error."
+  (condition-case err
+      (read string)
+    (error (and (not nil-on-error)
+                `(error (error-message-string ,err))))))
+
+(defun yas--read-keybinding (keybinding)
+  "Read KEYBINDING as a snippet keybinding, return a vector."
+  (when (and keybinding
+             (not (string-match "keybinding" keybinding)))
+    (condition-case err
+        (let ((res (or (and (string-match "^\\[.*\\]$" keybinding)
+                            (read keybinding))
+                       (read-kbd-macro keybinding 'need-vector))))
+          res)
+      (error
+       (yas--message 3 "warning: keybinding \"%s\" invalid since %s."
+                keybinding (error-message-string err))
+       nil))))
+
+(defvar yas-extra-modes nil
+  "If non-nil, also lookup snippets for this/these modes.
+
+Can be a symbol or a list of symbols.
+
+This variable probably makes more sense as buffer-local, so
+ensure your use `make-local-variable' when you set it.")
+(defun yas-extra-modes ()
+  (if (listp yas-extra-modes) yas-extra-modes (list yas-extra-modes)))
+(defvaralias 'yas/mode-symbol 'yas-extra-modes)
+
+(defun yas--table-get-create (mode)
+  "Get or create the snippet table corresponding to MODE."
+  (let ((table (gethash mode
+                        yas--tables)))
+    (unless table
+      (setq table (yas--make-snippet-table (symbol-name mode)))
+      (puthash mode table yas--tables)
+      (push (cons (intern (format "yas--direct-%s" mode))
+                  (yas--table-direct-keymap table))
+            yas--direct-keymaps))
+    table))
+
+(defun yas--get-snippet-tables ()
+  "Get snippet tables for current buffer.
+
+Return a list of `yas--table' objects. The list of modes to
+consider is returned by `yas--modes-to-activate'"
+  (remove nil
+          (mapcar #'(lambda (mode-name)
+                      (gethash mode-name yas--tables))
+                  (yas--modes-to-activate))))
+
+(defun yas--menu-keymap-get-create (mode &optional parents)
+  "Get or create the menu keymap for MODE and its PARENTS.
+
+This may very well create a plethora of menu keymaps and arrange
+them all in `yas--menu-table'"
+  (let* ((menu-keymap (or (gethash mode yas--menu-table)
+                          (puthash mode (make-sparse-keymap) 
yas--menu-table))))
+    (mapc #'yas--menu-keymap-get-create parents)
+    (define-key yas--minor-mode-menu (vector mode)
+        `(menu-item ,(symbol-name mode) ,menu-keymap
+                    :visible (yas--show-menu-p ',mode)))
+    menu-keymap))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Template-related and snippet loading functions
+
+(defun yas--parse-template (&optional file)
+  "Parse the template in the current buffer.
+
+Optional FILE is the absolute file name of the file being
+parsed.
+
+Optional GROUP is the group where the template is to go,
+otherwise we attempt to calculate it from FILE.
+
+Return a snippet-definition, i.e. a list
+
+ (KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING UUID)
+
+If the buffer contains a line of \"# --\" then the contents above
+this line are ignored. Directives can set most of these with the syntax:
+
+# directive-name : directive-value
+
+Here's a list of currently recognized directives:
+
+ * type
+ * name
+ * contributor
+ * condition
+ * group
+ * key
+ * expand-env
+ * binding
+ * uuid"
+  (goto-char (point-min))
+  (let* ((type 'snippet)
+         (name (and file
+                    (file-name-nondirectory file)))
+         (key nil)
+         template
+         bound
+         condition
+         (group (and file
+                     (yas--calculate-group file)))
+         expand-env
+         binding
+         uuid)
+    (if (re-search-forward "^# --\n" nil t)
+        (progn (setq template
+                     (buffer-substring-no-properties (point)
+                                                     (point-max)))
+               (setq bound (point))
+               (goto-char (point-min))
+               (while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*\\)$" 
bound t)
+                 (when (string= "uuid" (match-string-no-properties 1))
+                   (setq uuid (match-string-no-properties 2)))
+                 (when (string= "type" (match-string-no-properties 1))
+                   (setq type (if (string= "command" 
(match-string-no-properties 2))
+                                  'command
+                                'snippet)))
+                 (when (string= "key" (match-string-no-properties 1))
+                   (setq key (match-string-no-properties 2)))
+                 (when (string= "name" (match-string-no-properties 1))
+                   (setq name (match-string-no-properties 2)))
+                 (when (string= "condition" (match-string-no-properties 1))
+                   (setq condition (yas--read-lisp (match-string-no-properties 
2))))
+                 (when (string= "group" (match-string-no-properties 1))
+                   (setq group (match-string-no-properties 2)))
+                 (when (string= "expand-env" (match-string-no-properties 1))
+                   (setq expand-env (yas--read-lisp 
(match-string-no-properties 2)
+                                                   'nil-on-error)))
+                 (when (string= "binding" (match-string-no-properties 1))
+                   (setq binding (match-string-no-properties 2)))))
+      (setq template
+            (buffer-substring-no-properties (point-min) (point-max))))
+    (unless (or key binding)
+      (setq key (and file (file-name-nondirectory file))))
+    (when (eq type 'command)
+      (setq template (yas--read-lisp (concat "(progn" template ")"))))
+    (when group
+      (setq group (split-string group "\\.")))
+    (list key template name condition group expand-env file binding uuid)))
+
+(defun yas--calculate-group (file)
+  "Calculate the group for snippet file path FILE."
+  (let* ((dominating-dir (locate-dominating-file file
+                                                 ".yas-make-groups"))
+         (extra-path (and dominating-dir
+                          (replace-regexp-in-string (concat "^"
+                                                            (expand-file-name 
dominating-dir))
+                                                    ""
+                                                    (expand-file-name file))))
+         (extra-dir (and extra-path
+                         (file-name-directory extra-path)))
+         (group (and extra-dir
+                     (replace-regexp-in-string "/"
+                                               "."
+                                               (directory-file-name 
extra-dir)))))
+    group))
+
+(defun yas--subdirs (directory &optional filep)
+  "Return subdirs or files of DIRECTORY according to FILEP."
+  (remove-if (lambda (file)
+               (or (string-match "^\\."
+                                 (file-name-nondirectory file))
+                   (string-match "^#.*#$"
+                                 (file-name-nondirectory file))
+                   (string-match "~$"
+                                 (file-name-nondirectory file))
+                   (if filep
+                       (file-directory-p file)
+                     (not (file-directory-p file)))))
+             (directory-files directory t)))
+
+(defun yas--make-menu-binding (template)
+  (let ((mode (yas--table-mode (yas--template-table template))))
+    `(lambda () (interactive) (yas--expand-or-visit-from-menu ',mode 
,(yas--template-uuid template)))))
+
+(defun yas--expand-or-visit-from-menu (mode uuid)
+  (let* ((table (yas--table-get-create mode))
+         (yas--current-template (and table
+                                    (gethash uuid (yas--table-uuidhash 
table)))))
+    (when yas--current-template
+      (if yas-visit-from-menu
+          (yas--visit-snippet-file-1 yas--current-template)
+        (let ((where (if (region-active-p)
+                         (cons (region-beginning) (region-end))
+                       (cons (point) (point)))))
+          (yas-expand-snippet (yas--template-content yas--current-template)
+                              (car where)
+                              (cdr where)
+                              (yas--template-expand-env 
yas--current-template)))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Popping up for keys and templates
+;;
+(defvar yas--x-pretty-prompt-templates nil
+  "If non-nil, attempt to prompt for templates like TextMate.")
+
+
+(defun yas--prompt-for-template (templates &optional prompt)
+  "Interactively choose a template from the list TEMPLATES.
+
+TEMPLATES is a list of `yas--template'."
+  (when templates
+    (setq templates
+          (sort templates #'(lambda (t1 t2)
+                              (< (length (yas--template-name t1))
+                                 (length (yas--template-name t2))))))
+    (if yas--x-pretty-prompt-templates
+        (yas--x-pretty-prompt-templates "Choose a snippet" templates)
+      (some #'(lambda (fn)
+                (funcall fn (or prompt "Choose a snippet: ")
+                         templates
+                         #'yas--template-name))
+            yas-prompt-functions))))
+
+(defun yas--prompt-for-keys (keys &optional prompt)
+  "Interactively choose a template key from the list KEYS."
+  (when keys
+    (some #'(lambda (fn)
+              (funcall fn (or prompt "Choose a snippet key: ") keys))
+          yas-prompt-functions)))
+
+(defun yas--prompt-for-table (tables &optional prompt)
+  (when tables
+    (some #'(lambda (fn)
+              (funcall fn (or prompt "Choose a snippet table: ")
+                       tables
+                       #'yas--table-name))
+          yas-prompt-functions)))
+
+(defun yas-x-prompt (prompt choices &optional display-fn)
+  "Display choices in a x-window prompt."
+  ;; FIXME: HACK: if we notice that one of the objects in choices is
+  ;; actually a `yas--template', defer to `yas--x-prompt-pretty-templates'
+  ;;
+  ;; This would be better implemented by passing CHOICES as a
+  ;; strucutred tree rather than a list. Modifications would go as far
+  ;; up as `yas--all-templates' I think.
+  ;;
+  (when (and window-system choices)
+    (let ((chosen
+           (let (menu d) ;; d for display
+             (dolist (c choices)
+               (setq d (or (and display-fn (funcall display-fn c))
+                           c))
+               (cond ((stringp d)
+                      (push (cons (concat "   " d) c) menu))
+                     ((listp d)
+                      (push (car d) menu))))
+             (setq menu (list prompt (push "title" menu)))
+             (x-popup-menu (if (fboundp 'posn-at-point)
+                               (let ((x-y (posn-x-y (posn-at-point (point)))))
+                                 (list (list (+ (car x-y) 10)
+                                             (+ (cdr x-y) 20))
+                                       (selected-window)))
+                             t)
+                           menu))))
+      (or chosen
+          (keyboard-quit)))))
+
+(defun yas--x-pretty-prompt-templates (prompt templates)
+  "Display TEMPLATES, grouping neatly by table name."
+  (let ((organized (make-hash-table :test #'equal))
+        menu
+        more-than-one-table
+        prefix)
+    (dolist (tl templates)
+      (puthash (yas--template-table tl)
+               (cons tl
+                     (gethash (yas--template-table tl) organized))
+               organized))
+    (setq more-than-one-table (> (hash-table-count organized) 1))
+    (setq prefix (if more-than-one-table
+                     "   " ""))
+    (if more-than-one-table
+        (maphash #'(lambda (table templates)
+                     (push (yas--table-name table) menu)
+                     (dolist (tl templates)
+                       (push (cons (concat prefix (yas--template-name tl)) tl) 
menu))) organized)
+      (setq menu (mapcar #'(lambda (tl) (cons (concat prefix 
(yas--template-name tl)) tl)) templates)))
+
+    (setq menu (nreverse menu))
+    (or (x-popup-menu (if (fboundp 'posn-at-point)
+                          (let ((x-y (posn-x-y (posn-at-point (point)))))
+                            (list (list (+ (car x-y) 10)
+                                        (+ (cdr x-y) 20))
+                                  (selected-window)))
+                        t)
+                      (list prompt (push "title" menu)))
+        (keyboard-quit))))
+
+(defun yas-ido-prompt (prompt choices &optional display-fn)
+  (when (and (fboundp 'ido-completing-read)
+            (or (>= emacs-major-version 24)
+                ido-mode))
+    (yas-completing-prompt prompt choices display-fn #'ido-completing-read)))
+
+(eval-when-compile (require 'dropdown-list nil t))
+(defun yas-dropdown-prompt (prompt choices &optional display-fn)
+  (when (featurep 'dropdown-list)
+    (let (formatted-choices
+          filtered-choices
+          d
+          n)
+      (dolist (choice choices)
+        (setq d (or (and display-fn (funcall display-fn choice))
+                      choice))
+        (when (stringp d)
+          (push d formatted-choices)
+          (push choice filtered-choices)))
+
+      (setq n (and formatted-choices (dropdown-list formatted-choices)))
+      (if n
+          (nth n filtered-choices)
+        (keyboard-quit)))))
+
+(defun yas-completing-prompt (prompt choices &optional display-fn 
completion-fn)
+  (let (formatted-choices
+        filtered-choices
+        chosen
+        d
+        (completion-fn (or completion-fn
+                           #'completing-read)))
+    (dolist (choice choices)
+      (setq d (or (and display-fn (funcall display-fn choice))
+                    choice))
+      (when (stringp d)
+        (push d formatted-choices)
+        (push choice filtered-choices)))
+    (setq chosen (and formatted-choices
+                      (funcall completion-fn prompt
+                               formatted-choices
+                               nil
+                               'require-match
+                               nil
+                               nil)))
+    (let ((position (or (and chosen
+                             (position chosen formatted-choices :test 
#'string=))
+                        0)))
+      (nth position filtered-choices))))
+
+(defun yas-no-prompt (prompt choices &optional display-fn)
+  (first choices))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Loading snippets from files
+;;
+(defun yas--load-yas-setup-file (file)
+  (load file 'noerror))
+
+(defun yas-load-directory (top-level-dir &optional use-jit)
+  "Load snippets in directory hierarchy TOP-LEVEL-DIR.
+
+Below TOP-LEVEL-DIR each directory should be a mode name.
+
+Optional USE-JIT use jit-loading of snippets."
+  (interactive "DSelect the root directory: ")
+  (unless yas-snippet-dirs
+    (setq yas-snippet-dirs top-level-dir))
+  (dolist (dir (yas--subdirs top-level-dir))
+    (let* ((major-mode-and-parents (yas--compute-major-mode-and-parents
+                                    (concat dir "/dummy")))
+           (mode-sym (car major-mode-and-parents))
+           (parents (cdr major-mode-and-parents)))
+      ;; Attention: The parents and the menus are already defined
+      ;; here, even if the snippets are later jit-loaded.
+      ;;
+      ;; * We need to know the parents at this point since entering a
+      ;;   given mode should jit load for its parents
+      ;;   immediately. This could be reviewed, the parents could be
+      ;;   discovered just-in-time-as well
+      ;;
+      ;; * We need to create the menus here to support the `full'
+      ;;   option to `yas-use-menu' (all known snippet menus are shown to the 
user)
+      ;;
+      (yas--define-parents mode-sym parents)
+      (yas--menu-keymap-get-create mode-sym)
+      (let ((form `(yas--load-directory-1 ,dir
+                                         ',mode-sym
+                                         ',parents)))
+        (if use-jit
+            (yas--schedule-jit mode-sym form)
+            (eval form)))))
+  (when (interactive-p)
+    (yas--message 3 "Loaded snippets from %s." top-level-dir)))
+
+(defun yas--load-directory-1 (directory mode-sym parents &optional 
no-compiled-snippets)
+  "Recursively load snippet templates from DIRECTORY."
+  (unless (file-exists-p (concat directory "/" ".yas-skip"))
+    (if (and (not no-compiled-snippets)
+             (progn (yas--message 2 "Loading compiled snippets from %s" 
directory) t)
+             (load (expand-file-name ".yas-compiled-snippets" directory) 
'noerror (<= yas-verbosity 3)))
+      (yas--message 2 "Loading snippet files from %s" directory)
+      (yas--load-directory-2 directory mode-sym))))
+
+(defun yas--load-directory-2 (directory mode-sym)
+  ;; Load .yas-setup.el files wherever we find them
+  ;;
+  (yas--load-yas-setup-file (expand-file-name ".yas-setup" directory))
+  (let* ((default-directory directory)
+         (snippet-defs nil))
+    ;; load the snippet files
+    ;;
+    (with-temp-buffer
+      (dolist (file (yas--subdirs directory 'no-subdirs-just-files))
+        (when (file-readable-p file)
+          (insert-file-contents file nil nil nil t)
+          (push (yas--parse-template file)
+                snippet-defs))))
+    (when snippet-defs
+      (yas-define-snippets mode-sym
+                           snippet-defs))
+    ;; now recurse to a lower level
+    ;;
+    (dolist (subdir (yas--subdirs directory))
+      (yas--load-directory-2 subdir
+                            mode-sym))))
+
+(defun yas--load-snippet-dirs (&optional nojit)
+  "Reload the directories listed in `yas-snippet-dirs' or
+   prompt the user to select one."
+  (let (errors)
+    (if yas-snippet-dirs
+        (dolist (directory (reverse (yas-snippet-dirs)))
+          (cond ((file-directory-p directory)
+                 (yas-load-directory directory (not nojit))
+                 (if nojit
+                     (yas--message 3 "Loaded %s" directory)
+                   (yas--message 3 "Prepared just-in-time loading for %s" 
directory)))
+                (t
+                 (push (yas--message 0 "Check your `yas-snippet-dirs': %s is 
not a directory" directory) errors))))
+      (call-interactively 'yas-load-directory))
+    errors))
+
+(defun yas-reload-all (&optional interactive)
+  "Reload all snippets and rebuild the YASnippet menu.
+
+When called interactively force immediate reload of all known
+snippets under `yas-snippet-dirs', otherwise use just-in-time
+loading."
+  (interactive "p")
+  (catch 'abort
+    (let ((errors)
+          (snippet-editing-buffers
+           (remove-if-not #'(lambda (buffer)
+                              (with-current-buffer buffer 
yas--editing-template))
+                          (buffer-list))))
+      ;; Warn if there are buffers visiting snippets, since reloading will 
break
+      ;; any on-line editing of those buffers.
+      ;;
+      (when snippet-editing-buffers
+          (if interactive
+              (if (y-or-n-p "Some buffers editing live snippets, close them 
and proceed with reload?")
+                  (mapc #'kill-buffer snippet-editing-buffers)
+                (yas--message 1 "Aborted reload...")
+                (throw 'abort nil))
+            ;; in a non-interactive use, at least set
+            ;; `yas--editing-template' to nil, make it guess it next time 
around
+            (mapc #'(lambda (buffer) (setq yas--editing-template nil)) 
(buffer-list))))
+
+      ;; Empty all snippet tables, parenting info and all menu tables
+      ;;
+      (setq yas--tables (make-hash-table))
+      (setq yas--parents (make-hash-table))
+      (setq yas--menu-table (make-hash-table))
+
+      ;; Cancel all pending 'yas--scheduled-jit-loads'
+      ;;
+      (setq yas--scheduled-jit-loads (make-hash-table))
+
+      ;; Init the `yas-minor-mode-map', taking care not to break the
+      ;; menu....
+      ;;
+      (setcdr yas-minor-mode-map (cdr (yas--init-minor-keymap)))
+
+      ;; Reload the directories listed in `yas-snippet-dirs' or prompt
+      ;; the user to select one.
+      ;;
+      (setq errors (yas--load-snippet-dirs interactive))
+      ;; Reload the direct keybindings
+      ;;
+      (yas-direct-keymaps-reload)
+      ;; Reload the trigger-key (shoudn't be needed, but see issue #237)
+      ;;
+      (yas--trigger-key-reload)
+
+      (yas--message 3 "Reloaded everything%s...%s."
+                   (if interactive "" " (snippets will load just-in-time)")
+                   (if errors " (some errors, check *Messages*)" "")))))
+
+(defun yas--load-pending-jits ()
+  (when yas-minor-mode
+    (dolist (mode (yas--modes-to-activate))
+      (let ((forms (reverse (gethash mode yas--scheduled-jit-loads))))
+        ;; must reverse to maintain coherence with `yas-snippet-dirs'
+        (dolist (form forms)
+          (yas--message  3 "Loading for `%s', just-in-time: %s!" mode form)
+          (eval form))
+        (remhash mode yas--scheduled-jit-loads)))))
+
+;; (when (<= emacs-major-version 22)
+;;   (add-hook 'after-change-major-mode-hook 'yas--load-pending-jits))
+
+(defun yas--quote-string (string)
+  "Escape and quote STRING.
+foo\"bar\\! -> \"foo\\\"bar\\\\!\""
+  (concat "\""
+          (replace-regexp-in-string "[\\\"]"
+                                    "\\\\\\&"
+                                    string
+                                    t)
+          "\""))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Snippet compilation function
+
+(defun yas--initialize ()
+  "For backward compatibility, enable `yas-minor-mode' globally"
+  (yas-global-mode 1))
+
+(defun yas-compile-directory (top-level-dir)
+  "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR.
+
+This works by stubbing a few functions, then calling
+`yas-load-directory'."
+  (interactive "DTop level snippet directory?")
+  (flet ((yas--load-yas-setup-file
+          (file)
+          (let ((elfile (concat file ".el")))
+            (when (file-exists-p elfile)
+              (insert ";;; .yas-setup.el support file if any:\n;;;\n")
+              (insert-file-contents elfile)
+              (end-of-buffer)
+              )))
+         (yas-define-snippets
+          (mode snippets)
+          (insert ";;; Snippet definitions:\n;;;\n")
+          (let ((literal-snippets (list))
+                (print-length nil))
+            (dolist (snippet snippets)
+              (let ((key                    (first   snippet))
+                    (template-content       (second  snippet))
+                    (name                   (third   snippet))
+                    (condition              (fourth  snippet))
+                    (group                  (fifth   snippet))
+                    (expand-env             (sixth   snippet))
+                    (file                   nil) ;; (seventh snippet)) ;; omit 
on purpose
+                    (binding                (eighth  snippet))
+                    (uuid                    (ninth   snippet)))
+                (push `(,key
+                        ,template-content
+                        ,name
+                        ,condition
+                        ,group
+                        ,expand-env
+                        ,file
+                        ,binding
+                        ,uuid)
+                      literal-snippets)))
+            (insert (pp-to-string `(yas-define-snippets ',mode 
',literal-snippets)))
+            (insert "\n\n")))
+         (yas--load-directory-1
+          (dir mode parents &rest ignore)
+          (let ((output-file (concat (file-name-as-directory dir) 
".yas-compiled-snippets.el")))
+            (with-temp-file output-file
+              (insert (format ";;; Compiled snippets and support files for 
`%s'\n" mode))
+              (yas--load-directory-2 dir mode)
+              (insert (format ";;; Do not edit! File generated at %s\n" 
(current-time-string)))))))
+    (yas-load-directory top-level-dir nil)))
+
+(defun yas-recompile-all ()
+  "Compile every dir in `yas-snippet-dirs'."
+  (interactive)
+  (mapc #'yas-compile-directory (yas-snippet-dirs)))
+
+
+;;; JIT loading
+;;;
+
+(defvar yas--scheduled-jit-loads (make-hash-table)
+  "Alist of mode-symbols to forms to be evaled when `yas-minor-mode' kicks 
in.")
+
+(defun yas--schedule-jit (mode form)
+  (puthash mode
+           (cons form
+                 (gethash mode yas--scheduled-jit-loads))
+           yas--scheduled-jit-loads))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Some user level functions
+;;;
+
+(defun yas-about ()
+  (interactive)
+  (message (concat "yasnippet (version "
+                   yas--version
+                   ") -- pluskid <address@hidden>/joaotavora 
<address@hidden>")))
+
+(defun yas--define-parents (mode parents)
+  "Add PARENTS to the list of MODE's parents"
+  (puthash mode (remove-duplicates
+                 (append parents
+                         (gethash mode yas--parents)))
+           yas--parents))
+
+(defun yas-define-snippets (mode snippets)
+  "Define SNIPPETS for MODE.
+
+SNIPPETS is a list of snippet definitions, each taking the
+following form
+
+ (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
+
+Within these, only KEY and TEMPLATE are actually mandatory.
+
+TEMPLATE might be a lisp form or a string, depending on whether
+this is a snippet or a snippet-command.
+
+CONDITION, EXPAND-ENV and KEYBINDING are lisp forms, they have
+been `yas--read-lisp'-ed and will eventually be
+`yas--eval-lisp'-ed.
+
+The remaining elements are strings.
+
+FILE is probably of very little use if you're programatically
+defining snippets.
+
+UUID is the snippets \"unique-id\". Loading a second snippet file
+with the same uuid replaced the previous snippet.
+
+You can use `yas--parse-template' to return such lists based on
+the current buffers contents."
+  (let ((snippet-table (yas--table-get-create mode))
+        (template nil))
+    (dolist (snippet snippets)
+      (setq template (yas-define-snippets-1 snippet
+                                            snippet-table)))
+    template))
+
+(defun yas-define-snippets-1 (snippet snippet-table)
+  "Helper for `yas-define-snippets'."
+  ;; X) Calculate some more defaults on the values returned by
+  ;; `yas--parse-template'.
+  ;;
+  (let* ((file (seventh snippet))
+         (key (car snippet))
+         (name (or (third snippet)
+                   (and file
+                        (file-name-directory file))))
+         (condition (fourth snippet))
+         (group (fifth snippet))
+         (keybinding (yas--read-keybinding (eighth snippet)))
+         (uuid (or (ninth snippet)
+                  name))
+         (template (or (gethash uuid (yas--table-uuidhash snippet-table))
+                       (yas--make-blank-template))))
+    ;; X) populate the template object
+    ;;
+    (yas--populate-template template
+                           :table       snippet-table
+                           :key         key
+                           :content     (second snippet)
+                           :name        (or name key)
+                           :group       group
+                           :condition   condition
+                           :expand-env  (sixth snippet)
+                           :file        (seventh snippet)
+                           :keybinding  keybinding
+                           :uuid         uuid)
+    ;; X) Update this template in the appropriate table. This step
+    ;;    also will take care of adding the key indicators in the
+    ;;    templates menu entry, if any
+    ;;
+    (yas--update-template snippet-table template)
+    ;; X) Return the template
+    ;;
+    ;;
+    template))
+
+
+;;; Apropos snippet menu:
+;;
+;; The snippet menu keymaps are store by mode in hash table called
+;; `yas--menu-table'. They are linked to the main menu in
+;; `yas--menu-keymap-get-create' and are initially created empty,
+;; reflecting the table hierarchy.
+;;
+;; They can be populated in two mutually exclusive ways: (1) by
+;; reading `yas--template-group', which in turn is populated by the "#
+;; group:" directives of the snippets or the ".yas-make-groups" file
+;; or (2) by using a separate `yas-define-menu' call, which declares a
+;; menu structure based on snippets uuids.
+;;
+;; Both situations are handled in `yas--update-template-menu', which
+;; uses the predicate `yas--template-menu-managed-by-yas-define-menu'
+;; that can tell between the two situations.
+;;
+;; Note:
+;;
+;; * if `yas-define-menu' is used it must run before
+;;   `yas-define-snippets' and the UUIDS must match, otherwise we get
+;;   duplicate entries. The `yas--template' objects are created in
+;;   `yas-define-menu', holding nothing but the menu entry,
+;;   represented by a pair of ((menu-item NAME :keys KEYS) TYPE) and
+;;   stored in `yas--template-menu-binding-pair'. The (menu-item ...)
+;;   part is then stored in the menu keymap itself which make the item
+;;   appear to the user. These limitations could probably be revised.
+;;
+;; * The `yas--template-perm-group' slot is only used in
+;;   `yas-describe-tables'.
+;;
+(defun yas--template-menu-binding-pair-get-create (template &optional type)
+  "Get TEMPLATE's menu binding or assign it a new one.
+
+TYPE may be `:stay', signalling this menu binding should be
+static in the menu."
+  (or (yas--template-menu-binding-pair template)
+      (let ((key (yas--template-key template))
+            (keybinding (yas--template-keybinding template)))
+        (setf (yas--template-menu-binding-pair template)
+              (cons `(menu-item ,(or (yas--template-name template)
+                                     (yas--template-uuid template))
+                                ,(yas--make-menu-binding template)
+                                :keys ,nil)
+                    type)))))
+(defun yas--template-menu-managed-by-yas-define-menu (template)
+  "Non-nil if TEMPLATE's menu entry was included in a `yas-define-menu' call."
+  (cdr (yas--template-menu-binding-pair template)))
+
+
+(defun yas--show-menu-p (mode)
+  (cond ((eq yas-use-menu 'abbreviate)
+         (find mode
+               (mapcar #'(lambda (table)
+                           (yas--table-mode table))
+                       (yas--get-snippet-tables))))
+        ((eq yas-use-menu 'full)
+         t)
+        ((eq yas-use-menu t)
+         t)))
+
+(defun yas--delete-from-keymap (keymap uuid)
+  "Recursively delete items with UUID from KEYMAP and its submenus."
+
+  ;; XXX: This used to skip any submenus named \"parent mode\"
+  ;;
+  ;; First of all, recursively enter submenus, i.e. the tree is
+  ;; searched depth first so that stale submenus can be found in the
+  ;; higher passes.
+  ;;
+  (mapc #'(lambda (item)
+            (when (and (listp (cdr item))
+                       (keymapp (third (cdr item))))
+              (yas--delete-from-keymap (third (cdr item)) uuid)))
+        (rest keymap))
+  ;; Set the uuid entry to nil
+  ;;
+  (define-key keymap (vector (make-symbol uuid)) nil)
+  ;; Destructively modify keymap
+  ;;
+  (setcdr keymap (delete-if #'(lambda (item)
+                                (or (null (cdr item))
+                                    (and (keymapp (third (cdr item)))
+                                         (null (cdr (third (cdr item)))))))
+                            (rest keymap))))
+
+(defun yas-define-menu (mode menu &optional omit-items)
+  "Define a snippet menu for MODE according to MENU, ommitting OMIT-ITEMS.
+
+MENU is a list, its elements can be:
+
+- (yas-item UUID) : Creates an entry the snippet identified with
+  UUID. The menu entry for a snippet thus identified is
+  permanent, i.e. it will never move (be reordered) in the menu.
+
+- (yas-separator) : Creates a separator
+
+- (yas-submenu NAME SUBMENU) : Creates a submenu with NAME,
+  SUBMENU has the same form as MENU. NAME is also added to the
+  list of groups of the snippets defined thereafter.
+
+OMIT-ITEMS is a list of snippet uuid's that will always be
+ommited from MODE's menu, even if they're manually loaded.
+
+This function does nothing if `yas-use-menu' is nil.
+"
+  (when yas-use-menu
+    (let* ((table (yas--table-get-create mode))
+           (hash (yas--table-uuidhash table)))
+      (yas--define-menu-1 table
+                          (yas--menu-keymap-get-create mode)
+                          menu
+                          hash)
+      (dolist (uuid omit-items)
+        (let ((template (or (gethash uuid hash)
+                            (yas--populate-template (puthash uuid
+                                                             
(yas--make-blank-template)
+                                                             hash)
+                                                    :table table
+                                                    :uuid uuid))))
+          (setf (yas--template-menu-binding-pair template) (cons nil 
:none)))))))
+
+(defun yas--define-menu-1 (table menu-keymap menu uuidhash &optional 
group-list)
+  (dolist (e (reverse menu))
+    (cond ((eq (first e) 'yas-item)
+           (let ((template (or (gethash (second e) uuidhash)
+                               (yas--populate-template (puthash (second e)
+                                                               
(yas--make-blank-template)
+                                                               uuidhash)
+                                                      :table table
+                                                      :perm-group group-list
+                                                      :uuid (second e)))))
+             (define-key menu-keymap (vector (gensym))
+               (car (yas--template-menu-binding-pair-get-create template 
:stay)))))
+          ((eq (first e) 'yas-submenu)
+           (let ((subkeymap (make-sparse-keymap)))
+             (define-key menu-keymap (vector (gensym))
+               `(menu-item ,(second e) ,subkeymap))
+             (yas--define-menu-1 table
+                                subkeymap
+                                (third e)
+                                uuidhash
+                                (append group-list (list (second e))))))
+          ((eq (first e) 'yas-separator)
+           (define-key menu-keymap (vector (gensym))
+             '(menu-item "----")))
+          (t
+           (yas--message 3 "Don't know anything about menu entry %s" (first 
e))))))
+
+(defun yas--define (mode key template &optional name condition group)
+  "Define a snippet.  Expanding KEY into TEMPLATE.
+
+NAME is a description to this template.  Also update the menu if
+`yas-use-menu' is t.  CONDITION is the condition attached to
+this snippet.  If you attach a condition to a snippet, then it
+will only be expanded when the condition evaluated to non-nil."
+  (yas-define-snippets mode
+                       (list (list key template name condition group))))
+
+(defun yas-hippie-try-expand (first-time?)
+  "Integrate with hippie expand.  Just put this function in
+`hippie-expand-try-functions-list'."
+  (when yas-minor-mode
+    (if (not first-time?)
+        (let ((yas-fallback-behavior 'return-nil))
+          (yas-expand))
+      (undo 1)
+      nil)))
+
+
+;;; Apropos condition-cache:
+;;;
+;;;
+;;;
+;;;
+(defvar yas--condition-cache-timestamp nil)
+(defmacro yas-define-condition-cache (func doc &rest body)
+  "Define a function FUNC with doc DOC and body BODY, BODY is
+executed at most once every snippet expansion attempt, to check
+expansion conditions.
+
+It doesn't make any sense to call FUNC programatically."
+  `(defun ,func () ,(if (and doc
+                             (stringp doc))
+                        (concat doc
+"\n\nFor use in snippets' conditions. Within each
+snippet-expansion routine like `yas-expand', computes actual
+value for the first time then always returns a cached value.")
+                      (setq body (cons doc body))
+                      nil)
+     (let ((timestamp-and-value (get ',func 'yas--condition-cache)))
+       (if (equal (car timestamp-and-value) yas--condition-cache-timestamp)
+           (cdr timestamp-and-value)
+         (let ((new-value (progn
+                            ,@body
+                            )))
+           (put ',func 'yas--condition-cache (cons 
yas--condition-cache-timestamp new-value))
+           new-value)))))
+
+(defalias 'yas-expand 'yas-expand-from-trigger-key)
+(defun yas-expand-from-trigger-key (&optional field)
+  "Expand a snippet before point.
+
+If no snippet expansion is possible, fall back to the behaviour
+defined in `yas-fallback-behavior'.
+
+Optional argument FIELD is for non-interactive use and is an
+object satisfying `yas--field-p' to restrict the expansion to."
+  (interactive)
+  (setq yas--condition-cache-timestamp (current-time))
+  (let (templates-and-pos)
+    (unless (and yas-expand-only-for-last-commands
+                 (not (member last-command yas-expand-only-for-last-commands)))
+      (setq templates-and-pos (if field
+                                  (save-restriction
+                                    (narrow-to-region (yas--field-start field)
+                                                      (yas--field-end field))
+                                    (yas--current-key))
+                                (yas--current-key))))
+    (if (and templates-and-pos
+             (first templates-and-pos))
+        (yas--expand-or-prompt-for-template (first templates-and-pos)
+                                           (second templates-and-pos)
+                                           (third templates-and-pos))
+      (yas--fallback 'trigger-key))))
+
+(defun yas-expand-from-keymap ()
+  "Directly expand some snippets, searching `yas--direct-keymaps'.
+
+If expansion fails, execute the previous binding for this key"
+  (interactive)
+  (setq yas--condition-cache-timestamp (current-time))
+  (let* ((yas--prefix current-prefix-arg)
+         (vec (subseq (this-command-keys-vector) (if current-prefix-arg
+                                                     
universal-argument-num-events
+                                                   0)))
+         (templates (mapcan #'(lambda (table)
+                                (yas--fetch table vec))
+                            (yas--get-snippet-tables))))
+    (if templates
+        (yas--expand-or-prompt-for-template templates)
+      (let ((yas-fallback-behavior 'call-other-command))
+        (yas--fallback)))))
+
+(defun yas--expand-or-prompt-for-template (templates &optional start end)
+  "Expand one of TEMPLATES from START to END.
+
+Prompt the user if TEMPLATES has more than one element, else
+expand immediately. Common gateway for
+`yas-expand-from-trigger-key' and `yas-expand-from-keymap'."
+  (let ((yas--current-template (or (and (rest templates) ;; more than one
+                                       (yas--prompt-for-template (mapcar #'cdr 
templates)))
+                                  (cdar templates))))
+    (when yas--current-template
+      (yas-expand-snippet (yas--template-content yas--current-template)
+                          start
+                          end
+                          (yas--template-expand-env yas--current-template)))))
+
+(defun yas--trigger-key-for-fallback ()
+  ;; When `yas-trigger-key' is <tab> it correctly overrides
+  ;; org-mode's <tab>, for example and searching for fallbacks
+  ;; correctly returns `org-cycle'. However, most other modes bind
+  ;; "TAB" (which is translated from <tab>), and calling
+  ;; (key-binding "TAB") does not place return that command into
+  ;; our command-2 local. So we cheat.
+  ;;
+  (if (string= yas-trigger-key "<tab>")
+      "TAB"
+    yas-trigger-key))
+
+(defun yas--fallback (&optional from-trigger-key-p)
+  "Fallback after expansion has failed.
+
+Common gateway for `yas-expand-from-trigger-key' and
+`yas-expand-from-keymap'."
+  (cond ((eq yas-fallback-behavior 'return-nil)
+         ;; return nil
+         nil)
+        ((eq yas-fallback-behavior 'call-other-command)
+         (let* ((yas-minor-mode nil)
+                (yas--direct-keymaps nil)
+                (yas-trigger-key (yas--trigger-key-for-fallback))
+                (keys-1 (this-command-keys-vector))
+                (keys-2 (and yas-trigger-key
+                             from-trigger-key-p
+                             (stringp yas-trigger-key)
+                             (read-kbd-macro yas-trigger-key)))
+                (command-1 (and keys-1 (key-binding keys-1)))
+                (command-2 (and keys-2 (key-binding keys-2)))
+                ;; An (ugly) safety: prevents infinite recursion of
+                ;; yas-expand* calls.
+                (command (or (and (symbolp command-1)
+                                  (not (string-match "yas-expand" (symbol-name 
command-1)))
+                                  command-1)
+                             (and (symbolp command-2)
+                                  command-2))))
+           (when (and (commandp command)
+                      (not (string-match "yas-expand" (symbol-name command))))
+             (setq this-command command)
+             (call-interactively command))))
+        ((and (listp yas-fallback-behavior)
+              (cdr yas-fallback-behavior)
+              (eq 'apply (car yas-fallback-behavior)))
+         (if (cddr yas-fallback-behavior)
+             (apply (cadr yas-fallback-behavior)
+                    (cddr yas-fallback-behavior))
+           (when (commandp (cadr yas-fallback-behavior))
+             (setq this-command (cadr yas-fallback-behavior))
+             (call-interactively (cadr yas-fallback-behavior)))))
+        (t
+         ;; also return nil if all the other fallbacks have failed
+         nil)))
+
+
+
+;;; Utils for snippet development:
+
+(defun yas--all-templates (tables)
+  "Return all snippet tables applicable for the current buffer.
+
+Honours `yas-choose-tables-first', `yas-choose-keys-first' and
+`yas-buffer-local-condition'"
+  (when yas-choose-tables-first
+    (setq tables (list (yas--prompt-for-table tables))))
+  (mapcar #'cdr
+          (if yas-choose-keys-first
+              (let ((key (yas--prompt-for-keys
+                          (mapcan #'yas--table-all-keys tables))))
+                (when key
+                  (mapcan #'(lambda (table)
+                              (yas--fetch table key))
+                          tables)))
+            (remove-duplicates (mapcan #'yas--table-templates tables)
+                               :test #'equal))))
+
+(defun yas-insert-snippet (&optional no-condition)
+  "Choose a snippet to expand, pop-up a list of choices according
+to `yas--prompt-function'.
+
+With prefix argument NO-CONDITION, bypass filtering of snippets
+by condition."
+  (interactive "P")
+  (setq yas--condition-cache-timestamp (current-time))
+  (let* ((yas-buffer-local-condition (or (and no-condition
+                                              'always)
+                                         yas-buffer-local-condition))
+         (templates (yas--all-templates (yas--get-snippet-tables)))
+         (yas--current-template (and templates
+                                    (or (and (rest templates) ;; more than one 
template for same key
+                                             (yas--prompt-for-template 
templates))
+                                        (car templates))))
+         (where (if (region-active-p)
+                    (cons (region-beginning) (region-end))
+                  (cons (point) (point)))))
+    (if yas--current-template
+        (yas-expand-snippet (yas--template-content yas--current-template)
+                            (car where)
+                            (cdr where)
+                            (yas--template-expand-env yas--current-template))
+      (yas--message 3 "No snippets can be inserted here!"))))
+
+(defun yas-visit-snippet-file ()
+  "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)
+  (let* ((yas-buffer-local-condition 'always)
+         (templates (yas--all-templates (yas--get-snippet-tables)))
+         (yas-prompt-functions '(yas-ido-prompt yas-completing-prompt))
+         (template (and templates
+                        (or (yas--prompt-for-template templates
+                                                     "Choose a snippet 
template to edit: ")
+                            (car templates)))))
+
+    (if template
+        (yas--visit-snippet-file-1 template)
+      (message "No snippets tables active!"))))
+
+(defun yas--visit-snippet-file-1 (template)
+  (let ((file (yas--template-file template)))
+    (cond ((and file (file-readable-p file))
+           (find-file-other-window file)
+           (snippet-mode)
+           (set (make-local-variable 'yas--editing-template) template))
+          (file
+           (message "Original file %s no longer exists!" file))
+          (t
+           (switch-to-buffer (format "*%s*"(yas--template-name template)))
+           (let ((type 'snippet))
+             (when (listp (yas--template-content template))
+               (insert (format "# type: command\n"))
+               (setq type 'command))
+             (insert (format "# key: %s\n" (yas--template-key template)))
+             (insert (format "# name: %s\n" (yas--template-name template)))
+             (when (yas--template-keybinding template)
+               (insert (format "# binding: %s\n" (yas--template-keybinding 
template))))
+             (when (yas--template-expand-env template)
+               (insert (format "# expand-env: %s\n" (yas--template-expand-env 
template))))
+             (when (yas--template-condition template)
+               (insert (format "# condition: %s\n" (yas--template-condition 
template))))
+             (insert "# --\n")
+             (insert (if (eq type 'command)
+                         (pp-to-string (yas--template-content template))
+                       (yas--template-content template))))
+           (snippet-mode)
+           (set (make-local-variable 'yas--editing-template) template)))))
+
+(defun yas--guess-snippet-directories-1 (table)
+  "Guesses possible snippet subdirectories for TABLE."
+  (cons (yas--table-name table)
+        (mapcan #'(lambda (parent)
+                    (yas--guess-snippet-directories-1
+                     parent))
+                (yas--table-parents table))))
+
+(defun yas--guess-snippet-directories (&optional table)
+  "Try to guess suitable directories based on the current active
+tables (or optional TABLE).
+
+Returns a list of elemts (TABLE . DIRS) where TABLE is a
+`yas--table' object and DIRS is a list of all possible directories
+where snippets of table might exist."
+  (let ((main-dir (replace-regexp-in-string
+                   "/+$" ""
+                   (or (first (or (yas-snippet-dirs)
+                                  (setq yas-snippet-dirs 
'("~/.emacs.d/snippets")))))))
+        (tables (or (and table
+                         (list table))
+                    (yas--get-snippet-tables))))
+    ;; HACK! the snippet table created here is actually registered!
+    ;;
+    (unless (or table (gethash major-mode yas--tables))
+      (push (yas--table-get-create major-mode)
+            tables))
+
+    (mapcar #'(lambda (table)
+                (cons table
+                      (mapcar #'(lambda (subdir)
+                                  (concat main-dir "/" subdir))
+                              (yas--guess-snippet-directories-1 table))))
+            tables)))
+
+(defun yas--make-directory-maybe (table-and-dirs &optional main-table-string)
+  "Returns a dir inside  TABLE-AND-DIRS, prompts for creation if none exists."
+  (or (some #'(lambda (dir) (when (file-directory-p dir) dir)) (cdr 
table-and-dirs))
+      (let ((candidate (first (cdr table-and-dirs))))
+        (unless (file-writable-p (file-name-directory candidate))
+          (error (yas--format "%s is not writable." candidate)))
+        (if (y-or-n-p (format "Guessed directory (%s) for%s%s table \"%s\" 
does not exist! Create? "
+                              candidate
+                              (if (gethash (yas--table-mode (car 
table-and-dirs))
+                                           yas--tables)
+                                  ""
+                                " brand new")
+                              (or main-table-string
+                                  "")
+                              (yas--table-name (car table-and-dirs))))
+            (progn
+              (make-directory candidate 'also-make-parents)
+              ;; create the .yas-parents file here...
+              candidate)))))
+
+(defun yas-new-snippet (&optional no-template)
+  "Pops a new buffer for writing a snippet.
+
+Expands a snippet-writing snippet, unless the optional prefix arg
+NO-TEMPLATE is non-nil."
+  (interactive "P")
+  (let ((guessed-directories (yas--guess-snippet-directories)))
+
+    (switch-to-buffer "*new snippet*")
+    (erase-buffer)
+    (kill-all-local-variables)
+    (snippet-mode)
+    (yas-minor-mode 1)
+    (set (make-local-variable 'yas--guessed-modes) (mapcar #'(lambda (d)
+                                                              (yas--table-mode 
(car d)))
+                                                          guessed-directories))
+    (unless no-template (yas-expand-snippet "\
+# -*- mode: snippet -*-
+# name: $1
+# key: ${2:${1:$(replace-regexp-in-string \"\\\\\\\\(\\\\\\\\w+\\\\\\\\).*\" 
\"\\\\\\\\1\" yas-text)}}${3:
+# binding: ${4:direct-keybinding}}${5:
+# expand-env: ((${6:some-var} ${7:some-value}))}${8:
+# type: command}
+# --
+$0"))))
+
+(defun yas--compute-major-mode-and-parents (file)
+  "Given FILE, find the nearest snippet directory for a given
+mode, then return a list (MODE-SYM PARENTS), the mode's symbol and a list
+representing one or more of the mode's parents.
+
+Note that MODE-SYM need not be the symbol of a real major mode,
+neither do the elements of PARENTS."
+  (let* ((file-dir (and file
+                        (directory-file-name (or (some #'(lambda (special)
+                                                           
(locate-dominating-file file special))
+                                                       '(".yas-setup.el"
+                                                         ".yas-make-groups"
+                                                         ".yas-parents"))
+                                                 (directory-file-name 
(file-name-directory file))))))
+         (parents-file-name (concat file-dir "/.yas-parents"))
+         (major-mode-name (and file-dir
+                               (file-name-nondirectory file-dir)))
+         (major-mode-sym (or (and major-mode-name
+                                  (intern major-mode-name))))
+         (parents (when (file-readable-p parents-file-name)
+                         (mapcar #'intern
+                                 (split-string
+                                  (with-temp-buffer
+                                    (insert-file-contents parents-file-name)
+                                    (buffer-substring-no-properties (point-min)
+                                                                    
(point-max))))))))
+    (when major-mode-sym
+      (cons major-mode-sym parents))))
+
+(defvar yas--editing-template nil
+  "Supporting variable for `yas-load-snippet-buffer' and `yas--visit-snippet'")
+
+(defvar yas--current-template nil
+  "Holds the current template being expanded into a snippet.")
+
+(defvar yas--guessed-modes nil
+  "List of guessed modes supporting `yas-load-snippet-buffer'.")
+
+(defun yas--read-table ()
+  "Ask user for a snippet table, help with some guessing."
+  (let ((prompt (if (and (featurep 'ido)
+                         ido-mode)
+                    'ido-completing-read 'completing-read)))
+    (unless yas--guessed-modes
+      (set (make-local-variable 'yas--guessed-modes)
+           (or (yas--compute-major-mode-and-parents buffer-file-name))))
+    (intern
+     (funcall prompt (format "Choose or enter a table (yas guesses %s): "
+                             (if yas--guessed-modes
+                                 (first yas--guessed-modes)
+                               "nothing"))
+              (mapcar #'symbol-name yas--guessed-modes)
+              nil
+              nil
+              nil
+              nil
+              (if (first yas--guessed-modes)
+                  (symbol-name (first yas--guessed-modes)))))))
+
+(defun yas-load-snippet-buffer (table &optional interactive)
+  "Parse and load current buffer's snippet definition into TABLE.
+
+TABLE is a symbol naming a passed to `yas--table-get-create'.
+
+When called interactively, prompt for the table name and
+whether (and where) to save the snippet, then quit the window."
+  (interactive (list (yas--read-table) t))
+  (cond
+   ;;  We have `yas--editing-template', this buffer's content comes from a
+   ;;  template which is already loaded and neatly positioned,...
+   ;;
+   (yas--editing-template
+    (yas-define-snippets-1 (yas--parse-template (yas--template-file 
yas--editing-template))
+                           (yas--template-table yas--editing-template)))
+   ;; Try to use `yas--guessed-modes'. If we don't have that use the
+   ;; value from `yas--compute-major-mode-and-parents'
+   ;;
+   (t
+    (unless yas--guessed-modes
+      (set (make-local-variable 'yas--guessed-modes) (or 
(yas--compute-major-mode-and-parents buffer-file-name))))
+    (let* ((table (yas--table-get-create table)))
+      (set (make-local-variable 'yas--editing-template)
+           (yas-define-snippets-1 (yas--parse-template buffer-file-name)
+                                  table)))))
+
+  (when (and interactive
+             (or
+              ;; Only offer to save this if it looks like a library or new
+              ;; snippet (loaded from elisp, from a dir in `yas-snippet-dirs'
+              ;; which is not the first, or from an unwritable file)
+              ;;
+              (not (yas--template-file yas--editing-template))
+              (not (file-writable-p (yas--template-file 
yas--editing-template)))
+              (and (listp yas-snippet-dirs)
+                   (second yas-snippet-dirs)
+                   (not (string-match (expand-file-name (first 
yas-snippet-dirs))
+                                      (yas--template-file 
yas--editing-template)))))
+             (y-or-n-p (yas--format "Looks like a library or new snippet. Save 
to new file? ")))
+    (let* ((option (first (yas--guess-snippet-directories (yas--template-table 
yas--editing-template))))
+           (chosen (and option
+                        (yas--make-directory-maybe option))))
+      (when chosen
+        (let ((default-file-name (or (and (yas--template-file 
yas--editing-template)
+                                          (file-name-nondirectory 
(yas--template-file yas--editing-template)))
+                                     (yas--template-name 
yas--editing-template))))
+          (write-file (concat chosen "/"
+                              (read-from-minibuffer (format "File name to 
create in %s? " chosen)
+                                                    default-file-name)))
+          (setf (yas--template-file yas--editing-template) 
buffer-file-name)))))
+  (when interactive
+    (quit-window interactive)
+    (yas--message 3 "Snippet \"%s\" loaded for %s."
+                  (yas--template-name yas--editing-template)
+                  (yas--table-name (yas--template-table 
yas--editing-template)))))
+
+
+(defun yas-tryout-snippet (&optional debug)
+  "Test current buffers's snippet template in other buffer."
+  (interactive "P")
+  (let* ((major-mode-and-parent (yas--compute-major-mode-and-parents 
buffer-file-name))
+         (parsed (yas--parse-template))
+         (test-mode (or (and (car major-mode-and-parent)
+                             (fboundp (car major-mode-and-parent))
+                             (car major-mode-and-parent))
+                        (first yas--guessed-modes)
+                        (intern (read-from-minibuffer (yas--format "Please 
input a mode: ")))))
+         (yas--current-template
+          (and parsed
+               (fboundp test-mode)
+               (yas--populate-template (yas--make-blank-template)
+                                      :table       nil ;; no tables for 
ephemeral snippets
+                                      :key         (first parsed)
+                                      :content     (second parsed)
+                                      :name        (third parsed)
+                                      :expand-env  (sixth parsed)))))
+    (cond (yas--current-template
+           (let ((buffer-name (format "*testing snippet: %s*" 
(yas--template-name yas--current-template))))
+             (kill-buffer (get-buffer-create buffer-name))
+             (switch-to-buffer (get-buffer-create buffer-name))
+             (setq buffer-undo-list nil)
+             (condition-case nil (funcall test-mode) (error nil))
+            (yas-minor-mode 1)
+             (setq buffer-read-only nil)
+             (yas-expand-snippet (yas--template-content yas--current-template)
+                                 (point-min)
+                                 (point-max)
+                                 (yas--template-expand-env 
yas--current-template))
+             (when (and debug
+                        (require 'yasnippet-debug nil t))
+               (add-hook 'post-command-hook 'yas-debug-snippet-vars nil t))))
+          (t
+           (yas--message 3 "Cannot test snippet for unknown major mode")))))
+
+(defun yas--template-fine-group (template)
+  (car (last (or (yas--template-group template)
+                 (yas--template-perm-group template)))))
+
+(defun yas-describe-tables (&optional choose)
+  "Display snippets for each table."
+  (interactive "P")
+  (let* ((by-name-hash (and choose
+                            (y-or-n-p "Show by namehash? ")))
+         (buffer (get-buffer-create "*YASnippet tables*"))
+         (active-tables (yas--get-snippet-tables))
+         (remain-tables (let ((all))
+                          (maphash #'(lambda (k v)
+                                       (unless (find v active-tables)
+                                         (push v all)))
+                                   yas--tables)
+                          all))
+         (table-lists (list active-tables remain-tables))
+         (original-buffer (current-buffer))
+         (continue t)
+         (yas--condition-cache-timestamp (current-time)))
+    (with-current-buffer buffer
+      (setq buffer-read-only nil)
+      (erase-buffer)
+      (cond ((not by-name-hash)
+             (insert "YASnippet tables: \n")
+             (while (and table-lists
+                         continue)
+               (dolist (table (car table-lists))
+                 (yas--describe-pretty-table table original-buffer))
+               (setq table-lists (cdr table-lists))
+               (when table-lists
+                 (yas--create-snippet-xrefs)
+                 (display-buffer buffer)
+                 (setq continue (and choose (y-or-n-p "Show also non-active 
tables? ")))))
+             (yas--create-snippet-xrefs)
+             (help-mode)
+             (goto-char 1))
+            (t
+             (insert "\n\nYASnippet tables by NAMEHASH: \n")
+             (dolist (table (append active-tables remain-tables))
+               (insert (format "\nSnippet table `%s':\n\n" (yas--table-name 
table)))
+               (let ((keys))
+                 (maphash #'(lambda (k v)
+                              (push k keys))
+                          (yas--table-hash table))
+                 (dolist (key keys)
+                   (insert (format "   key %s maps snippets: %s\n" key
+                                   (let ((names))
+                                     (maphash #'(lambda (k v)
+                                                  (push k names))
+                                              (gethash key (yas--table-hash 
table)))
+                                     names))))))))
+      (goto-char 1)
+      (setq buffer-read-only t))
+    (display-buffer buffer)))
+
+(defun yas--describe-pretty-table (table &optional original-buffer)
+  (insert (format "\nSnippet table `%s'"
+                  (yas--table-name table)))
+  (if (yas--table-parents table)
+      (insert (format " parents: %s\n"
+                      (mapcar #'yas--table-name
+                              (yas--table-parents table))))
+    (insert "\n"))
+  (insert (make-string 100 ?-) "\n")
+  (insert "group                   state name                                  
  key             binding\n")
+  (let ((groups-hash (make-hash-table :test #'equal)))
+    (maphash #'(lambda (k v)
+                 (let ((group (or (yas--template-fine-group v)
+                                  "(top level)")))
+                   (when (yas--template-name v)
+                     (puthash group
+                              (cons v (gethash group groups-hash))
+                              groups-hash))))
+             (yas--table-uuidhash table))
+    (maphash
+     #'(lambda (group templates)
+         (setq group (truncate-string-to-width group 25 0 ?  "..."))
+         (insert (make-string 100 ?-) "\n")
+         (dolist (p templates)
+           (let ((name (truncate-string-to-width (propertize (format 
"\\\\snippet `%s'" (yas--template-name p))
+                                                             'yasnippet p)
+                                                 50 0 ? "..."))
+                 (group (prog1 group
+                          (setq group (make-string (length group) ? ))))
+                 (condition-string (let ((condition (yas--template-condition 
p)))
+                                     (if (and condition
+                                              original-buffer)
+                                         (with-current-buffer original-buffer
+                                           (if (yas--eval-condition condition)
+                                               "(y)"
+                                             "(s)"))
+                                       "(a)"))))
+             (insert group " ")
+             (insert condition-string " ")
+             (insert name
+                     (if (string-match "\\.\\.\\.$" name)
+                         "'"
+                       " ")
+                     " ")
+             (insert (truncate-string-to-width (or (yas--template-key p) "")
+                                               15 0 ?  "...") " ")
+             (insert (truncate-string-to-width (key-description 
(yas--template-keybinding p))
+                                               15 0 ?  "...") " ")
+             (insert "\n"))))
+     groups-hash)))
+
+
+
+;;; User convenience functions, for using in snippet definitions
+
+(defvar yas-modified-p nil
+  "Non-nil if field has been modified by user or transformation.")
+
+(defvar yas-moving-away-p nil
+  "Non-nil if user is about to exit field.")
+
+(defvar yas-text nil
+  "Contains current field text.")
+
+(defun yas-substr (str pattern &optional subexp)
+  "Search PATTERN in STR and return SUBEXPth match.
+
+If found, the content of subexp group SUBEXP (default 0) is
+  returned, or else the original STR will be returned."
+  (let ((grp (or subexp 0)))
+    (save-match-data
+      (if (string-match pattern str)
+          (match-string-no-properties grp str)
+        str))))
+
+(defun yas-choose-value (&rest possibilities)
+  "Prompt for a string in POSSIBILITIES and return it.
+
+The last element of POSSIBILITIES may be a list of strings."
+  (unless (or yas-moving-away-p
+              yas-modified-p)
+    (setq possibilities (nreverse possibilities))
+    (setq possibilities (if (listp (car possibilities))
+                            (append (reverse (car possibilities)) (rest 
possibilities))
+                                   possibilities))
+    (some #'(lambda (fn)
+              (funcall fn "Choose: " possibilities))
+          yas-prompt-functions)))
+
+(defun yas-key-to-value (alist)
+  "Prompt for a string in the list POSSIBILITIES and return it."
+  (unless (or yas-moving-away-p
+              yas-modified-p)
+    (let ((key (read-key-sequence "")))
+      (when (stringp key)
+        (or (cdr (find key alist :key #'car :test #'string=))
+            key)))))
+
+(defun yas-throw (text)
+  "Throw a yas--exception with TEXT as the reason."
+  (throw 'yas--exception (cons 'yas--exception text)))
+
+(defun yas-verify-value (possibilities)
+  "Verify that the current field value is in POSSIBILITIES
+
+Otherwise throw exception."
+  (when (and yas-moving-away-p (notany #'(lambda (pos) (string= pos yas-text)) 
possibilities))
+    (yas-throw (yas--format "Field only allows %s" possibilities))))
+
+(defun yas-field-value (number)
+  "Get the string for field with NUMBER.
+
+Use this in primary and mirror transformations to tget."
+  (let* ((snippet (car (yas--snippets-at-point)))
+         (field (and snippet
+                     (yas--snippet-find-field snippet number))))
+    (when field
+      (yas--field-text-for-display field))))
+
+(defun yas-text ()
+  "Return `yas-text' if that exists and is non-empty, else nil."
+  (if (and yas-text
+           (not (string= "" yas-text)))
+      yas-text))
+
+(defun yas-selected-text ()
+  "Return `yas-selected-text' if that exists and is non-empty, else nil."
+  (if (and yas-selected-text
+           (not (string= "" yas-selected-text)))
+      yas-selected-text))
+
+(defun yas--get-field-once (number &optional transform-fn)
+  (unless yas-modified-p
+    (if transform-fn
+        (funcall transform-fn (yas-field-value number))
+      (yas-field-value number))))
+
+(defun yas-default-from-field (number)
+  (unless yas-modified-p
+    (yas-field-value number)))
+
+(defun yas-inside-string ()
+  (equal 'font-lock-string-face (get-char-property (1- (point)) 'face)))
+
+(defun yas-unimplemented (&optional missing-feature)
+  (if yas--current-template
+      (if (y-or-n-p (format "This snippet is unimplemented (missing %s) Visit 
the snippet definition? "
+                            (or missing-feature
+                                "something")))
+          (yas--visit-snippet-file-1 yas--current-template))
+    (message "No implementation. Missing %s" (or missing-feature 
"something"))))
+
+
+;;; Snippet expansion and field management
+
+(defvar yas--active-field-overlay nil
+  "Overlays the currently active field.")
+
+(defvar yas--field-protection-overlays nil
+  "Two overlays protect the current active field ")
+
+(defconst yas--prefix nil
+  "A prefix argument for expansion direct from keybindings")
+
+(defvar yas-selected-text nil
+  "The selected region deleted on the last snippet expansion.")
+
+(defvar yas--start-column nil
+  "The column where the snippet expansion started.")
+
+(make-variable-buffer-local 'yas--active-field-overlay)
+(make-variable-buffer-local 'yas--field-protection-overlays)
+(put 'yas--active-field-overlay 'permanent-local t)
+(put 'yas--field-protection-overlays 'permanent-local t)
+
+(defstruct (yas--snippet (:constructor yas--make-snippet ()))
+  "A snippet.
+
+..."
+  (fields '())
+  (exit nil)
+  (id (yas--snippet-next-id) :read-only t)
+  (control-overlay nil)
+  active-field
+  ;; stacked expansion: the `previous-active-field' slot saves the
+  ;; active field where the child expansion took place
+  previous-active-field
+  force-exit)
+
+(defstruct (yas--field (:constructor yas--make-field (number start end 
parent-field)))
+  "A field."
+  number
+  start end
+  parent-field
+  (mirrors '())
+  (transform nil)
+  (modified-p nil)
+  next)
+
+(defstruct (yas--mirror (:constructor yas--make-mirror (start end transform)))
+  "A mirror."
+  start end
+  (transform nil)
+  parent-field
+  next)
+
+(defstruct (yas--exit (:constructor yas--make-exit (marker)))
+  marker
+  next)
+
+(defun yas--apply-transform (field-or-mirror field &optional empty-on-nil-p)
+  "Calculate transformed string for FIELD-OR-MIRROR from FIELD.
+
+If there is no transform for ht field, return nil.
+
+If there is a transform but it returns nil, return the empty
+string iff EMPTY-ON-NIL-P is true."
+  (let* ((yas-text (yas--field-text-for-display field))
+         (text yas-text)
+         (yas-modified-p (yas--field-modified-p field))
+         (yas-moving-away-p nil)
+         (transform (if (yas--mirror-p field-or-mirror)
+                        (yas--mirror-transform field-or-mirror)
+                      (yas--field-transform field-or-mirror)))
+         (start-point (if (yas--mirror-p field-or-mirror)
+                          (yas--mirror-start field-or-mirror)
+                        (yas--field-start field-or-mirror)))
+         (transformed (and transform
+                           (save-excursion
+                             (goto-char start-point)
+                             (let ((ret (yas--eval-lisp transform)))
+                               (or ret (and empty-on-nil-p "")))))))
+    transformed))
+
+(defsubst yas--replace-all (from to &optional text)
+  "Replace all occurance from FROM to TO.
+
+With optional string TEXT do it in that string."
+  (if text
+      (replace-regexp-in-string (regexp-quote from) to text t t)
+    (goto-char (point-min))
+    (while (search-forward from nil t)
+      (replace-match to t t text))))
+
+(defun yas--snippet-find-field (snippet number)
+  (find-if #'(lambda (field)
+               (eq number (yas--field-number field)))
+           (yas--snippet-fields snippet)))
+
+(defun yas--snippet-sort-fields (snippet)
+  "Sort the fields of SNIPPET in navigation order."
+  (setf (yas--snippet-fields snippet)
+        (sort (yas--snippet-fields snippet)
+              #'yas--snippet-field-compare)))
+
+(defun yas--snippet-field-compare (field1 field2)
+  "Compare two fields. The field with a number is sorted first.
+If they both have a number, compare through the number. If neither
+have, compare through the field's start point"
+  (let ((n1 (yas--field-number field1))
+        (n2 (yas--field-number field2)))
+    (if n1
+        (if n2
+            (or (zerop n2) (and (not (zerop n1))
+                                (< n1 n2)))
+          (not (zerop n1)))
+      (if n2
+          (zerop n2)
+        (< (yas--field-start field1)
+           (yas--field-start field2))))))
+
+(defun yas--field-probably-deleted-p (snippet field)
+  "Guess if SNIPPET's FIELD should be skipped."
+  (and
+   ;; field must be zero lentgh
+   ;;
+   (zerop (- (yas--field-start field) (yas--field-end field)))
+   ;; skip if:
+   (or
+    ;;  1) is a nested field and it's been modified
+    ;;
+    (and (yas--field-parent-field field)
+         (yas--field-modified-p field))
+    ;;  2) ends just before the snippet end
+    ;;
+    (and (eq field (car (last (yas--snippet-fields snippet))))
+         (= (yas--field-start field) (overlay-end 
(yas--snippet-control-overlay snippet)))))
+   ;; the field numbered 0, just before the exit marker, should
+   ;; never be skipped
+   ;;
+   (not (zerop (yas--field-number field)))))
+
+(defun yas--snippets-at-point (&optional all-snippets)
+  "Return a sorted list of snippets at point, most recently
+inserted first."
+  (sort
+   (remove nil (remove-duplicates (mapcar #'(lambda (ov)
+                                              (overlay-get ov 'yas--snippet))
+                                          (if all-snippets
+                                              (overlays-in (point-min) 
(point-max))
+                                            (nconc (overlays-at (point)) 
(overlays-at (1- (point))))))))
+   #'(lambda (s1 s2)
+       (<= (yas--snippet-id s2) (yas--snippet-id s1)))))
+
+(defun yas-next-field-or-maybe-expand ()
+  "Try to expand a snippet at a key before point, otherwise
+delegate to `yas-next-field'."
+  (interactive)
+  (if yas-triggers-in-field
+      (let ((yas-fallback-behavior 'return-nil)
+            (active-field (overlay-get yas--active-field-overlay 'yas--field)))
+        (when active-field
+          (unless (yas-expand-from-trigger-key active-field)
+            (yas-next-field))))
+    (yas-next-field)))
+
+(defun yas-next-field (&optional arg)
+  "Navigate to next field.  If there's none, exit the snippet."
+  (interactive)
+  (let* ((arg (or arg
+                  1))
+         (snippet (first (yas--snippets-at-point)))
+         (active-field (overlay-get yas--active-field-overlay 'yas--field))
+         (live-fields (remove-if #'(lambda (field)
+                                     (and (not (eq field active-field))
+                                          (yas--field-probably-deleted-p 
snippet field)))
+                                 (yas--snippet-fields snippet)))
+         (active-field-pos (position active-field live-fields))
+         (target-pos (and active-field-pos (+ arg active-field-pos)))
+         (target-field (and target-pos (nth target-pos live-fields))))
+    ;; First check if we're moving out of a field with a transform
+    ;;
+    (when (and active-field
+               (yas--field-transform active-field))
+      (let* ((yas-moving-away-p t)
+             (yas-text (yas--field-text-for-display active-field))
+             (text yas-text)
+             (yas-modified-p (yas--field-modified-p active-field)))
+        ;; primary field transform: exit call to field-transform
+        (yas--eval-lisp (yas--field-transform active-field))))
+    ;; Now actually move...
+    (cond ((and target-pos (>= target-pos (length live-fields)))
+           (yas-exit-snippet snippet))
+          (target-field
+           (yas--move-to-field snippet target-field))
+          (t
+           nil))))
+
+(defun yas--place-overlays (snippet field)
+  "Correctly place overlays for SNIPPET's FIELD"
+  (yas--make-move-field-protection-overlays snippet field)
+  (yas--make-move-active-field-overlay snippet field))
+
+(defun yas--move-to-field (snippet field)
+  "Update SNIPPET to move to field FIELD.
+
+Also create some protection overlays"
+  (goto-char (yas--field-start field))
+  (yas--place-overlays snippet field)
+  (overlay-put yas--active-field-overlay 'yas--field field)
+  (let ((number (yas--field-number field)))
+    ;; check for the special ${0: ...} field
+    (if (and number (zerop number))
+        (progn
+          (set-mark (yas--field-end field))
+          (setf (yas--snippet-force-exit snippet)
+                (or (yas--field-transform field)
+                    t)))
+      ;; make this field active
+      (setf (yas--snippet-active-field snippet) field)
+      ;; primary field transform: first call to snippet transform
+      (unless (yas--field-modified-p field)
+        (if (yas--field-update-display field snippet)
+            (yas--update-mirrors snippet)
+          (setf (yas--field-modified-p field) nil))))))
+
+(defun yas-prev-field ()
+  "Navigate to prev field.  If there's none, exit the snippet."
+  (interactive)
+  (yas-next-field -1))
+
+(defun yas-abort-snippet (&optional snippet)
+  (interactive)
+  (let ((snippet (or snippet
+                     (car (yas--snippets-at-point)))))
+    (when snippet
+      (setf (yas--snippet-force-exit snippet) t))))
+
+(defun yas-exit-snippet (snippet)
+  "Goto exit-marker of SNIPPET."
+  (interactive (list (first (yas--snippets-at-point))))
+  (when snippet
+    (setf (yas--snippet-force-exit snippet) t)
+    (goto-char (if (yas--snippet-exit snippet)
+                   (yas--exit-marker (yas--snippet-exit snippet))
+                 (overlay-end (yas--snippet-control-overlay snippet))))))
+
+(defun yas-exit-all-snippets ()
+  "Exit all snippets."
+  (interactive)
+  (mapc #'(lambda (snippet)
+            (yas-exit-snippet snippet)
+            (yas--check-commit-snippet))
+        (yas--snippets-at-point 'all-snippets)))
+
+
+;;; Some low level snippet-routines:
+
+(defmacro yas--inhibit-overlay-hooks (&rest body)
+  "Run BODY with `yas--inhibit-overlay-hooks' set to t."
+  (declare (indent 0))
+  `(let ((yas--inhibit-overlay-hooks t))
+     (progn ,@body)))
+
+(defvar yas-snippet-beg nil "Beginning position of the last snippet commited.")
+(defvar yas-snippet-end nil "End position of the last snippet commited.")
+
+(defun yas--commit-snippet (snippet)
+  "Commit SNIPPET, but leave point as it is.  This renders the
+snippet as ordinary text."
+
+  (let ((control-overlay (yas--snippet-control-overlay snippet)))
+    ;;
+    ;; Save the end of the moribund snippet in case we need to revive it
+    ;; its original expansion.
+    ;;
+    (when (and control-overlay
+               (overlay-buffer control-overlay))
+      (setq yas-snippet-beg (overlay-start control-overlay))
+      (setq yas-snippet-end (overlay-end control-overlay))
+      (delete-overlay control-overlay))
+
+    (yas--inhibit-overlay-hooks
+      (when yas--active-field-overlay
+        (delete-overlay yas--active-field-overlay))
+      (when yas--field-protection-overlays
+        (mapc #'delete-overlay yas--field-protection-overlays)))
+
+    ;; stacked expansion: if the original expansion took place from a
+    ;; field, make sure we advance it here at least to
+    ;; `yas-snippet-end'...
+    ;;
+    (let ((previous-field (yas--snippet-previous-active-field snippet)))
+      (when (and yas-snippet-end previous-field)
+        (yas--advance-end-maybe previous-field yas-snippet-end)))
+
+    ;; Convert all markers to points,
+    ;;
+    (yas--markers-to-points snippet)
+
+    ;; Take care of snippet revival
+    ;;
+    (if yas-snippet-revival
+        (push `(apply yas--snippet-revive ,yas-snippet-beg ,yas-snippet-end 
,snippet)
+              buffer-undo-list)
+      ;; Dismember the snippet... this is useful if we get called
+      ;; again from `yas--take-care-of-redo'....
+      (setf (yas--snippet-fields snippet) nil)))
+
+  (yas--message 3 "Snippet %s exited." (yas--snippet-id snippet)))
+
+(defun yas--safely-run-hooks (hook-var)
+  (condition-case error
+      (run-hooks hook-var)
+    (error
+     (yas--message 3 "%s error: %s" hook-var (error-message-string error)))))
+
+
+(defun yas--check-commit-snippet ()
+  "Checks if point exited the currently active field of the
+snippet, if so cleans up the whole snippet up."
+  (let* ((snippets (yas--snippets-at-point 'all-snippets))
+         (snippets-left snippets)
+         (snippet-exit-transform))
+    (dolist (snippet snippets)
+      (let ((active-field (yas--snippet-active-field snippet)))
+        (setq snippet-exit-transform (yas--snippet-force-exit snippet))
+        (cond ((or snippet-exit-transform
+                   (not (and active-field (yas--field-contains-point-p 
active-field))))
+               (setq snippets-left (delete snippet snippets-left))
+               (setf (yas--snippet-force-exit snippet) nil)
+               (yas--commit-snippet snippet))
+              ((and active-field
+                    (or (not yas--active-field-overlay)
+                        (not (overlay-buffer yas--active-field-overlay))))
+               ;;
+               ;; stacked expansion: this case is mainly for recent
+               ;; snippet exits that place us back int the field of
+               ;; another snippet
+               ;;
+               (save-excursion
+                 (yas--move-to-field snippet active-field)
+                 (yas--update-mirrors snippet)))
+              (t
+               nil))))
+    (unless (or (null snippets) snippets-left)
+      (if snippet-exit-transform
+          (yas--eval-lisp-no-saves snippet-exit-transform))
+      (yas--safely-run-hooks 'yas-after-exit-snippet-hook))))
+
+;; Apropos markers-to-points:
+;;
+;; This was found useful for performance reasons, so that an
+;; excessive number of live markers aren't kept around in the
+;; `buffer-undo-list'. However, in `markers-to-points', the
+;; set-to-nil markers can't simply be discarded and replaced with
+;; fresh ones in `points-to-markers'. The original marker that was
+;; just set to nil has to be reused.
+;;
+;; This shouldn't bring horrible problems with undo/redo, but it
+;; you never know
+;;
+(defun yas--markers-to-points (snippet)
+  "Convert all markers in SNIPPET to a cons (POINT . MARKER)
+where POINT is the original position of the marker and MARKER is
+the original marker object with the position set to nil."
+  (dolist (field (yas--snippet-fields snippet))
+    (let ((start (marker-position (yas--field-start field)))
+          (end (marker-position (yas--field-end field))))
+      (set-marker (yas--field-start field) nil)
+      (set-marker (yas--field-end field) nil)
+      (setf (yas--field-start field) (cons start (yas--field-start field)))
+      (setf (yas--field-end field) (cons end (yas--field-end field))))
+    (dolist (mirror (yas--field-mirrors field))
+      (let ((start (marker-position (yas--mirror-start mirror)))
+            (end (marker-position (yas--mirror-end mirror))))
+        (set-marker (yas--mirror-start mirror) nil)
+        (set-marker (yas--mirror-end mirror) nil)
+        (setf (yas--mirror-start mirror) (cons start (yas--mirror-start 
mirror)))
+        (setf (yas--mirror-end mirror) (cons end (yas--mirror-end mirror))))))
+  (let ((snippet-exit (yas--snippet-exit snippet)))
+    (when snippet-exit
+      (let ((exit (marker-position (yas--exit-marker snippet-exit))))
+        (set-marker (yas--exit-marker snippet-exit) nil)
+        (setf (yas--exit-marker snippet-exit) (cons exit (yas--exit-marker 
snippet-exit)))))))
+
+(defun yas--points-to-markers (snippet)
+  "Convert all cons (POINT . MARKER) in SNIPPET to markers. This
+is done by setting MARKER to POINT with `set-marker'."
+  (dolist (field (yas--snippet-fields snippet))
+    (setf (yas--field-start field) (set-marker (cdr (yas--field-start field))
+                                              (car (yas--field-start field))))
+    (setf (yas--field-end field) (set-marker (cdr (yas--field-end field))
+                                            (car (yas--field-end field))))
+    (dolist (mirror (yas--field-mirrors field))
+      (setf (yas--mirror-start mirror) (set-marker (cdr (yas--mirror-start 
mirror))
+                                                  (car (yas--mirror-start 
mirror))))
+      (setf (yas--mirror-end mirror) (set-marker (cdr (yas--mirror-end mirror))
+                                                (car (yas--mirror-end 
mirror))))))
+  (let ((snippet-exit (yas--snippet-exit snippet)))
+    (when snippet-exit
+      (setf (yas--exit-marker snippet-exit) (set-marker (cdr (yas--exit-marker 
snippet-exit))
+                                                       (car (yas--exit-marker 
snippet-exit)))))))
+
+(defun yas--field-contains-point-p (field &optional point)
+  (let ((point (or point
+                   (point))))
+    (and (>= point (yas--field-start field))
+         (<= point (yas--field-end field)))))
+
+(defun yas--field-text-for-display (field)
+  "Return the propertized display text for field FIELD.  "
+  (buffer-substring (yas--field-start field) (yas--field-end field)))
+
+(defun yas--undo-in-progress ()
+  "True if some kind of undo is in progress"
+  (or undo-in-progress
+      (eq this-command 'undo)
+      (eq this-command 'redo)))
+
+(defun yas--make-control-overlay (snippet start end)
+  "Creates the control overlay that surrounds the snippet and
+holds the keymap."
+  (let ((overlay (make-overlay start
+                               end
+                               nil
+                               nil
+                               t)))
+    (overlay-put overlay 'keymap yas-keymap)
+    (overlay-put overlay 'priority 100)
+    (overlay-put overlay 'yas--snippet snippet)
+    overlay))
+
+(defun yas-skip-and-clear-or-delete-char (&optional field)
+  "Clears unmodified field if at field start, skips to next tab.
+
+Otherwise deletes a character normally by calling `delete-char'."
+  (interactive)
+  (let ((field (or field
+                   (and yas--active-field-overlay
+                        (overlay-buffer yas--active-field-overlay)
+                        (overlay-get yas--active-field-overlay 'yas--field)))))
+    (cond ((and field
+                (not (yas--field-modified-p field))
+                (eq (point) (marker-position (yas--field-start field))))
+           (yas--skip-and-clear field)
+           (yas-next-field 1))
+          (t
+           (call-interactively 'delete-char)))))
+
+(defun yas--skip-and-clear (field)
+  "Deletes the region of FIELD and sets it modified state to t"
+  ;; Just before skipping-and-clearing the field, mark its children
+  ;; fields as modified, too. If the childen have mirrors-in-fields
+  ;; this prevents them from updating erroneously (we're skipping and
+  ;; deleting!).
+  ;;
+  (yas--mark-this-and-children-modified field)
+  (delete-region (yas--field-start field) (yas--field-end field)))
+
+(defun yas--mark-this-and-children-modified (field)
+  (setf (yas--field-modified-p field) t)
+  (let ((fom (yas--field-next field)))
+    (while (and fom
+                (yas--fom-parent-field fom))
+      (when (and (eq (yas--fom-parent-field fom) field)
+                 (yas--field-p fom))
+        (yas--mark-this-and-children-modified fom))
+      (setq fom (yas--fom-next fom)))))
+
+(defun yas--make-move-active-field-overlay (snippet field)
+  "Place the active field overlay in SNIPPET's FIELD.
+
+Move the overlay, or create it if it does not exit."
+  (if (and yas--active-field-overlay
+           (overlay-buffer yas--active-field-overlay))
+      (move-overlay yas--active-field-overlay
+                    (yas--field-start field)
+                    (yas--field-end field))
+    (setq yas--active-field-overlay
+          (make-overlay (yas--field-start field)
+                        (yas--field-end field)
+                        nil nil t))
+    (overlay-put yas--active-field-overlay 'priority 100)
+    (overlay-put yas--active-field-overlay 'face 'yas-field-highlight-face)
+    (overlay-put yas--active-field-overlay 'yas--snippet snippet)
+    (overlay-put yas--active-field-overlay 'modification-hooks 
'(yas--on-field-overlay-modification))
+    (overlay-put yas--active-field-overlay 'insert-in-front-hooks
+                 '(yas--on-field-overlay-modification))
+    (overlay-put yas--active-field-overlay 'insert-behind-hooks
+                 '(yas--on-field-overlay-modification))))
+
+(defvar yas--inhibit-overlay-hooks nil
+  "Bind this temporarity to non-nil to prevent running 
`yas--on-*-modification'.")
+
+(defun yas--on-field-overlay-modification (overlay after? beg end &optional 
length)
+  "Clears the field and updates mirrors, conditionally.
+
+Only clears the field if it hasn't been modified and it point it
+at field start. This hook doesn't do anything if an undo is in
+progress."
+  (unless (or yas--inhibit-overlay-hooks
+              (yas--undo-in-progress))
+    (let* ((field (overlay-get overlay 'yas--field))
+           (number (and field (yas--field-number field)))
+           (snippet (overlay-get yas--active-field-overlay 'yas--snippet)))
+      (cond (after?
+             (yas--advance-end-maybe field (overlay-end overlay))
+             (save-excursion
+               (yas--field-update-display field snippet))
+             (yas--update-mirrors snippet))
+            (field
+             (when (and (not after?)
+                        (not (yas--field-modified-p field))
+                        (eq (point) (if (markerp (yas--field-start field))
+                                        (marker-position (yas--field-start 
field))
+                                      (yas--field-start field))))
+               (yas--skip-and-clear field))
+             (setf (yas--field-modified-p field) t))))))
+
+;;; Apropos protection overlays:
+;;
+;; These exist for nasty users who will try to delete parts of the
+;; snippet outside the active field. Actual protection happens in
+;; `yas--on-protection-overlay-modification'.
+;;
+;; Currently this signals an error which inhibits the command. For
+;; commands that move point (like `kill-line'), point is restored in
+;; the `yas--post-command-handler' using a global
+;; `yas--protection-violation' variable.
+;;
+;; Alternatively, I've experimented with an implementation that
+;; commits the snippet before actually calling `this-command'
+;; interactively, and then signals an eror, which is ignored. but
+;; blocks all other million modification hooks. This presented some
+;; problems with stacked expansion.
+;;
+(defun yas--make-move-field-protection-overlays (snippet field)
+  "Place protection overlays surrounding SNIPPET's FIELD.
+
+Move the overlays, or create them if they do not exit."
+  (let ((start (yas--field-start field))
+        (end (yas--field-end field)))
+    ;; First check if the (1+ end) is contained in the buffer,
+    ;; otherwise we'll have to do a bit of cheating and silently
+    ;; insert a newline. the `(1+ (buffer-size))' should prevent this
+    ;; when using stacked expansion
+    ;;
+    (when (< (buffer-size) end)
+      (save-excursion
+        (yas--inhibit-overlay-hooks
+          (goto-char (point-max))
+          (newline))))
+    ;; go on to normal overlay creation/moving
+    ;;
+    (cond ((and yas--field-protection-overlays
+                (every #'overlay-buffer yas--field-protection-overlays))
+           (move-overlay (first yas--field-protection-overlays) (1- start) 
start)
+           (move-overlay (second yas--field-protection-overlays) end (1+ end)))
+          (t
+           (setq yas--field-protection-overlays
+                 (list (make-overlay (1- start) start nil t nil)
+                       (make-overlay end (1+ end) nil t nil)))
+           (dolist (ov yas--field-protection-overlays)
+             (overlay-put ov 'face 'yas--field-debug-face)
+             (overlay-put ov 'yas--snippet snippet)
+             ;; (overlay-put ov 'evaporate t)
+             (overlay-put ov 'modification-hooks 
'(yas--on-protection-overlay-modification)))))))
+
+(defvar yas--protection-violation nil
+  "When non-nil, signals attempts to erronesly exit or modify the snippet.
+
+Functions in the `post-command-hook', for example
+`yas--post-command-handler' can check it and reset its value to
+nil. The variables value is the point where the violation
+originated")
+
+(defun yas--on-protection-overlay-modification (overlay after? beg end 
&optional length)
+  "Signals a snippet violation, then issues error.
+
+The error should be ignored in `debug-ignored-errors'"
+  (unless yas--inhibit-overlay-hooks
+    (cond ((not (or after?
+                    (yas--undo-in-progress)))
+           (setq yas--protection-violation (point))
+           (error "Exit the snippet first!")))))
+
+(add-to-list 'debug-ignored-errors "^Exit the snippet first!$")
+
+
+;; Snippet expansion and "stacked" expansion:
+;;
+;; Stacked expansion is when you try to expand a snippet when already
+;; inside a snippet expansion.
+;;
+;; The parent snippet does not run its fields modification hooks
+;; (`yas--on-field-overlay-modification' and
+;; `yas--on-protection-overlay-modification') while the child snippet
+;; is active. This means, among other things, that the mirrors of the
+;; parent snippet are not updated, this only happening when one exits
+;; the child snippet.
+;;
+;; Unfortunately, this also puts some ugly (and not fully-tested)
+;; bits of code in `yas-expand-snippet' and
+;; `yas--commit-snippet'. I've tried to mark them with "stacked
+;; expansion:".
+;;
+;; This was thought to be safer in in an undo/redo perpective, but
+;; maybe the correct implementation is to make the globals
+;; `yas--active-field-overlay' and `yas--field-protection-overlays' be
+;; snippet-local and be active even while the child snippet is
+;; running. This would mean a lot of overlay modification hooks
+;; running, but if managed correctly (including overlay priorities)
+;; they should account for all situations...
+;;
+(defun yas-expand-snippet (content &optional start end expand-env)
+  "Expand snippet CONTENT at current point.
+
+Text between START and END will be deleted before inserting
+template. EXPAND-ENV is are let-style variable to value bindings
+considered when expanding the snippet."
+  (run-hooks 'yas-before-expand-snippet-hook)
+
+  ;;
+  (let* ((yas-selected-text (or yas-selected-text
+                                (and (region-active-p)
+                                     (buffer-substring-no-properties 
(region-beginning)
+                                                                     
(region-end)))))
+         (start (or start
+                    (and (region-active-p)
+                         (region-beginning))
+                    (point)))
+         (end (or end
+                  (and (region-active-p)
+                       (region-end))
+                  (point)))
+         (to-delete (and start
+                         end
+                         (buffer-substring-no-properties start end)))
+         snippet)
+    (goto-char start)
+    (setq yas--indent-original-column (current-column))
+    ;; Delete the region to delete, this *does* get undo-recorded.
+    ;;
+    (when (and to-delete
+               (> end start))
+      (delete-region start end))
+
+    (cond ((listp content)
+           ;; x) This is a snippet-command
+           ;;
+           (yas--eval-lisp-no-saves content))
+          (t
+           ;; x) This is a snippet-snippet :-)
+           ;;
+           ;;    Narrow the region down to the content, shoosh the
+           ;;    `buffer-undo-list', and create the snippet, the new
+           ;;    snippet updates its mirrors once, so we are left with
+           ;;    some plain text.  The undo action for deleting this
+           ;;    plain text will get recorded at the end.
+           ;;
+           ;;    stacked expansion: also shoosh the overlay modification hooks
+           (save-restriction
+             (narrow-to-region start start)
+             (let ((buffer-undo-list t))
+               ;; snippet creation might evaluate users elisp, which
+               ;; might generate errors, so we have to be ready to catch
+               ;; them mostly to make the undo information
+               ;;
+               (setq yas--start-column (save-restriction (widen) 
(current-column)))
+               (yas--inhibit-overlay-hooks
+                 (setq snippet
+                       (if expand-env
+                           (eval `(let* ,expand-env
+                                    (insert content)
+                                    (yas--snippet-create (point-min) 
(point-max))))
+                         (insert content)
+                         (yas--snippet-create (point-min) (point-max)))))))
+
+           ;; stacked-expansion: This checks for stacked expansion, save the
+           ;; `yas--previous-active-field' and advance its boudary.
+           ;;
+           (let ((existing-field (and yas--active-field-overlay
+                                      (overlay-buffer 
yas--active-field-overlay)
+                                      (overlay-get yas--active-field-overlay 
'yas--field))))
+             (when existing-field
+               (setf (yas--snippet-previous-active-field snippet) 
existing-field)
+               (yas--advance-end-maybe existing-field (overlay-end 
yas--active-field-overlay))))
+
+           ;; Exit the snippet immediately if no fields
+           ;;
+           (unless (yas--snippet-fields snippet)
+             (yas-exit-snippet snippet))
+
+           ;; Push two undo actions: the deletion of the inserted contents of
+           ;; the new snippet (without the "key") followed by an apply of
+           ;; `yas--take-care-of-redo' on the newly inserted snippet boundaries
+           ;;
+           ;; A small exception, if `yas-also-auto-indent-first-line'
+           ;; is t and `yas--indent' decides to indent the line to a
+           ;; point before the actual expansion point, undo would be
+           ;; messed up. We call the early point "newstart"".  case,
+           ;; and attempt to fix undo.
+           ;;
+           (let ((newstart (overlay-start (yas--snippet-control-overlay 
snippet)))
+                 (end (overlay-end (yas--snippet-control-overlay snippet))))
+             (when (< newstart start)
+               (push (cons (make-string (- start newstart) ? ) newstart) 
buffer-undo-list))
+             (push (cons newstart end) buffer-undo-list)
+             (push `(apply yas--take-care-of-redo ,start ,end ,snippet)
+                   buffer-undo-list))
+           ;; Now, schedule a move to the first field
+           ;;
+           (let ((first-field (car (yas--snippet-fields snippet))))
+             (when first-field
+               (sit-for 0) ;; fix issue 125
+               (yas--move-to-field snippet first-field)))
+           (yas--message 3 "snippet expanded.")
+           t))))
+
+(defun yas--take-care-of-redo (beg end snippet)
+  "Commits SNIPPET, which in turn pushes an undo action for
+reviving it.
+
+Meant to exit in the `buffer-undo-list'."
+  ;; slightly optimize: this action is only needed for snippets with
+  ;; at least one field
+  (when (yas--snippet-fields snippet)
+    (yas--commit-snippet snippet)))
+
+(defun yas--snippet-revive (beg end snippet)
+  "Revives the SNIPPET and creates a control overlay from BEG to
+END.
+
+BEG and END are, we hope, the original snippets boudaries. All
+the markers/points exiting existing inside SNIPPET should point
+to their correct locations *at the time the snippet is revived*.
+
+After revival, push the `yas--take-care-of-redo' in the
+`buffer-undo-list'"
+  ;; Reconvert all the points to markers
+  ;;
+  (yas--points-to-markers snippet)
+  ;; When at least one editable field existed in the zombie snippet,
+  ;; try to revive the whole thing...
+  ;;
+  (let ((target-field (or (yas--snippet-active-field snippet)
+                          (car (yas--snippet-fields snippet)))))
+    (when target-field
+      (setf (yas--snippet-control-overlay snippet) (yas--make-control-overlay 
snippet beg end))
+      (overlay-put (yas--snippet-control-overlay snippet) 'yas--snippet 
snippet)
+
+      (yas--move-to-field snippet target-field)
+
+      (push `(apply yas--take-care-of-redo ,beg ,end ,snippet)
+            buffer-undo-list))))
+
+(defun yas--snippet-create (begin end)
+  "Creates a snippet from an template inserted between BEGIN and END.
+
+Returns the newly created snippet."
+  (let ((snippet (yas--make-snippet)))
+    (goto-char begin)
+    (yas--snippet-parse-create snippet)
+
+    ;; Sort and link each field
+    (yas--snippet-sort-fields snippet)
+
+    ;; Create keymap overlay for snippet
+    (setf (yas--snippet-control-overlay snippet)
+          (yas--make-control-overlay snippet (point-min) (point-max)))
+
+    ;; Move to end
+    (goto-char (point-max))
+
+    snippet))
+
+
+;;; Apropos adjacencies and "fom's":
+;;
+;; Once the $-constructs bits like "$n" and "${:n" are deleted in the
+;; recently expanded snippet, we might actually have many fields,
+;; mirrors (and the snippet exit) in the very same position in the
+;; buffer. Therefore we need to single-link the
+;; fields-or-mirrors-or-exit (which I have abbreviated to "fom")
+;; according to their original positions in the buffer.
+;;
+;; Then we have operation `yas--advance-end-maybe' and
+;; `yas--advance-start-maybe', which conditionally push the starts and
+;; ends of these foms down the chain.
+;;
+;; This allows for like the printf with the magic ",":
+;;
+;;   printf ("${1:%s}\\n"${1:$(if (string-match "%" text) "," "\);")}  \
+;;   $2${1:$(if (string-match "%" text) "\);" "")}$0
+;;
+(defun yas--fom-start (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-start fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-start fom))
+        (t
+         (yas--exit-marker fom))))
+
+(defun yas--fom-end (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-end fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-end fom))
+        (t
+         (yas--exit-marker fom))))
+
+(defun yas--fom-next (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-next fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-next fom))
+        (t
+         (yas--exit-next fom))))
+
+(defun yas--fom-parent-field (fom)
+  (cond ((yas--field-p fom)
+         (yas--field-parent-field fom))
+        ((yas--mirror-p fom)
+         (yas--mirror-parent-field fom))
+        (t
+         nil)))
+
+(defun yas--calculate-adjacencies (snippet)
+  "Calculate adjacencies for fields or mirrors of SNIPPET.
+
+This is according to their relative positions in the buffer, and
+has to be called before the $-constructs are deleted."
+  (flet ((yas--fom-set-next-fom (fom nextfom)
+                               (cond ((yas--field-p fom)
+                                      (setf (yas--field-next fom) nextfom))
+                                     ((yas--mirror-p fom)
+                                      (setf (yas--mirror-next fom) nextfom))
+                                     (t
+                                      (setf (yas--exit-next fom) nextfom))))
+         (yas--compare-fom-begs (fom1 fom2)
+                               (if (= (yas--fom-start fom2) (yas--fom-start 
fom1))
+                                   (yas--mirror-p fom2)
+                                 (>= (yas--fom-start fom2) (yas--fom-start 
fom1))))
+         (yas--link-foms (fom1 fom2)
+                        (yas--fom-set-next-fom fom1 fom2)))
+    ;; make some yas--field, yas--mirror and yas--exit soup
+    (let ((soup))
+      (when (yas--snippet-exit snippet)
+        (push (yas--snippet-exit snippet) soup))
+      (dolist (field (yas--snippet-fields snippet))
+        (push field soup)
+        (dolist (mirror (yas--field-mirrors field))
+          (push mirror soup)))
+      (setq soup
+            (sort soup
+                  #'yas--compare-fom-begs))
+      (when soup
+        (reduce #'yas--link-foms soup)))))
+
+(defun yas--calculate-mirrors-in-fields (snippet mirror)
+  "Attempt to assign a parent field of SNIPPET to the mirror MIRROR.
+
+Use the tighest containing field if more than one field contains
+the mirror. Intended to be called *before* the dollar-regions are
+deleted."
+  (let ((min (point-min))
+        (max (point-max)))
+    (dolist (field (yas--snippet-fields snippet))
+      (when (and (<= (yas--field-start field) (yas--mirror-start mirror))
+                 (<= (yas--mirror-end mirror) (yas--field-end field))
+               (< min (yas--field-start field))
+               (< (yas--field-end field) max))
+          (setq min (yas--field-start field)
+                max (yas--field-end field))
+          (setf (yas--mirror-parent-field mirror) field)))))
+
+(defun yas--advance-end-maybe (fom newend)
+  "Maybe advance FOM's end to NEWEND if it needs it.
+
+If it does, also:
+
+* call `yas--advance-start-maybe' on FOM's next fom.
+
+* in case FOM is field call `yas--advance-end-maybe' on its parent
+  field
+
+Also, if FOM is an exit-marker, always call
+`yas--advance-start-maybe' on its next fom. This is beacuse
+exit-marker have identical start and end markers.
+
+"
+  (cond ((and fom (< (yas--fom-end fom) newend))
+         (set-marker (yas--fom-end fom) newend)
+         (yas--advance-start-maybe (yas--fom-next fom) newend)
+         (yas--advance-end-of-parents-maybe (yas--fom-parent-field fom) 
newend))
+        ((yas--exit-p fom)
+         (yas--advance-start-maybe (yas--fom-next fom) newend))))
+
+(defun yas--advance-start-maybe (fom newstart)
+  "Maybe advance FOM's start to NEWSTART if it needs it.
+
+If it does, also call `yas--advance-end-maybe' on FOM."
+  (when (and fom (< (yas--fom-start fom) newstart))
+    (set-marker (yas--fom-start fom) newstart)
+    (yas--advance-end-maybe fom newstart)))
+
+(defun yas--advance-end-of-parents-maybe (field newend)
+  "Like `yas--advance-end-maybe' but for parent fields.
+
+Only works for fields and doesn't care about the start of the
+next FOM. Works its way up recursively for parents of parents."
+  (when (and field
+             (< (yas--field-end field) newend))
+    (set-marker (yas--field-end field) newend)
+    (yas--advance-end-of-parents-maybe (yas--field-parent-field field) 
newend)))
+
+(defvar yas--dollar-regions nil
+  "When expanding the snippet the \"parse-create\" functions add
+  cons cells to this var")
+
+(defvar yas--backquote-markers-and-strings nil
+  "List of (MARKER . STRING) marking where the the values
+  from backquoted lisp expressions should be inserted at the end of
+  expansion" )
+
+(defun yas--snippet-parse-create (snippet)
+  "Parse a recently inserted snippet template, creating all
+necessary fields, mirrors and exit points.
+
+Meant to be called in a narrowed buffer, does various passes"
+  (let ((parse-start (point)))
+    ;; Reset the yas--dollar-regions
+    ;;
+    (setq yas--dollar-regions nil)
+    ;; protect just the backquotes
+    ;;
+    (yas--protect-escapes nil '(?`))
+    ;; replace all backquoted expressions
+    ;;
+    (goto-char parse-start)
+    (yas--save-backquotes)
+    ;; protect escaped characters
+    ;;
+    (yas--protect-escapes)
+    ;; parse fields with {}
+    ;;
+    (goto-char parse-start)
+    (yas--field-parse-create snippet)
+    ;; parse simple mirrors and fields
+    ;;
+    (goto-char parse-start)
+    (yas--simple-mirror-parse-create snippet)
+    ;; parse mirror transforms
+    ;;
+    (goto-char parse-start)
+    (yas--transform-mirror-parse-create snippet)
+    ;; calculate adjacencies of fields and mirrors
+    ;;
+    (yas--calculate-adjacencies snippet)
+    ;; Delete $-constructs
+    ;;
+    (yas--delete-regions yas--dollar-regions)
+    ;; restore backquoted expression values
+    ;;
+    (yas--restore-backquotes)
+    ;; restore escapes
+    ;;
+    (goto-char parse-start)
+    (yas--restore-escapes)
+    ;; update mirrors for the first time
+    ;;
+    (yas--update-mirrors snippet)
+    ;; indent the best we can
+    ;;
+    (goto-char parse-start)
+    (yas--indent snippet)))
+
+(defun yas--indent-according-to-mode (snippet-markers)
+  "Indent current line according to mode, preserving
+SNIPPET-MARKERS."
+  ;;; Apropos indenting problems....
+  ;;
+  ;; `indent-according-to-mode' uses whatever `indent-line-function'
+  ;; is available. Some implementations of these functions delete text
+  ;; before they insert. If there happens to be a marker just after
+  ;; the text being deleted, the insertion actually happens after the
+  ;; marker, which misplaces it.
+  ;;
+  ;; This would also happen if we had used overlays with the
+  ;; `front-advance' property set to nil.
+  ;;
+  ;; This is why I have these `trouble-markers', they are the ones at
+  ;; they are the ones at the first non-whitespace char at the line
+  ;; (i.e. at `yas--real-line-beginning'. After indentation takes place
+  ;; we should be at the correct to restore them to. All other
+  ;; non-trouble-markers have been *pushed* and don't need special
+  ;; attention.
+  ;;
+  (goto-char (yas--real-line-beginning))
+  (let ((trouble-markers (remove-if-not #'(lambda (marker)
+                                            (= marker (point)))
+                                        snippet-markers)))
+    (save-restriction
+      (widen)
+      (condition-case err
+          (indent-according-to-mode)
+        (error (yas--message 3 "Warning: `yas--indent-according-to-mode' 
having problems running %s" indent-line-function)
+               nil)))
+    (mapc #'(lambda (marker)
+              (set-marker marker (point)))
+          trouble-markers)))
+
+(defvar yas--indent-original-column nil)
+(defun yas--indent (snippet)
+  (let ((snippet-markers (yas--collect-snippet-markers snippet)))
+    ;; Look for those $>
+    (save-excursion
+      (while (re-search-forward "$>" nil t)
+        (delete-region (match-beginning 0) (match-end 0))
+        (when (not (eq yas-indent-line 'auto))
+          (yas--indent-according-to-mode snippet-markers))))
+    ;; Now do stuff for 'fixed and 'auto
+    (save-excursion
+      (cond ((eq yas-indent-line 'fixed)
+             (while (and (zerop (forward-line))
+                         (zerop (current-column)))
+               (indent-to-column yas--indent-original-column)))
+            ((eq yas-indent-line 'auto)
+             (let ((end (set-marker (make-marker) (point-max)))
+                   (indent-first-line-p yas-also-auto-indent-first-line))
+               (while (and (zerop (if indent-first-line-p
+                                      (prog1
+                                          (forward-line 0)
+                                        (setq indent-first-line-p nil))
+                                    (forward-line 1)))
+                           (not (eobp))
+                           (<= (point) end))
+                 (yas--indent-according-to-mode snippet-markers))))
+            (t
+             nil)))))
+
+(defun yas--collect-snippet-markers (snippet)
+  "Make a list of all the markers used by SNIPPET."
+  (let (markers)
+    (dolist (field (yas--snippet-fields snippet))
+      (push (yas--field-start field) markers)
+      (push (yas--field-end field) markers)
+      (dolist (mirror (yas--field-mirrors field))
+        (push (yas--mirror-start mirror) markers)
+        (push (yas--mirror-end mirror) markers)))
+    (let ((snippet-exit (yas--snippet-exit snippet)))
+      (when (and snippet-exit
+                 (marker-buffer (yas--exit-marker snippet-exit)))
+        (push (yas--exit-marker snippet-exit) markers)))
+    markers))
+
+(defun yas--real-line-beginning ()
+  (let ((c (char-after (line-beginning-position)))
+        (n (line-beginning-position)))
+    (while (or (eql c ?\ )
+               (eql c ?\t))
+      (incf n)
+      (setq c (char-after n)))
+    n))
+
+(defun yas--escape-string (escaped)
+  (concat "YASESCAPE" (format "%d" escaped) "PROTECTGUARD"))
+
+(defun yas--protect-escapes (&optional text escaped)
+  "Protect all escaped characters with their numeric ASCII value.
+
+With optional string TEXT do it in string instead of buffer."
+  (let ((changed-text text)
+        (text-provided-p text))
+    (mapc #'(lambda (escaped)
+              (setq changed-text
+                    (yas--replace-all (concat "\\" (char-to-string escaped))
+                                     (yas--escape-string escaped)
+                                     (when text-provided-p changed-text))))
+          (or escaped yas--escaped-characters))
+    changed-text))
+
+(defun yas--restore-escapes (&optional text escaped)
+  "Restore all escaped characters from their numeric ASCII value.
+
+With optional string TEXT do it in string instead of the buffer."
+  (let ((changed-text text)
+        (text-provided-p text))
+    (mapc #'(lambda (escaped)
+              (setq changed-text
+                    (yas--replace-all (yas--escape-string escaped)
+                                     (char-to-string escaped)
+                                     (when text-provided-p changed-text))))
+          (or escaped yas--escaped-characters))
+    changed-text))
+
+(defun yas--save-backquotes ()
+  "Save all the \"`(lisp-expression)`\"-style expression
+with their evaluated value into `yas--backquote-markers-and-strings'"
+  (while (re-search-forward yas--backquote-lisp-expression-regexp nil t)
+    (let ((current-string (match-string-no-properties 1)) transformed)
+      (delete-region (match-beginning 0) (match-end 0))
+      (setq transformed (yas--eval-lisp (yas--read-lisp (yas--restore-escapes 
current-string '(?`)))))
+      (goto-char (match-beginning 0))
+      (when transformed
+        (let ((marker (make-marker)))
+          (insert "Y") ;; quite horrendous, I love it :)
+          (set-marker marker (point))
+          (insert "Y")
+          (push (cons marker transformed) 
yas--backquote-markers-and-strings))))))
+
+(defun yas--restore-backquotes ()
+  "Replace all the markers in
+`yas--backquote-markers-and-strings' with their values"
+  (while yas--backquote-markers-and-strings
+    (let* ((marker-and-string (pop yas--backquote-markers-and-strings))
+           (marker (car marker-and-string))
+           (string (cdr marker-and-string)))
+      (save-excursion
+        (goto-char marker)
+        (delete-char -1)
+        (insert string)
+        (delete-char 1)
+        (set-marker marker nil)))))
+
+(defun yas--scan-sexps (from count)
+  (condition-case err
+      (with-syntax-table (standard-syntax-table)
+        (scan-sexps from count))
+    (error
+     nil)))
+
+(defun yas--make-marker (pos)
+  "Create a marker at POS with `nil' `marker-insertion-type'"
+  (let ((marker (set-marker (make-marker) pos)))
+    (set-marker-insertion-type marker nil)
+    marker))
+
+(defun yas--field-parse-create (snippet &optional parent-field)
+  "Parse most field expressions, except for the simple one \"$n\".
+
+The following count as a field:
+
+* \"${n: text}\", for a numbered field with default text, as long as N is not 
0;
+
+* \"${n: text$(expression)}, the same with a lisp expression;
+  this is caught with the curiously named 
`yas--multi-dollar-lisp-expression-regexp'
+
+* the same as above but unnumbered, (no N:) and number is calculated 
automatically.
+
+When multiple expressions are found, only the last one counts."
+  ;;
+  (save-excursion
+    (while (re-search-forward yas--field-regexp nil t)
+      (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
+             (number (and (match-string-no-properties 1)
+                          (string-to-number (match-string-no-properties 1))))
+             (brand-new-field (and real-match-end-0
+                                   ;; break if on "$(" immediately
+                                   ;; after the ":", this will be
+                                   ;; caught as a mirror with
+                                   ;; transform later.
+                                   (not (save-match-data
+                                          (eq (string-match "$[ \t\n]*("
+                                                            
(match-string-no-properties 2)) 0)))
+                                   ;; allow ${0: some exit text}
+                                   ;; (not (and number (zerop number)))
+                                   (yas--make-field number
+                                                   (yas--make-marker 
(match-beginning 2))
+                                                   (yas--make-marker (1- 
real-match-end-0))
+                                                   parent-field))))
+        (when brand-new-field
+          (goto-char real-match-end-0)
+          (push (cons (1- real-match-end-0) real-match-end-0)
+                yas--dollar-regions)
+          (push (cons (match-beginning 0) (match-beginning 2))
+                yas--dollar-regions)
+          (push brand-new-field (yas--snippet-fields snippet))
+          (save-excursion
+            (save-restriction
+              (narrow-to-region (yas--field-start brand-new-field) 
(yas--field-end brand-new-field))
+              (goto-char (point-min))
+              (yas--field-parse-create snippet brand-new-field)))))))
+  ;; if we entered from a parent field, now search for the
+  ;; `yas--multi-dollar-lisp-expression-regexp'. THis is used for
+  ;; primary field transformations
+  ;;
+  (when parent-field
+    (save-excursion
+      (while (re-search-forward yas--multi-dollar-lisp-expression-regexp nil t)
+        (let* ((real-match-end-1 (yas--scan-sexps (match-beginning 1) 1)))
+          ;; commit the primary field transformation if:
+          ;;
+          ;; 1. we don't find it in yas--dollar-regions (a subnested
+          ;; field) might have already caught it.
+          ;;
+          ;; 2. we really make sure we have either two '$' or some
+          ;; text and a '$' after the colon ':'. This is a FIXME: work
+          ;; my regular expressions and end these ugly hacks.
+          ;;
+          (when (and real-match-end-1
+                     (not (member (cons (match-beginning 0)
+                                        real-match-end-1)
+                                  yas--dollar-regions))
+                     (not (eq ?:
+                              (char-before (1- (match-beginning 1))))))
+            (let ((lisp-expression-string (buffer-substring-no-properties 
(match-beginning 1)
+                                                                          
real-match-end-1)))
+              (setf (yas--field-transform parent-field)
+                    (yas--read-lisp (yas--restore-escapes 
lisp-expression-string))))
+            (push (cons (match-beginning 0) real-match-end-1)
+                  yas--dollar-regions)))))))
+
+(defun yas--transform-mirror-parse-create (snippet)
+  "Parse the \"${n:$(lisp-expression)}\" mirror transformations."
+  (while (re-search-forward yas--transform-mirror-regexp nil t)
+    (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
+           (number (string-to-number (match-string-no-properties 1)))
+           (field (and number
+                       (not (zerop number))
+                       (yas--snippet-find-field snippet number)))
+           (brand-new-mirror
+            (and real-match-end-0
+                 field
+                 (yas--make-mirror (yas--make-marker (match-beginning 0))
+                                  (yas--make-marker (match-beginning 0))
+                                  (yas--read-lisp
+                                   (yas--restore-escapes
+                                    (buffer-substring-no-properties 
(match-beginning 2)
+                                                                    (1- 
real-match-end-0))))))))
+      (when brand-new-mirror
+        (push brand-new-mirror
+              (yas--field-mirrors field))
+        (yas--calculate-mirrors-in-fields snippet brand-new-mirror)
+        (push (cons (match-beginning 0) real-match-end-0) 
yas--dollar-regions)))))
+
+(defun yas--simple-mirror-parse-create (snippet)
+  "Parse the simple \"$n\" fields/mirrors/exitmarkers."
+  (while (re-search-forward yas--simple-mirror-regexp nil t)
+    (let ((number (string-to-number (match-string-no-properties 1))))
+      (cond ((zerop number)
+
+             (setf (yas--snippet-exit snippet)
+                   (yas--make-exit (yas--make-marker (match-end 0))))
+             (save-excursion
+               (goto-char (match-beginning 0))
+               (when yas-wrap-around-region
+                 (cond (yas-selected-text
+                        (insert yas-selected-text))
+                       ((and (eq yas-wrap-around-region 'cua)
+                             cua-mode
+                             (get-register ?0))
+                        (insert (prog1 (get-register ?0)
+                                  (set-register ?0 nil))))))
+               (push (cons (point) (yas--exit-marker (yas--snippet-exit 
snippet)))
+                     yas--dollar-regions)))
+            (t
+             (let ((field (yas--snippet-find-field snippet number)))
+               (if field
+