From 8cce02a195cb2e82762869f8ec6f61d269f46b04 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Wed, 20 Nov 2024 10:06:12 -0600 Subject: [PATCH 01/22] New console application webri --- bin/webri | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100755 bin/webri diff --git a/bin/webri b/bin/webri new file mode 100755 index 0000000000..450392ab82 --- /dev/null +++ b/bin/webri @@ -0,0 +1,92 @@ +#!/usr/bin/env ruby + +require 'optparse' +require 'open-uri' +require 'nokogiri' +require 'rdoc' + +include Nokogiri + +options = {} + +parser = OptionParser.new + +parser.version = RDoc::VERSION +parser.banner = <<-BANNER +Usage: #{parser.program_name} [options] name + + where name is the name of a page, a class, or a method. + +BANNER + +parser.on('-h', '--help', 'Print this help.') do + puts parser + exit +end +parser.on('-v', '--version', 'Print the version of webri.') do + puts RDoc::VERSION + exit +end +parser.on('-r', '--release=STR', 'Sets Ruby release to STR') do |release| + options[:release] = release +end +parser.parse! + +error_message = case ARGV.size +when 0 + 'No name given.' +when 1 + nil +else + 'Multiple names given.' +end +raise ArgumentError.new(error_message) if error_message + +name = ARGV.shift + +ReleasesUrl = 'https://docs.ruby-lang.org/en/' +html = URI.open(ReleasesUrl) +doc = Nokogiri::HTML(html) +link_eles = doc.xpath("//a") +href_for_release = {} +link_eles.each do |link_ele| + text = link_ele.text + next if text.match('outdated') + release = text.sub('Ruby ', '') + href = link_ele[:href] + href_for_release[release] = href +end +release = options[:release] +if release.nil? + release = href_for_release.keys[1] +end +href = href_for_release[release] +if href.nil? + message = <<-MESSAGE + +Unrecognized release #{release}: + Should be one of #{href_for_release.keys}. + Your installed Ruby is release #{RUBY_VERSION}. +MESSAGE + raise ArgumentError.new(message) +end +toc_url = URI.join(ReleasesUrl, href, 'table_of_contents.html') +html = URI.open(toc_url.to_s) +doc = Nokogiri::HTML(html) + +# Select executable for launching web browser. +host_os = RbConfig::CONFIG['host_os'] +executable_name = case host_os + when /linux|bsd/ + 'xdg-open' + when /darwin/ + 'open' + when /32$/ + 'start' + else + message = "Unrecognized host OS: '#{host_os}'." + raise RuntimeError.new(message) + end + +p release +p executable_name From 7a5739da8dac77192aadb714cbd66bab078ebfb4 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Wed, 20 Nov 2024 20:20:19 -0600 Subject: [PATCH 02/22] More --- bin/webri | 80 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/bin/webri b/bin/webri index 450392ab82..34e5a94212 100755 --- a/bin/webri +++ b/bin/webri @@ -62,18 +62,82 @@ if release.nil? end href = href_for_release[release] if href.nil? - message = <<-MESSAGE - -Unrecognized release #{release}: - Should be one of #{href_for_release.keys}. - Your installed Ruby is release #{RUBY_VERSION}. -MESSAGE - raise ArgumentError.new(message) + releases = href_for_release.keys + puts "Unrecognized release #{release}; available releases:" + releases.each_with_index do |release, i| + puts " #{i}: #{release}" + end + print "Choose (#{0..releases.size-1}): " + release = releases[gets.to_i] + href = href_for_release[release] end + toc_url = URI.join(ReleasesUrl, href, 'table_of_contents.html') html = URI.open(toc_url.to_s) doc = Nokogiri::HTML(html) +html = URI.open(toc_url.to_s) +doc = Nokogiri::HTML(html) + +data_for_name = {} + +# Get the files (free-standing pages). +file_a_eles = doc.xpath('//li[@class="file"]/a') +file_a_eles.each do |file_a_ele| + name = file_a_ele.text + data_for_name[name] ||= [] + data_for_name[name].push({ + type: :file, + text: file_a_ele.text, + name: file_a_ele.text, + link: file_a_ele.attributes['href'].value, + }) +end + +# Get the classes. +class_a_eles = doc.xpath('//li[@class="class"]/a') +class_a_eles.each do |class_a_ele| + name = class_a_ele.text + data_for_name[name] ||= [] + data_for_name[name].push({ + type: :class, + text: class_a_ele.text, + name: class_a_ele.text, + link: class_a_ele.attributes['href'].value, + }) +end + +# Get the modules. +module_a_eles = doc.xpath('//li[@class="module"]/a') +module_a_eles.each do |module_a_ele| + name = module_a_ele.text + data_for_name[name] ||= [] + data_for_name[name].push({ + type: :module, + text: module_a_ele.text, + name: module_a_ele.text, + link: module_a_ele.attributes['href'].value, + }) +end + +# Get the methods. +method_a_eles = doc.xpath('//li[@class="method"]/a') +method_a_eles.each do |method_a_ele| + name = method_a_ele.text + data_for_name[name] ||= [] + data_for_name[name].push({ + type: :method, + text: method_a_ele.text, + name: method_a_ele.text, + link: method_a_ele.attributes['href'].value, + }) +end +data_for_name.each_pair do |key, value| + p [key, value.size] +end + +# Get the methods. + # Select executable for launching web browser. host_os = RbConfig::CONFIG['host_os'] executable_name = case host_os @@ -88,5 +152,3 @@ executable_name = case host_os raise RuntimeError.new(message) end -p release -p executable_name From 59fa7710514cc8cd8a859163c66c44b21f5373e1 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Wed, 20 Nov 2024 21:11:21 -0600 Subject: [PATCH 03/22] More --- bin/webri | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/bin/webri b/bin/webri index 34e5a94212..89f05a2d12 100755 --- a/bin/webri +++ b/bin/webri @@ -121,15 +121,29 @@ module_a_eles.each do |module_a_ele| end # Get the methods. -method_a_eles = doc.xpath('//li[@class="method"]/a') -method_a_eles.each do |method_a_ele| +method_li_eles = doc.xpath('//li[@class="method"]') +method_li_eles.each do |method_li_ele| + method_a_ele = method_li_ele.xpath('./a').first name = method_a_ele.text + href = method_a_ele.attributes['href'].value data_for_name[name] ||= [] + method_span_ele = method_li_ele.xpath('./span').first + parent_name = method_span_ele.text data_for_name[name].push({ type: :method, - text: method_a_ele.text, - name: method_a_ele.text, - link: method_a_ele.attributes['href'].value, + text: name, + name: name, + link: href, + parent_name: parent_name, + }) + full_name = parent_name + name + p full_name + data_for_name[name].push({ + type: :method, + text: full_name, + name: full_name, + link: href, + parent_name: parent_name, }) end data_for_name.each_pair do |key, value| From d7917d09f5edda01f46514776c6bbad4b1437dad Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 04:18:06 -0600 Subject: [PATCH 04/22] More --- bin/webri | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/bin/webri b/bin/webri index 89f05a2d12..225902291c 100755 --- a/bin/webri +++ b/bin/webri @@ -42,7 +42,7 @@ else end raise ArgumentError.new(error_message) if error_message -name = ARGV.shift +target_name = ARGV.shift ReleasesUrl = 'https://docs.ruby-lang.org/en/' html = URI.open(ReleasesUrl) @@ -137,7 +137,6 @@ method_li_eles.each do |method_li_ele| parent_name: parent_name, }) full_name = parent_name + name - p full_name data_for_name[name].push({ type: :method, text: full_name, @@ -146,11 +145,9 @@ method_li_eles.each do |method_li_ele| parent_name: parent_name, }) end -data_for_name.each_pair do |key, value| - p [key, value.size] -end - -# Get the methods. +# data_for_name.each_pair do |key, value| +# p [key, value.size] +# end # Select executable for launching web browser. host_os = RbConfig::CONFIG['host_os'] From bb5946f1fb2f7369204c2b7fcb379f278cb315e0 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 04:32:28 -0600 Subject: [PATCH 05/22] More --- bin/webri | 77 +++++++++++++++++++++---------------------------------- 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/bin/webri b/bin/webri index 225902291c..505eb0ada2 100755 --- a/bin/webri +++ b/bin/webri @@ -46,8 +46,8 @@ target_name = ARGV.shift ReleasesUrl = 'https://docs.ruby-lang.org/en/' html = URI.open(ReleasesUrl) -doc = Nokogiri::HTML(html) -link_eles = doc.xpath("//a") +@doc = Nokogiri::HTML(html) +link_eles = @doc.xpath("//a") href_for_release = {} link_eles.each do |link_ele| text = link_ele.text @@ -74,62 +74,42 @@ end toc_url = URI.join(ReleasesUrl, href, 'table_of_contents.html') html = URI.open(toc_url.to_s) -doc = Nokogiri::HTML(html) +@doc = Nokogiri::HTML(html) html = URI.open(toc_url.to_s) -doc = Nokogiri::HTML(html) - -data_for_name = {} - -# Get the files (free-standing pages). -file_a_eles = doc.xpath('//li[@class="file"]/a') -file_a_eles.each do |file_a_ele| - name = file_a_ele.text - data_for_name[name] ||= [] - data_for_name[name].push({ - type: :file, - text: file_a_ele.text, - name: file_a_ele.text, - link: file_a_ele.attributes['href'].value, - }) -end - -# Get the classes. -class_a_eles = doc.xpath('//li[@class="class"]/a') -class_a_eles.each do |class_a_ele| - name = class_a_ele.text - data_for_name[name] ||= [] - data_for_name[name].push({ - type: :class, - text: class_a_ele.text, - name: class_a_ele.text, - link: class_a_ele.attributes['href'].value, - }) +@doc = Nokogiri::HTML(html) + +@data_for_name = {} + +def make_entries(type) + xpath = "//li[@class='#{type}']/a" + a_eles = @doc.xpath(xpath) + a_eles.each do |a_ele| + name = a_ele.text + @data_for_name[name] ||= [] + @data_for_name[name].push({ + type: type, + text: a_ele.text, + name: a_ele.text, + link: a_ele.attributes['href'].value, + }) + end end -# Get the modules. -module_a_eles = doc.xpath('//li[@class="module"]/a') -module_a_eles.each do |module_a_ele| - name = module_a_ele.text - data_for_name[name] ||= [] - data_for_name[name].push({ - type: :module, - text: module_a_ele.text, - name: module_a_ele.text, - link: module_a_ele.attributes['href'].value, - }) -end +make_entries('file') +make_entries('class') +make_entries('module') # Get the methods. -method_li_eles = doc.xpath('//li[@class="method"]') +method_li_eles = @doc.xpath('//li[@class="method"]') method_li_eles.each do |method_li_ele| method_a_ele = method_li_ele.xpath('./a').first name = method_a_ele.text href = method_a_ele.attributes['href'].value - data_for_name[name] ||= [] + @data_for_name[name] ||= [] method_span_ele = method_li_ele.xpath('./span').first parent_name = method_span_ele.text - data_for_name[name].push({ + @data_for_name[name].push({ type: :method, text: name, name: name, @@ -137,7 +117,7 @@ method_li_eles.each do |method_li_ele| parent_name: parent_name, }) full_name = parent_name + name - data_for_name[name].push({ + @data_for_name[name].push({ type: :method, text: full_name, name: full_name, @@ -145,9 +125,10 @@ method_li_eles.each do |method_li_ele| parent_name: parent_name, }) end -# data_for_name.each_pair do |key, value| +# @data_for_name.each_pair do |key, value| # p [key, value.size] # end +p @data_for_name.size # Select executable for launching web browser. host_os = RbConfig::CONFIG['host_os'] From df22951a9a5c495369fede0528a3567c80e6b961 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 04:54:28 -0600 Subject: [PATCH 06/22] More --- bin/webri | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bin/webri b/bin/webri index 505eb0ada2..ab19046fa3 100755 --- a/bin/webri +++ b/bin/webri @@ -87,12 +87,13 @@ def make_entries(type) a_eles.each do |a_ele| name = a_ele.text @data_for_name[name] ||= [] - @data_for_name[name].push({ - type: type, - text: a_ele.text, - name: a_ele.text, - link: a_ele.attributes['href'].value, - }) + main_entry = { + type: type, + text: a_ele.text, + name: a_ele.text, + link: a_ele.attributes['href'].value, + } + @data_for_name[name].push(main_entry) end end From 77f869cfe67e39f34bd19ad15541b1c1909d6bf2 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 05:05:33 -0600 Subject: [PATCH 07/22] More --- bin/webri | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/webri b/bin/webri index ab19046fa3..21af301455 100755 --- a/bin/webri +++ b/bin/webri @@ -82,9 +82,10 @@ html = URI.open(toc_url.to_s) @data_for_name = {} def make_entries(type) - xpath = "//li[@class='#{type}']/a" - a_eles = @doc.xpath(xpath) - a_eles.each do |a_ele| + xpath = "//li[@class='#{type}']" + li_eles = @doc.xpath(xpath) + li_eles.each do |li_ele| + a_ele = li_ele.xpath('./a').first name = a_ele.text @data_for_name[name] ||= [] main_entry = { From 1b1abb806f259afb0e55939f15916c7b7cfa954c Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 05:21:27 -0600 Subject: [PATCH 08/22] More --- bin/webri | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/bin/webri b/bin/webri index 21af301455..4ec8a69ccd 100755 --- a/bin/webri +++ b/bin/webri @@ -87,46 +87,34 @@ def make_entries(type) li_eles.each do |li_ele| a_ele = li_ele.xpath('./a').first name = a_ele.text + href = a_ele.attributes['href'].value @data_for_name[name] ||= [] main_entry = { type: type, text: a_ele.text, name: a_ele.text, - link: a_ele.attributes['href'].value, + link: href, } @data_for_name[name].push(main_entry) + next unless type == 'method' + method_span_ele = li_ele.xpath('./span').first + parent_name = method_span_ele.text + main_entry[:parent_name] = parent_name + full_name = parent_name + name + @data_for_name[name].push({ + type: :method, + text: full_name, + name: full_name, + link: href, + parent_name: parent_name, + }) end end make_entries('file') make_entries('class') make_entries('module') - -# Get the methods. -method_li_eles = @doc.xpath('//li[@class="method"]') -method_li_eles.each do |method_li_ele| - method_a_ele = method_li_ele.xpath('./a').first - name = method_a_ele.text - href = method_a_ele.attributes['href'].value - @data_for_name[name] ||= [] - method_span_ele = method_li_ele.xpath('./span').first - parent_name = method_span_ele.text - @data_for_name[name].push({ - type: :method, - text: name, - name: name, - link: href, - parent_name: parent_name, - }) - full_name = parent_name + name - @data_for_name[name].push({ - type: :method, - text: full_name, - name: full_name, - link: href, - parent_name: parent_name, - }) -end +make_entries('method') # @data_for_name.each_pair do |key, value| # p [key, value.size] # end From 9d2ed905f9df89ce09622b9d39acf8f701bb2021 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 05:47:05 -0600 Subject: [PATCH 09/22] More --- bin/webri | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/bin/webri b/bin/webri index 4ec8a69ccd..e69f629c1d 100755 --- a/bin/webri +++ b/bin/webri @@ -86,28 +86,32 @@ def make_entries(type) li_eles = @doc.xpath(xpath) li_eles.each do |li_ele| a_ele = li_ele.xpath('./a').first - name = a_ele.text + entry_name = a_ele.text href = a_ele.attributes['href'].value - @data_for_name[name] ||= [] + @data_for_name[entry_name] ||= [] main_entry = { type: type, - text: a_ele.text, - name: a_ele.text, + text: entry_name, link: href, } - @data_for_name[name].push(main_entry) + @data_for_name[entry_name].push(main_entry) next unless type == 'method' + # Add parent name to main entry. method_span_ele = li_ele.xpath('./span').first parent_name = method_span_ele.text main_entry[:parent_name] = parent_name - full_name = parent_name + name - @data_for_name[name].push({ - type: :method, - text: full_name, - name: full_name, - link: href, - parent_name: parent_name, - }) + # Add aliases. + full_name = parent_name + entry_name + bare_name = entry_name.sub(/^::/, '').sub(/^#/, '') + dot_name = '.' + bare_name + [full_name, bare_name, dot_name].each do |name| + @data_for_name[entry_name].push({ + type: type, + text: name, + link: href, + parent_name: parent_name, + }) + end end end From 850266fe491ed0aa9ee463210e6062fca01af763 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 05:59:13 -0600 Subject: [PATCH 10/22] More --- bin/webri | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/bin/webri b/bin/webri index e69f629c1d..469520ad04 100755 --- a/bin/webri +++ b/bin/webri @@ -86,28 +86,29 @@ def make_entries(type) li_eles = @doc.xpath(xpath) li_eles.each do |li_ele| a_ele = li_ele.xpath('./a').first - entry_name = a_ele.text + main_entry_name = a_ele.text href = a_ele.attributes['href'].value - @data_for_name[entry_name] ||= [] + @data_for_name[main_entry_name] ||= [] main_entry = { type: type, - text: entry_name, + text: main_entry_name, link: href, } - @data_for_name[entry_name].push(main_entry) + @data_for_name[main_entry_name].push(main_entry) next unless type == 'method' # Add parent name to main entry. method_span_ele = li_ele.xpath('./span').first parent_name = method_span_ele.text main_entry[:parent_name] = parent_name # Add aliases. - full_name = parent_name + entry_name - bare_name = entry_name.sub(/^::/, '').sub(/^#/, '') + full_name = parent_name + main_entry_name + bare_name = main_entry_name.sub(/^::/, '').sub(/^#/, '') dot_name = '.' + bare_name - [full_name, bare_name, dot_name].each do |name| - @data_for_name[entry_name].push({ + [full_name, bare_name, dot_name].each do |other_name| + @data_for_name[other_name] ||= [] + @data_for_name[other_name].push({ type: type, - text: name, + text: main_entry_name, link: href, parent_name: parent_name, }) @@ -119,9 +120,7 @@ make_entries('file') make_entries('class') make_entries('module') make_entries('method') -# @data_for_name.each_pair do |key, value| -# p [key, value.size] -# end + p @data_for_name.size # Select executable for launching web browser. From 13acd2a166c2eb511f2d9957821bb1d9eac65fa7 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 07:30:16 -0600 Subject: [PATCH 11/22] More --- bin/webri | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bin/webri b/bin/webri index 469520ad04..660a5ce50f 100755 --- a/bin/webri +++ b/bin/webri @@ -72,7 +72,8 @@ if href.nil? href = href_for_release[release] end -toc_url = URI.join(ReleasesUrl, href, 'table_of_contents.html') +url_stem = URI.join(ReleasesUrl, href) +toc_url = URI.join(url_stem, 'table_of_contents.html') html = URI.open(toc_url.to_s) @doc = Nokogiri::HTML(html) @@ -137,3 +138,10 @@ executable_name = case host_os raise RuntimeError.new(message) end +target_data = @data_for_name[target_name][1] +target_url = URI.join(url_stem, target_data[:link]) +p target_url + +command = "#{executable_name} #{target_url}" +p command +system(command) \ No newline at end of file From a4e3205749649278f4888cb3f3beeb8b7bfb3a26 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 07:52:31 -0600 Subject: [PATCH 12/22] More --- bin/webri | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bin/webri b/bin/webri index 660a5ce50f..78b083b4f4 100755 --- a/bin/webri +++ b/bin/webri @@ -61,14 +61,24 @@ if release.nil? release = href_for_release.keys[1] end href = href_for_release[release] + +def choose(choices) + selection = nil + range = (1..choices.size) + until range.include?(selection) + choices.each_with_index do |choice, i| + puts " #{i + 1}: #{choice}" + end + print "Choose (#{range}): " + selection = gets.to_i + end + choices[selection - 1] +end + if href.nil? releases = href_for_release.keys puts "Unrecognized release #{release}; available releases:" - releases.each_with_index do |release, i| - puts " #{i}: #{release}" - end - print "Choose (#{0..releases.size-1}): " - release = releases[gets.to_i] + release = choose(releases) href = href_for_release[release] end From 54d301979de2929766acfaabd3da568f35ed963d Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Thu, 21 Nov 2024 08:14:47 -0600 Subject: [PATCH 13/22] More --- bin/webri | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/bin/webri b/bin/webri index 78b083b4f4..8c86059df1 100755 --- a/bin/webri +++ b/bin/webri @@ -62,7 +62,7 @@ if release.nil? end href = href_for_release[release] -def choose(choices) +def choice_index(choices) selection = nil range = (1..choices.size) until range.include?(selection) @@ -72,13 +72,14 @@ def choose(choices) print "Choose (#{range}): " selection = gets.to_i end - choices[selection - 1] + selection - 1 end if href.nil? releases = href_for_release.keys puts "Unrecognized release #{release}; available releases:" - release = choose(releases) + index = choice_index(releases) + release = releases[index] href = href_for_release[release] end @@ -148,10 +149,10 @@ executable_name = case host_os raise RuntimeError.new(message) end -target_data = @data_for_name[target_name][1] +target_data = @data_for_name[target_name] +full_names = target_data.map {|x| x[:parent_name] + x[:text]} +index = choice_index(full_names) +target_data = target_data[index] target_url = URI.join(url_stem, target_data[:link]) -p target_url - command = "#{executable_name} #{target_url}" -p command system(command) \ No newline at end of file From 5af183d3b1e84e453ded5513bcd83b0a77f30027 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Fri, 22 Nov 2024 14:54:26 -0600 Subject: [PATCH 14/22] More --- bin/webri | 119 +---------------------------------- lib/rdoc/web_ri.rb | 151 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 117 deletions(-) create mode 100644 lib/rdoc/web_ri.rb diff --git a/bin/webri b/bin/webri index 8c86059df1..2b025835b6 100755 --- a/bin/webri +++ b/bin/webri @@ -1,11 +1,7 @@ #!/usr/bin/env ruby require 'optparse' -require 'open-uri' -require 'nokogiri' -require 'rdoc' - -include Nokogiri +require_relative '../lib/rdoc/web_ri' options = {} @@ -44,115 +40,4 @@ raise ArgumentError.new(error_message) if error_message target_name = ARGV.shift -ReleasesUrl = 'https://docs.ruby-lang.org/en/' -html = URI.open(ReleasesUrl) -@doc = Nokogiri::HTML(html) -link_eles = @doc.xpath("//a") -href_for_release = {} -link_eles.each do |link_ele| - text = link_ele.text - next if text.match('outdated') - release = text.sub('Ruby ', '') - href = link_ele[:href] - href_for_release[release] = href -end -release = options[:release] -if release.nil? - release = href_for_release.keys[1] -end -href = href_for_release[release] - -def choice_index(choices) - selection = nil - range = (1..choices.size) - until range.include?(selection) - choices.each_with_index do |choice, i| - puts " #{i + 1}: #{choice}" - end - print "Choose (#{range}): " - selection = gets.to_i - end - selection - 1 -end - -if href.nil? - releases = href_for_release.keys - puts "Unrecognized release #{release}; available releases:" - index = choice_index(releases) - release = releases[index] - href = href_for_release[release] -end - -url_stem = URI.join(ReleasesUrl, href) -toc_url = URI.join(url_stem, 'table_of_contents.html') -html = URI.open(toc_url.to_s) -@doc = Nokogiri::HTML(html) - -html = URI.open(toc_url.to_s) -@doc = Nokogiri::HTML(html) - -@data_for_name = {} - -def make_entries(type) - xpath = "//li[@class='#{type}']" - li_eles = @doc.xpath(xpath) - li_eles.each do |li_ele| - a_ele = li_ele.xpath('./a').first - main_entry_name = a_ele.text - href = a_ele.attributes['href'].value - @data_for_name[main_entry_name] ||= [] - main_entry = { - type: type, - text: main_entry_name, - link: href, - } - @data_for_name[main_entry_name].push(main_entry) - next unless type == 'method' - # Add parent name to main entry. - method_span_ele = li_ele.xpath('./span').first - parent_name = method_span_ele.text - main_entry[:parent_name] = parent_name - # Add aliases. - full_name = parent_name + main_entry_name - bare_name = main_entry_name.sub(/^::/, '').sub(/^#/, '') - dot_name = '.' + bare_name - [full_name, bare_name, dot_name].each do |other_name| - @data_for_name[other_name] ||= [] - @data_for_name[other_name].push({ - type: type, - text: main_entry_name, - link: href, - parent_name: parent_name, - }) - end - end -end - -make_entries('file') -make_entries('class') -make_entries('module') -make_entries('method') - -p @data_for_name.size - -# Select executable for launching web browser. -host_os = RbConfig::CONFIG['host_os'] -executable_name = case host_os - when /linux|bsd/ - 'xdg-open' - when /darwin/ - 'open' - when /32$/ - 'start' - else - message = "Unrecognized host OS: '#{host_os}'." - raise RuntimeError.new(message) - end - -target_data = @data_for_name[target_name] -full_names = target_data.map {|x| x[:parent_name] + x[:text]} -index = choice_index(full_names) -target_data = target_data[index] -target_url = URI.join(url_stem, target_data[:link]) -command = "#{executable_name} #{target_url}" -system(command) \ No newline at end of file +web_ri = RDoc::WebRI.new(target_name, options) diff --git a/lib/rdoc/web_ri.rb b/lib/rdoc/web_ri.rb new file mode 100644 index 0000000000..72b99fc25a --- /dev/null +++ b/lib/rdoc/web_ri.rb @@ -0,0 +1,151 @@ +# frozen_string_literal: true +require 'open-uri' +require 'nokogiri' +include Nokogiri + +require_relative '../rdoc' + +class RDoc::WebRI + + ReleasesUrl = 'https://docs.ruby-lang.org/en/' + + def initialize(target_name, options) + release_name = get_release_name(options[:release]) + entries = get_entries(release_name) + target_entries = entries[target_name] + target_url = get_target_url(target_entries, release_name) + open_url(target_url) + end + + class Entry + + attr_accessor :type, :full_name, :href + + def initialize(type, full_name, href) + self.type = type + self.full_name = full_name + self.href = href + end + + end + + def get_release_name(requested_release_name) + if requested_release_name.nil? + puts "Selecting documentation release based on installed Ruby (#{RUBY_VERSION})." + requested_release_name = RUBY_VERSION + end + available_release_names = [] + html = URI.open(ReleasesUrl) + @doc = Nokogiri::HTML(html) + link_eles = @doc.xpath("//a") + link_eles.each do |link_ele| + text = link_ele.text + next if text.match('outdated') + release_name = text.sub('Ruby ', '') + available_release_names.push(release_name) + end + release_name = nil + if available_release_names.include?(requested_release_name) + release_name = requested_release_name + else + available_release_names.each do |name| + if requested_release_name.start_with?(name) + release_name = name + break + end + end + end + if release_name.nil? + puts "Could not select documentation release '#{requested_release_name}' from #{available_release_names}." + release_name = get_choice(available_release_names) + end + puts "Selected documentation release #{release_name}." + release_name + end + + def get_entries(release_name) + toc_url = File.join(ReleasesUrl, release_name, 'table_of_contents.html') + html = URI.open(toc_url) + doc = Nokogiri::HTML(html) + entries = {} + %w[file class module method].each do |type| + add_entries(entries, doc, type) + end + entries + end + + def add_entries(entries, doc, type) + xpath = "//li[@class='#{type}']" + li_eles = doc.xpath(xpath) + li_eles.each do |li_ele| + a_ele = li_ele.xpath('./a').first + short_name = a_ele.text + full_name = if type == 'method' + method_span_ele = li_ele.xpath('./span').first + class_name = method_span_ele.text + class_name + short_name + else + short_name + end + href = a_ele.attributes['href'].value + entry = Entry.new(type, full_name, href) + entries[short_name] ||= [] + entries[short_name].push(entry) + next unless type == 'method' + # We want additional entries for full name, bare name, and dot name. + bare_name = short_name.sub(/^::/, '').sub(/^#/, '') + dot_name = '.' + bare_name + [full_name, bare_name, dot_name].each do |other_name| + entries[other_name] ||= [] + entries[other_name].push(entry) + end + end + end + + def get_target_url(target_entries, release_name) + target_entry = nil + if target_entries.size == 1 + target_entry = target_entries.first + else + full_names = target_entries.map { |entry| entry.full_name }.sort + index = get_choice_index(full_names) + target_entry = target_entries[index - 1] + end + File.join(ReleasesUrl, release_name, target_entry.href).to_s + end + + def open_url(target_url) + host_os = RbConfig::CONFIG['host_os'] + executable_name = case host_os + when /linux|bsd/ + 'xdg-open' + when /darwin/ + 'open' + when /32$/ + 'start' + else + message = "Unrecognized host OS: '#{host_os}'." + raise RuntimeError.new(message) + end + command = "#{executable_name} #{target_url}" + system(command) + end + + def get_choice(choices) + choices[get_choice_index(choices)] + end + + def get_choice_index(choices) + index = nil + range = (1..choices.size) + until range.include?(index) + choices.each_with_index do |choice, i| + puts " #{i + 1}: #{choice}" + end + print "Choose (#{range}): " + index = gets.to_i + end + index - 1 + end + +end From f3087cf822fb7d8c3e0e5452ab2a4f5e765e50ea Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Fri, 22 Nov 2024 18:55:16 -0600 Subject: [PATCH 15/22] More --- bin/webri | 2 ++ lib/rdoc/web_ri.rb | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/bin/webri b/bin/webri index 2b025835b6..23fdb6d146 100755 --- a/bin/webri +++ b/bin/webri @@ -1,5 +1,7 @@ #!/usr/bin/env ruby +# A console application to display Ruby HTML documentation. + require 'optparse' require_relative '../lib/rdoc/web_ri' diff --git a/lib/rdoc/web_ri.rb b/lib/rdoc/web_ri.rb index 72b99fc25a..d53e82aaf8 100644 --- a/lib/rdoc/web_ri.rb +++ b/lib/rdoc/web_ri.rb @@ -5,16 +5,23 @@ require_relative '../rdoc' +# A class to display Ruby HTML documentation. class RDoc::WebRI + # Where the documentation lives. ReleasesUrl = 'https://docs.ruby-lang.org/en/' + def initialize(target_name, options) release_name = get_release_name(options[:release]) entries = get_entries(release_name) target_entries = entries[target_name] - target_url = get_target_url(target_entries, release_name) - open_url(target_url) + if target_entries.nil? || target_entries.empty? + puts "No documentation found for #{target_name}." + else + target_url = get_target_url(target_entries, release_name) + open_url(target_url) + end end class Entry @@ -107,9 +114,10 @@ def get_target_url(target_entries, release_name) if target_entries.size == 1 target_entry = target_entries.first else - full_names = target_entries.map { |entry| entry.full_name }.sort + sorted_target_entries = target_entries.sort_by {|entry| entry.full_name} + full_names = sorted_target_entries.map { |entry| "#{entry.full_name} (#{entry.type})" } index = get_choice_index(full_names) - target_entry = target_entries[index - 1] + target_entry = sorted_target_entries[index] end File.join(ReleasesUrl, release_name, target_entry.href).to_s end @@ -137,15 +145,16 @@ def get_choice(choices) def get_choice_index(choices) index = nil - range = (1..choices.size) + range = (0..choices.size - 1) until range.include?(index) choices.each_with_index do |choice, i| - puts " #{i + 1}: #{choice}" + puts " #{i}: #{choice}" end print "Choose (#{range}): " - index = gets.to_i + response = gets + index = response.match(/\d+/) ? response.to_i : -1 end - index - 1 + index end end From d5e133db165250c5295140260c74ea70cae613e9 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Fri, 22 Nov 2024 20:36:34 -0600 Subject: [PATCH 16/22] More --- lib/rdoc/web_ri.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/rdoc/web_ri.rb b/lib/rdoc/web_ri.rb index d53e82aaf8..faac24c9fe 100644 --- a/lib/rdoc/web_ri.rb +++ b/lib/rdoc/web_ri.rb @@ -63,7 +63,7 @@ def get_release_name(requested_release_name) end end if release_name.nil? - puts "Could not select documentation release '#{requested_release_name}' from #{available_release_names}." + puts "Could not find documentation for release '#{requested_release_name}': available releases:" release_name = get_choice(available_release_names) end puts "Selected documentation release #{release_name}." @@ -151,6 +151,7 @@ def get_choice_index(choices) puts " #{i}: #{choice}" end print "Choose (#{range}): " + $stdout.flush response = gets index = response.match(/\d+/) ? response.to_i : -1 end From 47c75cef5d5e2c7a11d7a7fb8eb01745649e08be Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Fri, 22 Nov 2024 21:15:33 -0600 Subject: [PATCH 17/22] More --- bin/webri | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/bin/webri b/bin/webri index 23fdb6d146..ff1b7721e2 100755 --- a/bin/webri +++ b/bin/webri @@ -11,21 +11,33 @@ parser = OptionParser.new parser.version = RDoc::VERSION parser.banner = <<-BANNER +Command to open the web page for Ruby documentation +(page, class, module, or method). + Usage: #{parser.program_name} [options] name - where name is the name of a page, a class, or a method. + where name specifies one or more pages, classes, modules, or methods. + +If name specifies a single item, the page for that item is opened; +if it specifies multiple items, the names of those specific items are displayed, +and the user may choose among them. BANNER -parser.on('-h', '--help', 'Print this help.') do +parser.on('-h', '--help', 'Prints this help.') do puts parser exit end -parser.on('-v', '--version', 'Print the version of webri.') do +parser.on('-v', '--version', 'Prints the version of webri.') do puts RDoc::VERSION exit end -parser.on('-r', '--release=STR', 'Sets Ruby release to STR') do |release| +parser.on('-r', '--release=STR', + 'Sets desired documentation release to STR.', + "If not given, uses the release of the installed Ruby (#{RUBY_VERSION}).", + 'If given and not valid, the valid releases are displayed,', + 'and the user may choose among them.', +) do |release| options[:release] = release end parser.parse! From af80aa947f94a4d75189f84592019805e9ee6ca5 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Fri, 22 Nov 2024 21:52:28 -0600 Subject: [PATCH 18/22] More --- lib/rdoc/web_ri.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/rdoc/web_ri.rb b/lib/rdoc/web_ri.rb index faac24c9fe..5c19955fb7 100644 --- a/lib/rdoc/web_ri.rb +++ b/lib/rdoc/web_ri.rb @@ -15,8 +15,16 @@ class RDoc::WebRI def initialize(target_name, options) release_name = get_release_name(options[:release]) entries = get_entries(release_name) - target_entries = entries[target_name] - if target_entries.nil? || target_entries.empty? + # target_entries = entries[target_name] + target_entries = [] + entries.select do |name, value| + if name.match(Regexp.new(target_name)) + value.each do |x| + target_entries << x + end + end + end + if target_entries.empty? puts "No documentation found for #{target_name}." else target_url = get_target_url(target_entries, release_name) @@ -148,7 +156,8 @@ def get_choice_index(choices) range = (0..choices.size - 1) until range.include?(index) choices.each_with_index do |choice, i| - puts " #{i}: #{choice}" + s = "%6d" % i + puts " #{s}: #{choice}" end print "Choose (#{range}): " $stdout.flush From 2c2eab787c31a084718b43c5b91aff6bd2dbc98b Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Fri, 22 Nov 2024 22:18:33 -0600 Subject: [PATCH 19/22] More --- bin/webri | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bin/webri b/bin/webri index ff1b7721e2..38b0905eb4 100755 --- a/bin/webri +++ b/bin/webri @@ -22,6 +22,12 @@ If name specifies a single item, the page for that item is opened; if it specifies multiple items, the names of those specific items are displayed, and the user may choose among them. +The given name is converted to a Regexp, which is used to select +the items for consideration. + +Note that your command window may require you to escape certain characters; +in particular, you may need to escape circumflex (^), dollar sign ($), +and pound sign (#). BANNER parser.on('-h', '--help', 'Prints this help.') do From 2cf14b976277d8d58e551fd63fac8dfa4278143d Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Sat, 23 Nov 2024 09:30:57 -0600 Subject: [PATCH 20/22] More --- bin/webri | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/bin/webri b/bin/webri index 38b0905eb4..4166a2a02c 100755 --- a/bin/webri +++ b/bin/webri @@ -11,25 +11,32 @@ parser = OptionParser.new parser.version = RDoc::VERSION parser.banner = <<-BANNER -Command to open the web page for Ruby documentation -(page, class, module, or method). +webri is a console application for accessing Ruby online HTML documentation. Usage: #{parser.program_name} [options] name - where name specifies one or more pages, classes, modules, or methods. +Argument name selects the documentation to be accessed. -If name specifies a single item, the page for that item is opened; -if it specifies multiple items, the names of those specific items are displayed, -and the user may choose among them. +o If name specifies a single item, that item is selected. +o If name specifies multiple items, those items are displayed. -The given name is converted to a Regexp, which is used to select -the items for consideration. +The given name is converted to a Regexp, which is used to select documentation. Note that your command window may require you to escape certain characters; in particular, you may need to escape circumflex (^), dollar sign ($), and pound sign (#). + BANNER +parser.separator('Options:') +parser.on('-r', '--release=STR', + 'Sets the target documentation release to STR.', + 'If not given, uses the release of the installed Ruby', + "(currently #{RUBY_VERSION}).", + 'If given and not valid, the valid releases are displayed.', + ) do |release| + options[:release] = release +end parser.on('-h', '--help', 'Prints this help.') do puts parser exit @@ -38,14 +45,6 @@ parser.on('-v', '--version', 'Prints the version of webri.') do puts RDoc::VERSION exit end -parser.on('-r', '--release=STR', - 'Sets desired documentation release to STR.', - "If not given, uses the release of the installed Ruby (#{RUBY_VERSION}).", - 'If given and not valid, the valid releases are displayed,', - 'and the user may choose among them.', -) do |release| - options[:release] = release -end parser.parse! error_message = case ARGV.size From 3370f507a2bfb97d6f29b98ba23a1a5fecf14808 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Wed, 4 Dec 2024 09:29:07 -0600 Subject: [PATCH 21/22] More --- lib/rdoc/web_ri.rb | 168 ++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 107 deletions(-) diff --git a/lib/rdoc/web_ri.rb b/lib/rdoc/web_ri.rb index 5c19955fb7..c11bf4f170 100644 --- a/lib/rdoc/web_ri.rb +++ b/lib/rdoc/web_ri.rb @@ -1,21 +1,54 @@ # frozen_string_literal: true -require 'open-uri' -require 'nokogiri' -include Nokogiri +require 'rbconfig' +require 'find' require_relative '../rdoc' # A class to display Ruby HTML documentation. class RDoc::WebRI - # Where the documentation lives. - ReleasesUrl = 'https://docs.ruby-lang.org/en/' + def initialize(target_name, options) + ruby_exe_filepath = RbConfig.ruby + ruby_installation_dirpath = File.dirname(File.dirname(ruby_exe_filepath)) + ri_filepaths = get_ri_filepaths(ruby_installation_dirpath) + html_filepaths = get_html_filepaths(ruby_installation_dirpath) + filepaths = {} + missing_html = [] + unused_ri = [] + ri_filepaths.each do |ri_filepath| + next if ri_filepath == 'cache.ri' + filepath = ri_filepath.sub('.ri', '.html') + html_filepath = case + when filepath.match(/-c\.html/) + dirname = File.dirname(filepath) + basename = File.basename(filepath) + name = basename.sub('-c.html', '') + dirname + '.html' + when filepath.match(/-i\.html/) + dirname = File.dirname(filepath) + basename = File.basename(filepath) + name = basename.sub('-i.html', '') + dirname + '.html' + when filepath.match(/\/cdesc-/) + File.dirname(filepath) + '.html' + when File.basename(filepath).match(/^page-/) + filepath.sub('page-', '') + else + raise filepath + end + unless html_filepaths.include?(html_filepath) + missing_html.push(html_filepath) + unused_ri.push(ri_filepath) + end + filepaths[ri_filepath] = html_filepath + end + # puts missing_html.uniq + # puts unused_ri + puts filepaths.keys.sort.take(200) + puts target_name + return - def initialize(target_name, options) - release_name = get_release_name(options[:release]) - entries = get_entries(release_name) - # target_entries = entries[target_name] target_entries = [] entries.select do |name, value| if name.match(Regexp.new(target_name)) @@ -32,7 +65,7 @@ def initialize(target_name, options) end end - class Entry +class Entry attr_accessor :type, :full_name, :href @@ -44,107 +77,28 @@ def initialize(type, full_name, href) end - def get_release_name(requested_release_name) - if requested_release_name.nil? - puts "Selecting documentation release based on installed Ruby (#{RUBY_VERSION})." - requested_release_name = RUBY_VERSION - end - available_release_names = [] - html = URI.open(ReleasesUrl) - @doc = Nokogiri::HTML(html) - link_eles = @doc.xpath("//a") - link_eles.each do |link_ele| - text = link_ele.text - next if text.match('outdated') - release_name = text.sub('Ruby ', '') - available_release_names.push(release_name) - end - release_name = nil - if available_release_names.include?(requested_release_name) - release_name = requested_release_name - else - available_release_names.each do |name| - if requested_release_name.start_with?(name) - release_name = name - break - end - end - end - if release_name.nil? - puts "Could not find documentation for release '#{requested_release_name}': available releases:" - release_name = get_choice(available_release_names) - end - puts "Selected documentation release #{release_name}." - release_name - end - - def get_entries(release_name) - toc_url = File.join(ReleasesUrl, release_name, 'table_of_contents.html') - html = URI.open(toc_url) - doc = Nokogiri::HTML(html) - entries = {} - %w[file class module method].each do |type| - add_entries(entries, doc, type) - end - entries +def get_ri_filepaths(ruby_installation_dirpath) + # Directory containing filetree of .ri files installed by RI. + ri_dirpath = File.join(ruby_installation_dirpath, 'share', 'ri', RUBY_ENGINE_VERSION, 'system') + ri_filepaths = [] + Find.find(ri_dirpath).each do |path| + next unless path.end_with?('.ri') + path.sub!(ri_dirpath + '/', '') + ri_filepaths.push(path) end - - def add_entries(entries, doc, type) - xpath = "//li[@class='#{type}']" - li_eles = doc.xpath(xpath) - li_eles.each do |li_ele| - a_ele = li_ele.xpath('./a').first - short_name = a_ele.text - full_name = if type == 'method' - method_span_ele = li_ele.xpath('./span').first - class_name = method_span_ele.text - class_name + short_name - else - short_name - end - href = a_ele.attributes['href'].value - entry = Entry.new(type, full_name, href) - entries[short_name] ||= [] - entries[short_name].push(entry) - next unless type == 'method' - # We want additional entries for full name, bare name, and dot name. - bare_name = short_name.sub(/^::/, '').sub(/^#/, '') - dot_name = '.' + bare_name - [full_name, bare_name, dot_name].each do |other_name| - entries[other_name] ||= [] - entries[other_name].push(entry) - end - end + ri_filepaths end - def get_target_url(target_entries, release_name) - target_entry = nil - if target_entries.size == 1 - target_entry = target_entries.first - else - sorted_target_entries = target_entries.sort_by {|entry| entry.full_name} - full_names = sorted_target_entries.map { |entry| "#{entry.full_name} (#{entry.type})" } - index = get_choice_index(full_names) - target_entry = sorted_target_entries[index] + def get_html_filepaths(ruby_installation_dirpath) + # Directory containing filetree of .html files installed by RI. + html_dirpath = File.join(ruby_installation_dirpath, *%w[share doc ruby html]) + filepaths = [] + Find.find(html_dirpath).each do |path| + next unless path.end_with?('.html') + path.sub!(html_dirpath + '/', '') + filepaths.push(path) end - File.join(ReleasesUrl, release_name, target_entry.href).to_s - end - - def open_url(target_url) - host_os = RbConfig::CONFIG['host_os'] - executable_name = case host_os - when /linux|bsd/ - 'xdg-open' - when /darwin/ - 'open' - when /32$/ - 'start' - else - message = "Unrecognized host OS: '#{host_os}'." - raise RuntimeError.new(message) - end - command = "#{executable_name} #{target_url}" - system(command) + filepaths end def get_choice(choices) From 55d4d3e01e953e7cdbade0d305614298beff4a81 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Wed, 4 Dec 2024 12:37:00 -0600 Subject: [PATCH 22/22] More --- lib/rdoc/web_ri.rb | 91 ++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/lib/rdoc/web_ri.rb b/lib/rdoc/web_ri.rb index c11bf4f170..6b428cf6a1 100644 --- a/lib/rdoc/web_ri.rb +++ b/lib/rdoc/web_ri.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'rbconfig' require 'find' +require 'cgi' require_relative '../rdoc' @@ -12,71 +13,62 @@ def initialize(target_name, options) ruby_installation_dirpath = File.dirname(File.dirname(ruby_exe_filepath)) ri_filepaths = get_ri_filepaths(ruby_installation_dirpath) html_filepaths = get_html_filepaths(ruby_installation_dirpath) - filepaths = {} + target_urls = {} missing_html = [] unused_ri = [] ri_filepaths.each do |ri_filepath| next if ri_filepath == 'cache.ri' filepath = ri_filepath.sub('.ri', '.html') - html_filepath = case - when filepath.match(/-c\.html/) + name, target_url = case + when filepath.match(/-c\.html/) # Class method. dirname = File.dirname(filepath) - basename = File.basename(filepath) - name = basename.sub('-c.html', '') - dirname + '.html' - when filepath.match(/-i\.html/) + method_name = CGI.unescape(File.basename(filepath).sub('-c.html', '')) + target_url = dirname + '.html#method-c-' + method_name + name = dirname.gsub('/', '::') + '::' + method_name + [name, target_url] + when filepath.match(/-i\.html/) # Instance method. dirname = File.dirname(filepath) - basename = File.basename(filepath) - name = basename.sub('-i.html', '') - dirname + '.html' - when filepath.match(/\/cdesc-/) - File.dirname(filepath) + '.html' + method_name = CGI.unescape(File.basename(filepath).sub('-i.html', '')) + target_url = dirname + '.html#method-i-' + method_name + name = dirname.gsub('/', '::') + '#' + method_name + [name, target_url] + when filepath.match(/\/cdesc-/) # Class. + target_url = File.dirname(filepath) + '.html' + name = target_url.gsub('/', '::').sub('.html', '') + [name, target_url] when File.basename(filepath).match(/^page-/) - filepath.sub('page-', '') + target_url = filepath.sub('page-', '') # File. + name = target_url.sub('.html', '').sub(/_rdoc$/, '.rdoc').sub(/_md$/, '.md') + [name, target_url] else raise filepath end - unless html_filepaths.include?(html_filepath) - missing_html.push(html_filepath) + unless html_filepaths.include?(target_url) + missing_html.push(target_url) unused_ri.push(ri_filepath) end - filepaths[ri_filepath] = html_filepath + target_urls[name] = target_url end # puts missing_html.uniq # puts unused_ri - puts filepaths.keys.sort.take(200) - puts target_name - return - - target_entries = [] - entries.select do |name, value| + selected_urls = {} + target_urls.select do |name, value| if name.match(Regexp.new(target_name)) - value.each do |x| - target_entries << x - end + selected_urls[name] = value end end - if target_entries.empty? + case selected_urls.size + when 0 puts "No documentation found for #{target_name}." + when 1 + url = selected_urls.first[1] + open_url(url) else - target_url = get_target_url(target_entries, release_name) - open_url(target_url) + p get_choice(selected_urls.keys) end end -class Entry - - attr_accessor :type, :full_name, :href - - def initialize(type, full_name, href) - self.type = type - self.full_name = full_name - self.href = href - end - - end - def get_ri_filepaths(ruby_installation_dirpath) # Directory containing filetree of .ri files installed by RI. ri_dirpath = File.join(ruby_installation_dirpath, 'share', 'ri', RUBY_ENGINE_VERSION, 'system') @@ -121,4 +113,23 @@ def get_choice_index(choices) index end + def open_url(target_url) + host_os = RbConfig::CONFIG['host_os'] + executable_name = case host_os + when /linux|bsd/ + 'xdg-open' + when /darwin/ + 'open' + when /32$/ + 'start' + else + message = "Unrecognized host OS: '#{host_os}'." + raise RuntimeError.new(message) + end + command = "#{executable_name} #{target_url}" + p command + return + system(command) + end + end