Class: Talk::Language

Inherits:
Object
  • Object
show all
Defined in:
lib/languages/language.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLanguage

Returns a new instance of Language.



84
85
86
# File 'lib/languages/language.rb', line 84

def initialize
  @written = {}
end

Instance Attribute Details

#supported_languagesObject (readonly)

Returns the value of attribute supported_languages.



48
49
50
# File 'lib/languages/language.rb', line 48

def supported_languages
  @supported_languages
end

Class Method Details

.language_named(lang_name) ⇒ Object



78
79
80
81
# File 'lib/languages/language.rb', line 78

def language_named(lang_name)
  load_supported_languages if @languages.nil?
  @languages[lang_name.to_sym].new
end

.load_language(lang_name) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/languages/language.rb', line 65

def load_language(lang_name)
  lang_name = File.basename(lang_name.to_s, ".rb").to_sym
  new_classname = classname_for_filename(lang_name)
  source_file = path_for_language(lang_name)

  lang = Class.new(Talk::Language) {}

  lang.class_eval( IO.read(source_file), source_file )
  lang.class_eval( "def path\n\t\"#{File.dirname(source_file)}\"\nend" )
  lang.class_eval( "def name\n\t\"#{lang_name}\"\nend" )
  @languages[lang_name.to_sym] = lang
end

.load_supported_languagesObject



55
56
57
58
59
60
61
62
63
# File 'lib/languages/language.rb', line 55

def load_supported_languages
  @languages ||= {}

  local_dir = File.dirname(__FILE__)
  trimmed = Dir["#{local_dir}/*/"].map { |subdir| subdir.gsub(/\/$/, "") }
  supported = trimmed.select { |subdir| File.exists?(File.join(subdir, File.basename(subdir)+".rb")) }
  supported.each { |lang| load_language(lang) }
  supported.map { |lang| lang.to_sym }
end

.path_for_language(lang) ⇒ Object



51
52
53
# File 'lib/languages/language.rb', line 51

def path_for_language(lang)
  File.absolute_path(File.join(File.dirname(__FILE__), "#{lang}/#{lang}.rb"))
end

Instance Method Details

#classname_for_filename(name) ⇒ Object

/path/to/file_name.rb to FileName



195
196
197
# File 'lib/languages/language.rb', line 195

def classname_for_filename(name) # /path/to/file_name.rb to FileName
  File.basename(name.to_s, ".rb").split('_').collect { |word| word.capitalize }.join("")
end

#common_class_prefixObject



181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/languages/language.rb', line 181

def common_class_prefix
  prefix = nil
  @base[:class].each do |cls|
    if prefix.nil? then
      prefix = cls[:name]
    else
      prefix = string_overlap(prefix, cls[:name])
      return nil if prefix.length == 0
    end
  end

  prefix
end

#find_output_pathObject



126
127
128
129
# File 'lib/languages/language.rb', line 126

def find_output_path
  return File.join(ENV['TALK_DESTROOT'], @target[:destination]) if ENV['TALK_DESTROOT']
  @target[:destination]
end

#generate_template(output_file, template_file = nil, transform = nil) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/languages/language.rb', line 131

def generate_template(output_file, template_file=nil, transform=nil)
  template_file ||= output_file + ".erb"
  template_contents = IO.read(File.join(self.path, "templates", template_file))
  erb = ERB.new(template_contents)
  erb.filename = template_file
  source = erb.result(binding)
  source = transform.call(source) unless transform.nil?
  filename = File.join(@output_path, output_file)
  write(filename, source)
  source
end

#mapped_name(container_name, object_name, type, name_key = :name) ⇒ Object



204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/languages/language.rb', line 204

def mapped_name(container_name, object_name, type, name_key=:name)
  return object_name if @target[:map].nil? or @target[:map].empty?

  object_name = object_name[:name] if object_name.is_a? Hash
  container_name = container_name[:name] if container_name.is_a? Hash
  container_name = truncated_name(container_name)

  @target[:map].each do |map|
    matches = (map[:type] == type.to_s && map[:class_name] == container_name && map[:field_name] == object_name)
    return map[:new_field_name] if matches
  end

  object_name
end

#meta(name) ⇒ Object



143
144
145
146
147
148
149
150
151
152
# File 'lib/languages/language.rb', line 143

def meta(name)
  return nil if @target[:meta].nil?
  name = name.to_s

  @target[:meta].each do |meta|
    return meta[:value] if meta[:name].to_s == name
  end

  nil
end

#pruneObject



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/languages/language.rb', line 105

def prune
  # Delete anything we didn't conditionally write, unless it's a directory
  dirs = []
  Dir.glob(@output_path+"/**/*").each do |path|
    abs_path = File.absolute_path(path)
    unless @written.has_key?(abs_path) then
      if File.directory?(abs_path) then
        dirs.push abs_path
      else
        FileUtils::rm(abs_path)
      end
    end
  end

  # Now sort the directories by length, so longest directories are first
  # Since these are abspaths, that should guarantee subdirectories come before parents
  # Then delete each empty directory, tested by containing no entries other than '.' and '..'
  dirs.sort! { |a,b| b.length <=> a.length }
  dirs.each { |dir| FileUtils::rmdir(dir) if (Dir.entries(dir) - %w{ . .. }).empty? }
end

#render(base, target) ⇒ Object



88
89
90
91
92
93
94
95
# File 'lib/languages/language.rb', line 88

def render(base, target)
  @base = base
  @target = target
  @output_path = find_output_path

  make_source
  prune if @target[:prune]
end

#string_overlap(a, b) ⇒ Object



154
155
156
157
158
159
160
161
162
163
# File 'lib/languages/language.rb', line 154

def string_overlap(a,b)
  [a.length, b.length].min.times do |i|
    if a[i] != b[i] then
      return "" if i == 0
      return a[0..i-1]
    end
  end

  a.length < b.length ? a : b
end

#truncated_name(name) ⇒ Object



199
200
201
202
# File 'lib/languages/language.rb', line 199

def truncated_name(name)
  name = name[:name] if name.is_a? Hash
  name.split('.').last
end

#wrap_text_to_width(text, width = 80, preamble = "") ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/languages/language.rb', line 165

def wrap_text_to_width(text, width=80, preamble="")
  width -= preamble.length
  words = text.split(/\s+/)
  lines = []

  words.each do |word|
    if lines.empty? or (lines.last + " " + word).length >= width then
      lines.push (preamble + word)
    else
      lines.last << " " + word
    end
  end

  lines.empty? ? "" : lines.join("\n")
end

#write(path, contents, conditional = true) ⇒ Object



97
98
99
100
101
102
103
# File 'lib/languages/language.rb', line 97

def write(path, contents, conditional=true)
  @written[File.absolute_path(path)] = contents
  return if conditional and File.exists? path and IO.read(path) == contents
  
  FileUtils::mkdir_p(File.dirname(path))
  File.write(path, contents)
end