Created
December 5, 2011 15:47
-
-
Save kellyredding/1434021 to your computer and use it in GitHub Desktop.
Git-style namespaced key-value config file parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NamespacedKeyValueConfigFile | |
# This class parses a git-style config file of key=value configs grouped | |
# by [namespaces]. Each namespace gets a method that returns a hash of | |
# the key-value configs for the namespace. So given: | |
# [thing] | |
# key1 = val1 | |
# key2 = val2 | |
# [other] | |
# cool = true | |
# [nums] | |
# one = 1 | |
# You get: | |
# NamespacedKeyValueConfigFile.thing #=> {'key1' => 'val1', 'key2' => 'val2'} | |
# NamespacedKeyValueConfigFile.other #=> {'cool' => 'true'} | |
# NamespacedKeyValueConfigFile.nums #=> {'one' => '1'} | |
NAMESPACE_REGEX = /^\[(\w+)\].*/ | |
KEYVAL_REGEX = /^\W*(\w+)\s*=\s*([\w|\.|-]+).*/ | |
VALID_NS_REGEX = /^\w+$/ | |
attr_reader :__file__, :__data__ | |
def initialize(file) | |
self.__parse_file__(file) | |
end | |
def method_missing(meth, *args, &block) | |
if meth.to_s =~ VALID_NS_REGEX | |
(self.__data__.keys.include?(meth.to_s) ? self.__data__[meth.to_s] : {}).tap do |v| | |
block.call v if block | |
end | |
else | |
super | |
end | |
end | |
def respond_to?(*args) | |
meth = args.first | |
if meth.to_s =~ VALID_NS_REGEX && self.__data__.keys.include?(meth.to_s) | |
true | |
else | |
super | |
end | |
end | |
protected | |
# reset and reparse the data when a new file is given | |
def __parse_file__(file) | |
@__file__ = file | |
@__data__ = {} | |
File.open(self.__file__, "r") do |file| | |
file.readlines.each { |line| self.__parse_line__(line) } | |
end if self.__file__ && File.exists?(self.__file__.to_s) | |
end | |
def __parse_line__(line) | |
line.tap do | |
__set_ns__(line =~ NAMESPACE_REGEX ? $1 : @ns) | |
if @ns && line =~ KEYVAL_REGEX | |
self.__data__[@ns][$1] = $2 | |
end | |
end | |
end | |
private | |
def __set_ns__(ns) | |
return if ns.nil? || @ns == ns | |
self.__data__[ns] ||= {} | |
@ns = ns | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# bundler: gem 'assert', '~> 0.7' | |
require 'assert' | |
require 'config' | |
class NamespacedKeyValueConfigFile | |
class BasicTests < Assert::Context | |
desc "the namespaced key-value config file" | |
before do | |
@config = NamespacedKeyValueConfigFile.new(File.expand_path("../testcfg", __FILE__)) | |
end | |
subject { @config } | |
should have_reader :__file__, :__data__ | |
should "store data as a nested hash of key-values" do | |
assert_kind_of ::Hash, subject.__data__ | |
assert_kind_of ::Hash, subject.__data__[subject.__data__.keys.first] | |
end | |
should "parse out key value data for each config" do | |
assert_equal 'true', subject.__data__['thing1']['status'] | |
assert_equal 'version1', subject.__data__['thing2']['v1'] | |
assert_equal 'version2', subject.__data__['thing2']['v2'] | |
assert_equal 'ver.sion3', subject.__data__['thing2']['v3'] | |
assert_equal 'ver-s4', subject.__data__['thing2']['v4'] | |
assert_equal 'cmd1', subject.__data__['line']['c1'] | |
end | |
should "proxy its top-level __data__ hash keys as namespace methods" do | |
subject.__data__.each do |ns, configs| | |
assert_respond_to ns, subject | |
assert_equal configs, subject.send(ns) | |
end | |
end | |
should "return an empty hash for valid namespaces not configured" do | |
assert_equal Hash.new, subject.not_configured | |
end | |
should "raise no method errors when accessing invalid namespaces" do | |
assert_raises NoMethodError do | |
subject.send(:'abc%&#') | |
end | |
assert_raises NoMethodError do | |
subject.send(:'meth-with-hash-in-name') | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[thing1] | |
status=true | |
# comment line | |
[thing2] | |
v1 = version1 | |
v2 = version2 | |
# comment line | |
v3 = ver.sion3#comment line | |
v4 = ver-s4 four | |
[line] | |
c1 = cmd1, cmd2 # comment line | |
[ns] | |
ns1 = 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment