diff --git a/yasnippet.el b/yasnippet.el index ac54bb1..d79093d 100644 --- a/yasnippet.el +++ b/yasnippet.el @@ -242,6 +242,8 @@ representation using `read-kbd-macro'." (let ((old (and (boundp symbol) (symbol-value symbol)))) (set-default symbol key) + ;; On very first loading of this defcustom, + ;; `yas/trigger-key' is *not* loaded. (if (fboundp 'yas/trigger-key-reload) (yas/trigger-key-reload old))))) @@ -401,10 +403,7 @@ This cafn only work when snippets are loaded from files." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; User can also customize these -(defvar yas/keymap nil - "The keymap active while a snippet expansion is in progress.") - +;; User can also customize the next defvars (defun yas/define-some-keys (keys keymap definition) "Bind KEYS to DEFINITION in KEYMAP, read with `read-kbd-macro'." (let ((keys (or (and (listp keys) keys) @@ -412,7 +411,7 @@ This cafn only work when snippets are loaded from files." (dolist (key keys) (define-key keymap (read-kbd-macro key) definition)))) -(defun yas/init-yas-in-snippet-keymap () +(defvar yas/keymap (let ((map (make-sparse-keymap))) (mapc #'(lambda (binding) (yas/define-some-keys (car binding) map (cdr binding))) @@ -420,9 +419,8 @@ This cafn only work when snippets are loaded from files." (,yas/prev-field-key . yas/prev-field) ("C-g" . yas/abort-snippet) (,yas/skip-and-clear-key . yas/skip-and-clear-or-delete-char))) - (setq yas/keymap map))) - -(yas/init-yas-in-snippet-keymap) + map) + "The keymap active while a snippet expansion is in progress.") (defvar yas/key-syntaxes (list "w" "w_" "w_." "^ ") "A list of syntax of a key. This list is tried in the order @@ -460,47 +458,57 @@ Attention: These hooks are not run when exiting nested/stackd snippet expansion! 'face)))) '(require-snippet-condition . force-in-comment) t) - "Condition to yasnippet local to each buffer. + "Snippet expanding condition. -The default value helps filtering out potential snippet -expansions inside comments and string literals, unless the -snippet itself contains a condition that returns the symbol -`force-in-comment'. +This variable is a lisp form: - * If yas/buffer-local-condition evaluate to nil, snippet - won't be expanded. + * If it evaluates to nil, no snippets can be expanded. - * If it evaluate to the a cons cell where the car is the - symbol `require-snippet-condition' and the cdr is a - symbol (let's call it \"requirement\"): - * If the snippet has no condition, then it won't be - expanded. - * If the snippet has a condition but it evaluates to nil or - error occured during evaluation, it won't be expanded. - * If the snippet has a condition that evaluate to - non-nil (let's call it \"result\"): - * If \"requirement\" is t, the snippet is ready to be - expanded. - * If \"requirement\" is eq to \"result\", the snippet is ready - to be expanded. - * Otherwise the snippet won't be expanded. + * If it evaluates to the a cons (require-snippet-condition + . REQUIREMENT) - * If it evaluates to `always', snippet is unconditionally - expanded. + * Snippets bearing no \"# condition:\" directive are not + considered - * If it evaluates to other non-nil value: - * If the snippet has no condition, or has a condition that - evaluate to non-nil, it is ready to be expanded. - * Otherwise, it won't be expanded. + * Snippets bearing conditions that evaluate to nil (or + produce an error) won't be onsidered. -Here's an example: + * If the snippet has a condition that evaluates to non-nil + RESULT: + + * If REQUIREMENT is t, the snippet is considered + + * If REQUIREMENT is `eq' RESULT, the snippet is + considered + + * Otherwise, the snippet is not considered. + + * If it evaluates to the symbol 'always, all snippets are + considered for expansion, regardless of any conditions. + + * If it evaluates to t or some other non-nil value + + * Snippet bearing no conditions, or conditions that + evaluate to non-nil, are considered for expansion. + + * Otherwise, the snippet is not considered. + +Here's an example preventing snippets from being expanded from +inside comments, in `python-mode' only, with the exception of +snippets returning the symbol 'force-in-comment in their +conditions. (add-hook 'python-mode-hook '(lambda () (setq yas/buffer-local-condition '(if (python-in-string/comment) '(require-snippet-condition . force-in-comment) - t))))") + t)))) + +The default value is similar, it filters out potential snippet +expansions inside comments and string literals, unless the +snippet itself contains a condition that returns the symbol +`force-in-comment'.") (make-variable-buffer-local 'yas/buffer-local-condition) @@ -558,134 +566,135 @@ Here's an example: ;; XXX: `last-buffer-undo-list' is somehow needed in Carbon Emacs for MacOSX (defvar last-buffer-undo-list nil) -(defvar yas/minor-mode-map (make-sparse-keymap) - "The keymap used when `yas/minor-mode' is active.") - -(defvar yas/minor-mode-menu (make-sparse-keymap) - "Holds the YASnippet menu. For use with `easy-menu-define'.") +(defvar yas/minor-mode-menu nil + "Holds the YASnippet menu") (defun yas/init-minor-keymap () - (easy-menu-define yas/minor-mode-menu - yas/minor-mode-map - "Menu used when YAS/minor-mode is active." - '("YASnippet" - "----" - ["Expand trigger" yas/expand - :help "Possibly expand tab trigger before point"] - ["Insert at point..." yas/insert-snippet - :help "Prompt for an expandable snippet and expand it at point"] - ["New snippet..." yas/new-snippet - :help "Create a new snippet in an appropriate directory"] - ["Visit snippet file..." yas/visit-snippet-file - :help "Prompt for an expandable snippet and find its file"] - ["Find snippets..." yas/find-snippets - :help "Invoke `find-file' in the appropriate snippet directory"] - "----" - ("Snippet menu behaviour" - ["Visit snippets" (setq yas/visit-from-menu t) - :help "Visit snippets from the menu" - :active t :style radio :selected yas/visit-from-menu] - ["Expand snippets" (setq yas/visit-from-menu nil) - :help "Expand snippets from the menu" - :active t :style radio :selected (not yas/visit-from-menu)] - "----" - ["Show \"Real\" modes only" (setq yas/use-menu 'real-modes) - :help "Show snippet submenus for modes that appear to be real major modes" - :active t :style radio :selected (eq yas/use-menu 'real-modes)] - ["Show all modes" (setq yas/use-menu 't) - :help "Show one snippet submenu for each loaded table" - :active t :style radio :selected (eq yas/use-menu 't)] - ["Abbreviate according to current mode" (setq yas/use-menu 'abbreviate) - :help "Show only snippet submenus for the current active modes" - :active t :style radio :selected (eq yas/use-menu 'abbreviate)]) - ("Indenting" - ["Auto" (setq yas/indent-line 'auto) - :help "Indent each line of the snippet with `indent-according-to-mode'" - :active t :style radio :selected (eq yas/indent-line 'auto)] - ["Fixed" (setq yas/indent-line 'fixed) - :help "Indent the snippet to the current column" - :active t :style radio :selected (eq yas/indent-line 'fixed)] - ["None" (setq yas/indent-line 'none) - :help "Don't apply any particular snippet indentation after expansion" - :active t :style radio :selected (not (member yas/indent-line '(fixed auto)))] - "----" - ["Also auto indent first line" (setq yas/also-auto-indent-first-line - (not yas/also-auto-indent-first-line)) - :help "When auto-indenting also, auto indent the first line menu" - :active (eq yas/indent-line 'auto) - :style toggle :selected yas/also-auto-indent-first-line] - ) - ("Prompting method" - ["System X-widget" (setq yas/prompt-functions - (cons 'yas/x-prompt - (remove 'yas/x-prompt + (let ((map (make-sparse-keymap))) + (easy-menu-define yas/minor-mode-menu + map + "Menu used when YAS/minor-mode is active." + '("YASnippet" + "----" + ["Expand trigger" yas/expand + :help "Possibly expand tab trigger before point"] + ["Insert at point..." yas/insert-snippet + :help "Prompt for an expandable snippet and expand it at point"] + ["New snippet..." yas/new-snippet + :help "Create a new snippet in an appropriate directory"] + ["Visit snippet file..." yas/visit-snippet-file + :help "Prompt for an expandable snippet and find its file"] + ["Find snippets..." yas/find-snippets + :help "Invoke `find-file' in the appropriate snippet directory"] + "----" + ("Snippet menu behaviour" + ["Visit snippets" (setq yas/visit-from-menu t) + :help "Visit snippets from the menu" + :active t :style radio :selected yas/visit-from-menu] + ["Expand snippets" (setq yas/visit-from-menu nil) + :help "Expand snippets from the menu" + :active t :style radio :selected (not yas/visit-from-menu)] + "----" + ["Show \"Real\" modes only" (setq yas/use-menu 'real-modes) + :help "Show snippet submenus for modes that appear to be real major modes" + :active t :style radio :selected (eq yas/use-menu 'real-modes)] + ["Show all modes" (setq yas/use-menu 't) + :help "Show one snippet submenu for each loaded table" + :active t :style radio :selected (eq yas/use-menu 't)] + ["Abbreviate according to current mode" (setq yas/use-menu 'abbreviate) + :help "Show only snippet submenus for the current active modes" + :active t :style radio :selected (eq yas/use-menu 'abbreviate)]) + ("Indenting" + ["Auto" (setq yas/indent-line 'auto) + :help "Indent each line of the snippet with `indent-according-to-mode'" + :active t :style radio :selected (eq yas/indent-line 'auto)] + ["Fixed" (setq yas/indent-line 'fixed) + :help "Indent the snippet to the current column" + :active t :style radio :selected (eq yas/indent-line 'fixed)] + ["None" (setq yas/indent-line 'none) + :help "Don't apply any particular snippet indentation after expansion" + :active t :style radio :selected (not (member yas/indent-line '(fixed auto)))] + "----" + ["Also auto indent first line" (setq yas/also-auto-indent-first-line + (not yas/also-auto-indent-first-line)) + :help "When auto-indenting also, auto indent the first line menu" + :active (eq yas/indent-line 'auto) + :style toggle :selected yas/also-auto-indent-first-line] + ) + ("Prompting method" + ["System X-widget" (setq yas/prompt-functions + (cons 'yas/x-prompt + (remove 'yas/x-prompt + yas/prompt-functions))) + :help "Use your windowing system's (gtk, mac, windows, etc...) default menu" + :active t :style radio :selected (eq (car yas/prompt-functions) + 'yas/x-prompt)] + ["Dropdown-list" (setq yas/prompt-functions + (cons 'yas/dropdown-prompt + (remove 'yas/dropdown-prompt yas/prompt-functions))) - :help "Use your windowing system's (gtk, mac, windows, etc...) default menu" - :active t :style radio :selected (eq (car yas/prompt-functions) - 'yas/x-prompt)] - ["Dropdown-list" (setq yas/prompt-functions - (cons 'yas/dropdown-prompt - (remove 'yas/dropdown-prompt - yas/prompt-functions))) - :help "Use a special dropdown list" - :active t :style radio :selected (eq (car yas/prompt-functions) - 'yas/dropdown-prompt)] - ["Ido" (setq yas/prompt-functions - (cons 'yas/ido-prompt - (remove 'yas/ido-prompt - yas/prompt-functions))) - :help "Use an ido-style minibuffer prompt" - :active t :style radio :selected (eq (car yas/prompt-functions) - 'yas/ido-prompt)] - ["Completing read" (setq yas/prompt-functions - (cons 'yas/completing-prompt - (remove 'yas/completing-prompt-prompt - yas/prompt-functions))) - :help "Use a normal minibuffer prompt" - :active t :style radio :selected (eq (car yas/prompt-functions) - 'yas/completing-prompt-prompt)] - ) - ("Misc" - ["Wrap region in exit marker" - (setq yas/wrap-around-region - (not yas/wrap-around-region)) - :help "If non-nil automatically wrap the selected text in the $0 snippet exit" - :style toggle :selected yas/wrap-around-region] - ["Allow stacked expansions " - (setq yas/triggers-in-field - (not yas/triggers-in-field)) - :help "If non-nil allow snippets to be triggered inside other snippet fields" - :style toggle :selected yas/triggers-in-field] - ["Revive snippets on undo " - (setq yas/snippet-revival - (not yas/snippet-revival)) - :help "If non-nil allow snippets to become active again after undo" - :style toggle :selected yas/snippet-revival] - ["Good grace " - (setq yas/good-grace - (not yas/good-grace)) - :help "If non-nil don't raise errors in bad embedded eslip in snippets" - :style toggle :selected yas/good-grace] - ["Ignore filenames as triggers" - (setq yas/ignore-filenames-as-triggers - (not yas/ignore-filenames-as-triggers)) - :help "If non-nil don't derive tab triggers from filenames" - :style toggle :selected yas/ignore-filenames-as-triggers] - ) - "----" - ["Load snippets..." yas/load-directory - :help "Load snippets from a specific directory"] - ["Reload everything" yas/reload-all - :help "Cleanup stuff, reload snippets, rebuild menus"] - ["About" yas/about - :help "Display some information about YASsnippet"])) - ;; Now for the stuff that has direct keybindings - ;; - (yas/trigger-key-reload) - (define-key yas/minor-mode-map "\C-c&\C-s" 'yas/insert-snippet) - (define-key yas/minor-mode-map "\C-c&\C-n" 'yas/new-snippet) - (define-key yas/minor-mode-map "\C-c&\C-v" 'yas/visit-snippet-file) - (define-key yas/minor-mode-map "\C-c&\C-f" 'yas/find-snippets)) + :help "Use a special dropdown list" + :active t :style radio :selected (eq (car yas/prompt-functions) + 'yas/dropdown-prompt)] + ["Ido" (setq yas/prompt-functions + (cons 'yas/ido-prompt + (remove 'yas/ido-prompt + yas/prompt-functions))) + :help "Use an ido-style minibuffer prompt" + :active t :style radio :selected (eq (car yas/prompt-functions) + 'yas/ido-prompt)] + ["Completing read" (setq yas/prompt-functions + (cons 'yas/completing-prompt + (remove 'yas/completing-prompt-prompt + yas/prompt-functions))) + :help "Use a normal minibuffer prompt" + :active t :style radio :selected (eq (car yas/prompt-functions) + 'yas/completing-prompt-prompt)] + ) + ("Misc" + ["Wrap region in exit marker" + (setq yas/wrap-around-region + (not yas/wrap-around-region)) + :help "If non-nil automatically wrap the selected text in the $0 snippet exit" + :style toggle :selected yas/wrap-around-region] + ["Allow stacked expansions " + (setq yas/triggers-in-field + (not yas/triggers-in-field)) + :help "If non-nil allow snippets to be triggered inside other snippet fields" + :style toggle :selected yas/triggers-in-field] + ["Revive snippets on undo " + (setq yas/snippet-revival + (not yas/snippet-revival)) + :help "If non-nil allow snippets to become active again after undo" + :style toggle :selected yas/snippet-revival] + ["Good grace " + (setq yas/good-grace + (not yas/good-grace)) + :help "If non-nil don't raise errors in bad embedded eslip in snippets" + :style toggle :selected yas/good-grace] + ["Ignore filenames as triggers" + (setq yas/ignore-filenames-as-triggers + (not yas/ignore-filenames-as-triggers)) + :help "If non-nil don't derive tab triggers from filenames" + :style toggle :selected yas/ignore-filenames-as-triggers] + ) + "----" + ["Load snippets..." yas/load-directory + :help "Load snippets from a specific directory"] + ["Reload everything" yas/reload-all + :help "Cleanup stuff, reload snippets, rebuild menus"] + ["About" yas/about + :help "Display some information about YASsnippet"])) + ;; Now for the stuff that has direct keybindings + ;; + (define-key map "\C-c&\C-s" 'yas/insert-snippet) + (define-key map "\C-c&\C-n" 'yas/new-snippet) + (define-key map "\C-c&\C-v" 'yas/visit-snippet-file) + (define-key map "\C-c&\C-f" 'yas/find-snippets) + map)) + +(defvar yas/minor-mode-map (yas/init-minor-keymap) + "The keymap used when `yas/minor-mode' is active.") (defun yas/trigger-key-reload (&optional unbind-key) "Rebind `yas/expand' to the new value of `yas/trigger-key'. @@ -701,9 +710,6 @@ With optional UNBIND-KEY, try to unbind that key from (not (string= yas/trigger-key ""))) (define-key yas/minor-mode-map (read-kbd-macro yas/trigger-key) 'yas/expand))) -;;; eval'ed on require/load -(yas/init-minor-keymap) - ;;;###autoload (define-minor-mode yas/minor-mode "Toggle YASnippet mode. @@ -724,13 +730,7 @@ Key bindings: " yas" :group 'yasnippet (when yas/minor-mode - ;; when turning on the minor mode. - ;; - ;; re-read the `yas/trigger-key' if a `yas/minor-mode-map' is - ;; already built. Else, call `yas/init-minor-keymap' to build it - (unless (and (cdr yas/minor-mode-map) - (yas/trigger-key-reload)) - (yas/init-minor-keymap)) + (yas/trigger-key-reload) ;; load all snippets definitions unless we still don't have a ;; root-directory or some snippets have already been loaded. (unless (or (null yas/root-directory) @@ -789,27 +789,25 @@ Do this unless `yas/dont-activate' is t or the function ("}" (0 font-lock-keyword-face))))) -(defvar snippet-mode-map (make-sparse-keymap) +(defun yas/init-major-keymap () + (let ((map (make-sparse-keymap))) + (easy-menu-define nil + map + "Menu used when snippet-mode is active." + (cons "Snippet" + (mapcar #'(lambda (ent) + (when (third ent) + (define-key map (third ent) (second ent))) + (vector (first ent) (second ent) t)) + (list + (list "Load this snippet" 'yas/load-snippet-buffer "\C-c\C-c") + (list "Try out this snippet" 'yas/tryout-snippet "\C-c\C-t"))))) + map)) + +(defvar snippet-mode-map + (yas/init-major-keymap) "The keymap used when `snippet-mode' is active") -(defvar yas/major-mode-menu (make-sparse-keymap) - "Holds the snippet-mode menu. For use with `easy-menu-define'.") - -(defun yas/init-major-keymap () - (easy-menu-define yas/major-mode-menu - snippet-mode-map - "Menu used when snippet-mode is active." - (cons "Snippet" - (mapcar #'(lambda (ent) - (when (third ent) - (define-key snippet-mode-map (third ent) (second ent))) - (vector (first ent) (second ent) t)) - (list - (list "Load this snippet" 'yas/load-snippet-buffer "\C-c\C-c") - (list "Try out this snippet" 'yas/tryout-snippet "\C-c\C-t")))))) - -(progn - (yas/init-major-keymap)) (define-derived-mode snippet-mode text-mode "Snippet" "A mode for editing yasnippets" @@ -917,7 +915,7 @@ Has the following fields: (maphash #'(lambda (k v) (push (cons k v) alist)) namehash) - alist))))) + alist))))) ;; Filtering/condition logic @@ -1253,11 +1251,11 @@ Here's a list of currently recognized variables: (if yas/visit-from-menu (yas/visit-snippet-file-1 template) (let ((where (if mark-active - (cons (region-beginning) (region-end)) - (cons (point) (point))))) - (yas/expand-snippet (yas/template-content template) - (car where) - (cdr where))))) + (cons (region-beginning) (region-end)) + (cons (point) (point))))) + (yas/expand-snippet (yas/template-content template) + (car where) + (cdr where))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Popping up for keys and templates @@ -1429,17 +1427,11 @@ content of the file is the template." (setq yas/snippet-tables (make-hash-table)) (setq yas/menu-table (make-hash-table)) - ;; The minor mode and major mode keymap's cdr set to nil (this is - ;; the same as `make-sparse-keymap;) - (setf (cdr yas/minor-mode-menu) nil) - (setf (cdr yas/minor-mode-map) nil) - (setf (cdr yas/major-mode-menu) nil) - (setf (cdr snippet-mode-map) nil) - - ;; Initialize both keymaps + ;; Init the `yas/minor-mode-map', taking care not to break the + ;; menu.... ;; - (yas/init-minor-keymap) - (yas/init-major-keymap) + (setf (cdr yas/minor-mode-map) + (cdr (yas/init-minor-keymap))) ;; Now, clean up the other keymaps we might have cluttered up. (yas/kill-snippet-keybindings) @@ -1760,7 +1752,7 @@ not need to be a real mode." ,(yas/make-menu-binding template) :help ,name :keys ,(when (and key name) - (concat key yas/trigger-symbol)))))))))) + (concat key yas/trigger-symbol)))))))))) (defun yas/show-menu-p (mode) (cond ((eq yas/use-menu 'abbreviate) @@ -2429,7 +2421,7 @@ delegate to `yas/next-field'." (yas/text (yas/field-text-for-display active-field)) (text yas/text) (yas/modified-p (yas/field-modified-p active-field))) - ;;; primary field transform: exit call to field-transform + ;; primary field transform: exit call to field-transform (yas/read-and-eval-string (yas/field-transform active-field)))) ;; Now actually move... (cond ((>= target-pos (length live-fields)) @@ -2452,7 +2444,7 @@ Also create some protection overlays" (setf (yas/snippet-active-field snippet) field) (yas/place-overlays snippet field) (overlay-put yas/active-field-overlay 'yas/field field) - ;;; primary field transform: first call to snippet transform + ;; primary field transform: first call to snippet transform (unless (yas/field-modified-p field) (if (yas/field-update-display field snippet) (let ((inhibit-modification-hooks t)) @@ -2713,7 +2705,7 @@ progress." (let ((field (overlay-get yas/active-field-overlay 'yas/field))) (cond (after? (yas/advance-end-maybe field (overlay-end overlay)) - ;;; primary field transform: normal calls to expression +;;; primary field transform: normal calls to expression (let ((saved-point (point))) (yas/field-update-display field (car (yas/snippets-at-point))) (goto-char saved-point)) @@ -2831,7 +2823,7 @@ will be deleted before inserting template." (prog1 (buffer-substring-no-properties (region-beginning) (region-end)) (unless start (setq start (region-beginning)) - (unless end (setq end (region-end))))))) + (unless end (setq end (region-end))))))) (when start (goto-char start)) @@ -2873,7 +2865,7 @@ will be deleted before inserting template." (read expand-env) (error nil)))) (eval `(let ,read-vars - (yas/snippet-create (point-min) (point-max))))) + (yas/snippet-create (point-min) (point-max))))) (yas/snippet-create (point-min) (point-max)))))) ;; stacked-expansion: This checks for stacked expansion, save the @@ -2958,8 +2950,6 @@ Returns the newly created snippet." ;; Sort and link each field (yas/snippet-sort-fields snippet) - ;; (yas/update-mirrors snippet) ;; XXX: WHY was this here for so long... - ;; Create keymap overlay for snippet (setf (yas/snippet-control-overlay snippet) (yas/make-control-overlay snippet (point-min) (point-max))) @@ -3248,10 +3238,10 @@ With optional string TEXT do it in string instead of the buffer." "Replace all the \"`(lisp-expression)`\"-style expression with their evaluated value" (while (re-search-forward yas/backquote-lisp-expression-regexp nil t) - (let ((transformed (yas/read-and-eval-string (yas/restore-escapes (match-string 1))))) - (goto-char (match-end 0)) - (when transformed (insert transformed)) - (delete-region (match-beginning 0) (match-end 0))))) + (let ((transformed (yas/read-and-eval-string (yas/restore-escapes (match-string 1))))) + (goto-char (match-end 0)) + (when transformed (insert transformed)) + (delete-region (match-beginning 0) (match-end 0))))) (defun yas/scan-sexps (from count) (condition-case err @@ -3334,20 +3324,20 @@ When multiple expressions are found, only the last one counts." (defun yas/transform-mirror-parse-create (snippet) "Parse the \"${n:$(lisp-expression)}\" mirror transformations." (while (re-search-forward yas/transform-mirror-regexp nil t) - (let* ((real-match-end-0 (yas/scan-sexps (1+ (match-beginning 0)) 1)) - (number (string-to-number (match-string-no-properties 1))) - (field (and number - (not (zerop number)) - (yas/snippet-find-field snippet number)))) - (when (and real-match-end-0 - field) - (push (yas/make-mirror (yas/make-marker (match-beginning 0)) - (yas/make-marker (match-beginning 0)) - (yas/restore-escapes - (buffer-substring-no-properties (match-beginning 2) - (1- real-match-end-0)))) - (yas/field-mirrors field)) - (push (cons (match-beginning 0) real-match-end-0) yas/dollar-regions))))) + (let* ((real-match-end-0 (yas/scan-sexps (1+ (match-beginning 0)) 1)) + (number (string-to-number (match-string-no-properties 1))) + (field (and number + (not (zerop number)) + (yas/snippet-find-field snippet number)))) + (when (and real-match-end-0 + field) + (push (yas/make-mirror (yas/make-marker (match-beginning 0)) + (yas/make-marker (match-beginning 0)) + (yas/restore-escapes + (buffer-substring-no-properties (match-beginning 2) + (1- real-match-end-0)))) + (yas/field-mirrors field)) + (push (cons (match-beginning 0) real-match-end-0) yas/dollar-regions))))) (defun yas/simple-mirror-parse-create (snippet) "Parse the simple \"$n\" mirrors and the exit-marker." @@ -3395,52 +3385,52 @@ When multiple expressions are found, only the last one counts." (defun yas/update-mirrors (snippet) "Updates all the mirrors of SNIPPET." (save-excursion - (dolist (field (yas/snippet-fields snippet)) - (dolist (mirror (yas/field-mirrors field)) - ;; stacked expansion: I added an `inhibit-modification-hooks' - ;; here, for safety, may need to remove if we the mechanism is - ;; altered. - ;; - (let ((inhibit-modification-hooks t)) - (yas/mirror-update-display mirror field) - ;; `yas/place-overlays' is needed if the active field and - ;; protected overlays have been changed because of insertions - ;; in `yas/mirror-update-display' + (dolist (field (yas/snippet-fields snippet)) + (dolist (mirror (yas/field-mirrors field)) + ;; stacked expansion: I added an `inhibit-modification-hooks' + ;; here, for safety, may need to remove if we the mechanism is + ;; altered. ;; - (when (eq field (yas/snippet-active-field snippet)) - (yas/place-overlays snippet field))))))) + (let ((inhibit-modification-hooks t)) + (yas/mirror-update-display mirror field) + ;; `yas/place-overlays' is needed if the active field and + ;; protected overlays have been changed because of insertions + ;; in `yas/mirror-update-display' + ;; + (when (eq field (yas/snippet-active-field snippet)) + (yas/place-overlays snippet field))))))) (defun yas/mirror-update-display (mirror field) "Update MIRROR according to FIELD (and mirror transform)." (let ((reflection (or (yas/apply-transform mirror field) (yas/field-text-for-display field)))) - (when (and reflection - (not (string= reflection (buffer-substring-no-properties (yas/mirror-start mirror) - (yas/mirror-end mirror))))) - (goto-char (yas/mirror-start mirror)) - (insert reflection) - (if (> (yas/mirror-end mirror) (point)) - (delete-region (point) (yas/mirror-end mirror)) - (set-marker (yas/mirror-end mirror) (point)) - (yas/advance-start-maybe (yas/mirror-next mirror) (point)))))) + (when (and reflection + (not (string= reflection (buffer-substring-no-properties (yas/mirror-start mirror) + (yas/mirror-end mirror))))) + (goto-char (yas/mirror-start mirror)) + (insert reflection) + (if (> (yas/mirror-end mirror) (point)) + (delete-region (point) (yas/mirror-end mirror)) + (set-marker (yas/mirror-end mirror) (point)) + (yas/advance-start-maybe (yas/mirror-next mirror) (point)))))) (defun yas/field-update-display (field snippet) "Much like `yas/mirror-update-display', but for fields" (when (yas/field-transform field) - (let ((inhibit-modification-hooks t) - (transformed (yas/apply-transform field field)) - (point (point))) - (when (and transformed - (not (string= transformed (buffer-substring-no-properties (yas/field-start field) - (yas/field-end field))))) - (setf (yas/field-modified-p field) t) - (goto-char (yas/field-start field)) - (insert transformed) - (if (> (yas/field-end field) (point)) - (delete-region (point) (yas/field-end field)) - (set-marker (yas/field-end field) (point)) - (yas/advance-start-maybe (yas/field-next field) (point))) - t)))) + (let ((inhibit-modification-hooks t) + (transformed (yas/apply-transform field field)) + (point (point))) + (when (and transformed + (not (string= transformed (buffer-substring-no-properties (yas/field-start field) + (yas/field-end field))))) + (setf (yas/field-modified-p field) t) + (goto-char (yas/field-start field)) + (insert transformed) + (if (> (yas/field-end field) (point)) + (delete-region (point) (yas/field-end field)) + (set-marker (yas/field-end field) (point)) + (yas/advance-start-maybe (yas/field-next field) (point))) + t)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -3593,8 +3583,8 @@ When multiple expressions are found, only the last one counts." (snippet-mode) (yas/minor-mode 1) (let ((abbrev)) - (setq abbrev "$f") - (insert abbrev)) + (setq abbrev "$f") + (insert abbrev)) (unless quiet (add-hook 'post-command-hook 'yas/debug-snippet-vars 't 'local))) @@ -3666,15 +3656,15 @@ and return the directory. Return nil if not found." handle the end-of-buffer error fired in it by calling `forward-char' at the end of buffer." (condition-case err - ad-do-it - (error (message (error-message-string err))))) + ad-do-it + (error (message (error-message-string err))))) ;; disable c-electric-* serial command in YAS fields (add-hook 'c-mode-common-hook '(lambda () - (dolist (k '(":" ">" ";" "<" "{" "}")) - (define-key (symbol-value (make-local-variable 'yas/keymap)) - k 'self-insert-command)))) + (dolist (k '(":" ">" ";" "<" "{" "}")) + (define-key (symbol-value (make-local-variable 'yas/keymap)) + k 'self-insert-command)))) ;;; yasnippet.el ends here