(equal old new))
(yas/reload-all)))))
(defun yas/snippet-dirs ()
+ "Returns `yas/snippet-dirs' (which see) as a list."
(if (listp yas/snippet-dirs) yas/snippet-dirs (list yas/snippet-dirs)))
(defvaralias 'yas/root-directory 'yas/snippet-dirs)
(defstruct (yas/template (:constructor yas/make-blank-template))
"A template for a snippet."
- table
key
content
name
menu-binding-pair
group ;; as dictated by the #group: directive or .yas-make-groups
perm-group ;; as dictated by `yas/define-menu'
+ table
)
(defun yas/populate-template (template &rest args)
(save-match-data
(eval condition))))
(error (progn
- (message (format "[yas] error in condition evaluation: %s"
- (error-message-string err)))
+ (yas/message 1 "Error in condition evaluation: %s" (error-message-string err))
nil))))
(when result
(format "%s" result))))))
(error (if yas/good-grace
- (format "[yas] elisp error! %s" (error-message-string err))
- (error (format "[yas] elisp error: %s"
+ (yas/format "elisp error! %s" (error-message-string err))
+ (error (yas/format "elisp error: %s"
(error-message-string err)))))))))
(when (and (consp retval)
(eq 'yas/exception (car retval)))
(condition-case err
(eval form)
(error (if yas/good-grace
- (format "[yas] elisp error! %s" (error-message-string err))
- (error (format "[yas] elisp error: %s"
+ (yas/format "elisp error! %s" (error-message-string err))
+ (error (yas/format "elisp error: %s"
(error-message-string err)))))))
(defun yas/read-lisp (string &optional nil-on-error)
(read-kbd-macro keybinding 'need-vector))))
res)
(error
- (message "[yas] warning: keybinding \"%s\" invalid since %s."
+ (yas/message 3 "warning: keybinding \"%s\" invalid since %s."
keybinding (error-message-string err))
nil))))
(setq binding (match-string-no-properties 2)))))
(setq template
(buffer-substring-no-properties (point-min) (point-max))))
+ (unless (or key binding)
+ (setq key (and file (file-name-nondirectory file))))
(when (eq type 'command)
(setq template (yas/read-lisp (concat "(progn" template ")"))))
(when group
(keyboard-quit))))
(defun yas/ido-prompt (prompt choices &optional display-fn)
- (when (featurep 'ido)
+ (when (fboundp 'ido-completing-read)
(yas/completing-prompt prompt choices display-fn #'ido-completing-read)))
(eval-when-compile (require 'dropdown-list nil t))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Loading snippets from files
;;
-(defun yas/load-directory-1 (directory mode-sym &optional no-compiled-snippets)
- "Recursively load snippet templates from DIRECTORY."
- (unless (file-exists-p (concat directory "/" ".yas-skip"))
- ;; Load .yas-setup.el files wherever we find them
- ;;
- (load (expand-file-name ".yas-setup" directory) 'noerror)
- (if (and (not no-compiled-snippets)
- (load (expand-file-name ".yas-compiled-snippets" directory) 'noerror))
- (message "[yas] Loading much faster .yas-compiled-snippets from %s" directory)
- (let* ((default-directory directory)
- (snippet-defs nil))
- ;; load the snippet files
- ;;
- (with-temp-buffer
- (dolist (file (yas/subdirs directory 'no-subdirs-just-files))
- (when (file-readable-p file)
- (insert-file-contents file nil nil nil t)
- (push (yas/parse-template file)
- snippet-defs))))
- (when (or snippet-defs
- (cdr major-mode-and-parents))
- (yas/define-snippets mode-sym
- snippet-defs))
- ;; now recurse to a lower level
- ;;
- (dolist (subdir (yas/subdirs directory))
- (yas/load-directory-1 subdir
- mode-sym
- t))))))
+(defun yas/load-yas-setup-file (file)
+ (load file 'noerror))
-(defun yas/load-directory (top-level-dir)
+(defun yas/load-directory (top-level-dir &optional nojit)
"Load snippet definition from directory hierarchy under TOP-LEVEL-DIR.
-Below TOP-LEVEL-DIR., each directory is a mode name."
+Below TOP-LEVEL-DIR each directory is a mode name."
(interactive "DSelect the root directory: ")
(unless (file-directory-p top-level-dir)
(error "%s is not a directory" top-level-dir))
(concat dir "/dummy")))
(mode-sym (car major-mode-and-parents))
(parents (cdr major-mode-and-parents)))
- (puthash mode-sym (remove-duplicates
- (append parents
- (gethash mode-sym yas/parents)))
- yas/parents)
- (yas/schedule-jit mode-sym
- `(yas/load-directory-1 ,dir
- ',mode-sym))))
+ (yas/define-parents mode-sym parents)
+ (let ((form `(yas/load-directory-1 ,dir
+ ',mode-sym
+ ',parents)))
+ (if (or (called-interactively-p)
+ nojit)
+ (eval form)
+ (yas/schedule-jit mode-sym form)))))
(when (interactive-p)
- (message "[yas] Loaded snippets from %s." top-level-dir)))
+ (yas/message 3 "Loaded snippets from %s." top-level-dir)))
+
+(defun yas/load-directory-1 (directory mode-sym parents &optional no-compiled-snippets)
+ "Recursively load snippet templates from DIRECTORY."
+ (unless (file-exists-p (concat directory "/" ".yas-skip"))
+ (if (and (not no-compiled-snippets)
+ (load (expand-file-name ".yas-compiled-snippets" directory) 'noerror))
+ (message "[yas] Loading much faster .yas-compiled-snippets from %s" directory)
+ (yas/load-directory-2 directory mode-sym parents))))
-(defun yas/load-snippet-dirs ()
+(defun yas/load-directory-2 (directory mode-sym parents)
+ ;; Load .yas-setup.el files wherever we find them
+ ;;
+ (yas/load-yas-setup-file (expand-file-name ".yas-setup" directory))
+ (let* ((default-directory directory)
+ (snippet-defs nil))
+ ;; load the snippet files
+ ;;
+ (with-temp-buffer
+ (dolist (file (yas/subdirs directory 'no-subdirs-just-files))
+ (when (file-readable-p file)
+ (insert-file-contents file nil nil nil t)
+ (push (yas/parse-template file)
+ snippet-defs))))
+ (when snippet-defs
+ (yas/define-snippets mode-sym
+ snippet-defs))
+ ;; now recurse to a lower level
+ ;;
+ (dolist (subdir (yas/subdirs directory))
+ (yas/load-directory-2 subdir
+ mode-sym
+ nil))))
+
+(defun yas/load-snippet-dirs (&optional nojit)
"Reload the directories listed in `yas/snippet-dirs' or
prompt the user to select one."
- (if yas/snippet-dirs
- (dolist (directory (reverse (yas/snippet-dirs)))
- (yas/load-directory directory))
- (call-interactively 'yas/load-directory)))
-
-(defun yas/reload-all (&optional with-jit)
+ (let (errors)
+ (if yas/snippet-dirs
+ (dolist (directory (reverse (yas/snippet-dirs)))
+ (condition-case oops
+ (progn
+ (yas/load-directory directory nojit)
+ (yas/message 3 "Loaded %s" directory))
+ (error (push oops errors)
+ (yas/message 3 "Check your `yas/snippet-dirs': %s" (second oops)))))
+ (call-interactively 'yas/load-directory))
+ errors))
+
+(defun yas/reload-all (&optional nojit)
"Reload all snippets and rebuild the YASnippet menu. "
(interactive "p")
(let ((errors))
;; Reload the directories listed in `yas/snippet-dirs' or prompt
;; the user to select one.
;;
- (condition-case oops
- (yas/load-snippet-dirs)
- (error (push oops errors)
- (message "[yas] Check your `yas/snippet-dirs': %s" (second oops))))
+ (setq errors (yas/load-snippet-dirs nojit))
;; Reload the direct keybindings
;;
(yas/direct-keymaps-reload)
- (message "[yas] Reloaded everything...%s." (if errors " (some errors, check *Messages*)" ""))))
+ (yas/message 3 "Reloaded everything...%s." (if errors " (some errors, check *Messages*)" ""))))
(defun yas/quote-string (string)
"Escape and quote STRING.
"For backward compatibility, enable `yas/minor-mode' globally"
(yas/global-mode 1))
-(defun yas/compile-top-level-dir (top-level-dir)
- "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR."
+(defun yas/compile-directory (top-level-dir)
+ "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR.
+
+This works by stubbing a few functions, then calling
+`yas/load-directory'."
(interactive "DTop level snippet directory?")
- (dolist (dir (yas/subdirs top-level-dir))
- (yas/compile-snippets dir)))
-
-(defun yas/compile-snippets (input-dir &optional output-file)
- "Compile snippets files in INPUT-DIR to OUTPUT-FILE file.
-
-Prompts for INPUT-DIR and OUTPUT-FILE if called-interactively"
- (interactive (let* ((input-dir (read-directory-name "Snippet dir "))
- (output-file (let ((ido-everywhere nil))
- (read-file-name "Output file "
- input-dir nil nil
- ".yas-compiled-snippets.el"
- nil))))
- (list input-dir output-file)))
- (let ((default-directory input-dir))
- (with-temp-file (setq output-file (or output-file ".yas-compiled-snippets.el"))
- (flet ((yas/define-snippets
- (mode snippets)
- (insert (format ";;; %s - automatically compiled snippets for `%s' , do not edit!\n"
- (file-name-nondirectory output-file) mode))
- (insert ";;;\n")
- (let ((literal-snippets (list)))
- (dolist (snippet snippets)
- (let ((key (first snippet))
- (template-content (second snippet))
- (name (third snippet))
- (condition (fourth snippet))
- (group (fifth snippet))
- (expand-env (sixth snippet))
- (file nil) ;; (seventh snippet)) ;; omit on purpose
- (binding (eighth snippet))
- (uuid (ninth snippet)))
- (push `(,key
- ,template-content
- ,name
- ,condition
- ,group
- ,expand-env
- ,file
- ,binding
- ,uuid)
- literal-snippets)))
- (insert (pp-to-string `(yas/define-snippets ',mode ',literal-snippets ',parent-or-parents)))
- (insert "\n\n")
- (insert (format ";;; %s - automatically compiled snippets for `%s' end here\n"
- (file-name-nondirectory output-file) mode))
- (insert ";;;"))))
- (yas/load-directory-1 input-dir nil 'no-compiled-snippets))))
-
- (if (and (called-interactively-p)
- (yes-or-no-p (format "Open the resulting file (%s)? "
- (expand-file-name output-file))))
- (find-file-other-window output-file)))
+ (flet ((yas/load-yas-setup-file
+ (file)
+ (let ((elfile (concat file ".el")))
+ (when (file-exists-p elfile)
+ (insert ";;; .yas-setup.el support file if any:\n;;;\n")
+ (insert-file-contents elfile))))
+ (yas/define-snippets
+ (mode snippets)
+ (insert ";;; Snippet definitions:\n;;;\n")
+ (let ((literal-snippets (list)))
+ (dolist (snippet snippets)
+ (let ((key (first snippet))
+ (template-content (second snippet))
+ (name (third snippet))
+ (condition (fourth snippet))
+ (group (fifth snippet))
+ (expand-env (sixth snippet))
+ (file nil) ;; (seventh snippet)) ;; omit on purpose
+ (binding (eighth snippet))
+ (uuid (ninth snippet)))
+ (push `(,key
+ ,template-content
+ ,name
+ ,condition
+ ,group
+ ,expand-env
+ ,file
+ ,binding
+ ,uuid)
+ literal-snippets)))
+ (insert (pp-to-string `(yas/define-snippets ',mode ',literal-snippets)))
+ (insert "\n\n")))
+ (yas/load-directory-1
+ (dir mode parents &rest ignore)
+ (let ((output-file (concat (file-name-as-directory dir) ".yas-compiled-snippets.el")))
+ (with-temp-file output-file
+ (insert (format ";;; Compiled snippets and support files for `%s'\n" mode))
+ (yas/load-directory-2 dir mode parents)
+ (insert (format ";;; Do not edit! File generated at %s\n" (current-time-string)))))))
+ (yas/load-directory top-level-dir 'im-compiling-so-no-jit-ok?)))
+
+(defun yas/recompile-all ()
+ (mapc #'yas/compile-directory (yas/snippet-dirs)))
;;; JIT loading
yas/version
") -- pluskid <pluskid@gmail.com>/joaotavora <joaotavora@gmail.com>")))
+(defun yas/define-parents (mode parents)
+ "Add PARENTS to the list of MODE's parents"
+ (puthash mode-sym (remove-duplicates
+ (append parents
+ (gethash mode-sym yas/parents)))
+ yas/parents))
+
(defun yas/define-snippets (mode snippets)
"Define SNIPPETS for MODE.
(define-key keymap (vector (gensym))
'(menu-item "----")))
(t
- (message "[yas] Don't know anything about menu entry %s" (first e))))))
+ (yas/message 3 "Don't know anything about menu entry %s" (first e))))))
(defun yas/define (mode key template &optional name condition group)
"Define a snippet. Expanding KEY into TEMPLATE.
(car where)
(cdr where)
(yas/template-expand-env yas/current-template))
- (message "[yas] No snippets can be inserted here!"))))
+ (yas/message 3 "No snippets can be inserted here!"))))
(defun yas/visit-snippet-file ()
"Choose a snippet to edit, selection like `yas/insert-snippet'.
(or (some #'(lambda (dir) (when (file-directory-p dir) dir)) (cdr table-and-dirs))
(let ((candidate (first (cdr table-and-dirs))))
(unless (file-writable-p (file-name-directory candidate))
- (error "[yas] %s is not writable." candidate))
+ (error (yas/format "%s is not writable." candidate)))
(if (y-or-n-p (format "Guessed directory (%s) for%s%s table \"%s\" does not exist! Create? "
candidate
(if (gethash (intern (yas/table-name (car table-and-dirs)))
(not (string-match (expand-file-name (first yas/snippet-dirs))
(yas/template-file yas/editing-template)))))
- (when (y-or-n-p "[yas] Looks like a library or new snippet. Save to new file? ")
+ (when (y-or-n-p (yas/format "Looks like a library or new snippet. Save to new file? "))
(let* ((option (first (yas/guess-snippet-directories (yas/template-table yas/editing-template))))
(chosen (and option
(yas/make-directory-maybe option))))
(setf (yas/template-file yas/editing-template) buffer-file-name))))))
(when kill
(quit-window kill))
- (message "[yas] Snippet \"%s\" loaded for %s."
+ (yas/message 3 "Snippet \"%s\" loaded for %s."
(yas/template-name yas/editing-template)
(yas/table-name (yas/template-table yas/editing-template))))
(fboundp (car major-mode-and-parent))
(car major-mode-and-parent))
(first yas/guessed-modes)
- (intern (read-from-minibuffer "[yas] Please input a mode: "))))
+ (intern (read-from-minibuffer (yas/format "Please input a mode: ")))))
(yas/current-template
(and parsed
(fboundp test-mode)
(require 'yasnippet-debug nil t))
(add-hook 'post-command-hook 'yas/debug-snippet-vars nil t))))
(t
- (message "[yas] Cannot test snippet for unknown major mode")))))
+ (yas/message 3 "Cannot test snippet for unknown major mode")))))
(defun yas/template-fine-group (template)
(car (last (or (yas/template-group template)
Otherwise throw exception."
(when (and yas/moving-away-p (notany #'(lambda (pos) (string= pos yas/text)) possibilities))
- (yas/throw (format "[yas] Field only allows %s" possibilities))))
+ (yas/throw (yas/format "Field only allows %s" possibilities))))
(defun yas/field-value (number)
"Get the string for field with NUMBER.
(mapc #'(lambda (snippet)
(yas/exit-snippet snippet)
(yas/check-commit-snippet))
- (yas/snippets-at-point)))
+ (yas/snippets-at-point 'all-snippets)))
\f
;;; Some low level snippet-routines
;; again from `yas/take-care-of-redo'....
(setf (yas/snippet-fields snippet) nil)))
- (message "[yas] Snippet %s exited." (yas/snippet-id snippet)))
+ (yas/message 3 "Snippet %s exited." (yas/snippet-id snippet)))
(defun yas/safely-run-hooks (hook-var)
(condition-case error
(run-hooks hook-var)
(error
- (message "[yas] %s error: %s" hook-var (error-message-string error)))))
+ (yas/message 3 "%s error: %s" hook-var (error-message-string error)))))
(defun yas/check-commit-snippet ()
(when first-field
(sit-for 0) ;; fix issue 125
(yas/move-to-field snippet first-field)))
- (message "[yas] snippet expanded.")
+ (yas/message 3 "snippet expanded.")
t))))
(defun yas/take-care-of-redo (beg end snippet)
(widen)
(condition-case err
(indent-according-to-mode)
- (error (message "[yas] warning: `yas/indent-according-to-mode' having problems running %s" indent-line-function)
+ (error (yas/message 3 "Warning: `yas/indent-according-to-mode' having problems running %s" indent-line-function)
nil)))
(mapc #'(lambda (marker)
(set-marker marker (point)))
(apply (car fn-and-args)
(cdr fn-and-args)))
yas/post-command-runonce-actions)
- (error (message "[yas] Problem running `yas/post-command-runonce-actions'!")))
+ (error (yas/message 3 "Problem running `yas/post-command-runonce-actions'!")))
(setq yas/post-command-runonce-actions nil))
(cond (yas/protection-violation
(goto-char yas/protection-violation)
(gethash uuid (yas/table-uuidhash table)))))
(when yas/current-template
(yas/expand-snippet (yas/template-content yas/current-template)))))
+\f
+;;; Utils
+;;;
+
+(defvar yas/verbosity 4
+ "Log level for `yas/message' 4 means trace most anything, 0 means nothing.")
+(defun yas/message (level message &rest args)
+ (when (> yas/verbosity level)
+ (message (apply #'yas/format message args))))
+
+(defun yas/format (format-control &rest format-args)
+ (apply #'format (concat "[yas] " format-control) format-args))
\f
;;; Some hacks: