[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master c87afe0 26/63: Merge: snippet-local exit hook; error handl
From: |
Noam Postavsky |
Subject: |
[elpa] master c87afe0 26/63: Merge: snippet-local exit hook; error handling improvements |
Date: |
Mon, 17 Jul 2017 22:54:14 -0400 (EDT) |
branch: master
commit c87afe0901735d4421c712b25dfa69b2ac59c8e9
Merge: 9abf842 f3d0e03
Author: Noam Postavsky <address@hidden>
Commit: Noam Postavsky <address@hidden>
Merge: snippet-local exit hook; error handling improvements
---
yasnippet-tests.el | 30 +++++++++++++++
yasnippet.el | 106 ++++++++++++++++++++++++++++-------------------------
2 files changed, 86 insertions(+), 50 deletions(-)
diff --git a/yasnippet-tests.el b/yasnippet-tests.el
index a6abcb7..dc0c43c 100644
--- a/yasnippet-tests.el
+++ b/yasnippet-tests.el
@@ -553,6 +553,36 @@ TODO: correct this bug!"
"brother from another mother") ;; no newline should be
here!
)))
+(ert-deftest snippet-exit-hooks ()
+ (defvar yas--ran-exit-hook)
+ (with-temp-buffer
+ (yas-saving-variables
+ (let ((yas--ran-exit-hook nil)
+ (yas-triggers-in-field t))
+ (yas-with-snippet-dirs
+ '((".emacs.d/snippets"
+ ("emacs-lisp-mode"
+ ("foo" . "\
+# expand-env: ((yas-after-exit-snippet-hook (lambda () (setq
yas--ran-exit-hook t))))
+# --
+FOO ${1:f1} ${2:f2}")
+ ("sub" . "\
+# expand-env: ((yas-after-exit-snippet-hook (lambda () (setq
yas--ran-exit-hook 'sub))))
+# --
+SUB"))))
+ (yas-reload-all)
+ (emacs-lisp-mode)
+ (yas-minor-mode +1)
+ (insert "foo")
+ (ert-simulate-command '(yas-expand))
+ (should-not yas--ran-exit-hook)
+ (yas-mock-insert "sub")
+ (ert-simulate-command '(yas-expand))
+ (ert-simulate-command '(yas-next-field))
+ (should-not yas--ran-exit-hook)
+ (ert-simulate-command '(yas-next-field))
+ (should (eq yas--ran-exit-hook t)))))))
+
(defvar yas--barbaz)
(defvar yas--foobarbaz)
diff --git a/yasnippet.el b/yasnippet.el
index 644aa90..715dce6 100644
--- a/yasnippet.el
+++ b/yasnippet.el
@@ -340,9 +340,16 @@ per-snippet basis. A value of `cua' is considered
equivalent to
(const cua))) ; backwards compat
(defcustom yas-good-grace t
- "If non-nil, don't raise errors in inline elisp evaluation.
+ "If non-nil, don't raise errors in elisp evaluation.
-An error string \"[yas] error\" is returned instead."
+This affects both the inline elisp in snippets and the hook
+variables such as `yas-after-exit-snippet-hook'.
+
+If this variable's value is `inline', an error string \"[yas]
+error\" is returned instead of raising the error. If this
+variable's value is `hooks', a message is output to according to
+`yas-verbosity-level'. If this variable's value is t, both are
+active."
:type 'boolean)
(defcustom yas-visit-from-menu nil
@@ -1323,33 +1330,22 @@ Returns (TEMPLATES START END). This function respects
;;; Internal functions and macros:
-(defun yas--handle-error (err)
- "Handle error depending on value of `yas-good-grace'."
- (let ((msg (yas--format "elisp error: %s" (error-message-string err))))
- (if yas-good-grace msg
- (error "%s" msg))))
-
-(defun yas--eval-lisp (form)
+(defun yas--eval-for-string (form)
"Evaluate FORM and convert the result to string."
- (let ((retval (catch 'yas--exception
- (condition-case err
- (save-excursion
- (save-restriction
- (save-match-data
- (widen)
- (let ((result (eval form)))
- (when result
- (format "%s" result))))))
- (error (yas--handle-error err))))))
- (when (and (consp retval)
- (eq 'yas--exception (car retval)))
- (error (cdr retval)))
- retval))
+ (let ((debug-on-error (and (not (memq yas-good-grace '(t inline)))
+ debug-on-error)))
+ (condition-case oops
+ (save-excursion
+ (save-restriction
+ (save-match-data
+ (widen)
+ (let ((result (eval form)))
+ (when result
+ (format "%s" result))))))
+ ((debug error) (cdr oops)))))
-(defun yas--eval-lisp-no-saves (form)
- (condition-case err
- (eval form)
- (error (message "%s" (yas--handle-error err)))))
+(defun yas--eval-for-effect (form)
+ (yas--safely-run-hook (apply-partially #'eval form)))
(defun yas--read-lisp (string &optional nil-on-error)
"Read STRING as a elisp expression and return it.
@@ -1665,7 +1661,7 @@ this is a snippet or a snippet-command.
CONDITION, EXPAND-ENV and KEYBINDING are Lisp forms, they have
been `yas--read-lisp'-ed and will eventually be
-`yas--eval-lisp'-ed.
+`yas--eval-for-string'-ed.
The remaining elements are strings.
@@ -1758,8 +1754,7 @@ With prefix argument USE-JIT do jit-loading of snippets."
;;
(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))))
+ (let ((fun (apply-partially #'yas--load-directory-1 dir mode-sym)))
(if use-jit
(yas--schedule-jit mode-sym fun)
(funcall fun)))
@@ -2854,16 +2849,16 @@ The last element of POSSIBILITIES may be a list of
strings."
key)))))
(defun yas-throw (text)
- "Throw a yas--exception with TEXT as the reason."
- (throw 'yas--exception (cons 'yas--exception text)))
+ "Signal `yas-exception' with TEXT as the reason."
+ (signal 'yas-exception (list text)))
+(put 'yas-exception 'error-conditions '(error yas-exception))
+(put 'yas-exception 'error-message "[yas] Exception")
(defun yas-verify-value (possibilities)
"Verify that the current field value is in POSSIBILITIES.
-
-Otherwise throw exception."
- (when (and yas-moving-away-p
- (cl-notany (lambda (pos) (string= pos yas-text)) possibilities))
- (yas-throw (yas--format "Field only allows %s" possibilities))))
+Otherwise signal `yas-exception'."
+ (when (and yas-moving-away-p (cl-notany (lambda (pos) (string= pos
yas-text)) possibilities))
+ (yas-throw (format "Field only allows %s" possibilities))))
(defun yas-field-value (number)
"Get the string for field with NUMBER.
@@ -3020,7 +3015,7 @@ string iff EMPTY-ON-NIL-P is true."
(transformed (and transform
(save-excursion
(goto-char start-point)
- (let ((ret (yas--eval-lisp transform)))
+ (let ((ret (yas--eval-for-string transform)))
(or ret (and empty-on-nil-p "")))))))
transformed))
@@ -3333,12 +3328,19 @@ This renders the snippet as ordinary text."
(yas--maybe-move-to-active-field snippet))
(setq yas--snippets-to-move nil))
-(defun yas--safely-run-hooks (hook-var)
+(defun yas--safely-call-fun (fun)
(condition-case error
- (run-hooks hook-var)
- (error
- (yas--message 2 "%s error: %s" hook-var (error-message-string error)))))
-
+ (funcall fun)
+ ((debug error)
+ (yas--message 2 "Error running %s: %s"
+ (if (symbolp fun) fun "a hook")
+ (error-message-string error)))))
+
+(defun yas--safely-run-hook (hook)
+ (let ((debug-on-error (and (not (memq yas-good-grace '(t hooks)))
+ debug-on-error)))
+ (if (functionp hook) (yas--safely-call-fun hook)
+ (mapc #'yas--safely-call-fun hook))))
(defun yas--check-commit-snippet ()
"Check if point exited the currently active field of the snippet.
@@ -3346,15 +3348,19 @@ This renders the snippet as ordinary text."
If so cleans up the whole snippet up."
(let* ((snippets (yas-active-snippets 'all))
(snippets-left snippets)
- (snippet-exit-transform))
+ (snippet-exit-transform nil)
+ (snippet-exit-hook yas-after-exit-snippet-hook))
(dolist (snippet snippets)
(let ((active-field (yas--snippet-active-field snippet)))
(yas--letenv (yas--snippet-expand-env snippet)
+ ;; Note: the `force-exit' field could be a transform in case of
+ ;; ${0: ...}, see `yas--move-to-field'.
(setq snippet-exit-transform (yas--snippet-force-exit snippet))
(cond ((or snippet-exit-transform
(not (and active-field (yas--field-contains-point-p
active-field))))
(setq snippets-left (delete snippet snippets-left))
(setf (yas--snippet-force-exit snippet) nil)
+ (setq snippet-exit-hook yas-after-exit-snippet-hook)
(yas--commit-snippet snippet))
((and active-field
(or (not yas--active-field-overlay)
@@ -3371,8 +3377,8 @@ If so cleans up the whole snippet up."
nil)))))
(unless (or (null snippets) snippets-left)
(if snippet-exit-transform
- (yas--eval-lisp-no-saves snippet-exit-transform))
- (yas--safely-run-hooks 'yas-after-exit-snippet-hook))))
+ (yas--eval-for-effect snippet-exit-transform))
+ (yas--safely-run-hook snippet-exit-hook))))
;; Apropos markers-to-points:
;;
@@ -3648,7 +3654,7 @@ considered when expanding the snippet."
(cond ((listp content)
;; x) This is a snippet-command
;;
- (yas--eval-lisp-no-saves content))
+ (yas--eval-for-effect content))
(t
;; x) This is a snippet-snippet :-)
;;
@@ -4169,9 +4175,9 @@ with their evaluated value into
`yas--backquote-markers-and-strings'."
(delete-region (match-beginning 0) (match-end 0)))
(let ((before-change-functions
(cons detect-change before-change-functions)))
- (setq transformed (yas--eval-lisp (yas--read-lisp
- (yas--restore-escapes
- current-string '(?`))))))
+ (setq transformed (yas--eval-for-string (yas--read-lisp
+ (yas--restore-escapes
+ current-string '(?`))))))
(goto-char (match-beginning 0))
(when transformed
(let ((marker (make-marker))
- [elpa] master 0041efe 17/63: Make snippets work in org source blocks, (continued)
- [elpa] master 0041efe 17/63: Make snippets work in org source blocks, Noam Postavsky, 2017/07/17
- [elpa] master 47f37f7 42/63: Fix ${0:soon-to-be-deleted} with no other fields, Noam Postavsky, 2017/07/17
- [elpa] master e8ed276 52/63: Make sure tests don't rely on running order, Noam Postavsky, 2017/07/17
- [elpa] master 2a3a0cd 61/63: Update CONTRIBUTING.md information, Noam Postavsky, 2017/07/17
- [elpa] master b0e729b 58/63: Optionally add undo list to debug info, Noam Postavsky, 2017/07/17
- [elpa] master 274406e 55/63: Provide command line interface from yasnippet-debug.el, Noam Postavsky, 2017/07/17
- [elpa] master 6e9b7f9 30/63: Fix running hook variable set as buffer-local, Noam Postavsky, 2017/07/17
- [elpa] master 7f337f4 32/63: Fix nested snippet expansion, Noam Postavsky, 2017/07/17
- [elpa] master 1bf7a4c 47/63: Fix field parsing in modes that use the `syntax-table' property, Noam Postavsky, 2017/07/17
- [elpa] master 8797a31 45/63: * doc/snippet-expansion.org: Complete sentence fragment., Noam Postavsky, 2017/07/17
- [elpa] master c87afe0 26/63: Merge: snippet-local exit hook; error handling improvements,
Noam Postavsky <=
- [elpa] master 1043b6c 49/63: Restore syntax-propertize-function before indenting mirrors, Noam Postavsky, 2017/07/17
- [elpa] master 65952e3 53/63: Allow customizing overlay priority, Noam Postavsky, 2017/07/17
- [elpa] master 1a860bd 51/63: Fix undo information recording for multiline snippets, Noam Postavsky, 2017/07/17
- [elpa] master 22eeb1e 36/63: Fix interaction with c auto-fill, Noam Postavsky, 2017/07/17
- [elpa] master 0311fe2 15/63: Use :filter instead of yas--fallback, Noam Postavsky, 2017/07/17
- [elpa] master 1babe81 40/63: * yasnippet.el (yas-about): Fix compile warnings in previous commit., Noam Postavsky, 2017/07/17
- [elpa] master 2f5cb2e 56/63: Make yas-debug-process-command-line easier to debug, Noam Postavsky, 2017/07/17
- [elpa] master 164acd6 59/63: * yasnippet-debug.el (yas-debug-snippet): Show modified flag., Noam Postavsky, 2017/07/17
- [elpa] master 7b03ac2 57/63: Handle dead snippets better, Noam Postavsky, 2017/07/17
- [elpa] master 75cbf72 62/63: Update NEWS, version number to 0.12, and snippets submodule, Noam Postavsky, 2017/07/17