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) (should (= (length expected)
(length observed))))))) (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 () (defun yas--basic-jit-loading-1 ()
(with-temp-buffer (with-temp-buffer
(should (= 4 (hash-table-count yas--scheduled-jit-loads))) (should (= 4 (hash-table-count yas--scheduled-jit-loads)))

View File

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