summaryrefslogtreecommitdiff
path: root/tool/vpath.rb
blob: 48ab148405d5b0cb0d5e6a66b5373c3519c9b0c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# -*- coding: us-ascii -*-

class VPath
  attr_accessor :separator

  def initialize(*list)
    @list = list
    @additional = []
    @separator = nil
  end

  def inspect
    list.inspect
  end

  def search(meth, base, *rest)
    begin
      meth.call(base, *rest)
    rescue Errno::ENOENT => error
      list.each do |dir|
        return meth.call(File.join(dir, base), *rest) rescue nil
      end
      raise error
    end
  end

  def process(*args, &block)
    search(File.method(__callee__), *args, &block)
  end

  alias stat process
  alias lstat process

  def open(*args)
    f = search(File.method(:open), *args)
    if block_given?
      begin
        yield f
      ensure
        f.close unless f.closed?
      end
    else
      f
    end
  end

  def read(*args)
    open(*args) {|f| f.read}
  end

  def foreach(file, *args, &block)
    open(file) {|f| f.each(*args, &block)}
  end

  def def_options(opt)
    opt.on("-I", "--srcdir=DIR", "add a directory to search path") {|dir|
      @additional << dir
    }
    opt.on("-L", "--vpath=PATH LIST", "add directories to search path") {|dirs|
      @additional << [dirs]
    }
    opt.on("--path-separator=SEP", /\A(?:\W\z|\.(\W).+)/, "separator for vpath") {|sep, vsep|
      # hack for msys make.
      @separator = vsep || sep
    }
  end

  def list
    @additional.reject! do |dirs|
      case dirs
      when String
        @list << dirs
      when Array
        raise "--path-separator option is needed for vpath list" unless @separator
        # @separator ||= (require 'rbconfig'; RbConfig::CONFIG["PATH_SEPARATOR"])
        @list.concat(dirs[0].split(@separator))
      end
      true
    end
    @list
  end

  def strip(path)
    prefix = list.map {|dir| Regexp.quote(dir)}
    path.sub(/\A#{prefix.join('|')}(?:\/|\z)/, '')
  end
end