Module: SemillaGen

Defined in:
lib/semillagen.rb,
lib/semillagen/utils.rb,
lib/semillagen/version.rb,
lib/semillagen/generator.rb

Defined Under Namespace

Classes: TemplateItem

Constant Summary collapse

DEFAULT_TEMPLATE_FOLDER =
File.expand_path('../default_templates', File.dirname(__FILE__))
DEFAULT_PROJECTNAME =
"MagicBox"
TEMPLATE_FOLDER =
"semilla_templates"
VERSION =
'0.0.2'

Class Method Summary collapse

Class Method Details

.findTemplate(itemtype, templatename) ⇒ Object

Find the template for the specified item type and template name. Ex: Find a template for projects, named ClassicMVVMProjectTemplate

Parameters:

  • can (itemtype)

    be ‘:class’ or ‘:project’

  • (templatename)


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/semillagen/utils.rb', line 13

def self.findTemplate(itemtype, templatename)

  dirs = [
    File.expand_path(TEMPLATE_FOLDER), #current folder
    File.expand_path("~/#{TEMPLATE_FOLDER}"), #home folder
    SemillaGen::DEFAULT_TEMPLATE_FOLDER #gem lib folder
  ]

  absolute_path = nil;
  location = File.join(itemtype.to_s, templatename.to_s)
  #puts "location #{location}"
  
  dirs.each do |dir|
    #Look for location in dir
    currentlocation = File.join(dir, location)
    #puts currentlocation
    if File.directory? currentlocation
      absolute_path = currentlocation
      break;
    end
  end

  #If we found the template, absolute_path should not be nil
  puts "Template found at: #{absolute_path}"
  return absolute_path
end

.generate(itemtype, template, name) ⇒ Object

Generates items (Projects or Classes) using the specified template and name.

Parameters:

  • The (itemtype)

    kind of item to create, ‘:class’ or ‘:project’.

  • The (template)

    name of the template to use.

  • The (name)

    name of project or qualified class name to generate.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/semillagen/generator.rb', line 21

def self.generate(itemtype, template, name)
  
  #find the template folder
  template_folder = SemillaGen::findTemplate(itemtype, template)
  
  raise "Template not found." if template_folder.nil?
  
  
  if itemtype == :class
    #When item is a class type
    
    #Read the info.semilla file
    files = SemillaGen::parseInfoFile File.join(template_folder, "info.semilla")
    SemillaGen::generateFiles(template_folder, files, name)
  
  elsif itemtype == :project
    #when item is a project type
    
    SemillaGen::generateProject(template_folder, name)
  end
end

.generateFiles(templateFolder, fileList, qualifiedName) ⇒ Object

Generates files for a class.

Parameters:

  • The (templateFolder)

    folder where the template to be used is located.

  • The (fileList)

    collection of TemplateItems to be generated.

  • The (qualifiedName)

    qualified name of the class to be generated (includes namespaces)



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/semillagen/generator.rb', line 120

def self.generateFiles(templateFolder, fileList, qualifiedName)
  puts "Generating files for: #{qualifiedName}"
  
  fileList.map do |key, item|
    #puts "----------#{key}"
    
    #Check that the sourceFile exists
    source_full_path = File.absolute_path(File.join(templateFolder, item.source))
    if File.exists? source_full_path
      #Obtain namespaces
      namespaces = qualifiedName.split '.' #Separate all the qualified name components
      itemName = namespaces.last #the last component is the class name
      namespaces = namespaces.take(namespaces.length-1) #The rest is the namespace (as array)
      namespace_text = namespaces.join('.') #the namespace in ActionScript notation
      
      #Append to the target path, the namespaces as folders
      final_path = namespaces.unshift(item.target).join(File::SEPARATOR)
      #Make sure the final_path directories exist
      self.recursive_mkdir final_path
      
      #Generate the new name
      fileName = item.name_pattern.sub('@@', itemName)
      
      #Read the source file
      source_text = IO.read source_full_path
      
      #Define the keywords to be replaced in the template
      keywords = {}
      keywords['@@PACKAGE@@'] = namespace_text
      keywords['@@NAME@@'] = itemName
      #Replace the keywords in the source text
      keywords.each do |k,v|
        source_text.gsub! k, v #use gsub to teplace all ocurrences
      end
      #Write out the file
      outpath = File.join(final_path, fileName)
      puts "    => #{outpath}"
      File.open(outpath, 'w') {|w| w << source_text}
              
    else #The source file is not found but it was specified in the info.semilla file.
      raise "Template file is missing: [#{item.source}]"
    end
    
  end
  
end

.generateProject(templateFolder, name) ⇒ Object

Generates a project

Parameters:

  • The (templateFolder)

    folder containing the project template to use

  • The (name)

    name of the new project



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/semillagen/generator.rb', line 228

def self.generateProject(templateFolder, name)
  puts "Generating project [#{name}]"
  
  #Create directory
  Dir.mkdir name
  
  options = {}
  options[:project_name] = name
  options[:allowed_files] = %w{.gitignore} 
  options[:dont_process_contents] = %w{.swc .swf .jar .exe .bin}
  
  target_path = File.join(Dir.pwd, name)
  
  self.recursiveCopyDir(templateFolder, target_path, options)
    
end

.parseInfoFile(path) ⇒ Array of TemplateItem

Read a info.semilla file. This file contains a description of the files to create. Each line has the following format:

filename_pattern : template_file => target_path

filename_pattern = How the generated file should be named.
template_file = The file whose contents will be used to generate the new file.
                Some keywords inside the text will be replaced
                (@@PACKAGE@@, @@NAME@@)
target_path = The folder where the file should be created.

Parameters:

  • The (path)

    path to the info.semilla file to read.

Returns:

  • (Array of TemplateItem)

    The collection of TemplateItem parsed.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/semillagen/generator.rb', line 59

def self.parseInfoFile(path)
  
  files = {}
  
  if File.exists? path
    File.open(path, 'r') do |f|
      while(line = f.gets)
        line.strip! #Remove white space
        
        next if line.start_with?("#") or line.empty? #Skip comments or blank lines
        
        #Match "FILENAME => PATH"
        line.match(/([@\w.\-]+)\s*:\s*([\w.\-]+\.tpl) => ([\w.\-\/]+)/) do |m|
           nameFormat, sourceFile, targetPath = m.captures
           
           item = SemillaGen::TemplateItem.new
           item.target = targetPath
           item.name_pattern = nameFormat
           item.source = sourceFile
           
           files[sourceFile] = item
        end
        
      end
    end
  end
  
  return files
  
end

.processText(text, options) ⇒ String

Replaces the DEFAULT_PROJECTNAME in the string to the one specified in options

Parameters:

  • The (text)

    that will we processed

  • Hash (options)

    array with the values to be used while processing the text

Returns:

  • (String)


220
221
222
# File 'lib/semillagen/generator.rb', line 220

def self.processText(text, options)
  return text.gsub(SemillaGen::DEFAULT_PROJECTNAME, options[:project_name]) 
end

.recursive_mkdir(path) ⇒ Object

Creates a directory hierarchy for the given directory path if the directories do not exist.

Parameters:

  • The (path)

    path to create if it does not exist already.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/semillagen/generator.rb', line 96

def self.recursive_mkdir(path)
  steps = path.split File::SEPARATOR
  
  original_dir = Dir.pwd
  
  steps.each do |s|
    #Make dir if it does not exist
    if !File.directory? s
      Dir.mkdir s
      #puts "mkdir #{s}"
    end 
    Dir.chdir s
  end
  
  Dir.chdir original_dir
  
end

.recursiveCopyDir(path, target_path, options) ⇒ Object

Copies (while adjusting contents of files) files and directories recursively.

Parameters:

  • The (path)

    path where the source files are read

  • The (target_path)

    path where the new files will be copied to

  • Hash (options)

    containing some settings for the file generation/adjustment



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/semillagen/generator.rb', line 172

def self.recursiveCopyDir(path, target_path, options)
  Dir.foreach path do |f|
    #Skip hidden files, unless in 'allowedFiles' list
    next if f.start_with?(".") and !options[:allowed_files].include?(f)
    
    #The absolute path for the template file/dir
    source_path = File.join path, f
    #The name of the file/dir to generate
    target_name = self.processText f, options
    #The absolute path of the file/dir to generate
    generate_path = File.join target_path, target_name
    
    if File.directory?(source_path)
      #Create the new dir
      Dir.mkdir generate_path
      puts "mkdir #{generate_path}"
      self.recursiveCopyDir(source_path, generate_path, options)
      
    else
      #Copy the file to the new destination
      
      # -> **Only process files whose extension is not in options[:dont_process_contents]
      should_process = options[:dont_process_contents].index{|x| source_path.end_with? x}.nil?
      if should_process
        # -> Read file contents
        fileContents = IO.read source_path
        # -> Adjust project name in content
        fileContents = self.processText fileContents, options
        # -> Write file to destination path
        puts "write #{generate_path} [E]" #The [E] at the end means that the file's contents were editted (ex: Project name replaced).
        File.open(generate_path, 'w') {|w| w << fileContents}
      else
        #just copy the file as is
        puts "write #{generate_path}"
        `cp "#{source_path}" "#{generate_path}"`
      end
      
      
    end
  end
end