module Pathname::Extensions::Pathmap

Public Class Methods

included(host) click to toggle source
Calls superclass method
# File lib/pathname/extensions/pathmap.rb, line 8
def self.included(host)
  host.load_extensions :ext, :explode, :partial
  super
end

Public Instance Methods

pathmap(spec = nil, &block) click to toggle source

Map the path according to the given specification. The specification controls the details of the mapping. The following special patterns are recognized:

  • `%p` - The complete path.

  • `%f` - The base file name of the path, with its file extension,

    but without any directories.
  • `%n` - The file name of the path without its file extension.

  • `%d` - The directory list of the path.

  • `%x` - The file extension of the path. An empty string if there

    is no extension.
  • `%X` - Everything but the file extension.

  • `%s` - The alternate file separator if defined, otherwise use #

    the standard file separator.
  • `%%` - A percent sign.

@note

The `%d` specifier can also have a numeric prefix (e.g. `%2d`).

If the number is positive, only return (up to) `n` directories in the
path, starting from the left hand side.

If `n` is negative, return (up to) `n` directories from the
right hand side of the path.

@example

'a/b/c/d/file.txt'.pathmap("%2d")   => 'a/b'
'a/b/c/d/file.txt'.pathmap("%-2d")  => 'c/d'

Also the `%d`, `%p`, `%f`, `%n`, `%x`, and `%X` operators can take a pattern/replacement argument to perform simple string substitutions on a particular part of the path. The pattern and replacement are separated by a comma and are enclosed by curly braces. The replacement spec comes after the % character but before the operator letter. (e.g. `%{old,new}d`). Multiple replacement specs should be separated by semi-colons (e.g. `%{old,new;src,bin}d`).

Regular expressions may be used for the pattern, and back refs may be used in the replacement text. Curly braces, commas and semi-colons are excluded from both the pattern and replacement text (let's keep parsing reasonable).

@example

"src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class")
#=> "class/org/onestepback/proj/A.class"

@example If the replacement text is '*', then a block may be provided to perform some arbitrary calculation for the replacement.

"/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext|
   ext.downcase
} #=> "/path/to/file.txt"
# File lib/pathname/extensions/pathmap.rb, line 65
def pathmap(spec = nil, &block)
  return self if spec.nil?
  result = +''
  # noinspection SpellCheckingInspection
  spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
    # noinspection SpellCheckingInspection
    case frag
    when '%f'
      result << basename.to_s
    when '%n'
      result << basename.ext.to_s
    when '%d'
      result << dirname.to_s
    when '%x'
      result << extname.to_s
    when '%X'
      result << ext.to_s
    when '%p'
      result << to_s
    when '%s'
      result << (File::ALT_SEPARATOR || File::SEPARATOR)
    when '%-'
      result
    when '%%'
      result << '%'
    when /%(-?\d+)d/
      result << partial(Regexp.last_match(1).to_i).to_s
    when /^%{([^}]*)}(\d*[dpfnxX])/
      patterns = Regexp.last_match(1)
      operator = Regexp.last_match(2)
      result << pathmap('%' + operator).pathmap_replace(patterns, &block).to_s
    when /^%/
      raise ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
    else
      result << frag
    end
  end
  Pathname(result)
end
pathmap_replace(patterns, &block) click to toggle source

Perform the pathmap replacement operations on the given path. The patterns take the form 'pat1,rep1;pat2,rep2…'.

@param patterns [String] @param block [Proc] @return [Pathname]

# File lib/pathname/extensions/pathmap.rb, line 111
def pathmap_replace(patterns, &block)
  result = self
  patterns.split(';').each do |pair|
    pattern, replacement = pair.split(',')
    pattern = Regexp.new(pattern)
    result = if replacement == '*' && block_given?
               result.sub(pattern, &block)
             elsif replacement
               result.sub(pattern, replacement)
             else
               result.sub(pattern, '')
             end
  end
  result
end