mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
f6d2b48588
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47433 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
173 lines
5.8 KiB
Ruby
173 lines
5.8 KiB
Ruby
require 'rake/ext/core'
|
|
|
|
class String
|
|
|
|
rake_extension("ext") do
|
|
# Replace the file extension with +newext+. If there is no extension on
|
|
# the string, append the new extension to the end. If the new extension
|
|
# is not given, or is the empty string, remove any existing extension.
|
|
#
|
|
# +ext+ is a user added method for the String class.
|
|
#
|
|
# This String extension comes from Rake
|
|
def ext(newext='')
|
|
return self.dup if ['.', '..'].include? self
|
|
newext = (newext =~ /^\./) ? newext : ("." + newext) if newext != ''
|
|
self.chomp(File.extname(self)) << newext
|
|
end
|
|
end
|
|
|
|
rake_extension("pathmap") do
|
|
# Explode a path into individual components. Used by +pathmap+.
|
|
#
|
|
# This String extension comes from Rake
|
|
def pathmap_explode
|
|
head, tail = File.split(self)
|
|
return [self] if head == self
|
|
return [tail] if head == '.' || tail == '/'
|
|
return [head, tail] if head == '/'
|
|
return head.pathmap_explode + [tail]
|
|
end
|
|
protected :pathmap_explode
|
|
|
|
# Extract a partial path from the path. Include +n+ directories from the
|
|
# front end (left hand side) if +n+ is positive. Include |+n+|
|
|
# directories from the back end (right hand side) if +n+ is negative.
|
|
#
|
|
# This String extension comes from Rake
|
|
def pathmap_partial(n)
|
|
dirs = File.dirname(self).pathmap_explode
|
|
partial_dirs =
|
|
if n > 0
|
|
dirs[0...n]
|
|
elsif n < 0
|
|
dirs.reverse[0...-n].reverse
|
|
else
|
|
"."
|
|
end
|
|
File.join(partial_dirs)
|
|
end
|
|
protected :pathmap_partial
|
|
|
|
# Perform the pathmap replacement operations on the given path. The
|
|
# patterns take the form 'pat1,rep1;pat2,rep2...'.
|
|
#
|
|
# This String extension comes from Rake
|
|
def pathmap_replace(patterns, &block)
|
|
result = self
|
|
patterns.split(';').each do |pair|
|
|
pattern, replacement = pair.split(',')
|
|
pattern = Regexp.new(pattern)
|
|
if replacement == '*' && block_given?
|
|
result = result.sub(pattern, &block)
|
|
elsif replacement
|
|
result = result.sub(pattern, replacement)
|
|
else
|
|
result = result.sub(pattern, '')
|
|
end
|
|
end
|
|
result
|
|
end
|
|
protected :pathmap_replace
|
|
|
|
# Map the path according to the given specification. The specification
|
|
# controls the details of the mapping. The following special patterns are
|
|
# recognized:
|
|
#
|
|
# <tt>%p</tt> :: The complete path.
|
|
# <tt>%f</tt> :: The base file name of the path, with its file extension,
|
|
# but without any directories.
|
|
# <tt>%n</tt> :: The file name of the path without its file extension.
|
|
# <tt>%d</tt> :: The directory list of the path.
|
|
# <tt>%x</tt> :: The file extension of the path. An empty string if there
|
|
# is no extension.
|
|
# <tt>%X</tt> :: Everything *but* the file extension.
|
|
# <tt>%s</tt> :: The alternate file separator if defined, otherwise use #
|
|
# the standard file separator.
|
|
# <tt>%%</tt> :: A percent sign.
|
|
#
|
|
# The <tt>%d</tt> 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.
|
|
#
|
|
# Examples:
|
|
#
|
|
# 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
|
|
# 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
|
|
#
|
|
# Also the <tt>%d</tt>, <tt>%p</tt>, <tt>%f</tt>, <tt>%n</tt>,
|
|
# <tt>%x</tt>, and <tt>%X</tt> 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).
|
|
#
|
|
# For example:
|
|
#
|
|
# "src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class")
|
|
#
|
|
# returns:
|
|
#
|
|
# "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.
|
|
#
|
|
# For example:
|
|
#
|
|
# "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext|
|
|
# ext.downcase
|
|
# }
|
|
#
|
|
# Returns:
|
|
#
|
|
# "/path/to/file.txt"
|
|
#
|
|
# This String extension comes from Rake
|
|
def pathmap(spec=nil, &block)
|
|
return self if spec.nil?
|
|
result = ''
|
|
spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
|
|
case frag
|
|
when '%f'
|
|
result << File.basename(self)
|
|
when '%n'
|
|
result << File.basename(self).ext
|
|
when '%d'
|
|
result << File.dirname(self)
|
|
when '%x'
|
|
result << File.extname(self)
|
|
when '%X'
|
|
result << self.ext
|
|
when '%p'
|
|
result << self
|
|
when '%s'
|
|
result << (File::ALT_SEPARATOR || File::SEPARATOR)
|
|
when '%-'
|
|
# do nothing
|
|
when '%%'
|
|
result << "%"
|
|
when /%(-?\d+)d/
|
|
result << pathmap_partial($1.to_i)
|
|
when /^%\{([^}]*)\}(\d*[dpfnxX])/
|
|
patterns, operator = $1, $2
|
|
result << pathmap('%' + operator).pathmap_replace(patterns, &block)
|
|
when /^%/
|
|
fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
|
|
else
|
|
result << frag
|
|
end
|
|
end
|
|
result
|
|
end
|
|
end
|
|
|
|
end
|