Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'jit-loading', implementing #160.

  • Loading branch information...
commit 6d416253ac949accad0b468600cb2aaf073afb3b 2 parents 7bf1517 + fcb4dfe
@capitaomorte capitaomorte authored
Showing with 304 additions and 221 deletions.
  1. +93 −29 yasnippet-tests.el
  2. +211 −192 yasnippet.el
View
122 yasnippet-tests.el
@@ -20,7 +20,7 @@
;;; Commentary:
-;; Attempt to test basic snippet mechanics and the loading system
+;; Test basic snippet mechanics and the loading system
;;; Code:
@@ -29,6 +29,7 @@
(require 'ert-x)
+
;;; Snippet mechanics
(ert-deftest field-navigation ()
@@ -111,34 +112,84 @@ TODO: correct this bug!"
;;; Loading
;;;
-(ert-deftest basic-loading ()
+(defmacro with-some-interesting-snippet-dirs (&rest body)
+ `(yas/saving-variables
+ (with-snippet-dirs
+ '((".emacs.d/snippets"
+ ("c-mode"
+ (".yas-parents" . "cc-mode")
+ ("printf" . "printf($1);"))
+ ("emacs-lisp-mode" ("ert-deftest" . "(ert-deftest ${1:name} () $0)"))
+ ("lisp-interaction-mode" (".yas-parents" . "emacs-lisp-mode")))
+ ("library/snippets"
+ ("c-mode" (".yas-parents" . "c++-mode"))
+ ("cc-mode" ("def" . "# define"))
+ ("emacs-lisp-mode" ("dolist" . "(dolist)"))
+ ("lisp-interaction-mode" ("sc" . "brother from another mother"))))
+ ,@body)))
+
+(ert-deftest basic-jit-loading ()
"Test basic loading and expansion of snippets"
- (yas/saving-variables
- (with-snippet-dirs
- '((".emacs.d/snippets"
- ("c-mode"
- (".yas-parents" . "cc-mode")
- ("printf" . "printf($1);"))
- ("emacs-lisp-mode" ("ert-deftest" . "(ert-deftest ${1:name} () $0)"))
- ("lisp-interaction-mode" (".yas-parents" . "emacs-lisp-mode")))
- ("library/snippets"
- ("c-mode" (".yas-parents" . "c++-mode"))
- ("cc-mode" ("def" . "# define"))
- ("emacs-lisp-mode" ("dolist" . "(dolist)"))
- ("lisp-interaction-mode" ("sc" . "brother from another mother"))))
- (yas/reload-all)
- (with-temp-buffer
- (lisp-interaction-mode)
- (yas/minor-mode 1)
- (insert "sc")
- (ert-simulate-command '(yas/expand))
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- "brother from another mother"))))))
-
+ (with-some-interesting-snippet-dirs
+ (yas/reload-all)
+ (yas/basic-jit-loading-1)))
+(ert-deftest basic-jit-loading-with-compiled-snippets ()
+ "Test basic loading and expansion of snippets"
+ (with-some-interesting-snippet-dirs
+ (yas/reload-all)
+ (yas/recompile-all)
+ (flet ((yas/load-directory-2
+ (&rest dummies)
+ (ert-fail "yas/load-directory-2 shouldn't be called when snippets have been compiled")))
+ (yas/reload-all)
+ (yas/basic-jit-loading-1))))
+
+(defun yas/basic-jit-loading-1 (&optional compile)
+ (with-temp-buffer
+ (should (= 4 (hash-table-count yas/scheduled-jit-loads)))
+ (should (= 0 (hash-table-count yas/tables)))
+ (lisp-interaction-mode)
+ (yas/minor-mode 1)
+ (should (= 2 (hash-table-count yas/scheduled-jit-loads)))
+ (should (= 2 (hash-table-count yas/tables)))
+ (should (= 1 (hash-table-count (yas/table-uuidhash (gethash 'lisp-interaction-mode yas/tables)))))
+ (should (= 2 (hash-table-count (yas/table-uuidhash (gethash 'emacs-lisp-mode yas/tables)))))
+ (yas/should-expand '(("sc" . "brother from another mother")
+ ("dolist" . "(dolist)")
+ ("ert-deftest" . "(ert-deftest name () )")))
+ (c-mode)
+ (yas/minor-mode 1)
+ (should (= 0 (hash-table-count yas/scheduled-jit-loads)))
+ (should (= 4 (hash-table-count yas/tables)))
+ (should (= 1 (hash-table-count (yas/table-uuidhash (gethash 'c-mode yas/tables)))))
+ (should (= 1 (hash-table-count (yas/table-uuidhash (gethash 'cc-mode yas/tables)))))
+ (yas/should-expand '(("printf" . "printf();")
+ ("def" . "# define")))
+ (yas/should-not-expand '("sc" "dolist" "ert-deftest"))))
;;; Helpers
-;;;
+;;;
+
+(defun yas/should-expand (keys-and-expansions)
+ (dolist (key-and-expansion keys-and-expansions)
+ (yas/exit-all-snippets)
+ (erase-buffer)
+ (insert (car key-and-expansion))
+ (let ((yas/fallback-behavior nil))
+ (ert-simulate-command '(yas/expand)))
+ (should (string= (buffer-substring-no-properties (point-min) (point-max))
+ (cdr key-and-expansion))))
+ (yas/exit-all-snippets))
+
+(defun yas/should-not-expand (keys)
+ (dolist (key keys)
+ (yas/exit-all-snippets)
+ (erase-buffer)
+ (insert key)
+ (let ((yas/fallback-behavior nil))
+ (ert-simulate-command '(yas/expand)))
+ (should (string= (buffer-substring-no-properties (point-min) (point-max)) key))))
(defun yas/mock-insert (string)
(interactive)
@@ -157,7 +208,7 @@ TODO: correct this bug!"
(with-current-buffer (find-file file-or-dir-name)
(insert content)
(save-buffer)
- (kill-buffer)))
+ (kill-buffer (current-buffer))))
(t
(message "[yas] oops don't know this content")))))
@@ -179,10 +230,23 @@ TODO: correct this bug!"
(defmacro with-snippet-dirs (dirs &rest body)
`(let ((default-directory (make-temp-file "yasnippet-fixture" t)))
- (setq yas/snippet-dirs ',(mapcar #'car (cadr dirs)))
- (mapc #'yas/make-file-or-dirs ,dirs)
- ,@body))
+ (unwind-protect
+ (progn
+ (setq yas/snippet-dirs ',(mapcar #'car (cadr dirs)))
+ (mapc #'yas/make-file-or-dirs ,dirs)
+ ,@body)
+ (when (>= emacs-major-version 23)
+ (delete-directory default-directory 'recursive)))))
+
+;;; Older emacsen
+;;;
+(unless (fboundp 'special-mode)
+ (define-minor-mode special-mode "Just a placeholder for something isn't in emacs 22"))
+;;; btw to test this in emacs22 mac osx:
+;;; curl -L -O https://github.com/mirrors/emacs/raw/master/lisp/emacs-lisp/ert.el
+;;; curl -L -O https://github.com/mirrors/emacs/raw/master/lisp/emacs-lisp/ert-x.el
+;;; /usr/bin/emacs -nw -Q -L . -l yasnippet-tests.el --batch -e ert
(provide 'yasnippet-tests)
;;; yasnippet-tests.el ends here
View
403 yasnippet.el
@@ -181,6 +181,7 @@ as the default for storing the user's new snippets."
(equal old new))
(yas/reload-all)))))
(defun yas/snippet-dirs ()
+ "Returns `yas/snippet-dirs' (which see) as a list."
(if (listp yas/snippet-dirs) yas/snippet-dirs (list yas/snippet-dirs)))
(defvaralias 'yas/root-directory 'yas/snippet-dirs)
@@ -721,42 +722,55 @@ With optional UNBIND-KEY, try to unbind that key from
(define-key yas/minor-mode-map (read-kbd-macro yas/trigger-key) 'yas/expand)))
(defvar yas/tables (make-hash-table)
- "A hash table of MAJOR-MODE symbols to `yas/table' objects.")
+ "A hash table of mode symbols to `yas/table' objects.")
+
+(defvar yas/parents (make-hash-table)
+ "A hash table of mode symbols do lists of direct parent mode symbols.
+
+This list is populated when reading the \".yas-parents\" files
+found when traversing snippet directories with
+`yas/load-directory'.
+
+There might be additionalal parenting information stored in the
+`derived-mode-parent' property of some mode symbols, but that is
+not recorded here.")
(defvar yas/direct-keymaps (list)
"Keymap alist supporting direct snippet keybindings.
-This variable is is placed `emulation-mode-map-alists'.
+This variable is is placed in `emulation-mode-map-alists'.
-Its elements looks like (TABLE-NAME . KEYMAP) and are
-calculated when loading snippets. TABLE-NAME is a variable
-set buffer-locally when entering `yas/minor-mode'. KEYMAP binds
-all defined direct keybindings to the command
-`yas/expand-from-keymap', which acts similarly to `yas/expand'")
+Its elements looks like (TABLE-NAME . KEYMAP). They're
+instantiated on `yas/reload-all' but KEYMAP is added to only when
+loading snippets. `yas//direct-TABLE-NAME' is then a variable set
+buffer-locally when entering `yas/minor-mode'. KEYMAP binds all
+defined direct keybindings to the command
+`yas/expand-from-keymap' which then which snippet to expand.")
(defun yas/direct-keymaps-reload ()
"Force reload the direct keybinding for active snippet tables."
(interactive)
(setq yas/direct-keymaps nil)
(maphash #'(lambda (name table)
- (mapc #'(lambda (table)
- (push (cons (intern (format "yas//direct-%s" name))
- (yas/table-direct-keymap table))
- yas/direct-keymaps))
- (cons table (yas/table-get-all-parents table))))
+ (push (cons (intern (format "yas//direct-%s" name))
+ (yas/table-direct-keymap table))
+ yas/direct-keymaps))
yas/tables))
-(defun yas/direct-keymaps-set-vars ()
+(defun yas/modes-to-activate ()
+ "Compute list of mode symbols that are active for `yas/expand'
+and friends."
(let ((modes-to-activate (list major-mode))
(mode major-mode))
(while (setq mode (get mode 'derived-mode-parent))
(push mode modes-to-activate))
(dolist (mode (yas/extra-modes))
(push mode modes-to-activate))
- (dolist (mode modes-to-activate)
- (let ((name (intern (format "yas//direct-%s" mode))))
- (set-default name nil)
- (set (make-local-variable name) t)))))
+ (remove-duplicates
+ (append modes-to-activate
+ (mapcan #'(lambda (mode)
+ (yas/all-parents mode))
+ modes-to-activate)))))
(defvar yas/minor-mode-hook nil
"Hook run when yas/minor-mode is turned on")
@@ -793,16 +807,21 @@ Key bindings:
;;
(add-hook 'emulation-mode-map-alists 'yas/direct-keymaps)
(add-hook 'post-command-hook 'yas/post-command-handler nil t)
- (add-hook 'yas/minor-mode-hook 'yas/direct-keymaps-set-vars-runonce 'append))
+ ;; Set the `yas//direct-%s' vars for direct keymap expansion
+ ;;
+ (dolist (mode (yas/modes-to-activate))
+ (let ((name (intern (format "yas//direct-%s" mode))))
+ (set-default name nil)
+ (set (make-local-variable name) t)))
+ ;; Perform JIT loads
+ ;;
+ (yas/load-pending-jits))
(t
;; Uninstall the direct keymaps and the post-command hook
;;
(remove-hook 'post-command-hook 'yas/post-command-handler t)
(remove-hook 'emulation-mode-map-alists 'yas/direct-keymaps))))
-(defun yas/direct-keymaps-set-vars-runonce ()
- (yas/direct-keymaps-set-vars)
- (remove-hook 'yas/minor-mode-hook 'yas/direct-keymaps-set-vars-runonce))
(defvar yas/dont-activate nil
"If non-nil don't let `yas/minor-mode-on' active yas for this buffer.
@@ -831,10 +850,15 @@ Do this unless `yas/dont-activate' is truish "
:group 'yasnippet
:require 'yasnippet)
-(add-hook 'yas/global-mode-hook 'yas/reload-all-maybe)
-(defun yas/reload-all-maybe ()
- (if yas/global-mode
- (yas/reload-all)))
+(defadvice yas/global-mode (before yas/reload-with-jit (arg) activate)
+ (cond ((and arg
+ (numberp arg)
+ (> arg 1))
+ ;; explicitly enabling
+ (yas/reload-all 'with-jit))
+ ((not yas/global-mode)
+ ;; toggling
+ (yas/reload-all 'with-jit))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Major mode stuff
@@ -933,11 +957,6 @@ Has the following fields:
another hash of (NAME . TEMPLATE) where NAME is the snippet's
name and TEMPLATE is a `yas/template' object.
-`yas/table-parents'
-
- A list of tables considered parents of this table: i.e. when
- searching for expansions they are searched as well.
-
`yas/table-direct-keymap'
A keymap for the snippets in this table that have direct
@@ -1138,12 +1157,11 @@ conditions to filter out potential expansions."
(t
(eq requirement result)))))
-(defun yas/table-get-all-parents (table)
- "Returns a list of all parent tables of TABLE"
- (let ((parents (yas/table-parents table)))
- (when parents
- (append (copy-list parents)
- (mapcan #'yas/table-get-all-parents parents)))))
+(defun yas/all-parents (mode)
+ "Returns a list of all parent modes of MODE"
+ (let ((parents (gethash mode yas/parents)))
+ (append parents
+ (mapcan #'yas/all-parents parents))))
(defun yas/table-templates (table)
(when table
@@ -1267,11 +1285,7 @@ ensure your use `make-local-variable' when you set it.")
(defvaralias 'yas/mode-symbol 'yas/extra-modes)
(defun yas/table-get-create (mode)
- "Get the snippet table corresponding to MODE.
-
-Optional DIRECTORY gets recorded as the default directory to
-search for snippet files if the retrieved/created table didn't
-already have such a property."
+ "Get or create the snippet table corresponding to MODE."
(let ((table (gethash mode
yas/tables)))
(unless table
@@ -1281,31 +1295,15 @@ already have such a property."
(yas/table-direct-keymap table)))
table))
-(defun yas/get-snippet-tables (&optional mode-symbol dont-search-parents)
+(defun yas/get-snippet-tables ()
"Get snippet tables for current buffer.
-Return a list of 'yas/table' objects indexed by mode.
-
-The modes are tried in this order: optional MODE-SYMBOL, then
-`yas/extra-modes', then `major-mode' then, unless
-DONT-SEARCH-PARENTS is non-nil, the guessed parent mode of either
-MODE-SYMBOL or `major-mode'.
-
-Guessing is done by looking up the MODE-SYMBOL's
-`derived-mode-parent' property, see also `derived-mode-p'."
- (let ((mode-tables
- (remove nil
- (mapcar #'(lambda (mode)
- (gethash mode yas/tables))
- (remove nil (append (list mode-symbol)
- (yas/extra-modes)
- (list major-mode
- (and (not dont-search-parents)
- (get major-mode
- 'derived-mode-parent)))))))))
- (remove-duplicates
- (append mode-tables
- (mapcan #'yas/table-get-all-parents mode-tables)))))
+Return a list of `yas/table' objects. The list of modes to
+consider is returned by `yas/modes-to-activate'"
+ (remove nil
+ (mapcar #'(lambda (mode-name)
+ (gethash mode-name yas/tables))
+ (yas/modes-to-activate))))
(defun yas/menu-keymap-get-create (table)
"Get or create the main menu keymap correspondong to MODE.
@@ -1578,7 +1576,7 @@ TEMPLATES is a list of `yas/template'."
filtered-choices
chosen
d
- (completion-fn (or completion-fn
+ (completion-fn (or completion-fnn
#'completing-read)))
(dolist (choice choices)
(setq d (or (and display-fn (funcall display-fn choice))
@@ -1602,57 +1600,67 @@ TEMPLATES is a list of `yas/template'."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Loading snippets from files
;;
-(defun yas/load-directory-1 (directory mode-sym parents &optional no-compiled-snippets)
- "Recursively load snippet templates from DIRECTORY."
- (unless (file-exists-p (concat directory "/" ".yas-skip"))
- ;; Load .yas-setup.el files wherever we find them
- ;;
- (load (expand-file-name ".yas-setup" directory) 'noerror)
- (if (and (not no-compiled-snippets)
- (load (expand-file-name ".yas-compiled-snippets" directory) 'noerror))
- (message "Loading much faster .yas-compiled-snippets from %s" directory)
- (let* ((default-directory directory)
- (snippet-defs nil))
- ;; load the snippet files
- ;;
- (with-temp-buffer
- (dolist (file (yas/subdirs directory 'no-subdirs-just-files))
- (when (file-readable-p file)
- (insert-file-contents file nil nil nil t)
- (push (yas/parse-template file)
- snippet-defs))))
- (when (or snippet-defs
- (cdr major-mode-and-parents))
- (yas/define-snippets mode-sym
- snippet-defs
- parents))
- ;; now recurse to a lower level
- ;;
- (dolist (subdir (yas/subdirs directory))
- (yas/load-directory-1 subdir
- mode-sym
- parents
- t))))))
+(defun yas/load-yas-setup-file (file)
+ (load file 'noerror))
-(defun yas/load-directory (top-level-dir)
+(defun yas/load-directory (top-level-dir &optional nojit)
"Load snippet definition from directory hierarchy under TOP-LEVEL-DIR.
-Below TOP-LEVEL-DIR., each directory is a mode name."
+Below TOP-LEVEL-DIR each directory is a mode name."
(interactive "DSelect the root directory: ")
(unless (file-directory-p top-level-dir)
(error "%s is not a directory" top-level-dir))
(unless yas/snippet-dirs
(setq yas/snippet-dirs top-level-dir))
(dolist (dir (yas/subdirs top-level-dir))
- (let ((major-mode-and-parents (yas/compute-major-mode-and-parents
- (concat dir "/dummy"))))
- (yas/load-directory-1 dir
- (car major-mode-and-parents)
- (cdr major-mode-and-parents))))
+ (let* ((major-mode-and-parents (yas/compute-major-mode-and-parents
+ (concat dir "/dummy")))
+ (mode-sym (car major-mode-and-parents))
+ (parents (cdr major-mode-and-parents)))
+ (yas/define-parents mode-sym parents)
+ (let ((form `(yas/load-directory-1 ,dir
+ ',mode-sym
+ ',parents)))
+ (if (or (called-interactively-p)
+ nojit)
+ (eval form)
+ (yas/schedule-jit mode-sym form)))))
(when (interactive-p)
(yas/message 3 "Loaded snippets from %s." top-level-dir)))
-(defun yas/load-snippet-dirs ()
+(defun yas/load-directory-1 (directory mode-sym parents &optional no-compiled-snippets)
+ "Recursively load snippet templates from DIRECTORY."
+ (unless (file-exists-p (concat directory "/" ".yas-skip"))
+ (if (and (not no-compiled-snippets)
+ (load (expand-file-name ".yas-compiled-snippets" directory) 'noerror (<= yas/verbosity 2)))
+ (yas/message 2 "Loading much faster .yas-compiled-snippets from %s" directory)
+ (yas/load-directory-2 directory mode-sym parents))))
+
+(defun yas/load-directory-2 (directory mode-sym parents)
+ ;; Load .yas-setup.el files wherever we find them
+ ;;
+ (yas/load-yas-setup-file (expand-file-name ".yas-setup" directory))
+ (let* ((default-directory directory)
+ (snippet-defs nil))
+ ;; load the snippet files
+ ;;
+ (with-temp-buffer
+ (dolist (file (yas/subdirs directory 'no-subdirs-just-files))
+ (when (file-readable-p file)
+ (insert-file-contents file nil nil nil t)
+ (push (yas/parse-template file)
+ snippet-defs))))
+ (when snippet-defs
+ (yas/define-snippets mode-sym
+ snippet-defs))
+ ;; now recurse to a lower level
+ ;;
+ (dolist (subdir (yas/subdirs directory))
+ (yas/load-directory-2 subdir
+ mode-sym
+ nil))))
+
+(defun yas/load-snippet-dirs (&optional nojit)
"Reload the directories listed in `yas/snippet-dirs' or
prompt the user to select one."
(let (errors)
@@ -1660,21 +1668,26 @@ Below TOP-LEVEL-DIR., each directory is a mode name."
(dolist (directory (reverse (yas/snippet-dirs)))
(condition-case oops
(progn
- (yas/load-directory directory)
+ (yas/load-directory directory nojit)
(yas/message 3 "Loaded %s" directory))
(error (push oops errors)
(yas/message 3 "Check your `yas/snippet-dirs': %s" (second oops)))))
(call-interactively 'yas/load-directory))
errors))
-(defun yas/reload-all (&optional interactive)
+(defun yas/reload-all (&optional nojit)
"Reload all snippets and rebuild the YASnippet menu. "
(interactive "p")
(let ((errors))
- ;; Empty all snippet tables and all menu tables
+ ;; Empty all snippet tables, parenting info and all menu tables
;;
(setq yas/tables (make-hash-table))
+ (setq yas/parents (make-hash-table))
(setq yas/menu-table (make-hash-table))
+
+ ;; Cancel all pending 'yas/scheduled-jit-loads'
+ ;;
+ (setq yas/scheduled-jit-loads (make-hash-table))
;; Init the `yas/minor-mode-map', taking care not to break the
;; menu....
@@ -1685,7 +1698,7 @@ Below TOP-LEVEL-DIR., each directory is a mode name."
;; Reload the directories listed in `yas/snippet-dirs' or prompt
;; the user to select one.
;;
- (setq errors (yas/load-snippet-dirs))
+ (setq errors (yas/load-snippet-dirs nojit))
;; Reload the direct keybindings
;;
(yas/direct-keymaps-reload)
@@ -1694,6 +1707,18 @@ Below TOP-LEVEL-DIR., each directory is a mode name."
(yas/trigger-key-reload)
(yas/message 3 "Reloaded everything...%s." (if errors " (some errors, check *Messages*)" ""))))
+(defun yas/load-pending-jits ()
+ (when yas/minor-mode
+ (dolist (mode (yas/modes-to-activate))
+ (let ((forms (gethash mode yas/scheduled-jit-loads)))
+ (dolist (form forms)
+ (yas/message 3 "Loading snippets for %s, just in time: %s!" mode form)
+ (eval form))
+ (remhash mode yas/scheduled-jit-loads)))))
+
+;; (when (<= emacs-major-version 22)
+;; (add-hook 'after-change-major-mode-hook 'yas/load-pending-jits))
+
(defun yas/quote-string (string)
"Escape and quote STRING.
foo\"bar\\! -> \"foo\\\"bar\\\\!\""
@@ -1710,64 +1735,74 @@ foo\"bar\\! -> \"foo\\\"bar\\\\!\""
"For backward compatibility, enable `yas/minor-mode' globally"
(yas/global-mode 1))
-(defun yas/compile-top-level-dir (top-level-dir)
- "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR."
+(defun yas/compile-directory (top-level-dir)
+ "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR.
+
+This works by stubbing a few functions, then calling
+`yas/load-directory'."
(interactive "DTop level snippet directory?")
- (dolist (dir (yas/subdirs top-level-dir))
- (yas/compile-snippets dir)))
-
-(defun yas/compile-snippets (input-dir &optional output-file)
- "Compile snippets files in INPUT-DIR to OUTPUT-FILE file.
-
-Prompts for INPUT-DIR and OUTPUT-FILE if called-interactively"
- (interactive (let* ((input-dir (read-directory-name "Snippet dir "))
- (output-file (let ((ido-everywhere nil))
- (read-file-name "Output file "
- input-dir nil nil
- ".yas-compiled-snippets.el"
- nil))))
- (list input-dir output-file)))
- (let ((default-directory input-dir))
- (with-temp-file (setq output-file (or output-file ".yas-compiled-snippets.el"))
- (flet ((yas/define-snippets
- (mode snippets &optional parent-or-parents)
- (insert (format ";;; %s - automatically compiled snippets for `%s' , do not edit!\n"
- (file-name-nondirectory output-file) mode))
- (insert ";;;\n")
- (let ((literal-snippets (list)))
- (dolist (snippet snippets)
- (let ((key (first snippet))
- (template-content (second snippet))
- (name (third snippet))
- (condition (fourth snippet))
- (group (fifth snippet))
- (expand-env (sixth snippet))
- (file nil) ;; (seventh snippet)) ;; omit on purpose
- (binding (eighth snippet))
- (uuid (ninth snippet)))
- (push `(,key
- ,template-content
- ,name
- ,condition
- ,group
- ,expand-env
- ,file
- ,binding
- ,uuid)
- literal-snippets)))
- (insert (pp-to-string `(yas/define-snippets ',mode ',literal-snippets ',parent-or-parents)))
- (insert "\n\n")
- (insert (format ";;; %s - automatically compiled snippets for `%s' end here\n"
- (file-name-nondirectory output-file) mode))
- (insert ";;;"))))
- (yas/load-directory-1 input-dir nil nil 'no-compiled-snippets))))
-
- (if (and (called-interactively-p)
- (yes-or-no-p (format "Open the resulting file (%s)? "
- (expand-file-name output-file))))
- (find-file-other-window output-file)))
+ (flet ((yas/load-yas-setup-file
+ (file)
+ (let ((elfile (concat file ".el")))
+ (when (file-exists-p elfile)
+ (insert ";;; .yas-setup.el support file if any:\n;;;\n")
+ (insert-file-contents elfile)
+ (end-of-buffer)
+ )))
+ (yas/define-snippets
+ (mode snippets)
+ (insert ";;; Snippet definitions:\n;;;\n")
+ (let ((literal-snippets (list))
+ (print-length nil))
+ (dolist (snippet snippets)
+ (let ((key (first snippet))
+ (template-content (second snippet))
+ (name (third snippet))
+ (condition (fourth snippet))
+ (group (fifth snippet))
+ (expand-env (sixth snippet))
+ (file nil) ;; (seventh snippet)) ;; omit on purpose
+ (binding (eighth snippet))
+ (uuid (ninth snippet)))
+ (push `(,key
+ ,template-content
+ ,name
+ ,condition
+ ,group
+ ,expand-env
+ ,file
+ ,binding
+ ,uuid)
+ literal-snippets)))
+ (insert (pp-to-string `(yas/define-snippets ',mode ',literal-snippets)))
+ (insert "\n\n")))
+ (yas/load-directory-1
+ (dir mode parents &rest ignore)
+ (let ((output-file (concat (file-name-as-directory dir) ".yas-compiled-snippets.el")))
+ (with-temp-file output-file
+ (insert (format ";;; Compiled snippets and support files for `%s'\n" mode))
+ (yas/load-directory-2 dir mode parents)
+ (insert (format ";;; Do not edit! File generated at %s\n" (current-time-string)))))))
+ (yas/load-directory top-level-dir 'im-compiling-so-no-jit-ok?)))
+
+(defun yas/recompile-all ()
+ "Compile every dir in `yas/snippet-dirs'."
+ (interactive)
+ (mapc #'yas/compile-directory (yas/snippet-dirs)))
+;;; JIT loading
+;;;
+
+(defvar yas/scheduled-jit-loads (make-hash-table)
+ "Alist of mode-symbols to forms to be evaled when `yas/minor-mode' kicks in.")
+
+(defun yas/schedule-jit (mode form)
+ (puthash mode
+ (cons form
+ (gethash mode yas/scheduled-jit-loads))
+ yas/scheduled-jit-loads))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Some user level functions
@@ -1779,7 +1814,14 @@ Prompts for INPUT-DIR and OUTPUT-FILE if called-interactively"
yas/version
") -- pluskid <pluskid@gmail.com>/joaotavora <joaotavora@gmail.com>")))
-(defun yas/define-snippets (mode snippets &optional parent-mode)
+(defun yas/define-parents (mode parents)
+ "Add PARENTS to the list of MODE's parents"
+ (puthash mode-sym (remove-duplicates
+ (append parents
+ (gethash mode-sym yas/parents)))
+ yas/parents))
+
+(defun yas/define-snippets (mode snippets)
"Define SNIPPETS for MODE.
SNIPPETS is a list of snippet definitions, each taking the
@@ -1805,32 +1847,9 @@ UUID is the snippets \"unique-id\". Loading a second snippet file
with the same uuid replaced the previous snippet.
You can use `yas/parse-template' to return such lists based on
-the current buffers contents.
-
-Optional PARENT-MODE can be used to specify the parent tables of
-MODE. It can be a mode symbol of a list of mode symbols. It does
-not need to be a real mode."
- ;; X) `snippet-table' is created or retrieved for MODE, same goes
- ;; for the list of snippet tables `parent-tables'.
- ;;
+the current buffers contents."
(let ((snippet-table (yas/table-get-create mode))
- (parent-tables (mapcar #'yas/table-get-create
- (if (listp parent-mode)
- parent-mode
- (list parent-mode))))
(template nil))
- ;; X) Connect `snippet-table' with `parent-tables'.
- ;;
- ;; TODO: this should be a remove-duplicates of the concatenation
- ;; of `snippet-table's existings parents with the new parents...
- ;;
- (dolist (parent parent-tables)
- (unless (find parent (yas/table-parents snippet-table))
- (push parent
- (yas/table-parents snippet-table))))
-
- ;; X) Now, iterate for evey snippet def list
- ;;
(dolist (snippet snippets)
(setq template (yas/define-snippets-1 snippet
snippet-table)))
@@ -1982,7 +2001,7 @@ ommited from MODE's menu, even if they're manually loaded.
(define-key keymap (vector (gensym))
'(menu-item "----")))
(t
- (yas/message 3 "don't know anything about menu entry %s" (first e))))))
+ (yas/message 3 "Don't know anything about menu entry %s" (first e))))))
(defun yas/define (mode key template &optional name condition group)
"Define a snippet. Expanding KEY into TEMPLATE.
@@ -2999,7 +3018,7 @@ snippet as ordinary text."
;; again from `yas/take-care-of-redo'....
(setf (yas/snippet-fields snippet) nil)))
- (yas/message 3 "snippet %s exited." (yas/snippet-id snippet)))
+ (yas/message 3 "Snippet %s exited." (yas/snippet-id snippet)))
(defun yas/safely-run-hooks (hook-var)
(condition-case error
@@ -3688,7 +3707,7 @@ SNIPPET-MARKERS."
(widen)
(condition-case err
(indent-according-to-mode)
- (error (yas/message 3 "warning: yas/indent-according-to-mode habing problems running %s" indent-line-function)
+ (error (yas/message 3 "Warning: `yas/indent-according-to-mode' having problems running %s" indent-line-function)
nil)))
(mapc #'(lambda (marker)
(set-marker marker (point)))
@@ -4031,7 +4050,7 @@ that the rest of `yas/post-command-handler' runs.")
(apply (car fn-and-args)
(cdr fn-and-args)))
yas/post-command-runonce-actions)
- (error (yas/message 3 "problem running `yas/post-command-runonce-actions'!")))
+ (error (yas/message 3 "Problem running `yas/post-command-runonce-actions'!")))
(setq yas/post-command-runonce-actions nil))
(cond (yas/protection-violation
(goto-char yas/protection-violation)
Please sign in to comment.
Something went wrong with that request. Please try again.