diff --git a/Rakefile b/Rakefile index 23a1f9c..273b6f3 100644 --- a/Rakefile +++ b/Rakefile @@ -11,8 +11,7 @@ FileUtils.mkdir_p('pkg') desc "generate the bundle file." task :bundle do - sh 'emacs --batch -l yasnippet.el --eval "(yas/compile-bundle ' + - '\"./yasnippet.el\" \"./yasnippet-bundle.el\" \"./snippets\")"' + sh 'emacs --batch -l yasnippet.el --eval "(yas/compile-bundle)"' sh "tar czf pkg/yasnippet-bundle-#{$version}.el.tgz yasnippet-bundle.el" end diff --git a/doc/compile-doc.py b/doc/compile-doc.py index f44cc84..9e152cb 100755 --- a/doc/compile-doc.py +++ b/doc/compile-doc.py @@ -7,7 +7,7 @@ from pygments.formatters import HtmlFormatter # Set to True if you want inline CSS styles instead of classes -INLINESTYLES = False +INLINESTYLES = True from pygments.formatters import HtmlFormatter diff --git a/doc/define_snippet.rst b/doc/define_snippet.rst new file mode 100644 index 0000000..91e88cf --- /dev/null +++ b/doc/define_snippet.rst @@ -0,0 +1,276 @@ +========================= +How to define a snippet ? +========================= + +:Author: pluskid +:Contact: pluskid@gmail.com +:Date: 2008-03-20 + +.. contents:: + +The most convenient way to define snippets for YASnippet is to put +them in a directory arranged by the mode and use +``yas/load-directory`` to load them. + +However, this might slow down the Emacs startup speed if you have many +snippets. You can use ``yas/define-snippets`` to define a bunch of +snippets for a perticular mode. But this is hard to maintain! So, +there's a better way: define your snippets in directory and use +``yas/compile-bundle`` to compile it into a bundle file when you +modified your snippets. + +The release bundle of YASnippet is produced by +``yas/compile-bundle``. The bundle use ``yas/define-snippets`` to +define snippets. This avoid the IO and parsing overhead when loading +snippets. + +Finally, you can use ``yas/define`` to define a single snippet at your +convenience. I ofthen use this to do some testing. + +Define snippets in files +======================== + +Directory hierarchy +------------------- + +Here's the directory hierarchy of the ``snippets`` directory comes +with YASnippet: + +.. sourcecode:: text + + snippets + `-- text-mode/ + |-- cc-mode/ + | |-- c++-mode/ + | | |-- beginend + | | |-- class + | | `-- using + | |-- c-mode/ + | | `-- fopen + | |-- do + | |-- for + | |-- if + | |-- inc + | |-- inc.1 + | |-- main + | |-- once + | `-- struct + |-- css-mode/ + | |-- background + | |-- background.1 + | `-- border + |-- email + |-- html-mode/ + | |-- div + | |-- doctype + | |-- doctype.xhml1 + | |-- doctype.xhtml1_1 + | |-- doctype.xhtml1_strict + | `-- doctype.xhtml1_transitional + |-- objc-mode/ + | `-- prop + |-- perl-mode/ + | |-- cperl-mode/ + | |-- eval + | |-- for + | |-- fore + | |-- if + | |-- ife + | |-- ifee + | |-- sub + | |-- unless + | |-- while + | |-- xfore + | |-- xif + | |-- xunless + | `-- xwhile + |-- python-mode/ + | |-- __ + | |-- class + | |-- def + | |-- for + | |-- ifmain + | `-- while + |-- rst-mode/ + | |-- chapter + | |-- section + | `-- title + |-- ruby-mode/ + | |-- # + | |-- =b + | |-- Comp + | |-- all + | |-- am + | |-- any + | |-- app + | |-- bm + | |-- case + | |-- cla + | |-- classify + | |-- cls + | |-- collect + | |-- dee + | |-- deli + | |-- det + | |-- ea + | |-- eac + | |-- eai + | |-- eav + | |-- eawi + | |-- forin + | |-- if + | |-- ife + | |-- inject + | |-- mm + | |-- r + | |-- rb + | |-- reject + | |-- req + | |-- rreq + | |-- rw + | |-- select + | |-- w + | |-- y + | `-- zip + `-- time + +Snippet definitions are put in plain text files. They are arranged by +subdirectories. For example, snippets for ``c-mode`` are put in the +``c-mode`` directory. + +The parent directory acts as the *parent mode*. This is the way of +YASnippet to share snippet definitions among different modes. As you +can see above, ``c-mode`` and ``c++-mode`` share the same parents +``cc-mode``, while all modes are derived from ``text-mode``. This can +be also used to as an *alias* -- ``cperl-mode`` is an empty directory +whose parent is ``perl-mode``. + +File names act as the snippet trigger key. Note files starting with a +dot (``.``) are ignored. + +File content +------------ + +A file defining a snippet may just contain the template for the +snippet. Optionally it can also contains some meta data for the +snippet as well as comments. + +Generally speaking, if the file contains a line of ``# --``, then all +contents above that line are considered as meta data and comments; +below are template. Or else the whole file content is considered as +the template. + +Here's a typical example: + +.. sourcecode:: text + + #contributor : pluskid + #name : __...__ + # -- + __${init}__ + +Meta data are specified in the syntax of + +.. sourcecode:: text + + #data-name : data value + +Any other text above ``# --`` is considered as comment and +ignored. You might want to refer to the list of currently `supported +meta data`_ . + +Define snippets using elisp code +-------------------------------- + +As I mentioned above, you can define snippets directly by writing +elisp code. + +yas/define-snippets +~~~~~~~~~~~~~~~~~~~ + +The basic syntax of ``yas/define-snippets`` is + +.. sourcecode:: common-lisp + + (yas/define-snippets MODE SNIPPETS &optional PARENT) + +The parameters are self-descriptive. If you specify a ``PARENT``, then +the snippets of the parents may be shared by ``MODE``. Note if you use +this function several times, the later specified ``PARENT`` will +overwrite the original one. However, not specifying a ``PARENT`` won't +erase the original parent. + +The ``SNIPPETS`` parameter is a list of snippet definitions. Each +element should have the following form: + +.. sourcecode:: common-lisp + + (KEY TEMPLATE NAME CONDITION) + +The ``NAME`` and ``CONDITION`` can be omitted if you don't want to +provide one. Here's an example: + +.. sourcecode:: common-lisp + + (yas/define-snippets 'c++-mode + '( + ("using" "using namespace ${std}; + $0" "using namespace ... " nil) + ("class" "class ${1:Name} + { + public: + $1($2); + virtual ~$1(); + };" "class ... { ... }" nil) + ("beginend" "${1:v}.begin(), $1.end" "v.begin(), v.end()" nil) + ) + 'cc-mode) + +The example above is auto-generated code by ``yas/compile-bundle``. + +yas/compile-bundle +~~~~~~~~~~~~~~~~~~ + +``yas/compile-bundle`` can be used to parse the snippets from a +directory hierarchy and translate them into the elisp form. The +translated code is faster to load. Further more, the generated bundle +is a stand-alone file not depending on ``yasnippet.el``. The released +bundles of YASnippet are all generated this way. + +The basic syntax of ``yas/compile-bundle`` is + +.. sourcecode:: common-lisp + + (yas/compile-bundle &optional yasnippet yasnippet-bundle snippet-roots code) + +As you can see, all the parameters are optional. The default values +for those parameters are convenient for me to produce the default +release bundle: + +.. sourcecode:: common-lisp + + (yas/compile-bundle "yasnippet.el" + "./yasnippet-bundle.el" + '("snippets") + "(yas/initialize)") + +The ``snippet-roots`` can be a list of root directories. This is +useful when you have multiple snippet directories (maybe from other +users). The ``code`` parameter can be used to specify your own +customization code instead of the default ``(yas/initialize)``. For +example, you can set ``yas/trigger-key`` to ``(kbd "SPC")`` here if +you like. + +The Syntax of the Template +========================== + +.. _supported meta data: + +* ``name``: The name of the snippet. This is a one-line description of + the snippet. It will be displayed in the menu. So it's a good idea + to select a descriptive name fo a snippet -- especially + distinguishable among similar snippets. +* ``contributor``: The contributor of the snippet. +* ``condition``: The condition of the snippet. This is a piece of + elisp code. If a snippet has a condition, then it will only be + expanded when the condition code evaluate to some non-nil value. diff --git a/doc/index.rst b/doc/index.rst index fbdf166..12f9809 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -5,4 +5,133 @@ YASnippet - Yet Another Snippet extension for Emacs :Author: pluskid :Contact: pluskid@gmail.com :Date: 2008-03-20 -:Version: $Revision: 1 $ + +.. contents:: + +YASnippet is a re-design and re-write of my original extension +`smart-snippet`_. It is much cleaner and more powerful than +smart-snippet. + +.. _smart-snippet: http://code.google.com/p/smart-snippet/ + +Getting Started +=============== + +For the busy or impatient people +-------------------------------- + +Watch the `screencast at YouTube +`_ or download `the one +with a higher resolution +`_. + +For lazy poeple or beginners +---------------------------- + +.. _downloads page: http://code.google.com/p/yasnippet/downloads/list + +1. Download the latest bundle release [1]_ from the `downloads page`_. +2. Create a directory ``~/emacs/plugins``. +3. Unpack the downloaded bundle to that directory. +4. Add the following code to your ``~/.emacs`` file: + + .. sourcecode:: common-lisp + + (add-to-list 'load-path + "~/emacs/plugins") + (require 'yasnippet-bundle) + +For you +------- + +1. Download the latest YASnippet release package [2]_ from the + `downloads page`_. +2. Unpack it to a directory and add that directory to your + ``load-path``. +3. Add the following code to your ``~/.emacs`` file: + + .. sourcecode:: common-lisp + + (require 'yasnippet) ;; not yasnippet-bundle + (yas/initialize) + (yas/load-directory "/path/to/the/snippets/directory/") + +4. You can inspect into the ``snippets`` directory for adding your own + snippets. +5. Detailed document can be found at the ``doc`` directory. + +For geeks +--------- + +If you want to always follow the latest code. You can check out it +from the svn repository: + +.. sourcecode:: bash + + svn checkout http://yasnippet.googlecode.com/svn/trunk/ yasnippet + +However, I try to release a new version as soon as I made some changes +that will affect the normal use or added some new features. So there's +usually no need to follow the svn repository. Except that you might +find ``svn up`` is more convenient than downloading and unpacking the +release package. :D + +How to contribute ? +=================== + +If you like YASnippet, you can recommendate it to your friends. + +Issues +------ + +If you find a bug you can create a new issue at the `issue list +`_. Please describe +the problem as clear as possible. + +Suggestion, Feature Request +--------------------------- + +There's a `discussion group`_ for both smart-snippet and yasnippet. If +you have any suggesion, you can post to there and discuss with other +members. + +Especially, there's a `wish list`_ wiki page. I'll collect ideas from +the `discussion group`_ to the `wish list`_. So you might want to look +at the `wish list`_ before you post something. + +Snippets +-------- + +YASnippet comes with some default snippet definitions. However, they +are far from complete. So I'm calling users to share their +snippets. If you have some good snippet definitions, you can post them +to the `discussion group`_. You can specify the ``contributor`` +property of the snippet like: + +.. sourcecode:: text + + #contributor : pluskid + #name : __...__ + # -- + __${init}__ + +I'll incorporate (some of) them in the release if suitable. However, +if you have *many* snippets (especially when they need to be +maintained and updated constantly), it is not suitable to put them in +the YASnippet release package. A better way is to make your snippets +publicly available and tell me the URL. I'll try to keep a list of +them on the wiki page. + +.. _discussion group: http://groups.google.com/group/smart-snippet +.. _wish list: http://code.google.com/p/yasnippet/wiki/WishList + +Detailed Documentation +====================== + +* See `this page `_ on how to define a snippet by + yourself. +* Here's the `FAQ `_ page. + +.. [1] They usually named like ``yasnippet-bundle-x.y.z.el.tgz`` where + ``x.y.z`` is the version number. +.. [2] They usually named like ``yasnippet.x.y.z.tar.bz2``. diff --git a/yasnippet.el b/yasnippet.el index 5979f47..97ac821 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -873,15 +873,28 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\"" t) "\"")) -(defun yas/compile-bundle (yasnippet yasnippet-bundle snippet-roots) +(defun yas/compile-bundle + (&optional yasnippet yasnippet-bundle snippet-roots code) "Compile snippets in SNIPPET-ROOTS to a single bundle file. SNIPPET-ROOTS is a list of root directories that contains the snippets definition. YASNIPPET is the yasnippet.el file path. YASNIPPET-BUNDLE -is the output file of the compile result. Here's an example: +is the output file of the compile result. CODE is the code you would +like to used to initialize yasnippet. Here's the default value for +all the parameters: + + (yas/compile-bundle \"yasnippet.el\" + \"./yasnippet-bundle.el\" + '(\"snippets\") + \"(yas/initialize)\")" + (when (null yasnippet) + (setq yasnippet "yasnippet.el")) + (when (null yasnippet-bundle) + (setq yasnippet-bundle "./yasnippet-bundle.el")) + (when (null snippet-roots) + (setq snippet-roots '("snippets"))) + (when (null code) + (setq code "(yas/initialize)")) - (yas/compile-bundle \"~/.emacs.d/plugins/yasnippet/yasnippet.el\" - \"~/.emacs.d/plugins/yasnippet-bundle.el\" - '(\"~/.emacs.d/plugins/yasnippet/snippets\"))" (let ((dirs (or (and (listp snippet-roots) snippet-roots) (list snippet-roots))) (bundle-buffer nil)) @@ -892,7 +905,7 @@ is the output file of the compile result. Here's an example: (insert ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n") (insert ";;;; Auto-generated code ;;;;\n") (insert ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n") - (insert "(yas/initialize)\n") + (insert code "\n") (flet ((yas/define-snippets (mode snippets &optional parent) (with-current-buffer bundle-buffer @@ -902,10 +915,13 @@ is the output file of the compile result. Here's an example: (dolist (snippet snippets) (insert " (" (yas/quote-string (car snippet)) + " " (yas/quote-string (cadr snippet)) + " " (if (caddr snippet) (yas/quote-string (caddr snippet)) "nil") + " " (if (nth 3 snippet) (format "'%s" (nth 3 snippet)) "nil")