mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 21:13:04 +00:00
* Fixed issue 28,
http://code.google.com/p/yasnippet/issues/detail?id=28 * Added snippet registration routines `yas/register-snippet', `yas/unregister-snippet', `yas/cleanup-snippet', `yas/exterminate-snippets' and `yas/check-cleanup-snippet' * Adjusted existing code to call these routines. * Added some commentary to explain functionality.
This commit is contained in:
parent
e6276da02a
commit
b8e187b5b6
149
yasnippet.el
149
yasnippet.el
@ -258,7 +258,9 @@ You can customize the key through `yas/trigger-key'."
|
|||||||
;; The indicator for the mode line.
|
;; The indicator for the mode line.
|
||||||
" yas"
|
" yas"
|
||||||
:group 'editing
|
:group 'editing
|
||||||
(define-key yas/minor-mode-map yas/trigger-key 'yas/expand))
|
(define-key yas/minor-mode-map yas/trigger-key 'yas/expand)
|
||||||
|
|
||||||
|
(set 'yas/registered-snippets (make-hash-table :test 'eq)))
|
||||||
|
|
||||||
(defun yas/minor-mode-auto-on ()
|
(defun yas/minor-mode-auto-on ()
|
||||||
"Turn on YASnippet minor mode unless `yas/dont-activate' is
|
"Turn on YASnippet minor mode unless `yas/dont-activate' is
|
||||||
@ -646,8 +648,9 @@ will be deleted before inserting template."
|
|||||||
(yas/replace-all "\\`" yas/escape-backquote)
|
(yas/replace-all "\\`" yas/escape-backquote)
|
||||||
(yas/replace-all "\\$" yas/escape-dollar)
|
(yas/replace-all "\\$" yas/escape-dollar)
|
||||||
|
|
||||||
(let ((snippet (yas/make-snippet)))
|
;; Step 5: Create and register a brand new snippet in the local
|
||||||
;; Step 5: Create fields
|
;; `yas/registered-snippets' var. Create fields.
|
||||||
|
(let ((snippet (yas/register-snippet (yas/make-snippet))))
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(while (re-search-forward yas/field-regexp nil t)
|
(while (re-search-forward yas/field-regexp nil t)
|
||||||
(let ((number (or (match-string-no-properties 1)
|
(let ((number (or (match-string-no-properties 1)
|
||||||
@ -1246,16 +1249,138 @@ when the condition evaluated to non-nil."
|
|||||||
(defun yas/exit-snippet (snippet)
|
(defun yas/exit-snippet (snippet)
|
||||||
"Goto exit-marker of SNIPPET and delete the snippet."
|
"Goto exit-marker of SNIPPET and delete the snippet."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((overlay (yas/snippet-overlay snippet)))
|
(goto-char (yas/snippet-exit-marker snippet))
|
||||||
(let ((yas/snippet-beg (overlay-start overlay))
|
(yas/cleanup-snippet snippet)
|
||||||
(yas/snippet-end (overlay-end overlay)))
|
(run-hooks 'yas/after-exit-snippet-hook))
|
||||||
(goto-char (yas/snippet-exit-marker snippet))
|
|
||||||
(delete-overlay overlay)
|
|
||||||
(dolist (group (yas/snippet-groups snippet))
|
|
||||||
(dolist (field (yas/group-fields group))
|
|
||||||
(delete-overlay (yas/field-overlay field))))
|
|
||||||
|
|
||||||
(run-hooks 'yas/after-exit-snippet-hook))))
|
;; Snippet register and unregister routines.
|
||||||
|
;;
|
||||||
|
;; XXX: Commentary on this section by joaot.
|
||||||
|
;;
|
||||||
|
;; These routines, along with minor modifications upwards, allow some
|
||||||
|
;; management of currently active snippets.
|
||||||
|
;;
|
||||||
|
;; The idea is to temporarily set `post-command-hook' while locally
|
||||||
|
;; "registered" snippets last. After each command,
|
||||||
|
;; `yas/check-cleanup-snippet' is run, checking for some condition and
|
||||||
|
;; possibly unregistering the snippet. When no more snippets are
|
||||||
|
;; registered, the `post-command-hook' is cleared up.
|
||||||
|
;;
|
||||||
|
;; They were introduced to fix bug 28
|
||||||
|
;; "http://code.google.com/p/yasnippet/issues/detail?id=28". Whenever
|
||||||
|
;; point exits a snippet or a snippet field, *all* snippets are
|
||||||
|
;; destroyed. I think this scheme can also fix other bugs or
|
||||||
|
;; introduce new features. It can also be used with `pre-command-hook'
|
||||||
|
;; for instance.
|
||||||
|
;;
|
||||||
|
;; For example, to only allow one snippet at a time, add a similar
|
||||||
|
;; check to `pre-command-hook' that immediately destroys all
|
||||||
|
;; snippets if `this-command' equals `yas/snippet-expand'.
|
||||||
|
;;
|
||||||
|
;; Or also using `pre-command-hook', exterminate all snippets if
|
||||||
|
;; `this-command' is `undo' and some snippet fields have already been
|
||||||
|
;; partially filled out. This would at least work around issue 33,
|
||||||
|
;; which complains about undo.
|
||||||
|
;;
|
||||||
|
;; Tell me what you think!
|
||||||
|
;;
|
||||||
|
|
||||||
|
(defvar yas/registered-snippets nil
|
||||||
|
"A hash table holding all active snippets")
|
||||||
|
(eval-when-compile
|
||||||
|
(make-variable-buffer-local 'yas/registered-snippets))
|
||||||
|
|
||||||
|
(defun yas/register-snippet (snippet)
|
||||||
|
"Register SNIPPET in the `yas/registered-snippets' table. Add a
|
||||||
|
`yas/check-cleanup-snippet' function to the buffer-local
|
||||||
|
`post-command-hook' that should exist while at least one
|
||||||
|
registered snippet exists in the current buffer. Return snippet"
|
||||||
|
(puthash (yas/snippet-id snippet) snippet yas/registered-snippets)
|
||||||
|
(add-hook 'post-command-hook 'yas/check-cleanup-snippet 'append 'local)
|
||||||
|
snippet)
|
||||||
|
|
||||||
|
(defun yas/unregister-snippet (snippet)
|
||||||
|
"Unregister snippet from the `yas/registered-snippets'
|
||||||
|
table. Remove `yas/check-cleanup-snippet' from the buffer-local
|
||||||
|
`post-command-hook' if no more snippets registered in the
|
||||||
|
current buffer."
|
||||||
|
(remhash (yas/snippet-id snippet) yas/registered-snippets)
|
||||||
|
(when (eq 0
|
||||||
|
(hash-table-count yas/registered-snippets))
|
||||||
|
(remove-hook 'post-command-hook 'yas/check-cleanup-snippet 'local)))
|
||||||
|
|
||||||
|
(defun yas/exterminate-snippets ()
|
||||||
|
"Remove all locally registered snippets and remove
|
||||||
|
`yas/check-cleanup-snippet' from the `post-command-hook'"
|
||||||
|
(interactive)
|
||||||
|
(maphash #'(lambda (key snippet) (yas/cleanup-snippet snippet))
|
||||||
|
yas/registered-snippets))
|
||||||
|
|
||||||
|
(defun yas/cleanup-snippet (snippet)
|
||||||
|
"Cleanup SNIPPET, but leave point as it is. This renders the
|
||||||
|
snippet as ordinary text"
|
||||||
|
(let* ((overlay (yas/snippet-overlay snippet))
|
||||||
|
(yas/snippet-beg (overlay-start overlay))
|
||||||
|
(yas/snippet-end (overlay-end overlay)))
|
||||||
|
(delete-overlay overlay)
|
||||||
|
(dolist (group (yas/snippet-groups snippet))
|
||||||
|
(dolist (field (yas/group-fields group))
|
||||||
|
(delete-overlay (yas/field-overlay field)))))
|
||||||
|
(yas/unregister-snippet snippet))
|
||||||
|
|
||||||
|
(defun yas/check-cleanup-snippet ()
|
||||||
|
"Checks if point exited any of the fields of the snippet, if so
|
||||||
|
clean it up.
|
||||||
|
|
||||||
|
This function is part of `post-command-hook' while
|
||||||
|
registered snippets last."
|
||||||
|
(let ((snippet (yas/snippet-of-current-keymap)))
|
||||||
|
(cond (;;
|
||||||
|
;; No snippet at point, cleanup *all* snippets
|
||||||
|
;;
|
||||||
|
(null snippet)
|
||||||
|
(yas/exterminate-snippets))
|
||||||
|
(;;
|
||||||
|
;; A snippet exits at point, but point is out of any
|
||||||
|
;; snippet field.
|
||||||
|
;;
|
||||||
|
;; XXX: `every' and `notany' should be much slower than a
|
||||||
|
;; couple of `while' loops...
|
||||||
|
;;
|
||||||
|
(and snippet
|
||||||
|
(every #'(lambda (group)
|
||||||
|
(notany #'(lambda (field)
|
||||||
|
(let ((overlay (yas/field-overlay field)))
|
||||||
|
(and (>= (point) (overlay-start overlay))
|
||||||
|
(<= (point) (overlay-end overlay)))))
|
||||||
|
(yas/group-fields group)))
|
||||||
|
(yas/snippet-groups snippet)))
|
||||||
|
(yas/cleanup-snippet snippet))
|
||||||
|
(;;
|
||||||
|
;; Snippet at point, and point inside a snippet field,
|
||||||
|
;; everything is normal
|
||||||
|
;;
|
||||||
|
t
|
||||||
|
nil))))
|
||||||
|
|
||||||
|
(defun yas/debug-some-vars ()
|
||||||
|
(interactive)
|
||||||
|
(with-output-to-temp-buffer "*YASnippet trace*"
|
||||||
|
(princ "Interesting YASnippet vars: \n\n")
|
||||||
|
(princ (format "Register hash-table: %s\n\n" yas/registered-snippets))
|
||||||
|
(cond ((eq (hash-table-count yas/registered-snippets) 0)
|
||||||
|
(princ " No registered snippets\n"))
|
||||||
|
(t
|
||||||
|
(maphash #'(lambda (key snippet)
|
||||||
|
(princ (format "\t key %s for snippet %s with %s groups\n"
|
||||||
|
key
|
||||||
|
(yas/snippet-id snippet)
|
||||||
|
(length (yas/snippet-groups snippet)))))
|
||||||
|
yas/registered-snippets)))
|
||||||
|
(princ (format "\nPost command hook: %s\n" post-command-hook))
|
||||||
|
(princ (format "\nPre command hook: %s\n" pre-command-hook))))
|
||||||
|
|
||||||
|
;;(run-hooks 'yas/after-exit-snippet-hook)))) ;;; XXX: why was this here at top level?
|
||||||
|
|
||||||
(provide 'yasnippet)
|
(provide 'yasnippet)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user