public
Description: Git utilities for multiple repositories & submodules
Homepage: http://fiveruns.org
Clone URL: git://github.com/fiveruns/brigit.git
brigit / lib / brigit / config_parser.rb
100644 90 lines (74 sloc) 2.395 kb
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
88
89
90
module Brigit
  
  # Reworked from Sam Ruby's Ruby "PythonConfigParser," http://intertwingly.net/code/mars/planet/config.rb
  # which in turn is a port of Python's ConfigParser, http://docs.python.org/lib/module-ConfigParser.html
  class ConfigParser
    
    class Section
      
      attr_reader :name
      def initialize(name)
        @name = name
      end
      
      def options
        @options ||= {}
      end
      
      def method_missing(*args, &block)
        options.__send__(*args, &block)
      end
      
    end
    
    def self.section_pattern
      @section_pattern ||= /
\[ # [
([^\]]+) # very permissive!
\] # ]
/x
    end
    
    def self.option_pattern
      @option_pattern ||= /
([^:=\s][^:=]*) # very permissive!
\s*[:=]\s* # any number of space chars,
# followed by separator
# (either : or =), followed
# by any # space chars
(.*)$ # everything up to eol
/x
    end
 
 
    # FIXME: This is *way* ugly
    def parse(lines)
      sections = Hash.new { |_, name| Section.new(name) }
      section = nil
      option = nil
      lines.each_with_index do |line, number|
        next if skip? line
        if line =~ self.class.option_pattern
          # option line
          option, value = $1, $2
          option = option.downcase.strip
          value.sub!(/\s;.*/, '')
          value = '' if value == '""'
          section[option] = clean value
        elsif line =~ /^\s/ && section && option
          # continuation line
          value = line.strip
          section[option] = section[option] ? (section[option] << "\n#{clean value}") : clean(value)
        elsif line =~ self.class.section_pattern
          section = sections[$1]
          sections[$1] = section
          option = nil
        elsif !section
          raise SyntaxError, 'Missing section header'
        else
          raise SyntaxError, "Invalid syntax on line #{number}"
        end
      end
      sections
    end
    
    #######
    private
    #######
    
    def clean(value)
      value.sub(/\s*#.*/, '')
    end
    
    def skip?(line)
      line.strip.empty? || line =~ /^\s*[#;]/ || line =~ /^rem(\s|$)/i
    end
    
  end
  
end