diff --git a/lib/csv/table.rb b/lib/csv/table.rb
index e6c1ee11fa..a6059ce60a 100644
--- a/lib/csv/table.rb
+++ b/lib/csv/table.rb
@@ -144,14 +144,91 @@ class CSV
end
end
+ # :call-seq:
+ # table[n] -> row
+ # table[range] -> array_of_rows
+ # table[header] -> array_of_fields
#
- # In the default mixed mode, this method returns rows for index access and
- # columns for header access. You can force the index association by first
- # calling by_col!() or by_row!().
+ # Returns data from the table; does not modify the table.
#
- # Columns are returned as an Array of values. Altering that Array has no
- # effect on the table.
+ # ---
#
+ # The expression table[n], where +n+ is a non-negative \Integer,
+ # returns the +n+th row of the table, if that row exists,
+ # and if the access mode is :row or :col_or_row:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_row! # => #
+ # table[1] # => #
+ # table.by_col_or_row! # => #
+ # table[1] # => #
+ #
+ # Counts backward from the last row if +n+ is negative:
+ # table[-1] # => #
+ #
+ # Returns +nil+ if +n+ is too large or too small:
+ # table[4] # => nil
+ # table[-4] => nil
+ #
+ # Raises an exception if the access mode is :row
+ # and +n+ is not an
+ # {Integer-convertible object}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Integer-Convertible+Objects].
+ # table.by_row! # => #
+ # # Raises TypeError (no implicit conversion of String into Integer):
+ # table['Name']
+ #
+ # ---
+ #
+ # The expression table[range], where +range+ is a Range object,
+ # returns rows from the table, beginning at row range.first,
+ # if those rows exist, and if the access mode is :row or :col_or_row:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_row! # => #
+ # rows = table[1..2] # => #
+ # rows # => [#, #]
+ # table.by_col_or_row! # => #
+ # rows = table[1..2] # => #
+ # rows # => [#, #]
+ #
+ # If there are too few rows, returns all from range.first to the end:
+ # rows = table[1..50] # => #
+ # rows # => [#, #]
+ #
+ # Special case: if range.start == table.size, returns an empty \Array:
+ # table[table.size..50] # => []
+ #
+ # If range.end is negative, calculates the ending index from the end:
+ # rows = table[0..-1]
+ # rows # => [#, #, #]
+ #
+ # If range.start is negative, calculates the starting index from the end:
+ # rows = table[-1..2]
+ # rows # => [#]
+ #
+ # If range.start is larger than table.size, returns +nil+:
+ # table[4..4] # => nil
+ #
+ # ---
+ #
+ # The expression table[header], where +header+ is a \String,
+ # returns column values (\Array of \Strings) if the column exists
+ # and if the access mode is :col or :col_or_row:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_col! # => #
+ # table['Name'] # => ["foo", "bar", "baz"]
+ # table.by_col_or_row! # => #
+ # col = table['Name']
+ # col # => ["foo", "bar", "baz"]
+ #
+ # Modifying the returned column values does not modify the table:
+ # col[0] = 'bat'
+ # col # => ["bat", "bar", "baz"]
+ # table['Name'] # => ["foo", "bar", "baz"]
+ #
+ # Returns an \Array of +nil+ values if there is no such column:
+ # table['Nosuch'] # => [nil, nil, nil]
def [](index_or_header)
if @mode == :row or # by index
(@mode == :col_or_row and (index_or_header.is_a?(Integer) or index_or_header.is_a?(Range)))