mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 21:13:04 +00:00
* merged from trunk finally (expect more bugs)
* fixed indentation working * auto-indentation apparently working with dirty hack * , but did get to see the famous python bug twice, * contrived existing python snippets are working, even with `yas/indent-line' set to 'auto * fixed more bugs...
This commit is contained in:
parent
c15f037874
commit
c454bd2451
330
yasnippet.el
330
yasnippet.el
@ -1,10 +1,13 @@
|
||||
;;; yasnippet.el --- Yet another snippet extension for Emacs.
|
||||
|
||||
;; Copyright 2008 pluskid
|
||||
;;
|
||||
|
||||
;; Authors: pluskid <pluskid@gmail.com>, joaotavora <joaotavora@gmail.com>
|
||||
;; Version: 0.6.0
|
||||
;; X-URL: http://code.google.com/p/yasnippet/
|
||||
;; Keywords: snippet, textmate
|
||||
;; URL: http://code.google.com/p/yasnippet/
|
||||
;; EmacsWiki: YaSnippetMode
|
||||
|
||||
;; This file is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@ -35,7 +38,9 @@
|
||||
;; For more information and detailed usage, refer to the project page:
|
||||
;; http://code.google.com/p/yasnippet/
|
||||
|
||||
(require 'cl)
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile (require 'cl))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; User customizable variables
|
||||
@ -244,34 +249,43 @@ Attention: These hooks are not run when exiting nested/stackd snippet expansion!
|
||||
|
||||
(defvar yas/buffer-local-condition
|
||||
'(if (and (not (bobp))
|
||||
(or (equal "font-lock-comment-face"
|
||||
(or (equal 'font-lock-comment-face
|
||||
(get-char-property (1- (point))
|
||||
'face))
|
||||
(equal "font-lock-string-face"
|
||||
(equal 'font-lock-string-face
|
||||
(get-char-property (1- (point))
|
||||
'face))))
|
||||
'(require-snippet-condition . force-in-comment)
|
||||
t)
|
||||
"Condition to yasnippet local to each buffer.
|
||||
|
||||
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'.
|
||||
|
||||
* If yas/buffer-local-condition evaluate to nil, snippet
|
||||
won't 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):
|
||||
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 evaluate to nil or
|
||||
* 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
|
||||
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
|
||||
* If \"requirement\" is eq to \"result\", the snippet is ready
|
||||
to be expanded.
|
||||
* Otherwise the snippet won't be expanded.
|
||||
* If it evaluate to other non-nil value:
|
||||
|
||||
* If it evaluates to `always', snippet is unconditionally
|
||||
expanded.
|
||||
|
||||
* 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.
|
||||
@ -284,6 +298,13 @@ Here's an example:
|
||||
'(if (python-in-string/comment)
|
||||
'(require-snippet-condition . force-in-comment)
|
||||
t))))")
|
||||
(make-variable-buffer-local 'yas/buffer-local-condition)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Utility functions for transformations
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Internal variables
|
||||
@ -415,34 +436,33 @@ You can customize the key through `yas/trigger-key'."
|
||||
(error-message-string err)))
|
||||
nil))))
|
||||
|
||||
|
||||
(defun yas/filter-templates-by-condition (templates)
|
||||
"Filter the templates using the condition. The rules are:
|
||||
"Filter the templates using the applicable condition.
|
||||
|
||||
* If the template has no condition, it is kept.
|
||||
* If the template's condition eval to non-nil, it is kept.
|
||||
* Otherwise (eval error or eval to nil) it is filtered."
|
||||
(remove-if-not '(lambda (pair)
|
||||
(let ((condition (yas/template-condition (cdr pair))))
|
||||
(if (null condition)
|
||||
(if (yas/require-template-condition)
|
||||
nil
|
||||
t)
|
||||
(let ((result
|
||||
(yas/template-condition-predicate condition)))
|
||||
(if (yas/require-template-condition)
|
||||
(if (eq (yas/require-template-condition) t)
|
||||
result
|
||||
(eq result (yas/require-template-condition)))
|
||||
result)))))
|
||||
templates))
|
||||
TEMPLATES is a list of cons (KEY . TEMPLATE) where KEY is a
|
||||
string and TEMPLATE is a `yas/template' structure.
|
||||
|
||||
(defun yas/snippet-table-fetch (table key &optional no-condition)
|
||||
This function implements the rules described in
|
||||
`yas/buffer-local-condition'. See that variables documentation."
|
||||
(let ((requirement (yas/require-template-specific-condition-p)))
|
||||
(if (eq requirement 'always)
|
||||
templates
|
||||
(remove-if-not #'(lambda (pair)
|
||||
(let* ((condition (yas/template-condition (cdr pair)))
|
||||
(result (and condition
|
||||
(yas/template-condition-predicate condition))))
|
||||
(cond ((eq requirement t)
|
||||
result)
|
||||
(t
|
||||
(eq requirement result)))))
|
||||
templates))))
|
||||
|
||||
(defun yas/snippet-table-fetch (table key)
|
||||
"Fetch a snippet binding to KEY from TABLE. If not found,
|
||||
fetch from parent if any."
|
||||
(let* ((unfiltered (gethash key (yas/snippet-table-hash table)))
|
||||
(templates (or (and no-condition
|
||||
unfiltered)
|
||||
(yas/filter-templates-by-condition unfiltered))))
|
||||
(templates (yas/filter-templates-by-condition unfiltered)))
|
||||
(when (and (null templates)
|
||||
(not (null (yas/snippet-table-parent table))))
|
||||
(setq templates (yas/snippet-table-fetch
|
||||
@ -583,26 +603,32 @@ Here's a list of currently recognized variables:
|
||||
* name
|
||||
* contributor
|
||||
* condition
|
||||
* key
|
||||
* group
|
||||
|
||||
#name: #include \"...\"
|
||||
# --
|
||||
#include \"$1\""
|
||||
(goto-char (point-min))
|
||||
(let ((name file-name) template bound condition)
|
||||
(let ((name file-name) template bound condition key group)
|
||||
(if (re-search-forward "^# --\n" nil t)
|
||||
(progn (setq template
|
||||
(buffer-substring-no-properties (point)
|
||||
(point-max)))
|
||||
(setq bound (point))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^#\\([^ ]+\\) *: *\\(.*\\)$" bound t)
|
||||
(while (re-search-forward "^#\\([^ ]+?\\) *: *\\(.*\\)$" bound t)
|
||||
(when (string= "name" (match-string-no-properties 1))
|
||||
(setq name (match-string-no-properties 2)))
|
||||
(when (string= "condition" (match-string-no-properties 1))
|
||||
(setq condition (read (match-string-no-properties 2))))))
|
||||
(setq condition (read (match-string-no-properties 2))))
|
||||
(when (string= "group" (match-string-no-properties 1))
|
||||
(setq group (match-string-no-properties 2)))
|
||||
(when (string= "key" (match-string-no-properties 1))
|
||||
(setq key (match-string-no-properties 2)))))
|
||||
(setq template
|
||||
(buffer-substring-no-properties (point-min) (point-max))))
|
||||
(list template name condition)))
|
||||
(list key template name condition group)))
|
||||
|
||||
(defun yas/directory-files (directory file?)
|
||||
"Return directory files or subdirectories in full path."
|
||||
@ -649,12 +675,14 @@ TEMPLATES."
|
||||
|
||||
(defun yas/prompt-for-keys (keys)
|
||||
"Interactively choose a template key from the list KEYS."
|
||||
(if keys
|
||||
(some #'(lambda (fn)
|
||||
(funcall fn "Choose a snippet key: " keys))
|
||||
yas/prompt-functions))
|
||||
yas/prompt-functions)
|
||||
(message "[yas] no expansions possible here!")))
|
||||
|
||||
(defun yas/x-prompt (prompt choices &optional display-fn)
|
||||
(when window-system
|
||||
(when (and window-system choices)
|
||||
(let ((keymap (cons 'keymap
|
||||
(cons
|
||||
prompt
|
||||
@ -713,10 +741,11 @@ hierarchy."
|
||||
(dolist (file (yas/directory-files directory t))
|
||||
(when (file-readable-p file)
|
||||
(insert-file-contents file nil nil nil t)
|
||||
(let ((snippet-file-name (file-name-nondirectory file)))
|
||||
(push (cons snippet-file-name
|
||||
(yas/parse-template snippet-file-name))
|
||||
snippets)))))
|
||||
(let* ((snip (yas/parse-template))
|
||||
(key (or (car snip)
|
||||
(file-name-nondirectory file)))
|
||||
(snip (cdr snip)))
|
||||
(push (cons key snip) snippets)))))
|
||||
(yas/define-snippets mode-sym
|
||||
snippets
|
||||
parent)
|
||||
@ -779,19 +808,25 @@ all the parameters:
|
||||
(when (null snippet-roots)
|
||||
(setq snippet-roots '("snippets")))
|
||||
(when (null code)
|
||||
(setq code "(yas/initialize)"))
|
||||
(setq code (concat "(yas/initialize-bundle)"
|
||||
"\n;;;###autoload" ; break through so that won't
|
||||
"(require 'yasnippet-bundle)"))) ; be treated as magic comment
|
||||
|
||||
(let ((dirs (or (and (listp snippet-roots) snippet-roots)
|
||||
(list snippet-roots)))
|
||||
(bundle-buffer nil))
|
||||
(with-temp-buffer
|
||||
(setq bundle-buffer (current-buffer))
|
||||
(insert ";;; yasnippet-bundle.el --- "
|
||||
"Yet another snippet extension (Auto compiled bundle)\n")
|
||||
(insert-file-contents yasnippet)
|
||||
(goto-char (point-max))
|
||||
(insert ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n")
|
||||
(insert ";;;; Auto-generated code ;;;;\n")
|
||||
(insert ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n")
|
||||
(insert code "\n")
|
||||
(insert "(defun yas/initialize-bundle ()\n"
|
||||
" \"Initialize YASnippet and load snippets in the bundle.\""
|
||||
" (yas/initialize)\n")
|
||||
(flet ((yas/define-snippets
|
||||
(mode snippets &optional parent)
|
||||
(with-current-buffer bundle-buffer
|
||||
@ -802,15 +837,19 @@ all the parameters:
|
||||
(insert " ("
|
||||
(yas/quote-string (car snippet))
|
||||
" "
|
||||
(yas/quote-string (cadr snippet))
|
||||
(yas/quote-string (nth 1 snippet))
|
||||
" "
|
||||
(if (caddr snippet)
|
||||
(yas/quote-string (caddr snippet))
|
||||
(if (nth 2 snippet)
|
||||
(yas/quote-string (nth 2 snippet))
|
||||
"nil")
|
||||
" "
|
||||
(if (nth 3 snippet)
|
||||
(format "'%s" (nth 3 snippet))
|
||||
"nil")
|
||||
" "
|
||||
(if (nth 4 snippet)
|
||||
(yas/quote-string (nth 4 snippet))
|
||||
"nil")
|
||||
")\n"))
|
||||
(insert " )\n")
|
||||
(insert (if parent
|
||||
@ -820,11 +859,16 @@ all the parameters:
|
||||
(dolist (dir dirs)
|
||||
(dolist (subdir (yas/directory-files dir nil))
|
||||
(yas/load-directory-1 subdir nil))))
|
||||
|
||||
(insert ")\n\n" code "\n")
|
||||
(insert "(provide '"
|
||||
(file-name-nondirectory
|
||||
(file-name-sans-extension
|
||||
yasnippet-bundle))
|
||||
")\n")
|
||||
(insert ";;; "
|
||||
(file-name-nondirectory yasnippet-bundle)
|
||||
" ends here\n")
|
||||
(setq buffer-file-name yasnippet-bundle)
|
||||
(save-buffer))))
|
||||
|
||||
@ -853,9 +897,9 @@ all the parameters:
|
||||
"Define snippets for MODE. SNIPPETS is a list of
|
||||
snippet definition, of the following form:
|
||||
|
||||
(KEY TEMPLATE NAME CONDITION)
|
||||
(KEY TEMPLATE NAME CONDITION GROUP)
|
||||
|
||||
or the NAME and CONDITION may be omitted. The optional 3rd
|
||||
or the NAME, CONDITION or GROUP may be omitted. The optional 3rd
|
||||
parameter can be used to specify the parent mode of MODE. That
|
||||
is, when looking a snippet in MODE failed, it can refer to its
|
||||
parent mode. The PARENT-MODE may not need to be a real mode."
|
||||
@ -880,9 +924,10 @@ parent mode. The PARENT-MODE may not need to be a real mode."
|
||||
(dolist (snippet snippets)
|
||||
(let* ((full-key (car snippet))
|
||||
(key (file-name-sans-extension full-key))
|
||||
(name (or (caddr snippet) (file-name-extension full-key)))
|
||||
(name (or (nth 2 snippet) (file-name-extension full-key)))
|
||||
(condition (nth 3 snippet))
|
||||
(template (yas/make-template (cadr snippet)
|
||||
(group (nth 4 snippet))
|
||||
(template (yas/make-template (nth 1 snippet)
|
||||
(or name key)
|
||||
condition)))
|
||||
(yas/snippet-table-store snippet-table
|
||||
@ -890,10 +935,24 @@ parent mode. The PARENT-MODE may not need to be a real mode."
|
||||
key
|
||||
template)
|
||||
(when yas/use-menu
|
||||
(define-key keymap (vector (make-symbol full-key))
|
||||
(let ((group-keymap keymap))
|
||||
(when (and (not (null group))
|
||||
(not (string= "" group)))
|
||||
(dolist (subgroup (mapcar #'make-symbol
|
||||
(split-string group "\\.")))
|
||||
(let ((subgroup-keymap (lookup-key group-keymap
|
||||
(vector subgroup))))
|
||||
(when (null subgroup-keymap)
|
||||
(setq subgroup-keymap (make-sparse-keymap))
|
||||
(define-key group-keymap (vector subgroup)
|
||||
`(menu-item ,(symbol-name subgroup)
|
||||
,subgroup-keymap)))
|
||||
(setq group-keymap subgroup-keymap))))
|
||||
(define-key group-keymap (vector (make-symbol full-key))
|
||||
`(menu-item ,(yas/template-name template)
|
||||
,(yas/make-menu-binding (yas/template-content template))
|
||||
:keys ,(concat key yas/trigger-symbol))))))))
|
||||
,(yas/make-menu-binding (yas/template-content
|
||||
template))
|
||||
:keys ,(concat key yas/trigger-symbol)))))))))
|
||||
|
||||
(defun yas/set-mode-parent (mode parent)
|
||||
"Set parent mode of MODE to PARENT."
|
||||
@ -905,7 +964,7 @@ parent mode. The PARENT-MODE may not need to be a real mode."
|
||||
`(menu-item "parent mode"
|
||||
,(yas/menu-keymap-for-mode parent)))))
|
||||
|
||||
(defun yas/define (mode key template &optional name condition)
|
||||
(defun yas/define (mode key template &optional name condition group)
|
||||
"Define a snippet. Expanding KEY into TEMPLATE.
|
||||
NAME is a description to this template. Also update
|
||||
the menu if `yas/use-menu' is `t'. CONDITION is the
|
||||
@ -913,7 +972,7 @@ condition attached to this snippet. If you attach a
|
||||
condition to a snippet, then it will only be expanded
|
||||
when the condition evaluated to non-nil."
|
||||
(yas/define-snippets mode
|
||||
(list (list key template name condition))))
|
||||
(list (list key template name condition group))))
|
||||
|
||||
(defun yas/hippie-try-expand (first-time?)
|
||||
"Integrate with hippie expand. Just put this function in
|
||||
@ -924,14 +983,18 @@ when the condition evaluated to non-nil."
|
||||
(undo 1)
|
||||
nil))
|
||||
|
||||
(defun yas/require-template-condition ()
|
||||
(defun yas/require-template-specific-condition-p ()
|
||||
"Decides if this buffer requests/requires snippet-specific
|
||||
conditions to filter out potential expansions."
|
||||
(if (eq 'always yas/buffer-local-condition)
|
||||
'always
|
||||
(let ((local-condition (yas/template-condition-predicate
|
||||
yas/buffer-local-condition)))
|
||||
(and local-condition
|
||||
(consp local-condition)
|
||||
(eq 'require-snippet-condition (car local-condition))
|
||||
(symbolp (cdr local-condition))
|
||||
(cdr local-condition))))
|
||||
(cdr local-condition)))))
|
||||
|
||||
(defun yas/expand (&optional field)
|
||||
"Expand a snippet."
|
||||
@ -954,15 +1017,21 @@ when the condition evaluated to non-nil."
|
||||
(when (commandp command)
|
||||
(call-interactively command)))))))
|
||||
|
||||
(defun yas/choose-snippet ()
|
||||
(defun yas/choose-snippet (&optional no-condition)
|
||||
"Choose a snippet to expand, pop-up a list of choices according
|
||||
to `yas/prompt-function'."
|
||||
(interactive)
|
||||
(let* ((templates (mapcar #'cdr
|
||||
to `yas/prompt-function'.
|
||||
|
||||
With prefix argument NO-CONDITION, bypass filtering of snippets
|
||||
by condition."
|
||||
(interactive "P")
|
||||
(let* ((yas/buffer-local-condition (or (and no-condition
|
||||
'always)
|
||||
yas/buffer-local-condition))
|
||||
(templates (mapcar #'cdr
|
||||
(if yas/choose-keys-first
|
||||
(let ((key (yas/prompt-for-keys (yas/snippet-table-all-keys (yas/current-snippet-table)))))
|
||||
(when key
|
||||
(yas/snippet-table-fetch (yas/current-snippet-table) key 'no-condition)))
|
||||
(yas/snippet-table-fetch (yas/current-snippet-table) key)))
|
||||
(yas/snippet-table-all-templates (yas/current-snippet-table)))))
|
||||
(template-content (and templates
|
||||
(or (and (rest templates) ;; more than one template for same key
|
||||
@ -978,7 +1047,19 @@ to `yas/prompt-function'."
|
||||
;;; User conveniente functions, for using in snippet definitions
|
||||
;;;
|
||||
|
||||
(defun yas/substr (str pattern &optional subexp)
|
||||
"Search PATTERN in STR and return SUBEXPth match.
|
||||
|
||||
If found, the content of subexp group SUBEXP (default 0) is
|
||||
returned, or else the original STR will be returned."
|
||||
(let ((grp (or subexp 0)))
|
||||
(save-match-data
|
||||
(if (string-match pattern str)
|
||||
(match-string-no-properties grp str)
|
||||
str))))
|
||||
|
||||
(defun yas/choose-value (&rest possibilities)
|
||||
"Prompt for a string in the list POSSIBILITIES."
|
||||
(some #'(lambda (fn)
|
||||
(funcall fn "Choose: " possibilities))
|
||||
yas/prompt-functions))
|
||||
@ -987,11 +1068,14 @@ to `yas/prompt-function'."
|
||||
(throw 'yas/exception (cons 'yas/exception text)))
|
||||
|
||||
(defun yas/verify-value (&rest possibilities)
|
||||
"Verify that the current field value is in POSSIBILITIES
|
||||
|
||||
Otherwise throw exception."
|
||||
(when (and yas/moving-away (notany #'(lambda (pos) (string= pos yas/text)) possibilities))
|
||||
(yas/throw (format "[yas] field only allows %s" possibilities))))
|
||||
|
||||
(defun yas/field-value (number)
|
||||
(let ((snippet (car (yas/snippets-at-point)))
|
||||
(let* ((snippet (car (yas/snippets-at-point)))
|
||||
(field (and snippet
|
||||
(yas/snippet-find-field snippet number))))
|
||||
(when field
|
||||
@ -1016,10 +1100,9 @@ to `yas/prompt-function'."
|
||||
(defvar yas/start-column nil
|
||||
"The column where the snippet expansion started.")
|
||||
|
||||
(eval-when-compile
|
||||
(make-variable-buffer-local 'yas/active-field-overlay)
|
||||
(make-variable-buffer-local 'yas/field-protection-overlays)
|
||||
(make-variable-buffer-local 'yas/deleted-text))
|
||||
(make-variable-buffer-local 'yas/active-field-overlay)
|
||||
(make-variable-buffer-local 'yas/field-protection-overlays)
|
||||
(make-variable-buffer-local 'yas/deleted-text)
|
||||
|
||||
(defstruct (yas/snippet (:constructor yas/make-snippet ()))
|
||||
"A snippet.
|
||||
@ -1061,8 +1144,13 @@ for this field, apply it. Otherwise, returned nil."
|
||||
(transform (if (yas/mirror-p field-or-mirror)
|
||||
(yas/mirror-transform field-or-mirror)
|
||||
(yas/field-transform field-or-mirror)))
|
||||
(start-point (if (yas/mirror-p field-or-mirror)
|
||||
(yas/mirror-start field-or-mirror)
|
||||
(yas/field-start field-or-mirror)))
|
||||
(transformed (and transform
|
||||
(yas/eval-string transform))))
|
||||
(save-excursion
|
||||
(goto-char start-point)
|
||||
(yas/eval-string transform)))))
|
||||
transformed))
|
||||
|
||||
(defsubst yas/replace-all (from to)
|
||||
@ -1350,7 +1438,7 @@ snippet, if so cleans up the whole snippet up."
|
||||
(eq this-command 'undo)
|
||||
(eq this-command 'redo)))
|
||||
|
||||
(defun yas/make-control-overlay (start end)
|
||||
(defun yas/make-control-overlay (snippet start end)
|
||||
"Creates the control overlay that surrounds the snippet and
|
||||
holds the keymap."
|
||||
(let ((overlay (make-overlay start
|
||||
@ -1544,27 +1632,9 @@ will be deleted before inserting template."
|
||||
;; updates its mirrors once, so we are left with some plain text.
|
||||
;; The undo action for deleting this plain text will get recorded
|
||||
;; at the end of this function.
|
||||
;;
|
||||
;; (save-restriction
|
||||
;; (narrow-to-region end end)
|
||||
;; (condition-case err
|
||||
;; (let ((buffer-undo-list t))
|
||||
;; ;; snippet creation might evaluate users elisp, which
|
||||
;; ;; might generate errors, so we have to be ready to catch
|
||||
;; ;; them mostly to make the undo information
|
||||
;; ;;
|
||||
;; (insert template)
|
||||
;; (setq yas/deleted-text key)
|
||||
;; (setq yas/selected-text (if mark-active key ""))
|
||||
;; (setq snippet (yas/snippet-create (point-min) (point-max))))
|
||||
;; (error
|
||||
;; (push (cons (point-min) (point-max)) buffer-undo-list)
|
||||
;; (error (cadr err)))))
|
||||
|
||||
|
||||
|
||||
(save-restriction
|
||||
(narrow-to-region start start)
|
||||
(condition-case err
|
||||
(let ((buffer-undo-list t))
|
||||
;; snippet creation might evaluate users elisp, which
|
||||
;; might generate errors, so we have to be ready to catch
|
||||
@ -1574,7 +1644,10 @@ will be deleted before inserting template."
|
||||
(insert template)
|
||||
(setq yas/deleted-text key)
|
||||
(setq yas/selected-text (when mark-active key))
|
||||
(setq snippet (yas/snippet-create (point-min) (point-max)))))
|
||||
(setq snippet (yas/snippet-create (point-min) (point-max))))
|
||||
(error
|
||||
(push (cons (point-min) (point-max)) buffer-undo-list)
|
||||
(error (format "[yas] parse error: %s" (cadr err))))))
|
||||
|
||||
;; stacked-expansion: This checks for stacked expansion, save the
|
||||
;; `yas/previous-active-field' and advance its boudary.
|
||||
@ -1631,7 +1704,7 @@ After revival, push the `yas/take-care-of-redo' in the
|
||||
(let ((target-field (or (yas/snippet-active-field snippet)
|
||||
(car (yas/snippet-fields snippet)))))
|
||||
(when target-field
|
||||
(setf (yas/snippet-control-overlay snippet) (yas/make-control-overlay beg end))
|
||||
(setf (yas/snippet-control-overlay snippet) (yas/make-control-overlay snippet beg end))
|
||||
(overlay-put (yas/snippet-control-overlay snippet) 'yas/snippet snippet)
|
||||
|
||||
(yas/move-to-field snippet target-field)
|
||||
@ -1657,7 +1730,7 @@ Returns the newly created snippet."
|
||||
(yas/update-mirrors snippet)
|
||||
|
||||
;; Create keymap overlay for snippet
|
||||
(setf (yas/snippet-control-overlay snippet) (yas/make-control-overlay (point-min) (point-max)))
|
||||
(setf (yas/snippet-control-overlay snippet) (yas/make-control-overlay snippet (point-min) (point-max)))
|
||||
|
||||
;; Move to end
|
||||
(goto-char (point-max))
|
||||
@ -1702,14 +1775,14 @@ Meant to be called in a narrowed buffer, does various passes"
|
||||
;;
|
||||
(goto-char parse-start)
|
||||
(yas/field-parse-create snippet)
|
||||
;; parse mirror transforms
|
||||
;;
|
||||
(goto-char parse-start)
|
||||
(yas/transform-mirror-parse-create snippet)
|
||||
;; parse simple mirrors
|
||||
;;
|
||||
(goto-char parse-start)
|
||||
(yas/simple-mirror-parse-create snippet)
|
||||
;; parse mirror transforms
|
||||
;;
|
||||
(goto-char parse-start)
|
||||
(yas/transform-mirror-parse-create snippet)
|
||||
;; restore escapes
|
||||
;;
|
||||
(goto-char parse-start)
|
||||
@ -1720,21 +1793,21 @@ Meant to be called in a narrowed buffer, does various passes"
|
||||
(yas/indent snippet)))
|
||||
|
||||
(defun yas/indent (snippet)
|
||||
;;; XXX: fixed indentation not working
|
||||
(save-excursion
|
||||
(cond ((eq yas/indent-line 'fixed)
|
||||
(let ((fill-prefix (make-string yas/start-column ? )))
|
||||
(indent-region (point-min) (point-max))))
|
||||
(let* ((indent (if indent-tabs-mode
|
||||
(concat (make-string (/ column tab-width) ?\t)
|
||||
(make-string (% column tab-width) ?\ ))
|
||||
(make-string (current-colum) ?\ ))))
|
||||
(goto-char (point-min))
|
||||
(while (and (zerop (forward-line))
|
||||
(= (current-column) 0))
|
||||
(insert indent))))
|
||||
((eq yas/indent-line 'auto)
|
||||
(let ((begin (point-min))
|
||||
(end (point-max)))
|
||||
(let ((end (set-marker (make-marker) (point-max))))
|
||||
(save-restriction
|
||||
(widen)
|
||||
(indent-region (line-beginning-position) (point-max))
|
||||
(when (yas/snippet-exit snippet)
|
||||
(goto-char (yas/snippet-exit snippet))
|
||||
(indent-according-to-mode)
|
||||
;; XXX: Here is the indent problem:
|
||||
;; XXX: Here seems to be the indent problem:
|
||||
;;
|
||||
;; `indent-according-to-mode' uses whatever
|
||||
;; `indent-line-function' is available. Some
|
||||
@ -1747,7 +1820,13 @@ Meant to be called in a narrowed buffer, does various passes"
|
||||
;; This would also happen if we had used overlays with
|
||||
;; the `front-advance' property set to nil.
|
||||
;;
|
||||
(set-marker (yas/snippet-exit snippet) (point))))))
|
||||
(while (and (zerop (forward-line))
|
||||
(<= (point) end))
|
||||
(goto-char (yas/real-line-beginning))
|
||||
(insert-before-markers "Y")
|
||||
(indent-according-to-mode)
|
||||
(backward-delete-char 1))
|
||||
(set-marker end nil))))
|
||||
(t
|
||||
nil)))
|
||||
(save-excursion
|
||||
@ -1756,6 +1835,15 @@ Meant to be called in a narrowed buffer, does various passes"
|
||||
(when (not (eq yas/indent-line 'auto))
|
||||
(indent-according-to-mode)))))
|
||||
|
||||
(defun yas/real-line-beginning ()
|
||||
(let ((c (char-after (line-beginning-position)))
|
||||
(n (line-beginning-position)))
|
||||
(while (or (eql c ?\ )
|
||||
(eql c ?\t))
|
||||
(incf n)
|
||||
(setq c (char-after n)))
|
||||
n))
|
||||
|
||||
|
||||
(defun yas/escape-string (escaped)
|
||||
(concat "YASESCAPE" (format "%d" escaped) "PROTECTGUARD"))
|
||||
@ -1783,6 +1871,13 @@ Meant to be called in a narrowed buffer, does various passes"
|
||||
(insert transformed)
|
||||
(delete-region (match-beginning 0) (match-end 0)))))
|
||||
|
||||
(defun yas/scan-sexps (from count)
|
||||
(condition-case err
|
||||
(with-syntax-table (standard-syntax-table)
|
||||
(scan-sexps from count))
|
||||
(error
|
||||
nil)))
|
||||
|
||||
(defun yas/field-parse-create (snippet &optional parent-field)
|
||||
"Parse most field expression, except for the simple one \"$n\".
|
||||
|
||||
@ -1795,12 +1890,12 @@ The following count as a field:
|
||||
When multiple expressions are found, only the last one counts."
|
||||
(save-excursion
|
||||
(while (re-search-forward yas/field-regexp nil t)
|
||||
(let* ((real-match-end-0 (scan-sexps (1+ (match-beginning 0)) 1))
|
||||
(let* ((real-match-end-0 (yas/scan-sexps (1+ (match-beginning 0)) 1))
|
||||
(number (and (match-string-no-properties 1)
|
||||
(string-to-number (match-string-no-properties 1))))
|
||||
(brand-new-field (and real-match-end-0
|
||||
(not (save-match-data
|
||||
(eq (string-match "$(" (match-string-no-properties 2)) 0)))
|
||||
(eq (string-match "$[ \t\n]+(" (match-string-no-properties 2)) 0)))
|
||||
(not (and number (zerop number)))
|
||||
(yas/make-field number
|
||||
(set-marker (make-marker) (match-beginning 2))
|
||||
@ -1818,7 +1913,7 @@ When multiple expressions are found, only the last one counts."
|
||||
(when parent-field
|
||||
(save-excursion
|
||||
(while (re-search-forward yas/multi-dollar-lisp-expression-regexp nil t)
|
||||
(let* ((real-match-end-0 (scan-sexps (1+ (match-beginning 0)) 1)))
|
||||
(let* ((real-match-end-0 (yas/scan-sexps (1+ (match-beginning 0)) 1)))
|
||||
(when real-match-end-0
|
||||
(let ((lisp-expression-string (buffer-substring-no-properties (match-beginning 1) real-match-end-0)))
|
||||
(setf (yas/field-transform parent-field) lisp-expression-string))
|
||||
@ -1827,7 +1922,7 @@ 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 (scan-sexps (1+ (match-beginning 0)) 1))
|
||||
(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))
|
||||
@ -2008,3 +2103,14 @@ handle the end-of-buffer error fired in it by calling
|
||||
(condition-case 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 ()
|
||||
(make-variable-buffer-local 'yas/keymap)
|
||||
(dolist (k '(":" ">" ";" "<" "{" "}"))
|
||||
(define-key yas/keymap
|
||||
k 'self-insert-command))))
|
||||
|
||||
|
||||
;;; yasnippet.el ends here
|
||||
|
Loading…
x
Reference in New Issue
Block a user