1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
# This isn't usable outside Puppet::Interface; don't load it alone.
class Puppet::Interface
module DocGen
def self.strip_whitespace(text)
text.gsub!(/[ \t\f]+$/, '')
# We need to identify an indent: the minimum number of whitespace
# characters at the start of any line in the text.
#
# Using split rather than each_line is because the later only takes a
# block on Ruby 1.8.5 / Centos, and we support that. --daniel 2011-05-03
indent = text.split(/\n/).map {|x| x.index(/[^\s]/) }.compact.min
if indent > 0 then
text.gsub!(/^[ \t\f]{0,#{indent}}/, '')
end
return text
end
# The documentation attributes all have some common behaviours; previously
# we open-coded them across the set of six things, but that seemed
# wasteful - especially given that they were literally the same, and had
# the same bug hidden in them.
#
# This feels a bit like overkill, but at least the common code is common
# now. --daniel 2011-04-29
def attr_doc(name, &validate)
# Now, which form of the setter do we want, validated or not?
get_arg = "value.to_s"
if validate
define_method(:"_validate_#{name}", validate)
get_arg = "_validate_#{name}(#{get_arg})"
end
# We use module_eval, which I don't like much, because we can't have an
# argument to a block with a default value in Ruby 1.8, and I don't like
# the side-effects (eg: no argument count validation) of using blocks
# without as metheds. When we are 1.9 only (hah!) you can totally
# replace this with some up-and-up define_method. --daniel 2011-04-29
module_eval(<<-EOT, __FILE__, __LINE__ + 1)
def #{name}(value = nil)
self.#{name} = value unless value.nil?
@#{name}
end
def #{name}=(value)
@#{name} = Puppet::Interface::DocGen.strip_whitespace(#{get_arg})
end
EOT
end
end
module TinyDocs
extend Puppet::Interface::DocGen
attr_doc :summary do |value|
value =~ /\n/ and
raise ArgumentError, "Face summary should be a single line; put the long text in 'description' instead."
value
end
attr_doc :description
end
module FullDocs
extend Puppet::Interface::DocGen
include TinyDocs
attr_doc :examples
attr_doc :notes
attr_doc :license
attr_doc :short_description
def short_description(value = nil)
self.short_description = value unless value.nil?
if @short_description.nil? then
return nil if @description.nil?
lines = @description.split("\n")
grab = [5, lines.index('') || 5].min
@short_description = lines[0, grab].join("\n") + ' [...]'
end
@short_description
end
def author(value = nil)
unless value.nil? then
unless value.is_a? String
raise ArgumentError, 'author must be a string; use multiple statements for multiple authors'
end
if value =~ /\n/ then
raise ArgumentError, 'author should be a single line; use multiple statements for multiple authors'
end
@authors.push(Puppet::Interface::DocGen.strip_whitespace(value))
end
@authors.empty? ? nil : @authors.join("\n")
end
def authors
@authors
end
def author=(value)
if Array(value).any? {|x| x =~ /\n/ } then
raise ArgumentError, 'author should be a single line; use multiple statements'
end
@authors = Array(value).map{|x| Puppet::Interface::DocGen.strip_whitespace(x) }
end
alias :authors= :author=
def copyright(owner = nil, years = nil)
if years.nil? and not owner.nil? then
raise ArgumentError, 'copyright takes the owners names, then the years covered'
end
self.copyright_owner = owner unless owner.nil?
self.copyright_years = years unless years.nil?
if self.copyright_years or self.copyright_owner then
"Copyright #{self.copyright_years} by #{self.copyright_owner}"
else
"Unknown copyright owner and years."
end
end
attr_accessor :copyright_owner
def copyright_owner=(value)
case value
when String then @copyright_owner = value
when Array then @copyright_owner = value.join(", ")
else
raise ArgumentError, "copyright owner must be a string or an array of strings"
end
@copyright_owner
end
attr_accessor :copyright_years
def copyright_years=(value)
years = munge_copyright_year value
years = (years.is_a?(Array) ? years : [years]).
sort_by do |x| x.is_a?(Range) ? x.first : x end
@copyright_years = years.map do |year|
if year.is_a? Range then
"#{year.first}-#{year.last}"
else
year
end
end.join(", ")
end
def munge_copyright_year(input)
case input
when Range then input
when Integer then
if input < 1970 then
fault = "before 1970"
elsif input > (future = Time.now.year + 2) then
fault = "after #{future}"
end
if fault then
raise ArgumentError, "copyright with a year #{fault} is very strange; did you accidentally add or subtract two years?"
end
input
when String then
input.strip.split(/,/).map do |part|
part = part.strip
if part =~ /^\d+$/ then
part.to_i
elsif found = part.split(/-/) then
unless found.length == 2 and found.all? {|x| x.strip =~ /^\d+$/ }
raise ArgumentError, "#{part.inspect} is not a good copyright year or range"
end
Range.new(found[0].to_i, found[1].to_i)
else
raise ArgumentError, "#{part.inspect} is not a good copyright year or range"
end
end
when Array then
result = []
input.each do |item|
item = munge_copyright_year item
if item.is_a? Array
result.concat item
else
result << item
end
end
result
else
raise ArgumentError, "#{input.inspect} is not a good copyright year, set, or range"
end
end
end
end
|