### ----------------------------------------------------
### -- Text::CSV
### -- Licenses: Artistic-2.0
### -- Authors: H.Merijn Brand (Tux)
### -- File: doc/Text-CSV.pod
### ----------------------------------------------------
### -- Chunk 2 of 3
 will croak and set error 2013.

Using L</colrange> and L</rowrange> instead of L</fragment> will allow you
to combine row- and column selecting as a grid.

=head2 colrange
X<colrange>

 my Int @range = ^5, 5..9;
 $csv.colrange(@range);
 $csv.colrange("0-4;6-10");
 my @range = $csv.colrange;

Set or inspect the column ranges. When passed as an array of C<Int>, the
indexes are 0-based. When passed as a string, the syntax of the range is as
defined by L<RFC7111|/fragment> and thus 1-based.

=head2 rowrange
X<rowrange>

 $csv.rowrange("1;16-*");
 my @r = $csv.rowrange;

Set or inspect the row ranges. Only supports L<RFC7111|/fragment> style.
Indexes are 1-based.

=head2 column_names
=head2 column-names
X<column_names>
X<column-names>

Set the "keys" that will be used in the L</getline_hr> calls. If no keys
(column names) are passed, it will return the current setting as a list.

 $csv.column_names(< code description price >);
 my @names = $csv.column_names;

L</column_names> accepts a list of strings (the column names) or a single
array with the names. You can pass the return value from L</getline> too:

 $csv.column_names($csv.getline($io));

L</column_names> does B<no> checking on duplicates at all, which might lead
to unexpected results. As raku does not accept undefined keys in a hash,
passing just types will lead to fail later on.

 $csv.column_names(Str, "", "name"); # Will FAIL becaus of Str
 $csv.column_names(< code name count name >); # will drop the second column
 %hr = $csv.getline_hr($io);

=head2 header

Parse the CSV header and set C<sep> and encoding.

 my @hdr = $csv.header($fh).column-names;
 $csv.header($fh, sep-set => [ ";", ",", "|", "\t" ]);
 $csv.header($fh, munge-column-names => "fc");

The first argument should be a file handle.

Assuming that the file opened for parsing has a header, and the header does
not contain problematic characters like embedded newlines, read the first
line from the open handle then auto-detect whether the header separates the
column names with a character from the allowed separator list.

If any of the allowed separators matches, and none of the I<other> allowed
separators match, set L<C<sep>|/sep> to that separator for the current
CSV_XS instance and use it to parse the first line, map those to lowercase,
and use that to set the instance L</column_names>:

 my $csv = Text::CSV.new;
 my $fh = open "file.csv";
 $csv.header($fh);
 while (my $row = $csv.getline_hr($fh)) {
     ...
     }

If the header is empty, contains more than one unique separator out of the
allowed set, contains empty fields, or contains identical fields (after
folding), it will croak with error 1010, 1011, 1012, or 1013 respectively.

If the header contains embedded newlines or is not valid CSV in any other
way, this method will throw an exception.

A successful call to C<header> will always set the L<C<sep>|/sep> of the
C<$csv> object. This behavior can not be disabled.

=head3 return value

On error this method will throw an exception.

On success, this method will return the instance.

=head3 Options

=over 2

=item sep-set

 $csv.header($fh, sep_set => [ ";", ",", "|", "\t" ]);

The list of legal separators defaults to C<[ ";", "," ]> and can be changed
by this option.

Multi-byte sequences are allowed, both multi-character and Unicode. See
L<C<sep>|/sep>.

=item munge-column-names

This option offers the means to modify the column names into something that
is most useful to the application. The default is to map all column names
to fold case.

 $csv.header($fh, munge-column-names => "lc");

The following values are available:

  fc   - fold case
  lc   - lower case
  uc   - upper case
  none - do not change
  &cb  - supply a callback

 $csv.header($fh, munge-column-names => { "column_".$col++ });

=item set-column-names

 $csv.header($fh, :set-column-names);

The default is to set the instances column names using L</column_names> if
the method is successful, so subsequent calls to L</getline_hr> can return
a hash. Disable setting the header can be forced using a false value for
this option like C<:!set-column-names>.

=back

=head2 bind_columns
=head2 bind-columns
X<bind_columns>
X<bind-columns>

NYI!

Takes a list of scalar references to be used for output with L</print> or
to store in the fields fetched by L</getline>. When you do not pass enough
references to store the fetched fields in, L</getline> will fail with error
C<3006>. If you pass more than there are fields to return, the content of
the remaining references is left untouched.

 $csv.bind_columns(\$code, \$name, \$price, \$description);
 while ($csv.getline($io)) {
     print "The price of a $name is \x[20ac] $price\n";
     }

To reset or clear all column binding, call L</bind_columns> with the single
undefined argument like C<Array>. This will also clear column names.

 $csv.bind_columns(Array);

If no arguments are passed at all, L</bind_columns> will return the list of
current bindings or C<Array> if no binds are active.

=head2 eof
X<eof>

 $eof = $csv.eof;

If L</parse> or L</getline> was used with an IO stream, this method will
return C<True> if the last call hit end of file, otherwise it will return
C<False>. This is useful to see the difference between a failure and end
of file.

If the last L</parse> or L</getline> finished just before end of file, the
B<next> L</parse> or L</getline> will fail and set C<eof>.

That implies that if you are I<not> using L</auto-diag>, an idiom like

 while (my @row = $csv.getline ($fh)) {
     # ...
     }
 $csv.eof or $csv.error_diag;

will I<not> report the error. You would have to change that to

 while (my @row = $csv.getline ($fh)) {
     # ...
     }
 $csv.error_diag.error and $csv.error_diag;

=head2 types
X<types>

NYI!

 $csv.types(@types);
 my @types = $csv.types;

This method is used to force a type for all fields in a column. For
example, if you have an integer column, two columns with doubles and a
string column, then you might do a

 $csv.types(Int, Num, Num, Str);

You can unset column types by doing a

 $csv.types(Array);

=head2 row
X<row>

 CSV::Row $row = $csv.row;

Returns the last row parsed. See L<C<CSV::Row>|/CSV::Row>

=head2 fields
X<fields>

 CSV::Field @fields = $csv.fields;

This method returns the input to L</combine> or the resultant decomposed
fields of a successful L</parse> or L</getline>, whichever was called more
recently. The fields are still of type L<C<CSV::Field>|/CSV::Field> and
thus feature attributes.

=head2 strings
X<strings>

 @fields = $csv.strings;

This method returns the input to L</combine> or the resultant decomposed
fields of a successful L</parse> or L</getline>, whichever was called more
recently. The fields are simplified to Str entries from
L<C<CSV::Field>|/CSV::Field>, so no attributes ate available.

NYI: If types are used, the fields should comply to the types.

=head2 meta_info
X<meta_info>

=head2 meta-info
X<meta-info>

 $csv.meta_info(True);
 my $km = $csv.keep_meta;

This methods sets or inquires the default setting for keeping meta-info on
fields. See L<C<CSV::Field>|/CSV::Field>.

=head2 is_quoted
X<is_quoted>

=head2 is-quoted
X<is-quoted>

 my $quoted = $csv.is_quoted($column_idx);

Where C<$column_idx> is the (zero-based) index of the column in the last
result of L</parse> or L</getline>, even if C<meta> was false on that last
invocation.

This returns C<True> if the data in the indicated column was enclosed in
L<C<quote_char>|/quote_char> quotes. This might be important for fields
where content C<,20070108,> is to be treated as a numeric value, and where
C<,"20070108",> is explicitly marked as character string data.

Also see L<C<CSV::Field>|/CSV::Field>.

=head2 is_binary
X<is_binary>

=head2 is-binary
X<is-binary>

NYI/WIP: utf8-c8

 my $binary = $csv.is_binary($column_idx);

Where C<$column_idx> is the (zero-based) index of the column in the last
result of L</parse> or L</getline>, even if C<meta> was false on that last
invocation.

Also see L<C<CSV::Field>|/CSV::Field>.

=head2 is_missing
X<is_missing>

=head2 is-missing
X<is-missing>

NYI

 my $missing = $csv.is_missing($column_idx);

Where C<$column_idx> is the (zero-based) index of the column in the last
result of L</parse> or L</getline>, even if C<meta> was false on that last
invocation.

 while (my @row = $csv.getline_hr($fh, :meta)) {
     $csv.is_missing(0) and next; # This was an empty line
     }

When using L</getline_hr>, it is impossible to tell if the parsed fields
are undefined because they where not filled in the C<CSV> stream or because
they were not read at all, as B<all> the fields defined by L</column_names>
are set in the hash-ref. If you still need to know if all fields in each
row are provided, you should enable L<C<keep_meta>|/keep_meta> so you can
check the flags.

=head2 status
X<status>

 $status = $csv.status;

This method returns success (or failure) of the last invoked L</combine> or
L</parse> call.

=head2 error_input
X<error_input>

=head2 error-input
X<error-input>

 $bad_argument = $csv.error_input;

This method returns the erroneous argument (if it exists) of L</combine>,
L</parse>, or L</getline>, whichever was called most recent. If the last
invocation was successful, C<error_input> will return C<Str>.

=head1 DIAGNOSTICS

Errors are transported internally using the L<C<CSV::Diag>|/CSV::Diag>
class.  Text::CSV will return that object when it fails, so it can be
caught, but on non-fatal failures, like parse returning C<False>, one can
use the methods to inquire the internal status.

=head2 CSV::Diag

The method is created with the widest possible use in mind, serving both
the mindset of raku as well as the direct approach of the old module. It
is immutable: it is created with all available error parameters known at
the time of failure, and the cannot be changed afterwards.

 my CSV::Diag $d .= new(
     error   => 0,
     message => "",
     pos     => 0,
     field   => 0,
     record  => 0,
     buffer  => Str
     );

If only C<error> is given, the message is set accordingly if it is a known
error value.

The object can be used in many contexts:

=over 2

=item void context

 CSV::Diag.new(error => 2034, buffer => q{ "",}, pos => 1);

will print

 EIF - Loose unescaped quote : error 2034 @ record 1, field 1, position 2
  "?",

which is what happens when L<C<auto_diag>|/auto_diag> is C<True> and you
parse illegal CSV:

 Text::CSV.new(:auto_diag).parse(q{ "",});'
 EIF - Loose unescaped quote : error 2034 @ record 1, field 1, position 2
  "?",

=item numeric context

Will return the error code

 my Int $e;
 {   fail CSV::Diag(error => 2034);
     CATCH { default { $e = +$_; }}
     }
 # $e is now 2034

=item string context

Will return the error message

 my Str $e;
 {   fail CSV::Diag(error => 2034);
     CATCH { default { $e = ~$_; }}
     }
 # $e is now "EIF - Loose unescaped quote"

=item list context

All of the 6 items can be retrieved as a list or positional:

 {   fail CSV::Diag(error => 2034);
     CATCH { default { $_[0].say; }}
     }

The indices are chosen to be compatible with the old API

 $e[0] = error number
 $e[1] = error message
 $e[2] = error position in buffer
 $e[3] = field number
 $e[4] = record number
 $e[5] = errror buffer

=item hash context

All of the 6 items can be retrieved as a hash entry

 {   fail CSV::Diag(error => 2034);
     CATCH { default { $_<errno>.say; }}
     }

The keys are chosen to be compatible with the old API.

 $e<errno>  = error number
 $e<error>  = error message
 $e<pos>    = error position in buffer
 $e<field>  = field number
 $e<recno>  = record number
 $e<buffer> = errror buffer

=back

The CSV::Diag is also used by this Text::CSV method

=head2 error_diag
X<error_diag>

=head2 error-diag
X<error-diag>

 $csv.error_diag;
 $error_code = +$csv.error_diag;
 $error_str  = ~$csv.error_diag;
 ($cde, $str, $pos, $rec, $fld) = $csv.error_diag;

This function returns the diagnostics of the most recent error.

If called in void context, this will print the internal error code and the
associated error message along with the record number, the position of the
failure and the buffer of failure with an eject symbol at that position:

 $csv.parse(q{ "",})
 $csv.error_diag;

will print

 EIF - Loose unescaped quote : error 2034 @ record 1, field 1, position 2
  "?",

If called in list context, this will return the error code, the error
message, the location within the line that was being parsed, the record
number, and the buffer itself in that order. Their values are 1-based. The
position currently is index of the character at which the parsing failed in
the current record. The record number the index of the record parsed by the
csv instance. The field number is the index of the field the parser thinks
it is currently trying to parse.

If called as C<+$csv.error_diag> or C<$csv.error_diag.Num>, it will return
the error code. If called as C<~$csv.error_diag> or C<$csv.error_diag.Str>
it will return the error message.

=head2 record_number
X<record_number>

 $recno = $csv.record_number;

Returns the records parsed by this csv instance. This value should be more
accurate than C<$.> when embedded newlines come in play. Records written by
this instance are not counted.

=head2 set_diag
X<set_diag>

 $csv.set_diag(0);
 $csv.set_diag(2025, pos => 12, fieldno => 4, recno => 99);

Use to (re)set the diagnostics if you are dealing with errors.

=head1 CSV::Field

The fields are internally represented as CSV::Field objects. Any methods
that directly or indirectly supports the C<meta> attribute controls
weather the returned fields will be of this CSV::Field type or that the
fields are simplified to a simple basic type.

If the fields are represented/returned as CSV::Field, it supports these
methods:

=head2 new

 my CSV::Field $f .= new;
 my $f = CSV::Field.new("foo");
 my $f = CSV::Field.new(1);

Instantiate a new field. Optionally takes a C<Cool>.

=head2 Bool

 ?$f     and say "The field is true";
 $f.Bool and say "This field is true too";

Return the boolean value of the field. As CSV is text-only be design, this
will also return C<False> for C<"0">, where raku sees C<"0"> as C<True>.

=head2 text
=head2 Str

 $str = ~$f;
 $str = $f.Str;
 $str = $f.text;

Return the string representation of the field.

=head2 Buf

 $buf = $f.Buf;

Return the field data as "utf8-c8" encoded Buf.

=head2 Numeric

 $i = +$f;
 $i = $f.Int;
 $i = $f.Num;

Return the numeric representation of the field.

=head2 gist

 $f.gist.say;

Will show a complete compressed representation of the field with properties.
C<Q> is quoted, C<q> is unquoted. Likewise for C<B/b> for binary, C<8/7>
for Unicode-ness and C<M/m> for missing.

A field that was parsed as C<,cat,> would return

 qb7m:"cat"

A field parsed as C<,"Ħēłĺº",> would return

 QB8m:"Ħēłĺº"

=head2 add

 $f.add($str);

Accepts a Str to be added to this field.

=head2 set_quoted

 $f.set_quoted;

Set the fact the the field was/is quoted.

=head2 is_quoted

 $f.is_quoted and say "The field was quoted in CSV";

Is C<True> when the parsed field was quoted in the source.

=head2 undefined

 $f.undefined and say "The field is undefined";

Returns C<True> when the field is undefined. As CSV is all about strings,
the various options that allow interpreting empty fields as undefined make
this a required method.

=head2 is_binary

WIP: utf8-c8

 $f.is_binary and say "Do we need a Buf instead?";

Returns true if the field has data beyond ASCII.

=head2 is_utf8

 $f.is_utf8 or say "The field is empty or pure ACII";

Returns C<True> if the field is beyond ASCII, but still valid UTF-8.

=head2 is_missing

WIP

 $f.is_missing and fail;

Returns C<True> if the field is missing.

=head1 CSV::Row
X<CSV::Row>

This class is a wrapper over the current row of fields just to add
convenience methods.

This is the only argument to callbacks.

The fields in C<CSV::Row> are always of class L<C<CSV::Field>|/CSV::Field>
and thus contain all meta-information, even if the C<Text::CSV> attribute
L<C<meta_info>|/meta_info> is C<False>.

=head2 methods

=over 2

=item new

 my CSV::Row $row .= new;
 my CSV::Row $row .= new(csv => $csv, fields => @f.map({ CSV::Field.new(*) });

=item csv

The current Text::CSV object related to this row.

=item elems

Return the number of fields in the row.

=item fields

The fields (CSV::Field items) this row consist of.

=item push

 $row.push(CSV::Field.new(1));
 $row.push(1);
 $row.push("foo");
 $row.push($another-row);

Pushing simple things onto the row will extend the row by converting these
to CSV::Field objects.

Pushing a CSV::Row onto the row will extend that row with the fields of the
row being pushed.

=item pop

 my CSV::Field $f = $row.pop;

=item Str

 my $str = $row.Str;
 $io.say(~$row);

The stringification of the CSV::Row object is like invoking the
L<C<string>|/string> method. This only works if there is a Text::CSV
object known to the CSV::Row instance.

=item hash

 my %h = $row.hash;

Returns the hash with C<.csv>'s L<C<column_names>|/column_names> as keys
and the C<.text> of each matching C<fields> entry as values.

=item strings

 my @l = $row.strings;

Returns the C<.text> part of each entry in C<.fields>.

=back

The row allow direct indexing and iteration as well as hash addressing when
L</column_names> are set.

 my $field = $row[1];
 my $field = $row<foo>;

The last parsed row of a L<Text::CSV>|/Text::CSV> can be acquired using

 my CSV::Row $row = $csv.row;

################################################################################

=head1 FUNCTIONS

=head2 csv
X<csv>

This is an high-level function that aims at simple (user) interfaces. This
can be used to read/parse a C<CSV> file or stream (the default behavior) or
to produce a file or write to a stream (define the C<out> attribute). It
returns an array- or hash-reference on parsing or the
numeric value of L</error_diag> on writing. When this function fails you
can get to the error using the class call to L</error_diag>

 my $aoa = csv(in => "test.csv") or
     die Text::CSV.error_diag;

This function takes the arguments as key-value pairs. This can be passed as
a list or as an anonymous hash:

 my $aoa = csv(in => "test.csv", sep => ";");
 my $aoh = csv(in => $fh, :headers);

The arguments passed consist of two parts: the arguments to L</csv> itself
and the optional attributes to the C<CSV> object used inside the function
as enumerated and explained in L</new>.

If not overridden, the default option used for CSV is

 auto_diag => 1

The option that is always set and cannot be altered is

 binary    => 1

=head3 in
X<in>

Used to specify the source. C<in> can be a file name (e.g. C<"file.csv">),
which will be opened for reading and closed when finished, a file handle
(e.g. C<$fh> or C<FH>), a reference to a glob (e.g. C<\*ARGV>), the glob
itself (e.g. C<*STDIN>), or a reference to a scalar (e.g. C<\q{1,2,"csv"}>).

When used with L</out>, C<in> should be a reference to a CSV structure (AoA
or AoH) or a Callable (Sub, Routine, Code, or Block) that returns an
array-reference or a hash-reference.  The code-ref will be invoked with no
arguments.

 my $aoa = csv(in => "file.csv");

 open my $fh, "<", "file.csv";
 my $aoa = csv(in => $fh);

 my $csv = [[qw( Foo Bar )], [ 1, 2 ], [ 2, 3 ]];
 my $err = csv(in => $csv, out => "file.csv");

The C<in> attribute supports a wide range of types, all of which can be
combined with the use of C<fragment>:

=over 2

=item Str

 csv(in => "file.csv")

A plain string is interpreted as a file name to be opened for parsing.

=item IO

 my $io = open "file.csv", :r;
 csv(in => $io);

Parse from the already opened data stream.

=item Capture

 csv(in => \("str,ing"));

Parse from a single string.

=item Array of Strings

 csv(in => ["a,b\n1,2\n3,4\n"]);
 csv(in => ["a,b", "1,2", "3,4"]);

Parse from the String(s)

=item Array of Data

 csv(in => [[<a b>], [1, 2], [3, 4]]);
 csv(in => [{:a(1), :b(2)}, {:a(3), :b(4)}]);

Use the data as provided

=item Sub, Routine

 sub provider {
     @data.elems == 0 and return False;
     return @data.pop;
     }
 csv(in => &provider);

While the providing Routine returns a data row, use that as is. Stop when
the provider returns C<False>.

=item Callable, Block

 csv(in => { $sth.fetch });

While the providing Callable returns a data row, use that as is. Stop when
the provider returns C<False>.

=item Supply

 my $supply = Supply.from-list(@data);
 csv(in => $supply);

Fetch data rows from the supply.

=item Channel

 my $ch = Channel.new;
 start {
     $ch.send($_) for @data;
     $ch.close;
     }
 csv(in => $ch);

Fetch data from the Channel.

=item Iterator

 csv(in => @data.iterator);

Fetch data rows from the iterator.

=item Any

 csv(in => Any);

is a shortcut/fallback for

 csv(in => $*IN);

=back

=head3 out
X<out>

In output mode, the default CSV options when producing CSV are

 eol    => "\r\n"

The L</fragment> attribute is ignored in output mode.

C<out> can be a file name (e.g. C<"file.csv">), which will be opened for
writing and closed when finished, a file handle (e.g. C<$fh> or
C<IO::Handle>), a C<Channel>, a C<Supply>, a C<Callable>, or C<Nil>.

 csv(in => sub { $sth.fetch },        out => "dump.csv");
 csv(in => { $sth.fetchrow_hashref }, out => "dump.csv",
      headers => $sth.{NAME_lc});

When a code-ref is used for C<in>, the output is generated per invocation,
so no buffering is involved. This implies that there is no size restriction
on the number of records. The C<csv> function ends when the coderef returns
C<False>.

When a Callable is used for out, it is called on each row with the row as
only argument.

When C<Nil> is used for out, the output is completely suppressed. This can
be useful when streaming, and the output is not required, but the
side-effects of e.g. an C<on-in> hook is dealing with the data.

=over 2

=item Str:U

 my $str = csv(in => $in, out => Str);

Returns a single String of CSV data.

=item Str:D

 my $str = csv(in => $in, out => "out.csv");

Writes the data as CSV to the named file.

=item Array:U

 my $aoa = csv(in => $in, out => Array);

Returns an Array of Arrays.

=item Array:D

 my $aoa = csv(in => $in, out => @data);

Adds the records to an existing Array. If the existing array is not empty,
the type of the first record determines adding a list of Arrays or a list
of Hashes.

=item Hash:U

 my $aoh = csv(in => $in, out => Hash);

Returns an Array of Hashes

=item IO:D

 my $io = open "file.csv", :w;
 csv(in => $in, out => $io);

Writes the data as CSV to the IO handle.

=item Callable, Block, Sub, Routine

 my @d;
 csv(in => $in, out => { @d.push: $_ });

Passes the data rows to the Callable

=item Channel:U

 my $ch = csv(in => $in, out => Channel, :!meta);
 react {
     whenever $ch -> \row {
         @d.push: row;
         LAST { done; }
         }
     }

Writes the data rows into a new Channel, which is returned.

=item Channel:D

 my $ch = Channel.new;
 my $pr = start {
     react {
         whenever $ch -> \row {
             @d.push: row;
             LAST { done; }
             }
         }
     }
 csv(in => $in, out => $ch);
 await $pr;

Writes the data rows into the existing Channel.

=item Supplier:D

 my $sup = Supplier.new;
 $sup.Supply.tap (-> \row { @d.push: row; });
 csv(in => $in, out => $sup, :!meta);

Writes the data rows into the Supplier.

=item Supply:U

 my $sup = csv(in => $in, out => Supply, :!meta);
 $ch.tap (-> \row { @d.push: row; });

Writes the data rows into a new Supply.

=back

=head3 encoding
X<encoding>

If passed, it should be an encoding accepted by the C<:encoding()> option
to C<open>. There is no default value.

If C<encoding> is set to the literal value C<"auto">, the method L</header>
will be invoked on the opened stream to check if there is a BOM and set the
encoding accordingly. This is equal to passing True in the option
L<C<detect-bom>|/detect-bom>.

=head3 detect-bom
X<detect-bom>
X<detect_bom>

NYI for various reasons. Also see L</is-binary>

If C<detect-bom> is given, the method L</header> will be invoked on the
opened stream to check if there is a BOM and set the encoding accordingly.

C<detect_bom> can be abbreviated to C<bom>.

This is the same as setting L<C<encoding>|/encoding> to C<"auto">.

Note that as the method L</header> is invoked, its default is to also set
the headers.

=head3 headers
X<headers>

If this attribute is not given, the default behavior is to produce an array
of arrays.

If C<headers> is supplied, it should be an Array of column names, a Bool, a
Hash, a Callable, or a literal flag: C<auto>, C<lc>, C<uc>, or C<skip>.

=over 2

=item skip

When C<skip> is used, the header will not be included in the output.

 my $aoa = csv(in => $fh, headers => "skip");

=item auto

If C<auto> is used, the first line of the C<CSV> source will be read as the
list of field headers and used to produce an array of hashes.

 my $aoh = csv(in => $fh, headers => "auto");

=item lc

If C<lc> is used, the first line of the C<CSV> source will be read as the
list of field headers mapped to lower case and used to produce an array of
hashes. This is a variation of C<auto>.

 my $aoh = csv(in => $fh, headers => "lc");

=item uc

If C<uc> is used, the first line of the C<CSV> source will be read as the
list of field headers mapped to upper case and used to produce an array of
hashes. This is a variation of C<auto>.

 my $aoh = csv(in => $fh, headers => "uc");

=item Bool

If C<True> is passed, the method L</header> will be invoked with the
default options on the opened stream to check if there is a BOM and set the
encoding accordingly, detect and set L<C<sep>|/sep>, L<C<eol>|/eol> and
column names.

=item Callable

If a Callable is used, the first line of the C<CSV> source will be read as
the list of mangled field headers in which each field is passed as the only
argument to the coderef. This list is used to produce an array of hashes.

 my $i = 0;
 my $aoh = csv(in => $fh, headers => { $^h.lc ~ $i++ });

this example is a variation of using C<lc> where all headers are forced to
be unique by adding an index.

=item ARRAY

If  C<headers> is an Array, the entries in the list will be used as field
names. The first line is considered data instead of headers.

 my $aoh = csv(in => $fh, headers => [< Foo Bar >]);

=item HASH

If C<headers> is a Hash, this implies C<auto>, but header fields for that
exist as key in the Hash will be replaced by the value for that key. Given
a CSV file like

 post-kode,city,name,id number,fubble
 1234AA,Duckstad,Donald,13,"X313DF"

using

 csv (headers => %{ "post-kode" => "pc", "id number" => "ID" }, ...

will return an entry like

 { pc     => "1234AA",
   city   => "Duckstad",
   name   => "Donald",
   ID     => "13",
   fubble => "X313DF",
   }

=back

See also L<C<munge-column-names>|/munge-column-names> and
L<C<set-column-names>|/set-column-names>.

=head3 munge-column-names
X<munge-column-names>
X<munge_column_names>

If C<munge-column-names> is set, the method L</header> is invoked on the
opened stream with all matching arguments to detect and set the headers.

C<munge-column-names> can be abbreviated to C<munge>.

=head3 key
X<key>

If passed, will default L<C<headers>|/headers> to C<"auto"> and return a
hashref instead of an array of hashes. Allowed values are simple strings
or arrays where the first element is the joiner and the rest are the fields
to join to combine the key

 my $ref = csv(in => "test.csv", key =>        "code");
 my $ref = csv(in => "test.csv", key => [ ":", "code", "color" ]);

with test.csv like

 code,product,price,color
 1,pc,850,gray
 2,keyboard,12,white
 3,mouse,5,black

the first example will return

 { 1   => {
       code    => 1,
       color   => 'gray',
       price   => 850,
       product => 'pc'
       },
   2   => {
       code    => 2,
       color   => 'white',
       price   => 12,
       product => 'keyboard'
       },
   3   => {
       code    => 3,
       color   => 'black',
       price   => 5,
       product => 'mouse'
       }
   }

the second example will return

 { "1:gray"    => {
       code    => 1,
       color   => 'gray',
       price   => 850,
       product => 'pc'
       },
   "2:white"   => {
       code    => 2,
       color   => 'white',
       price   => 12,
       product => 'keyboard'
       },
   "3:black"   => {
       code    => 3,
       color   => 'black',
       price   => 5,
       product => 'mouse'
       }
   }

If C<out> points to an existing Hash, the data will be added to that instead
(existing records will be overwritten on reading duplicate keys). It returns
the value passed to C<out>:

 my $ref = csv(in => "test.csv", out => %hash, key =>        "code");
 my $ref = csv(in => "test.csv", out => %hash, key => [ ":", "code", "color" ]);

=head3 fragment
X<fragment>

Only output the fragment as defined in the L</fragment> method. This option
is ignored when I<generating> C<CSV>. See L</out>.

Combining all of them could give something like

 use Text::CSV qw( csv );
 my @aoh = csv(
     in       => "test.txt",
     encoding => "utf-8",
     headers  => "auto",
     sep_char => "|",
     fragment => "row=3;6