lazydoc 0.9.0 → 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.
- data/History +17 -0
- data/MIT-LICENSE +16 -15
- data/README +51 -30
- data/lib/lazydoc.rb +49 -17
- data/lib/lazydoc/attributes.rb +227 -72
- data/lib/lazydoc/document.rb +13 -11
- data/lib/lazydoc/version.rb +7 -0
- metadata +7 -4
data/History
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
== 1.0.0 / 2009-12-05
|
2
|
+
|
3
|
+
* optimized regexps
|
4
|
+
* updated Lazydoc::Attributes to automatically set source_file
|
5
|
+
when inherited
|
6
|
+
* added document method to Lazydoc to look up document for
|
7
|
+
source_file without automatically creating the document (as
|
8
|
+
is the case with Lazydoc[])
|
9
|
+
* register_file now guesses a default constant name based on
|
10
|
+
the path relative to a matching LOAD_PATH
|
11
|
+
* updated Lazydoc::Attributes to allow manually registered
|
12
|
+
comments across multiple source files
|
13
|
+
* added inheritance for lazy attributes
|
14
|
+
* changed registered_methods to return an array of the methods
|
15
|
+
whose documentation will be registered (no longer a hash by
|
16
|
+
default)
|
17
|
+
|
1
18
|
== 0.9.0 / 2009-05-25
|
2
19
|
|
3
20
|
* lazy attributes can now be accessed without auto-resolve
|
data/MIT-LICENSE
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
Copyright (c) 2008-2009, Regents of the University of Colorado.
|
2
|
+
Copyright (c) 2009, Simon Chiang.
|
2
3
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
software and associated documentation files (the "Software"), to deal
|
5
|
-
without restriction, including without limitation the rights
|
6
|
-
publish, distribute, sublicense, and/or sell
|
7
|
-
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
6
|
+
in the Software without restriction, including without limitation the rights
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
9
|
+
furnished to do so, subject to the following conditions:
|
8
10
|
|
9
|
-
The above copyright notice and this permission notice shall be included in all
|
10
|
-
substantial portions of the Software.
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
12
|
+
copies or substantial portions of the Software.
|
11
13
|
|
12
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
20
|
+
SOFTWARE.
|
data/README
CHANGED
@@ -6,9 +6,8 @@ Tap[http://tap.rubyforge.org] framework.
|
|
6
6
|
|
7
7
|
== Description
|
8
8
|
|
9
|
-
Lazydoc allows you to define lazy attributes that
|
10
|
-
|
11
|
-
Lazydoc pulls out the documentation:
|
9
|
+
Lazydoc allows you to define lazy attributes that access documentation in a
|
10
|
+
source file.
|
12
11
|
|
13
12
|
# Sample::key <value>
|
14
13
|
# This is the comment content. A content
|
@@ -35,8 +34,7 @@ Comments support wrapping, allowing for easy presentation:
|
|
35
34
|
# ..............................
|
36
35
|
# }
|
37
36
|
|
38
|
-
|
39
|
-
particularly method definitions:
|
37
|
+
Lazydoc also provides helpers to register method documentation:
|
40
38
|
|
41
39
|
class Helpers
|
42
40
|
extend Lazydoc::Attributes
|
@@ -49,7 +47,7 @@ particularly method definitions:
|
|
49
47
|
end
|
50
48
|
|
51
49
|
# register_caller will register the line
|
52
|
-
# that *calls* method_two
|
50
|
+
# that *calls* method_two (see below)
|
53
51
|
def method_two
|
54
52
|
Lazydoc.register_caller
|
55
53
|
end
|
@@ -59,19 +57,18 @@ particularly method definitions:
|
|
59
57
|
# registered by method_two
|
60
58
|
Helpers.const_attrs[:method_two] = Helpers.new.method_two
|
61
59
|
|
62
|
-
doc = Helpers.lazydoc
|
63
|
-
doc.resolve
|
64
|
-
|
65
60
|
one = Helpers.const_attrs[:method_one]
|
61
|
+
one.resolve
|
66
62
|
one.method_name # => "method_one"
|
67
63
|
one.arguments # => ["a", "b='str'", "&c"]
|
68
64
|
one.to_s # => "method_one is registered whenever it gets defined"
|
69
65
|
|
70
66
|
two = Helpers.const_attrs[:method_two]
|
67
|
+
two.resolve
|
71
68
|
two.subject # => "Helpers.const_attrs[:method_two] = Helpers.new.method_two"
|
72
69
|
two.to_s # => "*THIS* is the line that gets registered by method_two"
|
73
70
|
|
74
|
-
Lazy accessors may be defined to
|
71
|
+
Lazy accessors may be defined to access the registered lines more easily:
|
75
72
|
|
76
73
|
class Helpers
|
77
74
|
lazy_attr(:one, :method_one)
|
@@ -81,11 +78,10 @@ Lazy accessors may be defined to map the registered lines as well:
|
|
81
78
|
Helpers.one.method_name # => "method_one"
|
82
79
|
Helpers.two.subject # => "Helpers.const_attrs[:method_two] = Helpers.new.method_two"
|
83
80
|
|
84
|
-
Check out these links for
|
81
|
+
Check out these links for developments and bug tracking.
|
85
82
|
|
86
83
|
* Website[http://tap.rubyforge.org/lazydoc]
|
87
84
|
* Github[http://github.com/bahuvrihi/lazydoc/tree/master]
|
88
|
-
* Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/19948-lazydoc/tickets?q=all]
|
89
85
|
* {Google Group}[http://groups.google.com/group/ruby-on-tap]
|
90
86
|
|
91
87
|
== Usage
|
@@ -96,9 +92,9 @@ are represented by Comment objects.
|
|
96
92
|
|
97
93
|
=== Constant Attributes
|
98
94
|
|
99
|
-
Constant attributes are
|
100
|
-
that must consist of only lowercase letters and/or
|
101
|
-
example, these are constant attributes:
|
95
|
+
Constant attributes are defined in the documentation to look like constants,
|
96
|
+
but with an extra 'key' that must consist of only lowercase letters and/or
|
97
|
+
underscores. For example, these are constant attributes:
|
102
98
|
|
103
99
|
# Const::Name::key
|
104
100
|
# Const::Name::key_with_underscores
|
@@ -111,7 +107,7 @@ While these are not:
|
|
111
107
|
# Const::Name::k@y
|
112
108
|
|
113
109
|
Lazydoc parses a Lazydoc::Comment for each constant attribute by using the
|
114
|
-
remainder of the line as a value (ie subject) and
|
110
|
+
remainder of the line as a value (ie subject) and trailing lines as content.
|
115
111
|
Parsing continues until a non-comment line, an end key, or a new attribute
|
116
112
|
is reached; the comment is then stored by constant name and key.
|
117
113
|
|
@@ -139,8 +135,8 @@ is reached; the comment is then stored by constant name and key.
|
|
139
135
|
# 'another' => ['value for another', 'comment for another parsed to an end key']}
|
140
136
|
# }
|
141
137
|
|
142
|
-
Constant attributes are only parsed from
|
143
|
-
|
138
|
+
Constant attributes are only parsed from comment lines. To turn off attribute
|
139
|
+
parsing for a section of documentation, use start/stop keys:
|
144
140
|
|
145
141
|
str = %Q{
|
146
142
|
Const::Name::not_parsed
|
@@ -155,9 +151,9 @@ attribute parsing for a section of documentation, use start/stop keys:
|
|
155
151
|
doc.resolve(str)
|
156
152
|
doc.summarize {|comment| comment.value } # => {'Const::Name' => {'parsed' => 'value'}}
|
157
153
|
|
158
|
-
To hide attributes from RDoc, make use of the RDoc <tt>:startdoc:</tt>
|
159
|
-
document modifier like this (note
|
160
|
-
from hiding the example):
|
154
|
+
To hide attributes from RDoc, make use of the RDoc <tt>:startdoc:</tt>
|
155
|
+
document modifier like this (note the modifiers have an extra space in them to
|
156
|
+
prevent RDoc from hiding the example):
|
161
157
|
|
162
158
|
# :start doc::Const::Name::one hidden in RDoc
|
163
159
|
# * This line is visible in RDoc.
|
@@ -171,16 +167,17 @@ from hiding the example):
|
|
171
167
|
#
|
172
168
|
# * This line is also visible in RDoc.
|
173
169
|
|
174
|
-
As a side note,
|
175
|
-
|
176
|
-
'Const::Name::key' is equivalent to the method call
|
170
|
+
As a side note, the constant attribute syntax is designed to echo how the
|
171
|
+
Lazydoc::Attributes module makes comments accessible in code. In *very*
|
172
|
+
idiomatic Ruby 'Const::Name::key' is equivalent to the method call
|
173
|
+
'Const::Name.key'.
|
177
174
|
|
178
175
|
=== Code Comments
|
179
176
|
|
180
|
-
Code comments are lines registered for parsing if and when a Lazydoc gets
|
177
|
+
Code comments are lines registered for parsing if and when a Lazydoc gets
|
181
178
|
resolved. Unlike constant attributes, the registered line is the comment
|
182
|
-
subject (ie value) and
|
183
|
-
the behavior of RDoc).
|
179
|
+
subject (ie value) and the content consists of the preceding documentation
|
180
|
+
(basically mimicking the behavior of RDoc).
|
184
181
|
|
185
182
|
str = %Q{
|
186
183
|
# comment lines for
|
@@ -211,6 +208,31 @@ of a Regexp, the first matching line is used; Procs receive an array of
|
|
211
208
|
lines and should return the line number that should be used. See
|
212
209
|
{Comment#parse_up}[link://classes/Lazydoc/Comment.html] for more details.
|
213
210
|
|
211
|
+
Manually registering lines for documentation can be quite cumbersome. The
|
212
|
+
Lazydoc::Attributes module provides helpers to register method documentation
|
213
|
+
on classes with method-like inheritance.
|
214
|
+
|
215
|
+
class A
|
216
|
+
extend Lazydoc::Attributes
|
217
|
+
lazy_attr(:one, :method_one)
|
218
|
+
lazy_register(:method_one)
|
219
|
+
|
220
|
+
# documentation for method one
|
221
|
+
def method_one; end
|
222
|
+
end
|
223
|
+
|
224
|
+
class B < A
|
225
|
+
end
|
226
|
+
|
227
|
+
class C < B
|
228
|
+
# overriding documentation for method one
|
229
|
+
def method_one; end
|
230
|
+
end
|
231
|
+
|
232
|
+
A::one.comment # => "documentation for method one"
|
233
|
+
B::one.comment # => "documentation for method one"
|
234
|
+
C::one.comment # => "overriding documentation for method one"
|
235
|
+
|
214
236
|
== Installation
|
215
237
|
|
216
238
|
Lazydoc is available as a gem on RubyForge[http://rubyforge.org/projects/tap]. Use:
|
@@ -219,7 +241,6 @@ Lazydoc is available as a gem on RubyForge[http://rubyforge.org/projects/tap].
|
|
219
241
|
|
220
242
|
== Info
|
221
243
|
|
222
|
-
Copyright (c)
|
223
|
-
Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com]
|
224
|
-
Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
|
244
|
+
Copyright (c) 2009, Simon Chiang.
|
245
|
+
Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com]
|
225
246
|
License:: {MIT-Style}[link:files/MIT-LICENSE.html]
|
data/lib/lazydoc.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'lazydoc/version'
|
1
2
|
require 'lazydoc/document'
|
2
3
|
|
3
4
|
module Lazydoc
|
@@ -8,22 +9,54 @@ module Lazydoc
|
|
8
9
|
@registry ||= []
|
9
10
|
end
|
10
11
|
|
11
|
-
# Returns the
|
12
|
-
#
|
12
|
+
# Returns the document registered to the source file, or nil if no such
|
13
|
+
# document exists.
|
14
|
+
def document(source_file)
|
15
|
+
source_file = File.expand_path(source_file.to_s)
|
16
|
+
registry.find {|doc| doc.source_file == source_file }
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the document registered to the source file. If no such document
|
20
|
+
# exists, one will be created for it.
|
13
21
|
def [](source_file)
|
22
|
+
document(source_file) || register_file(source_file)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Guesses the default constant name for the source file by camelizing the
|
26
|
+
# shortest relative path from a matching $LOAD_PATH to the source file.
|
27
|
+
# Returns nil if the source file is not relative to any load path.
|
28
|
+
#
|
29
|
+
# ==== Code Credit
|
30
|
+
#
|
31
|
+
# The camelize algorithm is taken from the ActiveSupport {Inflections}[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
|
32
|
+
# module. See the {Tap::Env::StringExt}[http://tap.rubyforge.org/rdoc/classes/Tap/Env/StringExt.html]
|
33
|
+
# module (which uses the same) for a proper credit and license.
|
34
|
+
#
|
35
|
+
def guess_const_name(source_file)
|
14
36
|
source_file = File.expand_path(source_file.to_s)
|
15
|
-
|
37
|
+
|
38
|
+
load_paths = []
|
39
|
+
$LOAD_PATH.each do |load_path|
|
40
|
+
load_path = File.expand_path(load_path)
|
41
|
+
if source_file.rindex(load_path, 0) == 0
|
42
|
+
load_paths << load_path
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
return nil if load_paths.empty?
|
47
|
+
|
48
|
+
load_path = load_paths.sort_by {|load_path| load_path.length}.pop
|
49
|
+
extname = File.extname(source_file)
|
50
|
+
relative_path = source_file[(load_path.length + 1)..(-1 - extname.length)]
|
51
|
+
relative_path.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
16
52
|
end
|
17
53
|
|
18
|
-
# Generates a
|
19
|
-
# registry, or returns the document already registered to
|
54
|
+
# Generates a document for the source_file and default_const_name and adds it to
|
55
|
+
# registry, or returns the document already registered to the source file. An
|
20
56
|
# error is raised if you try to re-register a source_file with an inconsistent
|
21
57
|
# default_const_name.
|
22
|
-
def register_file(source_file, default_const_name=
|
23
|
-
|
24
|
-
lazydoc = registry.find {|doc| doc.source_file == source_file }
|
25
|
-
|
26
|
-
unless lazydoc
|
58
|
+
def register_file(source_file, default_const_name=guess_const_name(source_file))
|
59
|
+
unless lazydoc = document(source_file)
|
27
60
|
lazydoc = Document.new(source_file)
|
28
61
|
registry << lazydoc
|
29
62
|
end
|
@@ -32,16 +65,15 @@ module Lazydoc
|
|
32
65
|
lazydoc
|
33
66
|
end
|
34
67
|
|
35
|
-
# Registers the line number to the document for source_file and
|
36
|
-
#
|
68
|
+
# Registers the line number to the document for source_file and returns the
|
69
|
+
# new comment.
|
37
70
|
def register(source_file, line_number, comment_class=Comment)
|
38
71
|
Lazydoc[source_file].register(line_number, comment_class)
|
39
72
|
end
|
40
73
|
|
41
|
-
# Registers the method
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# register_caller is called (whew!). For instance:
|
74
|
+
# Registers the method to the line where it was called. To do so,
|
75
|
+
# register_caller examines the specified index in the call stack
|
76
|
+
# and extracts a file and line number. For instance:
|
45
77
|
#
|
46
78
|
# module Sample
|
47
79
|
# module_function
|
@@ -59,7 +91,7 @@ module Lazydoc
|
|
59
91
|
#
|
60
92
|
def register_caller(comment_class=Comment, caller_index=1)
|
61
93
|
caller[caller_index] =~ CALLER_REGEXP
|
62
|
-
Lazydoc[$1].register($
|
94
|
+
Lazydoc[$1].register($2.to_i - 1, comment_class)
|
63
95
|
end
|
64
96
|
|
65
97
|
# Parses the usage for a file (ie the first comment in the file
|
data/lib/lazydoc/attributes.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Lazydoc
|
2
2
|
|
3
3
|
# Attributes adds methods to declare class-level accessors for constant
|
4
|
-
# attributes.
|
4
|
+
# attributes associated with the class.
|
5
5
|
#
|
6
6
|
# # ConstName::key value
|
7
7
|
# class ConstName
|
@@ -9,132 +9,287 @@ module Lazydoc
|
|
9
9
|
# lazy_attr :key
|
10
10
|
# end
|
11
11
|
#
|
12
|
-
# ConstName.
|
13
|
-
#
|
12
|
+
# ConstName::key.subject # => 'value'
|
13
|
+
#
|
14
|
+
# Lazy attributes are inherited, but can be overridden.
|
15
|
+
#
|
16
|
+
# class SubclassA < ConstName; end
|
17
|
+
# SubclassA::key.subject # => 'value'
|
18
|
+
#
|
19
|
+
# # SubclassB::key overridden value
|
20
|
+
# class SubclassB < ConstName; end
|
21
|
+
# SubclassB::key.subject # => 'overridden value'
|
22
|
+
#
|
23
|
+
# You can use Attributes to register methods on modules, but currently the
|
24
|
+
# inheritance is a bit wonky; the accessors are methods on the extended
|
25
|
+
# class/module and so standard module inclusion will not pass them on.
|
26
|
+
# To work around you need to extend and redefine the accessors. Note,
|
27
|
+
# however, that methods do not need to be re-registered.
|
28
|
+
#
|
29
|
+
# module A
|
30
|
+
# extend Lazydoc::Attributes
|
31
|
+
# lazy_attr(:one, :method_one)
|
32
|
+
# lazy_register(:method_one)
|
33
|
+
#
|
34
|
+
# # documentation for method one
|
35
|
+
# def method_one; end
|
36
|
+
# end
|
14
37
|
#
|
38
|
+
# class B
|
39
|
+
# include A
|
40
|
+
# extend Lazydoc::Attributes
|
41
|
+
# lazy_attr(:one, :method_one)
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# class C < B
|
45
|
+
# # overriding documentation for method one
|
46
|
+
# def method_one; end
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# A::one.comment # => "documentation for method one"
|
50
|
+
# B::one.comment # => "documentation for method one"
|
51
|
+
# C::one.comment # => "overriding documentation for method one"
|
52
|
+
#
|
15
53
|
# ==== Keys and Register
|
16
54
|
#
|
17
|
-
#
|
18
|
-
# const_attrs
|
19
|
-
#
|
55
|
+
# Constant attributes parsed from a source file will ALWAYS be stored in
|
56
|
+
# const_attrs using a string (since the 'ConstName::key' syntax always
|
57
|
+
# results in a string key). A lazy_attr is basically shorthand for either
|
58
|
+
# of these statements:
|
59
|
+
#
|
60
|
+
# ConstName.const_attrs['key'].subject # => 'value'
|
61
|
+
# Lazydoc::Document['ConstName']['key'].subject # => 'value'
|
62
|
+
#
|
63
|
+
# By default a lazy_attr maps to the constant attribute with the same name
|
64
|
+
# as the accessor, but this can be overridden by specifying the string key
|
65
|
+
# for another attribute.
|
66
|
+
#
|
67
|
+
# class ConstName
|
68
|
+
# lazy_attr :alt, 'key'
|
69
|
+
# end
|
20
70
|
#
|
21
|
-
# ConstName.
|
71
|
+
# ConstName::alt.subject # => 'value'
|
72
|
+
# ConstName.const_attrs['alt'] # => nil
|
22
73
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
74
|
+
# Comments specified by non-string keys may also be stored in const_attrs;
|
75
|
+
# these will not conflict with constant attributes parsed from a source
|
76
|
+
# file. For instance you could manually register a comment to a symbol key
|
77
|
+
# using lazy_register:
|
26
78
|
#
|
27
79
|
# class Sample
|
28
80
|
# extend Lazydoc::Attributes
|
29
81
|
#
|
30
|
-
#
|
82
|
+
# lazy_register(:method_one)
|
83
|
+
#
|
31
84
|
# # this is the method one comment
|
32
85
|
# def method_one
|
33
86
|
# end
|
34
87
|
# end
|
35
88
|
#
|
36
|
-
# Sample.
|
37
|
-
# Sample.const_attrs[:method_one].comment # => "this is the method one comment"
|
89
|
+
# Sample.const_attrs[:method_one].comment # => "this is the method one comment"
|
38
90
|
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# lazy_attr.
|
91
|
+
# Manually-registered comments may then be paired with a lazy_attr. As
|
92
|
+
# before the key for the comment is provided in the definition.
|
42
93
|
#
|
43
94
|
# class Paired
|
44
95
|
# extend Lazydoc::Attributes
|
45
96
|
#
|
46
97
|
# lazy_attr(:one, :method_one)
|
47
|
-
#
|
48
|
-
# lazy_register(:method_two)
|
98
|
+
# lazy_register(:method_one)
|
49
99
|
#
|
50
|
-
#
|
51
|
-
# # this is the manually-registered method one comment
|
100
|
+
# # this is the method one comment
|
52
101
|
# def method_one
|
53
102
|
# end
|
54
|
-
#
|
55
|
-
# # this is the lazyily-registered method two comment
|
56
|
-
# def method_two
|
57
|
-
# end
|
58
103
|
# end
|
59
104
|
#
|
60
|
-
# Paired.
|
61
|
-
#
|
62
|
-
#
|
105
|
+
# Paired::one.comment # => "this is the method one comment"
|
106
|
+
#
|
107
|
+
# ==== Troubleshooting
|
63
108
|
#
|
109
|
+
# Under most circumstances Attributes will register all the necessary files
|
110
|
+
# to make constant attributes available. These include:
|
111
|
+
#
|
112
|
+
# * the file where the class is extended
|
113
|
+
# * the file where a subclass inherits from an extended class
|
114
|
+
# * files that declare a lazy_attr
|
115
|
+
#
|
116
|
+
# Be sure to call register_lazydoc in files that are not covered by one of
|
117
|
+
# these cases but nonetheless contain constant attributes that should be
|
118
|
+
# available to a lazy_attr.
|
64
119
|
module Attributes
|
65
|
-
|
66
|
-
# The source file for the extended class. By default source_file
|
67
|
-
# is set to the file where Attributes extends the class (if you
|
68
|
-
# include Attributes, you must set source_file manually).
|
69
|
-
attr_accessor :source_file
|
70
120
|
|
71
|
-
|
121
|
+
# Sets source_file as the file where Attributes first extends the class.
|
122
|
+
def self.extended(base)
|
72
123
|
caller[1] =~ CALLER_REGEXP
|
73
|
-
base.
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
124
|
+
unless base.instance_variable_defined?(:@lazydocs)
|
125
|
+
base.instance_variable_set(:@lazydocs, [Lazydoc[$1]])
|
126
|
+
end
|
127
|
+
|
128
|
+
unless base.instance_variable_defined?(:@lazy_registry)
|
129
|
+
base.instance_variable_set(:@lazy_registry, {})
|
130
|
+
end
|
131
|
+
|
79
132
|
super
|
80
133
|
end
|
81
134
|
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
|
135
|
+
# Returns the documents registered to the extending class.
|
136
|
+
#
|
137
|
+
# By default lazydocs contains a Document for the file where Attributes
|
138
|
+
# extends the class, or where a subclass first inherits from an extended
|
139
|
+
# class (if you include Attributes, you must set lazydocs manually).
|
140
|
+
#
|
141
|
+
# Additional documents may be added by calling register_lazydoc.
|
142
|
+
attr_reader :lazydocs
|
143
|
+
|
144
|
+
# Returns an array of the methods whose documentation will be automatically
|
145
|
+
# registered by Attributes. Set as_registry to true to return a hash of
|
146
|
+
# of (method_name, [comment_class, caller_index]) pairs where the
|
147
|
+
# registration arguments are the hash values.
|
148
|
+
def registered_methods(as_registry=false)
|
149
|
+
methods = {}
|
150
|
+
ancestors.reverse.each do |ancestor|
|
151
|
+
if ancestor.kind_of?(Attributes)
|
152
|
+
methods.merge!(ancestor.lazy_registry)
|
153
|
+
end
|
86
154
|
end
|
87
155
|
|
88
|
-
|
156
|
+
as_registry ? methods : methods.keys
|
89
157
|
end
|
90
158
|
|
91
159
|
# Returns the constant attributes resolved for the extended class.
|
92
160
|
def const_attrs
|
93
161
|
Document[to_s]
|
94
162
|
end
|
95
|
-
|
96
|
-
|
97
|
-
def lazydoc
|
98
|
-
Lazydoc[source_file]
|
99
|
-
end
|
163
|
+
|
164
|
+
protected
|
100
165
|
|
101
166
|
# A hash of (method_name, [comment_class, caller_index]) pairs indicating
|
102
|
-
# methods to lazily register, and the inputs to
|
103
|
-
#
|
104
|
-
|
105
|
-
|
167
|
+
# methods to lazily register, and the inputs used to register the method.
|
168
|
+
#
|
169
|
+
# The lazy_registry only contains methods lazily registered within the
|
170
|
+
# current class or module. To return methods registered throughout the
|
171
|
+
# inheritance hierarchy, use registered_methods(true)
|
172
|
+
attr_reader :lazy_registry
|
173
|
+
|
174
|
+
# Registers the calling file into lazydocs. Registration occurs by
|
175
|
+
# examining the call stack at the specified index.
|
176
|
+
def register_lazydoc(caller_index=0)
|
177
|
+
caller[caller_index] =~ CALLER_REGEXP
|
178
|
+
lazydocs << Lazydoc[File.expand_path($1)]
|
179
|
+
lazydocs.uniq!
|
180
|
+
self
|
106
181
|
end
|
107
182
|
|
108
183
|
# Creates a method that reads and resolves the constant attribute specified
|
109
|
-
# by key
|
110
|
-
#
|
184
|
+
# by key. The method has a signature like:
|
185
|
+
#
|
186
|
+
# def method(resolve=true)
|
187
|
+
# end
|
188
|
+
#
|
189
|
+
# To return the constant attribute without resolving, call the method with
|
190
|
+
# resolve == false. If writable is true, a corresponding writer is also
|
191
|
+
# created.
|
111
192
|
def lazy_attr(symbol, key=symbol.to_s, writable=true)
|
112
|
-
key
|
113
|
-
|
114
|
-
else "YAML.load(\'#{YAML.dump(key)}\')"
|
193
|
+
unless key.kind_of?(String) || key.kind_of?(Symbol)
|
194
|
+
raise "invalid lazy_attr key: #{key.inspect} (#{key.class})"
|
115
195
|
end
|
116
196
|
|
117
|
-
|
118
|
-
def #{symbol}(resolve=true)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
instance_eval(%Q{
|
124
|
-
def #{symbol}=(comment)
|
125
|
-
const_attrs[#{key}] = comment
|
126
|
-
end}) if writable
|
197
|
+
key = key.inspect
|
198
|
+
instance_eval %Q{def #{symbol}(resolve=true); get_const_attr(#{key}, resolve); end}
|
199
|
+
instance_eval(%Q{def #{symbol}=(comment); const_attrs[#{key}] = comment; end}) if writable
|
200
|
+
|
201
|
+
register_lazydoc(1)
|
127
202
|
end
|
128
203
|
|
129
204
|
# Marks the method for lazy registration. When the method is registered,
|
130
205
|
# it will be stored in const_attrs by method_name.
|
131
206
|
def lazy_register(method_name, comment_class=Method, caller_index=1)
|
132
|
-
|
207
|
+
lazy_registry[method_name.to_sym] = [comment_class, caller_index]
|
133
208
|
end
|
134
209
|
|
135
|
-
#
|
136
|
-
|
137
|
-
|
210
|
+
# Manually registers the next comment into const_attrs. Note a lazy_attr
|
211
|
+
# will still need to be defined to access this comment as an attribute.
|
212
|
+
def register___(key, comment_class=Method)
|
213
|
+
caller[0] =~ CALLER_REGEXP
|
214
|
+
source_file = File.expand_path($1)
|
215
|
+
const_attrs[key] = Lazydoc[source_file].register___(comment_class, 1)
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
|
220
|
+
# Inherits lazy_registry from parent to child. Also registers the
|
221
|
+
# source_file for the child as the file where the inheritance first
|
222
|
+
# occurs.
|
223
|
+
def inherited(child)
|
224
|
+
unless child.instance_variable_defined?(:@lazydocs)
|
225
|
+
caller.each do |call|
|
226
|
+
next if call =~ /in `inherited'$/
|
227
|
+
|
228
|
+
call =~ CALLER_REGEXP
|
229
|
+
child.instance_variable_set(:@lazydocs, [Lazydoc[$1]])
|
230
|
+
break
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
unless child.instance_variable_defined?(:@lazy_registry)
|
235
|
+
child.instance_variable_set(:@lazy_registry, {})
|
236
|
+
end
|
237
|
+
|
238
|
+
super
|
239
|
+
end
|
240
|
+
|
241
|
+
# Helper to traverse the inheritance hierarchy. The logic of this method
|
242
|
+
# is described in the dsl pattern: http://gist.github.com/181961
|
243
|
+
def each_ancestor # :nodoc:
|
244
|
+
yield(self)
|
245
|
+
|
246
|
+
blank, *ancestors = self.ancestors
|
247
|
+
ancestors.each do |ancestor|
|
248
|
+
yield(ancestor) if ancestor.kind_of?(Attributes)
|
249
|
+
end
|
250
|
+
|
251
|
+
nil
|
252
|
+
end
|
253
|
+
|
254
|
+
# Lazily registers the added method if marked for lazy registration.
|
255
|
+
def method_added(sym)
|
256
|
+
current = nil
|
257
|
+
each_ancestor do |ancestor|
|
258
|
+
if ancestor.lazy_registry.has_key?(sym)
|
259
|
+
current = ancestor
|
260
|
+
break
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
if current
|
265
|
+
args = current.lazy_registry[sym]
|
266
|
+
const_attrs[sym] ||= Lazydoc.register_caller(*args)
|
267
|
+
end
|
268
|
+
|
269
|
+
super
|
270
|
+
end
|
271
|
+
|
272
|
+
# helper to traverse up the inheritance hierarchy looking for the first
|
273
|
+
# const_attr assigned to key. the lazydocs for each class will be
|
274
|
+
# resolved along the way, if specified.
|
275
|
+
def get_const_attr(key, resolve) # :nodoc:
|
276
|
+
each_ancestor do |ancestor|
|
277
|
+
const_attrs = ancestor.const_attrs
|
278
|
+
|
279
|
+
unless const_attrs.has_key?(key)
|
280
|
+
next unless resolve
|
281
|
+
|
282
|
+
ancestor.lazydocs.each {|doc| doc.resolve }
|
283
|
+
next unless const_attrs.has_key?(key)
|
284
|
+
end
|
285
|
+
|
286
|
+
const_attr = const_attrs[key]
|
287
|
+
if resolve && const_attr.kind_of?(Comment)
|
288
|
+
const_attr.resolve
|
289
|
+
end
|
290
|
+
|
291
|
+
return const_attr
|
292
|
+
end
|
138
293
|
end
|
139
294
|
end
|
140
295
|
end
|
data/lib/lazydoc/document.rb
CHANGED
@@ -10,22 +10,22 @@ module Lazydoc
|
|
10
10
|
# A regexp matching an attribute start or end. After a match:
|
11
11
|
#
|
12
12
|
# $1:: const_name
|
13
|
-
# $
|
14
|
-
# $
|
13
|
+
# $2:: key
|
14
|
+
# $3:: end flag
|
15
15
|
#
|
16
|
-
ATTRIBUTE_REGEXP = /([A-Z][A-z]*(
|
16
|
+
ATTRIBUTE_REGEXP = /([A-Z][A-z]*(?:::[A-Z][A-z]*)*)?::([a-z_]+)(-?)/
|
17
17
|
|
18
18
|
# A regexp matching constants from the ATTRIBUTE_REGEXP leader
|
19
|
-
CONSTANT_REGEXP = /#.*?([A-Z][A-z]*(
|
19
|
+
CONSTANT_REGEXP = /#.*?([A-Z][A-z]*(?:::[A-Z][A-z]*)*)?$/
|
20
20
|
|
21
21
|
# A regexp matching a caller line, to extract the calling file
|
22
22
|
# and line number. After a match:
|
23
23
|
#
|
24
24
|
# $1:: file
|
25
|
-
# $
|
25
|
+
# $2:: line number (as a string, obviously)
|
26
26
|
#
|
27
27
|
# Note that line numbers in caller start at 1, not 0.
|
28
|
-
CALLER_REGEXP = /^(([A-z]:)?[^:]+):(\d+)/
|
28
|
+
CALLER_REGEXP = /^((?:[A-z]:)?[^:]+):(\d+)/
|
29
29
|
|
30
30
|
# A Document resolves constant attributes and code comments for a particular
|
31
31
|
# source file. Documents may be assigned a default_const_name to be used
|
@@ -40,9 +40,8 @@ module Lazydoc
|
|
40
40
|
# Document['Const::Name']['key'].value # => 'value a'
|
41
41
|
# Document['Default']['key'].value # => 'value b'
|
42
42
|
#
|
43
|
-
# As
|
44
|
-
#
|
45
|
-
# itself.
|
43
|
+
# As in the example, constant attibutes for all documents may be accessed
|
44
|
+
# from Document[].
|
46
45
|
class Document
|
47
46
|
class << self
|
48
47
|
|
@@ -136,6 +135,9 @@ module Lazydoc
|
|
136
135
|
# Returns the attributes for the specified const_name. If an empty
|
137
136
|
# const_name ('') is specified, and a default_const_name is set,
|
138
137
|
# the default_const_name will be used instead.
|
138
|
+
#
|
139
|
+
# Note this method will return ALL attributes associated with const_name,
|
140
|
+
# not just attributes associated with self.
|
139
141
|
def [](const_name)
|
140
142
|
const_name = default_const_name if default_const_name && const_name == ''
|
141
143
|
Document[const_name]
|
@@ -184,7 +186,7 @@ module Lazydoc
|
|
184
186
|
def register___(comment_class=Comment, caller_index=0)
|
185
187
|
caller[caller_index] =~ CALLER_REGEXP
|
186
188
|
block = lambda do |scanner, lines|
|
187
|
-
n = $
|
189
|
+
n = $2.to_i
|
188
190
|
n += 1 while lines[n] =~ /^\s*(#.*)?$/
|
189
191
|
n
|
190
192
|
end
|
@@ -216,7 +218,7 @@ module Lazydoc
|
|
216
218
|
comment.parse_down(scanner, lines) do |line|
|
217
219
|
if line =~ ATTRIBUTE_REGEXP
|
218
220
|
# rewind to capture the next attribute unless an end is specified.
|
219
|
-
scanner.unscan unless $
|
221
|
+
scanner.unscan unless $3 == '-' && $2 == key && $1.to_s == const_name
|
220
222
|
true
|
221
223
|
else false
|
222
224
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lazydoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: "1.0"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Chiang
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05
|
12
|
+
date: 2009-12-05 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -33,11 +33,14 @@ files:
|
|
33
33
|
- lib/lazydoc/subject.rb
|
34
34
|
- lib/lazydoc/trailer.rb
|
35
35
|
- lib/lazydoc/utils.rb
|
36
|
+
- lib/lazydoc/version.rb
|
36
37
|
- README
|
37
38
|
- MIT-LICENSE
|
38
39
|
- History
|
39
40
|
has_rdoc: true
|
40
41
|
homepage: http://tap.rubyforge.org/lazydoc
|
42
|
+
licenses: []
|
43
|
+
|
41
44
|
post_install_message:
|
42
45
|
rdoc_options:
|
43
46
|
- --title
|
@@ -63,9 +66,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
66
|
requirements: []
|
64
67
|
|
65
68
|
rubyforge_project: tap
|
66
|
-
rubygems_version: 1.3.
|
69
|
+
rubygems_version: 1.3.5
|
67
70
|
signing_key:
|
68
|
-
specification_version:
|
71
|
+
specification_version: 3
|
69
72
|
summary: Lazily pull documentation out of source files.
|
70
73
|
test_files: []
|
71
74
|
|