noe 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/CHANGELOG.md +27 -0
  2. data/Gemfile +2 -0
  3. data/LICENCE.md +22 -0
  4. data/README.md +111 -45
  5. data/Rakefile +18 -20
  6. data/bin/noe +1 -1
  7. data/lib/noe.rb +7 -21
  8. data/lib/noe/commons.rb +23 -0
  9. data/lib/noe/config.yaml +2 -2
  10. data/lib/noe/ext/array.rb +18 -0
  11. data/lib/noe/ext/hash.rb +48 -0
  12. data/lib/noe/go.rb +158 -40
  13. data/lib/noe/install.rb +13 -7
  14. data/lib/noe/list.rb +34 -10
  15. data/lib/noe/loader.rb +67 -0
  16. data/lib/noe/main.rb +15 -15
  17. data/lib/noe/prepare.rb +121 -0
  18. data/lib/noe/show_spec.rb +45 -0
  19. data/lib/noe/template.rb +84 -4
  20. data/noe.gemspec +186 -30
  21. data/spec/ext/hash/methodize_spec.rb +30 -0
  22. data/spec/noe_spec.rb +4 -0
  23. data/spec/spec_helper.rb +0 -2
  24. data/spec/template/entry/infer_wlang_dialect_spec.rb +31 -0
  25. data/tasks/gem.rake +44 -0
  26. data/tasks/spec_test.rake +61 -0
  27. data/tasks/unit_test.rake +56 -0
  28. data/tasks/yard.rake +36 -0
  29. data/templates/ruby/CHANGELOG.md +9 -1
  30. data/templates/ruby/README.md +47 -10
  31. data/templates/ruby/noespec.yaml +195 -26
  32. data/templates/ruby/short.yaml +33 -0
  33. data/templates/ruby/src/Gemfile +2 -0
  34. data/templates/ruby/src/LICENCE.md +22 -0
  35. data/templates/ruby/src/Manifest.txt +11 -0
  36. data/templates/ruby/src/README.md +6 -1
  37. data/templates/ruby/src/Rakefile +16 -36
  38. data/templates/ruby/src/__lower__.gemspec +178 -23
  39. data/templates/ruby/src/lib/__lower__.rb +5 -2
  40. data/templates/ruby/src/lib/__lower__/loader.rb +65 -0
  41. data/templates/ruby/src/spec/spec_helper.rb +0 -2
  42. data/templates/ruby/src/tasks/gem.rake +44 -0
  43. data/templates/ruby/src/tasks/spec_test.rake +61 -0
  44. data/templates/ruby/src/tasks/unit_test.rake +56 -0
  45. data/templates/ruby/src/tasks/yard.rake +36 -0
  46. metadata +349 -79
  47. data/LICENCE.txt +0 -20
  48. data/lib/noe/create.rb +0 -77
  49. data/templates/ruby/src/LICENCE.txt +0 -20
@@ -1,3 +1,30 @@
1
+ # 1.1.0 / FIX ME
2
+
3
+ * Template specification/instantiation enhancements
4
+
5
+ * Introduced a manifest entry in template-info
6
+ * Introduced an auto detection of the wlang dialect to use based on file extensions.
7
+ The dialect may also be specified under template-info/manifest/a_file_name/wlang-dialect
8
+ entry
9
+ * All hashes found in .noespec variables are methodized before being passed to template
10
+ * Templates are now instantiated on a specification being the result of YAML merging
11
+ between the user's .noespec file and the template noespec.yaml file.
12
+
13
+ * Command enhancements
14
+
15
+ * Removed 'noe create', which is replaced by an extended version named 'noe prepare'
16
+ * 'noe go' now supports --interactive and --safe-override additional options to control conflict strategy
17
+ * Added a 'noe show-spec' command that shows the complete specification used by 'noe go'
18
+ See 'noe help show-spec' for details
19
+ * 'noe COMMAND --help' is now an alias for 'noe help COMMAND'
20
+ * A wlang backtrace is now displayed when an instantation error occurs on 'noe go'
21
+
22
+ * Other changes
23
+
24
+ * Bumped wlang version to 0.10.0 to gain inclusion features on wlang/ruby and wlang/yaml
25
+ * Ruby skeleton largely enhanced (see it's own CHANGELOG.md)
26
+ * Noe code is now managed by Noe itself
27
+
1
28
  # 1.0.0 / 2011-01-10
2
29
 
3
30
  * Enhancements
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'http://rubygems.org'
2
+ gemspec :name => "noe"
@@ -0,0 +1,22 @@
1
+ # Licence
2
+
3
+ Copyright (c) 2011 - Bernard Lambeau
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 CHANGED
@@ -1,23 +1,14 @@
1
1
  # Noe - A simple and extensible project generator
2
2
 
3
- Noe helps development by providing support for project templates and instantiation.
3
+ Noe is a tool that generates projects from predefined skeletons (aka project/application
4
+ templates). Skeletons are designed for building specific products (a ruby library, a static
5
+ or dynamic web site, ...). Noe instantiates them and helps you maintaining your product
6
+ via meta-information provided by a .noespec yaml file.
4
7
 
5
- ## Why?
6
-
7
- I'm pretty sure I have seen announcements for similar projects on ruby-lang in the past,
8
- but I could not find them anymore... so I started mine. Please let me know alternatives
9
- and I'll add them below:
10
-
11
- See also:
12
-
13
- * ...
14
-
15
- Other reasons:
16
-
17
- * Noe is agnostic: it does not make any assumption about project semantics
18
- * Noe does not restrict itself to generation of ruby projects
19
- * Noe is not required at runtime: once your project is generated you're done
20
- * I don't like magic
8
+ Noe comes bundled with a skeleton for creating and maintaining a ruby gem. This skeleton
9
+ is written and maintained to follow ruby best practices and may also be tuned for your own
10
+ needs. Read more about it and related projects as well as the underlying philosophy in the
11
+ sections below.
21
12
 
22
13
  ## Getting started
23
14
 
@@ -26,19 +17,11 @@ Other reasons:
26
17
  [noe help install]
27
18
  noe install
28
19
 
29
- Have a loot at ~/.noerc and ~/.noe for configuration and a default ruby
30
- template.
31
-
32
- ## Usage summary
20
+ Have a loot at ~/.noerc and ~/.noe for configuration and a default ruby template. To
21
+ instantiate a ruby project simply execute the following commands in turn:
33
22
 
34
- Maintain your templates under ~/.noe (or what you provided at installation time). Have a
35
- look at github to find xxx.noe projects to find well-designed/documented templates for
36
- specific needs.
37
-
38
- To create a fresh new project:
39
-
40
- # Given a template xxx under ~/.noe/xxx
41
- noe create --template=xxx foo
23
+ # Given a template ruby under ~/.noe/ruby, install by default
24
+ noe prepare --template=ruby foo
42
25
  cd foo
43
26
 
44
27
  # Edit the template configuration foo/foo.noespec
@@ -47,10 +30,92 @@ To create a fresh new project:
47
30
  # Launch template instantiation
48
31
  noe go
49
32
 
50
- That's it! But also have a look at 'noe help create' and 'not help go' for additional
33
+ That's it! But also have a look at 'noe help prepare' and 'not help go' for additional
51
34
  options.
52
35
 
53
- ## About templates
36
+ ## Philosophy
37
+
38
+ Noe is designed to follow a certain number of good principles and helps you following
39
+ them as well.
40
+
41
+ ### Separation of concerns
42
+
43
+ Noe maintains a strong separation of concerns. In particular one has to make the distinction
44
+ between a) Noe itself, b) a skeleton and c) an instantiated product. This fact has two
45
+ main consequences:
46
+
47
+ * Noe itself **is not dedicated to specific products** (like a ruby library). Even if Noe
48
+ comes bundled with a default skeleton for ruby projects, writing skeletons for something
49
+ else should not be a problem. In other words, Noe itself is agnostic: the semantics of
50
+ generated products is the secret of the skeleton, under the responsibility of it's
51
+ maintainer.
52
+
53
+ * Noe **should not be a runtime dependency** of the product. Good skeletons maintain this
54
+ separation. As an example the default ruby skeleton is strictly independent of Noe itself.
55
+ Principles discussed below explain why this is important.
56
+
57
+ ### Master the tools YOU use
58
+
59
+ The separation of concerns described previously also drives what you have to learn and what
60
+ tools you have to master:
61
+
62
+ * As an ordinary Noe user (vs. skeleton maintainer) and because Noe itself (unlike skeletons
63
+ is project agnostic, you only have to know **basic Noe commands** (see 'noe --help') and
64
+ should never have to study Noe's API and internals. In contrast, you have to **master the
65
+ tools and best practices of your product's ecosystem**. A good skeleton should help you
66
+ along this task. As an example, the default ruby skeleton is fully documented to help you
67
+ gaining understanding of ***rake*, *spec*, *yard*, *bundler*** and so on but **not noe
68
+ itself**.
69
+
70
+ * This explains why Noe itself is not a runtime dependency. Using a particular skeleton
71
+ already means learning a lot, at least in the long run (see the section about Magic below).
72
+ Noe avoids interfering with generated products to avoid making the learning curve even
73
+ worse.
74
+
75
+ * Being a skeleton creator/maintainer is another story of course. To write a skeleton you'll
76
+ also have to learn **Noe's API and internals**. To write a good/reusable one, you'll
77
+ certainly have to **master the full ecosystem and best practices of the targetted product**,
78
+ which is a good opportunity for learning and sharing it!
79
+
80
+ ### Magic Only If Flexible
81
+
82
+ "Don't Repeat Yourself" and "Convention over Configuration" are certainly good principles.
83
+ However tuning, configuration and options exist, are useful and should certainly not be
84
+ hidden to the user. Instead configuration and options should come with default values,
85
+ and should be fully documented. Providing magic is great if there is a user-centric way
86
+ (in contrast to a developer one) of understanding and controlling the magic and underlying
87
+ assumptions.
88
+
89
+ As an example, the default ruby template comes with some magic: you can create a project
90
+ and immediately invoke 'rake test', 'rake yard', ... and not investigating further. You
91
+ can also have a look at the _tasks_ folder to understand and control the rake tasks that
92
+ your project will use... In fact, you **must** investigate: the generated product is yours,
93
+ not mine and YOU have to master your build chain!
94
+
95
+ ## Ruby skeleton and Related projects
96
+
97
+ Noe is inspired by existing projects, mostly from the ruby community. In particular, the
98
+ default ruby template has been heavily influenced by the projects below as well as feedback
99
+ of their authors:
100
+
101
+ * [hoe](http://seattlerb.rubyforge.org/hoe/), Ryan Davis and Eric Hodel
102
+ * [echoe](https://github.com/fauna/echoe), Evan Weaver
103
+ * [bones](https://github.com/TwP/bones), Tim Pease
104
+
105
+ These projects help you generating and maintaining ruby projects (generally gem libraries,
106
+ in fact). All provide powerful tools that supports you along the different steps of your
107
+ ruby software lifecycle (creating, testing, releasing, announcing, and so on.). They mostly
108
+ differ in the way you can tune/configure the generated project for specific needs.
109
+
110
+ These projects differ from the Ruby skeleton proposed by Noe in that they use a control
111
+ approach (rake tasks installed in your project via a development/runtime dependency) while
112
+ Noe uses a generative approach (the generated ruby project and rake tasks do not depend on
113
+ Noe at all).
114
+
115
+ You'll find more information about the Noe's ruby skeleton in it's own
116
+ [README](https://github.com/blambeau/noe/blob/master/templates/ruby/README.md).
117
+
118
+ ## Short guide for template maintainers
54
119
 
55
120
  Under ~/.noe, a valid template folder (say xxx) has the following structure
56
121
 
@@ -63,16 +128,17 @@ Under ~/.noe, a valid template folder (say xxx) has the following structure
63
128
 
64
129
  ### noespec.yaml
65
130
 
66
- The noespec.yaml file of a template is used to formally describe the template. When a project
67
- (say foo) is created (see 'noe create') using a template (say ruby) the file
68
- ~/.noe/ruby/noespec.yaml is used to generate foo/foo.noespec. The later is then used by
69
- 'noe go' to instantiate the project.
131
+ The noespec.yaml file of a template is used to formally describe the template. When a
132
+ project (say foo) is created (see 'noe prepare') using a template (say ruby) the file
133
+ ~/.noe/ruby/noespec.yaml is used to generate foo/foo.noespec. The later is then used
134
+ by 'noe go' to instantiate the project.
70
135
 
71
136
  The noespec.yaml file should ressemble something like this:
72
137
 
73
138
  # DO NOT TOUCH 'name' entry and specify the other
74
139
  template-info:
75
140
  name: !{template_name}
141
+ summary: ...
76
142
  description: ...
77
143
  version: ...
78
144
  author: ...
@@ -90,16 +156,16 @@ Have a look at ~/.noe/ruby/noespec.yaml and ~/.noe/ruby/src for an example.
90
156
 
91
157
  ### Instantiation process
92
158
 
93
- The instantiation process is really simple. Given the variables described in the noespec.yaml
94
- file (for which values are specified in your .noespec file) templates can use the following
95
- meta-constructions:
159
+ The instantiation process is really simple. Given the variables described in the
160
+ noespec.yaml file (for which values are specified in your .noespec file) templates
161
+ can use the following meta-constructions:
96
162
 
97
- * Template files and directories containing `__variable__` in their name are automatically
163
+ * Template files and directories containing `__variable__` in their name are automatically
98
164
  renamed (`__variable__` is replaced by the corresponding value).
99
- * All template files are instantiated by [wlang](https://github.com/blambeau/wlang). You don't
100
- have to know wlang in depth. You simply have to know that `!{ruby_expression}` in a file is
101
- replaced by the expression evaluation. Variables are automatically in scope of such expressions,
102
- so that `!{variable}` is replaced by its value.
165
+ * All template files are instantiated by [wlang](https://github.com/blambeau/wlang). You
166
+ don't have to know wlang in depth. You simply have to know that `!{ruby_expression}` in
167
+ a file is replaced by the expression evaluation. Variables are automatically in scope
168
+ of such expressions, so that `!{variable}` is replaced by its value.
103
169
 
104
170
  ## Contributing
105
171
 
@@ -111,7 +177,7 @@ Fork Noe on github! I'm particularly interested in the following enhancements:
111
177
  * Add support for multi-generated files from arrays in .noespec files
112
178
  * ...
113
179
 
114
- If you think that your template is worth considering for (ruby, rails, js, latex, or anything
115
- else) please let me known and I'll add it to the list below.
180
+ If you think that your template is worth considering for (ruby, rails, js, latex, or
181
+ anything else) please let me known and I'll add it to the list below.
116
182
 
117
183
  * ...
data/Rakefile CHANGED
@@ -1,24 +1,22 @@
1
- require "rake/gempackagetask"
2
- require "rspec/core/rake_task"
3
- require "yard"
4
-
5
- # We run tests by default
6
- task :default => :spec
7
-
8
- desc "Run all examples"
9
- RSpec::Core::RakeTask.new(:spec) do |t|
10
- t.rspec_opts = %w[--color]
11
- t.verbose = false
1
+ begin
2
+ gem "bundler", "~> 1.0"
3
+ require "bundler/setup"
4
+ rescue LoadError
5
+ abort "This project requires bundler, try 'gem install bundler'"
12
6
  end
13
7
 
14
- # About yard documentation
15
- YARD::Rake::YardocTask.new do |t|
16
- t.files = ['lib/**/*.rb']
17
- t.options = ['--output-dir', 'doc/api', '-', "README.md", "CHANGELOG.md"]
18
- end
8
+ # Dynamically load the gem spec
9
+ $gemspec_file = File.expand_path('../noe.gemspec', __FILE__)
10
+ $gemspec = Kernel.eval(File.read($gemspec_file))
11
+
12
+ # We run tests by default
13
+ task :default => :test
19
14
 
20
- desc "Create the .gem package"
21
- $spec = Kernel.eval(File.read(File.expand_path('../noe.gemspec', __FILE__)))
22
- Rake::GemPackageTask.new($spec) do |pkg|
23
- pkg.need_tar = true
15
+ #
16
+ # Install all tasks found in tasks folder
17
+ #
18
+ # See .rake files there for complete documentation.
19
+ #
20
+ Dir["tasks/*.rake"].each do |taskfile|
21
+ instance_eval File.read(taskfile), taskfile
24
22
  end
data/bin/noe CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby -rubygems
2
2
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
3
  require 'noe'
4
4
  Noe::Main.run(ARGV)
data/lib/noe.rb CHANGED
@@ -1,39 +1,25 @@
1
1
  module Noe
2
2
 
3
3
  # Noe's version
4
- VERSION = "1.0.0".freeze
5
-
6
- # Requires some gem
7
- def self.require(gem_name, version = nil, retried = false)
8
- begin
9
- Kernel.require gem_name
10
- rescue LoadError
11
- if retried
12
- raise
13
- else
14
- retried = true
15
- require 'rubygems'
16
- gem gem_name, version
17
- retry
18
- end
19
- end
20
- end
4
+ VERSION = "1.1.0".freeze
21
5
 
22
6
  class Error < StandardError; end
23
7
 
24
8
  end # module Noe
25
-
26
- Noe.require('quickl', ">= 0.2.0")
27
- Noe.require('wlang', ">= 0.9")
9
+ require 'noe/loader'
28
10
  require 'yaml'
29
11
  require 'fileutils'
12
+ require 'noe/ext/array'
13
+ require 'noe/ext/hash'
30
14
  require 'noe/config'
31
15
  require 'noe/template'
16
+
32
17
  require 'noe/main'
33
18
  require 'noe/commons'
34
19
  require 'noe/install'
35
20
  require 'noe/help'
36
21
  require 'noe/list'
37
- require 'noe/create'
22
+ require 'noe/prepare'
38
23
  require 'noe/go'
24
+ require 'noe/show_spec'
39
25
 
@@ -1,6 +1,16 @@
1
1
  module Noe
2
2
  module Commons
3
3
 
4
+ # Install options
5
+ def self.add_common_options(opt)
6
+ opt.on_tail("--version", "Show version") do
7
+ raise Quickl::Exit, "#{File.basename($0 || 'noe')} #{Noe::VERSION} (c) 2011, Bernard Lambeau"
8
+ end
9
+ opt.on_tail('--help', "Show detailed help") do
10
+ raise Quickl::Help
11
+ end
12
+ end
13
+
4
14
  # Returns configuration to use
5
15
  def config
6
16
  requester.config
@@ -13,6 +23,19 @@ module Noe
13
23
  def template(name = config.default)
14
24
  Template.new(File.join(templates_dir, name))
15
25
  end
26
+
27
+ def find_noespec_file(args)
28
+ # Find spec file
29
+ spec_file = if args.size == 1
30
+ valid_read_file!(args.first)
31
+ else
32
+ spec_files = Dir['*.noespec']
33
+ if spec_files.size > 1
34
+ raise Noe::Error, "Ambiguous request, multiple specs: #{spec_files.join(', ')}"
35
+ end
36
+ spec_files.first
37
+ end
38
+ end
16
39
 
17
40
  end # module Commons
18
41
  end # module Noe
@@ -22,8 +22,8 @@ templates-dir:
22
22
 
23
23
  #
24
24
  # Name of the default template that you want to use. Commands
25
- # that need a template (see 'noe help create', for example) use this
26
- # by default, and allow overriding this via a --template=NAME option.
25
+ # that need a template (see 'noe help prepare', for example) use this
26
+ # by default, and allow overriding it via a --template=NAME option.
27
27
  #
28
28
  default:
29
29
  ruby
@@ -0,0 +1,18 @@
1
+ class Array
2
+
3
+ def methodize_hashes!(recursive = true)
4
+ self.each do |val|
5
+ case val
6
+ when Hash
7
+ val.methodize!(recursive)
8
+ when Array
9
+ val.methodize_hashes!(recursive)
10
+ end
11
+ end
12
+ end
13
+
14
+ def noe_merge(right)
15
+ (self + right).uniq
16
+ end
17
+
18
+ end # class Array
@@ -0,0 +1,48 @@
1
+ class Hash
2
+
3
+ # Methodize this hash
4
+ def methodize!(recursive = true)
5
+ self.extend(Methodize)
6
+ if recursive
7
+ self.values.each do |val|
8
+ case val
9
+ when Hash
10
+ val.methodize!(recursive)
11
+ when Array
12
+ val.methodize_hashes!(recursive)
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ # Makes a fully recursive merge
19
+ def noe_merge(right)
20
+ self.merge(right) do |key,oldval,newval|
21
+ if oldval.nil?
22
+ newval
23
+ elsif oldval.class != newval.class
24
+ raise Noe::Error, "Conflict on #{key} has to be resolved manually, sorry.\n"\
25
+ "#{oldval} (#{oldval.class}) vs. #{newval} (#{newval.class})"
26
+ elsif oldval.respond_to?(:noe_merge)
27
+ oldval.noe_merge(newval)
28
+ else
29
+ newval
30
+ end
31
+ end
32
+ end
33
+
34
+ module Methodize
35
+
36
+ # Allows using hash.key as a synonym for hash[:key] and
37
+ # hash['key']
38
+ def method_missing(name, *args, &block)
39
+ if args.empty? and block.nil?
40
+ self[name] || self[name.to_s]
41
+ else
42
+ super(name, *args, &block)
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ end