Closes #504: Correctly discover buffers needing snippets immediately

* yasnippet-tests.el (issue-504-tricky-jit): New test.

* yasnippet.el (yas-load-directory): Use a new `impatient-buffers'
local and call `yas--load-pending-juts' in all those at the end.

* yasnippet.el (cl-lib): Don't need `eval-and-compile'.
This commit is contained in:
João Távora 2014-08-20 21:29:32 +01:00
parent f7ef023ebb
commit 1d4618b022
2 changed files with 56 additions and 32 deletions

View File

@ -485,6 +485,23 @@ TODO: correct this bug!"
(should (= (length expected)
(length observed)))))))
(ert-deftest issue-504-tricky-jit ()
(define-derived-mode yas--test-mode c-mode "Just a test mode")
(define-derived-mode yas--another-test-mode c-mode "Another test mode")
(yas-with-snippet-dirs
'((".emacs.d/snippets"
("yas--another-test-mode"
(".yas-parents" . "yas--test-mode"))
("yas--test-mode")))
(let ((b (with-current-buffer (generate-new-buffer "*yas-test*")
(yas--another-test-mode)
(current-buffer))))
(unwind-protect
(progn
(yas-reload-all)
(should (= 0 (hash-table-count yas--scheduled-jit-loads))))
(kill-buffer b)))))
(defun yas--basic-jit-loading-1 ()
(with-temp-buffer
(should (= 4 (hash-table-count yas--scheduled-jit-loads)))

View File

@ -130,8 +130,7 @@
;;; Code:
(require 'cl)
(eval-and-compile
(require 'cl-lib))
(require 'cl-lib)
(require 'easymenu)
(require 'help-mode)
@ -1736,36 +1735,44 @@ With prefix argument USE-JIT do jit-loading of snippets."
current-prefix-arg t))
(unless yas-snippet-dirs
(setq yas-snippet-dirs top-level-dir))
(dolist (dir (yas--subdirs top-level-dir))
(let* ((major-mode-and-parents (yas--compute-major-mode-and-parents
(concat dir "/dummy")))
(mode-sym (car major-mode-and-parents))
(parents (cdr major-mode-and-parents)))
;; Attention: The parents and the menus are already defined
;; here, even if the snippets are later jit-loaded.
;;
;; * We need to know the parents at this point since entering a
;; given mode should jit load for its parents
;; immediately. This could be reviewed, the parents could be
;; discovered just-in-time-as well
;;
;; * We need to create the menus here to support the `full'
;; option to `yas-use-menu' (all known snippet menus are shown to the user)
;;
(yas--define-parents mode-sym parents)
(yas--menu-keymap-get-create mode-sym)
(let ((fun `(lambda () ;; FIXME: Simulating lexical-binding.
(yas--load-directory-1 ',dir ',mode-sym))))
(if (and use-jit
(not (some #'(lambda (buffer)
(with-current-buffer buffer
;; FIXME: Shouldn't this use derived-mode-p?
(when (eq major-mode mode-sym)
(yas--message 3 "Discovered there was already %s in %s" buffer mode-sym)
t)))
(buffer-list))))
(yas--schedule-jit mode-sym fun)
(funcall fun)))))
(let ((impatient-buffers))
(dolist (dir (yas--subdirs top-level-dir))
(let* ((major-mode-and-parents (yas--compute-major-mode-and-parents
(concat dir "/dummy")))
(mode-sym (car major-mode-and-parents))
(parents (cdr major-mode-and-parents)))
;; Attention: The parents and the menus are already defined
;; here, even if the snippets are later jit-loaded.
;;
;; * We need to know the parents at this point since entering a
;; given mode should jit load for its parents
;; immediately. This could be reviewed, the parents could be
;; discovered just-in-time-as well
;;
;; * We need to create the menus here to support the `full'
;; option to `yas-use-menu' (all known snippet menus are shown to the user)
;;
(yas--define-parents mode-sym parents)
(yas--menu-keymap-get-create mode-sym)
(let ((fun `(lambda () ;; FIXME: Simulating lexical-binding.
(yas--load-directory-1 ',dir ',mode-sym))))
(if use-jit
(yas--schedule-jit mode-sym fun)
(funcall fun)))
;; Look for buffers that are already in `mode-sym', and so
;; need the new snippets immediately...
;;
(when use-jit
(cl-loop for buffer in (buffer-list)
do (with-current-buffer buffer
(when (eq major-mode mode-sym)
(yas--message 3 "Discovered there was already %s in %s" buffer mode-sym)
(push buffer impatient-buffers)))))))
;; ...after TOP-LEVEL-DIR has been completely loaded, call
;; `yas--load-pending-jits' in these impatient buffers.
;;
(cl-loop for buffer in impatient-buffers
do (with-current-buffer buffer (yas--load-pending-jits))))
(when interactive
(yas--message 3 "Loaded snippets from %s." top-level-dir)))