* Soon, no tweaking on snippet importations...

This commit is contained in:
capitaomorte 2010-04-01 16:05:41 +00:00
parent 5d9f7fb6b4
commit 92d0c45589
3 changed files with 198 additions and 121 deletions

View File

@ -23,10 +23,10 @@ Choice.options do
header '' header ''
header 'Standard Options:' header 'Standard Options:'
option :snippet_dir do option :bundle_dir do
short '-d' short '-d'
long '--snippet-dir=PATH' long '--bundle-dir=PATH'
desc 'Tells the program the directory to find the TextMate Snippets' desc 'Tells the program the directory to find the TextMate bundle directory'
default '.' default '.'
end end
@ -63,8 +63,8 @@ Choice.options do
option :info_plist do option :info_plist do
short '-g' short '-g'
long '--info-plist' long '--info-plist=PLIST'
desc "Attempt to derive menu information from \"info.plist\" type-file PLIST" desc "Specify a plist file derive menu information from defaults to \"bundle-dir\"/info.plist"
end end
separator '' separator ''
@ -87,6 +87,7 @@ class TmSubmenu
end end
def to_lisp(allsubmenus, def to_lisp(allsubmenus,
deleteditems,
indent = 0, indent = 0,
thingy = ["(", ")"]) thingy = ["(", ")"])
@ -94,6 +95,10 @@ class TmSubmenu
string = "" string = ""
items.each do |uuid| items.each do |uuid|
if deleteditems.index(uuid)
$stderr.puts "#{uuid} has been deleted!"
next
end
string += "\n" string += "\n"
string += " " * indent string += " " * indent
string += (first ? thingy[0] : (" " * thingy[0].length)) string += (first ? thingy[0] : (" " * thingy[0].length))
@ -102,17 +107,14 @@ class TmSubmenu
if submenu if submenu
str = "(yas/submenu " str = "(yas/submenu "
string += str + "\"" + submenu.name + "\"" string += str + "\"" + submenu.name + "\""
string += submenu.to_lisp(allsubmenus, string += submenu.to_lisp(allsubmenus, deleteditems,
indent + str.length + thingy[0].length) indent + str.length + thingy[0].length)
elsif TmSnippet::snippets_by_uid[uuid]
string += "(yas/item \"" + uuid + "\")"
elsif (uuid =~ /---------------------/)
string += "(yas/separator)"
else else
snippet = TmSnippet::snippets_by_uid[uuid] string += "(yas/external-item \"" + uuid + "\")"
sname = snippet ? snippet.name : uuid
if (sname !~ /---------------------/)
string += "(yas/item \"" + sname + "\")"
else
string += "(yas/separator)"
end
end end
first = false; first = false;
end end
@ -122,25 +124,29 @@ class TmSubmenu
return string return string
end end
def self.main_menu_to_lisp (hash) def self.main_menu_to_lisp (parsed_plist, modename)
mainmenu = TmSubmenu.new("__main_menu__", hash) mainmenu = parsed_plist["mainMenu"]
deleted = parsed_plist["deleted"]
root = TmSubmenu.new("__main_menu__", mainmenu)
all = {} all = {}
hash["submenus"].each_pair do |k,v| mainmenu["submenus"].each_pair do |k,v|
all[k] = TmSubmenu.new(v["name"], v) all[k] = TmSubmenu.new(v["name"], v)
end end
closing = "\n '(" closing = "\n '("
closing+= hash["excludedItems"].collect do |uuid| closing+= mainmenu["excludedItems"].collect do |uuid|
snippet = TmSnippet::snippets_by_uid[uuid] snippet = TmSnippet::snippets_by_uid[uuid]
"\"" + (snippet ? snippet.name : uuid) + "\"" "\"" + (snippet ? snippet.name : uuid) + "\""
end.join( "\n ") + "))" end.join( "\n ") + "))"
str = "(yas/define-menu " str = "(yas/define-menu "
return str + "'major-mode-name" + mainmenu.to_lisp(all, return str + "'#{modename}" + root.to_lisp(all,
str.length, deleted,
["'(" , closing]) str.length,
["'(" , closing])
end end
end end
@ -156,20 +162,29 @@ end
# #
class SkipSnippet < RuntimeError; end class SkipSnippet < RuntimeError; end
class TmSnippet class TmSnippet
@@known_substitutions=[ # unix to the rescue
{ #
"${TM_RAILS_TEMPLATE_START_RUBY_EXPR}" => "<%= ", # ack -aho '\${\d/[^/]*/[^/]*/}' imported/ruby-mode/ | sort | uniq
"${TM_RAILS_TEMPLATE_END_RUBY_EXPR}" => " %>", @@known_substitutions ={
"${TM_RAILS_TEMPLATE_START_RUBY_INLINE}" => "<% ", "content" => [
"${TM_RAILS_TEMPLATE_END_RUBY_INLINE}" => " -%>", {
"${TM_RAILS_TEMPLATE_END_RUBY_BLOCK}" => "end" , "${TM_RAILS_TEMPLATE_START_RUBY_EXPR}" => "<%= ",
"${0:$TM_SELECTED_TEXT}" => "${0:`yas/selected-text`", "${TM_RAILS_TEMPLATE_END_RUBY_EXPR}" => " %>",
}, "${TM_RAILS_TEMPLATE_START_RUBY_INLINE}" => "<% ",
{ "${TM_RAILS_TEMPLATE_END_RUBY_INLINE}" => " -%>",
#substitutions that have to take place "${TM_RAILS_TEMPLATE_END_RUBY_BLOCK}" => "end" ,
#after the first group "${0:$TM_SELECTED_TEXT}" => "${0:`yas/selected-text`",
} }
] ],
"condition" => [ {
/^source\..*$/ => ""
} ],
"binding" => [ {} ]
}
# now add some more substitutions
# TODO: find a better way to add more substitutions
#
require 'textmate_import_substitutions.rb'
@@snippets_by_uid={} @@snippets_by_uid={}
def self.snippets_by_uid; @@snippets_by_uid; end def self.snippets_by_uid; @@snippets_by_uid; end
@ -179,7 +194,7 @@ class TmSnippet
@info = info @info = info
@snippet = TmSnippet::read_plist(file) @snippet = TmSnippet::read_plist(file)
@@snippets_by_uid[self.uuid] = self; @@snippets_by_uid[self.uuid] = self;
raise SkipSnippet.new "not a snippet/command/macro." unless (scope || @snippet["command"]) raise SkipSnippet.new "not a snippet/command/macro." unless (@snippet["scope"] || @snippet["command"])
raise RuntimeError.new("Cannot convert this snippet #{file}!") unless @snippet; raise RuntimeError.new("Cannot convert this snippet #{file}!") unless @snippet;
end end
@ -205,16 +220,40 @@ class TmSnippet
@snippet["tabTrigger"] @snippet["tabTrigger"]
end end
def key_equivalent def binding
@snippet["keyEquivalent"] binding = @snippet["keyEquivalent"]
if binding
@@known_substitutions["binding"].each do |level|
level.each_pair do |k, v|
binding.gsub!(k,v)
end
end
end
"## binding: \""+ binding + "\"\n" if binding and not binding.empty?
end end
def content def content
@snippet["content"] content = @snippet["content"]
if content
@@known_substitutions["content"].each do |level|
level.each_pair do |k, v|
content.gsub!(k,v)
end
end
end
content
end end
def scope def condition
@snippet["scope"] condition = @snippet["scope"]
if condition
@@known_substitutions["condition"].each do |level|
level.each_pair do |k, v|
condition.gsub!(k,v)
end
end
end
"## condition: \""+ condition + "\"\n" if condition and not condition.empty?
end end
def to_yasnippet def to_yasnippet
@ -224,19 +263,10 @@ class TmSnippet
doc << "# key: #{self.tab_trigger}\n" if self.tab_trigger doc << "# key: #{self.tab_trigger}\n" if self.tab_trigger
doc << "# contributor: Translated from TextMate Snippet\n" doc << "# contributor: Translated from TextMate Snippet\n"
doc << "# name: #{self.name}\n" doc << "# name: #{self.name}\n"
if self.key_equivalent doc << (self.binding || "")
doc << "#" unless Choice.choices.convert_bindings doc << (self.condition || "")
doc << "# binding: \"#{self.key_equivalent}\"\n"
end
if self.scope
doc << "#"
doc << "# condition: \"#{self.scope}\"\n"
end
doc << "# --\n" doc << "# --\n"
if self.content doc << (self.content || "")
@@known_substitutions.each {|level| level.each_pair { |k, v| self.content.gsub!(k,v) }}
doc << "#{self.content}"
end
doc doc
end end
@ -272,13 +302,15 @@ end
if $0 == __FILE__ if $0 == __FILE__
# Read the info.plist if we have it
info_plist = TmSnippet::read_plist(Choice.choices.info_plist) if Choice.choices.info_plist; #
info_plist_file = Choice.choices.info_plist || File.join(Choice.choices.bundle_dir,"info.plist")
info_plist = TmSnippet::read_plist(info_plist_file) if info_plist_file and File.readable? info_plist_file;
# Glob snippets into snippet_files, going into subdirs # Glob snippets into snippet_files, going into subdirs
# #
original_dir = Dir.pwd original_dir = Dir.pwd
Dir.chdir Choice.choices.snippet_dir Dir.chdir Choice.choices.bundle_dir
snippet_files_glob = File.join("**", Choice.choices.snippet) snippet_files_glob = File.join("**", Choice.choices.snippet)
snippet_files = Dir.glob(snippet_files_glob) snippet_files = Dir.glob(snippet_files_glob)
@ -287,7 +319,7 @@ if $0 == __FILE__
puts "Will try to convert #{snippet_files.length} snippets...\n" unless Choice.choices.quiet puts "Will try to convert #{snippet_files.length} snippets...\n" unless Choice.choices.quiet
snippet_files.each do |file| snippet_files.each do |file|
begin begin
puts "Processing \"#{File.join(Choice.choices.snippet_dir,file)}\"\n" unless Choice.choices.quiet puts "Processing \"#{File.join(Choice.choices.bundle_dir,file)}\"\n" unless Choice.choices.quiet
snippet = TmSnippet.new(file,info_plist) snippet = TmSnippet.new(file,info_plist)
if Choice.choices.output_dir if Choice.choices.output_dir
@ -314,21 +346,22 @@ if $0 == __FILE__
end end
# Attempt to decypher the menu # Attempt to decypher the menu
# #
modename = Choice.choices.output_dir or "major-mode-name" modename = File.basename Choice.choices.output_dir || "major-mode-name"
str = TmSubmenu::main_menu_to_lisp(info_plist["mainMenu"]) if info_plist menustr = TmSubmenu::main_menu_to_lisp(info_plist, modename) if info_plist
puts str unless !str or Choice.choices.quiet puts menustr unless !menustr or Choice.choices.quiet
# Write some basic .yas-* files # Write some basic .yas-* files
# #
Dir.chdir original_dir
if Choice.choices.output_dir if Choice.choices.output_dir
FileUtils.mkdir_p Choice.choices.output_dir FileUtils.mkdir_p Choice.choices.output_dir
FileUtils.touch File.join(Choice.choices.output_dir, ".yas-make-groups") unless str FileUtils.touch File.join(original_dir, Choice.choices.output_dir, ".yas-make-groups") unless menustr
FileUtils.touch File.join(Choice.choices.output_dir, ".yas-ignore-filenames-as-triggers") FileUtils.touch File.join(original_dir, Choice.choices.output_dir, ".yas-ignore-filenames-as-triggers")
File.open(File.join(Choice.choices.output_dir, ".yas-setup.el"), 'w') do |file| File.open(File.join(original_dir, Choice.choices.output_dir, ".yas-setup.el"), 'w') do |file|
file.write ";; .yas-setup.el for #{modename}\n" file.write ";; .yas-setup.el for #{modename}\n"
file.write ";;\n" file.write ";;\n"
file.write ";;\n" file.write ";; Automatically translated menu\n"
file.write(str) file.write(menustr)
file.write "\n;;\n" file.write "\n;;\n"
file.write ";; .yas-setup.el for #{modename} ends here\n" file.write ";; .yas-setup.el for #{modename} ends here\n"
end end

View File

@ -0,0 +1,42 @@
class TmSnippet
@@known_substitutions["content"] += [{
/`[^`]*snippet_paren\.rb[\s\t]*`/ => "`(yas/ruby-snippet-paren)`",
/`[^`]*snippet_paren\.rb end[^`]*`/ => "`(yas/ruby-snippet-paren \'close)`"
},
{
%q@${1/.+/(/}@ => '${1:$(and (yas/text) "(")}',
%q@${1/.+/)/}@ => '${1:$(and (yas/text) ")")}',
%q@${2/.+/ => /}@ => '${2:$(and (yas/text) " => ")}',
%q@${1:${TM_FILENAME/\.\w+//}@ => '${1:$(and buffer-file-name (file-name-sans-extension buffer-file-name))}',
%q@${1/(^.*?\S.*)|.*/(?1:\()/}@ => '${1:$(and (string-match "[^\s\t]" yas/text) "(" )}',
%q@${1/(^.*?\S.*)|.*/(?1:\))/}@ => '${1:$(and (string-match "[^\s\t]" yas/text) ")" )}',
%q@${2/(^.*?\S.*)|.*/(?1:\()/}@ => '${2:$(and (string-match "[^\s\t]" yas/text) "(" )}',
%q@${2/(^.*?\S.*)|.*/(?1:\))/}@ => '${2:$(and (string-match "[^\s\t]" yas/text) ")" )}',
%q@${3/(^.*?\S.*)|.*/(?1:\()/}@ => '${3:$(and (string-match "[^\s\t]" yas/text) "(" )}',
%q@${3/(^.*?\S.*)|.*/(?1:\))/}@ => '${3:$(and (string-match "[^\s\t]" yas/text) ")" )}',
%q@${2/^\s*$|(.*\S.*)/(?1: )/}@ => '${2:$(and (string-match "[^\s\t]" yas/text) " " )}',
%q@${3/^\s*$|(.*\S.*)/(?1: )/}@ => '${3:$(and (string-match "[^\s\t]" yas/text) " " )}',
%q@${3/(^[rwab+]+$)|.*/(?1:")/}@ => '${}',
%q@${3/(^[rwab+]+$)|.*/(?1:, ")/}@ => '${}',
%q@${3/^\s*$|(.*\S.*)/(?1:, )/}@ => '${}',
%q@${1:"${2:path/or/url/or/pipe}@ => '${}',
%q@${2:${1/([\w&&[^_]]+)|./\u$1/g}@ => '${}',
%q@${TM_SELECTED_TEXT/([\t ]*).*/$1/m}@ => '${}',
%q@${1:"${2:path/to/file}"}${3/(^[rwab+]+$)|.*/(?1:, ")/}@ => '${}',
%q@${3:${TM_SELECTED_TEXT/(\A.*)|(.+)|\n\z/(?1:$0:(?2:\t$0))/g}@ => '${}',
%q@${1:${TM_FILENAME/(?:\A|_)([A-Za-z0-9]+)(?:\.rb)?/(?2::\u$1)/g}@ => '${}',
%q@${1/(^(?<var>\s*[a-z_][a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:|)/}@ => '${}',
%q@${1/(^(?<var>\s*[a-z_][a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1: |)/}@ => '${}',
%q@${1/(^(?<var>\s*[a-z_][a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:| )/}@ => '${}',
%q@${2/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:|)/}@ => '${}',
%q@${1/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:|)/}@ => '${}',
%q@${2/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:|)/}@ => '${}',
%q@${1/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:|)/}@ => '${}',
%q@${2/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:| )/}@ => '${}',
%q@${1/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:| )/}@ => '${}',
%q@${2/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:| )/}@ => '${}',
%q@${1/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:| )/}@ => '${}',
%q@${2/(^(?<var>\s*(?:\*|\*?[a-z_])[a-zA-Z0-9_]*\s*)(,\g<var>)*,?\s*$)|.*/(?1:| )/}@ => '${}'
}
]
end

View File

@ -890,7 +890,7 @@ Do this unless `yas/dont-activate' is t or the function
expand-env expand-env
file file
keybinding keybinding
uid uuid
menu-binding-pair) menu-binding-pair)
@ -937,27 +937,27 @@ Has the following fields:
the elements of the keyhash that are vectors appear here as the elements of the keyhash that are vectors appear here as
bindings to `yas/expand-from-keymap'. bindings to `yas/expand-from-keymap'.
`yas/table-uidhash' `yas/table-uuidhash'
A hash table mapping snippets uid's to the same `yas/template' A hash table mapping snippets uuid's to the same `yas/template'
objects. A snippet uid defaults to the snippet's name. objects. A snippet uuid defaults to the snippet's name.
" "
name name
(hash (make-hash-table :test 'equal)) (hash (make-hash-table :test 'equal))
(uidhash (make-hash-table :test 'equal)) (uuidhash (make-hash-table :test 'equal))
(parents nil) (parents nil)
(direct-keymap (make-sparse-keymap))) (direct-keymap (make-sparse-keymap)))
(defun yas/get-template-by-uid (mode uid) (defun yas/get-template-by-uuid (mode uuid)
"Find the snippet template in MODE by its UID." "Find the snippet template in MODE by its UUID."
(let* ((table (gethash mode yas/tables mode))) (let* ((table (gethash mode yas/tables mode)))
(when table (when table
(gethash uid (yas/table-uidhash table))))) (gethash uuid (yas/table-uuidhash table)))))
;; Apropos storing/updating, this works with two steps: ;; Apropos storing/updating, this works with two steps:
;; ;;
;; 1. `yas/remove-template-by-uid' to remove any existing mappings by ;; 1. `yas/remove-template-by-uuid' to remove any existing mappings by
;; snippet uid ;; snippet uuid
;; ;;
;; 2. `yas/add-template' to add the mappings again: ;; 2. `yas/add-template' to add the mappings again:
;; ;;
@ -966,9 +966,9 @@ Has the following fields:
;; TEMPLATE, and is also created a new namehash inside that ;; TEMPLATE, and is also created a new namehash inside that
;; entry. ;; entry.
;; ;;
(defun yas/remove-template-by-uid (table uid) (defun yas/remove-template-by-uuid (table uuid)
"Remove from TABLE a template identified by UID." "Remove from TABLE a template identified by UUID."
(let ((template (gethash uid (yas/table-uidhash table)))) (let ((template (gethash uuid (yas/table-uuidhash table))))
(when template (when template
(let* ((name (yas/template-name template)) (let* ((name (yas/template-name template))
(empty-keys nil)) (empty-keys nil))
@ -977,7 +977,7 @@ Has the following fields:
(maphash #'(lambda (k v) (maphash #'(lambda (k v)
(let ((template (gethash name v))) (let ((template (gethash name v)))
(when (and template (when (and template
(eq uid (yas/template-uid template))) (eq uuid (yas/template-uuid template)))
(remhash name v) (remhash name v)
(when (zerop (hash-table-count v)) (when (zerop (hash-table-count v))
(push k empty-keys))))) (push k empty-keys)))))
@ -987,9 +987,9 @@ Has the following fields:
(dolist (key empty-keys) (dolist (key empty-keys)
(remhash key (yas/table-hash table))) (remhash key (yas/table-hash table)))
;; Finally, remove the uid from the uidhash ;; Finally, remove the uuid from the uuidhash
;; ;;
(remhash uid (yas/table-uidhash table)))))) (remhash uuid (yas/table-uuidhash table))))))
(defun yas/add-template (table template) (defun yas/add-template (table template)
@ -1019,12 +1019,12 @@ keybinding)."
(setcar (cdr menu-binding) (setcar (cdr menu-binding)
name)) name))
(puthash (yas/template-uid template) template (yas/table-uidhash table)))) (puthash (yas/template-uuid template) template (yas/table-uuidhash table))))
(defun yas/update-template (snippet-table template) (defun yas/update-template (snippet-table template)
"Add or update TEMPLATE in SNIPPET-TABLE" "Add or update TEMPLATE in SNIPPET-TABLE"
(yas/remove-template-by-uid snippet-table (yas/template-uid template)) (yas/remove-template-by-uuid snippet-table (yas/template-uuid template))
(yas/add-template snippet-table template)) (yas/add-template snippet-table template))
(defun yas/fetch (table key) (defun yas/fetch (table key)
@ -1294,7 +1294,7 @@ 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 UID) (KEY TEMPLATE NAME CONDITION GROUP VARS FILE KEYBINDING UUID)
If the buffer contains a line of \"# --\" then the contents If the buffer contains a line of \"# --\" then the contents
above this line are ignored. Variables can be set above this above this line are ignored. Variables can be set above this
@ -1311,7 +1311,7 @@ Here's a list of currently recognized variables:
* key * key
* expand-env * expand-env
* binding * binding
* uid * uuid
#name: #include \"...\" #name: #include \"...\"
# -- # --
@ -1333,7 +1333,7 @@ Here's a list of currently recognized variables:
(yas/calculate-group file)))) (yas/calculate-group file))))
expand-env expand-env
binding binding
uid) uuid)
(if (re-search-forward "^# --\n" nil t) (if (re-search-forward "^# --\n" nil t)
(progn (setq template (progn (setq template
(buffer-substring-no-properties (point) (buffer-substring-no-properties (point)
@ -1341,8 +1341,8 @@ Here's a list of currently recognized variables:
(setq bound (point)) (setq bound (point))
(goto-char (point-min)) (goto-char (point-min))
(while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*\\)$" bound t) (while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*\\)$" bound t)
(when (string= "uid" (match-string-no-properties 1)) (when (string= "uuid" (match-string-no-properties 1))
(setq uid (match-string-no-properties 2))) (setq uuid (match-string-no-properties 2)))
(when (string= "type" (match-string-no-properties 1)) (when (string= "type" (match-string-no-properties 1))
(setq type (if (string= "command" (match-string-no-properties 2)) (setq type (if (string= "command" (match-string-no-properties 2))
'command 'command
@ -1364,7 +1364,7 @@ Here's a list of currently recognized variables:
(buffer-substring-no-properties (point-min) (point-max)))) (buffer-substring-no-properties (point-min) (point-max))))
(when (eq type 'command) (when (eq type 'command)
(setq template (yas/read-lisp (concat "(progn" template ")")))) (setq template (yas/read-lisp (concat "(progn" template ")"))))
(list key template name condition group expand-env file binding uid))) (list key template name condition group expand-env file binding uuid)))
(defun yas/calculate-group (file) (defun yas/calculate-group (file)
"Calculate the group for snippet file path FILE." "Calculate the group for snippet file path FILE."
@ -1399,12 +1399,12 @@ Here's a list of currently recognized variables:
(defun yas/make-menu-binding (template) (defun yas/make-menu-binding (template)
(let ((mode (intern (yas/table-name (yas/template-table template))))) (let ((mode (intern (yas/table-name (yas/template-table template)))))
`(lambda () (interactive) (yas/expand-or-visit-from-menu ',mode ,(yas/template-uid template))))) `(lambda () (interactive) (yas/expand-or-visit-from-menu ',mode ,(yas/template-uuid template)))))
(defun yas/expand-or-visit-from-menu (mode uid) (defun yas/expand-or-visit-from-menu (mode uuid)
(let* ((table (yas/table-get-create mode)) (let* ((table (yas/table-get-create mode))
(template (and table (template (and table
(gethash uid (yas/table-uidhash table))))) (gethash uuid (yas/table-uuidhash table)))))
(when template (when template
(if yas/visit-from-menu (if yas/visit-from-menu
(yas/visit-snippet-file-1 template) (yas/visit-snippet-file-1 template)
@ -1715,7 +1715,7 @@ Here's the default value for all the parameters:
(expand-env (sixth snippet)) (expand-env (sixth snippet))
(file nil) ;; (seventh snippet)) ;; omit on purpose (file nil) ;; (seventh snippet)) ;; omit on purpose
(binding (eighth snippet)) (binding (eighth snippet))
(uid (ninth snippet))) (uuid (ninth snippet)))
(push `(,key (push `(,key
,template-content ,template-content
,name ,name
@ -1724,7 +1724,7 @@ Here's the default value for all the parameters:
,expand-env ,expand-env
,file ,file
,binding ,binding
,uid) ,uuid)
literal-snippets))) literal-snippets)))
(insert (pp-to-string `(yas/define-snippets ',mode ',literal-snippets ',parent-or-parents))) (insert (pp-to-string `(yas/define-snippets ',mode ',literal-snippets ',parent-or-parents)))
(insert "\n\n")))) (insert "\n\n"))))
@ -1781,7 +1781,7 @@ Here's the default value for all the parameters:
SNIPPETS is a list of snippet definitions, each taking the SNIPPETS is a list of snippet definitions, each taking the
following form following form
(KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UID) (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV FILE KEYBINDING UUID)
Within these, only KEY and TEMPLATE are actually mandatory. Within these, only KEY and TEMPLATE are actually mandatory.
@ -1797,8 +1797,8 @@ The remaining elements are strings.
FILE is probably of very little use if you're programatically FILE is probably of very little use if you're programatically
defining snippets. defining snippets.
UID is the snippets \"unique-id\". Loading a second snippet file UUID is the snippets \"unique-id\". Loading a second snippet file
with the same uid replaced the previous snippet. with the same uuid replaced the previous snippet.
You can use `yas/parse-template' to return such lists based on You can use `yas/parse-template' to return such lists based on
the current buffers contents. the current buffers contents.
@ -1855,9 +1855,9 @@ not need to be a real mode."
(condition (fourth snippet)) (condition (fourth snippet))
(group (fifth snippet)) (group (fifth snippet))
(keybinding (yas/read-keybinding (eighth snippet))) (keybinding (yas/read-keybinding (eighth snippet)))
(uid (or (ninth snippet) (uuid (or (ninth snippet)
name)) name))
(template (or (gethash uid (yas/table-uidhash 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
@ -1871,7 +1871,7 @@ not need to be a real mode."
:expand-env (sixth snippet) :expand-env (sixth snippet)
:file (seventh snippet) :file (seventh snippet)
:keybinding keybinding :keybinding keybinding
:uid uid) :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
;; ;;
@ -1912,7 +1912,7 @@ not need to be a real mode."
(keybinding (yas/template-keybinding template))) (keybinding (yas/template-keybinding template)))
(setf (yas/template-menu-binding-pair template) (setf (yas/template-menu-binding-pair template)
(cons `(menu-item ,(or (yas/template-name template) (cons `(menu-item ,(or (yas/template-name template)
(yas/template-uid template)) (yas/template-uuid template))
,(yas/make-menu-binding template) ,(yas/make-menu-binding template)
:keys ,nil) :keys ,nil)
type))))) type)))))
@ -1965,29 +1965,29 @@ Skip any submenus named \"parent mode\""
(defun yas/define-menu (mode menu omit-items) (defun yas/define-menu (mode menu omit-items)
(let* ((table (yas/table-get-create mode)) (let* ((table (yas/table-get-create mode))
(hash (yas/table-uidhash table))) (hash (yas/table-uuidhash table)))
(yas/define-menu-1 table (yas/define-menu-1 table
(yas/menu-keymap-get-create table) (yas/menu-keymap-get-create table)
menu menu
hash) hash)
(dolist (uid omit-items) (dolist (uuid omit-items)
(let ((template (or (gethash uid hash) (let ((template (or (gethash uuid hash)
(yas/populate-template (puthash uid (yas/populate-template (puthash uuid
(yas/make-blank-template) (yas/make-blank-template)
hash) hash)
:table table :table table
:uid uid)))) :uuid uuid))))
(setf (yas/template-menu-binding-pair template) (cons nil :none)))))) (setf (yas/template-menu-binding-pair template) (cons nil :none))))))
(defun yas/define-menu-1 (table keymap menu uidhash) (defun yas/define-menu-1 (table keymap menu uuidhash)
(dolist (e (reverse menu)) (dolist (e (reverse menu))
(cond ((eq (first e) 'yas/item) (cond ((eq (first e) 'yas/item)
(let ((template (or (gethash (second e) uidhash) (let ((template (or (gethash (second e) uuidhash)
(yas/populate-template (puthash (second e) (yas/populate-template (puthash (second e)
(yas/make-blank-template) (yas/make-blank-template)
uidhash) uuidhash)
:table table :table table
:uid (second e))))) :uuid (second e)))))
(define-key keymap (vector (gensym)) (define-key keymap (vector (gensym))
;; '(menu-item "shit" 'ding) ;; '(menu-item "shit" 'ding)
(car (yas/snippet-menu-binding-pair-get-create template :stay))))) (car (yas/snippet-menu-binding-pair-get-create template :stay)))))
@ -1995,7 +1995,7 @@ Skip any submenus named \"parent mode\""
(let ((subkeymap (make-sparse-keymap))) (let ((subkeymap (make-sparse-keymap)))
(define-key keymap (vector (make-symbol (second e))) (define-key keymap (vector (make-symbol (second e)))
`(menu-item ,(second e) ,subkeymap)) `(menu-item ,(second e) ,subkeymap))
(yas/define-menu-1 table subkeymap (third e) uidhash))) (yas/define-menu-1 table subkeymap (third e) uuidhash)))
((eq (first e) 'yas/separator) ((eq (first e) 'yas/separator)
(define-key keymap (vector (gensym)) (define-key keymap (vector (gensym))
'(menu-item "----"))) '(menu-item "----")))
@ -2604,7 +2604,7 @@ With optional prefix argument KILL quit the window and buffer."
(push v (cdr active)) (push v (cdr active))
(push v (cdr sleeping)))) (push v (cdr sleeping))))
(push v (cdr always))))) (push v (cdr always)))))
(yas/table-uidhash table)) (yas/table-uuidhash table))
(dolist (type-and-templates (list always active sleeping)) (dolist (type-and-templates (list always active sleeping))
(dolist (p (cdr type-and-templates)) (dolist (p (cdr type-and-templates))
(let ((name (yas/template-name p))) (let ((name (yas/template-name p)))
@ -2622,7 +2622,6 @@ With optional prefix argument KILL quit the window and buffer."
(display-buffer buffer) (display-buffer buffer)
(setq continue (and choose (y-or-n-p "Show also non-active tables? "))))) (setq continue (and choose (y-or-n-p "Show also non-active tables? ")))))
(yas/create-snippet-xrefs) (yas/create-snippet-xrefs)
(goto-char (point-min))
(help-mode)) (help-mode))
(t (t
(insert "\n\nYASnippet tables by NAMEHASH: \n") (insert "\n\nYASnippet tables by NAMEHASH: \n")
@ -2639,7 +2638,9 @@ With optional prefix argument KILL quit the window and buffer."
(push k names)) (push k names))
(gethash key (yas/table-hash table))) (gethash key (yas/table-hash table)))
names)))))))))) names))))))))))
(display-buffer buffer))) (display-buffer buffer)
(with-current-buffer buffer
(beginning-of-buffer))))
;;; User convenience functions, for using in snippet definitions ;;; User convenience functions, for using in snippet definitions
@ -2692,12 +2693,6 @@ Otherwise throw exception."
(when (and yas/moving-away-p (notany #'(lambda (pos) (string= pos yas/text)) possibilities)) (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 (format "[yas] field only allows %s" possibilities))))
(defun yas/ephemeral-field (number)
"Automatically exit snippet when something is typed in field NUMBER.
To be used as a primary field transformation."
(when yas/modified-p (yas/exit-snippet (first (yas/snippets-at-point))) (yas/field-value number)))
(defun yas/field-value (number) (defun yas/field-value (number)
"A primary field transformation..." "A primary field transformation..."
(let* ((snippet (car (yas/snippets-at-point))) (let* ((snippet (car (yas/snippets-at-point)))
@ -2706,6 +2701,13 @@ To be used as a primary field transformation."
(when field (when field
(yas/field-text-for-display field)))) (yas/field-text-for-display field))))
(defun yas/text
(if yas/text
(if (not (string= "" yas/text))
))
(or (and yas/text)
(not ())))
(defun yas/get-field-once (number &optional transform-fn) (defun yas/get-field-once (number &optional transform-fn)
(unless yas/modified-p (unless yas/modified-p
(if transform-fn (if transform-fn
@ -4164,7 +4166,7 @@ and return the directory. Return nil if not found."
(prev-file file) (prev-file file)
;; `user' is not initialized outside the loop because ;; `user' is not initialized outside the loop because
;; `file' may not exist, so we may have to walk up part of the ;; `file' may not exist, so we may have to walk up part of the
;; hierarchy before we find the "initial UID". ;; hierarchy before we find the "initial UUID".
(user nil) (user nil)
try) try)
(while (not (or root (while (not (or root