* Rewrite `yas/load-snippet-buffer' yet again, is better.

* Alias `yas/mode-symbol' new variable yas/extra-modes and consolidate.
* ${0: ...} fields try to set the mark on exit, doesn't always work...
This commit is contained in:
capitaomorte 2010-04-13 12:31:12 +00:00
parent 5b25e4205d
commit dc47c98625

View File

@ -56,7 +56,7 @@
;; the list shadow other dir's snippets. Also, the first ;; the list shadow other dir's snippets. Also, the first
;; directory is taken as the default for storing the user's new snippets. ;; directory is taken as the default for storing the user's new snippets.
;; ;;
;; `yas/mode-symbol' ;; `yas/extra-modes'
;; ;;
;; A local variable that you can set in a hook to override ;; A local variable that you can set in a hook to override
;; snippet-lookup based on major mode. It is a a symbol (or ;; snippet-lookup based on major mode. It is a a symbol (or
@ -355,7 +355,7 @@ under the menu \"Yasnippet\".
corresponds to a major mode are listed. corresponds to a major mode are listed.
- If set to `abbreviate', only the current major-mode - If set to `abbreviate', only the current major-mode
menu and the modes set in `yas/mode-symbol' are listed. menu and the modes set in `yas/extra-modes' are listed.
Any other non-nil value, every submenu is listed." Any other non-nil value, every submenu is listed."
:type '(choice (const :tag "Full" t) :type '(choice (const :tag "Full" t)
@ -741,8 +741,8 @@ all defined direct keybindings to the command
(mode major-mode)) (mode major-mode))
(while (setq mode (get mode 'derived-mode-parent)) (while (setq mode (get mode 'derived-mode-parent))
(push mode modes-to-activate)) (push mode modes-to-activate))
(when yas/mode-symbol (dolist (mode (yas/extra-modes))
(push yas/mode-symbol modes-to-activate)) (push mode modes-to-activate))
(dolist (mode modes-to-activate) (dolist (mode modes-to-activate)
(let ((name (intern (format "yas//direct-%s" mode)))) (let ((name (intern (format "yas//direct-%s" mode))))
(set-default name nil) (set-default name nil)
@ -912,7 +912,7 @@ Has the following fields:
A symbol name normally corresponding to a major mode, but can A symbol name normally corresponding to a major mode, but can
also be a pseudo major-mode to be referenced in also be a pseudo major-mode to be referenced in
`yas/mode-symbol', for example. `yas/extra-modes', for example.
`yas/table-hash' `yas/table-hash'
@ -1214,9 +1214,17 @@ return an expression that when evaluated will issue an error."
keybinding name (error-message-string err)) keybinding name (error-message-string err))
nil)))) nil))))
(defvar yas/mode-symbol nil (defvar yas/extra-modes nil
"If non-nil, lookup snippets using this instead of `major-mode'.") "If non-nil, also lookup snippets for this/these modes.
(make-variable-buffer-local 'yas/mode-symbol)
Can be a symbol or a list of symbols.
This variable probably makes more sense as buffer-local, so
ensure your use `make-local-variable' when you set it.")
(defvaralias 'yas/mode-symbol 'yas/extra-modes)
(defun yas/extra-modes ()
(if (listp yas/extra-modes) yas/extra-modes (list yas/extra-modes)))
(defun yas/table-get-create (mode) (defun yas/table-get-create (mode)
"Get the snippet table corresponding to MODE. "Get the snippet table corresponding to MODE.
@ -1239,7 +1247,7 @@ already have such a property."
Return a list of 'yas/table' objects indexed by mode. Return a list of 'yas/table' objects indexed by mode.
The modes are tried in this order: optional MODE-SYMBOL, then The modes are tried in this order: optional MODE-SYMBOL, then
`yas/mode-symbol', then `major-mode' then, unless `yas/extra-modes', then `major-mode' then, unless
DONT-SEARCH-PARENTS is non-nil, the guessed parent mode of either DONT-SEARCH-PARENTS is non-nil, the guessed parent mode of either
MODE-SYMBOL or `major-mode'. MODE-SYMBOL or `major-mode'.
@ -1249,12 +1257,10 @@ Guessing is done by looking up the MODE-SYMBOL's
(mapcar #'(lambda (mode) (mapcar #'(lambda (mode)
(gethash mode yas/tables)) (gethash mode yas/tables))
(append (list mode-symbol) (append (list mode-symbol)
(if (listp yas/mode-symbol) (yas/extra-modes)
yas/mode-symbol
(list yas/mode-symbol))
(list major-mode (list major-mode
(and (not dont-search-parents) (and (not dont-search-parents)
(get (or mode-symbol major-mode) (get major-mode
'derived-mode-parent)))))) 'derived-mode-parent))))))
(all-tables)) (all-tables))
(dolist (table (remove nil mode-tables)) (dolist (table (remove nil mode-tables))
@ -1279,6 +1285,9 @@ them in all `yas/menu-table'"
(yas/table-name parent)) (yas/table-name parent))
(yas/menu-keymap-get-create parent)))) (yas/menu-keymap-get-create parent))))
parents) parents)
(define-key yas/minor-mode-menu (vector mode)
`(menu-item ,(symbol-name mode) ,menu-keymap
:visible (yas/show-menu-p ',mode)))
menu-keymap)) menu-keymap))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -1864,7 +1873,7 @@ not need to be a real mode."
(if (listp parent-mode) (if (listp parent-mode)
parent-mode parent-mode
(list parent-mode)))) (list parent-mode))))
(menu-keymap nil)) (template nil))
;; X) Connect `snippet-table' with `parent-tables'. ;; X) Connect `snippet-table' with `parent-tables'.
;; ;;
;; TODO: this should be a remove-duplicates of the concatenation ;; TODO: this should be a remove-duplicates of the concatenation
@ -1875,21 +1884,15 @@ not need to be a real mode."
(push parent (push parent
(yas/table-parents snippet-table)))) (yas/table-parents snippet-table))))
;; X) The keymap created here here is the menu keymap, it is also
;; gotten/created according to MODE. Make a menu entry for
;; mode
;;
(when yas/use-menu
(setq menu-keymap (yas/menu-keymap-get-create snippet-table))
(define-key yas/minor-mode-menu (vector mode)
`(menu-item ,(symbol-name mode) ,menu-keymap
:visible (yas/show-menu-p ',mode))))
;; X) Now, iterate for evey snippet def list ;; X) Now, iterate for evey snippet def list
;; ;;
(dolist (snippet snippets) (dolist (snippet snippets)
(yas/define-snippets-1 mode snippet snippet-table menu-keymap)))) (setq template (yas/define-snippets-1 snippet
snippet-table
(and yas/use-menu (yas/menu-keymap-get-create snippet-table)))))
template))
(defun yas/define-snippets-1 (mode snippet snippet-table menu-keymap) (defun yas/define-snippets-1 (snippet snippet-table &optional menu-keymap)
"Helper for `yas/define-snippets'." "Helper for `yas/define-snippets'."
;; X) Calculate some more defaults on the values returned by ;; X) Calculate some more defaults on the values returned by
;; `yas/parse-template'. ;; `yas/parse-template'.
@ -1909,7 +1912,6 @@ not need to be a real mode."
name)) name))
(template (or (gethash uuid (yas/table-uuidhash snippet-table)) (template (or (gethash uuid (yas/table-uuidhash snippet-table))
(yas/make-blank-template)))) (yas/make-blank-template))))
;; X) populate the template object ;; X) populate the template object
;; ;;
(yas/populate-template template (yas/populate-template template
@ -1922,10 +1924,10 @@ not need to be a real mode."
:file (seventh snippet) :file (seventh snippet)
:keybinding keybinding :keybinding keybinding
:uuid uuid) :uuid uuid)
;; X) setup the menu groups, reorganizing from group to group if ;; X) Setup the menu groups, reorganizing from group to group if
;; necessary ;; necessary
;; ;;
(when (and yas/use-menu (when (and menu-keymap
(not (cdr (yas/template-menu-binding-pair template)))) (not (cdr (yas/template-menu-binding-pair template))))
(let ((group-keymap menu-keymap)) (let ((group-keymap menu-keymap))
;; Delete this entry from another group if already exists ;; Delete this entry from another group if already exists
@ -1953,7 +1955,11 @@ not need to be a real mode."
;; also will take care of adding the key indicators in the ;; also will take care of adding the key indicators in the
;; templates menu entry, if any ;; templates menu entry, if any
;; ;;
(yas/update-template snippet-table template))) (yas/update-template snippet-table template)
;; X) Return the template
;;
;;
template))
(defun yas/snippet-menu-binding-pair-get-create (template &optional type) (defun yas/snippet-menu-binding-pair-get-create (template &optional type)
"Get TEMPLATE's menu binding or assign it a new one." "Get TEMPLATE's menu binding or assign it a new one."
@ -2326,14 +2332,10 @@ lurking."
(tables (or (and table (tables (or (and table
(list table)) (list table))
(yas/get-snippet-tables)))) (yas/get-snippet-tables))))
;; HACK! the snippet table created here is a dummy table that ;; HACK! the snippet table created here is actually registered!
;; holds the correct name so that `yas/make-directory-maybe' can
;; work. The real table, if it does not exist in
;; yas/tables will be created when the first snippet for
;; that mode is loaded.
;; ;;
(unless (or table (gethash major-mode yas/tables)) (unless (or table (gethash major-mode yas/tables))
(setq tables (cons (yas/make-snippet-table (symbol-name major-mode)) (setq tables (cons (yas/table-get-create major-mode)
tables))) tables)))
(mapcar #'(lambda (table) (mapcar #'(lambda (table)
@ -2368,13 +2370,11 @@ lurking."
(interactive "P") (interactive "P")
(let ((guessed-directories (yas/guess-snippet-directories))) (let ((guessed-directories (yas/guess-snippet-directories)))
(switch-to-buffer (format "*new snippet for %s*" (switch-to-buffer "*new snippet*")
(if guessed-directories
(yas/table-name (car (first guessed-directories)))
"unknown mode")))
(erase-buffer) (erase-buffer)
(set (make-local-variable 'yas/editing-template) nil)
(snippet-mode) (snippet-mode)
(setq yas/guessed-directories guessed-directories) (set (make-local-variable 'yas/guessed-directories) guessed-directories)
(unless (and choose-instead-of-guess (unless (and choose-instead-of-guess
(not (y-or-n-p "Insert a snippet with useful headers? "))) (not (y-or-n-p "Insert a snippet with useful headers? ")))
(yas/expand-snippet "\ (yas/expand-snippet "\
@ -2487,41 +2487,31 @@ With optional prefix argument KILL quit the window and buffer."
:expand-env (sixth parsed) :expand-env (sixth parsed)
:keybinding (yas/read-keybinding (eighth parsed))) :keybinding (yas/read-keybinding (eighth parsed)))
(yas/update-template (yas/template-table yas/editing-template) (yas/update-template (yas/template-table yas/editing-template)
yas/editing-template)) yas/editing-template)))
;; Now, prompt for new file creation much like ;; X) Option 2: We have `yas/guessed-directories', but no
;; `yas/new-snippet' if one of the following is true: ;; `yas/editing-template', which probablt means this buffer's
;; ;; content comes from `yas/new-snippet' call. Prompt user for a
;; 1) `yas/snippet-dirs' is a list and its first element does not ;; table, add the template to the table, then call
;; match this template's file (i.e. this is a library snippet, not ;;
;; a user snippet). ((and (boundp 'yas/guessed-directories)
;; yas/guessed-directories)
;; 2) yas/editing-template comes from a file that we cannot write to... (let* ((yas/prompt-functions '(yas/ido-prompt yas/completing-prompt))
;; (table (or (and yas/guessed-directories
(when (or (and (listp yas/snippet-dirs) (y-or-n-p "Let yasnippet guess tables? ")
(second yas/snippet-dirs) (or (and (second yas/guessed-directories)
(not (string-match (expand-file-name (first yas/snippet-dirs)) (car (some #'(lambda (fn)
(yas/template-file yas/editing-template)))) (funcall fn "Choose from guessed list of tables: "
(and (yas/template-file yas/editing-template) guessed-directories
(not (file-writable-p (yas/template-file yas/editing-template)))) #'(lambda (option)
(not (yas/template-file yas/editing-template))) (yas/table-name (car option)))))
(when (y-or-n-p "[yas] Also save snippet buffer to new file? ") yas/prompt-functions)))
(let* ((option (first (yas/guess-snippet-directories (yas/template-table yas/editing-template)))) (car (first yas/guessed-directories))))
(chosen (and option (yas/table-get-create (intern (read-from-minibuffer "Enter new/existing table: "))))))
(yas/make-directory-maybe option)))) (set (make-local-variable 'yas/editing-template)
(when chosen (yas/define-snippets-1 (yas/parse-template buffer-file-name)
(let ((default-file-name (or (and (yas/template-file yas/editing-template) table
(file-name-nondirectory (yas/template-file yas/editing-template))) (and yas/use-menu (yas/menu-keymap-get-create table))))))
(yas/template-name yas/editing-template)))) (;; X) Option 3: We have a file name, consider this a brand new
(write-file (concat chosen "/"
(read-from-minibuffer (format "File name to create in %s? " chosen)
default-file-name)))
(setf (yas/template-file yas/editing-template) buffer-file-name))))))
(when kill
(quit-window kill))
(message "[yas] Snippet \"%s\" loaded for %s."
(yas/template-name yas/editing-template)
(yas/table-name (yas/template-table yas/editing-template))))
(;; X) Option 2: We have a file name, consider this a brand new
;; snippet and calculate name, groups, etc from the current ;; snippet and calculate name, groups, etc from the current
;; file-name and buffer content ;; file-name and buffer content
;; ;;
@ -2534,63 +2524,47 @@ With optional prefix argument KILL quit the window and buffer."
(name (and parsed (name (and parsed
(third parsed)))) (third parsed))))
(when name (when name
(yas/define-snippets (car major-mode-and-parent) (set (make-local-variable 'yas/editing-template)
(list parsed) (yas/define-snippets (car major-mode-and-parent)
(cdr major-mode-and-parent))) (list parsed)
(when (and (buffer-modified-p) (cdr major-mode-and-parent)))))
(y-or-n-p "Also save snippet buffer? "))
(save-buffer))
(when kill
(quit-window kill))
(message "[yas] Snippet \"%s\" loaded for %s."
name
(car major-mode-and-parent)))
(message (format "[yas] Unknown major mode for snippet at %s" buffer-file-name))))) (message (format "[yas] Unknown major mode for snippet at %s" buffer-file-name)))))
(t
(message (format "[yas] This case not implemented yet"))))
;; Now, offer to save this shit
;;
;; 1) if `yas/snippet-dirs' is a list and its first element does not
;; match this template's file (i.e. this is a library snippet, not
;; a user snippet).
;;
;; 2) yas/editing-template comes from a file that we cannot write to...
;;
;; X) Option 3: We have `yas/guessed-directories', this (when (or (not (yas/template-file yas/editing-template))
;; buffer's content comes from `yas/new-snippet' call. Prompt (not (file-writable-p (yas/template-file yas/editing-template)))
;; user for dir and name in guessed dirs, then call (and (listp yas/snippet-dirs)
;; `yas/load-snippet-buffer' (ourselves) again to load the (second yas/snippet-dirs)
;; snippet based on the file-name. (not (string-match (expand-file-name (first yas/snippet-dirs))
;; (yas/template-file yas/editing-template)))))
((and (boundp 'yas/guessed-directories) (set (make-local-variable 'yas/guessed-directories)
yas/guessed-directories) (yas/guess-snippet-directories (yas/template-table yas/editing-template)))
(let* ((yas/prompt-functions '(yas/ido-prompt yas/completing-prompt)) (when (y-or-n-p "[yas] Also save snippet buffer to new file? ")
(guessed-directories yas/guessed-directories) (let* ((option (first yas/guessed-directories))
(option (or (and (not (y-or-n-p "Let yasnippet guess tables? ")) (chosen (and option
(first (yas/make-directory-maybe option))))
(yas/guess-snippet-directories (when chosen
(some #'(lambda (fn) (let ((default-file-name (or (and (yas/template-file yas/editing-template)
(funcall fn "Choose any snippet table: " (file-name-nondirectory (yas/template-file yas/editing-template)))
(let (res) (yas/template-name yas/editing-template))))
(maphash #'(lambda (k v) (write-file (concat chosen "/"
(push v res)) (read-from-minibuffer (format "File name to create in %s? " chosen)
yas/tables) default-file-name)))
res) (setf (yas/template-file yas/editing-template) buffer-file-name))))))
#'yas/table-name)) (when kill
yas/prompt-functions)))) (quit-window kill))
(and (second guessed-directories) (message "[yas] Snippet \"%s\" loaded for %s."
(some #'(lambda (fn) (yas/template-name yas/editing-template)
(funcall fn "Choose from guessed list of tables: " (yas/table-name (yas/template-table yas/editing-template))))
guessed-directories
#'(lambda (option)
(yas/table-name (car option)))))
yas/prompt-functions))
(first guessed-directories)))
(chosen))
(setq chosen (yas/make-directory-maybe option))
(unless chosen
(when (y-or-n-p "Having trouble... use snippet root dir? ")
(setq chosen (if (listp yas/snippet-dirs)
(first yas/snippet-dirs)
yas/snippet-dirs))))
(when chosen
(let ((default-directory chosen))
(call-interactively 'write-file))
(setq yas/guessed-directories nil)
(setq yas/editing-template nil)
(yas/load-snippet-buffer))))))
(defun yas/tryout-snippet (&optional debug) (defun yas/tryout-snippet (&optional debug)
@ -2996,10 +2970,8 @@ Also create some protection overlays"
(let ((number (yas/field-number field))) (let ((number (yas/field-number field)))
(if (and number (zerop number)) (if (and number (zerop number))
(progn (progn
(setf (yas/snippet-force-exit snippet) `(activate-mark ,(yas/field-start field) ,(yas/field-end field)))
(set-mark (yas/field-end field)) (set-mark (yas/field-end field))
;;(x-set-selection 'PRIMARY (cons (yas/field-start field) (yas/field-end-field))) (setf (yas/snippet-force-exit snippet) t))
(setq transient-mark-mode (cons 'only transient-mark-mode)))
;; primary field transform: first call to snippet transform ;; primary field transform: first call to snippet transform
(unless (yas/field-modified-p field) (unless (yas/field-modified-p field)
(if (yas/field-update-display field snippet) (if (yas/field-update-display field snippet)
@ -3279,9 +3251,6 @@ progress."
(snippet (overlay-get yas/active-field-overlay 'yas/snippet))) (snippet (overlay-get yas/active-field-overlay 'yas/snippet)))
(cond (after? (cond (after?
(yas/advance-end-maybe field (overlay-end overlay)) (yas/advance-end-maybe field (overlay-end overlay))
;; primary field transform: normal calls to expression or
;; force an exit on next `post-command-hook' if the
;; number is 0
(let ((saved-point (point))) (let ((saved-point (point)))
(yas/field-update-display field (car (yas/snippets-at-point))) (yas/field-update-display field (car (yas/snippets-at-point)))
(goto-char saved-point)) (goto-char saved-point))