new 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +16 -0
  5. data/Gemfile.lock +79 -0
  6. data/Guardfile +14 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +121 -0
  9. data/bin/new +6 -0
  10. data/lib/new/cli.rb +94 -0
  11. data/lib/new/core.rb +6 -0
  12. data/lib/new/dsl.rb +42 -0
  13. data/lib/new/interpolate.rb +100 -0
  14. data/lib/new/project.rb +34 -0
  15. data/lib/new/task.rb +41 -0
  16. data/lib/new/template.rb +64 -0
  17. data/lib/new/version.rb +41 -0
  18. data/lib/new.rb +72 -0
  19. data/new-0.0.0.gem +0 -0
  20. data/new-0.0.1.gem +0 -0
  21. data/spec/fixtures/custom/tasks/custom_bar_task/custom_bar_task.rb +3 -0
  22. data/spec/fixtures/custom/templates/custom_bar_template/custom_bar.txt +0 -0
  23. data/spec/fixtures/tasks/custom_bar_task/custom_bar_task.rb +1 -0
  24. data/spec/fixtures/tasks/foo_task/foo_task.rb +7 -0
  25. data/spec/fixtures/templates/foo_template/[FOO.BAR].txt.erb +1 -0
  26. data/spec/fixtures/templates/foo_template/nested_[FOO.BAR]/foo.txt.erb +1 -0
  27. data/spec/lib/new/cli_spec.rb +104 -0
  28. data/spec/lib/new/interpolate_spec.rb +41 -0
  29. data/spec/lib/new/project_spec.rb +30 -0
  30. data/spec/lib/new/task_spec.rb +39 -0
  31. data/spec/lib/new/template_spec.rb +59 -0
  32. data/spec/lib/new/version_spec.rb +28 -0
  33. data/spec/lib/new_spec.rb +19 -0
  34. data/spec/spec_helper.rb +26 -0
  35. data/tasks/gem/README.md +36 -0
  36. data/tasks/gem/gem.rb +122 -0
  37. data/templates/js/Gemfile +30 -0
  38. data/templates/js/Guardfile +7 -0
  39. data/templates/js/LICENSE-MIT.erb +22 -0
  40. data/templates/js/README.md.erb +61 -0
  41. data/templates/js/demo/index.html.erb +7 -0
  42. data/templates/js/lib/README.md +2 -0
  43. data/templates/js/spec/[PROJECT_NAME].spec.js.coffee.erb +1 -0
  44. data/templates/js/spec/index.html.erb +29 -0
  45. data/templates/js/spec/spec_helper.js.coffee +0 -0
  46. data/templates/js/spec/vendor/chai.js +3765 -0
  47. data/templates/js/spec/vendor/sinon-chai.js +106 -0
  48. data/templates/js/spec/vendor/sinon.js +4246 -0
  49. data/templates/js/src/README.md +3 -0
  50. data/templates/js/src/[PROJECT_NAME].js.coffee.erb +10 -0
  51. data/templates/js/testem.yml +12 -0
  52. metadata +70 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c3b29c54510394a8dfc16cc00b715664c80ebae
4
- data.tar.gz: b10f62854a0d4ae54c26828fe0478df3d788f9e9
3
+ metadata.gz: 6bc7ceccb527c6c45b6d98046b396a55890aa2bc
4
+ data.tar.gz: 688b33a0980e1ab5413d2e2d92fbc1b187d93c72
5
5
  SHA512:
6
- metadata.gz: dd87c91c29b0e0ea974c1492f1403d9945f5ca931ddd68d4bdeea0f3cba87cce14814bfd6a615ccec05041b5c934276c34a432d494ee4cde578bae833ae2cd78
7
- data.tar.gz: 0417f699e034770fd7376e83d244ad86e264765b239f278ae416fe96b82516a56048ea3493f0f07076795a6412f808488de5022e09e997497d9fa58d8f099af0
6
+ metadata.gz: 3896cfd37150e57dba854c0da96a35880e537434a2e9b5348e43884acc7b8445c22f8b27ebff21b887a711f8797b5d143b135b9c0388e3f5c072b0f12cc24fed
7
+ data.tar.gz: 3ad4cb4fbf8b15e15316a7d12bd74f9af061f9583164ef142f95c5f21a6b5c218ca55aaf83f809767f0923f78f2f35dffc1f16c29a28b9fe29e5ddad689f7e4c
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ .bundle
3
+ .tmp
4
+ .new
5
+ pkg
6
+ tmp
7
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activesupport'
4
+ gem 'colorize'
5
+ gem 'rake'
6
+ gem 'recursive-open-struct'
7
+ gem 'semantic'
8
+ gem 'thor'
9
+
10
+ group :development do
11
+ gem 'guard'
12
+ gem 'guard-bundler'
13
+ gem 'guard-rspec'
14
+ gem 'rspec'
15
+ gem 'terminal-notifier-guard'
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,79 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activesupport (4.0.2)
5
+ i18n (~> 0.6, >= 0.6.4)
6
+ minitest (~> 4.2)
7
+ multi_json (~> 1.3)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 0.3.37)
10
+ atomic (1.1.14)
11
+ celluloid (0.15.2)
12
+ timers (~> 1.1.0)
13
+ coderay (1.1.0)
14
+ colorize (0.6.0)
15
+ diff-lcs (1.2.5)
16
+ ffi (1.9.3)
17
+ formatador (0.2.4)
18
+ guard (2.3.0)
19
+ formatador (>= 0.2.4)
20
+ listen (~> 2.1)
21
+ lumberjack (~> 1.0)
22
+ pry (>= 0.9.12)
23
+ thor (>= 0.18.1)
24
+ guard-bundler (2.0.0)
25
+ bundler (~> 1.0)
26
+ guard (~> 2.2)
27
+ guard-rspec (4.2.5)
28
+ guard (~> 2.1)
29
+ rspec (>= 2.14, < 4.0)
30
+ i18n (0.6.9)
31
+ listen (2.4.0)
32
+ celluloid (>= 0.15.2)
33
+ rb-fsevent (>= 0.9.3)
34
+ rb-inotify (>= 0.9)
35
+ lumberjack (1.0.4)
36
+ method_source (0.8.2)
37
+ minitest (4.7.5)
38
+ multi_json (1.8.4)
39
+ pry (0.9.12.4)
40
+ coderay (~> 1.0)
41
+ method_source (~> 0.8)
42
+ slop (~> 3.4)
43
+ rake (10.1.0)
44
+ rb-fsevent (0.9.4)
45
+ rb-inotify (0.9.3)
46
+ ffi (>= 0.5.0)
47
+ recursive-open-struct (0.4.5)
48
+ rspec (2.14.1)
49
+ rspec-core (~> 2.14.0)
50
+ rspec-expectations (~> 2.14.0)
51
+ rspec-mocks (~> 2.14.0)
52
+ rspec-core (2.14.7)
53
+ rspec-expectations (2.14.4)
54
+ diff-lcs (>= 1.1.3, < 2.0)
55
+ rspec-mocks (2.14.4)
56
+ semantic (1.3.0)
57
+ slop (3.4.7)
58
+ terminal-notifier-guard (1.5.3)
59
+ thor (0.18.1)
60
+ thread_safe (0.1.3)
61
+ atomic
62
+ timers (1.1.0)
63
+ tzinfo (0.3.38)
64
+
65
+ PLATFORMS
66
+ ruby
67
+
68
+ DEPENDENCIES
69
+ activesupport
70
+ colorize
71
+ guard
72
+ guard-bundler
73
+ guard-rspec
74
+ rake
75
+ recursive-open-struct
76
+ rspec
77
+ semantic
78
+ terminal-notifier-guard
79
+ thor
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # More info at https://github.com/guard/guard#readme
2
+
3
+ notification :terminal_notifier, subtitle: 'ruby.gems.new'
4
+
5
+ guard :bundler do
6
+ watch('Gemfile')
7
+ end
8
+
9
+ guard :rspec, all_after_pass: true, all_on_start: true, cmd: 'bundle exec rspec' do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { 'spec' }
13
+ watch('.rspec') { 'spec' }
14
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ryan Brewster
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # new
2
+ ###### install
3
+ ```shell
4
+ gem install new
5
+ new init
6
+ ```
7
+
8
+ ###### Create a new project
9
+ ```shell
10
+ new [TEMPLATE] [NAME]
11
+ ```
12
+
13
+ ###### Release a new version
14
+ ```shell
15
+ new release
16
+ ```
17
+
18
+ #### Templates
19
+ Templates represent a boilerplate directory & file structure preconfigured for a given project type. _(eg js, ruby, gem, rails, etc.)_
20
+
21
+ #### Tasks
22
+ Tasks represent a process associated with releasing new code. Tasks are run in order they are listed in the project `.new` configuration file. _(eg github, gem, etc.)_
23
+
24
+ #### Local Config/Templates/Tasks
25
+ After running `new init`, you will have `.new` folder in your home directory. This directory contains:
26
+
27
+ * `.new` local configuration file
28
+ * `tasks` directory for custom tasks
29
+ * `templates` directory for custom templates
30
+
31
+ Copy or create custom templates & tasks in these folders. They will take precendence over the default templates included with the gem.
32
+
33
+ **Make sure to edit your local configuration file!**
34
+
35
+ ```yaml
36
+ # ~/.new/.new
37
+
38
+ license: MIT
39
+ developer:
40
+ name: Foo Bar
41
+ email: foo@bar.com
42
+ templates:
43
+ foo_template:
44
+ custom: option
45
+ tasks:
46
+ github:
47
+ username: foouser
48
+ ```
49
+
50
+
51
+ #### Custom Templates
52
+ * The directory name will be used for the template name.
53
+ * Templates can have a `.new` file in the root of the folder. These values can be accessed through interpolation.
54
+
55
+ ```yaml
56
+ # ~/.new/templates/foo_template/.new
57
+
58
+ foo: bar
59
+ tasks:
60
+ foo_task:
61
+ bar_task:
62
+ baz: 'baz'
63
+ ```
64
+
65
+ _Note: the tasks are followed by a colon `:` whether they have options or not._
66
+
67
+ ###### Interpolation
68
+ Use ERB template syntax in your files to interpolate template options. Make sure to add `.erb` to the end of the filename.
69
+
70
+ You can also access any custom values set in your local configuration file.
71
+
72
+ ```erb
73
+ <%# ~/.new/templates/foo_template/foo.txt.erb %>
74
+
75
+ <%= license %>
76
+ <%= developer.name %>
77
+ <%= developer.email %>
78
+ <%= type %>
79
+ <%= project_name %>
80
+ <%= foo %>
81
+ <%= tasks.bar_task.baz %>
82
+ ```
83
+
84
+ You can also interpolate directory and filenames using the syntax `foo_[DEVELOPER.NAME].txt`
85
+
86
+ _Note using the dot notation to access nested attributes._
87
+
88
+ #### Custom Tasks
89
+ * The directory name will be used for the task name
90
+ * A `.rb` file must be included in the directory with the same name
91
+ * The `.rb` file must contain a class of `New::Task::FooTask` and inherit from `New::Task`
92
+ * The `.rb` file must have a standard ruby `run` method that will run when a project is released.
93
+ * A Task can have an `OPTIONS` constant with default options needed for the task to run. These can be further customized in the project or local configuration `.new` file
94
+
95
+ ```ruby
96
+ # ~/.new/tasks/foo_task/foo_task.rb
97
+
98
+ class New::Task::FooTask < New::Test
99
+ OPTION = {
100
+ foo: 'bar'
101
+ }
102
+
103
+ def run
104
+ # do stuff here
105
+ # access task options from the `options` object
106
+ # access all project options from the `project_options` object
107
+ end
108
+ end
109
+ ```
110
+
111
+ #### TODO
112
+ * optional scripts when creating a template
113
+ * write templates
114
+ * write tasks
115
+
116
+ #### Contributing
117
+ 1. Fork it ( http://github.com/brewster1134/new/fork )
118
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
119
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
120
+ 4. Push to the branch (`git push origin my-new-feature`)
121
+ 5. Create new Pull Request
data/bin/new ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'new'
5
+
6
+ New::Cli.start ARGV
data/lib/new/cli.rb ADDED
@@ -0,0 +1,94 @@
1
+ require 'thor'
2
+ require 'yaml'
3
+
4
+ class New::Cli < Thor
5
+ desc '[TEMPLATE] [NAME]', "Create a new project with a given template (#{New.templates.join(' ')})"
6
+ # option :name, required: true
7
+ def method_missing method, *args
8
+ if New.templates.include? method.to_sym
9
+ # Split args that look like options (i.e start with - or --) into a separate array
10
+ positional_args, opts = Thor::Options.split args
11
+
12
+ # extract name from args
13
+ name = positional_args[0]
14
+ raise Thor::RequiredArgumentMissingError unless name
15
+
16
+ # Add all options here
17
+ # Make sure to include required options up above as well so they show in the help menu
18
+ parser = Thor::Options.new(
19
+ # name: Thor::Option.new(:name, required: true, type: :string)
20
+ )
21
+
22
+ # The options hash is frozen in #initialize so you need to merge and re-assign
23
+ self.options = options.merge(parser.parse(opts)).freeze
24
+
25
+ # Dispatch the command
26
+ project method, name
27
+ else
28
+ super
29
+ end
30
+ end
31
+
32
+ desc 'init', 'Set up your home directory folder for storing custom templates and default configuration'
33
+ def init
34
+ if Dir.exists? New::CUSTOM_DIR
35
+ New.say 'Home folder already exists.', type: :warn
36
+ else
37
+ # create folder
38
+ New.say 'Creating home folder.', type: :success
39
+ FileUtils.mkdir_p New::CUSTOM_DIR
40
+ FileUtils.mkdir_p File.join(New::CUSTOM_DIR, New::TASKS_DIR_NAME)
41
+ FileUtils.mkdir_p File.join(New::CUSTOM_DIR, New::TEMPLATES_DIR_NAME)
42
+
43
+ # create config file
44
+ New.say 'Creating default configuration file.', type: :success
45
+ File.open File.join(New::CUSTOM_DIR, New::CONFIG_FILE), 'w' do |f|
46
+ f.write New::Template::CUSTOM_CONFIG_TEMPLATE.to_yaml
47
+ end
48
+
49
+ New.say "Edit #{File.join(New::CUSTOM_DIR, New::CONFIG_FILE)} with your custom configuration details.", type: :warn
50
+ end
51
+ end
52
+
53
+ desc 'release', 'Release your new code (Run from within a project directory!)'
54
+ def release
55
+ project_config_file = File.join(Dir.pwd, New::CONFIG_FILE)
56
+ raise unless File.exists? project_config_file
57
+
58
+ # get project config file
59
+ project_config = YAML.load(File.open(project_config_file)).deep_symbolize_keys!
60
+
61
+ # extract tasks from configuration
62
+ tasks = (project_config[:tasks] || {}).keys.map(&:to_sym)
63
+
64
+ tasks.each do |task|
65
+ # require custom task and initialize it
66
+ begin
67
+ if New.custom_tasks.include? task
68
+ require "#{New::CUSTOM_DIR}/#{New::TASKS_DIR_NAME}/#{task}/#{task}"
69
+ else
70
+ require "#{New::DEFAULT_DIR}/#{New::TASKS_DIR_NAME}/#{task}/#{task}"
71
+ end
72
+ rescue LoadError
73
+ New.say "No task '#{task}' found!", type: :fail
74
+ next
75
+ end
76
+ "New::Task::#{task.to_s.classify}".constantize.new project_config
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def project template, name
83
+ if Dir.exists? File.join(Dir.pwd, name)
84
+ New.say "A project named #{name} already exists...", type: :warn
85
+ New.say " Overwrite it? [Yn]", type: :warn
86
+ exit if STDIN.gets.chomp! != 'Y'
87
+
88
+ # Delete existing project
89
+ FileUtils.rm_rf File.join(Dir.pwd, name)
90
+ end
91
+
92
+ New::Project.new template, name
93
+ end
94
+ end
data/lib/new/core.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'active_support/core_ext/hash/deep_merge'
2
+ require 'active_support/core_ext/hash/keys'
3
+ require 'active_support/core_ext/object/deep_dup'
4
+ require 'active_support/core_ext/string/inflections'
5
+ require 'colorize'
6
+ require 'date'
data/lib/new/dsl.rb ADDED
@@ -0,0 +1,42 @@
1
+ module New::Dsl
2
+ # Replacement for `puts` that accepts various stylistic arguments
3
+ # https://github.com/fazibear/colorize/blob/master/lib/colorize.rb
4
+ #
5
+ # justify: => [center|ljust|rjust] The type of justification to use
6
+ # padding: => [integer] The maximum string size to justify text in
7
+ # color: => [integer] See link above for supported colors
8
+ # bgcolor: => [integer] See link above for supported colors
9
+ # type: => [symbol] Preset colors for [:fail, :success, :warn]
10
+ #
11
+ def say text = '', args = {}
12
+ # Justify options
13
+ if args[:justify] && args[:padding]
14
+ text = text.send args[:justify], args[:padding]
15
+ end
16
+
17
+ # Color text
18
+ text = text.colorize(color: args[:color]) if args[:color]
19
+
20
+ # Color background
21
+ text = text.colorize(background: args[:bgcolor]) if args[:bgcolor]
22
+
23
+ # Type options
24
+ # process last due to the addition of special color codes
25
+ text = case args[:type]
26
+ when :fail
27
+ text.red
28
+ when :success
29
+ text.green
30
+ when :warn
31
+ text.yellow
32
+ else
33
+ text
34
+ end
35
+
36
+ if args[:indent]
37
+ text = (' ' * args[:indent]) + text
38
+ end
39
+
40
+ puts text
41
+ end
42
+ end
@@ -0,0 +1,100 @@
1
+ require 'erb'
2
+ require 'recursive-open-struct'
3
+
4
+ module New::Interpolate
5
+ # regex to match capital underscored template options names ie [PROJECT_NAME]
6
+ FILENAME_RENAME_MATCH = /\[([A-Z_.]+)\]/
7
+
8
+ # Convienance method for processing everything
9
+ #
10
+ def interpolate src_path, options
11
+ @src_path = src_path
12
+ @options = options
13
+
14
+ copy_to_tmp
15
+ process_paths
16
+ process_files
17
+ end
18
+
19
+ def dir; @dest_path; end
20
+
21
+ # Convert options to OpenStruct so we can use dot notation in the templates
22
+ #
23
+ def dot_options
24
+ @dot_options ||= RecursiveOpenStruct.new(@options)
25
+ end
26
+
27
+ private
28
+
29
+ # Allow templates to call option values directly
30
+ #
31
+ def method_missing method
32
+ dot_options.send(method.to_sym) || super
33
+ end
34
+
35
+ def copy_to_tmp
36
+ # Create a unique temporary path to store the processed files
37
+ @dest_path = File.join(New::TEMP_DIR, Time.now.to_i.to_s)
38
+
39
+ # Create a directory if an individual file is being processed
40
+ FileUtils.mkdir_p @dest_path if File.file? @src_path
41
+
42
+ # Copy to tmp
43
+ FileUtils.cp_r @src_path, @dest_path
44
+ end
45
+
46
+ # Collect files with a matching value to interpolate
47
+ #
48
+ def process_paths
49
+ get_path = -> type do
50
+ Dir.glob(File.join(@dest_path, '**/*')).select do |e|
51
+ File.send("#{type}?".to_sym, e) && e =~ FILENAME_RENAME_MATCH
52
+ end
53
+ end
54
+
55
+ # rename directories first
56
+ get_path[:directory].each{ |dir| process_path dir }
57
+ get_path[:file].each{ |file| process_path file }
58
+ end
59
+
60
+ # Interpolate filenames with template options
61
+ #
62
+ def process_path path
63
+ new_path = path.gsub FILENAME_RENAME_MATCH do
64
+ # Extract interpolated values into symbols
65
+ methods = $1.downcase.split('.').map(&:to_sym)
66
+
67
+ # Call each method on options
68
+ methods.inject(dot_options){ |options, method| options.send(method.to_sym) }
69
+ end
70
+
71
+ if File.file? path
72
+ File.rename path, new_path
73
+ else
74
+ FileUtils.mv path, new_path
75
+ end
76
+ end
77
+
78
+ # Collect files with an .erb extension to interpolate
79
+ #
80
+ def process_files
81
+ Dir.glob(File.join(@dest_path, '**/*.erb'), File::FNM_DOTMATCH).each do |file|
82
+ process_file file
83
+ end
84
+ end
85
+
86
+ # Interpolate erb template data
87
+ #
88
+ def process_file file
89
+ # Process the erb file
90
+ processed_file = ERB.new(File.read(file)).result(binding)
91
+
92
+ # Overwrite the original file with the processed file
93
+ File.open file, 'w' do |f|
94
+ f.write processed_file
95
+ end
96
+
97
+ # Remove the .erb from the file name
98
+ File.rename file, file.chomp('.erb')
99
+ end
100
+ end
@@ -0,0 +1,34 @@
1
+ class New::Project
2
+ include New::Version
3
+
4
+ # Create all variables and run new project creation methods
5
+ #
6
+ def initialize template, name
7
+ @project_dir = File.join(Dir.pwd, name.to_s) # the newly created project directory
8
+ @template = New::Template.new template, name
9
+
10
+ copy_template
11
+ create_config_file
12
+ end
13
+
14
+ private
15
+
16
+ # Create the new project by copying the template directory
17
+ #
18
+ def copy_template
19
+ FileUtils.cp_r @template.dir, @project_dir
20
+
21
+ # cleanup tmp
22
+ FileUtils.rm_rf @template.dir
23
+ end
24
+
25
+ # Create the .new configuration file in the new project
26
+ #
27
+ def create_config_file
28
+ new_config = File.join(@project_dir, New::CONFIG_FILE)
29
+ File.open new_config, 'w' do |f|
30
+ yaml_options = @template.options.deep_dup.deep_stringify_keys!.to_yaml
31
+ f.write(yaml_options)
32
+ end
33
+ end
34
+ end
data/lib/new/task.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'yaml'
2
+
3
+ class New::Task
4
+ def self.inherited task_class
5
+ task_class.name = caller.first[/[a-z_]+?(?=\.rb)/].to_sym
6
+ end
7
+
8
+ def initialize project_config
9
+ @project_config = project_config
10
+ run
11
+ end
12
+
13
+ def self.name= name
14
+ @name = name
15
+ end
16
+ def self.name; @name; end
17
+ def name; self.class.name.to_sym; end
18
+
19
+ # Return ALL available options
20
+ #
21
+ def project_options
22
+ custom_options = New.custom_config
23
+ project_options = @project_config
24
+
25
+ all_options = custom_options.deep_merge(project_options)
26
+
27
+ # Groom tasks (prevent tasks from the custom config from polluting the project config)
28
+ all_options[:tasks].each_key do |task|
29
+ all_options[:tasks].delete(task) unless project_options[:tasks].has_key?(task)
30
+ end
31
+
32
+ @project_options ||= all_options
33
+ end
34
+
35
+ # Return only the options for the given task
36
+ #
37
+ def options
38
+ default_options = self.class::OPTIONS rescue {}
39
+ @options ||= default_options.deep_merge(project_options[:tasks][name])
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ require 'yaml'
2
+
3
+ class New::Template
4
+ include New::Interpolate
5
+
6
+ # The foundation for new template configuration files
7
+ #
8
+ CUSTOM_CONFIG_TEMPLATE = {
9
+ license: '[LICENSE]',
10
+ version: '[VERSION]',
11
+ developer: {
12
+ name: '[NAME]',
13
+ email: '[EMAIL]'
14
+ }
15
+ }
16
+
17
+ def initialize type, name
18
+ @type = type
19
+ @name = name
20
+
21
+ interpolate template_dir, options
22
+ end
23
+
24
+ # Create the options object
25
+ #
26
+ def options
27
+ # merge options together
28
+ CUSTOM_CONFIG_TEMPLATE.clone
29
+ .deep_merge!(template_config)
30
+ .deep_merge!(New.custom_config)
31
+ .deep_merge!({
32
+ project_name: @name,
33
+ type: @type.to_s
34
+ })
35
+ end
36
+
37
+ private
38
+
39
+ # Get the template directory to copy from
40
+ #
41
+ def template_dir
42
+ @template_dir ||= if New.custom_templates.include? @type
43
+ @custom = true
44
+ File.join(New::CUSTOM_DIR, New::TEMPLATES_DIR_NAME, @type.to_s)
45
+ else
46
+ File.join(New::DEFAULT_DIR, New::TEMPLATES_DIR_NAME, @type.to_s)
47
+ end
48
+ end
49
+
50
+ # Get the configuration for the template
51
+ #
52
+ def template_config
53
+ return @template_config if @template_config
54
+
55
+ @template_config = YAML.load(File.open(File.join(template_dir, New::CONFIG_FILE))).deep_symbolize_keys! rescue {}
56
+ if @custom
57
+ @template_config.merge!({
58
+ custom: true
59
+ })
60
+ end
61
+
62
+ @template_config
63
+ end
64
+ end