bri 0.4.4 → 1.0.0.pre.beta1

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/TODO +2 -3
  3. data/bin/bri +21 -7
  4. data/lib/bri.rb +18 -15
  5. data/lib/bri/mall.rb +12 -14
  6. data/lib/bri/match/base.rb +1 -1
  7. data/lib/bri/match/class.rb +5 -1
  8. data/lib/bri/match/method.rb +2 -1
  9. data/lib/bri/renderer.rb +28 -188
  10. data/lib/bri/renderer/blank_line.rb +9 -0
  11. data/lib/bri/renderer/default.rb +27 -0
  12. data/lib/bri/renderer/document.rb +11 -0
  13. data/lib/bri/renderer/heading.rb +9 -0
  14. data/lib/bri/renderer/list.rb +24 -0
  15. data/lib/bri/renderer/list/base.rb +18 -0
  16. data/lib/bri/renderer/list/bullet.rb +15 -0
  17. data/lib/bri/renderer/list/labeled.rb +15 -0
  18. data/lib/bri/renderer/list/lower_lettered.rb +18 -0
  19. data/lib/bri/renderer/list/note.rb +15 -0
  20. data/lib/bri/renderer/list/numbered.rb +18 -0
  21. data/lib/bri/renderer/list/upper_lettered.rb +18 -0
  22. data/lib/bri/renderer/list_item.rb +24 -0
  23. data/lib/bri/renderer/paragraph.rb +11 -0
  24. data/lib/bri/renderer/result.rb +73 -0
  25. data/lib/bri/renderer/rule.rb +9 -0
  26. data/lib/bri/renderer/verbatim.rb +14 -0
  27. data/lib/bri/search/class.rb +3 -1
  28. data/lib/bri/search/method.rb +3 -3
  29. data/lib/bri/templates.rb +7 -38
  30. data/lib/bri/text_formatting_utils.rb +92 -0
  31. metadata +19 -12
  32. data/spec/bri_dummy_spec_class.rb +0 -132
  33. data/spec/lib/bri/mall_spec.rb +0 -38
  34. data/spec/lib/bri/match/class_spec.rb +0 -125
  35. data/spec/lib/bri/match/method_spec.rb +0 -112
  36. data/spec/lib/bri/matcher_spec.rb +0 -70
  37. data/spec/lib/bri/renderer_spec.rb +0 -338
  38. data/spec/lib/bri/search/class_method_spec.rb +0 -172
  39. data/spec/lib/bri/search/class_spec.rb +0 -66
  40. data/spec/lib/bri/search/instance_method_spec.rb +0 -173
  41. data/spec/lib/bri/search/method_spec.rb +0 -41
  42. data/spec/spec_helper.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74b87ae62d01b5be9164734271754be0cc3a1ef68ad3b35bd78b633d829a529a
4
- data.tar.gz: 27fdfe717c1cea3b49525ff5e9c59b462757d1d86db440bd4dc1fd9719f47c70
3
+ metadata.gz: 2a26dfbcd940347c2bf68246c1223702a30ae82cc6ff032fd9160f4f6cd2587f
4
+ data.tar.gz: ad88f5eb0b894300eb1f8073da1baf4444ebebd07aa992d772465044f1a6d444
5
5
  SHA512:
6
- metadata.gz: e0d96c3ae752ec0b5b3fb59ad58da596869fd91665282eeb588ba8c03041b3f26040f331189b9db84a6d55aaf5e5540430dddbd07c925a7dde198ed6939bc7f0
7
- data.tar.gz: 4f3cc64561cb91cc53caf689611c32f6daf8d0482eb2bee3407358fad32fd808e0b70ce613c979b57917c0c2afe4b135f48f46e19de8888a167591d205aadecc
6
+ metadata.gz: c258a7980e40af727d7d543f70d14398df03019be7496116180d6c6812e5becbad29bde410d26983b49ec6617cbb477c73ed357ef18cf60e72ab362fce914ec1
7
+ data.tar.gz: 9cbe6dc1a11b9cc745ce75b8f602416dbba701bcb0a22f0c973d15375875cf23d67faa1b03836d63595752a189cbccacb4c6d943a0464a2ef616cf4254b2b6a0
data/TODO CHANGED
@@ -1,7 +1,4 @@
1
1
  - Extend unqualified search to include class methods and case insensitive searches
2
- - {multi word label}[links] won't display correctly if the label is right where
3
- a line wrap occurs
4
- - Refactor the convoluted rendering of lists and list items
5
2
  - Detect ansi capabilities and use what is possible with graceful degradation?
6
3
  - Potentially try to detect method references in documentation prose and
7
4
  highlight these (e.g. Object#send and Object.new)
@@ -9,3 +6,5 @@
9
6
  - Add display of module constant aliases
10
7
  - Rewrite the search code into something understandable and maintainable
11
8
  (sleep deprivation is one hell of a drug)
9
+ - Add UTF8 rendering mode
10
+ - Add --stats switch to see timing data
data/bin/bri CHANGED
@@ -20,12 +20,26 @@ def parse_options
20
20
  opts.separator " * #instance_method_name"
21
21
  opts.separator " * .class_method_name"
22
22
  opts.separator ""
23
- opts.on( nil, "--classes", "List known classes" ) { |v| @options[:list_classes] = true }
24
- opts.on( nil, "--methods", "List known methods" ) { |v| @options[:list_methods] = true }
25
- opts.on( "-l", "--list-names", "List known namespaces/methods" ) { |v| @options[:list_names] = true }
26
- opts.on( "-w", "--width [COLUMNS]", "Set the output width", Integer ) { |v| Bri.width = v.to_i - 8 }
27
- opts.on( "-a", "--all", "Output all documentation for the term. Prefers core documents otherwise") { |v| @options[:show_all] = true }
28
- opts.on_tail( "-h", "--help", "This help text" ) { puts opts; exit }
23
+ opts.on( nil, "--classes", "List known classes" ) do |v|
24
+ @options[:list_classes] = true
25
+ end
26
+ opts.on( nil, "--methods", "List known methods" ) do |v|
27
+ @options[:list_methods] = true
28
+ end
29
+ opts.on( "-l", "--list-names", "List known namespaces/methods" ) do |v|
30
+ @options[:list_names] = true
31
+ end
32
+ opts.on( "-w", "--width [COLUMNS]", "Set the output width", Integer ) do |v|
33
+ Bri.width = v.to_i - 8
34
+ end
35
+ opts.on( "-a", "--all",
36
+ "Output gem documentation in addition to core documents" ) do |v|
37
+ @options[:show_all] = true
38
+ end
39
+ opts.on_tail( "-h", "--help", "This help text" ) do
40
+ puts opts
41
+ exit
42
+ end
29
43
  end
30
44
  parser.parse!( ARGV )
31
45
 
@@ -45,5 +59,5 @@ elsif @options[:list_methods]
45
59
  elsif @options[:list_names]
46
60
  puts Bri.list_names
47
61
  else
48
- puts Bri.ri( ARGV[0], show_all: @options[:show_all] )
62
+ puts Bri.ri( ARGV[0], @options )
49
63
  end
data/lib/bri.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'erb'
2
2
  require 'term/ansicolor'
3
3
 
4
+ require_relative 'bri/text_formatting_utils'
4
5
  require_relative 'bri/renderer'
5
6
  require_relative 'bri/mall'
6
7
  require_relative 'bri/matcher'
@@ -11,22 +12,24 @@ require_relative 'bri/match'
11
12
  module Bri
12
13
  DEFAULT_WIDTH = 72
13
14
 
14
- def self.ri( query, show_all: false )
15
+ def self.ri( query, options )
16
+ if options[:show_all]
17
+ Bri::Mall.ri_paths( system: true, site: true, home: true, gems: true )
18
+ else
19
+ Bri::Mall.ri_paths( system: true, site: true, home: true, gems: false )
20
+ end
21
+
15
22
  results = Bri::Matcher.new( query ).find
16
23
 
17
24
  if results.size == 0
18
25
  "No matching results found"
26
+
19
27
  elsif results.size == 1
20
28
  results.first.to_s
29
+
21
30
  elsif results.all? { |r| r.is_a?(Bri::Match::Class) }
22
- if show_all
23
- results.map(&:to_s)
24
- else
25
- gem_docs, core_docs = results.partition { |r| r.origin =~ %r{gem\b} }
26
-
27
- docs_to_output = core_docs.empty? ? gem_docs : core_docs
28
- docs_to_output.map(&:to_s)
29
- end
31
+ results.map(&:to_s)
32
+
30
33
  else
31
34
  qualified_methods = results.map(&:full_name).sort
32
35
  ERB.new( Bri::Templates::MULTIPLE_CHOICES, nil, '<>' ).result( binding )
@@ -47,18 +50,18 @@ module Bri
47
50
  end
48
51
 
49
52
  def self.list_classes
50
- Bri::Mall.instance.classes.join("\n" )
53
+ Bri::Mall.classes.join("\n" )
51
54
  end
52
55
 
53
56
  def self.list_methods
54
- ( Bri::Mall.instance.instance_methods +
55
- Bri::Mall.instance.class_methods ).sort.join( "\n" )
57
+ ( Bri::Mall.instance_methods +
58
+ Bri::Mall.class_methods ).sort.join( "\n" )
56
59
  end
57
60
 
58
61
  def self.list_names
59
- ( Bri::Mall.instance.classes +
60
- Bri::Mall.instance.instance_methods +
61
- Bri::Mall.instance.class_methods ).sort.join( "\n" )
62
+ ( Bri::Mall.classes +
63
+ Bri::Mall.instance_methods +
64
+ Bri::Mall.class_methods ).sort.join( "\n" )
62
65
  end
63
66
 
64
67
  end
@@ -1,18 +1,24 @@
1
1
  require 'rdoc/ri/paths'
2
2
  require 'rdoc/ri/store'
3
- require 'singleton'
4
3
 
5
4
  module Bri
6
5
  class Mall
7
- include Singleton
8
6
 
9
- attr_reader :stores
7
+ def self.ri_paths( system: true, site: true, home: true, gems: true )
8
+ @ri_paths ||= RDoc::RI::Paths.each( system, site, home, gems )
9
+ end
10
+
11
+ def self.stores
12
+ @stores ||= ri_paths.each_with_object( [] ) do |(path, type), stores|
13
+ stores << RDoc::Store.new( path, type ).tap { |store| store.load_cache }
14
+ end
15
+ end
10
16
 
11
- def classes
17
+ def self.classes
12
18
  stores.flat_map(&:module_names).uniq.sort
13
19
  end
14
20
 
15
- def class_methods
21
+ def self.class_methods
16
22
  stores.each_with_object( [] ) do |store, result|
17
23
  store.class_methods.each do |klass, methods|
18
24
  methods.each { |method| result << "#{klass}.#{method}" }
@@ -20,20 +26,12 @@ module Bri
20
26
  end.uniq
21
27
  end
22
28
 
23
- def instance_methods
29
+ def self.instance_methods
24
30
  stores.each_with_object( [] ) do |store, result|
25
31
  store.instance_methods.each do |klass, methods|
26
32
  methods.each { |method| result << "#{klass}##{method}" }
27
33
  end
28
34
  end.uniq
29
35
  end
30
-
31
- private
32
- def initialize
33
- # We want: system, site, home and gem documentation
34
- @stores = RDoc::RI::Paths.each( true, true, true, true ).each_with_object( [] ) do |(path, type), stores|
35
- stores << RDoc::Store.new( path, type ).tap { |store| store.load_cache }
36
- end
37
- end
38
36
  end
39
37
  end
@@ -8,7 +8,7 @@ module Bri
8
8
 
9
9
  private
10
10
  def build_description( source )
11
- source.map { |element| Bri::Renderer.render( element ) }.compact
11
+ source.map { |element| Bri::Renderer.new( element ).render }.compact.map(&:output)
12
12
  end
13
13
  end
14
14
  end
@@ -4,7 +4,11 @@ require 'rdoc/markup/paragraph'
4
4
  module Bri
5
5
  module Match
6
6
  class Class < Base
7
- include Bri::Templates::Helpers
7
+ # FIXME This should not be part of this class; the template may need
8
+ # a modiified binding.
9
+ #
10
+ include Bri::TextFormattingUtils
11
+
8
12
  TEMPLATE = Bri::Templates::CLASS_DESCRIPTION
9
13
 
10
14
  attr_reader :type, :name, :description_paragraphs,
@@ -1,7 +1,8 @@
1
1
  module Bri
2
2
  module Match
3
3
  class Method < Base
4
- include Bri::Templates::Helpers
4
+ include Bri::TextFormattingUtils
5
+
5
6
  TEMPLATE = Bri::Templates::METHOD_DESCRIPTION
6
7
 
7
8
  attr_accessor :full_name, :call_syntaxes, :description_paragraphs, :origin
@@ -1,195 +1,35 @@
1
1
  require 'strscan'
2
+ require 'rdoc'
3
+ require 'rdoc/markup'
4
+
5
+ require_relative 'renderer/default'
6
+ require_relative 'renderer/blank_line'
7
+ require_relative 'renderer/document'
8
+ require_relative 'renderer/heading'
9
+ require_relative 'renderer/list_item'
10
+ require_relative 'renderer/list'
11
+ require_relative 'renderer/paragraph'
12
+ require_relative 'renderer/rule'
13
+ require_relative 'renderer/verbatim'
14
+ require_relative 'renderer/result'
2
15
 
3
16
  module Bri
4
17
  module Renderer
5
- Color = ::Term::ANSIColor
6
-
7
- INDENT = ' ' * 2
8
- INDENT_WIDTH = 2
9
- LOWER_ALPHABET = ('a'..'z').to_a.map { |char| "#{char}." }.freeze
10
- UPPER_ALPHABET = ('A'..'Z').to_a.map { |char| "#{char}." }.freeze
11
-
12
- def self.render( element, width = Bri.width, alignment_width = 0 )
13
- case element
14
- when RDoc::Markup::Verbatim
15
- text = extract_text( element, width )
16
- styled_text = replace_markup( text )
17
- "#{indent( styled_text )}\n"
18
-
19
- when RDoc::Markup::List
20
- item_width = width - INDENT_WIDTH
21
- case element.type
22
- when :BULLET
23
- rendered_items = element.items.map { |item| render( item, item_width ) }
24
- rendered_items.map! { |item| item.gsub( /\n/, "\n#{INDENT}" ) }
25
- rendered_items.map! { |item| item.prepend( ' *' ) }
26
-
27
- when :NUMBER
28
- rendered_items = element.items.map { |item| render( item, item_width ) }
29
- rendered_items.map! { |item| item.gsub( /\n/, "\n#{INDENT}" ) }
30
- rendered_items.map!.with_index( 1 ) { |item, i| item.prepend( "#{i}." ) }
31
-
32
- when :LALPHA
33
- rendered_items = element.items.map { |item| render( item, item_width ) }
34
- rendered_items.map! { |item| item.gsub( /\n/, "\n#{INDENT}" ) }
35
- rendered_items.map!.with_index { |item, i| item.prepend( LOWER_ALPHABET[i] ) }
36
-
37
- when :UALPHA
38
- rendered_items = element.items.map { |item| render( item, item_width ) }
39
- rendered_items.map! { |item| item.gsub( /\n/, "\n#{INDENT}" ) }
40
- rendered_items.map!.with_index { |item, index| item.prepend( UPPER_ALPHABET[i] ) }
41
-
42
- when :LABEL
43
- # do nothing
44
- rendered_items = element.items.map { |item| render( item, item_width ) }
45
- rendered_items.map! { |item| item.gsub( /\n/, "\n#{INDENT}" ) }
46
-
47
- when :NOTE
48
- alignment_width = element.items.flat_map(&:label).map(&:size).max + 1
49
- rendered_items = element.items.map { |item| render( item, item_width, alignment_width ) }
50
- rendered_items.map! { |item| item.gsub( /\n/, "\n#{INDENT}" ) }
51
- end
52
-
53
- "#{rendered_items.join( "\n" )}\n"
54
-
55
- else
56
- text = extract_text( element, width, alignment_width )
57
-
58
- if text == "\n"
59
- nil
60
- else
61
- styled_text = replace_markup( text )
62
- wrapped_text = wrap_to_width( styled_text, width )
63
- indent( wrapped_text )
64
- end
65
- end
66
- end
67
-
68
- def self.extract_text( element, width, label_alignment_width = 0, conserve_newlines = false )
69
- case element
70
- when RDoc::Markup::Paragraph
71
- join_char = conserve_newlines ? "\n" : " "
72
- element.parts.map(&:strip).join( join_char ) + "\n"
73
-
74
- when RDoc::Markup::BlankLine
75
- "\n"
76
-
77
- when RDoc::Markup::Rule
78
- "-" * width + "\n"
79
-
80
- when RDoc::Markup::Verbatim
81
- element.parts.map { |part| part.prepend( " " ) }.join + "\n"
82
-
83
- when RDoc::Markup::Heading
84
- "<h>#{element.text}</h>\n"
85
-
86
- when RDoc::Markup::ListItem
87
- parts = element.parts.map { |part| extract_text( part, width, 0, true ) }.join
88
-
89
- if element.label
90
- labels = element.label.map { |l| "#{l}:" }.join("\n")
91
- sprintf( "%*s %s", -label_alignment_width, labels, parts )
92
- else
93
- parts
94
- end
95
-
96
- when RDoc::Markup::List
97
- render( element, width - INDENT_WIDTH ) + "\n"
98
-
99
- when RDoc::Markup::Document
100
- element.parts.
101
- map { |part| extract_text( part, width, label_alignment_width, conserve_newlines ) }.
102
- join + "\n"
103
- else
104
- raise "Don't know how to handle type #{element.class}: #{element.inspect}"
105
- end
106
- end
107
-
108
- def self.replace_markup( text )
109
- text.gsub!( /(?<!\\)<(?:tt|code)>/, Color.cyan )
110
- text.gsub!( /(?<!\\)<\/(?:tt|code)>/, Color.reset )
111
-
112
- text.gsub!( /(?<!\\)<b>/, Color.bold )
113
- text.gsub!( /(?<!\\)<\/b>/, Color.reset )
114
-
115
- text.gsub!( /(?<!\\)<(?:em|i)>/, Color.yellow )
116
- text.gsub!( /(?<!\\)<\/(?:em|i)>/, Color.reset )
117
-
118
- text.gsub!( "<h>", Color.green )
119
- text.gsub!( "</h>", Color.reset )
120
-
121
- text.gsub!( "\\<", "<" )
122
-
123
- text.gsub!( /(#\s*=>)(.*)/,
124
- "#{Color.dark}\\1#{Color.reset}#{Color.bold}\\2#{Color.reset}" )
125
-
126
- text.gsub!( /(^|\s)\*(.*?[a-zA-Z0-9]+.*?)\*/,
127
- "\\1#{Color.bold}\\2#{Color.reset}" )
128
- text.gsub!( /(^|\s)\+(.*?[a-zA-Z0-9]+.*?)\+/,
129
- "\\1#{Color.cyan}\\2#{Color.reset}" )
130
- text.gsub!( /(^|\s)_(.*?[a-zA-Z0-9]+.*?)_/,
131
- "\\1#{Color.yellow}\\2#{Color.reset}" )
132
-
133
- text.gsub!( %r{\b((?:https?|ftp)://[-\w.?%&=/]+)\b},
134
- "#{Color.underline}\\1#{Color.reset}" )
135
-
136
- text.gsub!( %r{\b(mailto:[-\w.%]+@[-\w.]+)\b},
137
- "#{Color.underline}\\1#{Color.reset}" )
138
-
139
- text.gsub!( %r{\b((?<!:\/\/)www.[-\w.?%&=]+)\b},
140
- "#{Color.underline}\\1#{Color.reset}" )
141
-
142
- text.gsub!( %r{\blink:(.*?)(\s|$)},
143
- "#{Color.underline}\\1#{Color.reset}\\2" )
144
-
145
- text.gsub!( %r{\{(.*?)\}\[(.*?)\]}, "\\1 (\\2)" )
146
- text.gsub!( %r{\[(#{Regexp.escape( Color.underline )}.*?#{Regexp.escape( Color.reset )})\]},
147
- " (\\1)" )
148
- text
149
- end
150
-
151
- def self.printable_length( text )
152
- Term::ANSIColor.uncolored( text ).length
153
- end
154
-
155
- def self.wrap_list( array, width = Bri.width )
156
- indent( wrap_to_width( array.join(" "), width ) )
157
- end
158
-
159
- def self.wrap_to_width( styled_text, width )
160
- styled_text.split( "\n" ).map { |row| wrap_row( row, width ) }.join
161
- end
162
-
163
- def self.wrap_row( physical_row, width )
164
- output_text = ''
165
- logical_row = ''
166
- printable_row_length = 0
167
-
168
- scanner = StringScanner.new( physical_row )
169
-
170
- while( !scanner.eos? )
171
- token = scanner.scan( /\S+/ ).to_s
172
- printable_token_length = printable_length( token )
173
-
174
- if printable_token_length + printable_row_length > width
175
- output_text << logical_row << "\n"
176
- logical_row = ''
177
- printable_row_length = 0
178
- end
179
-
180
- logical_row << token
181
- printable_row_length += printable_token_length
182
-
183
- token = scanner.scan( /\s*/ ).to_s
184
- logical_row << token
185
- printable_row_length += token.length
186
- end
187
-
188
- output_text << logical_row << "\n"
189
- end
190
-
191
- def self.indent( text )
192
- text.split( "\n" ).map { |row| "#{INDENT}#{row}" }.join("\n" )
18
+ RDOC_TO_BRI_RENDERER_CLASS_MAP = {
19
+ ::RDoc::Markup::Document => ::Bri::Renderer::Document,
20
+ ::RDoc::Markup::Paragraph => ::Bri::Renderer::Paragraph,
21
+ ::RDoc::Markup::BlankLine => ::Bri::Renderer::BlankLine,
22
+ ::RDoc::Markup::Rule => ::Bri::Renderer::Rule,
23
+ ::RDoc::Markup::Verbatim => ::Bri::Renderer::Verbatim,
24
+ ::RDoc::Markup::Heading => ::Bri::Renderer::Heading,
25
+ ::RDoc::Markup::ListItem => ::Bri::Renderer::ListItem,
26
+ ::RDoc::Markup::List => ::Bri::Renderer::List,
27
+ }
28
+ RDOC_TO_BRI_RENDERER_CLASS_MAP.default = ::Bri::Renderer::Default
29
+
30
+ def self.new( element )
31
+ renderer_class = RDOC_TO_BRI_RENDERER_CLASS_MAP[element.class]
32
+ renderer_class.new( element )
193
33
  end
194
34
  end
195
35
  end
@@ -0,0 +1,9 @@
1
+ module Bri
2
+ module Renderer
3
+ class BlankLine < Default
4
+ def extract_text( width, conserve_newlines = false )
5
+ "\n"
6
+ end
7
+ end
8
+ end
9
+ end