Skip to content

Conversation

@adam12
Copy link
Contributor

@adam12 adam12 commented Nov 27, 2025

Add the ability to look up documentation for global variables (e.g., $<, $LOAD_PATH) and predefined constants (e.g., STDIN, ARGV, RUBY_VERSION) directly through the ri command. Documentation is extracted from the globals.rdoc page in the system store.

Changes:

  • Add display_global method to look up and display global documentation
  • Add extract_global_section to parse hierarchical headings in globals.rdoc
  • Add predefined_global_constant? to identify STDIN, ARGV, RUBY_* etc.
  • Update display_name to handle $-prefixed names and predefined constants
  • Update expand_name to skip expansion for globals
  • Fix nil matches bug in error handling when unknown globals are queried
  • Update help text with examples for global variable lookups

Add the ability to look up documentation for global variables (e.g., $<,
$LOAD_PATH) and predefined constants (e.g., STDIN, ARGV, RUBY_VERSION)
directly through the ri command. Documentation is extracted from the
globals.rdoc page in the system store.

Changes:
- Add display_global method to look up and display global documentation
- Add extract_global_section to parse hierarchical headings in globals.rdoc
- Add predefined_global_constant? to identify STDIN, ARGV, RUBY_* etc.
- Update display_name to handle $-prefixed names and predefined constants
- Update expand_name to skip expansion for globals
- Fix nil matches bug in error handling when unknown globals are queried
- Update help text with examples for global variable lookups
@adam12 adam12 temporarily deployed to fork-preview-protection November 27, 2025 18:48 — with GitHub Actions Inactive
@adam12
Copy link
Contributor Author

adam12 commented Nov 27, 2025

Parsing globals is less than ideal but I am not sure of a better approach. I'd love to see some support for keywords too but the same trick won't work (AFAICT).

@matzbot
Copy link
Collaborator

matzbot commented Nov 30, 2025

🚀 Preview deployment available at: https://034ce9e8.rdoc-6cd.pages.dev (commit: 6c00877)

@st0012
Copy link
Member

st0012 commented Dec 11, 2025

The PR currently shows Data class for ri DATA. I think we can apply something similar to this diff to fix it:

diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
index fe95de0a..1b93516e 100644
--- a/lib/rdoc/ri/driver.rb
+++ b/lib/rdoc/ri/driver.rb
@@ -968,6 +968,16 @@ or the PAGER environment variable.
     # Handle global variables immediately (classes can't start with $)
     return display_global(name) if name.start_with?('$')
 
+    # Try predefined constants BEFORE class lookup to avoid case-insensitive
+    # filesystem matching (e.g., DATA matching Data class on macOS)
+    if predefined_global_constant?(name)
+      begin
+        return display_global(name)
+      rescue NotFoundError
+        # Fall through to class lookup
+      end
+    end
+
     if name =~ /\w:(\w|$)/ then
       display_page name
       return true
@@ -977,21 +987,8 @@ or the PAGER environment variable.
 
     display_method name if name =~ /::|#|\./
 
-    # If no class was found and it's a predefined constant, try globals lookup
-    # This handles ARGV, STDIN, etc. that look like class names but aren't
-    return display_global(name) if predefined_global_constant?(name)
-
     true
   rescue NotFoundError
-    # Before giving up, check if it's a predefined global constant
-    if predefined_global_constant?(name)
-      begin
-        return display_global(name)
-      rescue NotFoundError
-        # Fall through to original error handling
-      end
-    end
-
     matches = list_methods_matching name if name =~ /::|#|\./
     matches = classes.keys.grep(/^#{Regexp.escape name}/) if matches.nil? || matches.empty?
 
diff --git a/test/rdoc/ri/driver_test.rb b/test/rdoc/ri/driver_test.rb
index 72f54b70..561207ba 100644
--- a/test/rdoc/ri/driver_test.rb
+++ b/test/rdoc/ri/driver_test.rb
@@ -1075,6 +1075,46 @@ Foo::Bar#bother
     assert_match %r%command-line arguments%, out
   end
 
+  def test_display_name_predefined_constant_over_class
+    util_store
+
+    # Create a Data class that could conflict with DATA constant
+    # (on case-insensitive filesystems, DATA could match Data)
+    @cData = @top_level.add_class RDoc::NormalClass, 'Data'
+    @cData.add_comment 'Data class for value objects', @top_level
+    @cData.record_location @top_level
+    @store1.save_class @cData
+
+    # Create a globals page with DATA constant
+    globals = @store1.add_file 'globals.rdoc'
+    globals.parser = RDoc::Parser::Simple
+    globals.comment = RDoc::Comment.from_document(doc(
+      head(1, 'Pre-Defined Global Constants'),
+      head(3, 'DATA'),
+      para('File object for lines after __END__.')
+    ))
+    @store1.save_page globals
+    @store1.type = :system
+
+    # DATA (all caps) should show the predefined constant, not the Data class
+    out, = capture_output do
+      @driver.display_name 'DATA'
+    end
+
+    assert_match %r%DATA%, out
+    assert_match %r%__END__%, out
+    refute_match %r%value objects%, out
+
+    # Data (capitalized) should show the class, not the constant
+    out, = capture_output do
+      @driver.display_name 'Data'
+    end
+
+    assert_match %r%Data%, out
+    assert_match %r%value objects%, out
+    refute_match %r%__END__%, out
+  end
+
   def test_predefined_global_constant?
     assert @driver.predefined_global_constant?('STDIN')
     assert @driver.predefined_global_constant?('STDOUT')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants