teapot 0.6.0 → 0.7.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.
- 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
|