generamba 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +64 -0
  6. data/LICENSE.txt +21 -0
  7. data/Rakefile +6 -0
  8. data/Readme.md +51 -0
  9. data/bin/GenerambaSandbox/Rambafile +17 -0
  10. data/bin/console +14 -0
  11. data/bin/generamba +5 -0
  12. data/bin/setup +7 -0
  13. data/generamba.gemspec +31 -0
  14. data/lib/generamba.rb +17 -0
  15. data/lib/generamba/cli/cli.rb +15 -0
  16. data/lib/generamba/cli/gen_command.rb +26 -0
  17. data/lib/generamba/cli/setup_command.rb +80 -0
  18. data/lib/generamba/cli/template/template_create_command.rb +29 -0
  19. data/lib/generamba/cli/template/template_group.rb +12 -0
  20. data/lib/generamba/cli/template/template_install_command.rb +10 -0
  21. data/lib/generamba/cli/thor_extension.rb +34 -0
  22. data/lib/generamba/code_generation/Rambafile.liquid +37 -0
  23. data/lib/generamba/code_generation/code_module.rb +32 -0
  24. data/lib/generamba/code_generation/content_generator.rb +42 -0
  25. data/lib/generamba/code_generation/module_template.rb +20 -0
  26. data/lib/generamba/code_generation/rambafile_generator.rb +22 -0
  27. data/lib/generamba/configuration/project_configuration.rb +9 -0
  28. data/lib/generamba/configuration/user_preferences.rb +50 -0
  29. data/lib/generamba/constants/constants.rb +12 -0
  30. data/lib/generamba/constants/rambafile_constants.rb +24 -0
  31. data/lib/generamba/constants/rambaspec_constants.rb +16 -0
  32. data/lib/generamba/constants/user_preferences_constants.rb +5 -0
  33. data/lib/generamba/helpers/template_helper.rb +32 -0
  34. data/lib/generamba/helpers/xcodeproj_helper.rb +87 -0
  35. data/lib/generamba/module_generator.rb +97 -0
  36. data/lib/generamba/template/creator/new_template/Code/Service/service.h.liquid +11 -0
  37. data/lib/generamba/template/creator/new_template/Code/Service/service.m.liquid +13 -0
  38. data/lib/generamba/template/creator/new_template/Tests/Service/service_tests.m.liquid +35 -0
  39. data/lib/generamba/template/creator/new_template/template.rambaspec.liquid +20 -0
  40. data/lib/generamba/template/creator/template_creator.rb +38 -0
  41. data/lib/generamba/template/helpers/rambaspec_validator.rb +47 -0
  42. data/lib/generamba/template/installer/abstract_installer.rb +9 -0
  43. data/lib/generamba/template/installer/catalog_installer.rb +40 -0
  44. data/lib/generamba/template/installer/local_installer.rb +32 -0
  45. data/lib/generamba/template/installer/remote_installer.rb +43 -0
  46. data/lib/generamba/template/processor/template_declaration.rb +34 -0
  47. data/lib/generamba/template/processor/template_processor.rb +77 -0
  48. data/lib/generamba/version.rb +3 -0
  49. metadata +221 -0
@@ -0,0 +1,10 @@
1
+ module Generamba::CLI
2
+ class Template < Thor
3
+
4
+ desc 'install', 'Installs all the templates specified in the Rambafile from the current directory'
5
+ def install
6
+ template_processor = Generamba::TemplateProcessor.new
7
+ template_processor.install_templates
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,34 @@
1
+ require 'thor'
2
+
3
+ module Generamba::CLI
4
+ class ::Thor
5
+ no_commands do
6
+ def ask_index(message, array)
7
+ value_index = ask_with_validation(message,->(value){ (value.to_i >= 0 and value.to_i < array.count) },"Invalid selection. Please enter number from 0 to #{array.count-1}")
8
+ return array[value_index.to_i]
9
+ end
10
+
11
+ def ask_non_empty_string(message, description = 'Value should be nonempty string')
12
+ return ask_with_validation(message,->(value){value.length > 0 },description)
13
+ end
14
+
15
+ def ask_loop(message)
16
+ array = Array.new
17
+ loop do
18
+ value = ask(message)
19
+ break if value.empty?
20
+ array.push(value)
21
+ end
22
+ return array
23
+ end
24
+
25
+ def ask_with_validation(message, is_valid_value, description = 'Invalid value')
26
+ loop do
27
+ value = ask(message)
28
+ break if is_valid_value.call(value)
29
+ puts(description)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ ### Headers settings
2
+ company: {{ company }}
3
+
4
+ ### Xcode project settings
5
+ project_name: {{ project_name }}
6
+ prefix: {{ prefix }}
7
+ xcodeproj_path: {{ xcodeproj_path }}
8
+
9
+ ### Code generation settings section
10
+ # The main project target name
11
+ project_target: {{ project_target }}
12
+
13
+ # The file path for new modules
14
+ project_file_path: {{ project_file_path }}
15
+
16
+ # The Xcode group path to new modules
17
+ project_group_path: {{ project_group_path }}
18
+
19
+ ### Tests generation settings section
20
+ # The tests target name
21
+ test_target: {{ test_target }}
22
+
23
+ # The file path for new tests
24
+ test_file_path: {{ test_file_path }}
25
+
26
+ # The Xcode group path to new tests
27
+ test_group_path: {{ test_group_path }}
28
+
29
+ ### Dependencies settings section
30
+ podfile_path: {{ podfile_path }}
31
+ cartfile_path: {{ cartfile_path }}
32
+
33
+ ### Templates
34
+ templates:
35
+ #- {name: local_template_name, path: absolute/file/path}
36
+ #- {name: remote_template_name, git: https://github.com/igrekde/remote_template}
37
+ #- {name: catalog_template_name}
@@ -0,0 +1,32 @@
1
+ module Generamba
2
+
3
+ # Represents currently generating code module
4
+ class CodeModule
5
+ attr_reader :name, :description, :author, :company, :year, :prefix, :project_name
6
+
7
+ def initialize(name, description)
8
+ @name = name
9
+ @description = description
10
+ end
11
+
12
+ def author
13
+ Generamba::UserPreferences.obtain_username
14
+ end
15
+
16
+ def company
17
+ ProjectConfiguration.company
18
+ end
19
+
20
+ def year
21
+ Time.now.year.to_s
22
+ end
23
+
24
+ def prefix
25
+ ProjectConfiguration.prefix
26
+ end
27
+
28
+ def project_name
29
+ ProjectConfiguration.project_name
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ require 'liquid'
2
+ require 'tilt'
3
+
4
+ module Generamba
5
+
6
+ # Responsible for generating code using provided liquid templates
7
+ class ContentGenerator
8
+
9
+ # Generates and returns a body of a specific code file.
10
+ # @param file []Hash<String,String>] A hashmap with template's filename and filepath
11
+ # @param code_module [CodeModule] The model describing a generating module
12
+ # @param template [ModuleTemplate] The model describing a Generamba template used for code generation
13
+ #
14
+ # @return [String] The generated body
15
+ def self.create_file_content(file, code_module, template)
16
+ file_template = Tilt.new(template.template_path.join(file[TEMPLATE_FILE_PATH_KEY]))
17
+ file_name = File.basename(file[TEMPLATE_FILE_NAME_KEY])
18
+ module_info = {
19
+ 'name' => code_module.name,
20
+ 'file_name' => file_name,
21
+ 'description' => code_module.description,
22
+ 'project_name' => code_module.project_name
23
+ }
24
+
25
+ developer = {
26
+ 'name' => code_module.author,
27
+ 'company' => code_module.company
28
+ }
29
+
30
+ scope = {
31
+ 'year' => code_module.year,
32
+ 'date' => Time.now.strftime('%d/%m/%Y'),
33
+ 'developer' => developer,
34
+ 'module_info' => module_info,
35
+ 'prefix' => code_module.prefix
36
+ }
37
+
38
+ output = file_template.render(scope)
39
+ return output
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ require 'generamba/helpers/template_helper.rb'
2
+ require 'settingslogic'
3
+
4
+ module Generamba
5
+
6
+ # Represents a single Generamba module template
7
+ class ModuleTemplate
8
+ attr_reader :template_name, :template_path, :code_files, :test_files
9
+
10
+ def initialize(name)
11
+ spec_path = TemplateHelper.obtain_spec(name)
12
+ spec = Settingslogic.new(spec_path)
13
+
14
+ @code_files = spec[TEMPLATE_CODE_FILES_KEY]
15
+ @test_files = spec[TEMPLATE_TEST_FILES_KEY]
16
+ @template_name = spec.name
17
+ @template_path = TemplateHelper.obtain_path(name)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'liquid'
2
+ require 'tilt'
3
+
4
+ module Generamba
5
+
6
+ # Responsible for creating Generamba configs
7
+ class RambafileGenerator
8
+
9
+ # Creates a Rambafile using the provided properties hashmap
10
+ # @param properties Rambafile properties
11
+ #
12
+ # @return void
13
+ def self.create_rambafile(properties)
14
+ template = Tilt.new(File.dirname(__FILE__) + '/Rambafile.liquid')
15
+ output = template.render(properties)
16
+
17
+ File.open(RAMBAFILE_NAME, 'w+') {|f|
18
+ f.write(output)
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ require 'settingslogic'
2
+
3
+ module Generamba
4
+
5
+ # A singletone class representing a Rambafile of the current project
6
+ class ProjectConfiguration < Settingslogic
7
+ source Dir.getwd + '/' + RAMBAFILE_NAME
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ require 'generamba/constants/user_preferences_constants.rb'
2
+
3
+ module Generamba
4
+
5
+ # A class that provides methods for working with user-specific information.
6
+ # Currently it has methods for obtaining and saving username, later it may be improved to something more general.
7
+ class UserPreferences
8
+
9
+ def self.obtain_username
10
+ path = obtain_user_preferences_path
11
+
12
+ file_contents = open(path).read
13
+ preferences = file_contents.empty? ? {} : YAML.load(file_contents).to_hash
14
+
15
+ return preferences[USERNAME_KEY]
16
+ end
17
+
18
+ def self.save_username(username)
19
+ path = obtain_user_preferences_path
20
+
21
+ file_contents = open(path).read
22
+ preferences = file_contents.empty? ? {} : YAML.load(file_contents).to_hash
23
+
24
+ preferences[USERNAME_KEY] = username
25
+ File.open(path, 'w+') { |f| f.write(preferences.to_yaml) }
26
+ end
27
+
28
+ private
29
+
30
+ def self.obtain_user_preferences_path
31
+ home_path = Pathname.new(ENV['HOME'])
32
+ .join(GENERAMBA_HOME_DIR)
33
+
34
+ path_exists = Dir.exist?(home_path)
35
+
36
+ if path_exists == false
37
+ FileUtils.mkdir_p home_path
38
+ end
39
+
40
+ preferences_path = home_path.join(USER_PREFERENCES_FILE)
41
+ preferences_exist = File.file?(preferences_path)
42
+
43
+ if preferences_exist == false
44
+ File.open(preferences_path, 'w+') { |f| f.write('') }
45
+ end
46
+
47
+ return preferences_path
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ module Generamba
2
+
3
+ # General constants
4
+ RAMBAFILE_NAME = 'Rambafile'
5
+ RAMBASPEC_EXTENSION = '.rambaspec'
6
+ TEMPLATES_FOLDER = 'Templates'
7
+ RAMBLER_CATALOG_REPO = 'https://github.com/rambler-ios/generamba-catalog'
8
+ GENERAMBA_CATALOG_NAME = 'generamba-catalog'
9
+ GENERAMBA_HOME_DIR = '.generamba'
10
+ CATALOGS_DIR = 'catalogs'
11
+ USER_PREFERENCES_FILE = 'user_preferences.yml'
12
+ end
@@ -0,0 +1,24 @@
1
+ module Generamba
2
+
3
+ # Keys of Rambafile files
4
+ COMPANY_KEY = 'company'
5
+ PROJECT_NAME_KEY = 'project_name'
6
+ PROJECT_PREFIX_KEY = 'prefix'
7
+ XCODEPROJ_PATH_KEY = 'xcodeproj_path'
8
+
9
+ PROJECT_TARGET_KEY = 'project_target'
10
+ PROJECT_FILE_PATH_KEY = 'project_file_path'
11
+ PROJECT_GROUP_PATH_KEY = 'project_group_path'
12
+
13
+ TEST_TARGET_KEY = 'test_target'
14
+ TEST_FILE_PATH_KEY = 'test_file_path'
15
+ TEST_GROUP_PATH_KEY = 'test_group_path'
16
+
17
+ PODFILE_PATH_KEY = 'podfile_path'
18
+ CARTFILE_PATH_KEY = 'cartfile_path'
19
+
20
+ TEMPLATES_KEY = 'templates'
21
+ TEMPLATE_DECLARATION_NAME_KEY = 'name'
22
+ TEMPLATE_DECLARATION_LOCAL_KEY = 'local'
23
+ TEMPLATE_DECLARATION_GIT_KEY = 'git'
24
+ end
@@ -0,0 +1,16 @@
1
+ module Generamba
2
+
3
+ # Keys of .rambaspec files
4
+ TEMPLATE_NAME_KEY = 'name'
5
+ TEMPLATE_SUMMARY_KEY = 'summary'
6
+ TEMPLATE_AUTHOR_KEY = 'author'
7
+ TEMPLATE_VERSION_KEY = 'version'
8
+ TEMPLATE_LICENSE_KEY = 'license'
9
+
10
+ TEMPLATE_CODE_FILES_KEY = 'code_files'
11
+ TEMPLATE_TEST_FILES_KEY = 'test_files'
12
+ TEMPLATE_FILE_NAME_KEY = 'name'
13
+ TEMPLATE_FILE_PATH_KEY = 'path'
14
+
15
+ TEMPLATE_DEPENDENCIES_KEY = 'dependencies'
16
+ end
@@ -0,0 +1,5 @@
1
+ module Generamba
2
+
3
+ # Keys of file user_preferences.yml
4
+ USERNAME_KEY = 'username'
5
+ end
@@ -0,0 +1,32 @@
1
+ module Generamba
2
+
3
+ # Provides a number of helper methods for manipulating Generamba template files
4
+ class TemplateHelper
5
+
6
+ # Returns a file path for a specific template .rambaspec file
7
+ # @param template_name [String] The Generamba template name
8
+ #
9
+ # @return [Pathname]
10
+ def self.obtain_spec(template_name)
11
+ template_path = self.obtain_path(template_name)
12
+ spec_path = template_path.join(template_name + RAMBASPEC_EXTENSION)
13
+
14
+ return spec_path
15
+ end
16
+
17
+ # Returns a file path for a specific template folder
18
+ # @param template_name [String] The Generamba template name
19
+ #
20
+ # @return [Pathname]
21
+ def self.obtain_path(template_name)
22
+ path = Pathname.new(Dir.getwd)
23
+ .join(TEMPLATES_FOLDER)
24
+ .join(template_name)
25
+
26
+ error_description = "Cannot find #{template_name}! Add it to the Rambafile and run *generamba template install*"
27
+ raise StandardError.new(error_description) if path.exist? == false
28
+
29
+ return path
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,87 @@
1
+ module Generamba
2
+
3
+ # Provides a number of helper methods for working with xcodeproj gem
4
+ class XcodeprojHelper
5
+
6
+ # Returns a PBXProject class for a given name
7
+ # @param project_name [String] The name of the project file
8
+ #
9
+ # @return [Xcodeproj::Project]
10
+ def self.obtain_project(project_name)
11
+ Xcodeproj::Project.open(project_name)
12
+ end
13
+
14
+ # Returns an AbstractTarget class for a given name
15
+ # @param target_name [String] The name of the target
16
+ # @param project [Xcodeproj::Project] The target xcodeproj file
17
+ #
18
+ # @return [Xcodeproj::AbstractTarget]
19
+ def self.obtain_target(target_name, project)
20
+ project.targets.each { |target|
21
+ if target.name == target_name
22
+ return target
23
+ end
24
+ }
25
+ end
26
+
27
+ # Adds a provided file to a specific Project and Target
28
+ # @param project [Xcodeproj::Project] The target xcodeproj file
29
+ # @param target [AbstractTarget] The target for a file
30
+ # @param group_path [Pathname] The Xcode group path for current file
31
+ # @param file_path [Pathname] The file path for current file
32
+ #
33
+ # @return [void]
34
+ def self.add_file_to_project_and_target(project, target, group_path, file_path)
35
+ module_group = self.retreive_or_create_group(group_path, project)
36
+ xcode_file = module_group.new_file(File.absolute_path(file_path))
37
+
38
+ file_name = File.basename(file_path)
39
+ if File.extname(file_name) == '.m'
40
+ target.add_file_references([xcode_file])
41
+ end
42
+ end
43
+
44
+ # Recursively clears children of te given group
45
+ # @param project [Xcodeproj::Project] The working Xcode project file
46
+ # @param group_path [Pathname] The full group path
47
+ #
48
+ # @return [Void]
49
+ def self.clear_group(project, group_path)
50
+ module_group = self.retreive_or_create_group(group_path, project)
51
+ module_group.clear
52
+ end
53
+
54
+ private
55
+
56
+ # Finds or creates a group in a xcodeproj file with a given path
57
+ # @param group_path [Pathname] The full group path
58
+ # @param project [Xcodeproj::Project] The working Xcode project file
59
+ #
60
+ # @return [PBXGroup]
61
+ def self.retreive_or_create_group(group_path, project)
62
+ group_names = group_names_from_group_path(group_path)
63
+
64
+ final_group = project
65
+
66
+ group_names.each do |group_name|
67
+ next_group = final_group[group_name]
68
+ if (next_group == nil)
69
+ next_group = final_group.new_group(group_name)
70
+ end
71
+
72
+ final_group = next_group
73
+ end
74
+
75
+ return final_group
76
+ end
77
+
78
+ # Splits the provided Xcode group path to an array of separate groups
79
+ # @param group_path The full group path
80
+ #
81
+ # @return [[String]]
82
+ def self.group_names_from_group_path(group_path)
83
+ groups = group_path.to_s.split('/')
84
+ return groups
85
+ end
86
+ end
87
+ end