Compare commits

..

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

11 changed files with 693 additions and 645 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

View File

@ -1,7 +1,5 @@
language: generic language: generic
os: linux sudo: false
dist: xenial
git: git:
submodules: false submodules: false
@ -10,15 +8,14 @@ env:
- Wlexical=t - Wlexical=t
- Werror=t - Werror=t
- tests_Werror=t # For yasnippet-tests.el - tests_Werror=t # For yasnippet-tests.el
jobs: matrix:
- EMACS_VERSION=23.4 - EMACS_VERSION=23.4
# 24.3 gives a bunch of 'value returned from (car value-N) is # 24.3 gives a bunch of 'value returned from (car value-N) is
# unused' warnings. # unused' warnings.
- EMACS_VERSION=24.3 tests_Werror=nil - EMACS_VERSION=24.3 tests_Werror=nil
- EMACS_VERSION=24.5 - EMACS_VERSION=24.5
- EMACS_VERSION=25.3 - EMACS_VERSION=25.3
- EMACS_VERSION=26.3 - EMACS_VERSION=26-prerelease
- EMACS_VERSION=27-prerelease
install: install:

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

11
NEWS
View File

@ -1,17 +1,8 @@
Yasnippet NEWS -- history of user-visible changes. Yasnippet NEWS -- history of user-visible changes.
Copyright (C) 2017-2025 Free Software Foundation, Inc. Copyright (C) 2017-2019 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) * 0.14.0 (Dec 22, 2019)
** Changes ** Changes

View File

@ -15,7 +15,7 @@ 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
@ -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
@ -75,6 +71,10 @@ get some!
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
@ -103,9 +103,8 @@ common problems and practical snippet examples.
The [Github issue tracker][issues] is where most YASnippet-related The [Github issue tracker][issues] is where most YASnippet-related
discussion happens. Nevertheless, since YASnippet is a part of Emacs, discussion happens. Nevertheless, since YASnippet is a part of Emacs,
you may alternatively report bugs to Emacs via `M-x report-emacs-bug` or you may alternatively report bugs to the main Emacs bug list,
sending an email to `bug-gnu-emacs@gnu.org`, putting "yasnippet" bug-gnu-emacs@gnu.org, putting "yasnippet" somewhere in the subject.
somewhere in the subject.
## Important note regarding bug reporting ## Important note regarding bug reporting
@ -161,8 +160,6 @@ Finally, thank you very much for using YASnippet!
[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
[gnudevel]: http://elpa.gnu.org/devel/yasnippet.html
[yasmate]: http://github.com/joaotavora/yasmate [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

130
Rakefile Normal file
View File

@ -0,0 +1,130 @@
# -*- 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 "run test in interactive mode"
task :itests do
sh "#{$EMACS} -Q -L . -l yasnippet-tests.el" +
" --eval \"(call-interactively 'ert)\""
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
# rake doc[../htmlize]
#
# To do this interactively, load doc/yas-doc-helper, open one of the
# org files, and do `C-c C-e P'.
desc "Generate document"
task :doc, [:htmlize] do |t, args|
load_path = '-L .'
if args[:htmlize]
load_path += " -L #{args[:htmlize]}"
end
sh "#{$EMACS} -Q #{load_path} --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 describe`.chomp()
expRev = IO.read('doc/html-revision').chomp()
if curRev != expRev
raise ("The HTML rev: #{expRev},\n" +
"current rev: #{curRev}!\n")
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|
cmdline = $EMACS + ' --batch -L .'
if ENV['warnings']
cmdline += " --eval \"(setq byte-compile-warnings #{ENV['warnings']})\""
end
if ENV['Werror']
cmdline += " --eval \"(setq byte-compile-error-on-warn #{ENV['Werror']})\""
end
if ENV['Wlexical']
cmdline += " --eval \"(setq byte-compile-force-lexical-warnings #{ENV['Wlexical']})\""
end
cmdline +=" -f batch-byte-compile #{t.source}"
sh cmdline
end
task :compile => FileList["yasnippet.el"].ext('elc')
task :compile_all => FileList["*.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

@ -141,7 +141,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.
@ -210,12 +210,11 @@ inside a comment? Set [[sym:yas-buffer-local-condition][=yas-buffer-local-condi
#+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-syntax-comment-or-string-p)
(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 for a snippet that you want to expand in comments, specify a
@ -228,7 +227,7 @@ For the full set of possible conditions, see the documentation for
** 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

@ -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,17 +25,12 @@
;;; 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:
(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) (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
@ -137,24 +132,24 @@
(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).
@ -199,7 +194,7 @@ But replace link to \"current\" page with a span element."
;;:with-broken-links mark ;;:with-broken-links mark
:html-postamble :html-postamble
,(concat "<hr><p class='creator'>Generated by %c from " ,(concat "<hr><p class='creator'>Generated by %c from "
rev " " date "</p>\n" (or rev yas--version) " " date "</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". (when rev ;; Rakefile :doc:upload uses "html-revision".

View File

@ -1,6 +1,6 @@
;;; yasnippet-debug.el --- debug functions for yasnippet -*- lexical-binding: t -*- ;;; yasnippet-debug.el --- debug functions for yasnippet -*- lexical-binding: t -*-
;; Copyright (C) 2010-2025 Free Software Foundation, Inc. ;; Copyright (C) 2010, 2013-2014, 2017-2018 Free Software Foundation, Inc.
;; Author: João Távora ;; Author: João Távora
;; Keywords: emulations, convenience ;; Keywords: emulations, convenience
@ -40,6 +40,9 @@
;; Don't require '-L <path>' when debugging. ;; Don't require '-L <path>' when debugging.
(expand-file-name "yasnippet" yas--loaddir))) (expand-file-name "yasnippet" yas--loaddir)))
(require 'cl-lib) (require 'cl-lib)
(eval-when-compile
(unless (fboundp 'cl-flet)
(defalias 'cl-flet 'flet)))
(require 'color nil t) (require 'color nil t)
(require 'edebug) (require 'edebug)
(eval-when-compile (eval-when-compile
@ -221,13 +224,13 @@
(setq yas-debug-undo value) (setq yas-debug-undo value)
(yas--message 3 "debug undo %sabled" (if yas-debug-undo "en" "dis"))) (yas--message 3 "debug undo %sabled" (if yas-debug-undo "en" "dis")))
(defun yas-debug--target-snippet (snippet) (defadvice yas--snippet-parse-create (before yas-debug-target-snippet (snippet))
(add-to-list 'yas-debug-target-snippets snippet)) (add-to-list 'yas-debug-target-snippets snippet))
(defun yas-debug--untarget-snippet (snippet) (defadvice yas--commit-snippet (after yas-debug-untarget-snippet (snippet))
(setq yas-debug-target-snippets (setq yas-debug-target-snippets
(remq snippet yas-debug-target-snippets)) (remq snippet yas-debug-target-snippets))
(maphash (lambda (_k color-ov) (maphash (lambda (k color-ov)
(delete-overlay (cdr color-ov))) (delete-overlay (cdr color-ov)))
yas-debug-live-indicators) yas-debug-live-indicators)
(clrhash yas-debug-live-indicators)) (clrhash yas-debug-live-indicators))
@ -268,8 +271,10 @@ buffer-locally, otherwise install it globally. If HOOK is
do (printf "%S\n" undo-elem)))) do (printf "%S\n" undo-elem))))
(when hook (when hook
(setq yas-debug-target-buffer (current-buffer)) (setq yas-debug-target-buffer (current-buffer))
(advice-add 'yas--snippet-parse-create :before #'yas-debug--target-snippet) (ad-enable-advice 'yas--snippet-parse-create 'before 'yas-debug-target-snippet)
(advice-add 'yas--commit-snippet :after #'yas-debug--untarget-snippet) (ad-activate 'yas--snippet-parse-create)
(ad-enable-advice 'yas--commit-snippet 'after 'yas-debug-untarget-snippet)
(ad-activate 'yas--commit-snippet)
(add-hook 'post-command-hook #'yas-debug-snippets (add-hook 'post-command-hook #'yas-debug-snippets
nil (eq hook 'snippet-navigation)) nil (eq hook 'snippet-navigation))
;; Window management is slapped together, it does what I ;; Window management is slapped together, it does what I

View File

@ -1,8 +1,8 @@
;;; yasnippet-tests.el --- some yasnippet tests -*- lexical-binding: t -*- ;;; yasnippet-tests.el --- some yasnippet tests -*- lexical-binding: t -*-
;; Copyright (C) 2012-2025 Free Software Foundation, Inc. ;; Copyright (C) 2012-2015, 2017-2018 Free Software Foundation, Inc.
;; Author: João Távora <joaot@siscog.pt> ;; Author: João Távora <joaot@siscog.pt>
;; 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
@ -121,8 +121,7 @@ This lets `yas--maybe-expand-from-keymap-filter' work as expected."
(funcall fn) (funcall fn)
(cl-loop for var in vars (cl-loop for var in vars
for saved in saved-values for saved in saved-values
do (unless (eq (symbol-value var) saved) ;Beware read-only vars! do (set var saved)))))
(set var saved))))))
(defun yas-call-with-snippet-dirs (dirs fn) (defun yas-call-with-snippet-dirs (dirs fn)
(let* ((default-directory (make-temp-file "yasnippet-fixture" t)) (let* ((default-directory (make-temp-file "yasnippet-fixture" t))
@ -137,6 +136,20 @@ This lets `yas--maybe-expand-from-keymap-filter' work as expected."
;;; Older emacsen ;;; Older emacsen
;;; ;;;
(unless (fboundp 'special-mode)
;; FIXME: Why provide this default definition here?!?
(defalias 'special-mode 'fundamental))
(unless (fboundp 'string-suffix-p)
;; introduced in Emacs 24.4
(defun string-suffix-p (suffix string &optional ignore-case)
"Return non-nil if SUFFIX is a suffix of STRING.
If IGNORE-CASE is non-nil, the comparison is done without paying
attention to case differences."
(let ((start-pos (- (length string) (length suffix))))
(and (>= start-pos 0)
(eq t (compare-strings suffix nil nil
string start-pos nil ignore-case))))))
;;; Snippet mechanics ;;; Snippet mechanics
@ -543,19 +556,16 @@ XXXXX ------------------------"))))
(yas-mock-insert "foo bar") (yas-mock-insert "foo bar")
(ert-simulate-command '(yas-next-field)) (ert-simulate-command '(yas-next-field))
(goto-char (point-min)) (goto-char (point-min))
;; The default value of `org-adapt-indentation' changed between Org-mode 9.4 (let ((expected (with-temp-buffer
;; and 9.5, so force a specific value. (insert (format (concat "* Test foo bar\n"
(let* ((org-adapt-indentation nil) " " org-property-format "\n"
(expected (with-temp-buffer " " org-property-format "\n"
(insert (format (concat "* Test foo bar\n" " " org-property-format)
org-property-format "\n" ":PROPERTIES:" ""
org-property-format "\n" ":ID:" "foo bar-after"
org-property-format) ":END:" ""))
":PROPERTIES:" "" (delete-trailing-whitespace)
":ID:" "foo bar-after" (buffer-string))))
":END:" ""))
(delete-trailing-whitespace)
(buffer-string))))
;; Some org-mode versions leave trailing whitespace, some don't. ;; Some org-mode versions leave trailing whitespace, some don't.
(delete-trailing-whitespace) (delete-trailing-whitespace)
(should (equal expected (buffer-string)))))) (should (equal expected (buffer-string))))))
@ -700,7 +710,7 @@ mapconcat #'(lambda (arg)
;;; Snippet expansion and character escaping ;;; Snippet expansion and character escaping
;; Thanks to @zw963 (Billy) for the testing ;;; Thanks to @zw963 (Billy) for the testing
;;; ;;;
(ert-deftest escape-dollar () (ert-deftest escape-dollar ()
(with-temp-buffer (with-temp-buffer
@ -837,7 +847,7 @@ mapconcat #'(lambda (arg)
;; See https://github.com/joaotavora/yasnippet/issues/800. ;; See https://github.com/joaotavora/yasnippet/issues/800.
(with-temp-buffer (with-temp-buffer
(yas-minor-mode 1) (yas-minor-mode 1)
(yas-expand-snippet "```foo\n\n```") (should-error (yas-expand-snippet "```foo\n\n```"))
(erase-buffer) ; Bad snippet may leave wrong text. (erase-buffer) ; Bad snippet may leave wrong text.
;; But expanding the corrected snippet should work fine. ;; But expanding the corrected snippet should work fine.
(yas-expand-snippet "\\`\\`\\`foo\n\n\\`\\`\\`") (yas-expand-snippet "\\`\\`\\`foo\n\n\\`\\`\\`")
@ -845,8 +855,6 @@ mapconcat #'(lambda (arg)
(defmacro yas--with-font-locked-temp-buffer (&rest body) (defmacro yas--with-font-locked-temp-buffer (&rest body)
"Like `with-temp-buffer', but ensure `font-lock-mode'." "Like `with-temp-buffer', but ensure `font-lock-mode'."
;; NOTE: Replace all uses of this with `font-lock-ensure' when we
;; drop support for Emacs 24.
(declare (indent 0) (debug t)) (declare (indent 0) (debug t))
(let ((temp-buffer (make-symbol "temp-buffer"))) (let ((temp-buffer (make-symbol "temp-buffer")))
;; NOTE: buffer name must not start with a space, otherwise ;; NOTE: buffer name must not start with a space, otherwise
@ -866,8 +874,6 @@ mapconcat #'(lambda (arg)
(kill-buffer ,temp-buffer)))))))) (kill-buffer ,temp-buffer))))))))
(ert-deftest example-for-issue-474 () (ert-deftest example-for-issue-474 ()
;; This issue only reproduces in Emacs 24.3, most likely due to some
;; bug in the cc-mode included with that Emacs version.
(yas--with-font-locked-temp-buffer (yas--with-font-locked-temp-buffer
(c-mode) (c-mode)
(yas-minor-mode 1) (yas-minor-mode 1)
@ -941,18 +947,6 @@ mapconcat #'(lambda (arg)
(yas-mock-insert "baz") (yas-mock-insert "baz")
(should (string= (yas--buffer-contents) "foobaaarbazok"))))) (should (string= (yas--buffer-contents) "foobaaarbazok")))))
(ert-deftest yas-escaping-close-brace ()
"Close braces may be escaped with braces, reduction from eglot issue.
See https://github.com/joaotavora/eglot/issues/336."
(with-temp-buffer
(yas-minor-mode +1)
;; NOTE: put a period at the end to avoid the bug tested by
;; `protection-overlay-no-cheating'.
(yas-expand-snippet "${1:one{\\}}, ${2:two{\\}}.")
(yas-next-field)
(yas-next-field)
(should (string= (buffer-string) "one{}, two{}."))))
;;; Misc tests ;;; Misc tests
;;; ;;;
@ -1105,24 +1099,6 @@ hello ${1:$(when (stringp yas-text) (funcall func yas-text))} foo${1:$$(concat \
(should (= (length (yas--snippet-fields (nth 0 snippets))) 2)) (should (= (length (yas--snippet-fields (nth 0 snippets))) 2))
(should (= (length (yas--snippet-fields (nth 1 snippets))) 1)))))) (should (= (length (yas--snippet-fields (nth 1 snippets))) 1))))))
(ert-deftest nested-snippet-expansion-depth-2 ()
(with-temp-buffer
(yas-with-snippet-dirs
'((".emacs.d/snippets"
("text-mode"
("nest" . "( $1"))))
(let ((yas-triggers-in-field t))
(yas-reload-all)
(text-mode)
(yas-minor-mode +1)
(dotimes (_ 3)
(yas-mock-insert "nest")
(ert-simulate-command '(yas-expand)))
(dotimes (_ 3)
(yas-mock-insert ")")
(ert-simulate-command '(yas-next-field-or-maybe-expand)))
))))
(ert-deftest nested-snippet-expansion-2 () (ert-deftest nested-snippet-expansion-2 ()
(let ((yas-triggers-in-field t)) (let ((yas-triggers-in-field t))
(yas-with-snippet-dirs (yas-with-snippet-dirs
@ -1216,17 +1192,14 @@ hello ${1:$(when (stringp yas-text) (funcall func yas-text))} foo${1:$$(concat \
(defmacro yas-with-overriden-buffer-list (&rest body) (defmacro yas-with-overriden-buffer-list (&rest body)
(declare (debug t)) (declare (debug t))
;; FIXME: This macro was added by commit 185c771dedea as part of the
;; fix for https://github.com/joaotavora/yasnippet/issues/253,
;; but I don't know why it was/is needed.
(let ((saved-sym (make-symbol "yas--buffer-list"))) (let ((saved-sym (make-symbol "yas--buffer-list")))
`(let ((,saved-sym (symbol-function 'buffer-list))) `(let ((,saved-sym (symbol-function 'buffer-list)))
(cl-letf (((symbol-function 'buffer-list) (cl-letf (((symbol-function 'buffer-list)
(lambda (&rest args) (lambda ()
(cl-remove-if (lambda (buf) (cl-remove-if (lambda (buf)
(with-current-buffer buf (with-current-buffer buf
(eq major-mode 'lisp-interaction-mode))) (eq major-mode 'lisp-interaction-mode)))
(apply ,saved-sym args))))) (funcall ,saved-sym)))))
,@body)))) ,@body))))
@ -1305,7 +1278,7 @@ hello ${1:$(when (stringp yas-text) (funcall func yas-text))} foo${1:$$(concat \
(yas-minor-mode +1) (yas-minor-mode +1)
(should (equal (yas--template-content (yas-lookup-snippet "one")) (should (equal (yas--template-content (yas-lookup-snippet "one"))
"one")) "one"))
(should (eq (yas--key-binding "\C-c1") #'yas-expand-from-keymap)) (should (eq (yas--key-binding "\C-c1") 'yas-expand-from-keymap))
(yas-define-snippets (yas-define-snippets
'text-mode '(("_1" "one!" "won" nil nil nil nil nil "uuid-1"))) 'text-mode '(("_1" "one!" "won" nil nil nil nil nil "uuid-1")))
(should (null (yas-lookup-snippet "one" nil 'noerror))) (should (null (yas-lookup-snippet "one" nil 'noerror)))
@ -1379,14 +1352,14 @@ hello ${1:$(when (stringp yas-text) (funcall func yas-text))} foo${1:$$(concat \
yet-another-c-mode yet-another-c-mode
and-also-this-one and-also-this-one
and-that-one and-that-one
prog-mode ;; prog-mode doesn't exist in emacs 23.4
,@(if (fboundp 'lisp-data-mode) ;Emacs≥28 ,@(if (fboundp 'prog-mode)
'(lisp-data-mode)) '(prog-mode))
emacs-lisp-mode emacs-lisp-mode
lisp-interaction-mode)) lisp-interaction-mode))
(observed (yas--modes-to-activate))) (observed (yas--modes-to-activate)))
(should (equal major-mode (car observed))) (should (equal major-mode (car observed)))
(should-not (cl-set-exclusive-or expected observed))))))) (should (equal (sort expected #'string<) (sort observed #'string<))))))))
(ert-deftest extra-modes-parenthood () (ert-deftest extra-modes-parenthood ()
"Test activation of parents of `yas--extra-modes'." "Test activation of parents of `yas--extra-modes'."
@ -1403,44 +1376,40 @@ hello ${1:$(when (stringp yas-text) (funcall func yas-text))} foo${1:$$(concat \
(yas-activate-extra-mode 'and-that-one) (yas-activate-extra-mode 'and-that-one)
(let* ((expected-first `(and-that-one (let* ((expected-first `(and-that-one
yet-another-c-mode yet-another-c-mode
c-mode)) c-mode
,major-mode))
(expected-rest `(cc-mode (expected-rest `(cc-mode
prog-mode ;; prog-mode doesn't exist in emacs 23.4
,@(if (fboundp 'lisp-data-mode) ;Emacs≥28 ,@(if (fboundp 'prog-mode)
'(lisp-data-mode)) '(prog-mode))
emacs-lisp-mode emacs-lisp-mode
and-also-this-one and-also-this-one
lisp-interaction-mode)) lisp-interaction-mode))
(observed (remq 'fundamental-mode (yas--modes-to-activate)))) (observed (yas--modes-to-activate)))
(should-not (cl-set-exclusive-or (should (equal expected-first
expected-first (cl-subseq observed 0 (length expected-first))))
(cl-subseq observed 0 (length expected-first)))) (should (equal (sort expected-rest #'string<)
(should-not (cl-set-exclusive-or (sort (cl-subseq observed (length expected-first)) #'string<))))))))
expected-rest
(cl-subseq observed (length expected-first)))))))))
(defalias 'yas--phony-c-mode #'c-mode) (defalias 'yas--phony-c-mode 'c-mode)
(ert-deftest issue-492-and-494 () (ert-deftest issue-492-and-494 ()
"Aliases like `yas--phony-c-mode' should be considered as \"derived\"."
(define-derived-mode yas--test-mode yas--phony-c-mode "Just a test mode") (define-derived-mode yas--test-mode yas--phony-c-mode "Just a test mode")
(yas-with-snippet-dirs '((".emacs.d/snippets" (yas-with-snippet-dirs '((".emacs.d/snippets"
("yas--test-mode"))) ("yas--test-mode")))
(yas-reload-all) (yas-reload-all)
(with-temp-buffer (with-temp-buffer
(let* ((major-mode 'yas--test-mode) (let* ((major-mode 'yas--test-mode)
(expected `(fundamental-mode (expected `(fundamental-mode
c-mode c-mode
yas--phony-c-mode ,@(if (fboundp 'prog-mode)
yas--test-mode)) '(prog-mode))
;; The set of mode depends on some external factors: yas--phony-c-mode
;; `prog-mode': if cc-mode.el has been loaded. yas--test-mode))
;; `cc-mode': if we added `cc-mode' as yas--parent of `c-mode'. (observed (yas--modes-to-activate)))
(observed (cl-set-difference (yas--modes-to-activate) (should (null (cl-set-exclusive-or expected observed)))
'(prog-mode cc-mode)))) (should (= (length expected)
(should-not (cl-set-exclusive-or expected observed)) (length observed)))))))
(should (= (length expected)
(length observed)))))))
(define-derived-mode yas--test-mode c-mode "Just a test mode") (define-derived-mode yas--test-mode c-mode "Just a test mode")
(define-derived-mode yas--another-test-mode c-mode "Another test mode") (define-derived-mode yas--another-test-mode c-mode "Another test mode")
@ -1644,31 +1613,31 @@ TODO: be meaner"
(with-temp-buffer (with-temp-buffer
(yas-minor-mode -1) (yas-minor-mode -1)
(insert "foo") (insert "foo")
(should-not (eq (key-binding (kbd "TAB")) #'yas-expand)) (should (not (eq (key-binding (yas--read-keybinding "<tab>")) 'yas-expand)))
(yas-minor-mode 1) (yas-minor-mode 1)
(should (eq (key-binding (kbd "TAB")) #'yas-expand)) (should (eq (key-binding (yas--read-keybinding "<tab>")) 'yas-expand))
(yas-expand-snippet "$1 $2 $3") (yas-expand-snippet "$1 $2 $3")
;; (should (eq (key-binding [tab]) #'yas-next-field-or-maybe-expand)) (should (eq (key-binding [(tab)]) 'yas-next-field-or-maybe-expand))
(should (eq (key-binding (kbd "TAB")) #'yas-next-field-or-maybe-expand)) (should (eq (key-binding (kbd "TAB")) 'yas-next-field-or-maybe-expand))
(should (eq (key-binding [(shift tab)]) #'yas-prev-field)) (should (eq (key-binding [(shift tab)]) 'yas-prev-field))
(should (eq (key-binding [backtab]) #'yas-prev-field)))))) (should (eq (key-binding [backtab]) 'yas-prev-field))))))
(ert-deftest test-rebindings () (ert-deftest test-rebindings ()
(let* ((test-map (make-composed-keymap nil yas-minor-mode-map)) (let* ((yas-minor-mode-map (copy-keymap yas-minor-mode-map))
(minor-mode-map-alist (minor-mode-map-alist
(cons `(yas-minor-mode . ,test-map) (cons `(yas-minor-mode . ,yas-minor-mode-map)
(cl-remove 'yas-minor-mode minor-mode-map-alist (cl-remove 'yas-minor-mode minor-mode-map-alist
:test #'eq :key #'car)))) :test #'eq :key #'car))))
(define-key test-map [tab] nil) (define-key yas-minor-mode-map [tab] nil)
(define-key test-map (kbd "TAB") nil) (define-key yas-minor-mode-map (kbd "TAB") nil)
(define-key test-map (kbd "SPC") #'yas-expand) (define-key yas-minor-mode-map (kbd "SPC") 'yas-expand)
(with-temp-buffer (with-temp-buffer
(yas-minor-mode 1) (yas-minor-mode 1)
(should-not (eq (key-binding (kbd "TAB")) #'yas-expand)) (should-not (eq (key-binding (kbd "TAB")) 'yas-expand))
(should (eq (key-binding (kbd "SPC")) #'yas-expand)) (should (eq (key-binding (kbd "SPC")) 'yas-expand))
(yas-reload-all) (yas-reload-all)
(should-not (eq (key-binding (kbd "TAB")) #'yas-expand)) (should-not (eq (key-binding (kbd "TAB")) 'yas-expand))
(should (eq (key-binding (kbd "SPC")) #'yas-expand))))) (should (eq (key-binding (kbd "SPC")) 'yas-expand)))))
(ert-deftest test-yas-in-org () (ert-deftest test-yas-in-org ()
(yas-saving-variables (yas-saving-variables
@ -1681,18 +1650,16 @@ TODO: be meaner"
(org-mode) (org-mode)
(yas-minor-mode 1) (yas-minor-mode 1)
(insert "foo") (insert "foo")
;; (should (eq (key-binding [tab]) #'yas-expand)) (should (eq (key-binding [(tab)]) 'yas-expand))
(should (eq (key-binding (kbd "TAB")) #'yas-expand)))))) (should (eq (key-binding (kbd "TAB")) 'yas-expand))))))
(ert-deftest yas-org-native-tab-in-source-block-text () (ert-deftest yas-org-native-tab-in-source-block-text ()
"Test expansion of snippets in org source blocks." "Test expansion of snippets in org source blocks."
;; org 9+ no longer runs fontification for text-mode, so our hacks ;; org 9+ no longer runs fontification for text-mode, so our hacks
;; don't work. Note that old ert doesn't have skipping, so we have ;; don't work. Note that old ert doesn't have skipping, so we have
;; to expect failure instead. Starting with Org-mode 9.5 this seems ;; to expect failure instead.
;; to work again.
:expected-result (if (and (fboundp 'org-in-src-block-p) :expected-result (if (and (fboundp 'org-in-src-block-p)
(or (version< (org-version) "9") (version< (org-version) "9"))
(version<= "9.5" (org-version))))
:passed :failed) :passed :failed)
(let ((text-mode-hook #'yas-minor-mode)) (let ((text-mode-hook #'yas-minor-mode))
(do-yas-org-native-tab-in-source-block "text"))) (do-yas-org-native-tab-in-source-block "text")))
@ -1724,7 +1691,7 @@ TODO: be meaner"
(org-mode) (org-mode)
(yas-minor-mode 1) (yas-minor-mode 1)
(insert "#+BEGIN_SRC " mode "\nT\n#+END_SRC") (insert "#+BEGIN_SRC " mode "\nT\n#+END_SRC")
(if (fboundp 'font-lock-ensure) ;Emacs≥25 (if (fboundp 'font-lock-ensure)
(font-lock-ensure) (font-lock-ensure)
(jit-lock-fontify-now)) (jit-lock-fontify-now))
(re-search-backward "^T$") (goto-char (match-end 0)) (re-search-backward "^T$") (goto-char (match-end 0))

File diff suppressed because it is too large Load Diff