teapot 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +19 -47
- data/bin/teapot +66 -127
- data/lib/teapot/build.rb +4 -4
- data/lib/teapot/build/targets/application.rb +1 -1
- data/lib/teapot/build/targets/external.rb +1 -1
- data/lib/teapot/build/targets/files.rb +1 -1
- data/lib/teapot/build/targets/library.rb +3 -3
- data/lib/teapot/commands.rb +1 -1
- data/lib/teapot/configuration.rb +174 -0
- data/lib/teapot/context.rb +103 -61
- data/lib/teapot/controller.rb +56 -0
- data/lib/teapot/controller/build.rb +71 -0
- data/lib/teapot/controller/clean.rb +35 -0
- data/lib/teapot/controller/create.rb +52 -0
- data/lib/teapot/controller/fetch.rb +167 -0
- data/lib/teapot/controller/generate.rb +40 -0
- data/lib/teapot/controller/list.rb +79 -0
- data/lib/teapot/definition.rb +61 -0
- data/lib/teapot/dependency.rb +1 -1
- data/lib/teapot/generator.rb +109 -0
- data/lib/teapot/loader.rb +135 -0
- data/lib/teapot/name.rb +37 -0
- data/lib/teapot/package.rb +109 -0
- data/lib/teapot/target.rb +14 -25
- data/lib/teapot/version.rb +1 -1
- data/teapot.gemspec +6 -1
- data/test/teapot.rb +33 -0
- data/test/{test_config.rb → test_teapot.rb} +12 -9
- metadata +23 -25
- data/lib/teapot/config.rb +0 -164
@@ -0,0 +1,40 @@
|
|
1
|
+
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'teapot/controller'
|
22
|
+
|
23
|
+
module Teapot
|
24
|
+
class Controller
|
25
|
+
def generate(name, arguments)
|
26
|
+
context, configuration = load_teapot
|
27
|
+
|
28
|
+
configuration.load_all
|
29
|
+
|
30
|
+
generator = context.generators[name]
|
31
|
+
|
32
|
+
unless generator
|
33
|
+
abort "Could not find generator with name #{name.inspect}".color(:red)
|
34
|
+
end
|
35
|
+
|
36
|
+
log "Generating #{name.inspect} with arguments #{arguments.inspect}".color(:cyan)
|
37
|
+
generator.generate!(*arguments)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'teapot/controller'
|
22
|
+
|
23
|
+
module Teapot
|
24
|
+
class Controller
|
25
|
+
def list
|
26
|
+
context, configuration = load_teapot
|
27
|
+
|
28
|
+
# Should this somehow consider context.root_package?
|
29
|
+
configuration.packages.each do |package|
|
30
|
+
log "Package #{package.name} (from #{package.path}):".bright
|
31
|
+
|
32
|
+
begin
|
33
|
+
definitions = context.load(package)
|
34
|
+
|
35
|
+
definitions.each do |definition|
|
36
|
+
log "\t#{definition}"
|
37
|
+
|
38
|
+
definition.description.each_line do |line|
|
39
|
+
log "\t\t#{line.chomp}".color(:cyan)
|
40
|
+
end if definition.description
|
41
|
+
|
42
|
+
case definition
|
43
|
+
when Target
|
44
|
+
definition.dependencies.each do |name|
|
45
|
+
log "\t\t- depends on #{name.inspect}".color(:red)
|
46
|
+
end
|
47
|
+
|
48
|
+
definition.provisions.each do |(name, provision)|
|
49
|
+
if Dependency::Alias === provision
|
50
|
+
log "\t\t- provides #{name.inspect} => #{provision.dependencies.inspect}".color(:green)
|
51
|
+
else
|
52
|
+
log "\t\t- provides #{name.inspect}".color(:green)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
when Configuration
|
56
|
+
definition = definition.materialize
|
57
|
+
|
58
|
+
definition.packages.each do |package|
|
59
|
+
if package.local?
|
60
|
+
log "\t\t- links #{package.name} from #{package.options[:local]}".color(:green)
|
61
|
+
elsif package.external?
|
62
|
+
log "\t\t- clones #{package.name} from #{package.external_url(context.root)}".color(:green)
|
63
|
+
else
|
64
|
+
log "\t\t- references #{package.name} from #{package.path}".color(:green)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
definition.imports.each do |import|
|
69
|
+
log "\t\t- unmaterialised import #{import.name}".color(:red)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
rescue NonexistantTeapotError => error
|
74
|
+
log "\t#{error.message}".color(:red)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Teapot
|
22
|
+
class Definition
|
23
|
+
def initialize(context, package, name)
|
24
|
+
@context = context
|
25
|
+
@package = package
|
26
|
+
|
27
|
+
@name = name
|
28
|
+
|
29
|
+
@description = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# The context in which the definition was loaded:
|
33
|
+
attr :context
|
34
|
+
|
35
|
+
# The package in which the definition was specified:
|
36
|
+
attr :package
|
37
|
+
|
38
|
+
# The name of the definition:
|
39
|
+
attr :name
|
40
|
+
|
41
|
+
# A textual description of the definition, possibly in markdown format:
|
42
|
+
attr :description, true
|
43
|
+
|
44
|
+
def description=(text)
|
45
|
+
if text =~ /^(\t+)/
|
46
|
+
text = text.gsub(/#{$1}/, '')
|
47
|
+
end
|
48
|
+
|
49
|
+
@description = text
|
50
|
+
end
|
51
|
+
|
52
|
+
# The path that the definition is relative to:
|
53
|
+
def path
|
54
|
+
@package.path
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"<#{self.class.name} #{@name.dump}>"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/teapot/dependency.rb
CHANGED
@@ -0,0 +1,109 @@
|
|
1
|
+
# Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'teapot/definition'
|
22
|
+
require 'tempfile'
|
23
|
+
|
24
|
+
module Teapot
|
25
|
+
class Generator < Definition
|
26
|
+
def initialize(context, package, name)
|
27
|
+
super context, package, name
|
28
|
+
|
29
|
+
@generate = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate(&block)
|
33
|
+
@generate = Proc.new(&block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate!(*args)
|
37
|
+
@generate[*args]
|
38
|
+
end
|
39
|
+
|
40
|
+
def substitute(text, substitutions)
|
41
|
+
return text unless substitutions
|
42
|
+
|
43
|
+
# Use positive look behind so that the pattern is just the substitution key:
|
44
|
+
pattern = Regexp.new(substitutions.keys.map{|x| Regexp.escape(x)}.join('|'))
|
45
|
+
|
46
|
+
text.gsub(pattern) {|key| substitutions[key]}
|
47
|
+
end
|
48
|
+
|
49
|
+
def write(source, destination, substitutions = nil, mode = "a")
|
50
|
+
source_path = Pathname(path) + source
|
51
|
+
destination_path = Pathname(context.root) + destination
|
52
|
+
|
53
|
+
destination_path.dirname.mkpath
|
54
|
+
|
55
|
+
File.open(destination_path, mode) do |file|
|
56
|
+
text = File.read(source_path)
|
57
|
+
|
58
|
+
file.write substitute(text, substitutions)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def append(source, destination, substitutions = nil)
|
63
|
+
write(source, destination, substitutions, "a")
|
64
|
+
end
|
65
|
+
|
66
|
+
def merge(source, destination, substitutions = nil)
|
67
|
+
source_path = Pathname(path) + source
|
68
|
+
destination_path = Pathname(context.root) + destination
|
69
|
+
|
70
|
+
if destination_path.exist?
|
71
|
+
temporary_file = Tempfile.new(destination_path.basename.to_s)
|
72
|
+
|
73
|
+
# This functionality works, but needs improvements.
|
74
|
+
begin
|
75
|
+
# Need to ask user what to do?
|
76
|
+
write(source_path, temporary_file.path, substitutions, "w")
|
77
|
+
|
78
|
+
if temporary_file.read != destination_path.read
|
79
|
+
if `which opendiff`.chomp != ''
|
80
|
+
system("opendiff", "-merge", destination_path.to_s, destination_path.to_s, temporary_file.path)
|
81
|
+
elsif `which sdiff`.chomp != ''
|
82
|
+
system("sdiff", "-o", destination_path.to_s, destination_path.to_s, temporary_file.path)
|
83
|
+
else
|
84
|
+
abort "Can't find diff/merge tools. Please install sdiff!"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
ensure
|
88
|
+
temporary_file.unlink
|
89
|
+
end
|
90
|
+
else
|
91
|
+
write(source_path, destination_path, substitutions, "w")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def copy(source, destination, substitutions = nil)
|
96
|
+
source_path = Pathname(path) + source
|
97
|
+
|
98
|
+
if source_path.directory?
|
99
|
+
destination_path = Pathname(context.root) + destination
|
100
|
+
|
101
|
+
source_path.children(false).each do |child_path|
|
102
|
+
copy(source_path + child_path, destination_path + substitute(child_path.to_s, substitutions), substitutions)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
merge(source_path, destination, substitutions)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'teapot/target'
|
22
|
+
require 'teapot/generator'
|
23
|
+
require 'teapot/configuration'
|
24
|
+
|
25
|
+
require 'teapot/name'
|
26
|
+
require 'teapot/build'
|
27
|
+
|
28
|
+
module Teapot
|
29
|
+
LOADER_VERSION = "0.7"
|
30
|
+
MINIMUM_LOADER_VERSION = "0.7"
|
31
|
+
|
32
|
+
class IncompatibleTeapotError < StandardError
|
33
|
+
def initialize(version)
|
34
|
+
super "Version #{version} isn't compatible with current loader! Minimum supported version: #{MINIMUM_LOADER_VERSION}; Current version: #{LOADER_VERSION}."
|
35
|
+
end
|
36
|
+
|
37
|
+
attr :version
|
38
|
+
end
|
39
|
+
|
40
|
+
class NonexistantTeapotError < StandardError
|
41
|
+
def initialize(path)
|
42
|
+
super "Could not load #{path}!"
|
43
|
+
end
|
44
|
+
|
45
|
+
attr :path
|
46
|
+
end
|
47
|
+
|
48
|
+
class Loader
|
49
|
+
class Definitions < Array
|
50
|
+
def default_configuration
|
51
|
+
find{|definition| Configuration === definition}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Provides build_directory and build_external methods
|
56
|
+
include Build::Helpers
|
57
|
+
|
58
|
+
def initialize(context, package)
|
59
|
+
@context = context
|
60
|
+
@package = package
|
61
|
+
|
62
|
+
@defined = Definitions.new
|
63
|
+
@version = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
attr :context
|
67
|
+
attr :package
|
68
|
+
attr :defined
|
69
|
+
attr :version
|
70
|
+
|
71
|
+
def teapot_version(version)
|
72
|
+
version = version[0..2]
|
73
|
+
|
74
|
+
if version >= MINIMUM_LOADER_VERSION && version <= LOADER_VERSION
|
75
|
+
@version = version
|
76
|
+
else
|
77
|
+
raise IncompatibleTeapotError.new(version)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
alias required_version teapot_version
|
82
|
+
|
83
|
+
def define_target(*args)
|
84
|
+
target = Target.new(@context, @package, *args)
|
85
|
+
|
86
|
+
yield target
|
87
|
+
|
88
|
+
@defined << target
|
89
|
+
end
|
90
|
+
|
91
|
+
def define_generator(*args)
|
92
|
+
generator = Generator.new(@context, @package, *args)
|
93
|
+
|
94
|
+
yield generator
|
95
|
+
|
96
|
+
@defined << generator
|
97
|
+
end
|
98
|
+
|
99
|
+
def define_configuration(*args)
|
100
|
+
configuration = Configuration.new(@context, @package, *args)
|
101
|
+
|
102
|
+
yield configuration
|
103
|
+
|
104
|
+
configuration.top!
|
105
|
+
|
106
|
+
@defined << configuration
|
107
|
+
end
|
108
|
+
|
109
|
+
# Checks the host patterns and executes the block if they match.
|
110
|
+
def host(*args, &block)
|
111
|
+
name = @context.options[:host_platform] || RUBY_PLATFORM
|
112
|
+
|
113
|
+
if block_given?
|
114
|
+
if args.find{|arg| arg === name}
|
115
|
+
yield
|
116
|
+
end
|
117
|
+
else
|
118
|
+
name
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Load a teapot.rb file relative to the root of the @package.
|
123
|
+
def load(path)
|
124
|
+
absolute_path = @package.path + path
|
125
|
+
|
126
|
+
raise NonexistantTeapotError.new(absolute_path) unless File.exist?(absolute_path)
|
127
|
+
|
128
|
+
self.instance_eval(absolute_path.read, absolute_path.to_s)
|
129
|
+
|
130
|
+
if @version == nil
|
131
|
+
raise IncompatibleTeapotError.new("<unspecified>")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/teapot/name.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Teapot
|
22
|
+
class Name
|
23
|
+
def initialize(text)
|
24
|
+
@text = text
|
25
|
+
end
|
26
|
+
|
27
|
+
attr :text
|
28
|
+
|
29
|
+
def identifier
|
30
|
+
@identifier ||= @text.gsub(/\s+/, '')
|
31
|
+
end
|
32
|
+
|
33
|
+
def target
|
34
|
+
@target ||= @text.gsub(/\s+/, '-').downcase
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|