The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Parse::Path::Role::Path - Role for paths

SYNOPSIS

   package Parse::Path::MyNewPath;

   use Moo;

   with 'Parse::Path::Role::Path';

   sub _build_blueprint { {
      hash_step_regexp  => qr/(?<key>\w+)|(?<quote>")(?<key>[^"]+)(?<quote>")/,
      array_step_regexp => qr/\[(?<key>\d{1,5})\]/,
      delimiter_regexp  => qr/(?:\.|(?=\[))/,

      unescape_translation => [],

      pos_translation => [
         [qr/.?/, 'X+1'],
      ],

      delimiter_placement => {
         HH => '.',
         AH => '.',
      },

      array_key_sprintf        => '[%u]',
      hash_key_stringification => [
         [qr/.?/, '%s'],
      ],
   } }

DESCRIPTION

This is the base role for Parse::Path and contains 95% of the code. The idea behind the path classes is that they should be able to get by with a single blueprint and little to no changes to the main methods.

BLUEPRINT

The blueprint class attribute is a hashref of various properties (built using _build_blueprint) that detail how the path is parsed and put back together. All properties are required, though some can be turned off.

Path parsing

hash_step_regexp

hash_step_regexp => qr/(?<key>\w+)|(?<quote>")(?<key>[^"]+)(?<quote>")/

Regular expression for parsing a hash step. This should be a compiled RE, with a named capture called key. Optionally, a quote capture can be added for quoting capabilities.

Zero-length strings are acceptable if the RE allows for it. In some cases, ZLS are needed for root paths, ie: a delimiter as the first character of a path.

Beginning/ending markers should not be used, as they will be applied as needed.

array_step_regexp

array_step_regexp => qr/\[(?<key>\d{1,5})\]/
array_step_regexp => qr/\Z.\A/   # no-op; turn off array support

Regular expression for parsing an array step. This should be a compiled RE, with a named capture called key. Non-digits are not recommended, and really don't make sense in the scope of an array. Also, the RE should have some sort of digit limit to prevent overly sparse arrays. (See "Sparse arrays and memory usage" in Parse::Path.)

Arrays are checked first, as hashs could have zero-length strings. Arrays should not have zero-length strings, since they should match some sort of digit.

Paths that don't use arrays still require a RE, but can use a no-op like the one above.

delimiter_regexp

delimiter_regexp => qr/(?:\.|(?=\[))/

Regular expression for parsing path delimiter. This is always parsed after the hash/array step.

unescape_translation

   unescape_translation => [
      [qr/\"/, \&String::Escape::unbackslash],
      [qr/\'/, sub { my $str = $_[0]; $str =~ s|\\([\'\\])|$1|g; $str; }],
   ],

   unescape_translation => []  # turn off unescape support

Arrayref-of-arrayrefs used to unescape special characters in a key. Acts like a hashref, but is protected from Regexp stringification. The first value is a regular expression matching the quote capture (from "hash_step_regexp"). The value is a coderef of a subroutine that unescapes the string, as a single parameter in and out.

As this is a "hashref", multiple subs are supported. This is useful for allowing single quotes in literal strings (with a smaller subset of escape characters) and double quotes in strings that allow full escaping.

If quotes and escapes are used, the "hash_step_regexp" needs to be smart enough to handle all cases of quote escaping. (See the code in Parse::Path::DZIL for an example.)

Unescape support can be turned off by using an empty array. (But, the blueprint key still needs to exist.)

pos_translation

pos_translation => [
   [qr{^/+$},     0],
   [qr{^\.\./*$}, 'X-1'],
   [qr{^\./*$},   'X-0'],
   [qr{.?},       'X+1'],
],

Arrayref-of-arrayrefs used for pos translation. Acts like a hashref, but is protected from Regexp stringification. These are the absolute and relative identifers of the path. The "key" is a regular expression matching both the path step and right-side delimiter (extracted from shift_path_str).

The value meanings are as follows:

X+# = Forward relative path
X-0 = Stationary relative path (like . for file-based paths)
X-# = Backward relative path
#   = Absolute path (# = step position)

One of these REs must match, or the parser will die when it finds one it can't parse. Thus, it's advisable to have a "default" RE like qr/.?/.

Don't assume the RHS delimiter is going to be there. There may be cases where it's missing (like if key2hash was not passed a pos).

If the path doesn't have relative/absolute steps, it should be defined with a default of X+1.

Path stringification

delimiter_placement

delimiter_placement => {
   '0R' => '/',
   HH   => '.',
   AH   => '.',
},

Hashref used for delimiter placement. The keys have the following meanings:

    ##[LR]   = Position-specific placement, either on the left or right side of the step.
               Position can also be '-1' for the end of the path.

    [AH][AH] = Type-specific placement in-between the two types (ie: AH means an array on the left side
               and a hash on the right).

    [AH]     = Type-specific placement for the end of the path.

The value is the delimiter used in the placement.

array_key_sprintf

array_key_sprintf => '[%u]'
array_key_sprintf => ''  # turn off array support

String for sprintf that stringifies an array key to a step in the path.

hash_key_stringification

hash_key_stringification => [
   [qr/[^\"]+/, '"%s"' => \&String::Escape::backslash],
   [qr/\W|^$/,  "'%s'" => sub { my $str = $_[0]; $str =~ s|([\'\\])|\\$1|g; $str; }],
   [qr/.?/,     '%s'],
],

Arrayref-of-arrayrefs used for stringification of a hash key to a step in the path. The internal arrayref is composed of three pieces:

1 => RegexpRef = Matched against the hash key
2 => Str       = String for sprintf used for stringification
3 => CodeRef   = (Optional) Sub used to transform key prior to sprintf call

The third piece is typically used for backslashification. Using multiple REs, you can add in different conditions for different kinds of quoting.

CAVEATS

See "CAVEATS" in Parse::Path.

AVAILABILITY

The project homepage is https://github.com/SineSwiper/Parse-Path/wiki.

The latest version of this module is available from the Comprehensive Perl Archive Network (CPAN). Visit http://www.perl.com/CPAN/ to find a CPAN site near you, or see https://metacpan.org/module/Parse::Path/.

AUTHOR

Brendan Byrd <bbyrd@cpan.org>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2013 by Brendan Byrd.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)