Compare commits

..

No commits in common. "master" and "0.9.1" have entirely different histories.

24 changed files with 2321 additions and 4379 deletions

4
.gitignore vendored
View File

@ -9,7 +9,3 @@ extras/imported/**
*.elc *.elc
ert-x.* ert-x.*
ert.* ert.*
# ELPA-generated files
/yasnippet-autoloads.el
/yasnippet-pkg.el

7
.gitmodules vendored
View File

@ -0,0 +1,7 @@
[submodule "snippets"]
path = snippets
url = https://github.com/AndreaCrotti/yasnippet-snippets.git
branch = master
[submodule "yasmate"]
path = yasmate
url = https://github.com/capitaomorte/yasmate.git

View File

@ -1,49 +1,24 @@
language: generic language: emacs
os: linux
dist: xenial
git:
submodules: false
env: env:
global: - "EMACS=emacs23"
- Wlexical=t - "EMACS=emacs24"
- Werror=t
- tests_Werror=t # For yasnippet-tests.el
jobs:
- EMACS_VERSION=23.4
# 24.3 gives a bunch of 'value returned from (car value-N) is
# unused' warnings.
- EMACS_VERSION=24.3 tests_Werror=nil
- EMACS_VERSION=24.5
- EMACS_VERSION=25.3
- EMACS_VERSION=26.3
- EMACS_VERSION=27-prerelease
install: install:
- curl -LO https://github.com/npostavs/emacs-travis/releases/download/bins/emacs-bin-${EMACS_VERSION}.tar.gz - if [ "$EMACS" = "emacs23" ]; then
- tar -xaf emacs-bin-${EMACS_VERSION}.tar.gz -C / sudo apt-get -qq update &&
# Configure $PATH: Emacs installed to /tmp/emacs sudo apt-get -qq -f install &&
- export PATH=/tmp/emacs/bin:${PATH} sudo apt-get -qq install emacs23-nox &&
- if ! emacs -Q --batch --eval "(require 'cl-lib)" ; then
curl -Lo cl-lib.el http://elpa.gnu.org/packages/cl-lib-0.6.1.el ;
export warnings="'(not cl-functions)" ;
fi
- if ! emacs -Q --batch --eval "(require 'ert)" ; then
curl -LO https://raw.githubusercontent.com/ohler/ert/c619b56c5bc6a866e33787489545b87d79973205/lisp/emacs-lisp/ert.el && curl -LO https://raw.githubusercontent.com/ohler/ert/c619b56c5bc6a866e33787489545b87d79973205/lisp/emacs-lisp/ert.el &&
curl -LO https://raw.githubusercontent.com/ohler/ert/c619b56c5bc6a866e33787489545b87d79973205/lisp/emacs-lisp/ert-x.el ; curl -LO https://raw.githubusercontent.com/ohler/ert/c619b56c5bc6a866e33787489545b87d79973205/lisp/emacs-lisp/ert-x.el &&
curl -Lo cl-lib.el http://elpa.gnu.org/packages/cl-lib-0.5.el;
fi
- if [ "$EMACS" = "emacs24" ]; then
sudo add-apt-repository -y ppa:cassou/emacs &&
sudo apt-get -qq update &&
sudo apt-get -qq -f install &&
sudo apt-get -qq install emacs24-nox;
fi fi
- emacs --version
script: script:
- rake yasnippet.elc - rake compile; rake tests
- rake yasnippet-debug.elc
- rake yasnippet-tests.elc Werror=$tests_Werror
- rake tests
notifications:
email:
# Default is change, but that includes a new branch's 1st success.
on_success: never
on_failure: always # The default.

View File

@ -1,37 +1,29 @@
# Submitting Bug Reports or Patches # Submitting Bug Reports
As a GNU ELPA package, bugs or patches may be submitted to the main Please read [Important note regarding bug reporting][bugnote].
Emacs bug list, bug-gnu-emacs@gnu.org. Alternatively, you may use the
[Github issue tracker][issues]. # Contributing to Yasnippet
Please read [Important note regarding bug reporting][bugnote]. ## Copyright Assignment
# Contributing to Yasnippet Yasnippet is part of GNU ELPA, so it falls under the same copyright
assignment policy as the rest of Emacs (see "Copyright Assignment" in
## Copyright Assignment https://www.gnu.org/software/emacs/CONTRIBUTE). A copyright assignment
for Emacs also covers Yasnippet.
Yasnippet is part of GNU ELPA, so it falls under the same copyright
assignment policy as the rest of Emacs (see "Copyright Assignment" in ## Commit message format
https://www.gnu.org/software/emacs/CONTRIBUTE). A copyright assignment
for Emacs also covers Yasnippet. The commit message format roughly follows Emacs conventions, although
there is no separate Changelog file.
## Commit message format
The commit message's first sentence should be capitalized, no period
The commit message format roughly follows Emacs conventions. There is
no separate Changelog file. It may be followed by a paragraph with a longer explanation. The
changelog style entry goes at the end of the message.
Capitalize the first sentence, no period at the end
* foo.el (a-function): Terse summary of per-function changes.
Please make sure the summary line can be understood without having
to lookup bug numbers. It may be followed by a paragraph with a For trivial changes, a message consisting of just the changelog entry
longer explanation. The changelog style entry goes at the end of (the `* foo.el ...` part) is fine.
the message.
* foo.el (a-function): Terse summary of per-function changes. Use [bugnote]: https://github.com/capitaomorte/yasnippet#important-note-regarding-bug-reporting
double spacing between sentences (set `sentence-end-double-space'
to t).
For trivial changes, a message consisting of just the changelog entry
(e.g., `* foo.el (a-function): Fix docstring typo.`) is fine.
[bugnote]: https://github.com/joaotavora/yasnippet#important-note-regarding-bug-reporting
[issues]: https://github.com/joaotavora/yasnippet/issues

View File

@ -1,46 +0,0 @@
### Makefile for Yasnippet (stolen from Eglot)
# Variables
#
EMACS?=emacs
SELECTOR?=t
ERROR_ON_WARN=nil
LOAD_PATH=-L .
ELFILES := yasnippet.el yasnippet-tests.el
ELCFILES := $(ELFILES:.el=.elc)
BYTECOMP_ERROR_ON_WARN := \
--eval '(setq byte-compile-error-on-warn $(ERROR_ON_WARN))'
all: compile
%.elc: %.el
$(EMACS) -Q $(BYTECOMP_ERROR_ON_WARN) $(LOAD_PATH) \
--batch -f batch-byte-compile $<
compile: $(ELCFILES)
# Automated tests
#
yasnippet-check: compile
$(EMACS) -Q --batch \
$(LOAD_PATH) \
-l yasnippet \
-l yasnippet-tests \
--eval '(setq ert-batch-backtrace-right-margin 200)' \
--eval '(ert-run-tests-batch-and-exit (quote $(SELECTOR)))'
interactive: compile
$(EMACS) -Q \
$(LOAD_PATH) \
-l yasnippet \
-l yasnippet-tests \
check: yasnippet-check
# Cleanup
#
clean:
find . -iname '*.elc' -exec rm {} \;
.PHONY: all compile clean check

366
NEWS
View File

@ -1,368 +1,10 @@
Yasnippet NEWS -- history of user-visible changes. Yasnippet NEWS -- history of user-visible changes.
Copyright (C) 2017-2025 Free Software Foundation, Inc. Copyright (C) 2016 Free Software Foundation, Inc.
See the end of the file for license conditions. See the end of the file for license conditions.
Changes since 0.14.0:
- Silence warning about missing lexical-binding cookie.
- Bug fixes and code cleanups.
- Accept ${N} as another syntax for $N (issue #1012).
- Understand the new AUCTeX modes hierarchy (issue #1193).
- Try and use `major-mode-remap-alist` to find the right snippets for
Tree Sitter modes (issue #1169).
* 0.14.0 (Dec 22, 2019)
** Changes
*** New 'yas-auto-next' macro, automatically moves to next field.
See Github #937.
*** Yasnippet now officially requires Emacs 23 or greater.
See Github #940.
*** Snippets for 'fundamental-mode' are available in all modes.
See Github #949, and #936.
*** New function for snippets, 'yas-completing-read'.
See Github #934.
*** New function 'yas-maybe-expand-abbrev-key-filter'.
This can be used for making conditional keybindings for snippets.
Promoted from 'yas--maybe-expand-key-filter'. See Github #943.
*** DEL can now be used to clear fields, similar <delete>.
It is bound to the new conditional command 'yas-maybe-clear-field', which may
be bound to other keys as well. See Github #960 and #957.
*** Snippet field movement commands may now trigger eldoc.
See Github #952.
*** New variable 'yas-keymap-disable-hook'.
Can be used (e.g., for company-mode) to temporarily disable
'yas-keymap' bindings, or any binding made by the new function
'yas-filtered-definition'. See Github #987.
*** New variable 'yas-inhibit-overlay-modification-protection'.
This allows a snippet to remain active, even if some commands make
modifications outside the expected area (i.e., the active snippet
field).
*** 'yas-minor-mode' is no longer enabled in temp buffers.
That is, buffers whose name starts with a space. This setting may be
undone by removing 'yas-temp-buffer-p' from
'yas-dont-activate-functions'. See Github #985.
*** Accept unescaped '{', for LSP compatibility.
See Github #979.
** Fixed bugs
*** 'yas-not-string-or-comment-condition' no longer relies on 'this-command'.
This lets it work correctly with conditional key-bindings. See Github
#973, #991.
*** Fix snippet expansion in org src buffers.
Note that this still doesn't work in text-mode blocks.
See Github #976, #989.
*** Fix snippet insertion for keyless snippets.
See Github #1014.
*** Fix errors with company-mode completion within snippet fields.
See Github #995.
*** Fix errors with cc-mode.
See Github #962.
*** Fix problems with lsp-mode.
**** Improve performance in overlay heavy buffers (Github #926).
**** Fix double call of 'before/after-change-functions' (Github #966).
*** Fix errors with nested snippet expansion.
See Github #961, #1002.
*** Stop yas-field-highlight-face inheriting from bogus 'quote' face.
* 0.13.0 (May 13, 2018) * 0.9.1 (est. March 2016)
** Changes
*** Snippets for Yasnippet must now be installed separately. The
submodule linking to yasnippet-snippets was removed, as were the
"classic" snippets that came with the GNU ELPA package. The latter
can now be installed via the 'yasnippet-classic-snippets' package from
GNU ELPA.
See Github #848, #858, #834, #775.
*** 'snippet-mode' no longer derives from 'text-mode'.
It will derive from 'prog-mode' where available (Emacs 24.1 and newer)
or 'fundamental-mode' otherwise. See Github #826.
*** The default value of 'yas-key-syntaxes' is changed
Longer snippet abbrev keys are now preferred over shorter ones.
See Github #805.
*** New snippets are now created for the current major mode by default
Previously, extra activated modes could be guessed first.
See Github #875.
*** Yasnippet supports 'unload-feature' via 'yasnippet-unload-function'
See Github #753, #891.
*** New command 'yas-skip-and-clear-field' conditionally bound to 'C-d'
replaces obsoleted 'yas-skip-and-clear-or-delete-char'. The new
function may be bound to any key via the conditional binding value
'yas-maybe-skip-and-clear-field', instead of hardcoding the
'delete-char' fallback action. See Github #408, #892.
*** 'yas-lookup-snippet' now returns a struct
This allows 'yas-expand-snippet' to take looked up snippet's
environment into account. 'yas-expand-snippet' handles both
structured snippets, and plain text snippet bodies.
See Github #897.
** Fixed bugs
*** Avoid crashing due to Emacs Bug#30931
This prevents yasnippet's routines from triggering the bug, although
it is still possible to trigger it independently.
*** Don't enable undo when it's disabled
*** yas-also-auto-indent-first-line is once again respected
Yasnippet was behaving as if it was always t for single line snippets.
See Github #912.
*** Fixed handling of fixed indent with fields at beginning of line
See Github #906, #908.
*** Fixed incorrect snippets leaving "bad memory"
and possibly corrupting future expansions.
See Github #800.
*** 'global-whitespace-mode' now functions in new snippet buffers.
To fix this, the buffer name for new snippet buffers is now '+new
snippet+' instead of '*new snippet*'. See Github #842.
*** Nest snippet expansion may clear default field text
See Github #844.
*** Fixed undo list corruption snippet expand+indent.
See Github #869.
*** The '# --' marker in snippets now allows trailing whitespace.
See Github #862.
*** Fixed handling of nested simple $n fields
See Github #824, #894.
* 0.12.2 (Aug 28, 2017)
** The new option 'yas-also-auto-indent-empty-lines' allows restoring
the old indent behavior. See Github #850, #710, #685, #679.
** Keybinding triggered snippets once again deactivate the mark.
See Github #840.
* 0.12.1 (Jul 23, 2017)
This is a quick bugfix release.
** Compilation errors in yasnippet-tests.el and yasnippet-debug.el are fixed.
** A snippet-local setting of 'yas-indent-line' is now respected
during indentation triggered by auto-fill as well. See Github #838.
* 0.12.0 (Jul 17, 2017)
** Changes and New Features
*** Snippets can now expand in strings & comments by default again.
'yas-buffer-local-condition' is now a defcustom See Github #774.
*** 'yas-after-exit-snippet-hook' can now be bound in 'expand-env' of
snippets. See Github #28, #702, #779, #786.
*** Snippets under directories in 'yas-snippet-dirs' are now in
snippet-mode automatically.
*** Snippets can now be expanded in org source blocks, if
'org-src-tab-acts-natively' and 'org-src-fontify-natively' are set.
See Github #761.
*** 'yas-fallback-behavior' is now obsolete, 'yas-expand' is now bound
conditionally with an extended menu item, 'yas-maybe-expand'.
Therefore users wanting to bind 'yas-expand' to a different key, SPC
for example, should do
(define-key yas-minor-mode-map (kbd "SPC") yas-maybe-expand)
See Github #760, #808.
*** The documentation build output is now reproducible. The timestamp
now depends on the commit date, or the environment variable
SOURCE_DATE_EPOCH is that is set.
*** 'yas-indent-line' and 'expand-env' are now respected during mirror
updates. See Github #743.
*** New function 'yas-active-snippets'. Renamed from
'yas--snippets-at-point', which remains as an obsolete alias. See
Github #727.
*** New custom option 'yas-overlay-priority'. This is can be used to
give the snippet navigation keymaps higher priority than keymaps from
overlays created by other packages, like 'auto-complete'. See Github
#828.
** Fixed bugs
*** Snippets having ${0:soon-to-be-deleted} with no other fields now
correctly put the field 0 text in the active region after exiting.
See Github #653.
*** Fix undo of snippet insertion which also triggers indentation.
See Github #821.
*** Fixed a bug causing whitespace loss between mirrors.
*** Fixed several bugs causing problems when combining Yasnippet with
other modes and packages, like 'auto-fill-mode', 'c++-mode',
'rust-mode', and 'lentic'.
**** Fix another bug with auto-fill-mode.
See Github #784, #794.
**** Fix a bug in parsing of snippet fields for modes that use the
'syntax-table' text property, 'c++-mode' is one example of this. See
Github #815.
**** 'syntax-propertize-function' is now restored before indenting the
snippet. This improves compatibility with modes which rely on it for
indentation, like 'rust-mode'. See Github #782, #818.
**** Avoid trying to delete a snippet which is already deleted. This
prevents an error when using 'rust-mode's 'rust-format-buffer'
command.
**** Ensure inhibit-modification-hooks is nil while modifying buffer.
This fixes problems for packages relying on modification hooks, like
'lentic'. See Github #756, #712.
* 0.11.0 (Oct 26, 2016)
** Changes and New Features
*** Modifying buffer in backquoted expressions is deprecated!
Backquoted expressions should only return a string that will be
inserted. Snippets which modify the buffer as a side-effect will now
trigger a warning.
*** The verbosity levels for messages have been adjusted.
While the default verbosity level was increased by 1 (it was only
lower before due to a bug), several messages now only print at the
level 4, so the overall effect should be less messages by default.
*** Saving and loading snippets has been streamlined. Saving the
snippet to a file will now automatically load it. Additionally, the
buffer will be renamed from "*new snippet*" to whatever the snippet is
named. See also Github #718, #733, and #734.
*** `yas-escape-text' no longer signals an error when given nil.
*** `yas-describe-tables' is split into simpler commands.
**** `yas-describe-tables' takes a prefix arg to show non-active tables.
**** New command `yas-describe-tables-by-namehash' shows table by namehash.
*** Use the region contents as the snippet body of new snippets.
*** The dependency on `cl' is removed.
Yasnippet now only requires `cl-lib'.
** Fixed Bugs
*** Fix field navigation (tabbing) in the backwards direction.
See Github #722
*** Add support for deprecated yas/ symbols in `yas-define-menu'.
It was left out by accident. This support is conditional on
`yas-alias-to-yas/prefix-p', just like other obsolete yas/ bindings.
*** Fix overriding of snippet by a new snippet with same uuid.
See Github #714.
*** Fix handling of snippets with 2 mirros on the same line.
See Github #712.
* 0.10.0 (June 11th, 2016)
** Changes and New Features
*** Yasnippet now prints far fewer message by default.
See Github #682, #683.
*** `yas-wrap-around-region' can be set to a register.
The register's content will be used. This is like the old `cua'
option, but can be used with any register and doesn't require enabling
cua-mode.
*** Clearing of snippet fields is now decided by the command's effect.
The `delete-selection' property is no longer consulted. See Github #662.
*** Empty lines in snippet expansion are no longer indented.
See Github #679.
*** All lines from mirror output are now indented.
See Github #665.
*** New variable yas-alias-to-yas/prefix-p
See Github #696, #699.
*** New function yas-next-field-will-exit-p
See Github #561.
*** `snippet-mode' is now autoloaded.
** Fixed Bugs
*** Fix incompatibility with Emacs 25 and haskell-mode.
This should also help other modes with a non-nil syntax-propertize
function. See Github #687.
*** Text property changes no longer disable snippets.
This prevents cc-mode based modes from causing premature exit of
snippets. See Github #677.
*** Fields are now transformed correctly after `yas-next-field'.
See Github #381.
*** The $> construct is now escaped correctly, and documented.
See Github #640.
*** Avoid corruption of snippet content when loading from files.
See Github #707 and Emacs bug #23659.
*** `yas-wrap-around-region' now works for snippets with fields
farther down the buffer than $0. See Github #636.
*** The active region is deleted when using `yas-expand'.
This makes it consistent with `yas-insert-snippet'. See Github #523.
*** Fix mirror+autofill interaction.
See Github #643 and http://emacs.stackexchange.com/q/19206/5296.
*** Snippet insertion no longer adds irrelevant strings to kill ring.
See Github #675.
* 0.9.1 (April 3rd, 2016)
** Changes and New Features ** Changes and New Features
@ -411,7 +53,7 @@ good enough. See issue #497.
*** Documentation rewritten in org-mode and updated. *** Documentation rewritten in org-mode and updated.
A tremendous effort by Noam Postavsky. Hopefully easier to maintain A tremendous effort by Noam Postavsky. Hopefully easier to maintain
and navigate. Available at <http://joaotavora.github.io/yasnippet>. and navigate. Available at <http://capitaomorte.github.io/yasnippet>.
*** Snippets are now maintained in their own repo. *** Snippets are now maintained in their own repo.
Snippets live in Andrea Crotti's Snippets live in Andrea Crotti's
@ -419,7 +61,7 @@ Snippets live in Andrea Crotti's
for more details. for more details.
*** Textmate snippet importer moved to separate `yasmate' repo. *** Textmate snippet importer moved to separate `yasmate' repo.
URL is <https://github.com/joaotavora/yasmate>. See README.md for URL is <https://github.com/capitaomorte/yasmate>. See README.md for
more details. more details.
*** `yas-snippet-dirs' now allows symbols as aliases to directories. *** `yas-snippet-dirs' now allows symbols as aliases to directories.

View File

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/joaotavora/yasnippet.png)](https://travis-ci.org/joaotavora/yasnippet) [![Build Status](https://travis-ci.org/capitaomorte/yasnippet.png)](https://travis-ci.org/capitaomorte/yasnippet)
# Intro # Intro
@ -15,12 +15,12 @@ YASnippet. Watch [a demo on YouTube][youtube-demo].
# Installation # Installation
## Manual install from Git ## Install the most recent version
Clone this repository somewhere Clone this repository somewhere
$ cd ~/.emacs.d/plugins $ cd ~/.emacs.d/plugins
$ git clone --recursive https://github.com/joaotavora/yasnippet $ git clone --recursive https://github.com/capitaomorte/yasnippet
Add the following in your `.emacs` file: Add the following in your `.emacs` file:
@ -33,16 +33,12 @@ Add your own snippets to `~/.emacs.d/snippets` by placing files there or invokin
## Install with `package-install` ## Install with `package-install`
In a recent emacs `M-x list-packages` is the recommended way to list In a recent emacs `M-x list-packages` is the recommended way to list and install packages.
and install packages. [MELPA][melpa] keeps a very recent snapshot of YASnippet, see http://melpa.org/#installing.
It's available from [GNU ELPA][gnuelpa].
If you need a very recent snapshot, you can get it from
[GNU-devel ELPA][gnudevel] as well as [MELPA][melpa]
(see http://melpa.org/#installing).
## Install with el-get ## Install with el-get
El-get is another nice way to get the most recent version, too. See El-get is a nice way to get the most recent version, too. See
https://github.com/dimitri/el-get for instructions. https://github.com/dimitri/el-get for instructions.
## Use `yas-minor-mode` on a per-buffer basis ## Use `yas-minor-mode` on a per-buffer basis
@ -59,22 +55,33 @@ where you want YASnippet enabled.
<a name="import"></a> <a name="import"></a>
YASnippet no longer bundles snippets directly, but it's very easy to Yasnippet no longer bundles snippets directly, but it's very easy to
get some! get some!
1. [yasnippet-snippets] - a snippet collection package maintained by If you git-cloned yasnippet with the `--recursive` option you'll also
download "git submodules" and find two subdirs under the main tree.
1. `snippets/`
Points to [yasnippet-snippets] the snippet collection of
[AndreaCrotti](https://github.com/AndreaCrotti). [AndreaCrotti](https://github.com/AndreaCrotti).
It can be installed with `M-x package-install RET The default configuraiton already points to this dir, so to use
yasnippet-snippets` if you have added MELPA to your package them, just make sure the submodule really was downloaded
sources. (i.e. there are some files under `snippets/`)
2. [yasmate] a tool which is dedicated to converting textmate bundles 2. `yasmate/`
into yasnippet snippets.
Points to a github repo of the [yasmate] tool, which is dedicated
to converting textmate bundles into yasnippet snippets.
To use these snippets you have to run the tool first, so To use these snippets you have to run the tool first, so
[see its doc][yasmate]), and then point the `yas-snippet-dirs` [see its doc][yasmate]), and then point the `yas-snippet-dirs`
variable to the `.../yasmate/snippets` subdir. variable to the `.../yasmate/snippets` subdir.
If you have a working ruby environment, you can probably get lucky
directly with `rake convert-bundles`.
3. [textmate-to-yas.el] 3. [textmate-to-yas.el]
This is another textmate bundle converting tool using Elisp This is another textmate bundle converting tool using Elisp
@ -89,23 +96,16 @@ should be added like this to `yas-snippet-dirs`:
'("~/.emacs.d/snippets" ;; personal snippets '("~/.emacs.d/snippets" ;; personal snippets
"/path/to/some/collection/" ;; foo-mode and bar-mode snippet collection "/path/to/some/collection/" ;; foo-mode and bar-mode snippet collection
"/path/to/yasnippet/yasmate/snippets" ;; the yasmate collection "/path/to/yasnippet/yasmate/snippets" ;; the yasmate collection
"/path/to/yasnippet/snippets" ;; the default collection
)) ))
(yas-global-mode 1) ;; or M-x yas-reload-all if you've started YASnippet already. (yas-global-mode 1) ;; or M-x yas-reload-all if you've started YASnippet already.
# Manual, issues etc # Manual, issues etc
There's comprehensive [documentation][docs] on using and customising Please refer to the comprehensive [documentation][docs] for full
YASnippet. customisation and support. If you find a bug in the code or in the
documentation, please report it on [the GitHub issue tracker][issues].
There's a [list of support issues][support-issues], with solutions to
common problems and practical snippet examples.
The [Github issue tracker][issues] is where most YASnippet-related
discussion happens. Nevertheless, since YASnippet is a part of Emacs,
you may alternatively report bugs to Emacs via `M-x report-emacs-bug` or
sending an email to `bug-gnu-emacs@gnu.org`, putting "yasnippet"
somewhere in the subject.
## Important note regarding bug reporting ## Important note regarding bug reporting
@ -117,14 +117,14 @@ a way to reproduce the problem exactly like it happened to you.
To do this, we need to rule out interference from external factors To do this, we need to rule out interference from external factors
like other Emacs extensions or your own customisations. like other Emacs extensions or your own customisations.
Here's an example report that "sandboxes" an Emacs session just for Here's an example report that "sandboxes" an Emacs session just for
reproducing a bug. reproducing a bug.
``` ```
$ emacs --version $ emacs --version
Emacs 24.3 Emacs 24.3
$ cd /tmp/ $ cd /tmp/
$ git clone https://github.com/joaotavora/yasnippet.git yasnippet-bug $ git clone https://github.com/capitaomorte/yasnippet.git yasnippet-bug
$ cd yasnippet-bug $ cd yasnippet-bug
$ git log -1 --oneline $ git log -1 --oneline
6053db0 Closes #527: Unbreak case where yas-fallback-behaviour is a list 6053db0 Closes #527: Unbreak case where yas-fallback-behaviour is a list
@ -138,11 +138,11 @@ OR
When loading yasnippet I see "Error: failed to frobnicate"! When loading yasnippet I see "Error: failed to frobnicate"!
``` ```
Using `emacs -Q` or temporarily moving your `.emacs` init file to the side Using `emacs -Q` or temporarily moving your `.emacs` init file to the side
is another way to achieve good reproducibility. is another way to achieve good reproducibility.
Here's a Here's a
[another example](https://github.com/joaotavora/yasnippet/issues/318) [another example](https://github.com/capitaomorte/yasnippet/issues/318)
of a bug report. It has everything needed for a successful analysis of a bug report. It has everything needed for a successful analysis
and speedy resolution. and speedy resolution.
@ -153,16 +153,19 @@ do `git log -1` in the dir).
Any more info is welcome, but don't just paste a backtrace or an error Any more info is welcome, but don't just paste a backtrace or an error
message string you got, unless we ask for it. message string you got, unless we ask for it.
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 it's better to create a
github issue clearly marking your intent (user support/bug/feature
request).
Finally, thank you very much for using YASnippet! Finally, thank you very much for using YASnippet!
[docs]: http://joaotavora.github.io/yasnippet/ [docs]: http://capitaomorte.github.com/yasnippet/
[issues]: https://github.com/joaotavora/yasnippet/issues [issues]: https://github.com/capitaomorte/yasnippet/issues
[support-issues]: https://github.com/joaotavora/yasnippet/issues?q=label%3Asupport
[googlecode tracker]: http://code.google.com/p/yasnippet/issues/list [googlecode tracker]: http://code.google.com/p/yasnippet/issues/list
[forum]: http://groups.google.com/group/smart-snippet [forum]: http://groups.google.com/group/smart-snippet
[melpa]: http://melpa.milkbox.net/ [melpa]: http://melpa.milkbox.net/
[gnuelpa]: http://elpa.gnu.org/packages/yasnippet.html [yasmate]: http://github.com/capitaomorte/yasmate
[gnudevel]: http://elpa.gnu.org/devel/yasnippet.html
[yasmate]: http://github.com/joaotavora/yasmate
[textmate-to-yas.el]: https://github.com/mattfidler/textmate-to-yas.el [textmate-to-yas.el]: https://github.com/mattfidler/textmate-to-yas.el
[yasnippet-snippets]: http://github.com/AndreaCrotti/yasnippet-snippets [yasnippet-snippets]: http://github.com/AndreaCrotti/yasnippet-snippets

107
Rakefile Normal file
View File

@ -0,0 +1,107 @@
# -*- Ruby -*-
require 'fileutils'
$EMACS = ENV["EMACS"]
if not $EMACS or $EMACS == 't'
$EMACS = "emacs"
end
def find_version
File.read("yasnippet.el", :encoding => "UTF-8") =~ /;; Package-version: *([0-9.]+?) *$/
$version = $1
end
find_version
FileUtils.mkdir_p('pkg')
desc "run tests in batch mode"
task :tests do
sh "#{$EMACS} -Q -L . -l yasnippet-tests.el" +
" --batch -f ert-run-tests-batch-and-exit"
end
desc "create a release package"
task :package do
release_dir = "pkg/yasnippet-#{$version}"
FileUtils.mkdir_p(release_dir)
files = ['snippets', 'yasnippet.el']
FileUtils.cp_r files, release_dir
File.open(File.join(release_dir,'yasnippet-pkg.el'), 'w') do |file|
file.puts <<END
(define-package "yasnippet"
"#{$version}"
"A template system for Emacs")
END
end
sh "git clean -f snippets"
FileUtils.cd 'pkg' do
sh "tar cf yasnippet-#{$version}.tar yasnippet-#{$version}"
end
end
desc "create a release package and upload it to google code"
task :release => [:package, 'doc:archive'] do
raise "Not implemented for github yet!"
end
desc "Generate document"
task :doc do
sh "#{$EMACS} -Q -L . --batch -l doc/yas-doc-helper.el" +
" -f yas--generate-html-batch"
end
namespace :doc do
task :archive do
release_dir = "pkg/yasnippet-#{$version}"
FileUtils.mkdir_p(release_dir)
sh "tar cjf pkg/yasnippet-doc-#{$version}.tar.bz2 " +
"--exclude=doc/.svn --exclude=doc/images/.svn doc/*.html doc/images"
end
task :upload do
if File.exists? 'doc/gh-pages'
Dir.chdir 'doc/gh-pages' do
sh "git checkout gh-pages"
end
Dir.glob("doc/*.{html,css}").each do |file|
FileUtils.cp file, 'doc/gh-pages'
end
Dir.glob("doc/images/*").each do |file|
FileUtils.cp file, 'doc/gh-pages/images'
end
Dir.glob("doc/stylesheets/*.css").each do |file|
FileUtils.cp file, 'doc/gh-pages/stylesheets'
end
curRev = `git rev-parse --verify HEAD`.chomp()
expRev = IO.read('doc/html-revision').chomp()
if curRev != expRev
raise ("The HTML rev: #{expRev},\n" +
"current rev: #{curRev}!\n")
end
if !system "git diff-index --quiet HEAD"
system "git status --untracked-files=no"
raise "You have uncommitted changes!"
end
Dir.chdir 'doc/gh-pages' do
sh "git commit -a -m 'Automatic documentation update.\n\n" +
"From #{curRev.chomp()}'"
sh "git push"
end
end
end
end
desc "Compile yasnippet.el into yasnippet.elc"
rule '.elc' => '.el' do |t|
sh "#{$EMACS} --batch -L . --eval \"(byte-compile-file \\\"#{t.source}\\\")\""
end
task :compile => FileList["yasnippet.el"].ext('elc')
task :default => :doc
desc "use yasmate to convert textmate bundles"
task :convert_bundles do
cd "yasmate"
sh "rake convert_bundles"
end

View File

@ -2,67 +2,138 @@
#+TITLE: Frequently Asked Questions #+TITLE: Frequently Asked Questions
- *Note*: In addition to the questions and answers presented here,
you might also with to visit the list of [[https://github.com/joaotavora/yasnippet/issues?q=label%3Asupport][solved support issues]] in
the Github issue tracker. It might be more up-to-date than this
list.
* Why are my snippet abbrev keys triggering when I don't want them too?
Expansion of abbrev keys is controlled by [[sym:yas-key-syntaxes][=yas-key-syntaxes=]]. Try
removing entries which correspond to the abbrev key character syntax.
For example, if you have a snippet with abbrev key "bar", that you
don't want to trigger when point follows the text =foo_bar=, remove
the ="w"= entry (since "bar" has only word syntax characters).
* Why aren't my snippet abbrev keys triggering when I want them too?
See previous question, but in reverse.
* Why is there an extra newline? * Why is there an extra newline?
If there is a newline at the end of a snippet definition file, If you have a newline at the end of the snippet definition file, then
YASnippet will add a newline when expanding that snippet. When editing YASnippet will add a newline when you expanding a snippet. Please don't
or saving a snippet file, please be careful not to accidentally add a add a newline at the end if you don't want it when you saving the
terminal newline. snippet file.
Note that some editors will automatically add a newline for you. In Note some editors will automatically add a newline for you. In Emacs, if
Emacs, if you set =require-final-newline= to =t=, it will add the you set =require-final-newline= to =t=, it will add the final newline
final newline automatically. for you automatically.
* Why doesn't TAB expand a snippet?
First check the mode line to see if there's =yas=. If not, then try
=M-x yas-minor-mode= to manually turn on the minor mode and try to
expand the snippet again. If it works, then, you can add the following
code to your =.emacs= /before/ loading YASnippet:
#+BEGIN_SRC emacs-lisp
(add-hook 'the-major-mode-hook 'yas-minor-mode-on)
#+END_SRC
where =the-major-mode= is the major mode in which [[sym:yas-minor-mode][=yas-minor-mode=]] isn't
enabled by default.
From YASnippet 0.6 you can also use the command =M-x yas-global-mode= to
turn on YASnippet automatically for /all/ major modes.
If [[sym:yas-minor-mode][=yas-minor-mode=]] is on but the snippet still not expanded. Then try
to see what command is bound to the =TAB= key: press =C-h k= and then
press =TAB=. Emacs will show you the result.
You'll see a buffer prompted by Emacs saying that
=TAB runs the command ...=. Alternatively, you might see
=<tab> runs the command ...=, note the difference between =TAB= and
=<tab>= where the latter has priority. If you see =<tab>= bound to a
command other than [[sym:yas-expand][=yas-expand=]], (e.g. in =org-mode=) you can try the
following code to work around:
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook
(let ((original-command (lookup-key org-mode-map [tab])))
`(lambda ()
(setq yas-fallback-behavior
'(apply ,original-command))
(local-set-key [tab] 'yas-expand))))
#+END_SRC
replace =org-mode-hook= and =org-mode-map= with the major mode hook you
are dealing with (Use =C-h m= to see what major mode you are in).
As an alternative, you can also try
#+BEGIN_SRC emacs-lisp
(defun yas-advise-indent-function (function-symbol)
(eval `(defadvice ,function-symbol (around yas-try-expand-first activate)
,(format
"Try to expand a snippet before point, then call `%s' as usual"
function-symbol)
(let ((yas-fallback-behavior nil))
(unless (and (interactive-p)
(yas-expand))
ad-do-it)))))
(yas-advise-indent-function 'ruby-indent-line)
#+END_SRC
To /advise/ the modes indentation function bound to TAB, (in this case
=ruby-indent-line=) to first try to run [[sym:yas-expand][=yas-expand=]].
If the output of =C-h k RET <tab>= tells you that =<tab>= is indeed
bound to [[sym:yas-expand][=yas-expand=]] but YASnippet still doesn't work, check your
configuration and you may also ask for help on the [[http://groups.google.com/group/smart-snippet][discussion group]].
See this particular [[http://code.google.com/p/yasnippet/issues/detail?id=93&can=1][thread]] for quite some solutions and alternatives.
Don't forget to attach the information on what command is bound to TAB
as well as the mode information (Can be obtained by =C-h m=).
* Why doesn't TAB navigation work with flyspell * Why doesn't TAB navigation work with flyspell
This is [[https://debbugs.gnu.org/26672][Emacs Bug#26672]], so you should upgrade to version 25.3 or A workaround is to inhibit flyspell overlays while the snippet is
better. Otherwise, a workaround is to inhibit flyspell overlays while active:
the snippet is active:
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(add-hook 'flyspell-incorrect-hook (add-hook 'flyspell-incorrect-hook
#'(lambda (&rest _) #'(lambda (dummy1 dummy2 dymmy3)
(and yas-active-field-overlay (and yas-active-field-overlay
(overlay-buffer yas-active-field-overlay)))) (overlay-buffer yas-active-field-overlay))))
#+END_SRC #+END_SRC
* How do I use alternative keys, i.e. not TAB? This is apparently related to overlay priorities. For some reason, the
=keymap= property of flyspell's overlays always takes priority over the
same property in YASnippet's overlays, even if one sets the latter's
=priority= property to something big. If you know emacs-lisp and can
solve this problem, drop a line in the
[[http://groups.google.com/group/smart-snippet][discussion group]].
Edit the keymaps [[sym:yas-minor-mode-map][=yas-minor-mode-map=]] and [[sym:yas-keymap][=yas-keymap=]] as you would * How to I use alternative keys, i.e. not TAB?
any other keymap, but use [[sym:yas-filtered-definition][=yas-filtered-definition=]] on the definition
if you want to respect [[sym:yas-keymap-disable-hook][=yas-keymap-disable-hook=]]: Edit the keymaps [[sym:yas-minor-mode-map][=yas-minor-mode-map=]] and
[[sym:yas-keymap][=yas-keymap=]] as you would any other keymap:
#+begin_src emacs-lisp :exports code #+begin_src emacs-lisp :exports code
(define-key yas-minor-mode-map (kbd "<tab>") nil) (define-key yas-minor-mode-map (kbd "<tab>") nil)
(define-key yas-minor-mode-map (kbd "TAB") nil) (define-key yas-minor-mode-map (kbd "TAB") nil)
(define-key yas-minor-mode-map (kbd "<the new key>") yas-maybe-expand) (define-key yas-minor-mode-map (kbd "<the new key>") 'yas-expand)
;;keys for navigation ;;keys for navigation
(define-key yas-keymap [(tab)] nil) (define-key yas-keymap [(tab)] nil)
(define-key yas-keymap (kbd "TAB") nil) (define-key yas-keymap (kbd "TAB") nil)
(define-key yas-keymap [(shift tab)] nil) (define-key yas-keymap [(shift tab)] nil)
(define-key yas-keymap [backtab] nil) (define-key yas-keymap [backtab] nil)
(define-key yas-keymap (kbd "<new-next-field-key>") (define-key yas-keymap (kbd "<new-next-field-key>") 'yas-next-field-or-maybe-expand)
(yas-filtered-definition 'yas-next-field-or-maybe-expand)) (define-key yas-keymap (kbd "<new-prev-field-key>") 'yas-prev)
(define-key yas-keymap (kbd "<new-prev-field-key>")
(yas-filtered-definition 'yas-prev-field))
#+end_src #+end_src
* How do I turn off the minor mode where in some buffers?
The best way, since version 0.6.1c, is to set the default value of the
variable [[sym:yas-dont-activate][=yas-dont-activate=]] to a lambda function like so:
#+BEGIN_SRC emacs-lisp
(set-default 'yas-dont-activate
#'(lambda ()
(and yas-root-directory
(null (yas-get-snippet-tables)))))
#+END_SRC
This is also the default value starting for that version. It skips the
minor mode in buffers where it is not applicable (no snippet tables),
but only once you have setup your yas-root-directory.
* How do I define an abbrev key containing characters not supported by the filesystem? * How do I define an abbrev key containing characters not supported by the filesystem?
- *Note*: This question applies if you're still defining snippets - *Note*: This question applies if you're still defining snippets

View File

@ -3,7 +3,7 @@
The YASnippet documentation has been split into separate parts: The YASnippet documentation has been split into separate parts:
0. [[https://github.com/joaotavora/yasnippet/blob/master/README.mdown][README]] 0. [[https://github.com/capitaomorte/yasnippet/blob/master/README.mdown][README]]
Contains an introduction, installation instructions and other important Contains an introduction, installation instructions and other important
notes. notes.

View File

@ -1,10 +1,10 @@
<nav> <nav>
<ul class="center"> <ul class="center">
<li> <a href="index.html">Overview</a> <li> <a href="index.html">Overview</a>
<li> <a href="https://github.com/joaotavora/yasnippet/blob/master/README.mdown"> <li> <a href="https://github.com/capitaomorte/yasnippet/blob/master/README.mdown">
Intro and Tutorial</a> Intro and Tutorial</a>
<li class="center border">Snippet <li class="center">Snippet
<ul class="nopad"> <ul>
<li> <a href="snippet-organization.html">Organization</a> <li> <a href="snippet-organization.html">Organization</a>
<li> <a href="snippet-expansion.html">Expansion</a> <li> <a href="snippet-expansion.html">Expansion</a>
<li> <a href="snippet-development.html">Development</a> <li> <a href="snippet-development.html">Development</a>

View File

@ -4,7 +4,7 @@
#+LINK: sym file:snippet-reference.org::#%s #+LINK: sym file:snippet-reference.org::#%s
#+OPTIONS: author:nil num:nil timestamp:nil #+OPTIONS: author:nil num:nil
#+AUTHOR: #+AUTHOR:
# org < 8.0 use +STYLE, after use +HTML_HEAD # org < 8.0 use +STYLE, after use +HTML_HEAD
#+STYLE: <link rel="stylesheet" type="text/css" href="stylesheets/manual.css" /> #+STYLE: <link rel="stylesheet" type="text/css" href="stylesheets/manual.css" />

View File

@ -8,48 +8,52 @@
There are some ways you can quickly find a snippet file or create a new one: There are some ways you can quickly find a snippet file or create a new one:
- =M-x yas-new-snippet=, key binding: =C-c & C-n= - =M-x yas-new-snippet=
Creates a new buffer with a template for making a new snippet. The Creates a new buffer with a template for making a new snippet.
buffer is in =snippet-mode= (see [[snippet-mode][below]]). When you are done editing The buffer is in =snippet-mode= (see below). When you are done
the new snippet, use [[yas-load-snippet-buffer-and-close][=C-c C-c=]] to save it. editing the new snippet, use =C-c C-c= to save it. This will
prompt for a directory two steps: first, the snippet table
(with a default based on the major mode you started in), and then
then snippet collection directory (defaults to the first directory
in =yas-snippet-dirs=. (See [[file:snippet-organization.org][Organizing Snippets]]
for more detail on how snippets are organized.)
- =M-x yas-visit-snippet-file=, key binding: =C-c & C-v= - =M-x yas-find-snippets=
Lets you find the snippet file in the directory the snippet was
loaded from (if it exists) like =find-file-other-window=. The
directory searching logic is similar to =M-x yas-new-snippet=.
- =M-x yas-visit-snippet-file=
Prompts you for possible snippet expansions like Prompts you for possible snippet expansions like
[[sym:yas-insert-snippet][=yas-insert-snippet=]], but instead of expanding it, takes you directly [[sym:yas-insert-snippet][=yas-insert-snippet=]], but instead of expanding it, takes you directly
to the snippet definition's file, if it exists. to the snippet definition's file, if it exists.
Once you find this file it will be set to =snippet-mode= (see [[snippet-mode][ahead]]) Once you find this file it will be set to =snippet-mode= (see ahead) and
and you can start editing your snippet. you can start editing your snippet.
** Using the =snippet-mode= major mode <<snippet-mode>> ** Using the =snippet-mode= major mode
There is a major mode =snippet-mode= to edit snippets. You can set the There is a major mode =snippet-mode= to edit snippets. You can set the
buffer to this mode with =M-x snippet-mode=. It provides reasonably buffer to this mode with =M-x snippet-mode=. It provides reasonably
useful syntax highlighting. useful syntax highlighting.
Three commands are defined in this mode: Two commands are defined in this mode:
- =M-x yas-load-snippet-buffer=, key binding: =C-c C-l= - =M-x yas-load-snippet-buffer=
Prompts for a snippet table (with a default based on snippet's When editing a snippet, this loads the snippet into the correct
major mode) and loads the snippet currently being edited. mode and menu. Bound to =C-c C-c= by default while in
=snippet-mode=.
- =M-x yas-load-snippet-buffer-and-close=, key binding: =C-c C-c= - =M-x yas-tryout-snippet=
<<yas-load-snippet-buffer-and-close>>
Like =yas-load-snippet-buffer=, but also saves the snippet and When editing a snippet, this opens a new empty buffer, sets it to
calls =quit-window=. The destination is decided based on the the appropriate major mode and inserts the snippet there, so you
chosen snippet table and snippet collection directly (defaulting to can see what it looks like. This is bound to =C-c C-t= while in
the first directory in =yas-snippet-dirs= (see [[file:snippet-organization.org][Organizing Snippets]] =snippet-mode=.
for more detail on how snippets are organized).
- =M-x yas-tryout-snippet=, key binding: =C-c C-t=
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.
There are also /snippets for writing snippets/: =vars=, =$f= and =$m= There are also /snippets for writing snippets/: =vars=, =$f= and =$m=
:-). :-).
@ -62,7 +66,7 @@ expanded.
Optionally, if the file contains a line of =# --=, the lines above it Optionally, if the file contains a line of =# --=, the lines above it
count as comments, some of which can be /directives/ (or meta data). count as comments, some of which can be /directives/ (or meta data).
Snippet directives look like =# property: value= and tweak certain Snippet directives look like =# property: value= and tweak certain
snippet properties described below. If no =# --= is found, the whole snippets properties described below. If no =# --= is found, the whole
file is considered the snippet template. file is considered the snippet template.
Here's a typical example: Here's a typical example:
@ -80,7 +84,7 @@ Here's a list of currently supported directives:
This is the probably the most important directive, it's the This is the probably the most important directive, it's the
abbreviation you type to expand a snippet just before hitting the key abbreviation you type to expand a snippet just before hitting the key
that runs [[sym:yas-expand][=yas-expand=]]. If you don't specify this, that runs [[sym:yas-expand][=yas-expand=]]. If you don't specify this
the snippet will not be expandable through the trigger mechanism. the snippet will not be expandable through the trigger mechanism.
** =# name:= snippet name ** =# name:= snippet name
@ -89,12 +93,12 @@ This is a one-line description of the snippet. It will be displayed in
the menu. It's a good idea to select a descriptive name for a snippet -- the menu. It's a good idea to select a descriptive name for a snippet --
especially distinguishable among similar snippets. especially distinguishable among similar snippets.
If you omit this name, it will default to the file name the snippet If you omit this name it will default to the file name the snippet was
was loaded from. loaded from.
** =# condition:= snippet condition ** =# condition:= snippet condition
This is a piece of Emacs Lisp code. If a snippet has a condition, then This is a piece of Emacs-lisp code. If a snippet has a condition, then
it will only be expanded when the condition code evaluate to some it will only be expanded when the condition code evaluate to some
non-nil value. non-nil value.
@ -104,7 +108,7 @@ See also [[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]] in
** =# group:= snippet menu grouping ** =# group:= snippet menu grouping
When expanding/visiting snippets from the menu-bar menu, snippets for a When expanding/visiting snippets from the menu-bar menu, snippets for a
given mode can be grouped into sub-menus. This is useful if one has too given mode can be grouped into sub-menus . This is useful if one has too
many snippets for a mode which will make the menu too long. many snippets for a mode which will make the menu too long.
The =# group:= property only affect menu construction (See The =# group:= property only affect menu construction (See
@ -113,14 +117,14 @@ achieved by grouping snippets into sub-directories and using the
=.yas-make-groups= special file (for this see =.yas-make-groups= special file (for this see
[[./snippet-organization.org][Organizing Snippets]] [[./snippet-organization.org][Organizing Snippets]]
Refer to the bundled snippets for =ruby-mode= for examples of the Refer to the bundled snippets for =ruby-mode= for examples on the
=# group:= directive. Group can also be nested, e.g. =# group:= directive. Group can also be nested, e.g.
=control structure.loops= indicates that the snippet is under the =loops= =control structure.loops= tells that the snippet is under the =loops=
group which is under the =control structure= group. group which is under the =control structure= group.
** =# expand-env:= expand environment ** =# expand-env:= expand environment
This is another piece of Emacs Lisp code in the form of a =let= /varlist This is another piece of Emacs-lisp code in the form of a =let= /varlist
form/, i.e. a list of lists assigning values to variables. It can be form/, i.e. a list of lists assigning values to variables. It can be
used to override variable values while the snippet is being expanded. used to override variable values while the snippet is being expanded.
@ -154,9 +158,9 @@ You can use this directive to expand a snippet directly from a normal
Emacs keybinding. The keybinding will be registered in the Emacs keymap Emacs keybinding. The keybinding will be registered in the Emacs keymap
named after the major mode the snippet is active for. named after the major mode the snippet is active for.
Additionally a variable [[sym:yas-prefix][=yas-prefix=]] is set to the prefix argument Additionally a variable [[sym:yas-prefix][=yas-prefix=]] is set to to the prefix argument
you normally use for a command. This allows for small variations on the you normally use for a command. This allows for small variations on the
same snippet, for example in this =html-mode= snippet. same snippet, for example in this "html-mode" snippet.
#+BEGIN_SRC snippet #+BEGIN_SRC snippet
# name: <p>...</p> # name: <p>...</p>
@ -172,7 +176,7 @@ will expand the paragraph tag without newlines.
** =# type:= =snippet= or =command= ** =# type:= =snippet= or =command=
If the =type= directive is set to =command=, the body of the snippet If the =type= directive is set to =command=, the body of the snippet
is interpreted as Lisp code to be evaluated when the snippet is is interpreted as lisp code to be evaluated when the snippet is
triggered. triggered.
If it's =snippet= (the default when there is no =type= directive), the If it's =snippet= (the default when there is no =type= directive), the
@ -190,7 +194,7 @@ previous snippet.
This is optional and has no effect whatsoever on snippet functionality, This is optional and has no effect whatsoever on snippet functionality,
but it looks nice. but it looks nice.
* Template Syntax * <<Template syntax>>
The syntax of the snippet template is simple but powerful, very similar The syntax of the snippet template is simple but powerful, very similar
to TextMate's. to TextMate's.
@ -202,14 +206,14 @@ usually interpreted as plain text, except =$= and =`=. You need to
use =\= to escape them: =\$= and =\`=. The =\= itself may also needed to be use =\= to escape them: =\$= and =\`=. The =\= itself may also needed to be
escaped as =\\= sometimes. escaped as =\\= sometimes.
** Embedded Emacs Lisp code ** Embedded Emacs-lisp code
Emacs Lisp code can be embedded inside the template, written inside Emacs-Lisp code can be embedded inside the template, written inside
back-quotes (=`=). The Lisp forms are evaluated when the snippet is back-quotes (=`=). The lisp forms are evaluated when the snippet is
being expanded. The evaluation is done in the same buffer as the being expanded. The evaluation is done in the same buffer as the
snippet being expanded. snippet being expanded.
Here's an example for =c-mode= to calculate the header file guard Here's an example for c-mode` to calculate the header file guard
dynamically: dynamically:
#+BEGIN_SRC snippet #+BEGIN_SRC snippet
@ -221,8 +225,8 @@ dynamically:
#endif /* $1 */ #endif /* $1 */
#+END_SRC #+END_SRC
From version 0.6, snippet expansions are run with some special From version 0.6, snippets expansions are run with some special
Emacs Lisp variables bound. One of these is [[sym:yas-selected-text][=yas-selected-text=]]. You can Emacs-lisp variables bound. One of this is [[sym:yas-selected-text][=yas-selected-text=]]. You can
therefore define a snippet like: therefore define a snippet like:
#+BEGIN_SRC snippet #+BEGIN_SRC snippet
@ -235,27 +239,6 @@ to "wrap" the selected region inside your recently inserted snippet.
Alternatively, you can also customize the variable Alternatively, you can also customize the variable
[[sym:yas-wrap-around-region][=yas-wrap-around-region=]] to =t= which will do this automatically. [[sym:yas-wrap-around-region][=yas-wrap-around-region=]] to =t= which will do this automatically.
*** Note: backquote expressions should not modify the buffer
Please note that the Lisp forms in backquotes should *not* modify the
buffer, doing so will trigger a warning. For example, instead of
doing
#+BEGIN_SRC snippet
Timestamp: `(insert (current-time-string))`
#+END_SRC
do this:
#+BEGIN_SRC snippet
Timestamp: `(current-time-string)`
#+END_SRC
The warning may be suppressed with the following code in your init file:
#+BEGIN_SRC emacs-lisp
(add-to-list 'warning-suppress-types '(yasnippet backquote-change))
#+END_SRC
** Tab stop fields ** Tab stop fields
Tab stops are fields that you can navigate back and forth by =TAB= and Tab stops are fields that you can navigate back and forth by =TAB= and
@ -277,16 +260,16 @@ like this:
${N:default value} ${N:default value}
#+END_SRC #+END_SRC
They act as the default value for a tab stop. But when you first They acts as the default value for a tab stop. But when you firstly
type at a tab stop, the default value will be replaced by your typing. type at a tab stop, the default value will be replaced by your typing.
The number can be omitted if you don't want to create [[mirrors-fields][mirrors]] or The number can be omitted if you don't want to create [[mirrors]] or
[[mirror-transformations][transformations]] for this field. [[transformations]] for this field.
** Mirrors <<mirrors-fields>> ** <<Mirrors>>
We refer to tab stops with placeholders as a /field/. A field can We refer the tab stops with placeholders as a /field/. A field can have
have mirrors. *All* mirrors get updated whenever you update any field mirrors. Its mirrors will get updated when you change the text of a
text. Here's an example: field. Here's an example:
#+BEGIN_SRC snippet #+BEGIN_SRC snippet
\begin{${1:enumerate}} \begin{${1:enumerate}}
@ -299,15 +282,15 @@ also be inserted at =\end{$1}=. The best explanation is to see the
screencast([[http://www.youtube.com/watch?v=vOj7btx3ATg][YouTube]] or [[http://yasnippet.googlecode.com/files/yasnippet.avi][avi video]]). screencast([[http://www.youtube.com/watch?v=vOj7btx3ATg][YouTube]] or [[http://yasnippet.googlecode.com/files/yasnippet.avi][avi video]]).
The tab stops with the same number to the field act as its mirrors. If The tab stops with the same number to the field act as its mirrors. If
none of the tab stops have an initial value, the first one is selected as none of the tab stops has an initial value, the first one is selected as
the field and the others are its mirrors. the field and others mirrors.
** Mirrors with transformations <<mirror-transformations>> ** Mirrors with <<transformations>>
If the value of an =${n:=-construct starts with and contains =$(=, If the value of an =${n:=-construct starts with and contains =$(=,
then it is interpreted as a mirror for field =n= with a then it is interpreted as a mirror for field =n= with a
transformation. The mirror's text content is calculated according to transformation. The mirror's text content is calculated according to
this transformation, which is Emacs Lisp code that gets evaluated in this transformation, which is Emacs-lisp code that gets evaluated in
an environment where the variable [[sym:yas-text][=yas-text=]] is bound to the text an environment where the variable [[sym:yas-text][=yas-text=]] is bound to the text
content (string) contained in the field =n=. Here's an example for content (string) contained in the field =n=. Here's an example for
Objective-C: Objective-C:
@ -362,26 +345,12 @@ is not. Here's an snippet for rst title:
$0 $0
#+END_SRC #+END_SRC
Note that a mirror with a transform is not restricted to the text of
the field it is mirroring. By making use of [[sym:yas-field-value][=yas-field-value=]], a
mirror can look at any of the snippet's field (as mentioned above, all
mirrors are updated when any field is updated). Here is an example
which shows a "live" result of calling format:
#+BEGIN_SRC snippet
(format "${1:formatted %s}" "${2:value}")
=> "${1:$(ignore-errors (format (yas-field-value 1) (yas-field-value 2)))}"
#+END_SRC
To keep the example simple, it uses =ignore-errors= to suppress errors
due to incomplete format codes.
** Fields with transformations ** Fields with transformations
From version 0.6 on, you can also have Lisp transformation inside From version 0.6 on, you can also have lisp transformation inside
fields. These work mostly like mirror transformations. However, they fields. These work mostly mirror transformations but are evaluated when
are evaluated when you first enter the field, after each change you you first enter the field, after each change you make to the field and
make to the field and also just before you exit the field. also just before you exit the field.
The syntax is also a tiny bit different, so that the parser can The syntax is also a tiny bit different, so that the parser can
distinguish between fields and mirrors. In the following example distinguish between fields and mirrors. In the following example
@ -412,38 +381,25 @@ the field, and with some useful variables bound, notably
can place a transformation in the primary field that lets you select can place a transformation in the primary field that lets you select
default values for it. default values for it.
For example, the [[sym:yas-choose-value][=yas-completing-read=]] function is version of The [[sym:yas-choose-value][=yas-choose-value=]] does this work for you. For example:
=completing-read= which checks these variables. For example, asking
the user for the initial value of a field:
#+BEGIN_SRC snippet #+BEGIN_SRC snippet
<div align="${2:$$(yas-completing-read "Alignment? " '("right" "center" "left"))}"> <div align="${2:$$(yas-choose-value '("right" "center" "left"))}">
$0 $0
</div> </div>
#+END_SRC #+END_SRC
See the definition of [[sym:yas-choose-value][=yas-completing-read=]] to see how it was written See the definition of [[sym:yas-choose-value][=yas-choose-value=]] to see how it was written using
using the two variables. If you're really lazy :) and can't spare a the two variables.
tab keypress, you can automatically move to the next field (or exit)
after choosing the value with [[sym:yas-auto-next][=yas-auto-next=]]. The snippet above
becomes:
#+BEGIN_SRC snippet Here's another use, for LaTeX-mode, which calls reftex-label just as you
<div align="${2:$$(yas-auto-next
(yas-completing-read
"Alignment? "
'("right" "center" "left")))}">
$0
</div>
#+END_SRC
Here's another use, for =LaTeX-mode=, which calls reftex-label just as you
enter snippet field 2. This one makes use of [[sym:yas-modified-p][=yas-modified-p=]] directly. enter snippet field 2. This one makes use of [[sym:yas-modified-p][=yas-modified-p=]] directly.
#+BEGIN_SRC snippet #+BEGIN_SRC snippet
\section{${1:"Titel der Tour"}}% \section{${1:"Titel der Tour"}}%
\index{$1}% \index{$1}%
\label{{2:"waiting for reftex-label call..."$(unless yas-modified-p (reftex-label nil 'dont-insert))}}% \label{{2:"waiting for reftex-label call..."$(unless yas-modified-p (reftex-label nil 'dont-
insert))}}%
#+END_SRC #+END_SRC
The function [[sym:yas-verify-value][=yas-verify-value=]] has another neat trick, and makes use The function [[sym:yas-verify-value][=yas-verify-value=]] has another neat trick, and makes use
@ -458,7 +414,7 @@ From version 0.6 on, you can also have nested placeholders of the type:
#+END_SRC #+END_SRC
This allows you to choose if you want to give this =div= an =id= This allows you to choose if you want to give this =div= an =id=
attribute. If you tab forward after expanding, it will let you change attribute. If you tab forward after expanding it will let you change
"some\_id" to whatever you like. Alternatively, you can just press =C-d= "some\_id" to whatever you like. Alternatively, you can just press =C-d=
(which executes [[sym:yas-skip-and-clear-or-delete-char][=yas-skip-and-clear-or-delete-char=]]) and go straight to (which executes [[sym:yas-skip-and-clear-or-delete-char][=yas-skip-and-clear-or-delete-char=]]) and go straight to
the exit marker. the exit marker.
@ -466,9 +422,3 @@ the exit marker.
By the way, =C-d= will only clear the field if you cursor is at the By the way, =C-d= will only clear the field if you cursor is at the
beginning of the field /and/ it hasn't been changed yet. Otherwise, it beginning of the field /and/ it hasn't been changed yet. Otherwise, it
performs the normal Emacs =delete-char= command. performs the normal Emacs =delete-char= command.
** Indentation markers
If [[sym:yas-indent-line][=yas-indent-line=]] is *not* set to '=auto=, it's still possible to
indent specific lines by adding an indentation marker, =$>=, somewhere
on the line.

View File

@ -21,7 +21,7 @@
- Using hippie-expand - Using hippie-expand
- Call [[sym:yas-insert-snippet][=yas-insert-snippet=]] (use =M-x yas-insert-snippet= or its - Call [[sym:yas-insert-snippet][=yas-insert-snippet=]] (use =M-x yas-insert-snippet== or its
keybinding =C-c & C-s=). keybinding =C-c & C-s=).
- Use m2m's excellent auto-complete - Use m2m's excellent auto-complete
@ -32,33 +32,17 @@
** Trigger key ** Trigger key
[[sym:yas-expand][=yas-expand=]] tries to expand a /snippet abbrev/ (also known as [[sym:yas-expand][=yas-expand=]] tries to expand a /snippet abbrev/ (also known as
/snippet key/) before point. YASnippet also provides a /conditional /snippet key/) before point.
binding/ for this command: the variable [[sym:yas-expand][=yas-maybe-expand=]] contains a
special value which, when bound in a keymap, tells Emacs to call
[[sym:yas-expand][=yas-expand=]] if and only if there is a snippet abbrev before point.
If there is no snippet to expand, Emacs will behave as if [[sym:yas-expand][=yas-expand=]]
is unbound and so will run whatever command is bound to that key
normally.
When [[sym:yas-minor-mode][=yas-minor-mode=]] is enabled, it binds [[sym:yas-maybe-expand][=yas-maybe-expand=]] to =TAB= When [[sym:yas-minor-mode][=yas-minor-mode=]] is enabled, it binds [[sym:yas-expand][=yas-expand=]] to =TAB= and
and =<tab>= by default, however, you can freely remove those bindings: =<tab>= by default, however, you can freely set it to some other key:
#+begin_src emacs-lisp :exports code #+begin_src emacs-lisp :exports code
(define-key yas-minor-mode-map (kbd "<tab>") nil) (define-key yas-minor-mode-map (kbd "<tab>") nil)
(define-key yas-minor-mode-map (kbd "TAB") nil) (define-key yas-minor-mode-map (kbd "TAB") nil)
(define-key yas-minor-mode-map (kbd "<the new key>") 'yas-expand)
#+end_src #+end_src
And set your own:
#+begin_src emacs-lisp :exports code
;; Bind `SPC' to `yas-expand' when snippet expansion available (it
;; will still call `self-insert-command' otherwise).
(define-key yas-minor-mode-map (kbd "SPC") yas-maybe-expand)
;; Bind `C-c y' to `yas-expand' ONLY.
(define-key yas-minor-mode-map (kbd "C-c y") #'yas-expand)
#+end_src
To enable the YASnippet minor mode in all buffers globally use the To enable the YASnippet minor mode in all buffers globally use the
command [[sym:yas-global-mode][=yas-global-mode=]]. This will enable a modeline indicator, command [[sym:yas-global-mode][=yas-global-mode=]]. This will enable a modeline indicator,
=yas=: =yas=:
@ -66,18 +50,28 @@ command [[sym:yas-global-mode][=yas-global-mode=]]. This will enable a modeline
[[./images/minor-mode-indicator.png]] [[./images/minor-mode-indicator.png]]
When you use [[sym:yas-global-mode][=yas-global-mode=]] you can also selectively disable When you use [[sym:yas-global-mode][=yas-global-mode=]] you can also selectively disable
YASnippet in some buffers by calling [[sym:yas-minor-mode][=yas-minor-mode=]] with a negative YASnippet in some buffers by setting the buffer-local variable
argument in the buffer's mode hook. [[sym:yas-dont-active][=yas-dont-active=]] in the buffer's mode hook.
*** Fallback behaviour *** Fallback behaviour
YASnippet used to support a more complicated way of sharing [[sym:yas-fallback-behaviour][=yas-fallback-behaviour=]] is a customization variable bound to
keybindings before [[sym:yas-expand][=yas-maybe-expand=]] was added. This is now '=call-other-command= by default. If [[sym:yas-expand][=yas-expand=]] failed to find any
obsolete. suitable snippet to expand, it will disable the minor mode temporarily
and find if there's any other command bound to the same key.
If found, the command will be called. Usually this works very well
--when there's a snippet, expand it, otherwise, call whatever command
originally bind to the trigger key.
However, you can change this behavior by customizing the
[[sym:yas-fallback-behavior][=yas-fallback-behavior=]] variable. If you set this variable to
'=return-nil=, it will return =nil= instead of trying to call the
/original/ command when no snippet is found.
** Insert at point ** Insert at point
The command [[sym:yas-insert-snippet][=yas-insert-snippet=]] lets you insert snippets at point The command [[#yas-insert-snippet][=yas-insert-snippet=]] lets you insert snippets at point
/for your current major mode/. It prompts you for the snippet key /for your current major mode/. It prompts you for the snippet key
first, and then for a snippet template if more than one template first, and then for a snippet template if more than one template
exists for the same key. exists for the same key.
@ -89,19 +83,6 @@ snippets for the major mode, prefix this command with =C-u=.
The prompting methods used are again controlled by The prompting methods used are again controlled by
[[sym:yas-prompt-functions][=yas-prompt-functions=]]. [[sym:yas-prompt-functions][=yas-prompt-functions=]].
*** Inserting region or register contents into snippet
It's often useful to inject already written text in the middle of a
snippet. The variable [[sym:yas-wrap-around-region][=yas-wrap-around-region=]] when to t substitute
the region contents into the =$0= placeholder of a snippet expanded by
[[sym:yas-insert-snippet][=yas-insert-snippet=]]. Setting it to a character value (e.g. =?0=)
will insert the contents of corresponding register.
Older (versions 0.9.1 and below) of Yasnippet, supported a setting of
=cua= that is equivalent to =?0= but only worked with =cua-mode=
turned on. This setting is still supported for backwards
compatibility, but is now entirely equivalent to =?0=.
** Snippet keybinding ** Snippet keybinding
See the section of the =# binding:= directive in See the section of the =# binding:= directive in
@ -141,7 +122,7 @@ See the internal documentation on [[sym:yas-expand-snippet][=yas-expand-snippet=
* Controlling expansion * Controlling expansion
** Eligible snippets<<eligible-snippets>> ** Eligible snippets
YASnippet does quite a bit of filtering to find out which snippets are YASnippet does quite a bit of filtering to find out which snippets are
eligible for expanding at the current cursor position. eligible for expanding at the current cursor position.
@ -161,17 +142,15 @@ In particular, the following things matter:
=M-x describe-variable RET major-mode RET= to find out which major =M-x describe-variable RET major-mode RET= to find out which major
mode you are in currently. mode you are in currently.
- Parent tables - Parent tables
Snippet tables defined as the parent of some other eligible table Snippet tables defined as the parent of some other eligible table are
are also considered. This works recursively, i.e., parents of also considered. This works recursively, i.e. parents of parents of
parents of eligible tables are also considered. As a special case, eligible tables are also considered.
if a mode doesn't have a parent, then =fundamental-mode= is
considered to be its parent.
- Buffer-local list of extra modes - Buffer-local list of extra modes
Use [[sym:yas-activate-extra-mode][=yas-activate-extra-mode=]] to Use [[#yas-activate-extra-mode][=yas-activate-extra-mode=]] to
consider snippet tables whose name does not correspond to a major consider snippet tables whose name does not correspond to a major
mode. Typically, you call this from a minor mode hook, for example: mode. Typically, you call this from a minor mode hook, for example:
@ -183,52 +162,53 @@ In particular, the following things matter:
(yas-activate-extra-mode 'rails-mode))) (yas-activate-extra-mode 'rails-mode)))
#+END_SRC #+END_SRC
- Buffer-local [[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]] variable - Buffer-local
[[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]]
variable
This variable provides finer grained control over what snippets can This variable provides finer grained control over what snippets can
be expanded in the current buffer. For example, the constant be expanded in the current buffer. The default value won't let you
[[sym:yas-not-string-or-comment-condition][=yas-not-string-or-comment-condition=]] has a value that disables expand snippets inside comments or string literals for example. See
snippet expansion inside comments or string literals. See [[condition-system][the The condition system\_ for more info.
condition system]] for more info.
** The condition system <<condition-system>> ** The condition system
Consider this scenario: you are an old Emacs hacker. You like the Consider this scenario: you are an old Emacs hacker. You like the
abbrev-way and bind [[sym:yas-expand][=yas-expand=]] to =SPC=. However, you don't want abbrev-way and bind [[sym:yas-expand][=yas-expand=]] to =SPC=. However, you don't want
=if= to be expanded as a snippet when you are typing in a comment =if= to be expanded as a snippet when you are typing in a comment
block or a string (e.g. in =python-mode=). block or a string (e.g. in =python-mode=).
If you use the =# condition := directive (see [[./snippet-development.org][Writing Snippets]]) you If you use the =# condition := directive (see
could just specify the condition for =if= to be =(not [[./snippet-development.org][Writing Snippets]]) you could just specify
(python-syntax-comment-or-string-p))=. But how about =while=, =for=, the condition for =if= to be =(not (python-in-string/comment))=. But how
etc? Writing the same condition for all the snippets is just boring. about =while=, =for=, etc. ? Writing the same condition for all the
So you can instead set [[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]] to =(not snippets is just boring. So has a buffer local variable
(python-syntax-comment-or-string-p))= in =python-mode-hook=. [[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]]. You can set this variable to
=(not (python-in-string/comment))= in =python-mode-hook=.
Then, what if you really want some particular snippet to expand even Then, what if you really want some particular snippet to expand even
inside a comment? Set [[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]] like this inside a comment? Set [[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]] like this
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(add-hook 'python-mode-hook (add-hook 'python-mode-hook
(lambda () (lambda ()
(setq yas-buffer-local-condition (setq yas-buffer-local-condition
(lambda () '(if (python-in-string/comment)
(if (python-syntax-comment-or-string-p) '(require-snippet-condition . force-in-comment)
'(require-snippet-condition . force-in-comment) t))))
t)))))
#+END_SRC #+END_SRC
... and for a snippet that you want to expand in comments, specify a ... and specify the condition for a snippet that you're going to expand
condition which evaluates to the symbol =force-in-comment=. Then it in comment to be evaluated to the symbol =force-in-comment=. Then it can
can be expanded as you expected, while other snippets like =if= still be expanded as you expected, while other snippets like =if= still can't
can't expanded in comments. expanded in comment.
For the full set of possible conditions, see the documentation for For the full set of possible conditions, see the documentation for
[[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]]. [[sym:yas-buffer-local-condition][=yas-buffer-local-condition=]].
** Multiples snippet with the same key ** Multiples snippet with the same key
The rules outlined [[eligible-snippets][above]] can return more than The rules outlined [[Eligible%20snippets][above]] can return more than
one snippet to be expanded at point. one snippet to be expanded at point.
When there are multiple candidates, YASnippet will let you select one. When there are multiple candidates, YASnippet will let you select one.

View File

@ -24,7 +24,7 @@ In this menu, you can find
Invoking "Load snippets..." from the menu invokes [[sym:yas-load-directory][=yas-load-directory=]] Invoking "Load snippets..." from the menu invokes [[sym:yas-load-directory][=yas-load-directory=]]
and prompts you for a snippet directory hierarchy to load. and prompts you for a snippet directory hierarchy to load.
Also useful is the "Reload everything" item to invoke [[sym:yas-reload-all][=yas-reload-all=]] Also useful is the "Reload everything" item to invoke [[#yas-reload-all][=yas-reload-all=]]
which uncondionally reloads all the snippets directories defined in which uncondionally reloads all the snippets directories defined in
[[sym:yas-snippet-dirs][=yas-snippet-dirs=]] and rebuilds the menus. [[sym:yas-snippet-dirs][=yas-snippet-dirs=]] and rebuilds the menus.

View File

@ -4,9 +4,8 @@
* Basic structure * Basic structure
Snippet collections can be stored in plain text files. They are Snippet collections can be stored in plain text files. They are arranged by
arranged by sub-directories naming *snippet tables*. These mostly sub-directories naming *snippet tables*. These mostly name Emacs major names.
name Emacs major mode names.
#+begin_example #+begin_example
. .
@ -33,7 +32,7 @@
The default considers: The default considers:
- a personal collection that lives in =~/.emacs.d/snippets= - a personal collection that lives in =~/.emacs.d/snippets=
- the bundled collection, taken as a relative path to =yasnippet.el= location - 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 When you come across other snippet collections, do the following to try them
out: out:
@ -82,7 +81,7 @@
If you place an empty plain text file =.yas-make-groups= inside one If you place an empty plain text file =.yas-make-groups= inside one
of the mode directories, the names of these sub-directories are of the mode directories, the names of these sub-directories are
considered groups of snippets and [[file:snippet-menu.org][the menu]] is organized much more considered groups of snippets and [[snippet-menu.org][the menu]] is organized much more
cleanly: cleanly:
[[./images/menu-groups.png]] [[./images/menu-groups.png]]
@ -109,11 +108,9 @@
Yet another way to create a nice snippet menu is to write into Yet another way to create a nice snippet menu is to write into
=.yas-make-groups= a menu definition. TODO =.yas-make-groups= a menu definition. TODO
* The =.yas-setup.el= file * TODO The =.yas-setup.el= file
If there is file named =.yas-setup.el= in a mode's snippet ** TODO
subdirectory, it is loaded along with the snippets. Utility
functions used by the snippets can be put here.
* The =.yas-compiled-snippet.el= file * The =.yas-compiled-snippet.el= file
@ -130,3 +127,5 @@
A =.yas-skip= file in a mode's snippet subdirectory tells YASnippet A =.yas-skip= file in a mode's snippet subdirectory tells YASnippet
not to load snippets from there. not to load snippets from there.
** TODO

View File

@ -1,14 +1,5 @@
.center { margin-left: auto; margin-right: auto; text-align: center; } nav > ul > li.center > ul {
.current { padding: 0;
font-weight: bold;
background-color: #E0E8F0;
}
body { background-color: #E4F0F4 }
div#content {
max-width: 20cm;
margin-left: auto;
margin-right: auto;
} }
nav li { nav li {
@ -18,53 +9,18 @@ nav li {
list-style-type: none; list-style-type: none;
padding: 0.5em; padding: 0.5em;
} }
nav > ul > li { nav > ul > li {
display: inline-block; display: inline-block;
} }
.nopad {
padding: 0;
}
li.border {
border: solid;
border-width: 1px;
}
pre, code{ background-color: #F3F5F7; } /* match org's css for <pre> */
code { code {
/* http://neugierig.org/software/chromium/notes/2009/09/monospace-fonts-workaround.html */ background-color: #F3F5F7;
font-family: WorkAroundWebKitAndMozilla, monospace; font-family: courier, monospace;
white-space: nowrap;
} }
/* Styles for htmlize.el fontification. */ #content {
margin-left: 5%;
.org-comment { color: #005000; } /* font-lock-comment-face */ margin-right: 10%;
.org-keyword { font-weight: bold; } /* font-lock-keyword-face */ }
.org-string { color: #8b0000; } /* font-lock-string-face */
.org-warning { color: #ff8c00;
font-weight: bold; } /* warning */
.org-warning-1 { color: #ff0000;
font-weight: bold; } /* font-lock-warning-face */
.org-preprocessor { color: #483d8b; } /* font-lock-preprocessor-face */
.org-constant { color: #008b8b; } /* font-lock-constant-face */
.org-function-name { color: #0000ff; } /* font-lock-function-name-face */
.org-type { color: #228b22; } /* font-lock-type-face */
.org-variable-name { color: #a0522d; } /* font-lock-variable-name-face */
.org-rst-adornment { color: #a020f0; } /* rst-adornment */
.org-rst-block { color: #a020f0; } /* rst-block */
.org-rst-comment { color: #b22222; } /* rst-comment */
.org-rst-definition { color: #0000ff; } /* rst-definition */
.org-rst-directive { color: #483d8b; } /* rst-directive */
.org-rst-emphasis1 { font-style: italic; } /* rst-emphasis1 */
.org-rst-emphasis2 { font-weight: bold; } /* rst-emphasis2 */
.org-rst-external { color: #228b22; } /* rst-external */
.org-rst-level-1 { background-color: #d9d9d9; } /* rst-level-1 */
.org-rst-level-2 { background-color: #c7c7c7; } /* rst-level-2 */
.org-rst-level-3 { background-color: #b5b5b5; } /* rst-level-3 */
.org-rst-level-4 { background-color: #a3a3a3; } /* rst-level-4 */
.org-rst-level-5 { background-color: #919191; } /* rst-level-5 */
.org-rst-level-6 { background-color: #7f7f7f; } /* rst-level-6 */
.org-rst-literal { color: #8b2252; } /* rst-literal */
.org-rst-reference { color: #a0522d; } /* rst-reference */
.org-rst-transition { color: #a020f0; } /* rst-transition */

View File

@ -0,0 +1,93 @@
@media all
{
body {
margin: 1em auto;
/*margin: 10px 18% 10px 18%;*/
font-family: Arial;
/*text-align: justify;*/
font-size: 14pt;
padding: 10px;
line-height: 1.2em;
max-width: 600pt;
}
div#table-of-contents {
position: fixed;
left: 0%;
right: 0%;
top: 0px;
z-index: 100;
background: black;
}
div#table-of-contents h2 {
display: none;
}
div#table-of-contents a {
text-decoration: none;
color: white;
}
div#table-of-contents a:visited {
color: white;
}
div#table-of-contents a:hover {
color: orange;
}
div.outline-2 h2{
padding-top: 50px;
}
div#text-table-of-contents {
text-color: white;
text-align: center;
margin-left: 30%;
margin-right: 30%;
}
div#text-table-of-contents ul {
height: 2em;
width: 500px;
list-style: none;
margin: auto;
}
div#text-table-of-contents ul li {
float: left;
margin-left:auto;
margin-right: auto;
padding-left: 10px;
}
div#postamble{
position: fixed;
width: 800px;
height: 250px;
left: 50%;
right: 50%;
margin:-75px 0 0 -400px;
bottom: -20px;
font-size: 10pt;
color: grey;
background: url('siscog-bottom-logo.png') no-repeat;
/* background-size: 100% 100%; */
}
div#postamble *{
display: none;
}
div#postamble p.date{
position: relative;
bottom: -200px;
text-align: center;
display: block;
}
}

244
doc/yas-doc-helper.el Normal file → Executable file
View File

@ -1,6 +1,6 @@
;;; yas-doc-helper.el --- Help generate documentation for YASnippet -*- lexical-binding: t; -*- ;;; yas-doc-helper.el --- Help generate documentation for YASnippet
;; Copyright (C) 2012-2023 Free Software Foundation, Inc. ;; Copyright (C) 2012, 2013 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com> ;; Author: João Távora <joaotavora@gmail.com>
;; Keywords: convenience ;; Keywords: convenience
@ -25,186 +25,127 @@
;;; Code: ;;; Code:
(eval-when-compile (eval-when-compile
(require 'cl-lib)) (require 'cl))
(require 'org) (require 'org)
(require 'ox-publish) (or (require 'org-publish nil t)
(require 'ox-publish))
(require 'yasnippet) ; docstrings must be loaded (require 'yasnippet) ; docstrings must be loaded
;; Presumably one of org/ox-publish provided the following vars: (defun yas--org-raw-html (tag content)
(defvar org-publish-project-alist)
(defvar org-publish-use-timestamps-flag)
(defvar org-export-copy-to-kill-ring)
(defvar org-html-htmlize-output-type)
(defun yas--org-raw-html (tag content &optional attrs)
;; in version 8.0 org-mode changed the export syntax, see ;; in version 8.0 org-mode changed the export syntax, see
;; http://orgmode.org/worg/org-8.0.html#sec-8-1 ;; http://orgmode.org/worg/org-8.0.html#sec-8-1
(format (if (version< org-version "8.0.0") (format (if (version< org-version "8.0.0")
"@<%s>%s@</%s>" ; old: @<tag> "@<%s>%s@</%s>" ; old: @<tag>
"@@html:<%s>@@%s@@html:</%s>@@") ; new: @@html:<tag>@@ "@@html:<%s>@@%s@@html:</%s>@@") ; new: @@html:<tag>@@
(concat tag (if attrs " ") attrs) tag content tag))
content tag))
(defun yas--document-symbol (symbol level) (defun yas--document-symbol (symbol level)
(let* ((stars (make-string level ?*)) (flet ((concat-lines (&rest lines)
(args (and (fboundp symbol) (mapconcat #'identity lines "\n")))
(mapcar #'symbol-name (help-function-arglist symbol t)))) (let* ((stars (make-string level ?*))
(heading (cond ((fboundp symbol) (args (and (fboundp symbol)
(format (mapcar #'symbol-name (help-function-arglist symbol t))))
"%s %s (%s)\n" stars (yas--org-raw-html "code" symbol "class='function'") (heading (cond ((fboundp symbol)
(mapconcat (lambda (a) (format
(format (if (string-prefix-p "&" a) "%s =%s= (%s)" stars symbol
"/%s/" "=%s=") (mapconcat (lambda (a)
a)) (format (if (string-prefix-p "&" a)
args " "))) "/%s/" "=%s=") a))
(t args " ")))
(format "%s %s\n" stars (t
(yas--org-raw-html "code" symbol "class='variable'"))))) (format "%s =%s=\n" stars symbol))))
(after-heading (format ":PROPERTIES:\n:CUSTOM_ID: %s\n:END:" symbol)) (after-heading
(text-quoting-style 'grave) (concat-lines ":PROPERTIES:"
(body (or (cond ((fboundp symbol) (format ":CUSTOM_ID: %s" symbol)
(let ((doc-synth (car-safe (get symbol 'function-documentation)))) ":END:"))
(if (functionp doc-synth) (body (or (cond ((fboundp symbol)
(funcall doc-synth nil) (let ((doc-synth (car-safe (get symbol 'function-documentation))))
(documentation symbol t)))) (if (functionp doc-synth)
((boundp symbol) (funcall doc-synth nil)
(documentation-property symbol 'variable-documentation t)) (documentation symbol t))))
(t ((boundp symbol)
(format "*WARNING*: no symbol named =%s=" symbol))) (documentation-property symbol 'variable-documentation t))
(format "*WARNING*: no doc for symbol =%s=" symbol))) (t
(case-fold-search nil)) (format "*WARNING*: no symbol named =%s=" symbol)))
;; Do some transformations on the body: (format "*WARNING*: no doc for symbol =%s=" symbol)))
;; ARGxxx becomes @<code>arg@</code>xxx (case-fold-search nil))
;; FOO becomes /foo/ ;; do some transformations on the body:
;; `bar' becomes [[#bar][=bar=]] ;; ARGxxx becomes @<code>arg@</code>xxx
;; (...) becomes #+BEGIN_SRC elisp (...) #+END_SRC ;; FOO becomes /foo/
;; Info node `(some-manual) Node Name' becomes ;; `bar' becomes [[#bar][=bar=]]
;; [[https://www.gnu.org/software/emacs/manual/html_node/some-manual/Node-Name.html] (setq body (replace-regexp-in-string
;; [(some-manual) Node Name]] "\\<\\([A-Z][-A-Z0-9]+\\)\\(\\sw+\\)?\\>"
;; #'(lambda (match)
;; This is fairly fragile, though it seems to be working for (let* ((match1 (match-string 1 match))
;; now... (prefix (downcase match1))
(setq body (replace-regexp-in-string (suffix (match-string 2 match))
"\\<\\([A-Z][-A-Z0-9]+\\)\\(\\sw+\\)?\\>" (fmt (cond
#'(lambda (match) ((member prefix args)
(let* ((match1 (match-string 1 match)) (yas--org-raw-html "code" "%s"))
(prefix (downcase match1)) ((null suffix) "/%s/"))))
(suffix (match-string 2 match)) (if fmt (format fmt prefix)
(fmt (cond match1)))
((member prefix args) body t t 1)
(yas--org-raw-html "code" "%s")) body (replace-regexp-in-string
((null suffix) "/%s/")))) "`\\([a-z-]+\\)'"
(if fmt (format fmt prefix) #'(lambda (match)
match1))) (let* ((name (downcase (match-string 1 match)))
body t t 1) (sym (intern name)))
body (replace-regexp-in-string (if (memq sym yas--exported-syms)
"\\\\{[^}]+}" (format "[[#%s][=%s=]]" name name)
(lambda (match) (format "=%s=" name))))
(concat "#+BEGIN_EXAMPLE\n" body t))
(substitute-command-keys match) ;; output the paragraph
"#+END_EXAMPLE\n")) ;;
body t t) (concat-lines heading
body (substitute-command-keys body) after-heading
body (replace-regexp-in-string body))))
"Info node `(\\([-a-z]+\\)) \\([A-Za-z0-9 ]+\\)'"
(lambda (match)
(let* ((manual (match-string 1 match))
(node (match-string 2 match))
(html-node (replace-regexp-in-string " " "-" node t t)))
(format "Info node\
[[https://www.gnu.org/software/emacs/manual/html_node/%s/%s.html][(%s) %s]]"
manual html-node manual node)))
body t t)
body (replace-regexp-in-string
"`\\([-a-z]+\\)'"
#'(lambda (match)
(let* ((name (downcase (match-string 1 match)))
(sym (intern-soft name)))
(if (memq sym yas--exported-syms)
(format "[[#%s][=%s=]]" name name)
(format "=%s=" name))))
body t t)
body (replace-regexp-in-string
"\n\n +(.+\\(?:\n +.+\\)*"
(lambda (match)
(concat "\n#+BEGIN_SRC elisp\n"
match
"\n#+END_SRC\n"))
body t t))
;; output the paragraph
(concat heading after-heading "\n" body)))
(defun yas--document-symbols (level &rest names-and-predicates) (defun yas--document-symbols (level &rest names-and-predicates)
(let ((sym-lists (make-vector (length names-and-predicates) nil)) (let ((sym-lists (make-vector (length names-and-predicates) nil))
(stars (make-string level ?*))) (stars (make-string level ?*)))
(cl-loop for sym in yas--exported-syms (loop for sym in yas--exported-syms
do (cl-loop for test in (mapcar #'cdr names-and-predicates) do (loop for test in (mapcar #'cdr names-and-predicates)
for i from 0 for i from 0
do (when (funcall test sym) do (when (funcall test sym)
(push sym (aref sym-lists i)) (push sym (aref sym-lists i))
(cl-return)))) (return))))
(cl-loop for slist across sym-lists (loop for slist across sym-lists
for name in (mapcar #'car names-and-predicates) for name in (mapcar #'car names-and-predicates)
concat (format "\n%s %s\n" stars name) concat (format "\n%s %s\n" stars name)
concat (mapconcat (lambda (sym) concat (mapconcat (lambda (sym)
(yas--document-symbol sym (1+ level))) (yas--document-symbol sym (1+ level)))
slist "\n\n")))) slist "\n\n"))))
(defun yas--internal-link-snippet () (defun yas--internal-link-snippet ()
(interactive) (interactive)
(yas-expand-snippet "[[#$1][=${1:`yas/selected-text`}=]]")) (yas-expand-snippet "[[#$1][=${1:`yas/selected-text`}=]]"))
(define-key org-mode-map [M-f8] #'yas--internal-link-snippet) (define-key org-mode-map [M-f8] 'yas--internal-link-snippet)
;; This lets all the org files be exported to HTML with ;; This lets all the org files be exported to HTML with
;; `org-publish-current-project' (C-c C-e P). ;; `org-publish-current-project' (C-c C-e P).
(defun yas--make-preamble (props)
"Return contents of nav-menu-html.inc.
But replace link to \"current\" page with a span element."
(with-temp-buffer
(let ((dir (file-name-directory (plist-get props :input-file))))
(insert-file-contents (expand-file-name "nav-menu.html.inc" dir))
(goto-char (point-min))
(search-forward (concat "<a href=\""
(file-name-nondirectory
(plist-get props :output-file))
"\">"))
(replace-match "<span class='current'>")
(search-forward "</a>")
(replace-match "</span>")
(buffer-string))))
(let* ((dir (if load-file-name (file-name-directory load-file-name) (let* ((dir (if load-file-name (file-name-directory load-file-name)
default-directory)) default-directory))
(src-epoch (getenv "SOURCE_DATE_EPOCH")) (rev (with-temp-file (expand-file-name "html-revision" dir)
;; Presence of SOURCE_DATE_EPOCH indicates a reproducible (or (when (eq (call-process "git" nil t nil
;; build, don't depend on git. "rev-parse" "--verify" "HEAD") 0)
(rev (unless src-epoch (buffer-string))
(ignore-errors (princ yas--version (current-buffer)))))
(car (process-lines "git" "describe" "--dirty")))))
(date (format-time-string
"(%Y-%m-%d %H:%M:%S)"
(seconds-to-time
(string-to-number
(or (if rev (car (process-lines "git" "show" "--format=%ct"))
src-epoch)
"0")))
t))
(proj-plist (proj-plist
`(,@(when (fboundp 'org-html-publish-to-html) `(,@(when (fboundp 'org-html-publish-to-html)
'(:publishing-function org-html-publish-to-html)) '(:publishing-function org-html-publish-to-html))
:base-directory ,dir :publishing-directory ,dir :base-directory ,dir :publishing-directory ,dir
:html-preamble yas--make-preamble :html-preamble
;;:with-broken-links mark ,(with-temp-buffer
(insert-file-contents (expand-file-name "nav-menu.html.inc" dir))
(buffer-string))
:html-postamble :html-postamble
,(concat "<hr><p class='creator'>Generated by %c from " ,(concat "<hr><p class='creator'>Generated by %c on %d from "
rev " " date "</p>\n" rev "</p>\n"
"<p class='xhtml-validation'>%v</p>\n"))) "<p class='xhtml-validation'>%v</p>\n")))
(project (assoc "yasnippet" org-publish-project-alist))) (project (assoc "yasnippet" org-publish-project-alist)))
(when rev ;; Rakefile :doc:upload uses "html-revision".
(with-temp-file (expand-file-name "html-revision" dir)
(princ rev (current-buffer))))
(if project (if project
(setcdr project proj-plist) (setcdr project proj-plist)
(push `("yasnippet" . ,proj-plist) (push `("yasnippet" . ,proj-plist)
@ -214,8 +155,7 @@ But replace link to \"current\" page with a span element."
(let ((org-publish-use-timestamps-flag nil) (let ((org-publish-use-timestamps-flag nil)
(org-export-copy-to-kill-ring nil) (org-export-copy-to-kill-ring nil)
(org-confirm-babel-evaluate nil) (org-confirm-babel-evaluate nil)
(make-backup-files nil) (make-backup-files nil))
(org-html-htmlize-output-type 'css))
(org-publish "yasnippet" 'force))) (org-publish "yasnippet" 'force)))

1
snippets Submodule

@ -0,0 +1 @@
Subproject commit 3f3ff6f642d100bfcf093d282603f9fc0088cfe5

1
yasmate Submodule

@ -0,0 +1 @@
Subproject commit 0543618bd34a6715918992f01161c118f136bb37

View File

@ -1,8 +1,8 @@
;;; yasnippet-debug.el --- debug functions for yasnippet -*- lexical-binding: t -*- ;;; yasnippet-debug.el --- debug functions for yasnippet
;; Copyright (C) 2010-2025 Free Software Foundation, Inc. ;; Copyright (C) 2010, 2013, 2014 Free Software Foundation, Inc.
;; Author: João Távora ;; Author: João Távora
;; Keywords: emulations, convenience ;; Keywords: emulations, convenience
;; This program is free software; you can redistribute it and/or modify ;; This program is free software; you can redistribute it and/or modify
@ -20,335 +20,114 @@
;;; Commentary: ;;; Commentary:
;; Some debug functions. When loaded from the command line, provides ;; Just some debug functions
;; quick way to test out snippets in a fresh Emacs instance.
;;
;; emacs -Q -l yasnippet-debug [-v[v]]
;; [-M:<modename>] [-M.<filext>] [-S:[<snippet-file|name>]]
;; [-- <more-arguments-passed-to-Emacs>...]
;;
;; See the source in `yas-debug-process-command-line' for meaning of
;; args.
;;
;;; Code: ;;; Code:
(defconst yas--loaddir (require 'yasnippet)
(file-name-directory (or load-file-name buffer-file-name)) (require 'cl)
"Directory that yasnippet was loaded from.")
(require 'yasnippet (if (boundp 'yas--loaddir) (defun yas-debug-snippet-vars ()
;; Don't require '-L <path>' when debugging. "Debug snippets, fields, mirrors and the `buffer-undo-list'."
(expand-file-name "yasnippet" yas--loaddir))) (interactive)
(require 'cl-lib) (with-output-to-temp-buffer "*YASnippet trace*"
(require 'color nil t) (princ "Interesting YASnippet vars: \n\n")
(require 'edebug)
(eval-when-compile
(require 'subr-x nil t)
(cond ((fboundp 'when-let*) nil) ; Introduced in 26.
((fboundp 'when-let) ; Introduced in 25.1,
(defalias 'when-let* 'when-let)) ; deprecated in 26.
(t (defmacro when-let* (key-vals &rest body)
(declare (indent 1) (debug ((symbolp form) body)))
(let ((key-val (pop key-vals)))
(if key-val
`(let ((,(car key-val) ,(cadr key-val)))
(if ,(car key-val)
(when-let* ,key-vals
,@body)))
`(progn ,@body)))))))
(defvar yas-debug-live-indicators (princ (format "\nPost command hook: %s\n" post-command-hook))
(make-hash-table :test #'eq)) (princ (format "\nPre command hook: %s\n" pre-command-hook))
(defun yas-debug-live-colors () (princ (format "%s live snippets in total\n" (length (yas--snippets-at-point (quote all-snippets)))))
(let ((colors ())) (princ (format "%s overlays in buffer:\n\n" (length (overlays-in (point-min) (point-max)))))
(maphash (lambda (_k v) (push (nth 1 (car v)) colors)) yas-debug-live-indicators) (princ (format "%s live snippets at point:\n\n" (length (yas--snippets-at-point))))
colors))
(defvar yas-debug-recently-live-indicators)
(defun yas-debug-get-live-indicator (location)
(require 'color)
(when (boundp 'yas-debug-recently-live-indicators)
(push location yas-debug-recently-live-indicators))
(let (beg end)
(if (markerp location)
(setq beg (setq end (marker-position location)))
(setq beg (yas-debug-ov-fom-start location)
end (yas-debug-ov-fom-end location)))
(or (when-let* ((color-ov (gethash location yas-debug-live-indicators)))
(if (and beg end) (move-overlay (cdr color-ov) beg end)
(delete-overlay (cdr color-ov)))
color-ov)
(let* ((live-colors (yas-debug-live-colors))
(color
(cl-loop with best-color = nil with max-dist = -1
for color = (format "#%06X" (random #x1000000))
for comp = (if (fboundp 'color-complement)
(apply #'color-rgb-to-hex (color-complement color))
color)
if (< (color-distance color (face-foreground 'default))
(color-distance comp (face-foreground 'default)))
do (setq color comp)
for dist = (cl-loop for c in live-colors
minimize (color-distance c color))
if (or (not live-colors) (> dist max-dist))
do (setq best-color color) (setq max-dist dist)
repeat (if live-colors 100 1)
finally return `(:background ,best-color)))
(ov (make-overlay beg end)))
(if (markerp location)
(overlay-put ov 'before-string (propertize "" 'face color))
(overlay-put ov 'before-string (propertize "" 'face color))
(overlay-put ov 'after-string (propertize "" 'face color)))
(puthash location (cons color ov) yas-debug-live-indicators)))))
(defun yas-debug-live-marker (marker)
(let* ((color-ov (yas-debug-get-live-indicator marker))
(color (car color-ov))
(ov (cdr color-ov))
(decorator (overlay-get ov 'before-string))
(str (format "at %d" (+ marker))))
(if (markerp marker)
(propertize str
'cursor-sensor-functions
`(,(lambda (_window _oldpos dir)
(overlay-put
ov 'before-string
(propertize decorator
'face (if (eq dir 'entered)
'mode-line-highlight color)))))
'face color)
str)))
(defun yas-debug-ov-fom-start (ovfom)
(cond ((overlayp ovfom) (overlay-start ovfom))
((integerp ovfom) ovfom)
(t (yas--fom-start ovfom))))
(defun yas-debug-ov-fom-end (ovfom)
(cond ((overlayp ovfom) (overlay-end ovfom))
((integerp ovfom) ovfom)
(t (yas--fom-end ovfom))))
(defun yas-debug-live-range (range)
(let* ((color-ov (yas-debug-get-live-indicator range))
(color (car color-ov))
(ov (cdr color-ov))
(decorator-beg (overlay-get ov 'before-string))
(decorator-end (overlay-get ov 'after-string))
(beg (yas-debug-ov-fom-start range))
(end (yas-debug-ov-fom-end range)))
(if (and beg end (or (overlayp range)
(and (not (integerp beg))
(not (integerp end)))))
(propertize (format "from %d to %d" (+ beg) (+ end))
'cursor-sensor-functions
`(,(lambda (_window _oldpos dir)
(let ((face (if (eq dir 'entered)
'mode-line-highlight color)))
(overlay-put ov 'before-string
(propertize decorator-beg 'face face))
(overlay-put ov 'after-string
(propertize decorator-end 'face face)))))
'face color)
"<dead>")))
(defmacro yas-debug-with-tracebuf (outbuf &rest body)
(declare (indent 1) (debug (sexp body)))
(let ((tracebuf-var (make-symbol "tracebuf")))
`(let ((,tracebuf-var (or ,outbuf (get-buffer-create "*YASnippet trace*"))))
(unless (eq ,tracebuf-var (current-buffer))
(cl-flet ((printf (fmt &rest args)
(with-current-buffer ,tracebuf-var
(insert (apply #'format fmt args)))))
(unless ,outbuf
(with-current-buffer ,tracebuf-var
(erase-buffer)
(when (fboundp 'cursor-sensor-mode)
(cursor-sensor-mode +1))
(setq truncate-lines t)))
(setq ,outbuf ,tracebuf-var)
(save-restriction
(widen)
,@body))))))
(defun yas-debug-snippet (snippet &optional outbuf) (dolist (snippet (yas--snippets-at-point))
(yas-debug-with-tracebuf outbuf (princ (format "\tsid: %d control overlay from %d to %d\n"
(when-let* ((overlay (yas--snippet-control-overlay snippet))) (yas--snippet-id snippet)
(printf "\tsid: %d control overlay %s\n" (overlay-start (yas--snippet-control-overlay snippet))
(yas--snippet-id snippet) (overlay-end (yas--snippet-control-overlay snippet))))
(yas-debug-live-range overlay))) (princ (format "\tactive field: %s from %s to %s covering \"%s\"\n"
(when-let* ((active-field (yas--snippet-active-field snippet))) (yas--field-number (yas--snippet-active-field snippet))
(unless (consp (yas--field-start active-field)) (marker-position (yas--field-start (yas--snippet-active-field snippet)))
(printf "\tactive field: #%d %s %s covering \"%s\"\n" (marker-position (yas--field-end (yas--snippet-active-field snippet)))
(or (yas--field-number active-field) -1) (buffer-substring-no-properties (yas--field-start (yas--snippet-active-field snippet)) (yas--field-end (yas--snippet-active-field snippet)))))
(if (yas--field-modified-p active-field) "**" "--") (when (yas--snippet-exit snippet)
(yas-debug-live-range active-field) (princ (format "\tsnippet-exit: at %s next: %s\n"
(buffer-substring-no-properties (yas--field-start active-field) (yas--field-end active-field))))) (yas--exit-marker (yas--snippet-exit snippet))
(when-let* ((exit (yas--snippet-exit snippet))) (yas--exit-next (yas--snippet-exit snippet)))))
(printf "\tsnippet-exit: %s next: %s\n" (dolist (field (yas--snippet-fields snippet))
(yas-debug-live-marker (yas--exit-marker exit)) (princ (format "\tfield: %s from %s to %s covering \"%s\" next: %s%s\n"
(yas--exit-next exit))) (yas--field-number field)
(dolist (field (yas--snippet-fields snippet)) (marker-position (yas--field-start field))
(unless (consp (yas--field-start field)) (marker-position (yas--field-end field))
(printf "\tfield: %d %s %s covering \"%s\" next: %s%s\n" (buffer-substring-no-properties (yas--field-start field) (yas--field-end field))
(or (yas--field-number field) -1) (yas--debug-format-fom-concise (yas--field-next field))
(if (yas--field-modified-p field) "**" "--") (if (yas--field-parent-field field) "(has a parent)" "")))
(yas-debug-live-range field) (dolist (mirror (yas--field-mirrors field))
(buffer-substring-no-properties (yas--field-start field) (yas--field-end field)) (princ (format "\t\tmirror: from %s to %s covering \"%s\" next: %s\n"
(yas--debug-format-fom-concise (yas--field-next field)) (marker-position (yas--mirror-start mirror))
(if (yas--field-parent-field field) (marker-position (yas--mirror-end mirror))
(format " parent: %s" (buffer-substring-no-properties (yas--mirror-start mirror) (yas--mirror-end mirror))
(yas--debug-format-fom-concise (yas--debug-format-fom-concise (yas--mirror-next mirror)))))))
(yas--field-parent-field field)))
"")))
(dolist (mirror (yas--field-mirrors field))
(unless (consp (yas--mirror-start mirror))
(printf "\t\tmirror: %s covering \"%s\" next: %s\n"
(yas-debug-live-range mirror)
(buffer-substring-no-properties (yas--mirror-start mirror) (yas--mirror-end mirror))
(yas--debug-format-fom-concise (yas--mirror-next mirror))))))))
(defvar yas-debug-target-buffer nil) (princ (format "\nUndo is %s and point-max is %s.\n"
(defvar yas-debug-target-snippets nil nil) (if (eq buffer-undo-list t)
(make-variable-buffer-local 'yas-debug-target-snippets) "DISABLED"
"ENABLED")
(defvar yas-debug-undo nil) (point-max)))
(unless (eq buffer-undo-list t)
(defun yas-toggle-debug-undo (value) (princ (format "Undpolist has %s elements. First 10 elements follow:\n" (length buffer-undo-list)))
(interactive (list (not yas-debug-undo))) (let ((first-ten (subseq buffer-undo-list 0 (min 19
(setq yas-debug-undo value) (length buffer-undo-list)))))
(yas--message 3 "debug undo %sabled" (if yas-debug-undo "en" "dis"))) (dolist (undo-elem first-ten)
(princ (format "%2s: %s\n" (position undo-elem first-ten) (truncate-string-to-width (format "%s" undo-elem) 70))))))))
(defun yas-debug--target-snippet (snippet)
(add-to-list 'yas-debug-target-snippets snippet))
(defun yas-debug--untarget-snippet (snippet)
(setq yas-debug-target-snippets
(remq snippet yas-debug-target-snippets))
(maphash (lambda (_k color-ov)
(delete-overlay (cdr color-ov)))
yas-debug-live-indicators)
(clrhash yas-debug-live-indicators))
(defun yas-debug-snippets (&optional outbuf hook)
"Print debug information on active snippets to buffer OUTBUF.
If OUTBUF is nil, use a buffer named \"*YASsnippet trace*\".
If HOOK is non-nil, install `yas-debug-snippets' in
`post-command-hook' to update the information on every command
after this one. If it is `snippet-navigation' then install hook
buffer-locally, otherwise install it globally. If HOOK is
`edebug-create', also instrument the function
`yas--snippet-parse-create' with `edebug' and show its source."
(interactive (list nil t))
(condition-case err
(yas-debug-with-tracebuf outbuf
(unless (buffer-live-p yas-debug-target-buffer)
(setq yas-debug-target-buffer nil))
(with-current-buffer (or yas-debug-target-buffer (current-buffer))
(when yas-debug-target-snippets
(setq yas-debug-target-snippets
(cl-delete-if-not #'yas--snippet-p yas-debug-target-snippets)))
(let ((yas-debug-recently-live-indicators nil))
(printf "(length yas--snippets-snippets) => %d\n"
(length yas--active-snippets))
(dolist (snippet (or yas-debug-target-snippets
(yas-active-snippets)))
(printf "snippet %d\n" (yas--snippet-id snippet))
(yas-debug-snippet snippet outbuf))
(maphash (lambda (loc color-ov)
(unless (memq loc yas-debug-recently-live-indicators)
(delete-overlay (cdr color-ov))
(remhash loc yas-debug-live-indicators)))
yas-debug-live-indicators))
(when (and yas-debug-undo (listp buffer-undo-list))
(printf "Undo list has %s elements:\n" (length buffer-undo-list))
(cl-loop for undo-elem in buffer-undo-list
do (printf "%S\n" undo-elem))))
(when hook
(setq yas-debug-target-buffer (current-buffer))
(advice-add 'yas--snippet-parse-create :before #'yas-debug--target-snippet)
(advice-add 'yas--commit-snippet :after #'yas-debug--untarget-snippet)
(add-hook 'post-command-hook #'yas-debug-snippets
nil (eq hook 'snippet-navigation))
;; Window management is slapped together, it does what I
;; want when the caller has a single window open. Good
;; enough for now.
(when (eq hook 'edebug-create)
(edebug-instrument-function 'yas--snippet-parse-create)
(let ((buf-point (find-function-noselect 'yas--snippet-parse-create)))
(with-current-buffer (car buf-point)
(goto-char (cdr buf-point)))))
outbuf))
((debug error) (signal (car err) (cdr err)))))
(defun yas-debug-snippet-create ()
(yas-debug-snippets nil 'create))
(defun yas--debug-format-fom-concise (fom) (defun yas--debug-format-fom-concise (fom)
(when fom (when fom
(cond ((yas--field-p fom) (cond ((yas--field-p fom)
(format "field %s from %d to %d" (format "field %s from %d to %d"
(yas--field-number fom) (yas--field-number fom)
(+ (yas--field-start fom)) (marker-position (yas--field-start fom))
(+ (yas--field-end fom)))) (marker-position (yas--field-end fom))))
((yas--mirror-p fom) ((yas--mirror-p fom)
(format "mirror from %d to %d" (format "mirror from %d to %d"
(+ (yas--mirror-start fom)) (marker-position (yas--mirror-start fom))
(+ (yas--mirror-end fom)))) (marker-position (yas--mirror-end fom))))
(t (t
(format "snippet exit at %d" (format "snippet exit at %d"
(+ (yas--fom-start fom))))))) (marker-position (yas--fom-start fom)))))))
(defun yas-debug-process-command-line (&optional options)
"Implement command line processing."
(setq yas-verbosity 99)
(setq yas-triggers-in-field t)
(setq debug-on-error t)
(let* ((snippet-mode 'fundamental-mode)
(snippet-key nil))
(unless options
(setq options (cl-loop for opt = (pop command-line-args-left)
while (and opt (not (equal opt "--"))
(string-prefix-p "-" opt))
collect opt)))
(when-let* ((mode (cl-member "-M:" options :test #'string-prefix-p)))
(setq snippet-mode (intern (concat (substring (car mode) 3) "-mode"))))
(when-let* ((mode (cl-member "-M." options :test #'string-prefix-p)))
(setq snippet-mode
(cdr (cl-assoc (substring (car mode) 2) auto-mode-alist
:test (lambda (ext regexp) (string-match-p regexp ext))))))
(switch-to-buffer (get-buffer-create "*yas test*"))
(funcall snippet-mode)
(when-let* ((snippet-file (cl-member "-S:" options :test #'string-prefix-p)))
(setq snippet-file (substring (car snippet-file) 3))
(if (file-exists-p snippet-file)
(with-temp-buffer
(insert-file-contents snippet-file)
(let ((snippet-deflist (yas--parse-template snippet-file)))
(yas-define-snippets snippet-mode (list snippet-deflist))
(setq snippet-key (car snippet-deflist))))
(yas-reload-all)
(let ((template (yas--lookup-snippet-1 snippet-file snippet-mode)))
(if template
(setq snippet-key (yas--template-key template))
(error "No such snippet `%s'" snippet-file)))))
(display-buffer (find-file-noselect
(expand-file-name "yasnippet.el" yas--loaddir)))
(when-let* ((verbosity (car (or (member "-v" options) (member "-vv" options)))))
(set-window-buffer
(split-window) (yas-debug-snippets
nil (if (equal verbosity "-vv") 'edebug-create t))))
(yas-minor-mode +1)
(when snippet-key (insert snippet-key))))
(when command-line-args-left (defun yas-exterminate-package ()
(yas-debug-process-command-line)) (interactive)
(yas-global-mode -1)
(yas-minor-mode -1)
(mapatoms #'(lambda (atom)
(when (string-match "yas[-/]" (symbol-name atom))
(unintern atom obarray)))))
(defun yas-debug-test (&optional quiet)
(interactive "P")
(yas-load-directory (or (and (listp yas-snippet-dirs)
(first yas-snippet-dirs))
yas-snippet-dirs
"~/Source/yasnippet/snippets/"))
(set-buffer (switch-to-buffer "*YAS TEST*"))
(mapc #'yas--commit-snippet (yas--snippets-at-point 'all-snippets))
(erase-buffer)
(setq buffer-undo-list nil)
(setq undo-in-progress nil)
(snippet-mode)
(yas-minor-mode 1)
(let ((abbrev))
(setq abbrev "$f")
(insert abbrev))
(unless quiet
(add-hook 'post-command-hook 'yas-debug-snippet-vars 't 'local)))
(provide 'yasnippet-debug) (provide 'yasnippet-debug)
;; Local Variables: ;; Local Variables:
;; indent-tabs-mode: nil ;; indent-tabs-mode: nil
;; autoload-compute-prefixes: nil ;; byte-compile-warnings: (not cl-functions)
;; End: ;; End:
;;; yasnippet-debug.el ends here ;;; yasnippet-debug.el ends here

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff