0
-require 'rexml/document'
0
-$: << ENV['TM_SUPPORT_PATH'] + '/lib'
0
- def generate_rtf input
0
- generate_stylesheet_from_theme
0
- doc = rtf_document input
0
- CGI::unescapeHTML(doc)
0
- def add_style_recursive scopes, style, styles
0
- current = scopes.shift.strip
0
- styles[current] ||= {}
0
- styles[current][:default] = style
0
- add_style_recursive scopes, style, styles[current]
0
- def add_style_from_textmate_theme name, settings
0
- style_names = name.split ','
0
- style_names.each do |sn|
0
- add_style_recursive sn.split('.'), style, @styles
0
- if fs = settings['fontStyle']
0
- style[:bold] = fs =~ /bold/
0
- style[:italic] if fs =~ /italic/
0
- style[:underline] if fs =~ /underline/
0
- if col = settings['foreground']
0
- style[:color] = hex_color_to_rtf col
0
- @colors << style[:color]
0
- style[:color_index] = @num_colors+=1
0
- def hex_color_to_rtf hex
0
- hex =~ /#(..)(..)(..)/
0
- return "\\red#{r}\\green#{g}\\blue#{b};"
0
- def generate_stylesheet_from_theme(theme_class = nil)
0
- theme_class = '' if theme_class == nil
0
- require "#{ENV['TM_SUPPORT_PATH']}/lib/osx/plist"
0
- # Load TM preferences to discover the current theme and font settings
0
- textmate_pref_file = '~/Library/Preferences/com.macromates.textmate.plist'
0
- prefs = PropertyList.load(File.open(File.expand_path(textmate_pref_file)))
0
- theme_uuid = prefs['OakThemeManagerSelectedTheme']
0
- # Load the active theme. Unfortunately, this requires us to scan through
0
- # all discoverable theme files...
0
- unless theme_plist = find_theme(theme_uuid)
0
- print "Could not locate your theme file!"
0
- theme_comment = theme_plist['comment']
0
- theme_name = theme_plist['name']
0
- theme_class.replace(theme_name)
0
- theme_class.gsub!(/[^a-z0-9_-]/, '_')
0
- theme_class.gsub!(/_+/, '_')
0
- @font_name = prefs['OakTextViewNormalFontName'] || 'Monaco'
0
- @font_size = (prefs['OakTextViewNormalFontSize'] || 11).to_s
0
- @font_size.sub! /\.\d+$/, ''
0
- @font_size = @font_size.to_i * 3
0
- @font_name = '"' + @font_name + '"' if @font_name.include?(' ') &&
0
- !@font_name.include?('"')
0
- theme_plist['settings'].each do | setting |
0
- if (!setting['name'] and setting['settings'])
0
- body_bg = setting['settings']['background'] || '#ffffff'
0
- body_fg = setting['settings']['foreground'] || '#000000'
0
- selection_bg = setting['settings']['selection']
0
- body_bg = hex_color_to_rtf(body_bg)
0
- body_fg = hex_color_to_rtf(body_fg)
0
- selection_bg = hex_color_to_rtf(selection_bg) if selection_bg
0
- if setting['name'] && setting['scope']
0
- scope_name = setting['scope']
0
- # scope_name.gsub! /(^|[ ])-[^ ]+/, '' # strip negated scopes
0
- # scope_name.gsub! /\./, '_' # change inner '.' to '_'
0
- # #scope_name.gsub! /(^|[ ])/, '\1.'
0
- # scope_name.gsub! /[ ]/, '_' # spaces to underscores
0
- # scope_name.gsub! /(^|,\s+)/m, '\1'
0
- add_style_from_textmate_theme scope_name, setting['settings']
0
- "{\\colortbl;#{@colors}}"
0
- "{\\fonttbl {\\f0 #{@font_name};}}"
0
- def rtf_document input
0
-\\f0\\fs#{@font_size} #{document_to_rtf input}
0
- # \\f0\\fs#{@font_size}\\cf1\\b Hello, World!\\line
0
- # \\tab \\cf2 Next Line\\line
0
- # \\tab\\tab\\i \\cf3 Another line
0
- # Search heuristic is based on the Theme Builder bundle's
0
- # "Create for Current Language" command
0
- File.expand_path('~/Library/Application Support/TextMate/Themes'),
0
- '/Library/Application Support/TextMate/Themes',
0
- TextMate.app_path + '/Contents/SharedSupport/Themes'
0
- theme_dirs.each do |theme_dir|
0
- if File.exists? theme_dir
0
- themes = Dir.entries(theme_dir).find_all { |theme| theme =~ /.+\.(tmTheme|plist)$/ }
0
- themes.each do |theme|
0
- plist = PropertyList.load(File.open("#{theme_dir}/#{theme}"))
0
- return plist if plist["uuid"] == uuid
0
- lines = str.split(/\n/)
0
- lines.each do | line |
0
- line_sans_markup = line.gsub(/<[^>]*>/, '').gsub(/&[^;]+;/i, '.')
0
- while (index = line_sans_markup.index("\t"))
0
- tab = line_sans_markup[0..index].jlength - 1
0
- padding = " " * ((tab / width + 1) * width - tab)
0
- line_sans_markup.sub!("\t", padding)
0
- line.sub!("\t", padding)
0
- return lines.join("\n")
0
- def document_to_rtf(input, opt = {})
0
- # Read the source document / selection
0
- # Convert tabs to spaces using configured tab width
0
- input = detab(input, (ENV['TM_TAB_SIZE'] || '8').to_i)
0
- input.gsub! /\\/, "__backslash__"
0
- input.gsub! /\\n/, "__newline__"
0
- input.gsub! /\n/, "\\\\line\n"
0
- input.gsub! /\{/, "\\{"
0
- input.gsub! /\}/, "\\}"
0
- input.gsub! /__newline__/, "\\\\\\n"
0
- input.gsub! /__backslash__/, "\\\\\\"
0
- # Meat. The poor-man's tokenizer. Fortunately, our input is simple
0
- tokens = input.split(/(<[^>]*>)/)
0
- tokens.each do |token|
0
- # skip empty tags, resulting from name = ''
0
- if token =~ /^<([^>]+)>$/
0
- style = current_style_as_rtf
0
- if style && !style.empty? && !token.strip.empty?
0
- code_rtf << current_style_as_rtf << ' '
0
- code_rtf << token << '}'
0
- def get_style_recursive scopes, styles
0
- #scopes -= ["punctuation", "definition"] # nasty workaround hack
0
- return nil unless styles
0
- cur = scopes.shift.strip
0
- style = get_style_recursive(scopes, styles[cur]) || style
0
- style ||= styles[:default]
0
- def current_style_as_rtf
0
- rtf << "\\cf#{cur[:color_index]}" if cur[:color_index]
0
- rtf << "\\b" if cur[:bold]
0
- rtf << "\\i" if cur[:italic]
0
- rtf << "\\ul" if cur[:underline]
0
- new_style = get_style_recursive(name.split('.'), @styles)
0
- # p "got #{new_style.inspect}"
0
- # p "current: #{cur.inspect}"
0
- new_style = cur.merge new_style if new_style
0
- new_style ||= cur || {}
0
- unless new_style[:color_index]
0
- new_style[:color_index] = 0
0
- # p "merged: #{new_style.inspect}"
0
- @style_stack.unshift new_style