mirror of
https://github.com/joaotavora/yasnippet.git
synced 2025-10-13 21:13:04 +00:00
* reformed yas/new-snippet' and
yas/load-snippet-buffer'. Works, but probably buggy...
This commit is contained in:
parent
1727109305
commit
eebdf516b2
237
yasnippet.el
237
yasnippet.el
@ -867,8 +867,9 @@ Do this unless `yas/dont-activate' is t or the function
|
|||||||
;;; Internal structs for template management
|
;;; Internal structs for template management
|
||||||
|
|
||||||
(defstruct (yas/template (:constructor yas/make-template
|
(defstruct (yas/template (:constructor yas/make-template
|
||||||
(key content name condition expand-env file keybinding)))
|
(table key content name condition expand-env file keybinding)))
|
||||||
"A template for a snippet."
|
"A template for a snippet."
|
||||||
|
table
|
||||||
key
|
key
|
||||||
content
|
content
|
||||||
name
|
name
|
||||||
@ -987,7 +988,20 @@ keybinding)."
|
|||||||
(make-hash-table :test 'equal)
|
(make-hash-table :test 'equal)
|
||||||
(yas/snippet-table-hash table))))
|
(yas/snippet-table-hash table))))
|
||||||
(when (vectorp key)
|
(when (vectorp key)
|
||||||
(define-key (yas/snippet-table-direct-keymap table) key 'yas/expand-from-keymap))))
|
(define-key (yas/snippet-table-direct-keymap table) key 'yas/expand-from-keymap))))
|
||||||
|
|
||||||
|
(defun yas/update-snippet (snippet-table template name key keybinding)
|
||||||
|
"Update TEMPLATE in SNIPPET-TABLE, according to new props.
|
||||||
|
|
||||||
|
TEMPLATE, NAME, KEY and KEYBINDING."
|
||||||
|
;; The direct keybinding
|
||||||
|
(yas/remove-snippet snippet-table name keybinding template #'vectorp)
|
||||||
|
(when keybinding
|
||||||
|
(yas/add-snippet snippet-table name keybinding template))
|
||||||
|
;; The trigger key (key can be null if we removed the key)
|
||||||
|
(yas/remove-snippet snippet-table name key template #'stringp)
|
||||||
|
(when key
|
||||||
|
(yas/add-snippet snippet-table name key template)))
|
||||||
|
|
||||||
(defun yas/fetch (table key)
|
(defun yas/fetch (table key)
|
||||||
"Fetch snippets in TABLE by KEY. "
|
"Fetch snippets in TABLE by KEY. "
|
||||||
@ -1001,7 +1015,6 @@ keybinding)."
|
|||||||
namehash)
|
namehash)
|
||||||
alist)))))
|
alist)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; Filtering/condition logic
|
;;; Filtering/condition logic
|
||||||
|
|
||||||
@ -1216,12 +1229,15 @@ Guessing is done by looking up the MODE-SYMBOL's
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;; Template-related and snippet loading functions
|
;;; Template-related and snippet loading functions
|
||||||
|
|
||||||
(defun yas/parse-template (&optional file)
|
(defun yas/parse-template (&optional file group)
|
||||||
"Parse the template in the current buffer.
|
"Parse the template in the current buffer.
|
||||||
|
|
||||||
Optional FILE is the absolute file name of the file being
|
Optional FILE is the absolute file name of the file being
|
||||||
parsed.
|
parsed.
|
||||||
|
|
||||||
|
Optional GROUP is the group where the template is to go,
|
||||||
|
otherwise we attempt to calculate it from FILE.
|
||||||
|
|
||||||
Return a snippet-definition, i.e. a list
|
Return a snippet-definition, i.e. a list
|
||||||
|
|
||||||
(KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING)
|
(KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING)
|
||||||
@ -1258,8 +1274,9 @@ Here's a list of currently recognized variables:
|
|||||||
template
|
template
|
||||||
bound
|
bound
|
||||||
condition
|
condition
|
||||||
(group (and file
|
(group (or group
|
||||||
(yas/calculate-group file)))
|
(and file
|
||||||
|
(yas/calculate-group file))))
|
||||||
expand-env
|
expand-env
|
||||||
binding)
|
binding)
|
||||||
(if (re-search-forward "^# --\n" nil t)
|
(if (re-search-forward "^# --\n" nil t)
|
||||||
@ -1280,7 +1297,7 @@ Here's a list of currently recognized variables:
|
|||||||
(when (string= "condition" (match-string-no-properties 1))
|
(when (string= "condition" (match-string-no-properties 1))
|
||||||
(setq condition (yas/read-lisp (match-string-no-properties 2))))
|
(setq condition (yas/read-lisp (match-string-no-properties 2))))
|
||||||
(when (string= "group" (match-string-no-properties 1))
|
(when (string= "group" (match-string-no-properties 1))
|
||||||
(setq group (match-string-no-properties 2)))
|
(message "[yas] Warning: the \"# group:\" is no longer supported!"))
|
||||||
(when (string= "expand-env" (match-string-no-properties 1))
|
(when (string= "expand-env" (match-string-no-properties 1))
|
||||||
(setq expand-env (yas/read-lisp (match-string-no-properties 2)
|
(setq expand-env (yas/read-lisp (match-string-no-properties 2)
|
||||||
'nil-on-error)))
|
'nil-on-error)))
|
||||||
@ -1793,7 +1810,8 @@ not need to be a real mode."
|
|||||||
;; a key and a name for the snippet, because that is what
|
;; a key and a name for the snippet, because that is what
|
||||||
;; indexes the snippet tables
|
;; indexes the snippet tables
|
||||||
;;
|
;;
|
||||||
(setq template (yas/make-template key
|
(setq template (yas/make-template snippet-table
|
||||||
|
key
|
||||||
(second snippet)
|
(second snippet)
|
||||||
(or name key)
|
(or name key)
|
||||||
condition
|
condition
|
||||||
@ -1801,14 +1819,7 @@ not need to be a real mode."
|
|||||||
(seventh snippet)
|
(seventh snippet)
|
||||||
keybinding))
|
keybinding))
|
||||||
(when name
|
(when name
|
||||||
;; The direct keybinding
|
(yas/update-snippet snippet-table template name key keybinding))
|
||||||
(yas/remove-snippet snippet-table name keybinding template #'vectorp)
|
|
||||||
(when keybinding
|
|
||||||
(yas/add-snippet snippet-table name keybinding template))
|
|
||||||
;; The trigger key (key can be null if we removed the key)
|
|
||||||
(yas/remove-snippet snippet-table name key template #'stringp)
|
|
||||||
(when key
|
|
||||||
(yas/add-snippet snippet-table name key template)))
|
|
||||||
|
|
||||||
;; Setup the menu groups, reorganizing from group to group if
|
;; Setup the menu groups, reorganizing from group to group if
|
||||||
;; necessary
|
;; necessary
|
||||||
@ -1842,6 +1853,8 @@ not need to be a real mode."
|
|||||||
(concat key yas/trigger-symbol))
|
(concat key yas/trigger-symbol))
|
||||||
(and keybinding (key-description keybinding)))))))))))
|
(and keybinding (key-description keybinding)))))))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defun yas/show-menu-p (mode)
|
(defun yas/show-menu-p (mode)
|
||||||
(cond ((eq yas/use-menu 'abbreviate)
|
(cond ((eq yas/use-menu 'abbreviate)
|
||||||
(find mode
|
(find mode
|
||||||
@ -2096,6 +2109,7 @@ visited file in `snippet-mode'."
|
|||||||
(let ((file (yas/template-file template)))
|
(let ((file (yas/template-file template)))
|
||||||
(cond ((and file (file-exists-p file))
|
(cond ((and file (file-exists-p file))
|
||||||
(find-file-other-window file)
|
(find-file-other-window file)
|
||||||
|
(setq (make-local-variable 'yas/current-template) template)
|
||||||
(snippet-mode))
|
(snippet-mode))
|
||||||
(file
|
(file
|
||||||
(message "Original file %s no longer exists!" file))
|
(message "Original file %s no longer exists!" file))
|
||||||
@ -2117,7 +2131,8 @@ visited file in `snippet-mode'."
|
|||||||
(insert (if (eq type 'command)
|
(insert (if (eq type 'command)
|
||||||
(pp-to-string (yas/template-content template))
|
(pp-to-string (yas/template-content template))
|
||||||
(yas/template-content template))))
|
(yas/template-content template))))
|
||||||
(snippet-mode)))))
|
(setq (make-local-variable 'yas/current-template) template)
|
||||||
|
(snippet-mode)))))
|
||||||
|
|
||||||
(defun yas/guess-snippet-directories-1 (table &optional suffix)
|
(defun yas/guess-snippet-directories-1 (table &optional suffix)
|
||||||
"Guesses possible snippet subdirsdirectories for TABLE."
|
"Guesses possible snippet subdirsdirectories for TABLE."
|
||||||
@ -2130,9 +2145,9 @@ visited file in `snippet-mode'."
|
|||||||
(concat (yas/snippet-table-name parent) "/" suffix)))
|
(concat (yas/snippet-table-name parent) "/" suffix)))
|
||||||
(yas/snippet-table-parents table))))
|
(yas/snippet-table-parents table))))
|
||||||
|
|
||||||
(defun yas/guess-snippet-directories ()
|
(defun yas/guess-snippet-directories (&optional table)
|
||||||
"Try to guess suitable directories based on the current active
|
"Try to guess suitable directories based on the current active
|
||||||
tables.
|
tables or optional TABLE.
|
||||||
|
|
||||||
Returns a a list of options alist TABLE -> DIRS where DIRS are
|
Returns a a list of options alist TABLE -> DIRS where DIRS are
|
||||||
all the possibly directories where snippets of table might be
|
all the possibly directories where snippets of table might be
|
||||||
@ -2141,14 +2156,16 @@ lurking."
|
|||||||
(first yas/root-directory))
|
(first yas/root-directory))
|
||||||
yas/root-directory
|
yas/root-directory
|
||||||
(setq yas/root-directory "~/.emacs.d/snippets")))
|
(setq yas/root-directory "~/.emacs.d/snippets")))
|
||||||
(tables (yas/get-snippet-tables)))
|
(tables (or (and table
|
||||||
|
(list table))
|
||||||
|
(yas/get-snippet-tables))))
|
||||||
;; HACK! the snippet table created here is a dummy table that
|
;; HACK! the snippet table created here is a dummy table that
|
||||||
;; holds the correct name so that `yas/make-directory-maybe' can
|
;; holds the correct name so that `yas/make-directory-maybe' can
|
||||||
;; work. The real table, if it does not exist in
|
;; work. The real table, if it does not exist in
|
||||||
;; yas/snippet-tables will be created when the first snippet for
|
;; yas/snippet-tables will be created when the first snippet for
|
||||||
;; that mode is loaded.
|
;; that mode is loaded.
|
||||||
;;
|
;;
|
||||||
(unless (gethash major-mode yas/snippet-tables)
|
(unless (or table (gethash major-mode yas/snippet-tables))
|
||||||
(setq tables (cons (yas/make-snippet-table (symbol-name major-mode))
|
(setq tables (cons (yas/make-snippet-table (symbol-name major-mode))
|
||||||
tables)))
|
tables)))
|
||||||
|
|
||||||
@ -2180,50 +2197,25 @@ lurking."
|
|||||||
(defun yas/new-snippet (&optional choose-instead-of-guess)
|
(defun yas/new-snippet (&optional choose-instead-of-guess)
|
||||||
""
|
""
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(let* ((guessed-directories (yas/guess-snippet-directories))
|
(let ((guessed-directories (yas/guess-snippet-directories)))
|
||||||
(option (or (and choose-instead-of-guess
|
|
||||||
(some #'(lambda (fn)
|
(switch-to-buffer (format "*new snippet for %s*"
|
||||||
(funcall fn "Choose a snippet table: "
|
(if guessed-directories
|
||||||
guessed-directories
|
(yas/snippet-table-name (car (first guessed-directories)))
|
||||||
#'(lambda (option)
|
"unknown mode")))
|
||||||
(yas/snippet-table-name (car option)))))
|
(snippet-mode)
|
||||||
yas/prompt-functions))
|
(set (make-local-variable 'yas/guessed-directories)
|
||||||
(first guessed-directories)))
|
guessed-directories)
|
||||||
(chosen))
|
(unless (and choose-instead-of-guess
|
||||||
(setq chosen (yas/make-directory-maybe option (unless choose-instead-of-guess
|
(not (y-or-n-p "Insert a snippet with useful headers? ")))
|
||||||
" main")))
|
(yas/expand-snippet "\
|
||||||
(unless (or chosen
|
|
||||||
choose-instead-of-guess)
|
|
||||||
(if (y-or-n-p (format "Continue guessing for other active tables %s? "
|
|
||||||
(mapcar #'(lambda (table-and-dirs)
|
|
||||||
(yas/snippet-table-name (car table-and-dirs)))
|
|
||||||
(rest guessed-directories))))
|
|
||||||
(setq chosen (some #'yas/make-directory-maybe
|
|
||||||
(rest guessed-directories)))))
|
|
||||||
(unless (or chosen
|
|
||||||
choose-instead-of-guess)
|
|
||||||
(when (y-or-n-p "Having trouble... use snippet root dir? ")
|
|
||||||
(setq chosen (if (listp yas/root-directory)
|
|
||||||
(first yas/root-directory)
|
|
||||||
yas/root-directory))))
|
|
||||||
(if chosen
|
|
||||||
(let ((default-directory chosen)
|
|
||||||
(name (read-from-minibuffer "Enter a snippet name: ")))
|
|
||||||
(find-file-other-window (concat name
|
|
||||||
".yasnippet"))
|
|
||||||
(snippet-mode)
|
|
||||||
(unless (and choose-instead-of-guess
|
|
||||||
(not (y-or-n-p "Insert a snippet with useful headers? ")))
|
|
||||||
(yas/expand-snippet (format
|
|
||||||
"\
|
|
||||||
# -*- mode: snippet -*-
|
# -*- mode: snippet -*-
|
||||||
# name: %s
|
# name: $1
|
||||||
# key: $1${2:
|
# key: $2${3:
|
||||||
# binding: \"${3:direct-keybinding}\"}${4:
|
# binding: \"${4:direct-keybinding}\"}${5:
|
||||||
# expand-env: ((${5:some-var} ${6:some-value}))}
|
# expand-env: ((${6:some-var} ${7:some-value}))}
|
||||||
# --
|
# --
|
||||||
$0" name))))
|
$0"))))
|
||||||
(message "[yas] aborted snippet creation."))))
|
|
||||||
|
|
||||||
(defun yas/find-snippets (&optional same-window )
|
(defun yas/find-snippets (&optional same-window )
|
||||||
"Look for user snippets in guessed current mode's directory.
|
"Look for user snippets in guessed current mode's directory.
|
||||||
@ -2296,29 +2288,99 @@ there, otherwise, proposes to create the first option returned by
|
|||||||
|
|
||||||
With optional prefix argument KILL quit the window and buffer."
|
With optional prefix argument KILL quit the window and buffer."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(if buffer-file-name
|
(cond ( ;; X) Option 1: We have a file name, consider this as being
|
||||||
(let ((major-mode-and-parent (yas/compute-major-mode-and-parents buffer-file-name)))
|
;; a brand new snippet and calculate name, groups, etc from
|
||||||
(if major-mode-and-parent
|
;; the current file-name and buffer content
|
||||||
(let* ((yas/ignore-filenames-as-triggers (or yas/ignore-filenames-as-triggers
|
;;
|
||||||
(locate-dominating-file buffer-file-name ".yas-ignore-filenames-as-triggers")))
|
buffer-file-name
|
||||||
(parsed (yas/parse-template buffer-file-name))
|
(let ((major-mode-and-parent (yas/compute-major-mode-and-parents buffer-file-name)))
|
||||||
(name (and parsed
|
(if major-mode-and-parent
|
||||||
(third parsed))))
|
(let* ((yas/ignore-filenames-as-triggers (or yas/ignore-filenames-as-triggers
|
||||||
(when name
|
(locate-dominating-file buffer-file-name ".yas-ignore-filenames-as-triggers")))
|
||||||
(let ((yas/better-guess-for-replacements t))
|
(parsed (yas/parse-template buffer-file-name))
|
||||||
(yas/define-snippets (car major-mode-and-parent)
|
(name (and parsed
|
||||||
(list parsed)
|
(third parsed))))
|
||||||
(cdr major-mode-and-parent)))
|
(when name
|
||||||
(when (and (buffer-modified-p)
|
(let ((yas/better-guess-for-replacements t))
|
||||||
(y-or-n-p "Also save snippet buffer? "))
|
(yas/define-snippets (car major-mode-and-parent)
|
||||||
(save-buffer))
|
(list parsed)
|
||||||
(if kill
|
(cdr major-mode-and-parent))))
|
||||||
(quit-window kill)
|
(when (and (buffer-modified-p)
|
||||||
(message "[yas] Snippet \"%s\" loaded for %s."
|
(y-or-n-p "Save snippet buffer? "))
|
||||||
name
|
(save-buffer))
|
||||||
(car major-mode-and-parent)))))
|
(if kill
|
||||||
(message "[yas] Cannot load snippet for unknown major mode")))
|
(quit-window kill)
|
||||||
(message "Save the buffer as a file first!")))
|
(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)))))
|
||||||
|
;; X) Option 2: We have `yas/current-template', this buffer's
|
||||||
|
;; content comes from a template which is already loaded and
|
||||||
|
;; neatly positioned,...
|
||||||
|
;;
|
||||||
|
((and (boundp 'yas/current-template)
|
||||||
|
yas/current-template
|
||||||
|
(yas/template-p yas/current-template))
|
||||||
|
|
||||||
|
(let ((parsed ((yas/parse-template))))
|
||||||
|
;; ... just change its template, expand-env, condition, key,
|
||||||
|
;; keybinding and name. The group cannot be changed.
|
||||||
|
(setf (yas/template-content yas/current-template) (second parsed))
|
||||||
|
(setf (yas/template-key yas/current-template) (first parsed))
|
||||||
|
(setf (yas/template-name yas/current-template) (third parsed))
|
||||||
|
(setf (yas/template-condition yas/current-template) (fourth parsed))
|
||||||
|
(setf (yas/template-expand-env yas/current-template) (sixth parsed))
|
||||||
|
(setf (yas/template-keybinding yas/current-template) (eighth parsed))
|
||||||
|
(yas/update-snippet (yas/template-table yas/current-template)
|
||||||
|
yas/current-template
|
||||||
|
(yas/template-name yas/current-template)
|
||||||
|
(yas/template-key yas/current-template)
|
||||||
|
(yas/template-keybinding yas/current-template)))
|
||||||
|
;; ..., if an original file is found offer to overwrite that
|
||||||
|
;; file. If the file cannot be found, prompt user for
|
||||||
|
;; creation much like `yas/new-snippet'.
|
||||||
|
;;
|
||||||
|
(if (and (yas/template-file yas/current-template)
|
||||||
|
(file-writable-p (yas/template-file yas/current-template))
|
||||||
|
(y-or-n-p (format "[yas] Save snippet buffer and overwrite %s?"
|
||||||
|
(yas/template-file yas/current-template))))
|
||||||
|
(write-file (yas/template-file yas/current-template))
|
||||||
|
(let* ((guess (first (yas/guess-snippet-directories (yas/template-table yas/current-template))))
|
||||||
|
(chosen (and guess
|
||||||
|
(yas/make-directory-maybe option))))
|
||||||
|
(when chosen
|
||||||
|
(let ((default-directory chosen))
|
||||||
|
(call-interactively 'write-file))))))
|
||||||
|
;; X) Option 3: We have `yas/guessed-directories', this
|
||||||
|
;; buffer's content comes from `yas/new-snippet' call. Prompt
|
||||||
|
;; user for dir and name in guessed dirs, then call
|
||||||
|
;; `yas/load-snippet-buffer' (ourselves) again to load the
|
||||||
|
;; snippet based on the file-name.
|
||||||
|
;;
|
||||||
|
((and (boundp 'yas/guessed-directories)
|
||||||
|
yas/guessed-directories)
|
||||||
|
(let* ((guessed-directories yas/guessed-directories)
|
||||||
|
(option (or (and (second guessed-directories)
|
||||||
|
(some #'(lambda (fn)
|
||||||
|
(funcall fn "Choose a snippet table: "
|
||||||
|
guessed-directories
|
||||||
|
#'(lambda (option)
|
||||||
|
(yas/snippet-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/root-directory)
|
||||||
|
(first yas/root-directory)
|
||||||
|
yas/root-directory))))
|
||||||
|
(when chosen
|
||||||
|
(let ((default-directory chosen))
|
||||||
|
(call-interactively 'write-file))
|
||||||
|
(setq yas/guessed-directories nil)
|
||||||
|
(yas/load-snippet-buffer))))))
|
||||||
|
|
||||||
|
|
||||||
(defun yas/tryout-snippet (&optional debug)
|
(defun yas/tryout-snippet (&optional debug)
|
||||||
"Test current buffers's snippet template in other buffer."
|
"Test current buffers's snippet template in other buffer."
|
||||||
@ -2331,7 +2393,8 @@ With optional prefix argument KILL quit the window and buffer."
|
|||||||
(intern (read-from-minibuffer "[yas] please input a mode: "))))
|
(intern (read-from-minibuffer "[yas] please input a mode: "))))
|
||||||
(template (and parsed
|
(template (and parsed
|
||||||
(fboundp test-mode)
|
(fboundp test-mode)
|
||||||
(yas/make-template (first parsed)
|
(yas/make-template nil ;; an ephemeral snippet has no table...
|
||||||
|
(first parsed)
|
||||||
(second parsed)
|
(second parsed)
|
||||||
(third parsed)
|
(third parsed)
|
||||||
nil
|
nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user