iniparse-1.4.2/0000755000175000017500000000000012725022733013545 5ustar terceiroterceiroiniparse-1.4.2/iniparse.gemspec0000644000175000017500000000323612725022733016730 0ustar terceiroterceiro# Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.specification_version = 2 if s.respond_to? :specification_version= s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.rubygems_version = '1.3.5' ## Leave these as is they will be modified for you by the rake gemspec task. ## If your rubyforge_project name is different, then edit it and comment out ## the sub! line in the Rakefile s.name = 'iniparse' s.version = '1.4.2' s.date = '2015-12-03' s.rubyforge_project = 'iniparse' s.summary = 'A pure Ruby library for parsing INI documents.' s.authors = ['Anthony Williams'] s.email = 'hi@antw.me' s.homepage = 'http://github.com/antw/iniparse' s.licenses = ['MIT'] s.description = 'A pure Ruby library for parsing INI documents. ' \ 'Preserves the structure of the original document, ' \ 'including whitespace and comments' s.require_paths = %w(lib) s.rdoc_options = ['--charset=UTF-8'] s.extra_rdoc_files = %w(LICENSE README.rdoc) # Dependencies. s.add_development_dependency('rspec', '~> 2.14') # = MANIFEST = s.files = %w[ Gemfile LICENSE README.rdoc Rakefile TODO iniparse.gemspec lib/iniparse.rb lib/iniparse/document.rb lib/iniparse/generator.rb lib/iniparse/line_collection.rb lib/iniparse/lines.rb lib/iniparse/parser.rb ] # = MANIFEST = end iniparse-1.4.2/LICENSE0000644000175000017500000000205012725022733014547 0ustar terceiroterceiroCopyright (c) 2008-2010 Anthony Williams Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.iniparse-1.4.2/.travis.yml0000644000175000017500000000017412725022733015660 0ustar terceiroterceirolanguage: ruby script: "bundle exec rspec" bundler_args: "--without extras" rvm: - "2.1.0" - "1.9.3" - "jruby-19mode" iniparse-1.4.2/.rspec0000644000175000017500000000001012725022733014651 0ustar terceiroterceiro--color iniparse-1.4.2/README.rdoc0000644000175000017500000000534112725022733015356 0ustar terceiroterceiro= IniParse {Build Status}[http://travis-ci.org/antw/iniparse] IniParse is a pure Ruby library for parsing INI[http://en.wikipedia.org/wiki/INI_file] configuration and data files. === Main features * Support for duplicate options. While not common, some INI files contain an option more than once. IniParse does not overwrite previous options, but allows you to access all of the duplicate values. * Preservation of white space and blank lines. When writing back to your INI file, line indents, white space and comments (and their indents) are preserved. Only trailing white space (which has no significance in INI files) will be removed. * Preservation of section and option ordering. Sections and options are kept in the same order they are in the original document ensuring that nothing gets mangled when writing back to the file. If you don't need the above mentioned features, you may find the simpler IniFile gem does all you need. === Opening an INI file Parsing an INI file is fairly simple: IniParse.parse( File.read('path/to/my/file.ini') ) # => IniParse::Document IniParse.parse returns an IniParse::Document instance which represents the passed "INI string". Assuming you know the structure of the document, you can access the sections in the INI document with IniParse::Document#[]. For example: document = IniParse.parse( File.read('path/to/my/file.ini') ) document['a_section'] # => IniParse::Lines::Section document['a_section']['an_option'] # => "a value" document['a_section']['another_option'] # => "another value" In the event that duplicate options were found, an array of the values will be supplied to you. document = IniParse.parse <<-EOS [my_section] key = value key = another value key = a third value EOS document['my_section']['key'] # => ['value', 'another value', 'third value'] Options which appear before the first section will be added to a section called "__anonymous__". document = IniParse.parse <<-EOS driver = true [driver] key = value EOS document['__anonymous__']['driver'] # => true document['driver']['key'] # => 'value' === Updating an INI file document['a_section']['an_option'] # => "a value" document['a_section']['an_option'] = 'a new value' document['a_section']['an_option'] # => "a new value" Delete entire sections by calling `#delete` with the section name... document.delete('a_section') ... or a single option with `#delete` on the section object: document['a_section'].delete('an_option') === Creating a new INI file See IniParse::Generator. iniparse-1.4.2/lib/0000755000175000017500000000000012725022733014313 5ustar terceiroterceiroiniparse-1.4.2/lib/iniparse/0000755000175000017500000000000012725022733016125 5ustar terceiroterceiroiniparse-1.4.2/lib/iniparse/parser.rb0000644000175000017500000000556512725022733017761 0ustar terceiroterceiromodule IniParse class Parser # Returns the line types. # # ==== Returns # Array # def self.parse_types @@parse_types ||= [] end # Sets the line types. Handy if you want to add your own custom Line # classes. # # ==== Parameters # types:: An array containing Line classes. # def self.parse_types=(types) parse_types.replace(types) end self.parse_types = [ IniParse::Lines::Section, IniParse::Lines::Option, IniParse::Lines::Blank ] # Creates a new Parser instance for parsing string +source+. # # ==== Parameters # source:: The source string. # def initialize(source) @source = source.dup end # Parses the source string and returns the resulting data structure. # # ==== Returns # IniParse::Document # def parse IniParse::Generator.gen do |generator| @source.split("\n", -1).each do |line| generator.send(*Parser.parse_line(line)) end end end class << self # Takes a raw line from an INI document, striping out any inline # comment, and indent, then returns the appropriate tuple so that the # Generator instance can add the line to the Document. # # ==== Raises # IniParse::ParseError: If the line could not be parsed. # def parse_line(line) sanitized, opts = strip_indent(*strip_comment(line, {})) parsed = nil @@parse_types.each do |type| break if (parsed = type.parse(sanitized, opts)) end if parsed.nil? raise IniParse::ParseError, "A line of your INI document could not be parsed to a " \ "LineType: '#{line}'." end parsed end ####### private ####### # Strips in inline comment from a line (or value), removes trailing # whitespace and sets the comment options as applicable. def strip_comment(line, opts) if m = /^(^)(?:(;|\#)(\s*)(.*))$$/.match(line) || m = /^(.*?)(?:\s+(;|\#)(\s*)(.*))$/.match(line) # Comment lines. opts[:comment] = m[4].rstrip opts[:comment_prefix] = m[3] opts[:comment_sep] = m[2] # Remove the line content (since an option value may contain a # semi-colon) _then_ get the index of the comment separator. opts[:comment_offset] = line[(m[1].length..-1)].index(m[2]) + m[1].length line = m[1] else line.rstrip! end [line, opts] end # Removes any leading whitespace from a line, and adds it to the options # hash. def strip_indent(line, opts) if m = /^(\s+).*$/.match(line) line.lstrip! opts[:indent] = m[1] end [line, opts] end end end # Parser end # IniParse iniparse-1.4.2/lib/iniparse/lines.rb0000644000175000017500000002245712725022733017576 0ustar terceiroterceiromodule IniParse module Lines # A base class from which other line types should inherit. module Line # ==== Parameters # opts:: Extra options for the line. # def initialize(opts = {}) @comment = opts.fetch(:comment, nil) @comment_sep = opts.fetch(:comment_sep, ';') @comment_prefix = opts.fetch(:comment_prefix, ' ') @comment_offset = opts.fetch(:comment_offset, 0) @indent = opts.fetch(:indent, '') end # Returns if this line has an inline comment. def has_comment? not @comment.nil? end # Returns this line as a string as it would be represented in an INI # document. def to_ini [*line_contents].map { |ini| if has_comment? ini += ' ' if ini =~ /\S/ # not blank ini = ini.ljust(@comment_offset) ini += comment end @indent + ini }.join "\n" end # Returns the contents for this line. def line_contents '' end # Returns the inline comment for this line. Includes the comment # separator at the beginning of the string. def comment "#{ @comment_sep }#{ @comment_prefix }#{ @comment }" end # Returns whether this is a line which has no data. def blank? false end # Returns the options used to create the line def options { comment: @comment, comment_sep: @comment_sep, comment_prefix: @comment_prefix, comment_offset: @comment_offset, indent: @indent } end end # Represents a section header in an INI document. Section headers consist # of a string of characters wrapped in square brackets. # # [section] # key=value # etc # ... # class Section include Line @regex = /^\[ # Opening bracket ([^\]]+) # Section name \]$ # Closing bracket /x attr_accessor :key attr_reader :lines include Enumerable # ==== Parameters # key:: The section name. # opts:: Extra options for the line. # def initialize(key, opts = {}) super(opts) @key = key.to_s @lines = IniParse::OptionCollection.new end def self.parse(line, opts) if m = @regex.match(line) [:section, m[1], opts] end end # Returns this line as a string as it would be represented in an INI # document. Includes options, comments and blanks. def to_ini coll = lines.to_a if coll.any? [*super,coll.to_a.map do |line| if line.kind_of?(Array) line.map { |dup_line| dup_line.to_ini }.join($/) else line.to_ini end end].join($/) else super end end # Enumerates through each Option in this section. # # Does not yield blank and comment lines by default; if you want _all_ # lines to be yielded, pass true. # # ==== Parameters # include_blank:: Include blank/comment lines? # def each(*args, &blk) @lines.each(*args, &blk) end # Adds a new option to this section, or updates an existing one. # # Note that +[]=+ has no knowledge of duplicate options and will happily # overwrite duplicate options with your new value. # # section['an_option'] # # => ['duplicate one', 'duplicate two', ...] # section['an_option'] = 'new value' # section['an_option] # # => 'new value' # # If you do not wish to overwrite duplicates, but wish instead for your # new option to be considered a duplicate, use +add_option+ instead. # def []=(key, value) line = @lines[key.to_s] opts = {} if line.kind_of?(Array) opts = line.first.options elsif line.respond_to? :options opts = line.options end @lines[key.to_s] = IniParse::Lines::Option.new(key.to_s, value, opts) end # Returns the value of an option identified by +key+. # # Returns nil if there is no corresponding option. If the key provided # matches a set of duplicate options, an array will be returned containing # the value of each option. # def [](key) key = key.to_s if @lines.has_key?(key) if (match = @lines[key]).kind_of?(Array) match.map { |line| line.value } else match.value end end end # Deletes the option identified by +key+. # # Returns the section. # def delete(*args) @lines.delete(*args) self end # Like [], except instead of returning just the option value, it returns # the matching line instance. # # Will return an array of lines if the key matches a set of duplicates. # def option(key) @lines[key.to_s] end # Returns true if an option with the given +key+ exists in this section. def has_option?(key) @lines.has_key?(key.to_s) end # Merges section +other+ into this one. If the section being merged into # this one contains options with the same key, they will be handled as # duplicates. # # ==== Parameters # other:: The section to merge into this one. # def merge!(other) other.lines.each(true) do |line| if line.kind_of?(Array) line.each { |duplicate| @lines << duplicate } else @lines << line end end end ####### private ####### def line_contents '[%s]' % key end end # Stores options which appear at the beginning of a file, without a # preceding section. class AnonymousSection < Section def initialize super('__anonymous__') end def to_ini # Remove the leading space which is added by joining the blank line # content with the options. super.gsub(/\A\n/, '') end ####### private ####### def line_contents '' end end # Represents probably the most common type of line in an INI document: # an option. Consists of a key and value, usually separated with an =. # # key = value # class Option include Line @regex = /^\s*([^=]+) # Option = (.*?)$ # Value /x attr_accessor :key, :value # ==== Parameters # key:: The option key. # value:: The value for this option. # opts:: Extra options for the line. # def initialize(key, value, opts = {}) super(opts) @key, @value = key.to_s, value end def self.parse(line, opts) if m = @regex.match(line) [:option, m[1].strip, typecast(m[2].strip), opts] end end # Attempts to typecast values. def self.typecast(value) case value when /^\s*$/ then nil when /^-?(?:\d|[1-9]\d+)$/ then Integer(value) when /^-?(?:\d|[1-9]\d+)(?:\.\d+)?(?:e[+-]?\d+)?$/i then Float(value) when /^true$/i then true when /^false$/i then false else value end end ####### private ####### # returns an array to support multiple lines or a single one at once # because of options key duplication def line_contents if value.kind_of?(Array) value.map { |v, i| "#{key} = #{v}" } else "#{key} = #{value}" end end end # Represents a blank line. Used so that we can preserve blank lines when # writing back to the file. class Blank include Line def blank? true end def self.parse(line, opts) if line !~ /\S/ # blank if opts[:comment].nil? [:blank] else [:comment, opts[:comment], opts] end end end end # Represents a comment. Comment lines begin with a semi-colon or hash. # # ; this is a comment # # also a comment # class Comment < Blank # Returns if this line has an inline comment. # # Being a Comment this will always return true, even if the comment # is nil. This would be the case if the line starts with a comment # seperator, but has no comment text. See spec/fixtures/smb.ini for a # real-world example. # def has_comment? true end # Returns the inline comment for this line. Includes the comment # separator at the beginning of the string. # # In rare cases where a comment seperator appeared in the original file, # but without a comment, just the seperator will be returned. # def comment @comment !~ /\S/ ? @comment_sep : super end end end # Lines end # IniParse iniparse-1.4.2/lib/iniparse/line_collection.rb0000644000175000017500000001142512725022733021617 0ustar terceiroterceiromodule IniParse # Represents a collection of lines in an INI document. # # LineCollection acts a bit like an Array/Hash hybrid, allowing arbitrary # lines to be added to the collection, but also indexes the keys of Section # and Option lines to enable O(1) lookup via LineCollection#[]. # # The lines instances are stored in an array, +@lines+, while the index of # each Section/Option is held in a Hash, +@indicies+, keyed with the # Section/Option#key value (see LineCollection#[]=). # module LineCollection include Enumerable def initialize @lines = [] @indicies = {} end # Retrive a value identified by +key+. def [](key) has_key?(key) ? @lines[ @indicies[key] ] : nil end # Set a +value+ identified by +key+. # # If a value with the given key already exists, the value will be replaced # with the new one, with the new value taking the position of the old. # def []=(key, value) key = key.to_s if has_key?(key) @lines[ @indicies[key] ] = value else @lines << value @indicies[key] = @lines.length - 1 end end # Appends a line to the collection. # # Note that if you pass a line with a key already represented in the # collection, the old item will be replaced. # def <<(line) line.blank? ? (@lines << line) : (self[line.key] = line) ; self end alias_method :push, :<< # Enumerates through the collection. # # By default #each does not yield blank and comment lines. # # ==== Parameters # include_blank:: Include blank/comment lines? # def each(include_blank = false) @lines.each do |line| if include_blank || ! (line.is_a?(Array) ? line.empty? : line.blank?) yield(line) end end end # Removes the value identified by +key+. def delete(key) key = key.key if key.respond_to?(:key) unless (idx = @indicies[key]).nil? @indicies.delete(key) @indicies.each { |k,v| @indicies[k] = v -= 1 if v > idx } @lines.delete_at(idx) end end # Returns whether +key+ is in the collection. def has_key?(*args) @indicies.has_key?(*args) end # Return an array containing the keys for the lines added to this # collection. def keys map { |line| line.key } end # Returns this collection as an array. Includes blank and comment lines. def to_a @lines.dup end # Returns this collection as a hash. Does not contain blank and comment # lines. def to_hash Hash[ *(map { |line| [line.key, line] }).flatten ] end alias_method :to_h, :to_hash end # A implementation of LineCollection used for storing (mostly) Option # instances contained within a Section. # # Since it is assumed that an INI document will only represent a section # once, if SectionCollection encounters a Section key already held in the # collection, the existing section is merged with the new one (see # IniParse::Lines::Section#merge!). class SectionCollection include LineCollection def <<(line) if line.kind_of?(IniParse::Lines::Option) option = line line = IniParse::Lines::AnonymousSection.new line.lines << option if option end if line.blank? || (! has_key?(line.key)) super # Adding a new section, comment or blank line. else self[line.key].merge!(line) end self end end # A implementation of LineCollection used for storing (mostly) Option # instances contained within a Section. # # Whenever OptionCollection encounters an Option key already held in the # collection, it treats it as a duplicate. This means that instead of # overwriting the existing value, the value is changed to an array # containing the previous _and_ the new Option instances. class OptionCollection include LineCollection # Appends a line to the collection. # # If you push an Option with a key already represented in the collection, # the previous Option will not be overwritten, but treated as a duplicate. # # ==== Parameters # line:: The line to be added to this section. # def <<(line) if line.kind_of?(IniParse::Lines::Section) raise IniParse::LineNotAllowed, "You can't add a Section to an OptionCollection." end if line.blank? || (! has_key?(line.key)) super # Adding a new option, comment or blank line. else self[line.key] = [self[line.key], line].flatten end self end # Return an array containing the keys for the lines added to this # collection. def keys map { |line| line.kind_of?(Array) ? line.first.key : line.key } end end end iniparse-1.4.2/lib/iniparse/generator.rb0000644000175000017500000001342512725022733020445 0ustar terceiroterceiromodule IniParse # Generator provides a means for easily creating new INI documents. # # Rather than trying to hack together new INI documents by manually creating # Document, Section and Option instances, it is preferable to use Generator # which will handle it all for you. # # The Generator is exposed through IniParse.gen. # # IniParse.gen do |doc| # doc.section("vehicle") do |vehicle| # vehicle.option("road_side", "left") # vehicle.option("realistic_acceleration", true) # vehicle.option("max_trains", 500) # end # # doc.section("construction") do |construction| # construction.option("build_on_slopes", true) # construction.option("autoslope", true) # end # end # # # => IniParse::Document # # This can be simplified further if you don't mind the small overhead # which comes with +method_missing+: # # IniParse.gen do |doc| # doc.vehicle do |vehicle| # vehicle.road_side = "left" # vehicle.realistic_acceleration = true # vehicle.max_trains = 500 # end # # doc.construction do |construction| # construction.build_on_slopes = true # construction.autoslope = true # end # end # # # => IniParse::Document # # If you want to add slightly more complicated formatting to your document, # each line type (except blanks) takes a number of optional parameters: # # :comment:: # Adds an inline comment at the end of the line. # :comment_offset:: # Indent the comment. Measured in characters from _beginning_ of the line. # See String#ljust. # :indent:: # Adds the supplied text to the beginning of the line. # # If you supply +:indent+, +:comment_sep+, or +:comment_offset+ options when # adding a section, the same options will be inherited by all of the options # which belong to it. # # IniParse.gen do |doc| # doc.section("vehicle", # :comment => "Options for vehicles", :indent => " " # ) do |vehicle| # vehicle.option("road_side", "left") # vehicle.option("realistic_acceleration", true) # vehicle.option("max_trains", 500, :comment => "More = slower") # end # end.to_ini # # [vehicle] ; Options for vehicles # road_side = left # realistic_acceleration = true # max_trains = 500 ; More = slower # class Generator attr_reader :context attr_reader :document def initialize(opts = {}) # :nodoc: @document = IniParse::Document.new @context = @document @in_section = false @opt_stack = [opts] end def gen # :nodoc: yield self @document end # Creates a new IniParse::Document with the given sections and options. # # ==== Returns # IniParse::Document # def self.gen(opts = {}, &blk) new(opts).gen(&blk) end # Creates a new section with the given name and adds it to the document. # # You can optionally supply a block (as detailed in the documentation for # Generator#gen) in order to add options to the section. # # ==== Parameters # name:: A name for the given section. # def section(name, opts = {}) if @in_section # Nesting sections is bad, mmmkay? raise LineNotAllowed, "You can't nest sections in INI files." end # Add to a section if it already exists if @document.has_section?(name.to_s()) @context = @document[name.to_s()] else @context = Lines::Section.new(name, line_options(opts)) @document.lines << @context end if block_given? begin @in_section = true with_options(opts) { yield self } @context = @document blank() ensure @in_section = false end end end # Adds a new option to the current section. # # Can only be called as part of a section block, or after at least one # section has been added to the document. # # ==== Parameters # key:: The key (name) for this option. # value:: The option's value. # opts:: Extra options for the line (formatting, etc). # # ==== Raises # IniParse::NoSectionError:: # If no section has been added to the document yet. # def option(key, value, opts = {}) @context.lines << Lines::Option.new( key, value, line_options(opts) ) rescue LineNotAllowed # Tried to add an Option to a Document. raise NoSectionError, 'Your INI document contains an option before the first section is ' \ 'declared which is not allowed.' end # Adds a new comment line to the document. # # ==== Parameters # comment:: The text for the comment line. # def comment(comment, opts = {}) @context.lines << Lines::Comment.new( line_options(opts.merge(:comment => comment)) ) end # Adds a new blank line to the document. def blank @context.lines << Lines::Blank.new end # Wraps lines, setting default options for each. def with_options(opts = {}) # :nodoc: opts = opts.dup opts.delete(:comment) @opt_stack.push( @opt_stack.last.merge(opts)) yield self @opt_stack.pop end def method_missing(name, *args, &blk) # :nodoc: if m = name.to_s.match(/(.*)=$/) option(m[1], *args) else section(name.to_s, *args, &blk) end end ####### private ####### # Returns options for a line. # # If the context is a section, we use the section options as a base, # rather than the global defaults. # def line_options(given_opts) # :nodoc: @opt_stack.last.empty? ? given_opts : @opt_stack.last.merge(given_opts) end end end iniparse-1.4.2/lib/iniparse/document.rb0000644000175000017500000000570612725022733020300 0ustar terceiroterceiromodule IniParse # Represents an INI document. class Document include Enumerable attr_reader :lines attr_accessor :path # Creates a new Document instance. def initialize(path = nil) @path = path @lines = IniParse::SectionCollection.new end # Enumerates through each Section in this document. # # Does not yield blank and comment lines by default; if you want _all_ # lines to be yielded, pass true. # # ==== Parameters # include_blank:: Include blank/comment lines? # def each(*args, &blk) @lines.each(*args, &blk) end # Returns the section identified by +key+. # # Returns nil if there is no Section with the given key. # def [](key) @lines[key.to_s] end # Returns the section identified by +key+. # # If there is no Section with the given key it will be created. # def section(key) @lines[key.to_s] ||= Lines::Section.new(key.to_s) end # Deletes the section whose name matches the given +key+. # # Returns the document. # def delete(*args) @lines.delete(*args) self end # Returns this document as a string suitable for saving to a file. def to_ini string = @lines.to_a.map { |line| line.to_ini }.join($/) string = "#{ string }\n" unless string[-1] == "\n" string end alias_method :to_s, :to_ini # Returns a has representation of the INI with multi-line options # as an array def to_hash result = {} @lines.entries.each do |section| result[section.key] ||= {} section.entries.each do |option| opts = Array(option) val = opts.map { |o| o.respond_to?(:value) ? o.value : o } val = val.size > 1 ? val : val.first result[section.key][opts.first.key] = val end end result end alias_method :to_h, :to_hash # A human-readable version of the document, for debugging. def inspect sections = @lines.select { |l| l.is_a?(IniParse::Lines::Section) } "#" end # Returns true if a section with the given +key+ exists in this document. def has_section?(key) @lines.has_key?(key.to_s) end # Saves a copy of this Document to disk. # # If a path was supplied when the Document was initialized then nothing # needs to be given to Document#save. If Document was not given a file # path, or you wish to save the document elsewhere, supply a path when # calling Document#save. # # ==== Parameters # path:: A path to which this document will be saved. # # ==== Raises # IniParseError:: If your document couldn't be saved. # def save(path = nil) @path = path if path raise IniParseError, 'No path given to Document#save' if @path !~ /\S/ File.open(@path, 'w') { |f| f.write(self.to_ini) } end end end iniparse-1.4.2/lib/iniparse.rb0000644000175000017500000000305212725022733016452 0ustar terceiroterceirodir = File.expand_path('iniparse', File.dirname(__FILE__)) require File.join(dir, 'document') require File.join(dir, 'generator') require File.join(dir, 'line_collection') require File.join(dir, 'lines') require File.join(dir, 'parser') module IniParse VERSION = '1.4.2' # A base class for IniParse errors. class IniParseError < StandardError; end # Raised if an error occurs parsing an INI document. class ParseError < IniParseError; end # Raised when an option line is found during parsing before the first # section. class NoSectionError < ParseError; end # Raised when a line is added to a collection which isn't allowed (e.g. # adding a Section line into an OptionCollection). class LineNotAllowed < IniParseError; end module_function # Parse given given INI document source +source+. # # See IniParse::Parser.parse # # ==== Parameters # source:: The source from the INI document. # # ==== Returns # IniParse::Document # def parse(source) IniParse::Parser.new(source.gsub(/(?:: The path to the INI document. # # ==== Returns # IniParse::Document # def open(path) document = parse(File.read(path)) document.path = path document end # Creates a new IniParse::Document using the specification you provide. # # See IniParse::Generator. # # ==== Returns # IniParse::Document # def gen(&blk) IniParse::Generator.new.gen(&blk) end end iniparse-1.4.2/Rakefile0000644000175000017500000000652012725022733015215 0ustar terceiroterceirorequire 'rubygems' require 'rake' require 'date' require 'rake/clean' require 'rdoc/task' require 'rspec/core/rake_task' ############################################################################## # Helpers ############################################################################## def name @name ||= Dir['*.gemspec'].first.split('.').first end def version line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/] line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1] end def date Date.today.to_s end def rubyforge_project name end def gemspec_file "#{name}.gemspec" end def gem_file "#{name}-#{version}.gem" end def replace_header(head, header_name) head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"} end ############################################################################## # Packaging & Installation. ############################################################################## CLEAN.include ['pkg', '*.gem', 'doc', 'coverage'] desc 'Build the gem, and push to Github' task :release => :build do unless `git branch` =~ /^\* master$/ puts "You must be on the master branch to release!" exit! end sh "git commit --allow-empty -a -m 'Release #{version}'" sh "git tag v#{version}" sh "git push origin master" sh "git push origin v#{version}" puts "Push to Rubygems.org with" puts " gem push pkg/#{name}-#{version}.gem" end desc 'Builds the IniParse gem' task :build => :gemspec do sh "mkdir -p pkg" sh "gem build #{gemspec_file}" sh "mv #{gem_file} pkg" end desc 'Creates a fresh gemspec' task :gemspec => :validate do # read spec file and split out manifest section spec = File.read(gemspec_file) head, manifest, tail = spec.split(" # = MANIFEST =\n") # replace name version and date replace_header(head, :name) replace_header(head, :version) replace_header(head, :date) #comment this out if your rubyforge_project has a different name replace_header(head, :rubyforge_project) # determine file list from git ls-files files = `git ls-files`. split("\n"). sort. reject { |file| file =~ /^\./ }. reject { |file| file =~ /^(rdoc|pkg|spec)/ }. map { |file| " #{file}" }. join("\n") # piece file back together and write manifest = " s.files = %w[\n#{files}\n ]\n" spec = [head, manifest, tail].join(" # = MANIFEST =\n") File.open(gemspec_file, 'w') { |io| io.write(spec) } puts "Updated #{gemspec_file}" end task :validate do libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"] unless libfiles.empty? puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir." exit! end unless Dir['VERSION*'].empty? puts "A `VERSION` file at root level violates Gem best practices." exit! end end ############################################################################## # Documentation ############################################################################## Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = "iniparse #{version}" rdoc.rdoc_files.include('README*') rdoc.rdoc_files.include('lib/**/*.rb') end ############################################################################## # Tests & Metrics. ############################################################################## RSpec::Core::RakeTask.new('spec') do |spec| spec.pattern = 'spec/**/*_spec.rb' end iniparse-1.4.2/TODO0000644000175000017500000000012412725022733014232 0ustar terceiroterceiro* Support multi-line options with backslashes (presumably with OptionCollection). iniparse-1.4.2/spec/0000755000175000017500000000000012725022733014477 5ustar terceiroterceiroiniparse-1.4.2/spec/generator/0000755000175000017500000000000012725022733016465 5ustar terceiroterceiroiniparse-1.4.2/spec/generator/without_section_blocks_spec.rb0000644000175000017500000001036512725022733024615 0ustar terceiroterceirorequire 'spec_helper' # Tests use of the Generator when used like so: # # @gen = IniParse::Generator.new # @gen.comment('My very own comment') # @gen.section('my_section') # @gen.option('my_option', 'my value') # ... # # Or # # IniParse::Generator.gen do |doc| # doc.comment('My very own comment') # doc.section('my_section') # doc.option('my_option', 'my value') # end # describe 'When generating a document using Generator without section blocks,' do before(:each) { @gen = IniParse::Generator.new } # -- # ========================================================================== # SECTION LINES # ========================================================================== # ++ describe 'adding a section' do it 'should add a Section to the document' do @gen.section("a section") @gen.document.should have_section("a section") end it 'should change the Generator context to the section' do @gen.section("a section") @gen.context.should == @gen.document['a section'] end it 'should pass extra options to the Section instance' do @gen.section("a section", :indent => ' ') @gen.document["a section"].to_ini.should match(/\A /) end end # -- # ========================================================================== # OPTION LINES # ========================================================================== # ++ describe 'adding a option' do it 'should pass extra options to the Option instance' do @gen.section("a section") @gen.option("my option", "a value", :indent => ' ') @gen.document["a section"].option("my option").to_ini.should match(/^ /) end describe 'when the context is a Document' do it "should add the option to an __anonymous__ section" do @gen.option("key", "value") @gen.document['__anonymous__']['key'].should eql('value') end end describe 'when the context is a Section' do it 'should add the option to the section' do @gen.section("a section") @gen.option("my option", "a value") @gen.document["a section"].should have_option("my option") @gen.document["a section"]["my option"].should == "a value" end end end # -- # ========================================================================== # COMMENT LINES # ========================================================================== # ++ describe 'adding a comment' do it 'should pass extra options to the Option instance' do @gen.comment("My comment", :indent => ' ') @gen.document.lines.to_a.first.to_ini.should match(/^ /) end it 'should ignore any extra :comment option' do @gen.comment("My comment", :comment => 'Ignored') comment_ini = @gen.document.lines.to_a.first.to_ini comment_ini.should match(/My comment/) comment_ini.should_not match(/Ignored/) end describe 'when the context is a Document' do it 'should add a comment to the document' do @gen.comment('My comment') comment = @gen.document.lines.to_a.first comment.should be_kind_of(IniParse::Lines::Comment) comment.to_ini.should match(/; My comment/) end end describe 'when the context is a Section' do it 'should add a comment to the section' do @gen.section('a section') @gen.comment('My comment') comment = @gen.document['a section'].lines.to_a.first comment.should be_kind_of(IniParse::Lines::Comment) comment.to_ini.should match(/My comment/) end end end # -- # ========================================================================== # BLANK LINES # ========================================================================== # ++ describe 'adding a blank line' do it 'should add a blank line to the document when it is the context' do @gen.blank comment = @gen.document.lines.to_a.first comment.should be_kind_of(IniParse::Lines::Blank) end it 'should add a blank line to the section when it is the context' do @gen.section('a section') @gen.blank comment = @gen.document['a section'].lines.to_a.first comment.should be_kind_of(IniParse::Lines::Blank) end end end iniparse-1.4.2/spec/generator/method_missing_spec.rb0000644000175000017500000000611212725022733023035 0ustar terceiroterceirorequire 'spec_helper' # Tests use of the Generator when used like so: # # IniParse::Generator.gen do |doc| # doc.comment 'My very own comment' # doc.my_section do |section| # section.my_option = 'my value' # end # end # describe 'When generating a document using Generator with section blocks using method_missing,' do # -- # ========================================================================== # SECTION LINES # ========================================================================== # ++ describe 'adding a section' do it 'should yield an object with generator methods' do IniParse::Generator.gen do |doc| doc.a_section do |section| %w( option comment blank ).each do |meth| section.should respond_to(meth) end end end end it 'should add a Section to the document' do IniParse::Generator.gen do |doc| doc.a_section { |section| } end.should have_section("a_section") end it 'should change the Generator context to the section during the section block' do IniParse::Generator.gen do |doc| doc.a_section do |section| section.context.should be_kind_of(IniParse::Lines::Section) section.context.key.should == "a_section" end end end it 'should reset the Generator context to the document after the section block' do IniParse::Generator.gen do |doc| doc.a_section { |section| } doc.context.should be_kind_of(IniParse::Document) end end it 'should append a blank line to the document, after the section' do IniParse::Generator.gen do |doc| doc.a_section { |section| } end.lines.to_a.last.should be_kind_of(IniParse::Lines::Blank) end it 'should raise a LineNotAllowed if you attempt to nest a section' do lambda do IniParse::Generator.gen do |doc| doc.a_section do |section_one| section_one.another_section { |section_two| } end end end.should raise_error(IniParse::LineNotAllowed) end end # -- # ========================================================================== # OPTION LINES # ========================================================================== # ++ describe 'adding a option' do describe 'when the context is a Document' do it "adds the option to an __anonymous__ section" do doc = IniParse::Generator.gen { |doc| doc.my_option = "a value" } doc['__anonymous__']['my_option'].should eql('a value') end end describe 'when the context is a Section' do it 'should add the option to the section' do document = IniParse::Generator.gen do |doc| doc.a_section do |section| section.my_option = "a value" end end section = document["a_section"] section.should have_option("my_option") section["my_option"].should == "a value" end end end # Comments and blanks are added in the same way as in the # 'with_section_block_spec.rb' specification. end iniparse-1.4.2/spec/generator/with_section_blocks_spec.rb0000644000175000017500000002427612725022733024073 0ustar terceiroterceirorequire 'spec_helper' # Tests use of the Generator when used like so: # # IniParse::Generator.gen do |doc| # doc.comment('My very own comment') # doc.section('my_section') do |section| # section.option('my_option', 'my value') # end # end # describe 'When generating a document using Generator with section blocks,' do it 'should be able to compile an empty document' do lambda { IniParse::Generator.gen { |doc| } }.should_not raise_error end it 'should raise LocalJumpError if no block is given' do lambda { IniParse::Generator.gen }.should raise_error(LocalJumpError) end it "should yield an object with generator methods" do IniParse::Generator.gen do |doc| %w( section option comment blank ).each do |meth| doc.should respond_to(meth) end end end # -- # ========================================================================== # SECTION LINES # ========================================================================== # ++ describe 'adding a section' do it 'should yield an object with generator methods' do IniParse::Generator.gen do |doc| doc.section("a section") do |section| %w( option comment blank ).each do |meth| section.should respond_to(meth) end end end end it 'should add a Section to the document' do IniParse::Generator.gen do |doc| doc.section("a section") { |section| } end.should have_section("a section") end it 'should change the Generator context to the section during the section block' do IniParse::Generator.gen do |doc| doc.section("a section") do |section| section.context.should be_kind_of(IniParse::Lines::Section) section.context.key.should == "a section" end end end it 'should reset the Generator context to the document after the section block' do IniParse::Generator.gen do |doc| doc.section("a section") { |section| } doc.context.should be_kind_of(IniParse::Document) end end it "should use the parent document's options as a base" do document = IniParse::Generator.gen(:indent => ' ') do |doc| doc.section("a section") { |section| } end document["a section"].to_ini.should match(/\A /) end it 'should pass extra options to the Section instance' do document = IniParse::Generator.gen do |doc| doc.section("a section", :indent => ' ') { |section| } end document["a section"].to_ini.should match(/\A /) end it 'should append a blank line to the document, after the section' do IniParse::Generator.gen do |doc| doc.section("a section") { |section| } end.lines.to_a.last.should be_kind_of(IniParse::Lines::Blank) end it 'should raise a LineNotAllowed if you attempt to nest a section' do lambda do IniParse::Generator.gen do |doc| doc.section("a section") do |section_one| section_one.section("another_section") { |section_two| } end end end.should raise_error(IniParse::LineNotAllowed) end end # -- # ========================================================================== # OPTION LINES # ========================================================================== # ++ describe 'adding a option' do describe 'when the context is a Document' do it "should add the option to an __anonymous__ section" do document = IniParse::Generator.gen do |doc| doc.option("my option", "a value") end document['__anonymous__']['my option'].should eql('a value') end end describe 'when the context is a Section' do it 'should add the option to the section' do document = IniParse::Generator.gen do |doc| doc.section("a section") do |section| section.option("my option", "a value") end end section = document["a section"] section.should have_option("my option") section["my option"].should == "a value" end it 'should pass extra options to the Option instance' do document = IniParse::Generator.gen do |doc| doc.section("a section") do |section| section.option("my option", "a value", :indent => " ") end end document["a section"].option("my option").to_ini.should match(/^ /) end it "should use the parent document's options as a base" do document = IniParse::Generator.gen(:indent => " ") do |doc| doc.section("a section") do |section| section.option("my option", "a value") end end document["a section"].option("my option").to_ini.should match(/^ /) end it "should use the parent section's options as a base" do document = IniParse::Generator.gen do |doc| doc.section("a section", :indent => " ") do |section| section.option("my option", "a value") end end document["a section"].option("my option").to_ini.should match(/^ /) end it "should allow customisation of the parent's options" do document = IniParse::Generator.gen do |doc| doc.section("a section", :indent => " ") do |section| section.option("my option", "a value", { :comment_sep => "#", :comment => 'a comment' }) end end option_ini = document["a section"].option("my option").to_ini option_ini.should match(/^ /) option_ini.should match(/ # a comment/) end it "should not use the parent section's comment when setting line options" do document = IniParse::Generator.gen do |doc| doc.section("a section", :comment => "My section") do |section| section.option("my option", "a value") end end document["a section"].option("my option").to_ini.should_not match(/My section$/) end end end # -- # ========================================================================== # COMMENT LINES # ========================================================================== # ++ describe 'adding a comment' do it 'should pass extra options to the Option instance' do document = IniParse::Generator.gen do |doc| doc.comment("My comment", :indent => ' ') end document.lines.to_a.first.to_ini.should match(/\A /) end it 'should ignore any extra :comment option' do document = IniParse::Generator.gen do |doc| doc.comment("My comment", :comment => 'Ignored') end document.lines.to_a.first.to_ini.should match(/My comment/) document.lines.to_a.first.to_ini.should_not match(/Ignored/) end describe 'when the context is a Document' do it 'should add a comment to the document' do document = IniParse::Generator.gen do |doc| doc.comment("My comment") end comment = document.lines.to_a.first comment.should be_kind_of(IniParse::Lines::Comment) comment.to_ini.should match(/My comment/) end it 'should use the default line options as a base' do document = IniParse::Generator.gen do |doc| doc.comment("My comment") end comment_ini = document.lines.to_a.first.to_ini # Match separator (;) and offset (0). comment_ini.should == '; My comment' end end describe 'when the context is a Section' do it 'should add a comment to the section' do document = IniParse::Generator.gen do |doc| doc.section("a section") do |section| section.comment("My comment") end end comment = document['a section'].lines.to_a.first comment.should be_kind_of(IniParse::Lines::Comment) comment.to_ini.should match(/My comment/) end it "should use the parent document's line options as a base" do document = IniParse::Generator.gen(:comment_offset => 5) do |doc| doc.section("a section") do |section| section.comment("My comment") end end document['a section'].lines.to_a.first.to_ini.should match(/^ ;/) end it "should use the parent section's line options as a base" do document = IniParse::Generator.gen do |doc| doc.section("a section", :comment_offset => 5) do |section| section.comment("My comment") end end document['a section'].lines.to_a.first.to_ini.should match(/^ ;/) end it "should allow customisation of the parent's options" do document = IniParse::Generator.gen do |doc| doc.section("a section", :comment_offset => 5) do |section| section.comment("My comment", :comment_sep => "#") end end # Match separator (#) and offset (5) document['a section'].lines.to_a.first.to_ini.should \ == ' # My comment' end it "should not use the parent section's comment when setting line options" do document = IniParse::Generator.gen do |doc| doc.section("a section", :comment => "My section") do |section| section.comment("My comment") end end comment_ini = document['a section'].lines.to_a.first.to_ini comment_ini.should match(/My comment/) comment_ini.should_not match(/My section/) end end end # -- # ========================================================================== # BLANK LINES # ========================================================================== # ++ describe 'adding a blank line' do it 'should add a blank line to the document when it is the context' do document = IniParse::Generator.gen do |doc| doc.blank end document.lines.to_a.first.should be_kind_of(IniParse::Lines::Blank) end it 'should add a blank line to the section when it is the context' do document = IniParse::Generator.gen do |doc| doc.section("a section") do |section| section.blank end end document['a section'].lines.to_a.first.should be_kind_of(IniParse::Lines::Blank) end end end iniparse-1.4.2/spec/iniparse_spec.rb0000644000175000017500000000266312725022733017657 0ustar terceiroterceirorequire 'spec_helper' describe "IniParse" do describe '.parse' do context 'with a line ending in a backslash' do let(:ini) do <<-'INI'.gsub(/^\s*/, '') [a] opt = 1 \ other = 2 INI end let(:doc) { IniParse.parse(ini) } it 'recognises the line continuation' do expect(doc.to_s).to eq("[a]\nopt = 1 other = 2\n") end it 'has one option' do expect(doc['a'].to_a.length).to eq(1) end end context 'with a line ending in a double-backslash' do let(:ini) do <<-'INI'.gsub(/^\s*/, '') [a] opt = 1 \\ other = 2 INI end let(:doc) { IniParse.parse(ini) } it 'does not see a line continuation' do expect(doc.to_s).to eq(ini) end it 'has one option' do expect(doc['a'].to_a.length).to eq(2) end end end describe '.open' do before(:each) { File.stub(:read).and_return('[section]') } it 'should return an IniParse::Document' do IniParse.open('/my/path.ini').should be_kind_of(IniParse::Document) end it 'should set the path on the returned Document' do IniParse.open('/my/path.ini').path.should == '/my/path.ini' end it 'should read the file at the given path' do File.should_receive(:read).with('/my/path.ini').and_return('[section]') IniParse.open('/my/path.ini') end end end iniparse-1.4.2/spec/spec_helper_spec.rb0000644000175000017500000001242512725022733020333 0ustar terceiroterceirorequire 'spec_helper' # -- # ============================================================================ # Empty array. # ============================================================================ # ++ describe 'An empty array' do it 'should not pass be_section_tuple' do [].should_not be_section_tuple end it 'should not pass be_option_tuple' do [].should_not be_option_tuple end it 'should not pass be_blank_tuple' do [].should_not be_blank_tuple end it 'should not pass be_comment_tuple' do [].should_not be_comment_tuple end end # -- # ============================================================================ # Section tuple. # ============================================================================ # ++ describe 'Line tuple [:section, "key", {:opt => "val"}]' do before(:all) { @tuple = [:section, "key", {:opt => "val"}] } it 'should pass be_section_tuple' do @tuple.should be_section_tuple end it 'should pass be_section_tuple("key")' do @tuple.should be_section_tuple("key") end it 'should fail be_section_tuple("invalid")' do @tuple.should_not be_section_tuple("invalid") end it 'should pass be_section_tuple("key", {:opt => "val"})' do @tuple.should be_section_tuple("key", {:opt => "val"}) end it 'should not pass be_section_tuple("key", {:invalid => "val"})' do @tuple.should_not be_section_tuple("key", {:invalid => "val"}) end it 'should not pass be_section_tuple("key", {:opt => "invalid"})' do @tuple.should_not be_section_tuple("key", {:opt => "invalid"}) end it 'should fail be_option_tuple' do @tuple.should_not be_option_tuple end it 'should fail be_blank_tuple' do @tuple.should_not be_blank_tuple end it 'should fail be_comment_tuple' do @tuple.should_not be_comment_tuple end end # -- # ============================================================================ # Option tuple. # ============================================================================ # ++ describe 'Line tuple [:option, "key", "val", {:opt => "val"}]' do before(:all) { @tuple = [:option, "key", "val", {:opt => "val"}] } it 'should fail be_section_tuple' do @tuple.should_not be_section_tuple end it 'should pass be_option_tuple' do @tuple.should be_option_tuple end it 'should pass be_option_tuple("key")' do @tuple.should be_option_tuple("key") end it 'should fail be_option_tuple("invalid")' do @tuple.should_not be_option_tuple("invalid") end it 'should pass be_option_tuple("key", "val")' do @tuple.should be_option_tuple("key", "val") end it 'should pass be_option_tuple(:any, "val")' do @tuple.should be_option_tuple(:any, "val") end it 'should fail be_option_tuple("key", "invalid")' do @tuple.should_not be_option_tuple("key", "invalid") end it 'should pass be_option_tuple("key", "val", { :opt => "val" })' do @tuple.should be_option_tuple("key", "val", { :opt => "val" }) end it 'should fail be_option_tuple("key", "val", { :invalid => "val" })' do @tuple.should_not be_option_tuple("key", "val", { :invalid => "val" }) end it 'should fail be_option_tuple("key", "val", { :opt => "invalid" })' do @tuple.should_not be_option_tuple("key", "val", { :opt => "invalid" }) end it 'should fail be_blank_tuple' do @tuple.should_not be_blank_tuple end it 'should fail be_comment_tuple' do @tuple.should_not be_comment_tuple end end # -- # ============================================================================ # Blank tuple. # ============================================================================ # ++ describe 'Line tuple [:blank]' do before(:all) { @tuple = [:blank] } it 'should fail be_section_tuple' do @tuple.should_not be_section_tuple end it 'should fail be_option_tuple' do @tuple.should_not be_option_tuple end it 'should pass be_blank_tuple' do @tuple.should be_blank_tuple end it 'should fail be_comment_tuple' do @tuple.should_not be_comment_tuple end end # -- # ============================================================================ # Coment tuple. # ============================================================================ # ++ describe 'Line tuple [:comment, "A comment", {:opt => "val"}]' do before(:all) { @tuple = [:comment, "A comment", {:opt => "val"}] } it 'should fail be_section_tuple' do @tuple.should_not be_section_tuple end it 'should fail be_option_tuple' do @tuple.should_not be_option_tuple end it 'should fail be_blank_tuple' do @tuple.should_not be_blank_tuple end it 'should pass be_comment_tuple' do @tuple.should be_comment_tuple end it 'should pass be_comment_tuple("A comment")' do @tuple.should be_comment_tuple("A comment") end it 'should fail be_comment_tuple("Invalid")' do @tuple.should_not be_comment_tuple("Invalid") end it 'should pass be_comment_tuple("A comment", {:opt => "val"})' do @tuple.should be_comment_tuple("A comment", {:opt => "val"}) end it 'should fail be_comment_tuple("A comment", {:invalid => "val"})' do @tuple.should_not be_comment_tuple("A comment", {:invalid => "val"}) end it 'should fail be_comment_tuple("A comment", {:opt => "invalid"})' do @tuple.should_not be_comment_tuple("A comment", {:opt => "invalid"}) end end iniparse-1.4.2/spec/lines_spec.rb0000644000175000017500000003333112725022733017153 0ustar terceiroterceirorequire 'spec_helper' module IniParse::Test class FakeLine include IniParse::Lines::Line def line_contents 'fake line' end end end describe "IniParse::Lines::Line module" do describe '#to_ini' do it 'should return +line_contents+' do IniParse::Test::FakeLine.new.to_ini.should == 'fake line' end it 'should preserve line indents' do IniParse::Test::FakeLine.new( :indent => ' ' ).to_ini.should == ' fake line' end describe 'when a comment is set' do it 'should correctly include the comment' do IniParse::Test::FakeLine.new( :comment => 'comment', :comment_sep => ';', :comment_offset => 10 ).to_ini.should == 'fake line ; comment' end it 'should correctly indent the comment' do IniParse::Test::FakeLine.new( :comment => 'comment', :comment_sep => ';', :comment_offset => 15 ).to_ini.should == 'fake line ; comment' end it 'should use ";" as a default comment seperator' do IniParse::Test::FakeLine.new( :comment => 'comment' ).to_ini.should == 'fake line ; comment' end it 'should use the correct seperator' do IniParse::Test::FakeLine.new( :comment => 'comment', :comment_sep => '#' ).to_ini.should == 'fake line # comment' end it 'should use the ensure a space is added before the comment seperator' do IniParse::Test::FakeLine.new( :comment => 'comment', :comment_sep => ';', :comment_offset => 0 ).to_ini.should == 'fake line ; comment' end it 'should not add an extra space if the line is blank' do line = IniParse::Test::FakeLine.new( :comment => 'comment', :comment_sep => ';', :comment_offset => 0 ) line.stub(:line_contents).and_return('') line.to_ini.should == '; comment' end end describe 'when no comment is set' do it 'should not add trailing space if :comment_offset has a value' do IniParse::Test::FakeLine.new(:comment_offset => 10).to_ini.should == 'fake line' end it 'should not add a comment seperator :comment_sep has a value' do IniParse::Test::FakeLine.new(:comment_sep => ';').to_ini.should == 'fake line' end end end describe '#has_comment?' do it 'should return true if :comment has a non-blank value' do IniParse::Test::FakeLine.new(:comment => 'comment').should have_comment end it 'should return true if :comment has a blank value' do IniParse::Test::FakeLine.new(:comment => '').should have_comment end it 'should return false if :comment has a nil value' do IniParse::Test::FakeLine.new.should_not have_comment IniParse::Test::FakeLine.new(:comment => nil).should_not have_comment end end end # # Section # describe 'IniParse::Lines::Section' do before(:each) { @section = IniParse::Lines::Section.new('a section') } it 'should respond_to +lines+' do @section.should respond_to(:lines) end it 'should not respond_to +lines=+' do @section.should_not respond_to(:lines=) end it 'should include Enumerable' do IniParse::Lines::Section.included_modules.should include(Enumerable) end describe '#initialize' do it 'should typecast the given key to a string' do IniParse::Lines::Section.new(:symbol).key.should == 'symbol' end end describe '#option' do it 'should retrieve the line identified by the given key' do option = IniParse::Lines::Option.new('k', 'value one') @section.lines << option @section.option('k').should == option end it 'should return nil if the given key does not exist' do @section.option('does_not_exist').should be_nil end end describe '#each' do it 'should call #each on +lines+' do @section.lines.should_receive(:each) @section.each { |l| } end end describe '#[]' do it 'should return nil if the given key does not exist' do @section['k'].should be_nil end it 'should return a value if the given key exists' do @section.lines << IniParse::Lines::Option.new('k', 'v') @section['k'].should == 'v' end it 'should return an array of values if the key is a duplicate' do @section.lines << IniParse::Lines::Option.new('k', 'v1') @section.lines << IniParse::Lines::Option.new('k', 'v2') @section.lines << IniParse::Lines::Option.new('k', 'v3') @section['k'].should == ['v1', 'v2', 'v3'] end it 'should typecast the key to a string' do @section.lines << IniParse::Lines::Option.new('k', 'v') @section[:k].should == 'v' end end describe '#[]=' do it 'should add a new Option with the given key and value' do @section['k'] = 'a value' @section.option('k').should be_kind_of(IniParse::Lines::Option) @section['k'].should == 'a value' end it 'should update the Option if one already exists' do @section.lines << IniParse::Lines::Option.new('k', 'orig value') @section['k'] = 'new value' @section['k'].should == 'new value' end it 'should replace the existing Option if it is an array' do @section.lines << IniParse::Lines::Option.new('k', 'v1') @section.lines << IniParse::Lines::Option.new('k', 'v2') @section['k'] = 'new value' @section.option('k').should be_kind_of(IniParse::Lines::Option) @section['k'].should == 'new value' end it 'should typecast the key to a string' do @section[:k] = 'a value' @section['k'].should == 'a value' end end describe '#merge!' do before(:each) do @section.lines << IniParse::Lines::Option.new('a', 'val1') @section.lines << IniParse::Lines::Blank.new @section.lines << IniParse::Lines::Comment.new @section.lines << IniParse::Lines::Option.new('b', 'val2') @new_section = IniParse::Lines::Section.new('new section') end it 'should merge options from the given Section into the receiver' do @new_section.lines << IniParse::Lines::Option.new('c', 'val3') @new_section.lines << IniParse::Lines::Option.new('d', 'val4') @section.merge!(@new_section) @section['a'].should == 'val1' @section['b'].should == 'val2' @section['c'].should == 'val3' @section['d'].should == 'val4' end it 'should handle duplicates' do @new_section.lines << IniParse::Lines::Option.new('a', 'val2') @section.merge!(@new_section) @section['a'].should == ['val1', 'val2'] end it 'should handle duplicates on both sides' do @section.lines << IniParse::Lines::Option.new('a', 'val2') @new_section.lines << IniParse::Lines::Option.new('a', 'val3') @new_section.lines << IniParse::Lines::Option.new('a', 'val4') @section.merge!(@new_section) @section['a'].should == ['val1', 'val2', 'val3', 'val4'] end it 'should copy blank lines' do @new_section.lines << IniParse::Lines::Blank.new @section.merge!(@new_section) line = nil @section.each(true) { |l| line = l } line.should be_kind_of(IniParse::Lines::Blank) end it 'should copy comments' do @new_section.lines << IniParse::Lines::Comment.new @section.merge!(@new_section) line = nil @section.each(true) { |l| line = l } line.should be_kind_of(IniParse::Lines::Comment) end end describe '#delete' do let(:opt_one) { IniParse::Lines::Option.new('a', 'b') } let(:opt_two) { IniParse::Lines::Option.new('c', 'd') } before(:each) do @section.lines << opt_one @section.lines << opt_two end it 'removes the option given a key' do lambda { @section.delete('a') }. should change { @section['a'] }.to(nil) end it 'removes the option given an Option' do lambda { @section.delete(opt_one) }. should change { @section['a'] }.to(nil) end it 'should not remove non-matching lines' do lambda { @section.delete('a') }.should_not change { @section['c'] } end it 'returns the section' do @section.delete('a').should eql(@section) end end describe '#to_ini' do it 'should include the section key' do IniParse::Lines::Section.new('a section').to_ini.should == '[a section]' end it 'should include lines belonging to the section' do @section.lines << IniParse::Lines::Option.new('a', 'val1') @section.lines << IniParse::Lines::Blank.new @section.lines << IniParse::Lines::Comment.new( :comment => 'my comment', :comment_sep => ';', :comment_offset => 0 ) @section.lines << IniParse::Lines::Option.new('b', 'val2') @section.to_ini.should == "[a section]\n" \ "a = val1\n" \ "\n" \ "; my comment\n" \ "b = val2" end it 'should include duplicate lines' do @section.lines << IniParse::Lines::Option.new('a', 'val1') @section.lines << IniParse::Lines::Option.new('a', 'val2') @section.to_ini.should == "[a section]\n" \ "a = val1\n" \ "a = val2" end end describe '#has_option?' do before do @section['first'] = 'value' end it 'should return true if an option with the given key exists' do @section.should have_option('first') end it 'should return true if no option with the given key exists' do @section.should_not have_option('second') end end end # # Option # describe 'Iniparse::Lines::Option' do describe '#initialize' do it 'should typecast the given key to a string' do IniParse::Lines::Option.new(:symbol, '').key.should == 'symbol' end end describe '#to_ini' do it 'should include the key and value' do IniParse::Lines::Option.new('key', 'value').to_ini.should == 'key = value' end end describe '.parse' do def parse(line, opts = {}) IniParse::Lines::Option.parse(line, opts) end it 'should typecast empty values to nil' do parse('key =').should be_option_tuple('key', nil) parse('key = ').should be_option_tuple('key', nil) parse('key = ').should be_option_tuple('key', nil) end it 'should not typecast "true" if true is part of a word' do parse('key = TestTrueTest').should be_option_tuple('key', 'TestTrueTest') parse('key = TrueTest').should be_option_tuple('key', 'TrueTest') parse('key = TestTrue').should be_option_tuple('key', 'TestTrue') end it 'should not typecast "false" if false is part of a word' do parse('key = TestFalseTest').should be_option_tuple('key', 'TestFalseTest') parse('key = FalseTest').should be_option_tuple('key', 'FalseTest') parse('key = TestFalse').should be_option_tuple('key', 'TestFalse') end it 'should typecast "true" to TrueClass' do parse('key = true').should be_option_tuple('key', true) parse('key = TRUE').should be_option_tuple('key', true) end it 'should typecast "false" to FalseClass' do parse('key = false').should be_option_tuple('key', false) parse('key = FALSE').should be_option_tuple('key', false) end it 'should typecast integer values to Integer' do parse('key = 1').should be_option_tuple('key', 1) parse('key = 10').should be_option_tuple('key', 10) end it 'should not typecast integers with a leading 0 to Integer' do parse('key = 0700').should be_option_tuple('key', '0700') end it 'should typecast negative integer values to Integer' do parse('key = -1').should be_option_tuple('key', -1) end it 'should typecast float values to Float' do parse('key = 3.14159265').should be_option_tuple('key', 3.14159265) end it 'should typecast negative float values to Float' do parse('key = -3.14159265').should be_option_tuple('key', -3.14159265) end it 'should typecast scientific notation numbers to Float' do parse('key = 10e5').should be_option_tuple('key', 10e5) parse('key = 10e+5').should be_option_tuple('key', 10e5) parse('key = 10e-5').should be_option_tuple('key', 10e-5) parse('key = -10e5').should be_option_tuple('key', -10e5) parse('key = -10e+5').should be_option_tuple('key', -10e5) parse('key = -10e-5').should be_option_tuple('key', -10e-5) parse('key = 3.14159265e5').should be_option_tuple('key', 3.14159265e5) parse('key = 3.14159265e+5').should be_option_tuple('key', 3.14159265e5) parse('key = 3.14159265e-5').should be_option_tuple('key', 3.14159265e-5) parse('key = -3.14159265e5').should be_option_tuple('key', -3.14159265e5) parse('key = -3.14159265e+5').should be_option_tuple('key', -3.14159265e5) parse('key = -3.14159265e-5').should be_option_tuple('key', -3.14159265e-5) end end end # # Blank # # # Comment # describe 'IniParse::Lines::Comment' do describe '#has_comment?' do it 'should return true if :comment has a non-blank value' do IniParse::Lines::Comment.new(:comment => 'comment').should have_comment end it 'should return true if :comment has a blank value' do IniParse::Lines::Comment.new(:comment => '').should have_comment end it 'should return true if :comment has a nil value' do IniParse::Lines::Comment.new.should have_comment IniParse::Lines::Comment.new(:comment => nil).should have_comment end end describe '#to_ini' do it 'should return the comment' do IniParse::Lines::Comment.new( :comment => 'a comment' ).to_ini.should == '; a comment' end it 'should preserve comment offset' do IniParse::Lines::Comment.new( :comment => 'a comment', :comment_offset => 10 ).to_ini.should == ' ; a comment' end it 'should return just the comment_sep if the comment is blank' do IniParse::Lines::Comment.new.to_ini.should == ';' end end end iniparse-1.4.2/spec/spec_helper.rb0000644000175000017500000001004312725022733017313 0ustar terceiroterceiro$:.push File.join(File.dirname(__FILE__), '..', 'lib') require 'rubygems' require 'rspec' require 'iniparse' require File.join(File.dirname(__FILE__), 'spec_fixtures') module IniParse module Test module Helpers # Taken from Merb Core's spec helper. # Merb is licenced using the MIT License and is copyright # Engine Yard Inc. class BeKindOf def initialize(expected) # + args @expected = expected end def matches?(target) @target = target @target.kind_of?(@expected) end def failure_message "expected #{@expected} but got #{@target.class}" end def negative_failure_message "expected #{@expected} to not be #{@target.class}" end def description "be_kind_of #{@target}" end end # Used to match line tuples returned by Parser.parse_line. class BeLineTuple def initialize(type, value_keys = [], *expected) @expected_type = type @value_keys = value_keys if expected.nil? @expected_opts = {} @expected_values = [] else @expected_opts = expected.pop @expected_values = expected end end def matches?(tuple) @tuple = tuple @failure_message = catch(:fail) do tuple? correct_type? correct_values? correct_opts? true end @failure_message == true end def failure_message "expected #{@expected_type} tuple #{@failure_message}" end def negative_failure_message "expected #{@tuple.inspect} to not be #{@expected_type} tuple" end def description "be_#{@expected_type}_tuple #{@tuple}" end ####### private ####### # Matchers. def tuple? throw :fail, "but was #{@tuple.class}" unless @tuple.kind_of?(Array) end def correct_type? throw :fail, "but was #{type} tuple" unless type == @expected_type end def correct_values? # Make sure the values match. @value_keys.each_with_index do |key, i| if @expected_values[i] != :any && values[i] != @expected_values[i] throw :fail, 'with %s value of "%s" but was "%s"' % [ key, values[i], @expected_values[i] ] end end end def correct_opts? if(! @expected_opts.nil?) if (! @expected_opts.empty?) && opts.empty? throw :fail, 'with options but there were none' end @expected_opts.each do |key, value| unless opts.has_key?(key) throw :fail, 'with option "%s", but key was not present' % key end unless opts[key] == value throw :fail, 'with option "%s" => "%s" but was "%s"' % [ key, value, opts[key] ] end end end end # Tuple values, etc. def type @type ||= @tuple.first end def values @values ||= @tuple.length < 3 ? [] : @tuple[1..-2] end def opts @opts ||= @tuple.last end end def be_kind_of(expected) # + args BeKindOf.new(expected) end def be_section_tuple(key = :any, opts = {}) BeLineTuple.new(:section, [:key], key, opts) end def be_option_tuple(key = :any, value = :any, opts = {}) BeLineTuple.new(:option, [:key, :value], key, value, opts) end def be_blank_tuple BeLineTuple.new(:blank) end def be_comment_tuple(comment = :any, opts = {}) BeLineTuple.new(:comment, [:comment], comment, opts) end def fixture(fix) IniParse::Test::Fixtures[fix] end end end end RSpec.configure do |config| config.include(IniParse::Test::Helpers) end iniparse-1.4.2/spec/fixtures/0000755000175000017500000000000012725022733016350 5ustar terceiroterceiroiniparse-1.4.2/spec/fixtures/authconfig.ini0000644000175000017500000000060112725022733021175 0ustar terceiroterceiro[global] #--authconfig--start-line-- # Generated by authconfig on 2014/04/08 15:14:28 # DO NOT EDIT THIS SECTION (delimited by --start-line--/--end-line--) # Any modification may be deleted or altered by authconfig in future template homedir = /home/%U template shell = /bin/bash winbind use default domain = true winbind offline logon = false #--authconfig--end-line-- iniparse-1.4.2/spec/fixtures/race07.ini0000644000175000017500000000544212725022733020137 0ustar terceiroterceiro; All names and Steam IDs changed to fake values. [Header] Game=RACE 07 Version=1.1.1.14 TimeString=2008/09/13 23:26:32 Aids=0,0,0,0,0,1,1,0,0 [Race] RaceMode=5 Scene=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.TRK AIDB=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW Race Length=0.100 Track Length=4018.8376 [Slot010] Driver=Mark Voss SteamUser=mvoss SteamId=1865369 Vehicle=Chevrolet Lacetti 2007 Team=TEMPLATE_TEAM QualTime=1:37.839 Laps=13 Lap=(0, -1.000, 1:48.697) Lap=(1, 89.397, 1:39.455) Lap=(2, 198.095, 1:38.060) Lap=(3, 297.550, 1:38.632) Lap=(4, 395.610, 1:38.031) Lap=(5, 494.242, 1:39.562) Lap=(6, 592.273, 1:39.950) Lap=(7, 691.835, 1:38.366) Lap=(8, 791.785, 1:39.889) Lap=(9, 890.151, 1:39.420) Lap=(10, 990.040, 1:39.401) Lap=(11, 1089.460, 1:39.506) Lap=(12, 1188.862, 1:40.017) LapDistanceTravelled=3857.750244 BestLap=1:38.031 RaceTime=0:21:38.988 [Slot016] Driver=Corey Ball SteamUser=cball SteamId=889853 Vehicle=SEAT Leon 2007 Team=TEMPLATE_TEAM QualTime=1:37.904 Laps=9 Lap=(0, -1.000, 1:51.434) Lap=(1, 89.397, 1:39.427) Lap=(2, 200.831, 1:38.394) Lap=(3, 300.258, 1:40.239) Lap=(4, 398.653, 1:38.172) Lap=(5, 498.891, 1:38.427) Lap=(6, 597.063, 1:39.271) Lap=(7, 695.490, 1:39.922) Lap=(8, 794.761, 1:40.305) LapDistanceTravelled=532.898193 BestLap=1:38.172 RaceTime=DNF Reason=0 [Slot013] Driver=Gabriel Lloyd SteamUser=glloyd SteamId=635 Vehicle=Chevrolet Lacetti 2007 Team=TEMPLATE_TEAM QualTime=1:36.607 Laps=13 Lap=(0, -1.000, 1:50.816) Lap=(1, 89.397, 1:38.835) Lap=(2, 200.213, 1:38.082) Lap=(3, 299.048, 1:38.367) Lap=(4, 397.131, 1:37.825) Lap=(5, 495.497, 1:38.757) Lap=(6, 593.322, 1:38.718) Lap=(7, 692.080, 1:38.478) Lap=(8, 790.797, 1:39.347) Lap=(9, 889.275, 1:38.713) Lap=(10, 988.622, 1:38.952) Lap=(11, 1087.336, 1:39.285) Lap=(12, 1186.288, 1:40.555) LapDistanceTravelled=3898.517578 BestLap=1:37.825 RaceTime=0:21:36.730 [Slot018] Driver=Reino Lintula SteamUser=rlintula SteamId=1816 Vehicle=SEAT Leon 2007 Team=TEMPLATE_TEAM QualTime=1:39.602 Laps=7 Lap=(0, -1.000, 1:52.788) Lap=(1, 112.593, 1:39.346) Lap=(2, 225.381, 1:40.680) Lap=(3, 324.727, 1:38.775) Lap=(4, 425.407, 1:40.149) Lap=(5, 524.182, 1:41.551) Lap=(6, 624.331, 1:46.908) LapDistanceTravelled=1333.551270 BestLap=1:38.775 RaceTime=DNF Reason=0 [Slot002] Driver=Jerry Lalich SteamUser=jlalich SteamId=236892 Vehicle=Chevrolet Lacetti 2007 Team=TEMPLATE_TEAM QualTime=1:38.081 Laps=13 Lap=(0, -1.000, 1:48.530) Lap=(1, 89.397, 1:39.213) Lap=(2, 197.927, 1:37.933) Lap=(3, 297.140, 1:37.717) Lap=(4, 395.073, 1:38.500) Lap=(5, 492.790, 1:38.641) Lap=(6, 591.290, 1:39.810) Lap=(7, 689.931, 1:39.177) Lap=(8, 789.742, 1:40.122) Lap=(9, 888.918, 1:38.928) Lap=(10, 989.040, 1:39.238) Lap=(11, 1087.968, 1:39.223) Lap=(12, 1187.206, 1:39.888) LapDistanceTravelled=3892.720215 BestLap=1:37.717 RaceTime=0:21:36.920 [END] iniparse-1.4.2/spec/fixtures/smb.ini0000644000175000017500000000604612725022733017640 0ustar terceiroterceiro; Configuration file for the Samba software suite. ; ============================================================================ ; ; For the format of this file and comprehensive descriptions of all the ; configuration option, please refer to the man page for smb.conf(5). ; ; The following configuration should suit most systems for basic usage and ; initial testing. It gives all clients access to their home directories and ; allows access to all printers specified in /etc/printcap. ; BEGIN required configuration ; Parameters inside the required configuration block should not be altered. ; They may be changed at any time by upgrades or other automated processes. ; ; Site-specific customizations will only be preserved if they are done ; outside this block. If you choose to make customizations, it is your ; own responsibility to verify that they work correctly with the supported ; configuration tools. [global] debug pid = yes log level = 1 server string = Mac OS X printcap name = cups printing = cups encrypt passwords = yes use spnego = yes passdb backend = odsam idmap domains = default idmap config default: default = yes idmap config default: backend = odsam idmap alloc backend = odsam idmap negative cache time = 5 map to guest = Bad User guest account = nobody unix charset = UTF-8-MAC display charset = UTF-8-MAC dos charset = 437 vfs objects = darwinacl,darwin_streams ; Don't become a master browser unless absolutely necessary. os level = 2 domain master = no ; For performance reasons, set the transmit buffer size ; to the maximum and enable sendfile support. max xmit = 131072 use sendfile = yes ; The darwin_streams module gives us named streams support. stream support = yes ea support = yes ; Enable locking coherency with AFP. darwin_streams:brlm = yes ; Core files are invariably disabled system-wide, but attempting to ; dump core will trigger a crash report, so we still want to try. enable core files = yes ; Configure usershares for use by the synchronize-shares tool. usershare max shares = 1000 usershare path = /var/samba/shares usershare owner only = no usershare allow guests = yes usershare allow full config = yes ; Filter inaccessible shares from the browse list. com.apple:filter shares by access = yes ; Check in with PAM to enforce SACL access policy. obey pam restrictions = yes ; Don't be trying to enforce ACLs in userspace. acl check permissions = no ; Make sure that we resolve unqualified names as NetBIOS before DNS. name resolve order = lmhosts wins bcast host ; Pull in system-wide preference settings. These are managed by ; synchronize-preferences tool. include = /var/db/smb.conf [printers] comment = All Printers path = /tmp printable = yes guest ok = no create mode = 0700 writeable = no browseable = no ; Site-specific parameters can be added below this comment. ; END required configuration. iniparse-1.4.2/spec/fixtures/openttd.ini0000644000175000017500000002476712725022733020546 0ustar terceiroterceiro [misc] display_opt = SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|FULL_DETAIL|WAYPOINTS news_ticker_sound = false fullscreen = false language = english_US.lng resolution = 1680,936 screenshot_format = savegame_format = rightclick_emulate = false small_font = medium_font = large_font = small_size = 6 medium_size = 10 large_size = 16 small_aa = false medium_aa = false large_aa = false sprite_cache_size = 4 player_face = 0 transparency_options = 3 transparency_locks = 0 invisibility_options = 30 keyboard = keyboard_caps = [music] playlist = 0 music_vol = 0 effect_vol = 0 custom_1 = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 custom_2 = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 playing = false shuffle = false extmidi = timidity [difficulty] max_no_competitors = 0 competitor_start_time = 2 number_towns = 1 number_industries = 2 max_loan = 500000 initial_interest = 2 vehicle_costs = 0 competitor_speed = 2 competitor_intelligence = 0 vehicle_breakdowns = 1 subsidy_multiplier = 2 construction_cost = 0 terrain_type = 0 quantity_sea_lakes = 0 economy = 0 line_reverse_mode = 0 disasters = 0 town_council_tolerance = 0 diff_level = 3 [game_creation] town_name = english landscape = temperate snow_line = 56 snow_line_height = 7 starting_year = 1960 land_generator = 1 oil_refinery_limit = 32 tgen_smoothness = 0 generation_seed = 83252223 tree_placer = 2 heightmap_rotation = 0 se_flat_world_height = 0 map_x = 9 map_y = 9 [vehicle] road_side = left realistic_acceleration = true mammoth_trains = true never_expire_vehicles = true max_trains = 500 max_roadveh = 500 max_aircraft = 200 max_ships = 300 servint_ispercent = false servint_trains = 150 servint_roadveh = 150 servint_ships = 360 servint_aircraft = 100 wagon_speed_limits = true disable_elrails = false freight_trains = 1 plane_speed = 4 dynamic_engines = false extend_vehicle_life = 0 [construction] build_on_slopes = true autoslope = true extra_dynamite = false longbridges = true signal_side = true road_stop_on_town_road = true raw_industry_construction = 1 [station] always_small_airport = true join_stations = true nonuniform_stations = true station_spread = 12 modified_catchment = true adjacent_stations = true [economy] town_layout = 2 station_noise_level = false inflation = true multiple_industry_per_town = true same_industry_close = true bribe = true exclusive_rights = true give_money = true smooth_economy = true allow_shares = false town_growth_rate = 1 larger_towns = 6 initial_city_size = 2 mod_road_rebuild = true dist_local_authority = 20 town_noise_population = 800,2000,4000 [pf] forbid_90_deg = false roadveh_queue = true pathfinder_for_trains = 2 pathfinder_for_roadvehs = 2 pathfinder_for_ships = 0 wait_oneway_signal = 15 wait_twoway_signal = 41 wait_for_pbs_path = 30 reserve_paths = false path_backoff_interval = 20 opf.pf_maxlength = 4096 opf.pf_maxdepth = 48 npf.npf_max_search_nodes = 10000 npf.npf_rail_firstred_penalty = 1000 npf.npf_rail_firstred_exit_penalty = 10000 npf.npf_rail_lastred_penalty = 1000 npf.npf_rail_station_penalty = 100 npf.npf_rail_slope_penalty = 100 npf.npf_rail_curve_penalty = 1 npf.npf_rail_depot_reverse_penalty = 5000 npf.npf_rail_pbs_cross_penalty = 300 npf.npf_rail_pbs_signal_back_penalty = 1500 npf.npf_buoy_penalty = 200 npf.npf_water_curve_penalty = 25 npf.npf_road_curve_penalty = 1 npf.npf_crossing_penalty = 300 npf.npf_road_drive_through_penalty = 800 yapf.disable_node_optimization = false yapf.max_search_nodes = 10000 yapf.rail_firstred_twoway_eol = true yapf.rail_firstred_penalty = 1000 yapf.rail_firstred_exit_penalty = 10000 yapf.rail_lastred_penalty = 1000 yapf.rail_lastred_exit_penalty = 10000 yapf.rail_station_penalty = 1000 yapf.rail_slope_penalty = 200 yapf.rail_curve45_penalty = 300 yapf.rail_curve90_penalty = 600 yapf.rail_depot_reverse_penalty = 5000 yapf.rail_crossing_penalty = 300 yapf.rail_look_ahead_max_signals = 10 yapf.rail_look_ahead_signal_p0 = 500 yapf.rail_look_ahead_signal_p1 = -100 yapf.rail_look_ahead_signal_p2 = 5 yapf.rail_pbs_cross_penalty = 300 yapf.rail_pbs_station_penalty = 800 yapf.rail_pbs_signal_back_penalty = 1500 yapf.rail_doubleslip_penalty = 100 yapf.rail_longer_platform_penalty = 800 yapf.rail_longer_platform_per_tile_penalty = 0 yapf.rail_shorter_platform_penalty = 4000 yapf.rail_shorter_platform_per_tile_penalty = 0 yapf.road_slope_penalty = 200 yapf.road_curve_penalty = 100 yapf.road_crossing_penalty = 300 yapf.road_stop_penalty = 800 [order] gotodepot = true no_servicing_if_no_breakdowns = true timetabling = true improved_load = true selectgoods = true serviceathelipad = true gradual_loading = true [gui] colored_news_year = 1901 ending_year = 2051 autosave = yearly vehicle_speed = true status_long_date = true show_finances = true autoscroll = false reverse_scroll = true smooth_scroll = false measure_tooltip = true errmsg_duration = 5 toolbar_pos = 1 window_snap_radius = 10 population_in_label = true link_terraform_toolbar = true liveries = 2 prefer_teamchat = false scrollwheel_scrolling = 0 scrollwheel_multiplier = 5 pause_on_newgame = false advanced_vehicle_list = 2 timetable_in_ticks = false loading_indicators = 1 default_rail_type = 6 enable_signal_gui = true drag_signals_density = 4 semaphore_build_before = 1975 train_income_warn = true order_review_system = 2 lost_train_warn = true autorenew = true autorenew_months = 12 autorenew_money = 80000 always_build_infrastructure = false new_nonstop = false keep_all_autosave = false autosave_on_exit = false max_num_autosaves = 16 bridge_pillars = true auto_euro = true news_message_timeout = 2 show_track_reservation = false default_signal_type = 0 cycle_signal_types = 0 console_backlog_timeout = 100 console_backlog_length = 100 network_chat_box_width = 700 network_chat_box_height = 25 right_mouse_btn_emulation = 0 [ai] ainew_active = false ai_in_multiplayer = false ai_disable_veh_train = false ai_disable_veh_roadveh = false ai_disable_veh_aircraft = false ai_disable_veh_ship = false [locale] currency = GBP units = imperial [network] max_join_time = 500 pause_on_join = true server_bind_ip = 0.0.0.0 server_port = 3979 server_advertise = false lan_internet = 1 client_name = Ant server_password = rcon_password = default_company_pass = server_name = connect_to_ip = network_id = autoclean_companies = false autoclean_unprotected = 12 autoclean_protected = 36 max_companies = 8 max_clients = 10 max_spectators = 10 restart_game_year = 0 min_active_clients = 0 server_lang = ANY reload_cfg = false last_host = last_port = [currency] rate = 1 separator = . to_euro = 0 prefix = "" suffix = " credits" [servers] [bans] [news_display] arrival_player = summarized arrival_other = summarized accident = full company_info = full open = summarized close = summarized economy = summarized production_player = full production_other = full production_nobody = summarized advice = full new_vehicles = full acceptance = summarized subsidies = summarized general = summarized [version] version_string = r14768 version_number = 070039B0 [preset-J] gcf/1_other/BlackCC/mauvetoblackw.grf = gcf/1_other/OpenGFX/newbuildings.grf = gcf/1_other/OpenGFX/OpenGFX_NewShips_v0.1.grf = gcf/1_other/OpenGFX/OpenGFX_NewWaterFeatures.grf = gcf/1_other/OpenGFX/OpenGFX_-_newEyeCandy_v0.2.grf = gcf/1_other/OpenGFX/OpenGFX_-_newFaces_v0.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newFonts_-_Newspaper_Fonts_v0.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newFonts_-_Small_Fonts_v0.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newIndustries_v0.8.grf = gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_-_Airports_v0.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_-_newBridges_v0.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_v0.6.grf = gcf/1_other/OpenGFX/OpenGFX_NewLandscape_v0.3.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newTerrain_v0.4.grf = gcf/4_infrastructure/transrapidtrackset/z/signals.grf = gcf/8_vehicles/trains_wagons/pb_ukrs/pb_ukrs.grf = gcf/8_vehicles/trains_wagons/pb_ukrs/ukrsap1w.grf = gcf/6_town_buildings/ttrs3/ttrs3w.GRF = gcf/7_stations/basic_platforms/basic_platformsw.grf = gcf/1_other/townnames/british/brit_names.grf = gcf/7_stations/indstatr/indstatrw.grf = gcf/5_industries_cargos/pikkind/pikkindw.grf = gcf/4_infrastructure/ukroadset/UKRoadsetw.grf = gcf/7_stations/newstats/newstatsw.grf = gcf/4_infrastructure/nhfoundations/nhfoundationsw.grf = gcf/4_infrastructure/bktun/BKTunw.grf = gcf/7_stations/buffers/buffers.grf = gcf/8_vehicles/planes/pb_av8/pb_av8w.grf = gcf/8_vehicles/road_vehicles/egrvts/egrvts.grf = gcf/4_infrastructure/b_newbridges/newbridgesW.GRF = gcf/8_vehicles/ships/newships/newshipsw.grf = gcf/8_vehicles/ships/newships/nshp_ecs.grf = gcf/4_infrastructure/nhdep/nhdepw.grf = gcf/4_infrastructure/fence/fencew.grf = gcf/2_landscape/stolentrees/stolentreesw_162_108.grf = gcf/5_industries_cargos/pikkind/z/pikbrikw.grf = [newgrf] gcf/2_landscape/rivers/riversw.grf = gcf/1_other/townnames/british/brit_names.grf = gcf/8_vehicles/planes/pb_av8/pb_av8w.grf = gcf/8_vehicles/trains_wagons/empty/empty.grf = gcf/8_vehicles/road_vehicles/grvts/egrvts.grf = gcf/7_stations/buffers/buffers.grf = gcf/8_vehicles/road_vehicles/heqsdt/heqsdt.grf = gcf/7_stations/indstatr/indstatrw.grf = gcf/1_other/BlackCC/mauvetoblackw.grf = gcf/4_infrastructure/b_newtramtracks/NewTramTracksW_v0.4.1.grf = gcf/4_infrastructure/nhfoundations/nhfoundationsw.grf = gcf/8_vehicles/ships/newships/newshipsw.grf = gcf/8_vehicles/ships/newships/nshp_ecs.grf = gcf/7_stations/newstats/newstatsw.grf = gcf/4_infrastructure/nhdep/nhdepw.grf = gcf/1_other/OpenGFX/morebuildings.grf = gcf/1_other/OpenGFX/newbuildings022.grf = gcf/1_other/OpenGFX/hq.grf = gcf/1_other/OpenGFX/OpenGFX_NewWaterFeatures.grf = gcf/1_other/OpenGFX/OpenGFX_-_newEyeCandy_v0.2.grf = gcf/1_other/OpenGFX/OpenGFX_NewIndustries_v0.10.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_-_Airports_v0.1.grf = gcf/1_other/OpenGFX/OpenGFX_newInfrastructure_v0.7.grf = gcf/1_other/OpenGFX/OpenGFX_NewLandscape_v0.3.1.grf = gcf/1_other/OpenGFX/OpenGFX_-_newTerrain_v0.4.grf = gcf/5_industries_cargos/pikkind/pikkindw.grf = gcf/2_landscape/stolentrees/stolentreesw_162_108.grf = gcf/4_infrastructure/totalbridges/total_bridges.grf = gcf/7_stations/ukwaypoints/ukwaypointsw.grf = gcf/8_vehicles/trains_wagons/pb_ukrs/pb_ukrs.grf = 0 3 0 gcf/8_vehicles/trains_wagons/pb_ukrs/ukrsap1w.grf = gcf/4_infrastructure/yarrs/yarrs.grf = gcf/6_town_buildings/w2w/w2w.grf = gcf/1_other/townnames/welsh/welshnames.grf = gcf/2_landscape/smoothsnow/smoothsnoww.grf = gcf/6_town_buildings/pb_ukrh/pb_ukrhw.grf = gcf/9_last/shiptool/shiptoolv4.grf = [newgrf-static] iniparse-1.4.2/spec/spec_fixtures.rb0000644000175000017500000000272712725022733017717 0ustar terceiroterceiromodule IniParse module Test class Fixtures @@fixtures = {} def self.[](fix) if @@fixtures.has_key?(fix) @@fixtures[fix] else @@fixtures[fix] = File.read( File.join(File.expand_path('fixtures', File.dirname(__FILE__)), fix) ) end end def self.[]=(fix, val) @@fixtures[fix] = val end end end end IniParse::Test::Fixtures[:comment_before_section] = <<-FIX.gsub(/^ /, '') ; This is a comment [first_section] key = value FIX IniParse::Test::Fixtures[:blank_before_section] = <<-FIX.gsub(/^ /, '') [first_section] key = value FIX IniParse::Test::Fixtures[:blank_in_section] = <<-FIX.gsub(/^ /, '') [first_section] key = value FIX IniParse::Test::Fixtures[:option_before_section] = <<-FIX.gsub(/^ /, '') foo = bar [foo] another = thing FIX IniParse::Test::Fixtures[:invalid_line] = <<-FIX.gsub(/^ /, '') this line is not valid FIX IniParse::Test::Fixtures[:section_with_equals] = <<-FIX.gsub(/^ /, '') [first_section = name] key = value [another_section = a name] another = thing FIX IniParse::Test::Fixtures[:comment_line] = <<-FIX.gsub(/^ /, '') [first_section] ; block comment ; ; with more lines ; key = value FIX IniParse::Test::Fixtures[:duplicate_section] = <<-FIX.gsub(/^ /, '') [first_section] key = value another = thing [second_section] okay = yes [first_section] third = fourth another = again FIX iniparse-1.4.2/spec/document_spec.rb0000644000175000017500000001061412725022733017656 0ustar terceiroterceirorequire 'spec_helper' describe "IniParse::Document" do it 'should have a +lines+ reader' do methods = IniParse::Document.instance_methods.map { |m| m.to_sym } methods.should include(:lines) end it 'should not have a +lines+ writer' do methods = IniParse::Document.instance_methods.map { |m| m.to_sym } methods.should_not include(:lines=) end it 'should delegate #[] to +lines+' do doc = IniParse::Document.new doc.lines.should_receive(:[]).with('key') doc['key'] end it 'should call #each to +lines+' do doc = IniParse::Document.new doc.lines.should_receive(:each) doc.each { |l| } end it 'should be enumerable' do IniParse::Document.included_modules.should include(Enumerable) sections = [ IniParse::Lines::Section.new('first section'), IniParse::Lines::Section.new('second section') ] doc = IniParse::Document.new doc.lines << sections[0] << sections[1] doc.map { |line| line }.should == sections end describe '#has_section?' do before(:all) do @doc = IniParse::Document.new @doc.lines << IniParse::Lines::Section.new('first section') @doc.section('another section') end it 'should return true if a section with the given key exists' do @doc.should have_section('first section') @doc.should have_section('another section') end it 'should return true if no section with the given key exists' do @doc.should_not have_section('second section') end end describe '#delete' do let(:document) do IniParse::Generator.gen do |doc| doc.section('first') do |section| section.alpha = 'bravo' section.charlie = 'delta' end doc.section('second') do |section| section.echo = 'foxtrot' section.golf = 'hotel' end end end it 'removes the section given a key' do lambda { document.delete('first') }. should change { document['first'] }.to(nil) end it 'removes the section given a Section' do lambda { document.delete(document['first']) }. should change { document['first'] }.to(nil) end it 'removes the lines' do lambda { document.delete('first') }. should change { document.to_ini.match(/alpha/) }.to(nil) end it 'returns the document' do document.delete('first').should eql(document) end end describe '#to_ini' do let(:document) do IniParse.parse(<<-EOF.gsub(/^\s+/, '')) [one] alpha = bravo [two] chalie = delta EOF end context 'when the document has a trailing Blank line' do it 'outputs the newline to the output string' do expect(document.to_ini).to match(/\n\Z/) end it 'does not add a second newline to the output string' do expect(document.to_ini).to_not match(/\n\n\Z/) end end # when the document has a trailing Blank line context 'when the document has no trailing Blank line' do before { document.delete('two') } it 'adds a newline to the output string' do expect(document.to_ini).to match(/\n\Z/) end end # when the document has no trailing Blank line end # to_ini describe '#save' do describe 'when no path is given to save' do it 'should save the INI document if a path was given when initialized' do doc = IniParse::Document.new('/a/path/to/a/file.ini') File.should_receive(:open).with('/a/path/to/a/file.ini', 'w') doc.save end it 'should raise IniParseError if no path was given when initialized' do lambda { IniParse::Document.new.save }.should \ raise_error(IniParse::IniParseError) end end describe 'when a path is given to save' do it "should update the document's +path+" do File.stub(:open).and_return(true) doc = IniParse::Document.new('/a/path/to/a/file.ini') doc.save('/a/new/path.ini') doc.path.should == '/a/new/path.ini' end it 'should save the INI document to the given path' do File.should_receive(:open).with('/a/new/path.ini', 'w') IniParse::Document.new('/a/path/to/a/file.ini').save('/a/new/path.ini') end it 'should raise IniParseError if no path was given when initialized' do lambda { IniParse::Document.new.save }.should \ raise_error(IniParse::IniParseError) end end end end iniparse-1.4.2/spec/line_collection_spec.rb0000644000175000017500000001405112725022733021201 0ustar terceiroterceirorequire 'spec_helper' # ---------------------------------------------------------------------------- # Shared specs for all Collection types... # ---------------------------------------------------------------------------- share_examples_for "LineCollection" do before(:each) do @collection << (@c1 = IniParse::Lines::Comment.new) @collection << @i1 @collection << @i2 @collection << (@b1 = IniParse::Lines::Blank.new) @collection << @i3 @collection << (@b2 = IniParse::Lines::Blank.new) end describe '#each' do it 'should remove blanks and comments by default' do @collection.each { |l| l.should be_kind_of(@i1.class) } end it 'should not remove blanks and comments if true is given' do arr = [] # map(true)->each(true) not possible with Enumerable @collection.each(true) do |line| arr << line end arr.should == [@c1, @i1, @i2, @b1, @i3, @b2] end end describe '#[]' do it 'should fetch the correct value' do @collection['first'].should == @i1 @collection['second'].should == @i2 @collection['third'].should == @i3 end it 'should return nil if the given key does not exist' do @collection['does not exist'].should be_nil end end describe '#[]=' do it 'should successfully add a new key' do @collection['fourth'] = @new @collection['fourth'].should == @new end it 'should successfully update an existing key' do @collection['second'] = @new @collection['second'].should == @new # Make sure the old data is gone. @collection.detect { |s| s.key == 'second' }.should be_nil end it 'should typecast given keys to a string' do @collection[:a_symbol] = @new @collection['a_symbol'].should == @new end end describe '#<<' do it 'should set the key correctly if given a new item' do @collection.should_not have_key(@new.key) @collection << @new @collection.should have_key(@new.key) end it 'should append Blank lines' do @collection << IniParse::Lines::Blank.new @collection.instance_variable_get(:@lines).last.should \ be_kind_of(IniParse::Lines::Blank) end it 'should append Comment lines' do @collection << IniParse::Lines::Comment.new @collection.instance_variable_get(:@lines).last.should \ be_kind_of(IniParse::Lines::Comment) end it 'should return self' do (@collection << @new).should == @collection end end describe '#delete' do it 'should remove the given value and adjust the indicies' do @collection['second'].should_not be_nil @collection.delete('second') @collection['second'].should be_nil @collection['first'].should == @i1 @collection['third'].should == @i3 end it "should do nothing if the supplied key does not exist" do @collection.delete('does not exist') @collection['first'].should == @i1 @collection['third'].should == @i3 end end describe '#to_a' do it 'should return an array' do @collection.to_a.should be_kind_of(Array) end it 'should include all lines' do @collection.to_a.should == [@c1, @i1, @i2, @b1, @i3, @b2] end it 'should include references to the same line objects as the collection' do @collection << @new @collection.to_a.last.object_id.should == @new.object_id end end describe '#to_hash' do it 'should return a hash' do @collection.to_hash.should be_kind_of(Hash) end it 'should have the correct keys' do hash = @collection.to_hash hash.keys.length.should == 3 hash.should have_key('first') hash.should have_key('second') hash.should have_key('third') end it 'should have the correct values' do hash = @collection.to_hash hash['first'].should == @i1 hash['second'].should == @i2 hash['third'].should == @i3 end end describe '#keys' do it 'should return an array of strings' do @collection.keys.should == ['first', 'second', 'third'] end end end # ---------------------------------------------------------------------------- # On with the collection specs... # ---------------------------------------------------------------------------- describe 'IniParse::OptionCollection' do before(:each) do @collection = IniParse::OptionCollection.new @i1 = IniParse::Lines::Option.new('first', 'v1') @i2 = IniParse::Lines::Option.new('second', 'v2') @i3 = IniParse::Lines::Option.new('third', 'v3') @new = IniParse::Lines::Option.new('fourth', 'v4') end it_should_behave_like 'LineCollection' describe '#<<' do it 'should raise a LineNotAllowed exception if a Section is pushed' do lambda { @collection << IniParse::Lines::Section.new('s') }.should \ raise_error(IniParse::LineNotAllowed) end it 'should add the Option as a duplicate if an option with the same key exists' do option_one = IniParse::Lines::Option.new('k', 'value one') option_two = IniParse::Lines::Option.new('k', 'value two') @collection << option_one @collection << option_two @collection['k'].should == [option_one, option_two] end end describe '#keys' do it 'should handle duplicates' do @collection << @i1 << @i2 << @i3 @collection << IniParse::Lines::Option.new('first', 'v5') @collection.keys.should == ['first', 'second', 'third'] end end end describe 'IniParse::SectionCollection' do before(:each) do @collection = IniParse::SectionCollection.new @i1 = IniParse::Lines::Section.new('first') @i2 = IniParse::Lines::Section.new('second') @i3 = IniParse::Lines::Section.new('third') @new = IniParse::Lines::Section.new('fourth') end it_should_behave_like 'LineCollection' describe '#<<' do it 'should add merge Section with the other, if it is a duplicate' do new_section = IniParse::Lines::Section.new('first') @collection << @i1 @i1.should_receive(:merge!).with(new_section).once @collection << new_section end end end iniparse-1.4.2/spec/fixture_spec.rb0000644000175000017500000001515412725022733017532 0ustar terceiroterceirorequire 'spec_helper' describe "IniParse" do describe 'openttd.ini fixture' do before(:all) do @fixture = fixture('openttd.ini') end it 'should parse without any errors' do lambda { IniParse.parse(@fixture) }.should_not raise_error end it 'should have the correct sections' do IniParse.parse(fixture('openttd.ini')).lines.keys.should == [ 'misc', 'music', 'difficulty', 'game_creation', 'vehicle', 'construction', 'station', 'economy', 'pf', 'order', 'gui', 'ai', 'locale', 'network', 'currency', 'servers', 'bans', 'news_display', 'version', 'preset-J', 'newgrf', 'newgrf-static' ] end it 'should have the correct options' do # Test the keys from one section. doc = IniParse.parse(@fixture) section = doc['misc'] section.lines.keys.should == [ 'display_opt', 'news_ticker_sound', 'fullscreen', 'language', 'resolution', 'screenshot_format', 'savegame_format', 'rightclick_emulate', 'small_font', 'medium_font', 'large_font', 'small_size', 'medium_size', 'large_size', 'small_aa', 'medium_aa', 'large_aa', 'sprite_cache_size', 'player_face', 'transparency_options', 'transparency_locks', 'invisibility_options', 'keyboard', 'keyboard_caps' ] # Test some of the options. section['display_opt'].should == 'SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|FULL_DETAIL|WAYPOINTS' section['news_ticker_sound'].should be_false section['language'].should == 'english_US.lng' section['resolution'].should == '1680,936' section['large_size'].should == 16 # Test some other options. doc['currency']['suffix'].should == '" credits"' doc['news_display']['production_nobody'].should == 'summarized' doc['version']['version_number'].should == '070039B0' doc['preset-J']['gcf/1_other/BlackCC/mauvetoblackw.grf'].should be_nil doc['preset-J']['gcf/1_other/OpenGFX/OpenGFX_-_newFaces_v0.1.grf'].should be_nil end it 'should be identical to the original when calling #to_ini' do IniParse.parse(@fixture).to_ini.should == @fixture end end describe 'race07.ini fixture' do before(:all) do @fixture = fixture('race07.ini') end it 'should parse without any errors' do lambda { IniParse.parse(@fixture) }.should_not raise_error end it 'should have the correct sections' do IniParse.parse(fixture('race07.ini')).lines.keys.should == [ 'Header', 'Race', 'Slot010', 'Slot016', 'Slot013', 'Slot018', 'Slot002', 'END' ] end it 'should have the correct options' do # Test the keys from one section. doc = IniParse.parse(@fixture) section = doc['Slot010'] section.lines.keys.should == [ 'Driver', 'SteamUser', 'SteamId', 'Vehicle', 'Team', 'QualTime', 'Laps', 'Lap', 'LapDistanceTravelled', 'BestLap', 'RaceTime' ] # Test some of the options. section['Driver'].should == 'Mark Voss' section['SteamUser'].should == 'mvoss' section['SteamId'].should == 1865369 section['Vehicle'].should == 'Chevrolet Lacetti 2007' section['Team'].should == 'TEMPLATE_TEAM' section['QualTime'].should == '1:37.839' section['Laps'].should == 13 section['LapDistanceTravelled'].should == 3857.750244 section['BestLap'].should == '1:38.031' section['RaceTime'].should == '0:21:38.988' section['Lap'].should == [ '(0, -1.000, 1:48.697)', '(1, 89.397, 1:39.455)', '(2, 198.095, 1:38.060)', '(3, 297.550, 1:38.632)', '(4, 395.610, 1:38.031)', '(5, 494.242, 1:39.562)', '(6, 592.273, 1:39.950)', '(7, 691.835, 1:38.366)', '(8, 791.785, 1:39.889)', '(9, 890.151, 1:39.420)', '(10, 990.040, 1:39.401)', '(11, 1089.460, 1:39.506)', '(12, 1188.862, 1:40.017)' ] doc['Header']['Version'].should == '1.1.1.14' doc['Header']['TimeString'].should == '2008/09/13 23:26:32' doc['Header']['Aids'].should == '0,0,0,0,0,1,1,0,0' doc['Race']['AIDB'].should == 'GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW' doc['Race']['Race Length'].should == 0.1 end it 'should be identical to the original when calling #to_ini' do pending('awaiting presevation (or lack) of whitespace around =') do IniParse.parse(@fixture).to_ini.should == @fixture end end end describe 'smb.ini fixture' do before(:all) do @fixture = fixture('smb.ini') end it 'should parse without any errors' do lambda { IniParse.parse(@fixture) }.should_not raise_error end it 'should have the correct sections' do IniParse.parse(@fixture).lines.keys.should == [ 'global', 'printers' ] end it 'should have the correct options' do # Test the keys from one section. doc = IniParse.parse(@fixture) section = doc['global'] section.lines.keys.should == [ 'debug pid', 'log level', 'server string', 'printcap name', 'printing', 'encrypt passwords', 'use spnego', 'passdb backend', 'idmap domains', 'idmap config default: default', 'idmap config default: backend', 'idmap alloc backend', 'idmap negative cache time', 'map to guest', 'guest account', 'unix charset', 'display charset', 'dos charset', 'vfs objects', 'os level', 'domain master', 'max xmit', 'use sendfile', 'stream support', 'ea support', 'darwin_streams:brlm', 'enable core files', 'usershare max shares', 'usershare path', 'usershare owner only', 'usershare allow guests', 'usershare allow full config', 'com.apple:filter shares by access', 'obey pam restrictions', 'acl check permissions', 'name resolve order', 'include' ] section['display charset'].should == 'UTF-8-MAC' section['vfs objects'].should == 'darwinacl,darwin_streams' section['usershare path'].should == '/var/samba/shares' end it 'should be identical to the original when calling #to_ini' do IniParse.parse(@fixture).to_ini.should == @fixture end end describe 'authconfig.ini fixture' do before(:all) do @fixture = fixture('authconfig.ini') end it 'should be identical to the original when calling #to_ini' do IniParse.parse(@fixture).to_ini.should == @fixture end end describe 'option before section fixture' do before(:all) do @fixture = fixture(:option_before_section) end it 'should be identical to the original when calling #to_ini' do IniParse.parse(@fixture).to_ini.should == @fixture end end end iniparse-1.4.2/spec/parser/0000755000175000017500000000000012725022733015773 5ustar terceiroterceiroiniparse-1.4.2/spec/parser/line_parsing_spec.rb0000644000175000017500000002644412725022733022016 0ustar terceiroterceirorequire 'spec_helper' # Tests parsing of individual, out of context, line types using #parse_line. describe 'Parsing a line' do it 'should strip leading whitespace and set the :indent option' do IniParse::Parser.parse_line(' [section]').should \ be_section_tuple(:any, {:indent => ' '}) end it 'should raise an error if the line could not be matched' do lambda { IniParse::Parser.parse_line('invalid line') }.should \ raise_error(IniParse::ParseError) end it 'should parse using the types set in IniParse::Parser.parse_types' do begin # Remove last type. type = IniParse::Parser.parse_types.pop type.should_not_receive(:parse) IniParse::Parser.parse_line('[section]') ensure IniParse::Parser.parse_types << type end end # -- # ========================================================================== # Option lines. # ========================================================================== # ++ describe 'with "k = v"' do before(:all) do @tuple = IniParse::Parser.parse_line('k = v') end it 'should return an option tuple' do @tuple.should be_option_tuple('k', 'v') end it 'should set no indent, comment, offset or separator' do @tuple.last[:indent].should be_nil @tuple.last[:comment].should be_nil @tuple.last[:comment_offset].should be_nil @tuple.last[:comment_sep].should be_nil end end describe 'with "k = a value with spaces"' do it 'should return an option tuple' do IniParse::Parser.parse_line('k = a value with spaces').should \ be_option_tuple('k', 'a value with spaces') end end describe 'with "k = v ; a comment "' do before(:all) do @tuple = IniParse::Parser.parse_line('k = v ; a comment') end it 'should return an option tuple' do @tuple.should be_option_tuple('k', 'v') end it 'should set the comment to "a comment"' do @tuple.should be_option_tuple(:any, :any, :comment => 'a comment') end it 'should set the comment separator to ";"' do @tuple.should be_option_tuple(:any, :any, :comment_sep => ';') end it 'should set the comment offset to 6' do @tuple.should be_option_tuple(:any, :any, :comment_offset => 6) end end describe 'with "k = v;w;x y;z"' do before(:all) do @tuple = IniParse::Parser.parse_line('k = v;w;x y;z') end it 'should return an option tuple with the correct value' do @tuple.should be_option_tuple(:any, 'v;w;x y;z') end it 'should not set a comment' do @tuple.last[:comment].should be_nil @tuple.last[:comment_offset].should be_nil @tuple.last[:comment_sep].should be_nil end end describe 'with "k = v;w ; a comment"' do before(:all) do @tuple = IniParse::Parser.parse_line('k = v;w ; a comment') end it 'should return an option tuple with the correct value' do @tuple.should be_option_tuple(:any, 'v;w') end it 'should set the comment to "a comment"' do @tuple.should be_option_tuple(:any, :any, :comment => 'a comment') end it 'should set the comment separator to ";"' do @tuple.should be_option_tuple(:any, :any, :comment_sep => ';') end it 'should set the comment offset to 8' do @tuple.should be_option_tuple(:any, :any, :comment_offset => 8) end end describe 'with "key=value"' do it 'should return an option tuple with the correct key and value' do IniParse::Parser.parse_line('key=value').should \ be_option_tuple('key', 'value') end end describe 'with "key= value"' do it 'should return an option tuple with the correct key and value' do IniParse::Parser.parse_line('key= value').should \ be_option_tuple('key', 'value') end end describe 'with "key =value"' do it 'should return an option tuple with the correct key and value' do IniParse::Parser.parse_line('key =value').should \ be_option_tuple('key', 'value') end end describe 'with "key = value"' do it 'should return an option tuple with the correct key and value' do IniParse::Parser.parse_line('key = value').should \ be_option_tuple('key', 'value') end end describe 'with "key ="' do it 'should return an option tuple with the correct key' do IniParse::Parser.parse_line('key =').should \ be_option_tuple('key') end it 'should set the option value to nil' do IniParse::Parser.parse_line('key =').should \ be_option_tuple(:any, nil) end end describe 'with "key = EEjDDJJjDJDJD233232=="' do it 'should include the "equals" in the option value' do IniParse::Parser.parse_line('key = EEjDDJJjDJDJD233232==').should \ be_option_tuple('key', 'EEjDDJJjDJDJD233232==') end end describe 'with "key = ==EEjDDJJjDJDJD233232"' do it 'should include the "equals" in the option value' do IniParse::Parser.parse_line('key = ==EEjDDJJjDJDJD233232').should \ be_option_tuple('key', '==EEjDDJJjDJDJD233232') end end describe 'with "key.two = value"' do it 'should return an option tuple with the correct key' do IniParse::Parser.parse_line('key.two = value').should \ be_option_tuple('key.two') end end describe 'with "key/with/slashes = value"' do it 'should return an option tuple with the correct key' do IniParse::Parser.parse_line('key/with/slashes = value').should \ be_option_tuple('key/with/slashes', 'value') end end describe 'with "key_with_underscores = value"' do it 'should return an option tuple with the correct key' do IniParse::Parser.parse_line('key_with_underscores = value').should \ be_option_tuple('key_with_underscores', 'value') end end describe 'with "key-with-dashes = value"' do it 'should return an option tuple with the correct key' do IniParse::Parser.parse_line('key-with-dashes = value').should \ be_option_tuple('key-with-dashes', 'value') end end describe 'with "key with spaces = value"' do it 'should return an option tuple with the correct key' do IniParse::Parser.parse_line('key with spaces = value').should \ be_option_tuple('key with spaces', 'value') end end # -- # ========================================================================== # Section lines. # ========================================================================== # ++ describe 'with "[section]"' do before(:all) do @tuple = IniParse::Parser.parse_line('[section]') end it 'should return a section tuple' do @tuple.should be_section_tuple('section') end it 'should set no indent, comment, offset or separator' do @tuple.last[:indent].should be_nil @tuple.last[:comment].should be_nil @tuple.last[:comment_offset].should be_nil @tuple.last[:comment_sep].should be_nil end end describe 'with "[section with whitespace]"' do it 'should return a section tuple with the correct key' do IniParse::Parser.parse_line('[section with whitespace]').should \ be_section_tuple('section with whitespace') end end describe 'with "[ section with surounding whitespace ]"' do it 'should return a section tuple with the correct key' do IniParse::Parser.parse_line('[ section with surounding whitespace ]').should \ be_section_tuple(' section with surounding whitespace ') end end describe 'with "[section] ; a comment"' do before(:all) do @tuple = IniParse::Parser.parse_line('[section] ; a comment') end it 'should return a section tuple' do @tuple.should be_section_tuple('section') end it 'should set the comment to "a comment"' do @tuple.should be_section_tuple(:any, :comment => 'a comment') end it 'should set the comment separator to ";"' do @tuple.should be_section_tuple(:any, :comment_sep => ';') end it 'should set the comment offset to 10' do @tuple.should be_section_tuple(:any, :comment_offset => 10) end end describe 'with "[section;with#comment;chars]"' do before(:all) do @tuple = IniParse::Parser.parse_line('[section;with#comment;chars]') end it 'should return a section tuple with the correct key' do @tuple.should be_section_tuple('section;with#comment;chars') end it 'should not set a comment' do @tuple.last[:indent].should be_nil @tuple.last[:comment].should be_nil @tuple.last[:comment_offset].should be_nil @tuple.last[:comment_sep].should be_nil end end describe 'with "[section;with#comment;chars] ; a comment"' do before(:all) do @tuple = IniParse::Parser.parse_line('[section;with#comment;chars] ; a comment') end it 'should return a section tuple with the correct key' do @tuple.should be_section_tuple('section;with#comment;chars') end it 'should set the comment to "a comment"' do @tuple.should be_section_tuple(:any, :comment => 'a comment') end it 'should set the comment separator to ";"' do @tuple.should be_section_tuple(:any, :comment_sep => ';') end it 'should set the comment offset to 29' do @tuple.should be_section_tuple(:any, :comment_offset => 29) end end # -- # ========================================================================== # Comment lines. # ========================================================================== # ++ describe 'with "; a comment"' do before(:all) do @tuple = IniParse::Parser.parse_line('; a comment') end it 'should return a comment tuple with the correct comment' do @tuple.should be_comment_tuple('a comment') end it 'should set the comment separator to ";"' do @tuple.should be_comment_tuple(:any, :comment_sep => ';') end it 'should set the comment offset to 0' do @tuple.should be_comment_tuple(:any, :comment_offset => 0) end end describe 'with " ; a comment"' do before(:all) do @tuple = IniParse::Parser.parse_line(' ; a comment') end it 'should return a comment tuple with the correct comment' do @tuple.should be_comment_tuple('a comment') end it 'should set the comment separator to ";"' do @tuple.should be_comment_tuple(:any, :comment_sep => ';') end it 'should set the comment offset to 1' do @tuple.should be_comment_tuple(:any, :comment_offset => 1) end end describe 'with ";"' do before(:all) do @tuple = IniParse::Parser.parse_line(';') end it 'should return a comment tuple with an empty value' do @tuple.should be_comment_tuple('') end it 'should set the comment separator to ";"' do @tuple.should be_comment_tuple(:any, :comment_sep => ';') end it 'should set the comment offset to 0' do @tuple.should be_comment_tuple(:any, :comment_offset => 0) end end # -- # ========================================================================== # Blank lines. # ========================================================================== # ++ describe 'with ""' do it 'should return a blank tuple' do IniParse::Parser.parse_line('').should be_blank_tuple end end describe 'with " "' do it 'should return a blank tuple' do IniParse::Parser.parse_line(' ').should be_blank_tuple end end end iniparse-1.4.2/spec/parser/document_parsing_spec.rb0000644000175000017500000000624312725022733022700 0ustar terceiroterceirorequire 'spec_helper' # Tests parsing of multiple lines, in context, using #parse. describe 'Parsing a document' do describe 'when a comment preceeds a single section and option' do before(:all) do @doc = IniParse::Parser.new(fixture(:comment_before_section)).parse end it 'should have a comment as the first line' do @doc.lines.to_a.first.should be_kind_of(IniParse::Lines::Comment) end it 'should have one section' do @doc.lines.keys.should == ['first_section'] end it 'should have one option belonging to `first_section`' do @doc['first_section']['key'].should == 'value' end end it 'should allow blank lines to preceed the first section' do lambda { @doc = IniParse::Parser.new(fixture(:blank_before_section)).parse }.should_not raise_error @doc.lines.to_a.first.should be_kind_of(IniParse::Lines::Blank) end it 'should allow a blank line to belong to a section' do lambda { @doc = IniParse::Parser.new(fixture(:blank_in_section)).parse }.should_not raise_error @doc['first_section'].lines.to_a.first.should be_kind_of(IniParse::Lines::Blank) end it 'should permit comments on their own line' do lambda { @doc = IniParse::Parser.new(fixture(:comment_line)).parse }.should_not raise_error line = @doc['first_section'].lines.to_a.first line.comment.should eql('; block comment ;') end it 'should permit options before the first section' do doc = IniParse::Parser.new(fixture(:option_before_section)).parse doc.lines.should have_key('__anonymous__') doc['__anonymous__']['foo'].should eql('bar') doc['foo']['another'].should eql('thing') end it 'should raise ParseError if a line could not be parsed' do lambda { IniParse::Parser.new(fixture(:invalid_line)).parse }.should \ raise_error(IniParse::ParseError) end describe 'when a section name contains "="' do before(:all) do @doc = IniParse::Parser.new(fixture(:section_with_equals)).parse end it 'should have two sections' do @doc.lines.to_a.length.should == 2 end it 'should have one section' do @doc.lines.keys.should == ['first_section = name', 'another_section = a name'] end it 'should have one option belonging to `first_section = name`' do @doc['first_section = name']['key'].should == 'value' end it 'should have one option belonging to `another_section = a name`' do @doc['another_section = a name']['another'].should == 'thing' end end describe 'when a document contains a section multiple times' do before(:all) do @doc = IniParse::Parser.new(fixture(:duplicate_section)).parse end it 'should only add the section once' do # "first_section" and "second_section". @doc.lines.to_a.length.should == 2 end it 'should retain values from the first time' do @doc['first_section']['key'].should == 'value' end it 'should add new keys' do @doc['first_section']['third'].should == 'fourth' end it 'should merge in duplicate keys' do @doc['first_section']['another'].should == %w( thing again ) end end end iniparse-1.4.2/.gitignore0000644000175000017500000000010512725022733015531 0ustar terceiroterceiro.DS_Store coverage/* doc/* pkg/* *.rbc *.swp *.gem rdoc Gemfile.lock iniparse-1.4.2/Gemfile0000644000175000017500000000004612725022733015040 0ustar terceiroterceirosource 'https://rubygems.org' gemspec