yasnippet/extras/textmate_import.rb
capitaomorte 3d0262d67f * textmate_import imports macros just like commands (no body)
* imported the Rails macros, no adjustments
* logic in rails-mode/.yas-setup.el supports the "intelligent" migration snippet
2009-11-17 17:34:55 +00:00

224 lines
6.5 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# This is a quick script to generate YASnippets from TextMate Snippets.
#
# I based the script off of a python script of a similar nature by
# Jeff Wheeler: http://nokrev.com
# http://code.nokrev.com/?p=snippet-copier.git;a=blob_plain;f=snippet_copier.py
#
# Usage
#
# Make sure you have the plist and the choice gem installed
# $ sudo gem install plist
# $ sudo gem install choice
#
# Usage: snippet_copier.rb [-dofp]
#
# Standard Options:
# -d, --snippet-dir=PATH Tells the program the directory to find the TextMate Snippets
# -o, --output-dir=PATH What directory to write the new YASnippets to
# -f, --file=SNIPPET FILE NAME A specific snippet that you want to copy or a glob for various files
# -p, --print-pretty Pretty prints multiple snippets when printing to standard out
# -b, --convert-bindings TextMate "keyEquivalent" keys are translated to YASnippet "# binding :" directives
# -g, --info-plist=INFO Attempt to derive group information from "info.plist" type-file PLIST
#
# Common options:
# --help Show this message
require 'rubygems'
require 'plist'
require 'choice'
require 'ruby-debug' if $DEBUG
Choice.options do
header ''
header 'Standard Options:'
option :snippet_dir do
short '-d'
long '--snippet-dir=PATH'
desc 'Tells the program the directory to find the TextMate Snippets'
default '.'
end
option :output_dir do
short '-o'
long '--output-dir=PATH'
desc 'What directory to write the new YASnippets to'
end
option :snippet do
short '-f'
long '--file=SNIPPET FILE NAME'
desc 'A specific snippet that you want to copy or a glob for various files'
default '*.{tmSnippet,plist,tmMacro}'
end
option :print_pretty do
short '-p'
long '--pretty-print'
desc 'Pretty prints multiple snippets when printing to standard out'
end
option :convert_bindings do
short '-b'
long '--convert-bindings'
desc "TextMate \"keyEquivalent\" keys are translated to YASnippet \"# binding :\" directives"
end
option :info_plist do
short '-g'
long '--info-plist'
desc "Attempt to derive group information from \"info.plist\" type-file PLIST"
end
separator ''
separator 'Common options: '
option :help do
long '--help'
desc 'Show this message'
end
end
class TmSnippet
@@known_substitutions=[
{
"${TM_RAILS_TEMPLATE_START_RUBY_EXPR}" => "<%= ",
"${TM_RAILS_TEMPLATE_END_RUBY_EXPR}" => " %>",
"${TM_RAILS_TEMPLATE_START_RUBY_INLINE}" => "<% ",
"${TM_RAILS_TEMPLATE_END_RUBY_INLINE}" => " -%>",
"${TM_RAILS_TEMPLATE_END_RUBY_BLOCK}" => "end" ,
"${0:$TM_SELECTED_TEXT}" => "$TM_SELECTED_TEXT$0",
},
{ "$TM_SELECTED_TEXT" => "`yas/selected-text`" }
]
attr_reader :file
# Makes a TmSnippet
#
# * file is the .tmsnippet/.plist file path relative to cwd
# * optional info is a Plist.parsed info.plist found in the bundle dir
#
def initialize(file,info=nil)
@file = file
@info = info
@snippet = Plist::parse_xml(file)
end
def name
@snippet["name"]
end
def group
if @info
submenus = @info["mainMenu"]["submenus"]
container = submenus.keys.find do |submenu|
submenus[submenu]["items"].member?(uuid)
end
submenus[container]["name"] if container;
end
end
def uuid
@snippet["uuid"]
end
def tab_trigger
@snippet["tabTrigger"]
end
def key_equivalent
@snippet["keyEquivalent"]
end
def content
@snippet["content"]
end
def scope
@snippet["scope"]
end
def to_yasnippet
doc = "# -*- mode: snippet -*-\n"
doc << "# type: command\n" unless self.content
doc << "# key: #{self.tab_trigger}\n" if self.tab_trigger
doc << "# contributor: Translated from TextMate Snippet\n"
doc << "# name: #{self.name}\n"
if self.key_equivalent
doc << "#" unless Choice.choices.convert_bindings
doc << "# binding: \"#{self.key_equivalent}\"\n"
end
if self.scope
doc << "#"
doc << "# condition: \"#{self.scope}\"\n"
end
doc << "# --\n"
if self.content
@@known_substitutions.each {|level| level.each_pair { |k, v| self.content.gsub!(k,v) }}
doc << "#{self.content}"
end
doc
end
def canonicalize(filename)
invalid_char = /[^ a-z_0-9.+=~(){}'"'"'`&#,-]/i
filename.
gsub(invalid_char, ''). # remove invalid characters
gsub(/ {2,}/,' '). # squeeze repeated spaces into a single one
rstrip # remove trailing whitespaces
end
def yasnippet_file(basedir)
# files cannot end with dots (followed by spaces) on windows
basedir = File.join(basedir,group.gsub(/[.]+ *$/,'')) if group
File.join(basedir,canonicalize(@file[0, @file.length-File.extname(@file).length]) + ".yasnippet")
end
end
if $0 == __FILE__
info_plist = Plist::parse_xml(Choice.choices.info_plist) if Choice.choices.info_plist
if Choice.choices.output_dir
FileUtils.mkdir_p Choice.choices.output_dir
FileUtils.touch File.join(Choice.choices.output_dir, ".yas-make-groups")
FileUtils.touch File.join(Choice.choices.output_dir, ".yas-ignore-filenames-as-triggers")
end
original_dir = Dir.pwd
Dir.chdir Choice.choices.snippet_dir
snippet_files_glob = File.join("**", Choice.choices.snippet)
snippet_files = Dir.glob(snippet_files_glob)
puts "Will try to convert #{snippet_files.length} snippets...\n"
snippet_files.each do |file|
begin
puts "Processing \"#{File.join(Choice.choices.snippet_dir,file)}\"\n"
snippet = TmSnippet.new(file,info_plist)
if Choice.choices.output_dir
file_to_create = snippet.yasnippet_file(File.join(original_dir, Choice.choices.output_dir))
FileUtils.mkdir_p(File.dirname(file_to_create))
File.open(file_to_create, 'w') do |f|
f.write(snippet.to_yasnippet)
end
else
if Choice.choices.print_pretty
puts "--------------------------------------------"
end
puts snippet.to_yasnippet
if Choice.choices.print_pretty
puts "--------------------------------------------"
end
puts "\n\n"
end
rescue Exception => e
$stderr.puts "Oops... #{e.class}:#{e.message}"
end
end
end