ri_for 0.3.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/README ADDED
@@ -0,0 +1,101 @@
1
+ A "run time RI for ruby methods", this gem allows you to query for information about objects' methods at runtime--for example within irb or ruby-debug. It reveals everything known about the method. This includes source, ri, arity, rdoc comments (1.9 only), etc.
2
+
3
+ For me it has proved quite useful, and I wouldn't do a ruby-debug session without it--you might really like it.
4
+
5
+ Examples:
6
+
7
+ >> class A;
8
+ def go(a); end;
9
+ end
10
+
11
+ >> A.desc_method :go
12
+ #<UnboundMethod: A#go> arity: 1
13
+ ri for A#go
14
+ Nothing known about A
15
+ (end ri)
16
+ def go(a)
17
+ # do nothing
18
+ end
19
+ Parameters: go(a)
20
+
21
+ >> File.desc_method :delete
22
+ ri for File.delete
23
+ ----------------------------------------------------------- File::delete
24
+ File.delete(file_name, ...) => integer
25
+ File.unlink(file_name, ...) => integer
26
+
27
+ From Ruby 1.9.1
28
+ ------------------------------------------------------------------------
29
+ Deletes the named files, returning the number of names passed as
30
+ arguments. Raises an exception on any error. See also +Dir::rmdir+.
31
+
32
+ (end ri)
33
+ #<Method: File.delete> arity: -1
34
+ appears to be a c method
35
+ #parameters signature: delete( [[:rest]] )
36
+
37
+ Or (my favorite) a debug session:
38
+
39
+ (rdb:1) l=
40
+ ...
41
+ 74 assert(assigns['order'].order_line_items.map(:unit_price).min >= -5)
42
+ ...
43
+ (rdb:1) desc_method :assert
44
+ #<Method: StoreControllerTest(Test::Unit::Assertions)#assert> arity: -2
45
+ ri for Test::Unit::Assertions#assert
46
+ ------------------------------------------ Test::Unit::Assertions#assert
47
+ assert(boolean, message=nil)
48
+
49
+ From gem test-unit-2.0.1
50
+ ------------------------------------------------------------------------
51
+ Asserts that +boolean+ is not false or nil.
52
+
53
+ Example:
54
+
55
+ assert [1, 2].include?(5)
56
+
57
+ (end ri)
58
+ def assert(boolean, message = nil)
59
+ _wrap_assertion do
60
+ assert_block("assert should not be called with a block.") do
61
+ (not block_given?)
62
+ end
63
+ assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
64
+ end
65
+ end
66
+ Parameters: assert(boolean, message = nil)
67
+
68
+ Thus, you can look at methods' source/rdocs without having to step into them. Deftly convenient.
69
+
70
+ ========= How to Install=====
71
+ $ gem install rogerdpack-desc_method
72
+ or
73
+ $ gem install rogerdpack-desc_method --source http://gems.github.com
74
+ if you don't have gems.github.com as a gem source.
75
+
76
+ Usage:
77
+ >> require 'desc_method'
78
+ >> Class.desc_method :method_name # class or instance method name
79
+ ...
80
+ >> some_instance.desc_method :method_name
81
+
82
+ Other goodies included:
83
+
84
+ Class#desc_class method
85
+
86
+ An example:
87
+ >> Object.desc_class
88
+ # outputs descriptive info about that class--RI, method list, etc.
89
+ >> Object.desc_class :verbose => true
90
+ # outputs RI, method lists including inherited methods, ancestors, all constants etc.
91
+
92
+ Kernel#methods has been monkey patched to output a "separator" between its inherited and non inherited methods--i.e.
93
+ >> instance.methods
94
+ => [:first, :second, :after_this_are_inherited>>>>>, :some_inherited_method, :another_inherited_method] # adds in that separator
95
+
96
+ I'll probably remove that in a future release since it turns out you can just run Kernel#methods(false) for about much.
97
+
98
+ === Thanks ===
99
+ This gem wraps for convenience the functionality of Method#source_location, ruby2ruby, et al, and also contains some code inspiration from manvenu, SourceRef (MBARI), and Python's Method#desc. It also wouldn't be useful without irb and the ruby-debug folks. Thanks!
100
+
101
+ Comments/suggestions welcome rogerdpack on gmail or github
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'jeweler'
2
+ Jeweler::Tasks.new do |s|
3
+ s.name = %q{ri_for}
4
+ s.authors = ["Roger Pack"]
5
+ s.description = s.summary = %q{ruby method describer to make it possible to inspect methods [rdoc, signature, etc.] at runtime, for example while debugging.}
6
+ s.email = ["rogerdpack@gmail.comm"]
7
+
8
+ s.homepage = %q{http://github.com/rogerdpack/method_describer}
9
+ s.add_dependency(%q<rdoc>, [">= 2.3"]) # for sane ri lookup times
10
+ s.add_dependency(%q<require_all>, [">= 1.1"]) # require_rel
11
+ s.add_dependency(%q<rdp-arguments>, [">= 0.6.4"])
12
+ s.add_dependency(%q<sane>, ['>= 0.1.2'])
13
+ s.add_dependency(%q<ParseTree>) # these next two for 1.8 only...
14
+ s.add_dependency(%q<ruby2ruby>)
15
+ s.add_development_dependency("rubydoctest")
16
+ end
17
+
data/TODO ADDED
@@ -0,0 +1 @@
1
+ see issues
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -0,0 +1,31 @@
1
+ require_rel 'method_ri'
2
+
3
+ class Class
4
+ # just runs ri against the class, outputs a big
5
+ def desc_class options = {}
6
+ # want_output = false, verbose = false
7
+ begin
8
+ puts "begin RI"
9
+ RDoc::RI::Driver.run [to_s, '--no-pager']
10
+ puts 'end ri'
11
+ rescue SystemExit
12
+ # not found
13
+ end
14
+
15
+ class_methods = methods(false)
16
+ for ancestor in ancestors[1..-1] # skip the first one, which is yourself
17
+ class_methods -= ancestor.methods(false)
18
+ end
19
+
20
+ doc = []
21
+ doc << to_s
22
+ doc += ["non inherited methods:", instance_methods(false).sort.join(", ")]
23
+ doc += ['non inherited class methods:', class_methods.sort.join(', ')]
24
+ doc += ["ancestors:", ancestors.join(', ')] if options[:verbose]
25
+ doc += ["Constants (possible sub classes):", constants.join(', ')] if constants.length > 0 && options[:verbose]
26
+ puts doc
27
+ doc if options[:want_output]
28
+ end
29
+
30
+ end
31
+
@@ -0,0 +1,20 @@
1
+ =begin rdoc
2
+ add method methods2 so that it returns lists that are split into two kind of [adds a marker where the inherited methods begin].
3
+ =end
4
+ module Kernel
5
+ alias :methods_old :methods
6
+ def methods2 all = true
7
+ if all
8
+ # give some marker designating when the inherited methods start
9
+ (public_methods(false) << :"inherited methods after this point >>") + (public_methods(true) - public_methods(false))
10
+ else
11
+ public_methods(false)
12
+ end
13
+ end
14
+ end
15
+
16
+ if $0 == __FILE__
17
+ class A; end
18
+ puts 'A.methods', A.methods(true).inspect, A.methods(false).inspect
19
+ puts 'A.new.methods', A.new.methods.inspect
20
+ end
@@ -0,0 +1,176 @@
1
+ require 'rubygems'
2
+ require 'rdoc'
3
+ require 'rdoc/ri/driver'
4
+ require 'sane'
5
+
6
+ if RUBY_VERSION < '1.9'
7
+ require 'ruby2ruby'
8
+ require 'parse_tree'
9
+ gem 'rdp-arguments' # TODO why is this necessary?
10
+ require 'arguments' # rogerdpack-arguments
11
+ end
12
+
13
+ module SourceLocationDesc
14
+
15
+ # add a Method#desc which spits out all it knows about that method
16
+ # ri, location, local ri, etc.
17
+ # TODO does this work with class methods?
18
+ def ri options = {}
19
+ want_just_summary = options[:want_just_summary]
20
+ want_the_description_returned = options[:want_the_description_returned]
21
+ doc = []
22
+ # to_s is something like "#<Method: String#strip>"
23
+ # or #<Method: GiftCertsControllerTest(Test::Unit::TestCase)#get>
24
+ # or "#<Method: A.go>"
25
+ # or "#<Method: Order(id: integer, order_number: integer).get_cc_processor>"
26
+ # or "#<Method: Order(id: integer, order_number: integer)(ActiveRecord::Base).get_cc_processor>"
27
+
28
+ string = to_s
29
+
30
+ # derive class_name
31
+ parenthese_count = string.count '('
32
+
33
+ if parenthese_count== 1
34
+ # case #<Method: GiftCertsControllerTest(Test::Unit::TestCase)#get>
35
+ # case #<Method: Order(id: integer, order_number: integer).get_cc_processor>
36
+ if string.include? "id: " # TODO huh?
37
+ string =~ /Method: (.+)\(/
38
+ else
39
+ string =~ /\(([^\(]+)\)[\.#]/ # extract out what is between last parentheses
40
+ end
41
+ class_name = $1
42
+ elsif parenthese_count == 0
43
+ # case "#<Method: A.go>"
44
+ string =~ /Method: ([^#\.]+)/
45
+ class_name = $1
46
+ elsif parenthese_count == 2
47
+ # case "#<Method: Order(id: integer, order_number: integer)(ActiveRecord::Base).get_cc_processor>"
48
+ string =~ /\(([^\(]+)\)[\.#]/
49
+ class_name = $1
50
+ else
51
+ raise 'bad ' + string
52
+ end
53
+
54
+ # now get method name, type
55
+ string =~ /Method: .*([#\.])(.*)>/ # include the # or .
56
+ joiner = $1
57
+ method_name = $2
58
+ full_name = "#{class_name}#{joiner}#{method_name} arity #{arity}"
59
+ sig = "sig: #{full_name} arity: #{arity}"
60
+ doc << sig
61
+ param_string = sig
62
+
63
+ # now gather up any other information we now about it, in case there are no rdocs, so we can see it early...
64
+
65
+ if !(respond_to? :source_location)
66
+ # pull out names for 1.8
67
+ begin
68
+ klass = eval(class_name)
69
+ # we don't call to_ruby to overcome ruby2ruby bug http://rubyforge.org/tracker/index.php?func=detail&aid=26891&group_id=1513&atid=5921
70
+ if joiner == '#'
71
+ raw_code = ParseTree.new.parse_tree_for_method(klass, method_name)
72
+ else
73
+ raw_code = ParseTree.new.parse_tree_for_method(klass.singleton_class, method_name)
74
+ end
75
+ doc << Ruby2Ruby.new.process(ParseTree.new.process(raw_code))
76
+
77
+ args = Arguments.names(klass, method_name, false) rescue Arguments.names(klass.singleton_class, method_name, false)
78
+ out = []
79
+ args.each{|arg_pair|
80
+ out << arg_pair.join(' = ')
81
+ } if args
82
+ out = out.join(', ')
83
+ param_string = out
84
+ return out if want_just_summary
85
+
86
+ param_string = "Parameters: #{method_name}(" + out + ")"
87
+ doc << param_string unless want_the_description_returned
88
+ rescue Exception => e
89
+ doc << "appears to be a c method"
90
+ puts "fail to parse tree: #{class_name} #{e} #{e.backtrace}" if $VERBOSE
91
+ end
92
+ else
93
+ # 1.9.x
94
+ file, line = source_location
95
+ param_string = to_s
96
+ if file
97
+ # then it's a pure ruby method
98
+ all_lines = File.readlines(file)
99
+ head_and_sig = all_lines[0...line]
100
+ sig = head_and_sig[-1]
101
+ head = head_and_sig[0..-2]
102
+
103
+ doc << sig
104
+ head.reverse_each do |line|
105
+ break unless line =~ /^\s*#(.*)/
106
+ doc.unshift " " + $1.strip
107
+ end
108
+ doc.unshift " at #{file}:#{line}"
109
+
110
+ # now the real code will end with 'end' same whitespace as the first
111
+ sig_white_space = sig.scan(/\W+/)[0]
112
+ body = all_lines[line..-1]
113
+ body.each{|line|
114
+ doc << line
115
+ if line.start_with?(sig_white_space + "end")
116
+ break
117
+ end
118
+ }
119
+ already_got_ri = true
120
+ param_string = sig
121
+ return sig + "\n" + head[0] if want_just_summary
122
+ else
123
+ doc << 'appears to be a c method'
124
+ end
125
+ if respond_to? :parameters
126
+ doc << "Original code signature: %s" % sig.to_s.strip if sig
127
+ doc << "#parameters signature: %s( %p )" % [name, parameters]
128
+ end
129
+ end
130
+
131
+ puts doc # always output it since RI does currently [todo make optional I suppose, and non out-putty]
132
+
133
+
134
+ # now run default RI for it
135
+ begin
136
+ puts 'Searching ri for ' + full_name + "..."
137
+ RDoc::RI::Driver.run [full_name, '--no-pager'] unless want_just_summary
138
+ rescue *[StandardError, SystemExit]
139
+ # not found
140
+ ensure
141
+ puts '(end ri)'
142
+ end unless already_got_ri
143
+
144
+ if want_the_description_returned # give them something they can examine
145
+ doc
146
+ else
147
+ param_string # one liner
148
+ end
149
+ end
150
+
151
+ alias :desc :ri
152
+ end
153
+
154
+ class Method; include SourceLocationDesc; end
155
+ class UnboundMethod; include SourceLocationDesc; end
156
+
157
+ # TODO mixin from a separate module
158
+ class Object
159
+ # currently rather verbose, but will attempt to describe all it knows about a method
160
+ def ri_for name, options = {}
161
+ if self.is_a?(Class) || self.is_a?(Module)
162
+ # i.e. String.strip
163
+ begin
164
+ instance_method(name).ri(options)
165
+ rescue NameError => e #allows for Class.instance_method_name
166
+ puts e, e.backtrace
167
+ method(name).ri(options)
168
+ end
169
+ else
170
+ method(name).desc(options)
171
+ end
172
+ end
173
+ end
174
+
175
+ # attribution
176
+ # originally gleaned from http://p.ramaze.net/17901
data/lib/ri_for.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'sane'
2
+ require_rel 'ri_for'
@@ -0,0 +1,51 @@
1
+ # this comment should never be shown
2
+ module M
3
+ def go_here
4
+ 345
5
+ end
6
+ end
7
+
8
+ class A
9
+ def self.inspect
10
+ "A(id: integer, b: integer)"
11
+ end
12
+ # this should never be shown with go2
13
+ def go
14
+ 33
15
+ end
16
+ # some suh-weet rdoc
17
+ def self.go2
18
+ 34
19
+ end
20
+
21
+ include M
22
+ end
23
+
24
+
25
+
26
+ class B
27
+ def self.go2
28
+ 35
29
+ end
30
+ end
31
+
32
+ =begin
33
+ doctest: should parse funky inspect classes [railsy], too
34
+
35
+ doctest_require: '../lib/ri_for'
36
+ >> $VERBOSE = true
37
+ >> A.ri_for(:go, :want_the_description_returned => true).join('..')
38
+ >> A.ri_for(:go2, :want_the_description_returned => true).join('..')
39
+ >> B.ri_for(:go2, :want_the_description_returned => true).join('..').include?('35')
40
+ => true
41
+ >> RUBY_VERSION > '1.8' || A.ri_for(:go2, :want_the_description_returned => true).join('..').include?('suh-weet rdoc')
42
+ => true
43
+ >> A.ri_for(:go2, :want_the_description_returned => true).join('..').include? 'never be shown'
44
+ => false
45
+
46
+ # dual whammy... TODO do these test provide full coverage?
47
+
48
+ >> RUBY_VERSION > '1.8' || A.ri_for(:go_here, :want_the_description_returned => true).join('..').include?('345')
49
+ >> RUBY_VERSION > '1.8' || A.ri_for(:go_here, :want_the_description_returned => true).join('..').include?('345')
50
+
51
+ =end
@@ -0,0 +1,104 @@
1
+ require 'rubygems'
2
+ require 'ffi'
3
+
4
+ $VERBOSE = true
5
+
6
+ class A
7
+ # a suh-weet rdoc
8
+ def go(a=5)
9
+ a = 33
10
+ end
11
+
12
+ def self.go22(b=5)
13
+ b = 3
14
+ end
15
+ end
16
+
17
+ =begin
18
+ doctest_require: '../lib/ri_for'
19
+ >> $VERBOSE = true
20
+ >> output = A.ri_for(:go, :want_the_description_returned => true).join(' ')
21
+ >> output.include? 'a = 33'
22
+ => true
23
+ >> RUBY_VERSION < '1.9' || output.include?('suh-weet')
24
+ => true
25
+
26
+ >> output = A.new.ri_for(:go, :want_the_description_returned => true).join(' ')
27
+ >> output.include? 'a = 33'
28
+ => true
29
+ >> RUBY_VERSION < '1.9' || output.include?('suh-weet')
30
+ => true
31
+
32
+ >> output = A.ri_for(:go22, :want_the_description_returned => true).join(' ')
33
+ >> output.include? 'b = 3'
34
+ => true
35
+
36
+ it should return you something useful
37
+
38
+ >> A.ri_for(:go22) == nil
39
+ => false
40
+ >> A.ri_for(:go) == nil
41
+ => false
42
+
43
+ it should work with Module, too
44
+
45
+ >> FFI::Library.ri_for(:attach_function) == nil
46
+ => false
47
+
48
+ =end
49
+
50
+
51
+ =begin
52
+ doctest:
53
+
54
+ it should return true if you run it against a "real" class
55
+ >> String.desc_class(:want_output => true).length > 1
56
+ => true
57
+ >> class A; end
58
+ >> A.desc_class(:want_output => true).length > 1
59
+ => true
60
+
61
+ it shouldn't report itself as an ancestor of itself
62
+ >> A.desc_class(:want_output => true).grep(/ancestors/).include? '[A]'
63
+ => false
64
+
65
+ also lists constants
66
+ >> A.desc_class(:want_output => true, :verbose => true).grep(/constants/i)
67
+ => [] # should be none since we didn't add any constants to A
68
+ >> class A; B = 3; end
69
+ >> A.desc_class(:want_output => true, :verbose => true).grep(/constants/i).length
70
+ => 1 # should be none since we didn't add any constants to A
71
+
72
+ should work with sub methods
73
+ >> String.ri_for(:strip)
74
+
75
+ doctest_require: '../lib/ri_for'
76
+ =end
77
+
78
+ =begin
79
+ doctest:
80
+ >> require 'pathname'
81
+
82
+ it should display the name
83
+
84
+ >> Pathname.instance_method(:children).desc(:want_the_description_returned => true).grep(/children/).size > 0
85
+ => true # ["#<UnboundMethod: Pathname#children>"]
86
+
87
+ >> Pathname.instance_method(:children).desc(:want_the_description_returned => true).grep(/Dir.foreach/).size > 0
88
+ => true # the code itself
89
+
90
+ and arity
91
+ >> Pathname.instance_method(:children).desc(:want_the_description_returned => true).grep(/arity/)
92
+ => ["sig: Pathname#children arity -1 arity: -1"]
93
+
94
+ # todo: one that is guaranteed to exit you early [no docs at all ever]
95
+
96
+ wurx with class methods
97
+ >> class A; def self.go(a = 3); a=5; end; end
98
+ >> class A; def go2(a=4) a =7; end; end
99
+ >> A.ri_for(:go)
100
+ >> A.ri_for(:go2)
101
+
102
+ >> File.ri_for :delete
103
+
104
+ =end
data/todo ADDED
@@ -0,0 +1 @@
1
+ see issues
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ri_for
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Roger Pack
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-02 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rdoc
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "2.3"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: require_all
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "1.1"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rdp-arguments
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.6.4
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: sane
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.1.2
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: ParseTree
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: ruby2ruby
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ - !ruby/object:Gem::Dependency
76
+ name: rubydoctest
77
+ type: :development
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ description: ruby method describer to make it possible to inspect methods [rdoc, signature, etc.] at runtime, for example while debugging.
86
+ email:
87
+ - rogerdpack@gmail.comm
88
+ executables: []
89
+
90
+ extensions: []
91
+
92
+ extra_rdoc_files:
93
+ - README
94
+ - TODO
95
+ files:
96
+ - README
97
+ - Rakefile
98
+ - VERSION
99
+ - lib/ri_for.rb
100
+ - lib/ri_for/class_desc.rb
101
+ - lib/ri_for/kernel_new_methods_list.rb
102
+ - lib/ri_for/method_ri.rb
103
+ - test/test_big_name.rb
104
+ - test/test_method.rb
105
+ - todo
106
+ - TODO
107
+ has_rdoc: true
108
+ homepage: http://github.com/rogerdpack/method_describer
109
+ licenses: []
110
+
111
+ post_install_message:
112
+ rdoc_options:
113
+ - --charset=UTF-8
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: "0"
121
+ version:
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: "0"
127
+ version:
128
+ requirements: []
129
+
130
+ rubyforge_project:
131
+ rubygems_version: 1.3.5
132
+ signing_key:
133
+ specification_version: 3
134
+ summary: ruby method describer to make it possible to inspect methods [rdoc, signature, etc.] at runtime, for example while debugging.
135
+ test_files:
136
+ - test/test_big_name.rb
137
+ - test/test_method.rb