From 76bb00bd8a3b0130187405c8f813497e6bc3c5ca Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Mon, 23 Apr 2018 09:32:08 +0200 Subject: Upgrade yasnippet --- .emacs.d/lisp/yasnippet.el | 79 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/.emacs.d/lisp/yasnippet.el b/.emacs.d/lisp/yasnippet.el index 9c7e88f..87536a2 100644 --- a/.emacs.d/lisp/yasnippet.el +++ b/.emacs.d/lisp/yasnippet.el @@ -1412,15 +1412,51 @@ Returns (TEMPLATES START END). This function respects ;;; Internal functions and macros: +(defun yas--remove-misc-free-from-undo (old-undo-list) + "Tries to work around Emacs Bug#30931. +Helper function for `yas--save-restriction-and-widen'." + ;; If Bug#30931 is unfixed, we get (# . INTEGER) + ;; entries in the undo list. If we call `type-of' on the + ;; Lisp_Misc_Free object then Emacs aborts, so try to find it by + ;; checking that its type is none of the expected ones. + (when (consp buffer-undo-list) + (let* ((prev buffer-undo-list) + (undo-list prev)) + (while (and (consp undo-list) + ;; Only check new entries. + (not (eq undo-list old-undo-list))) + (let ((entry (pop undo-list))) + (when (consp entry) + (let ((head (car entry))) + (unless (or (stringp head) + (markerp head) + (integerp head) + (symbolp head) + (not (integerp (cdr entry)))) + ;; (message "removing misc free %S" entry) + (setcdr prev undo-list))))) + (setq prev undo-list))))) + +(defmacro yas--save-restriction-and-widen (&rest body) + "Equivalent to (save-restriction (widen) BODY). +Also tries to work around Emacs Bug#30931." + (declare (debug (body)) (indent 0)) + ;; Disable garbage collection, since it could cause an abort. + `(let ((gc-cons-threshold most-positive-fixnum) + (old-undo-list buffer-undo-list)) + (prog1 (save-restriction + (widen) + ,@body) + (yas--remove-misc-free-from-undo old-undo-list)))) + (defun yas--eval-for-string (form) "Evaluate FORM and convert the result to string." (let ((debug-on-error (and (not (memq yas-good-grace '(t inline))) debug-on-error))) (condition-case oops (save-excursion - (save-restriction + (yas--save-restriction-and-widen (save-match-data - (widen) (let ((result (eval form))) (when result (format "%s" result)))))) @@ -3390,9 +3426,8 @@ This renders the snippet as ordinary text." ;; (yas--markers-to-points snippet) - ;; Take care of snippet revival - ;; - (if yas-snippet-revival + ;; Take care of snippet revival on undo. + (if (and yas-snippet-revival (listp buffer-undo-list)) (push `(apply yas--snippet-revive ,yas-snippet-beg ,yas-snippet-end ,snippet) buffer-undo-list) ;; Dismember the snippet... this is useful if we get called @@ -3963,8 +3998,9 @@ After revival, push the `yas--take-care-of-redo' in the (when (yas--maybe-move-to-active-field snippet) (setf (yas--snippet-control-overlay snippet) (yas--make-control-overlay snippet beg end)) (overlay-put (yas--snippet-control-overlay snippet) 'yas--snippet snippet) - (push `(apply yas--take-care-of-redo ,snippet) - buffer-undo-list))) + (when (listp buffer-undo-list) + (push `(apply yas--take-care-of-redo ,snippet) + buffer-undo-list)))) (defun yas--snippet-create (content expand-env begin end) "Create a snippet from a template inserted at BEGIN to END. @@ -3984,16 +4020,18 @@ Returns the newly created snippet." (narrow-to-region begin end) (goto-char (point-min)) (yas--snippet-parse-create snippet)) - (push (cons (point-min) (point-max)) - buffer-undo-list) + (when (listp buffer-undo-list) + (push (cons (point-min) (point-max)) + buffer-undo-list)) ;; Indent, collecting undo information normally. (yas--indent snippet) ;; Follow up with `yas--take-care-of-redo' on the newly ;; inserted snippet boundaries. - (push `(apply yas--take-care-of-redo ,snippet) - buffer-undo-list) + (when (listp buffer-undo-list) + (push `(apply yas--take-care-of-redo ,snippet) + buffer-undo-list)) ;; Sort and link each field (yas--snippet-sort-fields snippet) @@ -4185,8 +4223,7 @@ Meant to be called in a narrowed buffer, does various passes" (syntax-ppss-flush-cache parse-start)) ;; Set "next" links of fields & mirrors. (yas--calculate-adjacencies snippet) - (save-restriction - (widen) ; Delete $-constructs. + (yas--save-restriction-and-widen ; Delete $-constructs. (yas--delete-regions yas--dollar-regions)) ;; Make sure to do this insertion *after* deleting the dollar ;; regions, otherwise we invalidate the calculated positions of @@ -4327,8 +4364,7 @@ Buffer must be narrowed to BEG..END used to create the snapshot info." "Indent the lines between FROM and TO with `indent-according-to-mode'. The SNIPPET's markers are preserved." (save-excursion - (save-restriction - (widen) + (yas--save-restriction-and-widen (let* ((snippet-markers (yas--collect-snippet-markers snippet)) (to (set-marker (make-marker) to))) (goto-char from) @@ -4437,8 +4473,8 @@ Lisp expression." (setq yas--change-detected t))))) (while (re-search-forward yas--backquote-lisp-expression-regexp nil t) (let ((current-string (match-string-no-properties 1)) transformed) - (save-restriction (widen) - (delete-region (match-beginning 0) (match-end 0))) + (yas--save-restriction-and-widen + (delete-region (match-beginning 0) (match-end 0))) (let ((before-change-functions (cons detect-change before-change-functions))) (setq transformed (yas--eval-for-string (yas--read-lisp @@ -4448,8 +4484,7 @@ Lisp expression." (when transformed (let ((marker (make-marker)) (before-change-functions (cdr before-change-functions))) - (save-restriction - (widen) + (yas--save-restriction-and-widen (insert "Y") ;; quite horrendous, I love it :) (set-marker marker (point)) (insert "Y")) @@ -4469,8 +4504,7 @@ SAVED-QUOTES is the in format returned by `yas--save-backquotes'." (cl-loop for (marker . string) in saved-quotes do (save-excursion (goto-char marker) - (save-restriction - (widen) + (yas--save-restriction-and-widen (delete-char -1) (insert string) (delete-char 1)) @@ -4651,8 +4685,7 @@ When multiple expressions are found, only the last one counts." (defun yas--update-mirrors (snippet) "Update all the mirrors of SNIPPET." - (save-restriction - (widen) + (yas--save-restriction-and-widen (save-excursion (cl-loop for (field . mirror) -- cgit v1.3