Module: Pathname::Extensions::Pathmap

Defined in:
lib/pathname/extensions/pathmap.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(host) ⇒ Object



8
9
10
11
# File 'lib/pathname/extensions/pathmap.rb', line 8

def self.included(host)
  host.load_extensions :ext, :explode, :partial
  super
end

Instance Method Details

#pathmap(spec = nil, &block) ⇒ Object

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.

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.

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).

Examples:

'a/b/c/d/file.txt'.pathmap("%2d")   => 'a/b'
'a/b/c/d/file.txt'.pathmap("%-2d")  => 'c/d'
"src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class")
#=> "class/org/onestepback/proj/A.class"

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"


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# 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) ⇒ Pathname

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

Parameters:

  • patterns (String)
  • block (Proc)

Returns:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 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