templater 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -0
- data/README +1 -1
- data/ROADMAP +35 -0
- data/Rakefile +5 -5
- data/lib/templater.rb +2 -1
- data/lib/templater/actions/evaluation.rb +21 -0
- data/lib/templater/cli/generator.rb +7 -7
- data/lib/templater/description.rb +13 -15
- data/lib/templater/generator.rb +19 -0
- data/spec/actions/custom_action_spec.rb +18 -0
- data/spec/actions/evaluation_spec.rb +40 -0
- data/spec/options_parser_spec.rb +4 -4
- metadata +8 -5
- data/TODO +0 -3
data/LICENSE
CHANGED
data/README
CHANGED
@@ -68,7 +68,7 @@ This is how to create a very simple system for generating things:
|
|
68
68
|
|
69
69
|
The generator classes override the source_root method to specify where templates will be located. All subclasses of Templater::Generator that have any actions must do this. The +template+ and +file+ methods add actions to the generator. In the first case, a template that is rendered with ERB and then put in its destination location, in the other case a file that is copied. +empty_directory+ action creates empty directory under destination root.
|
70
70
|
|
71
|
-
Neither manifolds or generators actually do anything by themselves, they are just abstract
|
71
|
+
Neither manifolds or generators actually do anything by themselves, they are just abstract representations. The last line invokes the command-line-interface, which fetches the desired generator, tells it to render its templates and checks with the user if there are any problems. The generators can easily be used without the command-line-interface, so it is easy to construct an alternative interface.
|
72
72
|
|
73
73
|
== Invoking other generators
|
74
74
|
|
data/ROADMAP
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
Roadmap:
|
2
|
+
|
3
|
+
0.5:
|
4
|
+
|
5
|
+
* Custom actions (ex.: append/prepend to existing files).
|
6
|
+
|
7
|
+
0.6:
|
8
|
+
|
9
|
+
* Internals overview.
|
10
|
+
* Plugins development guide.
|
11
|
+
* Overall improvements in documentation.
|
12
|
+
|
13
|
+
0.7:
|
14
|
+
|
15
|
+
* Haml support.
|
16
|
+
|
17
|
+
0.8:
|
18
|
+
|
19
|
+
* Interactive UI.
|
20
|
+
|
21
|
+
0.9:
|
22
|
+
|
23
|
+
* Built-in generators generator.
|
24
|
+
* Executable to run the generator above.
|
25
|
+
* Clean up as much as possible before stabilization period.
|
26
|
+
|
27
|
+
1.0:
|
28
|
+
|
29
|
+
* Redundant spec coverage.
|
30
|
+
* Generators in natural languages with Treetop. We can write generators using
|
31
|
+
plain text and use Cucumber-like steps to process actions.
|
32
|
+
|
33
|
+
1.x:
|
34
|
+
|
35
|
+
* Add magic template names for files.
|
data/Rakefile
CHANGED
@@ -8,8 +8,8 @@ require File.join(File.dirname(__FILE__), 'lib', 'templater')
|
|
8
8
|
|
9
9
|
PLUGIN = "templater"
|
10
10
|
NAME = "templater"
|
11
|
-
AUTHOR = "Jonas Nicklas"
|
12
|
-
EMAIL = "jonas.nicklas@gmail.com"
|
11
|
+
AUTHOR = "Jonas Nicklas, Michael Klishin"
|
12
|
+
EMAIL = "jonas.nicklas@gmail.com, michael.s.klishin@gmail.com"
|
13
13
|
HOMEPAGE = "http://templater.rubyforge.org/"
|
14
14
|
SUMMARY = "File generation system"
|
15
15
|
|
@@ -36,7 +36,7 @@ spec = Gem::Specification.new do |s|
|
|
36
36
|
s.version = Templater::VERSION
|
37
37
|
s.platform = Gem::Platform::RUBY
|
38
38
|
s.has_rdoc = true
|
39
|
-
s.extra_rdoc_files = ["README", "LICENSE", '
|
39
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'ROADMAP']
|
40
40
|
s.summary = SUMMARY
|
41
41
|
s.description = s.summary
|
42
42
|
s.author = AUTHOR
|
@@ -44,7 +44,7 @@ spec = Gem::Specification.new do |s|
|
|
44
44
|
s.homepage = HOMEPAGE
|
45
45
|
s.require_path = 'lib'
|
46
46
|
s.autorequire = PLUGIN
|
47
|
-
s.files = %w(LICENSE README Rakefile
|
47
|
+
s.files = %w(LICENSE README Rakefile ROADMAP) + Dir.glob("{lib,spec}/**/*")
|
48
48
|
|
49
49
|
s.add_dependency "highline", ">= 1.4.0"
|
50
50
|
s.add_dependency "diff-lcs", ">= 1.1.2"
|
@@ -140,4 +140,4 @@ namespace :spec do
|
|
140
140
|
end
|
141
141
|
|
142
142
|
desc 'Default: run unit tests.'
|
143
|
-
task :default => 'spec'
|
143
|
+
task :default => 'spec'
|
data/lib/templater.rb
CHANGED
@@ -14,6 +14,7 @@ require path + 'actions/template'
|
|
14
14
|
require path + 'actions/file'
|
15
15
|
require path + 'actions/directory'
|
16
16
|
require path + 'actions/empty_directory'
|
17
|
+
require path + 'actions/evaluation'
|
17
18
|
require path + 'description'
|
18
19
|
require path + 'generator'
|
19
20
|
require path + 'manifold'
|
@@ -44,6 +45,6 @@ module Templater
|
|
44
45
|
class MalformattedArgumentError < ArgumentError #:nodoc:
|
45
46
|
end
|
46
47
|
|
47
|
-
VERSION = '0.
|
48
|
+
VERSION = '0.5.0'
|
48
49
|
|
49
50
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Templater
|
2
|
+
module Actions
|
3
|
+
class Evaluation < Action
|
4
|
+
attr_reader :generaor, :name, :options, :operation
|
5
|
+
|
6
|
+
def initialize(generator, name, options = {}, &operation)
|
7
|
+
@generator, @name = generator, name
|
8
|
+
@options = options
|
9
|
+
@operation = operation
|
10
|
+
end
|
11
|
+
|
12
|
+
def render
|
13
|
+
self.generator.instance_eval(&operation) || ''
|
14
|
+
end
|
15
|
+
|
16
|
+
def identical?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -5,11 +5,11 @@ module Templater
|
|
5
5
|
class Generator
|
6
6
|
|
7
7
|
def initialize(generator_name, generator_class, destination_root, name, version)
|
8
|
-
@generator_name
|
8
|
+
@generator_name = generator_name
|
9
9
|
@destination_root = destination_root
|
10
|
-
@generator_class
|
11
|
-
@name
|
12
|
-
@version
|
10
|
+
@generator_class = generator_class
|
11
|
+
@name = name
|
12
|
+
@version = version
|
13
13
|
end
|
14
14
|
|
15
15
|
def version
|
@@ -20,11 +20,11 @@ module Templater
|
|
20
20
|
# outputs a helpful message and quits
|
21
21
|
def help
|
22
22
|
puts "Usage: #{@name} #{@generator_name} [options] [args]"
|
23
|
-
puts
|
23
|
+
puts
|
24
24
|
puts @generator_class.desc
|
25
|
-
puts
|
25
|
+
puts
|
26
26
|
puts @options[:opts]
|
27
|
-
puts
|
27
|
+
puts
|
28
28
|
exit
|
29
29
|
end
|
30
30
|
|
@@ -1,25 +1,23 @@
|
|
1
1
|
module Templater
|
2
|
-
|
2
|
+
|
3
3
|
class Description
|
4
4
|
attr_accessor :name, :options, :block
|
5
|
-
|
5
|
+
|
6
6
|
def initialize(name, options={}, &block)
|
7
7
|
@name = name
|
8
8
|
@options = options
|
9
9
|
@block = block
|
10
|
-
end
|
10
|
+
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
class ActionDescription < Description
|
14
|
-
|
15
14
|
def compile(generator)
|
16
15
|
@block.call(generator)
|
17
16
|
end
|
18
|
-
|
19
17
|
end
|
20
|
-
|
18
|
+
|
21
19
|
class ArgumentDescription < Description
|
22
|
-
|
20
|
+
|
23
21
|
# Checks if the given argument is valid according to this description
|
24
22
|
#
|
25
23
|
# === Parameters
|
@@ -35,7 +33,7 @@ module Templater
|
|
35
33
|
elsif options[:as] == :array and not argument.is_a?(Array)
|
36
34
|
raise Templater::MalformattedArgumentError, "Expected the argument to be an Array, but was '#{argument.inspect}'"
|
37
35
|
end
|
38
|
-
|
36
|
+
|
39
37
|
invalid = catch :invalid do
|
40
38
|
block.call(argument) if block
|
41
39
|
throw :invalid, :not_invalid
|
@@ -43,7 +41,7 @@ module Templater
|
|
43
41
|
raise Templater::ArgumentError, invalid unless invalid == :not_invalid
|
44
42
|
end
|
45
43
|
end
|
46
|
-
|
44
|
+
|
47
45
|
def extract(argument)
|
48
46
|
case options[:as]
|
49
47
|
when :hash
|
@@ -60,11 +58,11 @@ module Templater
|
|
60
58
|
end
|
61
59
|
return argument
|
62
60
|
end
|
63
|
-
|
61
|
+
|
64
62
|
end
|
65
|
-
|
63
|
+
|
66
64
|
class InvocationDescription < Description
|
67
|
-
|
65
|
+
|
68
66
|
def get(generator)
|
69
67
|
klass = generator.class.manifold.generator(name)
|
70
68
|
if klass and block
|
@@ -73,6 +71,6 @@ module Templater
|
|
73
71
|
klass.new(generator.destination_root, generator.options, *generator.arguments)
|
74
72
|
end
|
75
73
|
end
|
76
|
-
|
74
|
+
|
77
75
|
end
|
78
|
-
end
|
76
|
+
end
|
data/lib/templater/generator.rb
CHANGED
@@ -308,6 +308,25 @@ module Templater
|
|
308
308
|
end
|
309
309
|
end
|
310
310
|
|
311
|
+
# Evaluates given block in the scope of generator. Useful for modification
|
312
|
+
# of existing files, for instance, Merb generators may update routing
|
313
|
+
# file or something.
|
314
|
+
#
|
315
|
+
# === Parameters
|
316
|
+
# name<Symbol>:: The name of this custom action
|
317
|
+
# options<Hash>:: Options for this custom action
|
318
|
+
# &block<Proc>:: A block to execute when the generator is instantiated
|
319
|
+
#
|
320
|
+
# === Options
|
321
|
+
# :before<Symbol>:: Name of a method to execute before this template is invoked
|
322
|
+
# :after<Symbol>:: Name of a method to execute after this template is invoked
|
323
|
+
def custom_action(name, *args, &block)
|
324
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
325
|
+
actions[name] = ActionDescription.new(name, options) do |generator|
|
326
|
+
Actions::Evaluation.new(generator, name, options, &block)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
311
330
|
# An easy way to add many templates to a generator, each item in the list is added as a
|
312
331
|
# template. The provided list can be either an array of Strings or a Here-Doc with templates
|
313
332
|
# on individual lines.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Templater::Generator, ".custom_action" do
|
4
|
+
before do
|
5
|
+
@generator_class = Templater::Generator
|
6
|
+
@generator_class.stub!(:source_root).and_return('/tmp/source')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'evaluates given block in context of generator' do
|
10
|
+
$custom_action_evaluation_result = "not called yet"
|
11
|
+
@generator_class.custom_action :update_routes_rb do
|
12
|
+
$custom_action_evaluation_result = source_root
|
13
|
+
end
|
14
|
+
|
15
|
+
@generator_class.new("/tmp/destination").render!
|
16
|
+
$custom_action_evaluation_result.should == "/tmp/source"
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Templater::Actions::Evaluation do
|
4
|
+
before do
|
5
|
+
@generator = mock('a generator')
|
6
|
+
@generator.stub!(:source_root).and_return('/tmp/source')
|
7
|
+
@generator.stub!(:destination_root).and_return('/tmp/destination')
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#render' do
|
11
|
+
it "returns result of block evaluation" do
|
12
|
+
evaluation = Templater::Actions::Evaluation.new(@generator, :monkey) do
|
13
|
+
"noop"
|
14
|
+
end
|
15
|
+
evaluation.render.should == "noop"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns empty string when block returned nil" do
|
19
|
+
evaluation = Templater::Actions::Evaluation.new(@generator, :monkey) do
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
evaluation.render.should == ""
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#identical?" do
|
27
|
+
it "always returns false" do
|
28
|
+
noop_evaluation = Templater::Actions::Evaluation.new(@generator, :monkey) do
|
29
|
+
"noop"
|
30
|
+
end
|
31
|
+
|
32
|
+
another_evaluation = Templater::Actions::Evaluation.new(@generator, :monkey) do
|
33
|
+
"noop"
|
34
|
+
end
|
35
|
+
|
36
|
+
noop_evaluation.should_not be_identical
|
37
|
+
another_evaluation.should_not be_identical
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/spec/options_parser_spec.rb
CHANGED
@@ -2,17 +2,17 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
2
2
|
require "tempfile"
|
3
3
|
|
4
4
|
describe Templater::CLI::Parser do
|
5
|
-
describe "given unknown option" do
|
5
|
+
describe "given unknown option" do
|
6
6
|
it "outputs a meaninful error message instead of just blowing up" do
|
7
7
|
lambda do
|
8
8
|
Templater::CLI::Parser.parse(["--this-option-is-unknown", "--second-unknown-option"])
|
9
9
|
end.should_not raise_error
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
it "lists unknown options" do
|
13
|
-
e = OptionParser::InvalidOption.new("--this-option-is-unknown", "--second-unknown-option")
|
13
|
+
e = OptionParser::InvalidOption.new("--this-option-is-unknown", "--second-unknown-option")
|
14
14
|
output = Templater::CLI::Parser.error_message(e)
|
15
|
-
|
15
|
+
|
16
16
|
output.should =~ /--this-option-is-unknown/
|
17
17
|
output.should =~ /--second-unknown-option/
|
18
18
|
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: templater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Jonas Nicklas
|
7
|
+
- Jonas Nicklas, Michael Klishin
|
8
8
|
autorequire: templater
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 0.9.5
|
44
44
|
version:
|
45
45
|
description: File generation system
|
46
|
-
email: jonas.nicklas@gmail.com
|
46
|
+
email: jonas.nicklas@gmail.com, michael.s.klishin@gmail.com
|
47
47
|
executables: []
|
48
48
|
|
49
49
|
extensions: []
|
@@ -51,17 +51,18 @@ extensions: []
|
|
51
51
|
extra_rdoc_files:
|
52
52
|
- README
|
53
53
|
- LICENSE
|
54
|
-
-
|
54
|
+
- ROADMAP
|
55
55
|
files:
|
56
56
|
- LICENSE
|
57
57
|
- README
|
58
58
|
- Rakefile
|
59
|
-
-
|
59
|
+
- ROADMAP
|
60
60
|
- lib/templater
|
61
61
|
- lib/templater/actions
|
62
62
|
- lib/templater/actions/action.rb
|
63
63
|
- lib/templater/actions/directory.rb
|
64
64
|
- lib/templater/actions/empty_directory.rb
|
65
|
+
- lib/templater/actions/evaluation.rb
|
65
66
|
- lib/templater/actions/file.rb
|
66
67
|
- lib/templater/actions/template.rb
|
67
68
|
- lib/templater/capture_helpers.rb
|
@@ -80,8 +81,10 @@ files:
|
|
80
81
|
- lib/templater/spec/helpers.rb
|
81
82
|
- lib/templater.rb
|
82
83
|
- spec/actions
|
84
|
+
- spec/actions/custom_action_spec.rb
|
83
85
|
- spec/actions/directory_spec.rb
|
84
86
|
- spec/actions/empty_directory_spec.rb
|
87
|
+
- spec/actions/evaluation_spec.rb
|
85
88
|
- spec/actions/file_spec.rb
|
86
89
|
- spec/actions/template_spec.rb
|
87
90
|
- spec/core_ext
|