* More work on yas/load-snippet-buffer, more intuitive now.

This commit is contained in:
capitaomorte 2010-04-16 15:53:23 +00:00
parent dc47c98625
commit 94ca84751d

View File

@ -54,7 +54,11 @@
;; when used for bulk (re)loading of snippets (at startup or ;; when used for bulk (re)loading of snippets (at startup or
;; via `yas/reload-all'), directories appearing earlier in ;; via `yas/reload-all'), directories appearing earlier in
;; 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.
;;
;; The deprecated `yas/root-directory' aliases this variable
;; for backward-compatibility.
;; ;;
;; `yas/extra-modes' ;; `yas/extra-modes'
;; ;;
@ -64,6 +68,9 @@
;; `yas/snippet-dirs' and is used for deciding which ;; `yas/snippet-dirs' and is used for deciding which
;; snippets to consider for the active buffer. ;; snippets to consider for the active buffer.
;; ;;
;; Deprecated `yas/mode-symbol' aliases this variable for
;; backward-compatibility.
;;
;; Major commands are: ;; Major commands are:
;; ;;
;; M-x yas/expand ;; M-x yas/expand
@ -178,6 +185,8 @@ as the default for storing the user's new snippets."
(unless (or (not (fboundp 'yas/reload-all)) (unless (or (not (fboundp 'yas/reload-all))
(equal old new)) (equal old new))
(yas/reload-all))))) (yas/reload-all)))))
(defun yas/snippet-dirs ()
(if (listp yas/snippet-dirs) yas/snippet-dirs (list yas/snippet-dirs)))
(defvaralias 'yas/root-directory 'yas/snippet-dirs) (defvaralias 'yas/root-directory 'yas/snippet-dirs)
(defcustom yas/prompt-functions '(yas/x-prompt (defcustom yas/prompt-functions '(yas/x-prompt
@ -1221,10 +1230,9 @@ Can be a symbol or a list of symbols.
This variable probably makes more sense as buffer-local, so This variable probably makes more sense as buffer-local, so
ensure your use `make-local-variable' when you set it.") ensure your use `make-local-variable' when you set it.")
(defvaralias 'yas/mode-symbol 'yas/extra-modes)
(defun yas/extra-modes () (defun yas/extra-modes ()
(if (listp yas/extra-modes) yas/extra-modes (list yas/extra-modes))) (if (listp yas/extra-modes) yas/extra-modes (list yas/extra-modes)))
(defvaralias 'yas/mode-symbol '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.
@ -1254,19 +1262,18 @@ MODE-SYMBOL or `major-mode'.
Guessing is done by looking up the MODE-SYMBOL's Guessing is done by looking up the MODE-SYMBOL's
`derived-mode-parent' property, see also `derived-mode-p'." `derived-mode-parent' property, see also `derived-mode-p'."
(let ((mode-tables (let ((mode-tables
(mapcar #'(lambda (mode) (remove nil
(gethash mode yas/tables)) (mapcar #'(lambda (mode)
(append (list mode-symbol) (gethash mode yas/tables))
(yas/extra-modes) (remove nil (append (list mode-symbol)
(list major-mode (yas/extra-modes)
(and (not dont-search-parents) (list major-mode
(get major-mode (and (not dont-search-parents)
'derived-mode-parent)))))) (get major-mode
(all-tables)) 'derived-mode-parent)))))))))
(dolist (table (remove nil mode-tables)) (remove-duplicates
(push table all-tables) (append mode-tables
(nconc all-tables (yas/table-get-all-parents table))) (mapcan #'yas/table-get-all-parents mode-tables)))))
(remove-duplicates all-tables)))
(defun yas/menu-keymap-get-create (table) (defun yas/menu-keymap-get-create (table)
"Get or create the main menu keymap correspondong to MODE. "Get or create the main menu keymap correspondong to MODE.
@ -1634,10 +1641,8 @@ content of the file is the template."
"Reload the directories listed in `yas/snippet-dirs' or "Reload the directories listed in `yas/snippet-dirs' or
prompt the user to select one." prompt the user to select one."
(if yas/snippet-dirs (if yas/snippet-dirs
(if (listp yas/snippet-dirs) (dolist (directory (reverse (yas/snippet-dirs)))
(dolist (directory (reverse yas/snippet-dirs)) (yas/load-directory directory))
(yas/load-directory directory))
(yas/load-directory yas/snippet-dirs))
(call-interactively 'yas/load-directory))) (call-interactively 'yas/load-directory)))
(defun yas/reload-all (&optional reset-root-directory) (defun yas/reload-all (&optional reset-root-directory)
@ -1666,12 +1671,7 @@ content of the file is the template."
;; Reload the directories listed in `yas/snippet-dirs' or prompt ;; Reload the directories listed in `yas/snippet-dirs' or prompt
;; the user to select one. ;; the user to select one.
;; ;;
(if yas/snippet-dirs (yas/load-snippet-dirs)
(if (listp yas/snippet-dirs)
(dolist (directory (reverse yas/snippet-dirs))
(yas/load-directory directory))
(yas/load-directory yas/snippet-dirs))
(call-interactively 'yas/load-directory))
;; Reload the direct keybindings ;; Reload the direct keybindings
;; ;;
(yas/direct-keymaps-reload) (yas/direct-keymaps-reload)
@ -2325,18 +2325,16 @@ all the possibly directories where snippets of table might be
lurking." lurking."
(let ((main-dir (replace-regexp-in-string (let ((main-dir (replace-regexp-in-string
"/+$" "" "/+$" ""
(or (and (listp yas/snippet-dirs) (or (first (yas/snippet-dirs))
(first yas/snippet-dirs)) (setq yas/snippet-dirs '("~/.emacs.d/snippets")))))
yas/snippet-dirs
(setq yas/snippet-dirs "~/.emacs.d/snippets"))))
(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 actually registered! ;; HACK! the snippet table created here is actually registered!
;; ;;
(unless (or table (gethash major-mode yas/tables)) (unless (or table (gethash major-mode yas/tables))
(setq tables (cons (yas/table-get-create major-mode) (push (yas/table-get-create major-mode)
tables))) tables))
(mapcar #'(lambda (table) (mapcar #'(lambda (table)
(cons table (cons table
@ -2374,7 +2372,7 @@ lurking."
(erase-buffer) (erase-buffer)
(set (make-local-variable 'yas/editing-template) nil) (set (make-local-variable 'yas/editing-template) nil)
(snippet-mode) (snippet-mode)
(set (make-local-variable 'yas/guessed-directories) guessed-directories) (set (make-local-variable 'yas/guessed-modes) (mapcar #'car 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 "\
@ -2388,7 +2386,7 @@ lurking."
$0")))) $0"))))
(defun yas/find-snippets (&optional same-window ) (defun yas/find-snippets (&optional same-window )
"Look for user snippets in guessed current mode's directory. "Find snippet file in guessed current mode's directory.
Calls `find-file' interactively in the guessed directory. Calls `find-file' interactively in the guessed directory.
@ -2416,9 +2414,7 @@ there, otherwise, proposes to create the first option returned by
(rest guessed-directories))))) (rest guessed-directories)))))
(unless chosen (unless chosen
(when (y-or-n-p "Having trouble... go to snippet root dir? ") (when (y-or-n-p "Having trouble... go to snippet root dir? ")
(setq chosen (if (listp yas/snippet-dirs) (setq chosen (first (yas/snippet-dirs)))))
(first yas/snippet-dirs)
yas/snippet-dirs))))
(if chosen (if chosen
(let ((default-directory chosen)) (let ((default-directory chosen))
(setq buffer (call-interactively (if same-window (setq buffer (call-interactively (if same-window
@ -2433,7 +2429,11 @@ there, otherwise, proposes to create the first option returned by
(defun yas/compute-major-mode-and-parents (file &optional prompt-if-failed) (defun yas/compute-major-mode-and-parents (file &optional prompt-if-failed)
(let* ((file-dir (and file (let* ((file-dir (and file
(directory-file-name (or (locate-dominating-file file ".yas-make-groups") (directory-file-name (or (some #'(lambda (special)
(locate-dominating-file file special))
'(".yas-setup.el"
".yas-make-groups"
".yas-parents"))
(directory-file-name (file-name-directory file)))))) (directory-file-name (file-name-directory file))))))
(parents-file-name (concat file-dir "/.yas-parents")) (parents-file-name (concat file-dir "/.yas-parents"))
(major-mode-name (and file-dir (major-mode-name (and file-dir
@ -2459,112 +2459,112 @@ there, otherwise, proposes to create the first option returned by
(defvar yas/current-template nil (defvar yas/current-template nil
"Holds the current template being expanded into a snippet.") "Holds the current template being expanded into a snippet.")
(defvar yas/guessed-directories nil (defvar yas/guessed-modes nil
"Supporting variable for `yas/load-snippet-buffer' and `yas/new-snippet'") "List of guessed modes supporting `yas/load-snippet-buffer'.")
(defun yas/load-snippet-buffer (&optional kill) (defun yas/load-snippet-buffer (&optional kill)
"Parse and load current buffer's snippet definition. "Parse and load current buffer's snippet definition.
With optional prefix argument KILL quit the window and buffer." With optional prefix argument KILL quit the window and buffer."
(interactive "P") (interactive "P")
(cond
;; X) Option 1: We have `yas/editing-template', this buffer's
;; content comes from a template which is already loaded and
;; neatly positioned,...
;;
((and (boundp 'yas/editing-template)
yas/editing-template
(yas/template-p yas/editing-template))
(let ((parsed (yas/parse-template (yas/template-file yas/editing-template)))) (if (not (or yas/editing-template
;; ... just change its template, expand-env, condition, key, yas/guessed-modes))
;; keybinding and name. The group cannot be changed. ;; X) Option 1: We have nothing to indicate where this snippet
(yas/populate-template yas/editing-template ;; belongs to, guess a mode-list from `buffer-file-name' and
:content (second parsed) ;; call `yas/load-snippet-buffer' again with `yas/guessed-modes'
:key (first parsed) ;; set to it. If not even `buffer-file-name' then use
:name (third parsed) ;; `yas/guessed-modes' set to 'just-prompt.
:condition (fourth parsed) ;;
:expand-env (sixth parsed) (let* ((major-mode-and-parent (yas/compute-major-mode-and-parents buffer-file-name))
:keybinding (yas/read-keybinding (eighth parsed))) (yas/ignore-filenames-as-triggers (or yas/ignore-filenames-as-triggers
(yas/update-template (yas/template-table yas/editing-template) (and buffer-file-name
yas/editing-template))) (locate-dominating-file
;; X) Option 2: We have `yas/guessed-directories', but no buffer-file-name
;; `yas/editing-template', which probablt means this buffer's ".yas-ignore-filenames-as-triggers"))))
;; content comes from `yas/new-snippet' call. Prompt user for a (yas/guessed-modes (or major-mode-and-parent
;; table, add the template to the table, then call 'just-prompt)))
;; (yas/load-snippet-buffer kill))
((and (boundp 'yas/guessed-directories) (cond
yas/guessed-directories) ;; X) Option 1: We have `yas/editing-template', this buffer's
(let* ((yas/prompt-functions '(yas/ido-prompt yas/completing-prompt)) ;; content comes from a template which is already loaded and
(table (or (and yas/guessed-directories ;; neatly positioned,...
(y-or-n-p "Let yasnippet guess tables? ") ;;
(or (and (second yas/guessed-directories) (yas/editing-template
(car (some #'(lambda (fn) (let ((parsed (yas/parse-template (yas/template-file yas/editing-template))))
(funcall fn "Choose from guessed list of tables: " ;; ... just change its template, expand-env, condition, key,
guessed-directories ;; keybinding and name. The group cannot be changed.
#'(lambda (option) (yas/populate-template yas/editing-template
(yas/table-name (car option))))) :content (second parsed)
yas/prompt-functions))) :key (first parsed)
(car (first yas/guessed-directories)))) :name (third parsed)
(yas/table-get-create (intern (read-from-minibuffer "Enter new/existing table: ")))))) :condition (fourth parsed)
(set (make-local-variable 'yas/editing-template) :expand-env (sixth parsed)
(yas/define-snippets-1 (yas/parse-template buffer-file-name) :keybinding (yas/read-keybinding (eighth parsed)))
table (yas/update-template (yas/template-table yas/editing-template)
(and yas/use-menu (yas/menu-keymap-get-create table)))))) yas/editing-template)))
(;; X) Option 3: We have a file name, consider this a brand new ;; X) Option 2: We have `yas/guessed-modes', but no
;; snippet and calculate name, groups, etc from the current ;; `yas/editing-template', which probablt means this buffer's
;; file-name and buffer content ;; content comes from `yas/new-snippet' call. Prompt user for a
;; table, add the template to the table, then call
;;
(yas/guessed-modes
(if (eq yas/guessed-modes 'just-prompt)
(setq yas/guessed-modes nil))
(let* ((prompt (if (and (featurep 'ido)
ido-mode)
'ido-completing-read 'completing-read))
(table (yas/table-get-create
(intern
(funcall prompt (format "Choose or enter a table (yas guesses %s): "
(if yas/guessed-modes
(first yas/guessed-modes)
"nothing"))
(mapcar #'symbol-name yas/guessed-modes)
nil
nil
nil
nil
(if (first yas/guessed-modes)
(symbol-name (first yas/guessed-modes))))))))
(set (make-local-variable 'yas/editing-template)
(yas/define-snippets-1 (yas/parse-template buffer-file-name)
table
(and yas/use-menu (yas/menu-keymap-get-create table)))))))
;; 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...
;; ;;
buffer-file-name
(let ((major-mode-and-parent (yas/compute-major-mode-and-parents buffer-file-name)))
(if major-mode-and-parent
(let* ((yas/ignore-filenames-as-triggers (or yas/ignore-filenames-as-triggers
(locate-dominating-file buffer-file-name ".yas-ignore-filenames-as-triggers")))
(parsed (yas/parse-template buffer-file-name))
(name (and parsed
(third parsed))))
(when name
(set (make-local-variable 'yas/editing-template)
(yas/define-snippets (car major-mode-and-parent)
(list parsed)
(cdr major-mode-and-parent)))))
(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...
;;
(when (or (not (yas/template-file yas/editing-template)) (when (or (not (yas/template-file yas/editing-template))
(not (file-writable-p (yas/template-file yas/editing-template))) (not (file-writable-p (yas/template-file yas/editing-template)))
(and (listp yas/snippet-dirs) (and (listp yas/snippet-dirs)
(second yas/snippet-dirs) (second yas/snippet-dirs)
(not (string-match (expand-file-name (first yas/snippet-dirs)) (not (string-match (expand-file-name (first yas/snippet-dirs))
(yas/template-file yas/editing-template))))) (yas/template-file yas/editing-template)))))
(set (make-local-variable 'yas/guessed-directories) (set (make-local-variable 'yas/guessed-modes)
(yas/guess-snippet-directories (yas/template-table yas/editing-template))) (yas/guess-snippet-directories (yas/template-table yas/editing-template)))
(when (y-or-n-p "[yas] Also save snippet buffer to new file? ") (when (y-or-n-p "[yas] Also save snippet buffer to new file? ")
(let* ((option (first yas/guessed-directories)) (let* ((option (first yas/guessed-modes))
(chosen (and option (chosen (and option
(yas/make-directory-maybe option)))) (yas/make-directory-maybe option))))
(when chosen (when chosen
(let ((default-file-name (or (and (yas/template-file yas/editing-template) (let ((default-file-name (or (and (yas/template-file yas/editing-template)
(file-name-nondirectory (yas/template-file yas/editing-template))) (file-name-nondirectory (yas/template-file yas/editing-template)))
(yas/template-name yas/editing-template)))) (yas/template-name yas/editing-template))))
(write-file (concat chosen "/" (write-file (concat chosen "/"
(read-from-minibuffer (format "File name to create in %s? " chosen) (read-from-minibuffer (format "File name to create in %s? " chosen)
default-file-name))) default-file-name)))
(setf (yas/template-file yas/editing-template) buffer-file-name)))))) (setf (yas/template-file yas/editing-template) buffer-file-name))))))
(when kill (when kill
(quit-window kill)) (quit-window kill))
(message "[yas] Snippet \"%s\" loaded for %s." (message "[yas] Snippet \"%s\" loaded for %s."
(yas/template-name yas/editing-template) (yas/template-name yas/editing-template)
(yas/table-name (yas/template-table yas/editing-template)))) (yas/table-name (yas/template-table yas/editing-template)))))
(defun yas/tryout-snippet (&optional debug) (defun yas/tryout-snippet (&optional debug)
@ -2575,8 +2575,8 @@ With optional prefix argument KILL quit the window and buffer."
(test-mode (or (and (car major-mode-and-parent) (test-mode (or (and (car major-mode-and-parent)
(fboundp (car major-mode-and-parent)) (fboundp (car major-mode-and-parent))
(car major-mode-and-parent)) (car major-mode-and-parent))
(and yas/guessed-directories (and yas/guessed-modes
(intern (yas/table-name (car (first yas/guessed-directories))))) (intern (yas/table-name (car (first yas/guessed-modes)))))
(intern (read-from-minibuffer "[yas] please input a mode: ")))) (intern (read-from-minibuffer "[yas] please input a mode: "))))
(yas/current-template (yas/current-template
(and parsed (and parsed