bri 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,40 @@
1
+ = What is this ?
2
+ During the days of Ruby 1.8, the ri command was slow. I mean really slow. Glacially. Starting a web browser and looking up a class or method description on ruby-doc.org often felt faster.
3
+
4
+ Then Mauricio Fernandez produced fastri and qri that produced results a whole lot faster than the native ri tool. Unfortunately, Mauricio seems to have lost interest and didn't port fastri to ruby 1.9. There are patches porting fastri to 1.9.1, but they are iffy and don't work well with 1.9.2 and the new rdoc cache format.
5
+
6
+ Now with ruby 1.9 and the rdoc 2.x gem ri is very responsive. However the output format looks like darkfish without the HTML and uses up a lot of space. And subjectively, it's ugly.
7
+
8
+ This is where bri comes in: it tries to emulate fastri/qris output format and lookup patterns while using the new rdoc 2.x infrastructure.
9
+
10
+ To compare, do 'ri Array' and 'bri Array' and see which appeals more to you.
11
+
12
+ = Too... much... text...
13
+ Bri is a Beautiful RI formatter.
14
+
15
+ = Usage
16
+
17
+ bri Array # looks up the class description of Array in the ri documentation
18
+
19
+ bri Array.class_method # looks up the class method of the given class
20
+
21
+ bri Array#instance_method # looks up the instance method of the given class
22
+
23
+ bri .class_method # looks up the class method in any class
24
+
25
+ bri #instance_method # looks up the instance method in any class
26
+
27
+ bri method # looks up an instance method in any class, first looking for
28
+ # an exact match, then methods names where the beginning matches
29
+ # the given search term, and finally looking for the term
30
+ # anywhere in the method name
31
+
32
+ = Requirements
33
+ * Ruby 1.9.2
34
+ * rdoc 2.5.x
35
+ * term-ansicolor
36
+
37
+
38
+ = The Cheesy Stuff
39
+ There are many bries, but there is only one RI bri.
40
+ (Apologies to Pierre).
data/TODO ADDED
@@ -0,0 +1,6 @@
1
+ - Prepend/markup list items properly
2
+ - Extend unqualified search to include class methods and case insensitive searches
3
+ - Misc. error handlings
4
+ - Do more specs
5
+ - Add command line option parsing and help
6
+ - Set output width dynamically leveraging all synergy effects
data/bin/bri ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bri'
3
+
4
+ if ARGV.size != 1
5
+ STDERR.puts "Usage: #{$0} <reference>"
6
+ exit 0
7
+ end
8
+
9
+ puts Bri.ri( ARGV[0] )
data/lib/bri.rb ADDED
@@ -0,0 +1,51 @@
1
+ $: << File.dirname( __FILE__ )
2
+ require 'erb'
3
+ require 'term/ansicolor'
4
+
5
+
6
+ require 'bri/mall'
7
+ require 'bri/matcher'
8
+ require 'bri/templates'
9
+ require 'bri/search'
10
+ require 'bri/match'
11
+
12
+ module Bri
13
+ WIDTH = 72
14
+
15
+ def self.format_elements( array )
16
+ rows = []
17
+ row = []
18
+ row_length = 0
19
+
20
+ array.each do |element|
21
+ element_length_with_separator = element.length + 2
22
+
23
+ if row_length + element_length_with_separator >= WIDTH
24
+ rows << row
25
+ row = []
26
+ row_length = 0
27
+ end
28
+
29
+ row << element
30
+ row_length += element_length_with_separator
31
+ end
32
+
33
+ rows << row
34
+ rows
35
+ end
36
+
37
+ def self.ri( query )
38
+ results = Bri::Matcher.new( query ).find
39
+
40
+ if results.size == 0
41
+ "No matching results found"
42
+ elsif results.size == 1
43
+ results.first.to_s
44
+ else
45
+ qualified_methods = results.collect{ |result| result.full_name }.sort
46
+ ERB.new( Bri::Templates::MULTIPLE_CHOICES, nil, '<>' ).result( binding )
47
+ end
48
+ end
49
+
50
+ end
51
+
data/lib/bri/mall.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'rdoc/ri/paths'
2
+ require 'rdoc/ri/store'
3
+ require 'singleton'
4
+
5
+ module Bri
6
+ class Mall
7
+ include Singleton
8
+
9
+ attr_reader :stores
10
+
11
+ def classes
12
+ @stores.collect { |store| store.modules }.flatten.uniq.sort
13
+ end
14
+
15
+ private
16
+ def initialize
17
+ @stores = []
18
+
19
+ # We want: system, site, home and gem documentation
20
+ RDoc::RI::Paths.each( true, true, true, true ) do |path, type|
21
+ @stores << RDoc::RI::Store.new( path, type ).tap { |store| store.load_cache }
22
+ end
23
+ end
24
+
25
+ end
26
+ end
data/lib/bri/match.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'bri/match/base'
2
+ require 'bri/match/class'
3
+ require 'bri/match/method'
@@ -0,0 +1,53 @@
1
+ module Bri
2
+ module Match
3
+ class Base
4
+ def to_s
5
+ ERB.new( self.class.const_get( :TEMPLATE ), nil, '<>' ).
6
+ result( binding )
7
+ end
8
+
9
+ private
10
+ def build_description( source )
11
+ result = []
12
+ source.each do |element|
13
+ case element
14
+ when RDoc::Markup::Paragraph
15
+ result << reflow( element.text )
16
+ when RDoc::Markup::BlankLine
17
+ result << ""
18
+ when RDoc::Markup::Rule
19
+ result << "-" * Bri::WIDTH
20
+ when RDoc::Markup::Verbatim
21
+ result << element.text
22
+ when RDoc::Markup::Heading
23
+ result << ' ' * element.level + element.text
24
+ when RDoc::Markup::ListItem
25
+ result << "#{element.label} #{build_description( element.parts ).join}"
26
+ when RDoc::Markup::List
27
+ case element.type
28
+ when :NOTE, :LABEL
29
+ result << "Note:"
30
+ result << build_description( element.items ).join( "\n" )
31
+ when :NUMBER
32
+ result << "Numbered List:"
33
+ result << build_description( element.items ).join( "\n" )
34
+ when :BULLET
35
+ #FIXME: Add bullet symbol to each item
36
+ result << "Bulletet List:"
37
+ result << build_description( element.items ).join( "\n" )
38
+ else
39
+ raise "Don't know how to handle list type #{element.type}: #{element.inspect}"
40
+ end
41
+ else
42
+ raise "Don't know how to handle type #{element.class}: #{element.inspect}"
43
+ end
44
+ end
45
+ result
46
+ end
47
+
48
+ def reflow( text, width = Bri::WIDTH )
49
+ array_to_width( text.split( /\s+/ ), width, " ", 1 )
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,32 @@
1
+ require 'rdoc/markup'
2
+ require 'rdoc/markup/paragraph'
3
+
4
+ module Bri
5
+ module Match
6
+ class Class < Base
7
+ include Bri::Templates::Helpers
8
+ TEMPLATE = Bri::Templates::CLASS_DESCRIPTION
9
+
10
+ attr_reader :type, :name, :description_paragraphs
11
+ attr_reader :includes, :constants, :class_methods, :instance_methods
12
+ attr_reader :attributes
13
+
14
+ def initialize( rdoc_result )
15
+ @type = rdoc_result.type
16
+ @name = rdoc_result.name
17
+ @description_paragraphs = rdoc_result.comment.parts.collect { |p| p.parts.join( " " ) }
18
+ @includes = rdoc_result.includes.collect { |i| i.full_name }
19
+ @constants = rdoc_result.constants.collect { |c| { :name => c.name,
20
+ :value => c.value } }
21
+ @attributes = rdoc_result.attributes.collect { |a| "#{a.name} (#{a.rw})" }
22
+
23
+ class_methods, instance_methods = rdoc_result.method_list.
24
+ select {|m| m.visibility == :public }.
25
+ partition { |m| m.singleton }
26
+ @class_methods = class_methods.collect { |m| m.name }
27
+ @instance_methods = instance_methods.collect { |m| m.name }
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ module Bri
2
+ module Match
3
+ class Method < Base
4
+ include Bri::Templates::Helpers
5
+ TEMPLATE = Bri::Templates::METHOD_DESCRIPTION
6
+
7
+ attr_accessor :full_name, :call_syntaxes, :description_paragraphs
8
+
9
+ def initialize( rdoc_method )
10
+ @full_name = rdoc_method.full_name
11
+ @call_syntaxes = rdoc_method.call_seq.split( "\n" ).
12
+ map { |e| " " + e }.
13
+ join( "\n" ) + "\n" rescue ''
14
+ @description_paragraphs = build_description( rdoc_method.comment.parts )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module Bri
2
+ class Matcher
3
+ def initialize( term )
4
+ @term = term
5
+ end
6
+
7
+ def find
8
+ search_instance = create_search_instance( subject, @term )
9
+ search_instance.search( type )
10
+ search_instance.matches
11
+ end
12
+
13
+ def type
14
+ case @term
15
+ when /^[A-Z]/ then :fully_qualified
16
+ when /^[_a-z]/ then :unqualified
17
+ when /^[.#]/ then :partially_qualified
18
+ else :error
19
+ end
20
+ end
21
+
22
+ def subject
23
+ case @term
24
+ when /^[A-Z].*\./, /^\./ then :class_method
25
+ when /^[A-Z].*#/, /^#/ then :instance_method
26
+ when /^[A-Z][^.#]*/ then :module
27
+ else :method
28
+ end
29
+ end
30
+
31
+ private
32
+ def create_search_instance( type, term )
33
+ case type
34
+ when :module then Bri::Search::Class.new( term )
35
+ when :class_method then Bri::Search::ClassMethod.new( term )
36
+ when :instance_method then Bri::Search::InstanceMethod.new( term )
37
+ when :method then Bri::Search::InstanceMethod.new( term )
38
+ else nil # FIXME: Error handling
39
+ end
40
+ end
41
+ end
42
+ end
data/lib/bri/search.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'bri/search/base'
2
+ require 'bri/search/class'
3
+ require 'bri/search/method'
4
+ require 'bri/search/class_method'
5
+ require 'bri/search/instance_method'
@@ -0,0 +1,12 @@
1
+ module Bri
2
+ module Search
3
+ class Base
4
+ attr_reader :term, :matches
5
+
6
+ def initialize( term )
7
+ @term = term
8
+ @matches = []
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module Bri
2
+ module Search
3
+ class Class < Base
4
+
5
+ def search( type = :fully_qualified )
6
+ # NOTE: classes are only searched as fully qualified for the time being
7
+ # FIXME: What do we do if more than one store defines the same class?
8
+ store = Bri::Mall.instance.stores.detect { |s| s.modules.include? @term }
9
+ @matches << Bri::Match::Class.new( store.load_class( @term ) ) if store
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Bri
2
+ module Search
3
+ class ClassMethod < Method
4
+ private
5
+ def store_methods( store )
6
+ store.class_methods
7
+ end
8
+
9
+ def method_rdoc( store, klass = @class_term, method = @method_term )
10
+ store.load_method( klass, method )
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Bri
2
+ module Search
3
+ class InstanceMethod < Method
4
+ private
5
+ def store_methods( store )
6
+ store.instance_methods
7
+ end
8
+
9
+ def method_rdoc( store, klass = @class_term, method = @method_term )
10
+ store.load_method( klass, "#" + method )
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,84 @@
1
+ module Bri
2
+ module Search
3
+ class Method < Base
4
+ attr_reader :class_term, :method_term
5
+
6
+ def initialize( term )
7
+ super
8
+ @class_term, @method_term = term.split( /[\.#]/, 2 )
9
+
10
+ if @class_term !~ /^[A-Z]/ && @method_term.nil?
11
+ @method_term, @class_term = @class_term, @method_term
12
+ end
13
+
14
+ @class_term = nil if @class_term == ""
15
+ end
16
+
17
+ def search( type = :fully_qualified )
18
+ case type
19
+ when :fully_qualified then fully_qualified_search
20
+ when :partially_qualified then partially_qualified_search
21
+ when :unqualified then unqualified_search
22
+ else :error # TODO: Error handling
23
+ end
24
+ end
25
+
26
+ private
27
+ def fully_qualified_search
28
+ store = store_for_method
29
+
30
+ @matches << Bri::Match::Method.new( method_rdoc( store ) ) if store
31
+ end
32
+
33
+ def store_for_method
34
+ Bri::Mall.instance.stores.detect do |store|
35
+ store_methods( store ).has_key?( @class_term ) &&
36
+ store_methods( store )[@class_term].include?( @method_term )
37
+ end
38
+ end
39
+
40
+ def classes_with_method( store, method )
41
+ store_methods( store ).select { |klass, methods| methods.include? method }.keys
42
+ end
43
+
44
+ def candidates_from_method_re( store, method_re )
45
+ candidates = {}
46
+ store_methods( store ).each do |klass, methods|
47
+ matching_methods = methods.grep( method_re )
48
+ next if matching_methods.empty?
49
+ candidates[klass] = matching_methods
50
+ end
51
+ candidates
52
+ end
53
+
54
+
55
+ def partially_qualified_search
56
+ Bri::Mall.instance.stores.each do |store|
57
+ classes_with_method( store, @method_term ).each do |klass|
58
+ @matches << Bri::Match::Method.new( method_rdoc( store, klass, @method_term ) )
59
+ end
60
+ end
61
+ end
62
+
63
+ def unqualified_search
64
+ [ /^#{Regexp.escape @method_term}$/,
65
+ /^#{Regexp.escape @method_term}/,
66
+ /#{Regexp.escape @method_term}/ ].each do |method_re|
67
+ unqualified_search_worker( method_re )
68
+ break unless @matches.empty?
69
+ end
70
+ end
71
+
72
+ def unqualified_search_worker( method_re )
73
+ Bri::Mall.instance.stores.each do |store|
74
+ candidates_from_method_re( store, method_re ).each do |klass, methods|
75
+ methods.each do |method|
76
+ @matches << Bri::Match::Method.new( method_rdoc( store, klass, method ) )
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,109 @@
1
+ module Bri
2
+ module Templates
3
+ MULTIPLE_CHOICES =<<-EOT
4
+ <%= Bri::Templates::Helpers.hrule( "Multiple choices:" ) %>
5
+
6
+ <%= Bri::Templates::Helpers.array_to_width( qualified_methods.sort ) %>
7
+
8
+
9
+ EOT
10
+
11
+ CLASS_DESCRIPTION =<<-EOT
12
+ <%= hrule( type + ": " + name ) %>
13
+ <% if description_paragraphs.empty? %>
14
+ (no description...)
15
+ <% else %>
16
+ <% description_paragraphs.each do |paragraph| %>
17
+ <%= array_to_width( paragraph.split( /\s+/ ), 72, " ") %>
18
+ <% end %>
19
+ <% end %>
20
+
21
+ <%= hrule %>
22
+
23
+ <% if !includes.empty? %>
24
+ <%= section_header( "Includes:" ) %>
25
+ <%= array_to_width( includes.sort ) %>
26
+
27
+
28
+ <% end %>
29
+ <% if !constants.empty? %>
30
+ <%= section_header( "Constants:" ) %>
31
+ <%= array_to_width( constants.sort ) %>
32
+
33
+
34
+ <% end %>
35
+ <% if !class_methods.empty? %>
36
+ <%= section_header( "Class methods:" ) %>
37
+ <%= array_to_width( class_methods.sort ) %>
38
+
39
+
40
+ <% end %>
41
+ <% if !instance_methods.empty? %>
42
+ <%= section_header( "Instance methods:" ) %>
43
+ <%= array_to_width( instance_methods.sort ) %>
44
+
45
+
46
+ <% end %>
47
+ <% if !attributes.empty? %>
48
+ <%= section_header( "Attributes:" ) %>
49
+ <%= array_to_width( attributes.sort ) %>
50
+
51
+
52
+ <% end %>
53
+ EOT
54
+
55
+ METHOD_DESCRIPTION =<<-EOT
56
+ <%= hrule( full_name ) %>
57
+ <%= call_syntaxes %>
58
+ <%= hrule %>
59
+ <% if description_paragraphs.empty? %>
60
+ (no description...)
61
+ <% else %>
62
+ <%= description_paragraphs.join( "\n" ) %>
63
+ <% end %>
64
+
65
+ EOT
66
+
67
+ module Helpers
68
+ def hrule( text = '', width = Bri::WIDTH )
69
+ '-' * ( width - text.length - 1 ) + " " +
70
+ Term::ANSIColor::bold + text + Term::ANSIColor::reset +
71
+ "\n"
72
+ end
73
+ module_function :hrule
74
+
75
+ def section_header( text )
76
+ Term::ANSIColor::green + Term::ANSIColor::underline + text + Term::ANSIColor::reset + "\n"
77
+ end
78
+ module_function :section_header
79
+
80
+ def array_to_width( array, width = Bri::WIDTH, separator = ", ", indent_steps = 1 )
81
+ indentation = ' '
82
+ rows = '' + indentation * indent_steps
83
+ row = ''
84
+ row_length = 0
85
+
86
+ array = add_separators( array, separator )
87
+
88
+ array.each do |element|
89
+ if row.length + element.length >= width
90
+ rows << row + "\n" + indentation * indent_steps
91
+ row = ''
92
+ end
93
+
94
+ row << element
95
+ end
96
+
97
+ rows << row
98
+ rows
99
+ end
100
+ module_function :array_to_width
101
+
102
+ def add_separators( array, separator )
103
+ last_element = array.pop
104
+ array.map { |e| e + separator } + [ last_element ]
105
+ end
106
+ module_function :add_separators
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Mall do
4
+ # NOTE the specs here are commented out until I figure out how to properly
5
+ # test singletons. Otherwise specs will fail in a bulk run while
6
+ # running fine on their own
7
+ subject { Bri::Mall.instance }
8
+
9
+ before( :each ) do
10
+ RDoc::RI::Paths.stub!( :each ).
11
+ and_yield( "store1_path", "store1_type" ).
12
+ and_yield( "store2_path", "store2_type" )
13
+ RDoc::RI::Store.stub!( :new ).
14
+ and_return { mock( RDoc::RI::Store, :load_cache=> true ) }
15
+ end
16
+
17
+ # describe "the instance" do
18
+
19
+ # its( :stores ) { should have(2).objects }
20
+ # end
21
+
22
+ # describe "#classes" do
23
+ # it "should query all stores for their modules" do
24
+ # subject.stores.each do |store|
25
+ # store.should_receive( :modules ).and_return( true )
26
+ # end
27
+
28
+ # subject.classes
29
+ # end
30
+
31
+ # it "should return a sorted array of unique class names" do
32
+ # subject.stores.first.stub!( :modules => [ "C", "B", "A" ] )
33
+ # subject.stores.last.stub!( :modules => [ "Z", "B", "C" ] )
34
+ # subject.classes.should == [ "A", "B", "C", "Z" ]
35
+ # end
36
+ # end
37
+
38
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Match::Class do
4
+ let( :fake_paragraph ) do
5
+ mock( RDoc::Markup::Paragraph, :parts => [ "This is row one",
6
+ "And this is row 2" ] )
7
+ end
8
+
9
+ let( :fake_description ) do
10
+ mock( RDoc::Markup::Document, :parts => [ fake_paragraph ] )
11
+ end
12
+
13
+ let( :fake_include ) do
14
+ mock( RDoc::Include, :full_name => "Included::Module" )
15
+ end
16
+
17
+ let( :fake_constant ) do
18
+ mock( RDoc::Constant, :name => "MockConstant", :value => "This is my value" )
19
+ end
20
+
21
+ let( :fake_attribute ) do
22
+ mock( RDoc::Constant, :name => "attribute", :rw => 'R' )
23
+ end
24
+
25
+ let( :fake_public_instance_method ) do
26
+ mock( RDoc::AnyMethod, :name => "public_instance",
27
+ :singleton => false,
28
+ :visibility => :public )
29
+ end
30
+
31
+ let( :fake_protected_instance_method ) do
32
+ mock( RDoc::AnyMethod, :name => "protected_instance",
33
+ :singleton => false,
34
+ :visibility => :protected )
35
+ end
36
+
37
+ let( :fake_private_instance_method ) do
38
+ mock( RDoc::AnyMethod, :name => "private_instance",
39
+ :singleton => false,
40
+ :visibility => :private )
41
+ end
42
+
43
+ let( :fake_public_class_method ) do
44
+ mock( RDoc::AnyMethod, :name => "public_class",
45
+ :singleton => true,
46
+ :visibility => :public )
47
+ end
48
+
49
+ let( :fake_protected_class_method ) do
50
+ mock( RDoc::AnyMethod, :name => "protected_class",
51
+ :singleton => true,
52
+ :visibility => :protected )
53
+ end
54
+
55
+ let( :fake_private_class_method ) do
56
+ mock( RDoc::AnyMethod, :name => "private_class",
57
+ :singleton => true,
58
+ :visibility => :private )
59
+ end
60
+
61
+ let( :rdoc_class ) { mock( RDoc::NormalClass, :type => "module",
62
+ :name => "MyModule",
63
+ :comment => fake_description,
64
+ :includes => [ fake_include ],
65
+ :constants => [ fake_constant ],
66
+ :attributes => [ fake_attribute ],
67
+ :method_list => [ fake_public_instance_method,
68
+ fake_protected_instance_method,
69
+ fake_private_instance_method,
70
+ fake_public_class_method,
71
+ fake_protected_class_method,
72
+ fake_private_class_method ]
73
+ )
74
+ }
75
+
76
+ describe "#initialize" do
77
+ context "a class with everything" do
78
+ subject { Bri::Match::Class.new( rdoc_class ) }
79
+
80
+ its( :type ) { should == rdoc_class.type }
81
+ its( :name ) { should == rdoc_class.name }
82
+ its( :description_paragraphs ) { should == fake_description.parts.collect { |p| p.parts.join( " " ) } }
83
+ its( :includes ) { should == rdoc_class.includes.collect{ |i| i.full_name } }
84
+ its( :constants ) { should == rdoc_class.constants.collect { |c| { :name => c.name, :value => c.value } } }
85
+ its( :attributes ) { should == rdoc_class.attributes.collect { |a| "#{a.name} (#{a.rw})" } }
86
+ its( :instance_methods ) { should == rdoc_class.method_list.select { |m| m.visibility == :public && m.singleton == false }.collect { |m| m.name } }
87
+ its( :class_methods ) { should == rdoc_class.method_list.select { |m| m.visibility == :public && m.singleton == true }.collect { |m| m.name } }
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Match::Method do
4
+ let( :fake_paragraph ) do
5
+ RDoc::Markup::Paragraph.new "This is line one", "This is line two"
6
+ end
7
+
8
+ let( :fake_description ) do
9
+ mock( RDoc::Markup::Document, :parts => [ fake_paragraph ] )
10
+ end
11
+
12
+ let( :rdoc_method ) do
13
+ mock( RDoc::AnyMethod, :full_name => "This::IS::My.full_name",
14
+ :call_seq => "First\nSecond\nThird",
15
+ :comment => fake_description )
16
+ end
17
+
18
+ describe "#initialize" do
19
+ subject { Bri::Match::Method.new( rdoc_method ) }
20
+
21
+ its( :full_name ) { should == rdoc_method.full_name }
22
+ its( :call_syntaxes ) { should == " First\n Second\n Third\n" }
23
+ its( :description_paragraphs ) { should == [ " This is line one This is line two" ] }
24
+ end
25
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Matcher do
4
+ describe "#type" do
5
+
6
+ context "the query term begins with a capital" do
7
+ subject { Bri::Matcher.new( "Foo" ) }
8
+ its( :type ) { should == :fully_qualified }
9
+ end
10
+
11
+ context "the query term begins with a lower case letter" do
12
+ subject { Bri::Matcher.new( "foo" ) }
13
+ its( :type ) { should == :unqualified }
14
+ end
15
+
16
+ context "the query term begins with a _" do
17
+ subject { Bri::Matcher.new( "_foo" ) }
18
+ its( :type ) { should == :unqualified }
19
+ end
20
+
21
+ context "the query begins with a ." do
22
+ subject { Bri::Matcher.new( ".foo" ) }
23
+ its( :type ) { should == :partially_qualified }
24
+ end
25
+
26
+ context "the query begins with a #" do
27
+ subject { Bri::Matcher.new( "#foo" ) }
28
+ its( :type ) { should == :partially_qualified }
29
+ end
30
+
31
+ context "it begins with a character other than _, ., #, or a letter" do
32
+ subject { Bri::Matcher.new( "2134" ) }
33
+ its( :type ) { should == :error }
34
+ end
35
+ end
36
+
37
+ describe "#subject" do
38
+ context "the term begins with a capital letter" do
39
+ context "and the term contains a ." do
40
+ subject { Bri::Matcher.new( "Foo.bar" ) }
41
+ its( :subject ) { should == :class_method }
42
+ end
43
+
44
+ context "and the term contains a #" do
45
+ subject { Bri::Matcher.new( "Foo#bar" ) }
46
+ its( :subject ) { should == :instance_method }
47
+ end
48
+
49
+ context "and the term contains neither . nor #" do
50
+ subject { Bri::Matcher.new( "FooBar" ) }
51
+ its( :subject ) { should == :module }
52
+ end
53
+ end
54
+ end
55
+
56
+ context "the term begins with a ." do
57
+ subject { Bri::Matcher.new( ".foo" ) }
58
+ its( :subject ) { should == :class_method }
59
+ end
60
+
61
+ context "the term begins with a #" do
62
+ subject { Bri::Matcher.new( "#foo" ) }
63
+ its( :subject ) { should == :instance_method }
64
+ end
65
+
66
+ context "the term begins with neither a capital letter nor . or #" do
67
+ subject { Bri::Matcher.new( "foo" ) }
68
+ its( :subject ) { should == :method }
69
+ end
70
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Search::ClassMethod do
4
+ context "the searches" do
5
+ let( :paragraph ) { RDoc::Markup::Paragraph.new( "Foo Description" ) }
6
+ let( :document ) { mock( RDoc::Markup::Document, :parts => [ paragraph ] ) }
7
+ let( :rdoc_method ) { mock( RDoc::AnyMethod, :full_name => "Foo",
8
+ :call_seq => "",
9
+ :comment => document ) }
10
+ before( :each ) do
11
+ store_one = mock( RDoc::RI::Store, :load_cache => true,
12
+ :load_class => true,
13
+ :load_method => rdoc_method,
14
+ :modules => %w{ ClassThree },
15
+ :class_methods => { "ClassThree" => [ "method" ] } )
16
+ store_two = mock( RDoc::RI::Store, :load_cache => true,
17
+ :load_class => true,
18
+ :load_method => rdoc_method,
19
+ :modules => %w{ ClassOne ClassTwo },
20
+ :class_methods => { "ClassOne" => [ "method" ],
21
+ "ClassTwo" => [ "method", "my_other_method" ] } )
22
+ Bri::Mall.instance.stub!( :stores => [ store_one, store_two ] )
23
+ Bri::Match::Class.stub!( :new ).and_return( mock( Bri::Match::Class ) )
24
+ end
25
+
26
+ describe "a fully qualified search" do
27
+ context "if there are no matching methods in any store" do
28
+ subject { Bri::Search::ClassMethod.new( "I::Dont::Exist.go_away" ) }
29
+ it "should have no matches" do
30
+ subject.search( :fully_qualified )
31
+ subject.matches.should == []
32
+ end
33
+ end
34
+
35
+ context "if there are matching methods in the stores" do
36
+ subject { Bri::Search::ClassMethod.new( "ClassOne.method" ) }
37
+ it "should have a match for each method" do
38
+ subject.search( :fully_qualified )
39
+ subject.matches.size.should == 1
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "a partially qualified search" do
45
+ context "if there are no matching methods in any store" do
46
+ subject { Bri::Search::ClassMethod.new( ".go_away" ) }
47
+ it "should have no matches" do
48
+ subject.search( :partially_qualified )
49
+ subject.matches.should == []
50
+ end
51
+ end
52
+
53
+ context "if there are matching methods in the stores" do
54
+ subject { Bri::Search::ClassMethod.new( ".method" ) }
55
+ it "should have a match for each method" do
56
+ subject.search( :partially_qualified )
57
+ subject.matches.size.should == 3
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "an unqualified search" do
63
+ context "if there are no matching methods in any store" do
64
+ subject { Bri::Search::ClassMethod.new( "go_away" ) }
65
+ it "should have no matches" do
66
+ subject.search( :unqualified )
67
+ subject.matches.should == []
68
+ end
69
+ end
70
+
71
+ context "if there are matching methods in the stores" do
72
+ context "if there are matching methods, where the match starts at the beginning of the method name" do
73
+ subject { Bri::Search::ClassMethod.new( "method" ) }
74
+ it "should have a match for each method" do
75
+ subject.search( :unqualified )
76
+ subject.matches.size.should == 3
77
+ end
78
+ end
79
+
80
+ context "if there are matching methods, but none where the match starts at the beginning of the method name" do
81
+ subject { Bri::Search::ClassMethod.new( "other" ) }
82
+ it "should have a match for each method" do
83
+ subject.search( :unqualified )
84
+ subject.matches.size.should == 1
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Search::Class do
4
+ before( :each ) do
5
+ store_one = mock( RDoc::RI::Store, :load_cache => true,
6
+ :load_class => true,
7
+ :modules => %w{ ClassThree } )
8
+ store_two = mock( RDoc::RI::Store, :load_cache => true,
9
+ :load_class => true,
10
+ :modules => %w{ ClassOne ClassTwo } )
11
+ Bri::Mall.instance.stub!( :stores => [ store_one, store_two ] )
12
+ Bri::Match::Class.stub!( :new ).and_return( mock( Bri::Match::Class ) )
13
+ end
14
+
15
+ describe "#search" do
16
+ context "if there are no matching modules in any store" do
17
+ subject { Bri::Search::Class.new( "I::Dont::Exist" ) }
18
+ it "should have no matches" do
19
+ subject.search
20
+ subject.matches.should == []
21
+ end
22
+ end
23
+
24
+ context "if there is a matching module in the stores" do
25
+ subject { Bri::Search::Class.new( "ClassOne" ) }
26
+ it "should have a match for each name" do
27
+ subject.search
28
+ subject.matches.size.should == 1
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Search::InstanceMethod do
4
+ context "the searches" do
5
+ let( :paragraph ) { RDoc::Markup::Paragraph.new( "Foo Description" ) }
6
+ let( :document ) { mock( RDoc::Markup::Document, :parts => [ paragraph ] ) }
7
+ let( :rdoc_method ) { mock( RDoc::AnyMethod, :full_name => "Foo",
8
+ :call_seq => "",
9
+ :comment => document ) }
10
+ before( :each ) do
11
+ store_one = mock( RDoc::RI::Store, :load_cache => true,
12
+ :load_class => true,
13
+ :load_method => rdoc_method,
14
+ :modules => %w{ ClassThree },
15
+ :instance_methods => { "ClassThree" => [ "method" ] } )
16
+ store_two = mock( RDoc::RI::Store, :load_cache => true,
17
+ :load_class => true,
18
+ :load_method => rdoc_method,
19
+ :modules => %w{ ClassOne ClassTwo },
20
+ :instance_methods => { "ClassOne" => [ "method" ],
21
+ "ClassTwo" => [ "method", "my_other_method" ] } )
22
+ Bri::Mall.instance.stub!( :stores => [ store_one, store_two ] )
23
+ Bri::Match::Class.stub!( :new ).and_return( mock( Bri::Match::Class ) )
24
+ end
25
+
26
+ describe "a fully qualified search" do
27
+ context "if there are no matching methods in any store" do
28
+ subject { Bri::Search::InstanceMethod.new( "I::Dont::Exist#go_away" ) }
29
+ it "should have no matches" do
30
+ subject.search( :fully_qualified )
31
+ subject.matches.should == []
32
+ end
33
+ end
34
+
35
+ context "if there are matching methods in the stores" do
36
+ subject { Bri::Search::InstanceMethod.new( "ClassOne#method" ) }
37
+ it "should have a match for each method" do
38
+ subject.search( :fully_qualified )
39
+ subject.matches.size.should == 1
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "a partially qualified search" do
45
+ context "if there are no matching methods in any store" do
46
+ subject { Bri::Search::InstanceMethod.new( "#go_away" ) }
47
+ it "should have no matches" do
48
+ subject.search( :partially_qualified )
49
+ subject.matches.should == []
50
+ end
51
+ end
52
+
53
+ context "if there are matching methods in the stores" do
54
+ subject { Bri::Search::InstanceMethod.new( "#method" ) }
55
+ it "should have a match for each method" do
56
+ subject.search( :partially_qualified )
57
+ subject.matches.size.should == 3
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "an unqualified search" do
63
+ context "if there are no matching methods in any store" do
64
+ subject { Bri::Search::InstanceMethod.new( "go_away" ) }
65
+ it "should have no matches" do
66
+ subject.search( :unqualified )
67
+ subject.matches.should == []
68
+ end
69
+ end
70
+
71
+ context "if there are matching methods in the stores" do
72
+ context "if there are matching methods, where the match starts at the beginning of the method name" do
73
+ subject { Bri::Search::InstanceMethod.new( "method" ) }
74
+ it "should have a match for each method" do
75
+ subject.search( :unqualified )
76
+ subject.matches.size.should == 3
77
+ end
78
+ end
79
+
80
+ context "if there are matching methods, but none where the match starts at the beginning of the method name" do
81
+ subject { Bri::Search::InstanceMethod.new( "other" ) }
82
+ it "should have a match for each method" do
83
+ subject.search( :unqualified )
84
+ subject.matches.size.should == 1
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bri::Search::Method do
4
+ describe "#initialize" do
5
+ context "the searchterm is a class" do
6
+ subject { Bri::Search::Method.new( "Class" ) }
7
+ its( :class_term ) { should == "Class" }
8
+ its( :method_term ) { should be_nil }
9
+ end
10
+
11
+ context "the search term is a fully qualified class method" do
12
+ subject { Bri::Search::Method.new( "Class.method" ) }
13
+ its( :class_term ) { should == "Class" }
14
+ its( :method_term ) { should == "method" }
15
+ end
16
+
17
+ context "the search term is a fully qualified instance method" do
18
+ subject { Bri::Search::Method.new( "Class#method" ) }
19
+ its( :class_term ) { should == "Class" }
20
+ its( :method_term ) { should == "method" }
21
+ end
22
+
23
+ context "the search term begins with a ." do
24
+ subject { Bri::Search::Method.new( ".method" ) }
25
+ its( :class_term ) { should be_nil }
26
+ its( :method_term ) { should == "method" }
27
+ end
28
+
29
+ context "the search term begins with a #" do
30
+ subject { Bri::Search::Method.new( "#method" ) }
31
+ its( :class_term ) { should be_nil }
32
+ its( :method_term ) { should == "method" }
33
+ end
34
+
35
+ context "the search term is not a class and does not contain a . or #" do
36
+ subject { Bri::Search::Method.new( "method" ) }
37
+ its( :class_term ) { should be_nil }
38
+ its( :method_term ) { should == "method" }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1 @@
1
+ require File.join( File.dirname( __FILE__ ), '..', 'lib', 'bri.rb' )
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bri
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - Sven Riedel
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-19 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: term-ansicolor
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ - 5
32
+ version: 1.0.5
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rdoc
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 2
45
+ - 5
46
+ - 0
47
+ version: 2.5.0
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ description: An alternative to the ri command
51
+ email: sr@gimp.org
52
+ executables:
53
+ - bri
54
+ extensions: []
55
+
56
+ extra_rdoc_files:
57
+ - README
58
+ files:
59
+ - README
60
+ - TODO
61
+ - bin/bri
62
+ - lib/bri.rb
63
+ - lib/bri/mall.rb
64
+ - lib/bri/matcher.rb
65
+ - lib/bri/match.rb
66
+ - lib/bri/match/base.rb
67
+ - lib/bri/match/class.rb
68
+ - lib/bri/match/method.rb
69
+ - lib/bri/search.rb
70
+ - lib/bri/search/base.rb
71
+ - lib/bri/search/class.rb
72
+ - lib/bri/search/method.rb
73
+ - lib/bri/search/class_method.rb
74
+ - lib/bri/search/instance_method.rb
75
+ - lib/bri/templates.rb
76
+ - spec/spec_helper.rb
77
+ - spec/lib/bri/mall_spec.rb
78
+ - spec/lib/bri/matcher_spec.rb
79
+ - spec/lib/bri/match/class_match_spec.rb
80
+ - spec/lib/bri/match/method_match_spec.rb
81
+ - spec/lib/bri/search/class_spec.rb
82
+ - spec/lib/bri/search/class_method_search_spec.rb
83
+ - spec/lib/bri/search/instance_method_spec.rb
84
+ - spec/lib/bri/search/method_spec.rb
85
+ has_rdoc: true
86
+ homepage:
87
+ licenses: []
88
+
89
+ post_install_message:
90
+ rdoc_options:
91
+ - --charset=UTF-8
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 1
101
+ - 9
102
+ - 2
103
+ version: 1.9.2
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ requirements: []
113
+
114
+ rubyforge_project:
115
+ rubygems_version: 1.3.7
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: Beautified RI in the spirit of fastri/qri. Unlike fastri, bri builds on top of the rdoc 2.x backend, only output and formatting is handled by bri
119
+ test_files: []
120
+