pax_global_header 0000666 0000000 0000000 00000000064 13625747173 0014531 g ustar 00root root 0000000 0000000 52 comment=088afb7601ffb062753114e5ef6084fd323cfc67
antw-iniparse-088afb7/ 0000775 0000000 0000000 00000000000 13625747173 0014733 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/.bundle/ 0000775 0000000 0000000 00000000000 13625747173 0016262 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/.bundle/config 0000664 0000000 0000000 00000000033 13625747173 0017446 0 ustar 00root root 0000000 0000000 ---
BUNDLE_WITHOUT: extras
antw-iniparse-088afb7/.gitignore 0000664 0000000 0000000 00000000105 13625747173 0016717 0 ustar 00root root 0000000 0000000 .DS_Store
coverage/*
doc/*
pkg/*
*.rbc
*.swp
*.gem
rdoc
Gemfile.lock
antw-iniparse-088afb7/.rspec 0000664 0000000 0000000 00000000010 13625747173 0016037 0 ustar 00root root 0000000 0000000 --color
antw-iniparse-088afb7/.travis.yml 0000664 0000000 0000000 00000000300 13625747173 0017035 0 ustar 00root root 0000000 0000000 language: ruby
script: "bundle exec rspec"
bundler_args: "--without extras"
before_install:
- gem update --system
- gem update bundler
- gem cleanup bundler
rvm:
- 2.4
- 2.3
- 2.2
antw-iniparse-088afb7/CHANGELOG.md 0000664 0000000 0000000 00000001752 13625747173 0016551 0 ustar 00root root 0000000 0000000 ### 1.5.0
* OptionCollection no longer yields duplicate keys as an array, but instead yields each key in turn.
For example, given an INI file:
[test]
a = 1
a = 2
b = 3
IniParse would previously yield a single "a" key: an array containing two `Line`s:
doc['test'].map { |line| line }
# => [[, ], ]
Instead, each key/value pair will be yielded in turn:
doc['test'].map { |line| line }
# => [, , ]
Directly accessing values via `[]` will still return an array of values as before:
doc['test']['a']
# => [1, 2]
* LineCollection#each may be called without a block, returning an Enumerator.
doc = IniParse.parse(<<~EOF)
[test]
a = x
b = y
EOF
doc[test].each
# => #
This allows for chaining as in the standard library:
doc['test'].map.with_index { |a, i| { index: i, value: a.value } }
# => [{ index: 0, value: 'x' }, { index: 1, value: 'y' }]
antw-iniparse-088afb7/Gemfile 0000664 0000000 0000000 00000000046 13625747173 0016226 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gemspec
antw-iniparse-088afb7/LICENSE 0000664 0000000 0000000 00000002050 13625747173 0015735 0 ustar 00root root 0000000 0000000 Copyright (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. antw-iniparse-088afb7/README.rdoc 0000664 0000000 0000000 00000005341 13625747173 0016544 0 ustar 00root root 0000000 0000000 = IniParse {
}[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.
antw-iniparse-088afb7/Rakefile 0000664 0000000 0000000 00000006300 13625747173 0016377 0 ustar 00root root 0000000 0000000 require '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 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)
# 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
antw-iniparse-088afb7/TODO 0000664 0000000 0000000 00000000124 13625747173 0015420 0 ustar 00root root 0000000 0000000 * Support multi-line options with backslashes (presumably with
OptionCollection).
antw-iniparse-088afb7/iniparse.gemspec 0000664 0000000 0000000 00000003213 13625747173 0020111 0 ustar 00root root 0000000 0000000 # 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.5.0'
s.date = '2020-02-27'
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', '~> 3.4')
# = MANIFEST =
s.files = %w[
CHANGELOG.md
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
antw-iniparse-088afb7/lib/ 0000775 0000000 0000000 00000000000 13625747173 0015501 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/lib/iniparse.rb 0000664 0000000 0000000 00000003061 13625747173 0017640 0 ustar 00root root 0000000 0000000 dir = 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.5.0'.freeze
# 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
antw-iniparse-088afb7/lib/iniparse/ 0000775 0000000 0000000 00000000000 13625747173 0017313 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/lib/iniparse/document.rb 0000664 0000000 0000000 00000005706 13625747173 0021466 0 ustar 00root root 0000000 0000000 module 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
antw-iniparse-088afb7/lib/iniparse/generator.rb 0000664 0000000 0000000 00000013425 13625747173 0021633 0 ustar 00root root 0000000 0000000 module 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
antw-iniparse-088afb7/lib/iniparse/line_collection.rb 0000664 0000000 0000000 00000012170 13625747173 0023003 0 ustar 00root root 0000000 0000000 module 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)
return enum_for(:each, include_blank) unless block_given?
@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) || (has_key?('__anonymous__') && (line.blank? || line.kind_of?(IniParse::Lines::Comment)))
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
def each(*args)
return enum_for(:each, *args) unless block_given?
super(*args) do |value|
if value.is_a?(Array)
value.each { |item| yield(item) }
else
yield value
end
end
end
# Return an array containing the keys for the lines added to this
# collection.
def keys
map(&:key).uniq
end
end
end
antw-iniparse-088afb7/lib/iniparse/lines.rb 0000664 0000000 0000000 00000023044 13625747173 0020755 0 ustar 00root root 0000000 0000000 module 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, '')
@option_sep = opts.fetch(:option_sep, nil)
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,
option_sep: @option_sep
}
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, not greedy
(\s*=\s*) # Separator, greedy
(.*?)$ # 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
@option_sep = opts.fetch(:option_sep, ' = ')
end
def self.parse(line, opts)
if m = @regex.match(line)
opts[:option_sep] = m[2]
[:option, m[1].strip, typecast(m[3].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}#{@option_sep}#{v}" }
else
"#{key}#{@option_sep}#{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
antw-iniparse-088afb7/lib/iniparse/parser.rb 0000664 0000000 0000000 00000005600 13625747173 0021135 0 ustar 00root root 0000000 0000000 module 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.inspect}."
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 = line.chomp
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
antw-iniparse-088afb7/spec/ 0000775 0000000 0000000 00000000000 13625747173 0015665 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/spec/document_spec.rb 0000664 0000000 0000000 00000010673 13625747173 0021051 0 ustar 00root root 0000000 0000000 require 'spec_helper'
describe "IniParse::Document" do
it 'should have a +lines+ reader' do
methods = IniParse::Document.instance_methods.map { |m| m.to_sym }
expect(methods).to include(:lines)
end
it 'should not have a +lines+ writer' do
methods = IniParse::Document.instance_methods.map { |m| m.to_sym }
expect(methods).not_to include(:lines=)
end
it 'should delegate #[] to +lines+' do
doc = IniParse::Document.new
expect(doc.lines).to receive(:[]).with('key')
doc['key']
end
it 'should call #each to +lines+' do
doc = IniParse::Document.new
expect(doc.lines).to receive(:each)
doc.each { |l| }
end
it 'should be enumerable' do
expect(IniParse::Document.included_modules).to 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]
expect(doc.map { |line| line }).to eq(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
expect(@doc).to have_section('first section')
expect(@doc).to have_section('another section')
end
it 'should return true if no section with the given key exists' do
expect(@doc).not_to 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
expect { document.delete('first') }.
to change { document['first'] }.to(nil)
end
it 'removes the section given a Section' do
expect { document.delete(document['first']) }.
to change { document['first'] }.to(nil)
end
it 'removes the lines' do
expect { document.delete('first') }.
to change { document.to_ini.match(/alpha/) }.to(nil)
end
it 'returns the document' do
expect(document.delete('first')).to 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')
expect(File).to 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
expect { IniParse::Document.new.save }.to \
raise_error(IniParse::IniParseError)
end
end
describe 'when a path is given to save' do
it "should update the document's +path+" do
allow(File).to receive(:open).and_return(true)
doc = IniParse::Document.new('/a/path/to/a/file.ini')
doc.save('/a/new/path.ini')
expect(doc.path).to eq('/a/new/path.ini')
end
it 'should save the INI document to the given path' do
expect(File).to 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
expect { IniParse::Document.new.save }.to \
raise_error(IniParse::IniParseError)
end
end
end
end
antw-iniparse-088afb7/spec/fixture_spec.rb 0000664 0000000 0000000 00000017345 13625747173 0020724 0 ustar 00root root 0000000 0000000 require '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
expect { IniParse.parse(@fixture) }.not_to raise_error
end
it 'should have the correct sections' do
expect(IniParse.parse(fixture('openttd.ini')).lines.keys).to eq([
'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']
expect(section.lines.keys).to eq([
'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.
expect(section['display_opt']).to eq('SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|FULL_DETAIL|WAYPOINTS')
expect(section['news_ticker_sound']).to be_falsey
expect(section['language']).to eq('english_US.lng')
expect(section['resolution']).to eq('1680,936')
expect(section['large_size']).to eq(16)
# Test some other options.
expect(doc['currency']['suffix']).to eq('" credits"')
expect(doc['news_display']['production_nobody']).to eq('summarized')
expect(doc['version']['version_number']).to eq('070039B0')
expect(doc['preset-J']['gcf/1_other/BlackCC/mauvetoblackw.grf']).to be_nil
expect(doc['preset-J']['gcf/1_other/OpenGFX/OpenGFX_-_newFaces_v0.1.grf']).to be_nil
end
it 'should be identical to the original when calling #to_ini' do
expect(IniParse.parse(@fixture).to_ini).to eq(@fixture)
end
end
describe 'race07.ini fixture' do
before(:all) do
@fixture = fixture('race07.ini')
end
it 'should parse without any errors' do
expect { IniParse.parse(@fixture) }.not_to raise_error
end
it 'should have the correct sections' do
expect(IniParse.parse(fixture('race07.ini')).lines.keys).to eq([
'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']
expect(section.lines.keys).to eq([
'Driver', 'SteamUser', 'SteamId', 'Vehicle', 'Team', 'QualTime',
'Laps', 'Lap', 'LapDistanceTravelled', 'BestLap', 'RaceTime'
])
# Test some of the options.
expect(section['Driver']).to eq('Mark Voss')
expect(section['SteamUser']).to eq('mvoss')
expect(section['SteamId']).to eq(1865369)
expect(section['Vehicle']).to eq('Chevrolet Lacetti 2007')
expect(section['Team']).to eq('TEMPLATE_TEAM')
expect(section['QualTime']).to eq('1:37.839')
expect(section['Laps']).to eq(13)
expect(section['LapDistanceTravelled']).to eq(3857.750244)
expect(section['BestLap']).to eq('1:38.031')
expect(section['RaceTime']).to eq('0:21:38.988')
expect(section['Lap']).to eq([
'(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)'
])
expect(doc['Header']['Version']).to eq('1.1.1.14')
expect(doc['Header']['TimeString']).to eq('2008/09/13 23:26:32')
expect(doc['Header']['Aids']).to eq('0,0,0,0,0,1,1,0,0')
expect(doc['Race']['AIDB']).to eq('GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW')
expect(doc['Race']['Race Length']).to eq(0.1)
end
it 'should be identical to the original when calling #to_ini' do
pending('awaiting presevation (or lack) of whitespace around =')
expect(IniParse.parse(@fixture).to_ini).to eq(@fixture)
end
end
describe 'smb.ini fixture' do
before(:all) do
@fixture = fixture('smb.ini')
end
it 'should parse without any errors' do
expect { IniParse.parse(@fixture) }.not_to raise_error
end
it 'should have the correct sections' do
expect(IniParse.parse(@fixture).lines.keys).to eq([
'global', 'printers'
])
end
it 'should have the correct options' do
# Test the keys from one section.
doc = IniParse.parse(@fixture)
section = doc['global']
expect(section.lines.keys).to eq([
'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'
])
expect(section['display charset']).to eq('UTF-8-MAC')
expect(section['vfs objects']).to eq('darwinacl,darwin_streams')
expect(section['usershare path']).to eq('/var/samba/shares')
end
it 'should be identical to the original when calling #to_ini' do
expect(IniParse.parse(@fixture).to_ini).to eq(@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
expect(IniParse.parse(@fixture).to_ini).to eq(@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
expect(IniParse.parse(@fixture).to_ini).to eq(@fixture)
end
end
describe 'DOS line endings' do
before(:all) do
@fixture = fixture(:dos_endings)
end
it 'should have the correct sections' do
expect(IniParse.parse(@fixture).lines.keys).to eq(%w[database])
end
it 'should have the correct options' do
# Test the keys from one section.
doc = IniParse.parse(@fixture)
section = doc['database']
expect(section.lines.keys).to eq(%w[first second])
expect(section['first']).to eq(true)
expect(section['second']).to eq(false)
end
pending 'should be identical to the original when calling #to_ini' do
expect(IniParse.parse(@fixture).to_ini).to eq(@fixture)
end
end
describe 'anonymous-order.ini fixture' do
# https://github.com/antw/iniparse/issues/17
let(:raw) { fixture(:anon_section_with_comments) }
it 'should be identical to the original when calling #to_ini' do
expect(IniParse.parse(raw).to_ini).to eq(raw)
end
end
end
antw-iniparse-088afb7/spec/fixtures/ 0000775 0000000 0000000 00000000000 13625747173 0017536 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/spec/fixtures/authconfig.ini 0000664 0000000 0000000 00000000601 13625747173 0022363 0 ustar 00root root 0000000 0000000 [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--
antw-iniparse-088afb7/spec/fixtures/openttd.ini 0000664 0000000 0000000 00000024762 13625747173 0021727 0 ustar 00root root 0000000 0000000
[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]
antw-iniparse-088afb7/spec/fixtures/race07.ini 0000664 0000000 0000000 00000005442 13625747173 0021325 0 ustar 00root root 0000000 0000000 ; 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]
antw-iniparse-088afb7/spec/fixtures/smb.ini 0000664 0000000 0000000 00000006046 13625747173 0021026 0 ustar 00root root 0000000 0000000 ; 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.
antw-iniparse-088afb7/spec/generator/ 0000775 0000000 0000000 00000000000 13625747173 0017653 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/spec/generator/method_missing_spec.rb 0000664 0000000 0000000 00000006154 13625747173 0024231 0 ustar 00root root 0000000 0000000 require '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|
expect(section).to respond_to(meth)
end
end
end
end
it 'should add a Section to the document' do
expect(IniParse::Generator.gen do |doc|
doc.a_section { |section| }
end).to 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|
expect(section.context).to be_kind_of(IniParse::Lines::Section)
expect(section.context.key).to eq("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| }
expect(doc.context).to be_kind_of(IniParse::Document)
end
end
it 'should append a blank line to the document, after the section' do
expect(IniParse::Generator.gen do |doc|
doc.a_section { |section| }
end.lines.to_a.last).to be_kind_of(IniParse::Lines::Blank)
end
it 'should raise a LineNotAllowed if you attempt to nest a section' do
expect do
IniParse::Generator.gen do |doc|
doc.a_section do |section_one|
section_one.another_section { |section_two| }
end
end
end.to 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" }
expect(doc['__anonymous__']['my_option']).to 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"]
expect(section).to have_option("my_option")
expect(section["my_option"]).to eq("a value")
end
end
end
# Comments and blanks are added in the same way as in the
# 'with_section_block_spec.rb' specification.
end
antw-iniparse-088afb7/spec/generator/with_section_blocks_spec.rb 0000664 0000000 0000000 00000024472 13625747173 0025257 0 ustar 00root root 0000000 0000000 require '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
expect { IniParse::Generator.gen { |doc| } }.not_to raise_error
end
it 'should raise LocalJumpError if no block is given' do
expect { IniParse::Generator.gen }.to 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|
expect(doc).to 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|
expect(section).to respond_to(meth)
end
end
end
end
it 'should add a Section to the document' do
expect(IniParse::Generator.gen do |doc|
doc.section("a section") { |section| }
end).to 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|
expect(section.context).to be_kind_of(IniParse::Lines::Section)
expect(section.context.key).to eq("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| }
expect(doc.context).to 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
expect(document["a section"].to_ini).to 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
expect(document["a section"].to_ini).to match(/\A /)
end
it 'should append a blank line to the document, after the section' do
expect(IniParse::Generator.gen do |doc|
doc.section("a section") { |section| }
end.lines.to_a.last).to be_kind_of(IniParse::Lines::Blank)
end
it 'should raise a LineNotAllowed if you attempt to nest a section' do
expect do
IniParse::Generator.gen do |doc|
doc.section("a section") do |section_one|
section_one.section("another_section") { |section_two| }
end
end
end.to 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
expect(document['__anonymous__']['my option']).to 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"]
expect(section).to have_option("my option")
expect(section["my option"]).to eq("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
expect(document["a section"].option("my option").to_ini).to 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
expect(document["a section"].option("my option").to_ini).to 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
expect(document["a section"].option("my option").to_ini).to 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
expect(option_ini).to match(/^ /)
expect(option_ini).to 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
expect(document["a section"].option("my option").to_ini).not_to 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
expect(document.lines.to_a.first.to_ini).to match(/\A /)
end
it 'should ignore any extra :comment option' do
document = IniParse::Generator.gen do |doc|
doc.comment("My comment", :comment => 'Ignored')
end
expect(document.lines.to_a.first.to_ini).to match(/My comment/)
expect(document.lines.to_a.first.to_ini).not_to 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
expect(comment).to be_kind_of(IniParse::Lines::Comment)
expect(comment.to_ini).to 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).
expect(comment_ini).to eq('; 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
expect(comment).to be_kind_of(IniParse::Lines::Comment)
expect(comment.to_ini).to 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
expect(document['a section'].lines.to_a.first.to_ini).to 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
expect(document['a section'].lines.to_a.first.to_ini).to 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)
expect(document['a section'].lines.to_a.first.to_ini).to \
eq(' # 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
expect(comment_ini).to match(/My comment/)
expect(comment_ini).not_to 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
expect(document.lines.to_a.first).to 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
expect(document['a section'].lines.to_a.first).to be_kind_of(IniParse::Lines::Blank)
end
end
end
antw-iniparse-088afb7/spec/generator/without_section_blocks_spec.rb 0000664 0000000 0000000 00000010467 13625747173 0026006 0 ustar 00root root 0000000 0000000 require '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")
expect(@gen.document).to have_section("a section")
end
it 'should change the Generator context to the section' do
@gen.section("a section")
expect(@gen.context).to eq(@gen.document['a section'])
end
it 'should pass extra options to the Section instance' do
@gen.section("a section", :indent => ' ')
expect(@gen.document["a section"].to_ini).to 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 => ' ')
expect(@gen.document["a section"].option("my option").to_ini).to match(/^ /)
end
describe 'when the context is a Document' do
it "should add the option to an __anonymous__ section" do
@gen.option("key", "value")
expect(@gen.document['__anonymous__']['key']).to 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")
expect(@gen.document["a section"]).to have_option("my option")
expect(@gen.document["a section"]["my option"]).to eq("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 => ' ')
expect(@gen.document.lines.to_a.first.to_ini).to 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
expect(comment_ini).to match(/My comment/)
expect(comment_ini).not_to 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
expect(comment).to be_kind_of(IniParse::Lines::Comment)
expect(comment.to_ini).to 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
expect(comment).to be_kind_of(IniParse::Lines::Comment)
expect(comment.to_ini).to 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
expect(comment).to 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
expect(comment).to be_kind_of(IniParse::Lines::Blank)
end
end
end
antw-iniparse-088afb7/spec/iniparse_spec.rb 0000664 0000000 0000000 00000002715 13625747173 0021043 0 ustar 00root root 0000000 0000000 require '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) { allow(File).to receive(:read).and_return('[section]') }
it 'should return an IniParse::Document' do
expect(IniParse.open('/my/path.ini')).to be_kind_of(IniParse::Document)
end
it 'should set the path on the returned Document' do
expect(IniParse.open('/my/path.ini').path).to eq('/my/path.ini')
end
it 'should read the file at the given path' do
expect(File).to receive(:read).with('/my/path.ini').and_return('[section]')
IniParse.open('/my/path.ini')
end
end
end
antw-iniparse-088afb7/spec/line_collection_spec.rb 0000664 0000000 0000000 00000015200 13625747173 0022364 0 ustar 00root root 0000000 0000000 require 'spec_helper'
# ----------------------------------------------------------------------------
# Shared specs for all Collection types...
# ----------------------------------------------------------------------------
shared_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| expect(l).to 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
expect(arr).to eq([@c1, @i1, @i2, @b1, @i3, @b2])
end
end
describe '#[]' do
it 'should fetch the correct value' do
expect(@collection['first']).to eq(@i1)
expect(@collection['second']).to eq(@i2)
expect(@collection['third']).to eq(@i3)
end
it 'should return nil if the given key does not exist' do
expect(@collection['does not exist']).to be_nil
end
end
describe '#[]=' do
it 'should successfully add a new key' do
@collection['fourth'] = @new
expect(@collection['fourth']).to eq(@new)
end
it 'should successfully update an existing key' do
@collection['second'] = @new
expect(@collection['second']).to eq(@new)
# Make sure the old data is gone.
expect(@collection.detect { |s| s.key == 'second' }).to be_nil
end
it 'should typecast given keys to a string' do
@collection[:a_symbol] = @new
expect(@collection['a_symbol']).to eq(@new)
end
end
describe '#<<' do
it 'should set the key correctly if given a new item' do
expect(@collection).not_to have_key(@new.key)
@collection << @new
expect(@collection).to have_key(@new.key)
end
it 'should append Blank lines' do
@collection << IniParse::Lines::Blank.new
expect(@collection.instance_variable_get(:@lines).last).to \
be_kind_of(IniParse::Lines::Blank)
end
it 'should append Comment lines' do
@collection << IniParse::Lines::Comment.new
expect(@collection.instance_variable_get(:@lines).last).to \
be_kind_of(IniParse::Lines::Comment)
end
it 'should return self' do
expect(@collection << @new).to eq(@collection)
end
end
describe '#delete' do
it 'should remove the given value and adjust the indicies' do
expect(@collection['second']).not_to be_nil
@collection.delete('second')
expect(@collection['second']).to be_nil
expect(@collection['first']).to eq(@i1)
expect(@collection['third']).to eq(@i3)
end
it "should do nothing if the supplied key does not exist" do
@collection.delete('does not exist')
expect(@collection['first']).to eq(@i1)
expect(@collection['third']).to eq(@i3)
end
end
describe '#to_a' do
it 'should return an array' do
expect(@collection.to_a).to be_kind_of(Array)
end
it 'should include all lines' do
expect(@collection.to_a).to eq([@c1, @i1, @i2, @b1, @i3, @b2])
end
it 'should include references to the same line objects as the collection' do
@collection << @new
expect(@collection.to_a.last.object_id).to eq(@new.object_id)
end
end
describe '#to_hash' do
it 'should return a hash' do
expect(@collection.to_hash).to be_kind_of(Hash)
end
it 'should have the correct keys' do
hash = @collection.to_hash
expect(hash.keys.length).to eq(3)
expect(hash).to have_key('first')
expect(hash).to have_key('second')
expect(hash).to have_key('third')
end
it 'should have the correct values' do
hash = @collection.to_hash
expect(hash['first']).to eq(@i1)
expect(hash['second']).to eq(@i2)
expect(hash['third']).to eq(@i3)
end
end
describe '#keys' do
it 'should return an array of strings' do
expect(@collection.keys).to eq(['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
expect { @collection << IniParse::Lines::Section.new('s') }.to \
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
expect(@collection['k']).to eq([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')
expect(@collection.keys).to eq(['first', 'second', 'third'])
end
end
context 'with duplicate lines' do
let(:collection) { IniParse::OptionCollection.new }
let(:opt_1) { IniParse::Lines::Option.new('my_key', 'value_1') }
let(:opt_2) { IniParse::Lines::Option.new('my_key', 'value_2') }
before do
collection << opt_1
collection << opt_2
end
it 'yields each item in turn' do
expect { |b| collection.each(&b) }.to yield_successive_args(opt_1, opt_2)
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
expect(@i1).to receive(:merge!).with(new_section).once
@collection << new_section
end
end
end
antw-iniparse-088afb7/spec/lines_spec.rb 0000664 0000000 0000000 00000034137 13625747173 0020346 0 ustar 00root root 0000000 0000000 require '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
expect(IniParse::Test::FakeLine.new.to_ini).to eq('fake line')
end
it 'should preserve line indents' do
expect(IniParse::Test::FakeLine.new(
:indent => ' '
).to_ini).to eq(' fake line')
end
describe 'when a comment is set' do
it 'should correctly include the comment' do
expect(IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => ';', :comment_offset => 10
).to_ini).to eq('fake line ; comment')
end
it 'should correctly indent the comment' do
expect(IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => ';', :comment_offset => 15
).to_ini).to eq('fake line ; comment')
end
it 'should use ";" as a default comment seperator' do
expect(IniParse::Test::FakeLine.new(
:comment => 'comment'
).to_ini).to eq('fake line ; comment')
end
it 'should use the correct seperator' do
expect(IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => '#'
).to_ini).to eq('fake line # comment')
end
it 'should use the ensure a space is added before the comment seperator' do
expect(IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => ';', :comment_offset => 0
).to_ini).to eq('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
)
allow(line).to receive(:line_contents).and_return('')
expect(line.to_ini).to eq('; comment')
end
end
describe 'when no comment is set' do
it 'should not add trailing space if :comment_offset has a value' do
expect(IniParse::Test::FakeLine.new(:comment_offset => 10).to_ini).to eq('fake line')
end
it 'should not add a comment seperator :comment_sep has a value' do
expect(IniParse::Test::FakeLine.new(:comment_sep => ';').to_ini).to eq('fake line')
end
end
end
describe '#has_comment?' do
it 'should return true if :comment has a non-blank value' do
expect(IniParse::Test::FakeLine.new(:comment => 'comment')).to have_comment
end
it 'should return true if :comment has a blank value' do
expect(IniParse::Test::FakeLine.new(:comment => '')).to have_comment
end
it 'should return false if :comment has a nil value' do
expect(IniParse::Test::FakeLine.new).not_to have_comment
expect(IniParse::Test::FakeLine.new(:comment => nil)).not_to 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
expect(@section).to respond_to(:lines)
end
it 'should not respond_to +lines=+' do
expect(@section).not_to respond_to(:lines=)
end
it 'should include Enumerable' do
expect(IniParse::Lines::Section.included_modules).to include(Enumerable)
end
describe '#initialize' do
it 'should typecast the given key to a string' do
expect(IniParse::Lines::Section.new(:symbol).key).to eq('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
expect(@section.option('k')).to eq(option)
end
it 'should return nil if the given key does not exist' do
expect(@section.option('does_not_exist')).to be_nil
end
end
describe '#each' do
it 'should call #each on +lines+' do
expect(@section.lines).to receive(:each)
@section.each { |l| }
end
end
describe '#[]' do
it 'should return nil if the given key does not exist' do
expect(@section['k']).to be_nil
end
it 'should return a value if the given key exists' do
@section.lines << IniParse::Lines::Option.new('k', 'v')
expect(@section['k']).to eq('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')
expect(@section['k']).to eq(['v1', 'v2', 'v3'])
end
it 'should typecast the key to a string' do
@section.lines << IniParse::Lines::Option.new('k', 'v')
expect(@section[:k]).to eq('v')
end
end
describe '#[]=' do
it 'should add a new Option with the given key and value' do
@section['k'] = 'a value'
expect(@section.option('k')).to be_kind_of(IniParse::Lines::Option)
expect(@section['k']).to eq('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'
expect(@section['k']).to eq('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'
expect(@section.option('k')).to be_kind_of(IniParse::Lines::Option)
expect(@section['k']).to eq('new value')
end
it 'should typecast the key to a string' do
@section[:k] = 'a value'
expect(@section['k']).to eq('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)
expect(@section['a']).to eq('val1')
expect(@section['b']).to eq('val2')
expect(@section['c']).to eq('val3')
expect(@section['d']).to eq('val4')
end
it 'should handle duplicates' do
@new_section.lines << IniParse::Lines::Option.new('a', 'val2')
@section.merge!(@new_section)
expect(@section['a']).to eq(['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)
expect(@section['a']).to eq(['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 }
expect(line).to 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 }
expect(line).to 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
expect { @section.delete('a') }.
to change { @section['a'] }.to(nil)
end
it 'removes the option given an Option' do
expect { @section.delete(opt_one) }.
to change { @section['a'] }.to(nil)
end
it 'should not remove non-matching lines' do
expect { @section.delete('a') }.not_to change { @section['c'] }
end
it 'returns the section' do
expect(@section.delete('a')).to eql(@section)
end
end
describe '#to_ini' do
it 'should include the section key' do
expect(IniParse::Lines::Section.new('a section').to_ini).to eq('[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')
expect(@section.to_ini).to eq(
"[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')
expect(@section.to_ini).to eq(
"[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
expect(@section).to have_option('first')
end
it 'should return true if no option with the given key exists' do
expect(@section).not_to 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
expect(IniParse::Lines::Option.new(:symbol, '').key).to eq('symbol')
end
end
describe '#to_ini' do
it 'should include the key and value' do
expect(IniParse::Lines::Option.new('key', 'value').to_ini).to eq('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
expect(parse('key =')).to be_option_tuple('key', nil)
expect(parse('key = ')).to be_option_tuple('key', nil)
expect(parse('key = ')).to be_option_tuple('key', nil)
end
it 'should not typecast "true" if true is part of a word' do
expect(parse('key = TestTrueTest')).to be_option_tuple('key', 'TestTrueTest')
expect(parse('key = TrueTest')).to be_option_tuple('key', 'TrueTest')
expect(parse('key = TestTrue')).to be_option_tuple('key', 'TestTrue')
end
it 'should not typecast "false" if false is part of a word' do
expect(parse('key = TestFalseTest')).to be_option_tuple('key', 'TestFalseTest')
expect(parse('key = FalseTest')).to be_option_tuple('key', 'FalseTest')
expect(parse('key = TestFalse')).to be_option_tuple('key', 'TestFalse')
end
it 'should typecast "true" to TrueClass' do
expect(parse('key = true')).to be_option_tuple('key', true)
expect(parse('key = TRUE')).to be_option_tuple('key', true)
end
it 'should typecast "false" to FalseClass' do
expect(parse('key = false')).to be_option_tuple('key', false)
expect(parse('key = FALSE')).to be_option_tuple('key', false)
end
it 'should typecast integer values to Integer' do
expect(parse('key = 1')).to be_option_tuple('key', 1)
expect(parse('key = 10')).to be_option_tuple('key', 10)
end
it 'should not typecast integers with a leading 0 to Integer' do
expect(parse('key = 0700')).to be_option_tuple('key', '0700')
end
it 'should typecast negative integer values to Integer' do
expect(parse('key = -1')).to be_option_tuple('key', -1)
end
it 'should typecast float values to Float' do
expect(parse('key = 3.14159265')).to be_option_tuple('key', 3.14159265)
end
it 'should typecast negative float values to Float' do
expect(parse('key = -3.14159265')).to be_option_tuple('key', -3.14159265)
end
it 'should typecast scientific notation numbers to Float' do
expect(parse('key = 10e5')).to be_option_tuple('key', 10e5)
expect(parse('key = 10e+5')).to be_option_tuple('key', 10e5)
expect(parse('key = 10e-5')).to be_option_tuple('key', 10e-5)
expect(parse('key = -10e5')).to be_option_tuple('key', -10e5)
expect(parse('key = -10e+5')).to be_option_tuple('key', -10e5)
expect(parse('key = -10e-5')).to be_option_tuple('key', -10e-5)
expect(parse('key = 3.14159265e5')).to be_option_tuple('key', 3.14159265e5)
expect(parse('key = 3.14159265e+5')).to be_option_tuple('key', 3.14159265e5)
expect(parse('key = 3.14159265e-5')).to be_option_tuple('key', 3.14159265e-5)
expect(parse('key = -3.14159265e5')).to be_option_tuple('key', -3.14159265e5)
expect(parse('key = -3.14159265e+5')).to be_option_tuple('key', -3.14159265e5)
expect(parse('key = -3.14159265e-5')).to 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
expect(IniParse::Lines::Comment.new(:comment => 'comment')).to have_comment
end
it 'should return true if :comment has a blank value' do
expect(IniParse::Lines::Comment.new(:comment => '')).to have_comment
end
it 'should return true if :comment has a nil value' do
expect(IniParse::Lines::Comment.new).to have_comment
expect(IniParse::Lines::Comment.new(:comment => nil)).to have_comment
end
end
describe '#to_ini' do
it 'should return the comment' do
expect(IniParse::Lines::Comment.new(
:comment => 'a comment'
).to_ini).to eq('; a comment')
end
it 'should preserve comment offset' do
expect(IniParse::Lines::Comment.new(
:comment => 'a comment', :comment_offset => 10
).to_ini).to eq(' ; a comment')
end
it 'should return just the comment_sep if the comment is blank' do
expect(IniParse::Lines::Comment.new.to_ini).to eq(';')
end
end
end
antw-iniparse-088afb7/spec/parser/ 0000775 0000000 0000000 00000000000 13625747173 0017161 5 ustar 00root root 0000000 0000000 antw-iniparse-088afb7/spec/parser/document_parsing_spec.rb 0000664 0000000 0000000 00000006341 13625747173 0024065 0 ustar 00root root 0000000 0000000 require '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
expect(@doc.lines.to_a.first).to be_kind_of(IniParse::Lines::Comment)
end
it 'should have one section' do
expect(@doc.lines.keys).to eq(['first_section'])
end
it 'should have one option belonging to `first_section`' do
expect(@doc['first_section']['key']).to eq('value')
end
end
it 'should allow blank lines to preceed the first section' do
expect {
@doc = IniParse::Parser.new(fixture(:blank_before_section)).parse
}.not_to raise_error
expect(@doc.lines.to_a.first).to be_kind_of(IniParse::Lines::Blank)
end
it 'should allow a blank line to belong to a section' do
expect {
@doc = IniParse::Parser.new(fixture(:blank_in_section)).parse
}.not_to raise_error
expect(@doc['first_section'].lines.to_a.first).to be_kind_of(IniParse::Lines::Blank)
end
it 'should permit comments on their own line' do
expect {
@doc = IniParse::Parser.new(fixture(:comment_line)).parse
}.not_to raise_error
line = @doc['first_section'].lines.to_a.first
expect(line.comment).to eql('; block comment ;')
end
it 'should permit options before the first section' do
doc = IniParse::Parser.new(fixture(:option_before_section)).parse
expect(doc.lines).to have_key('__anonymous__')
expect(doc['__anonymous__']['foo']).to eql('bar')
expect(doc['foo']['another']).to eql('thing')
end
it 'should raise ParseError if a line could not be parsed' do
expect { IniParse::Parser.new(fixture(:invalid_line)).parse }.to \
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
expect(@doc.lines.to_a.length).to eq(2)
end
it 'should have one section' do
expect(@doc.lines.keys).to eq(['first_section = name',
'another_section = a name'])
end
it 'should have one option belonging to `first_section = name`' do
expect(@doc['first_section = name']['key']).to eq('value')
end
it 'should have one option belonging to `another_section = a name`' do
expect(@doc['another_section = a name']['another']).to eq('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".
expect(@doc.lines.to_a.length).to eq(2)
end
it 'should retain values from the first time' do
expect(@doc['first_section']['key']).to eq('value')
end
it 'should add new keys' do
expect(@doc['first_section']['third']).to eq('fourth')
end
it 'should merge in duplicate keys' do
expect(@doc['first_section']['another']).to eq(%w( thing again ))
end
end
end
antw-iniparse-088afb7/spec/parser/line_parsing_spec.rb 0000664 0000000 0000000 00000027040 13625747173 0023175 0 ustar 00root root 0000000 0000000 require '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
expect(IniParse::Parser.parse_line(' [section]')).to \
be_section_tuple(:any, {:indent => ' '})
end
it 'should raise an error if the line could not be matched' do
expect { IniParse::Parser.parse_line('invalid line') }.to \
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
expect(type).not_to 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
expect(@tuple).to be_option_tuple('k', 'v')
end
it 'should set no indent, comment, offset or separator' do
expect(@tuple.last[:indent]).to be_nil
expect(@tuple.last[:comment]).to be_nil
expect(@tuple.last[:comment_offset]).to be_nil
expect(@tuple.last[:comment_sep]).to be_nil
end
end
describe 'with "k = a value with spaces"' do
it 'should return an option tuple' do
expect(IniParse::Parser.parse_line('k = a value with spaces')).to \
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
expect(@tuple).to be_option_tuple('k', 'v')
end
it 'should set the comment to "a comment"' do
expect(@tuple).to be_option_tuple(:any, :any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
expect(@tuple).to be_option_tuple(:any, :any, :comment_sep => ';')
end
it 'should set the comment offset to 6' do
expect(@tuple).to 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
expect(@tuple).to be_option_tuple(:any, 'v;w;x y;z')
end
it 'should not set a comment' do
expect(@tuple.last[:comment]).to be_nil
expect(@tuple.last[:comment_offset]).to be_nil
expect(@tuple.last[:comment_sep]).to 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
expect(@tuple).to be_option_tuple(:any, 'v;w')
end
it 'should set the comment to "a comment"' do
expect(@tuple).to be_option_tuple(:any, :any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
expect(@tuple).to be_option_tuple(:any, :any, :comment_sep => ';')
end
it 'should set the comment offset to 8' do
expect(@tuple).to 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
expect(IniParse::Parser.parse_line('key=value')).to \
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
expect(IniParse::Parser.parse_line('key= value')).to \
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
expect(IniParse::Parser.parse_line('key =value')).to \
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
expect(IniParse::Parser.parse_line('key = value')).to \
be_option_tuple('key', 'value')
end
end
describe 'with "key ="' do
it 'should return an option tuple with the correct key' do
expect(IniParse::Parser.parse_line('key =')).to \
be_option_tuple('key')
end
it 'should set the option value to nil' do
expect(IniParse::Parser.parse_line('key =')).to \
be_option_tuple(:any, nil)
end
end
describe 'with "key = EEjDDJJjDJDJD233232=="' do
it 'should include the "equals" in the option value' do
expect(IniParse::Parser.parse_line('key = EEjDDJJjDJDJD233232==')).to \
be_option_tuple('key', 'EEjDDJJjDJDJD233232==')
end
end
describe 'with "key = ==EEjDDJJjDJDJD233232"' do
it 'should include the "equals" in the option value' do
expect(IniParse::Parser.parse_line('key = ==EEjDDJJjDJDJD233232')).to \
be_option_tuple('key', '==EEjDDJJjDJDJD233232')
end
end
describe 'with "key.two = value"' do
it 'should return an option tuple with the correct key' do
expect(IniParse::Parser.parse_line('key.two = value')).to \
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
expect(IniParse::Parser.parse_line('key/with/slashes = value')).to \
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
expect(IniParse::Parser.parse_line('key_with_underscores = value')).to \
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
expect(IniParse::Parser.parse_line('key-with-dashes = value')).to \
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
expect(IniParse::Parser.parse_line('key with spaces = value')).to \
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
expect(@tuple).to be_section_tuple('section')
end
it 'should set no indent, comment, offset or separator' do
expect(@tuple.last[:indent]).to be_nil
expect(@tuple.last[:comment]).to be_nil
expect(@tuple.last[:comment_offset]).to be_nil
expect(@tuple.last[:comment_sep]).to be_nil
end
end
describe 'with "[section with whitespace]"' do
it 'should return a section tuple with the correct key' do
expect(IniParse::Parser.parse_line('[section with whitespace]')).to \
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
expect(IniParse::Parser.parse_line('[ section with surounding whitespace ]')).to \
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
expect(@tuple).to be_section_tuple('section')
end
it 'should set the comment to "a comment"' do
expect(@tuple).to be_section_tuple(:any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
expect(@tuple).to be_section_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 10' do
expect(@tuple).to 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
expect(@tuple).to be_section_tuple('section;with#comment;chars')
end
it 'should not set a comment' do
expect(@tuple.last[:indent]).to be_nil
expect(@tuple.last[:comment]).to be_nil
expect(@tuple.last[:comment_offset]).to be_nil
expect(@tuple.last[:comment_sep]).to 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
expect(@tuple).to be_section_tuple('section;with#comment;chars')
end
it 'should set the comment to "a comment"' do
expect(@tuple).to be_section_tuple(:any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
expect(@tuple).to be_section_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 29' do
expect(@tuple).to 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
expect(@tuple).to be_comment_tuple('a comment')
end
it 'should set the comment separator to ";"' do
expect(@tuple).to be_comment_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 0' do
expect(@tuple).to 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
expect(@tuple).to be_comment_tuple('a comment')
end
it 'should set the comment separator to ";"' do
expect(@tuple).to be_comment_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 1' do
expect(@tuple).to 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
expect(@tuple).to be_comment_tuple('')
end
it 'should set the comment separator to ";"' do
expect(@tuple).to be_comment_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 0' do
expect(@tuple).to be_comment_tuple(:any, :comment_offset => 0)
end
end
# --
# ==========================================================================
# Blank lines.
# ==========================================================================
# ++
describe 'with ""' do
it 'should return a blank tuple' do
expect(IniParse::Parser.parse_line('')).to be_blank_tuple
end
end
describe 'with " "' do
it 'should return a blank tuple' do
expect(IniParse::Parser.parse_line(' ')).to be_blank_tuple
end
end
end
antw-iniparse-088afb7/spec/spec_fixtures.rb 0000664 0000000 0000000 00000003566 13625747173 0021107 0 ustar 00root root 0000000 0000000 module 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::Test::Fixtures[:dos_endings] =
"[database]\r\n" \
"first = true\r\n" \
"second = false\r\n"
# https://github.com/antw/iniparse/issues/17
IniParse::Test::Fixtures[:anon_section_with_comments] = <<-FIX.gsub(/^ /, '')
#####################
# A lot of comments #
#####################
# optiona comment
optiona = A
# optionb comment
optionb = B
# optionc comment
optionc = C
FIX
antw-iniparse-088afb7/spec/spec_helper.rb 0000664 0000000 0000000 00000010053 13625747173 0020502 0 ustar 00root root 0000000 0000000 $:.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 failure_message_when_negated
"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 failure_message_when_negated
"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
antw-iniparse-088afb7/spec/spec_helper_spec.rb 0000664 0000000 0000000 00000012655 13625747173 0021526 0 ustar 00root root 0000000 0000000 require 'spec_helper'
# --
# ============================================================================
# Empty array.
# ============================================================================
# ++
describe 'An empty array' do
it 'should not pass be_section_tuple' do
expect([]).not_to be_section_tuple
end
it 'should not pass be_option_tuple' do
expect([]).not_to be_option_tuple
end
it 'should not pass be_blank_tuple' do
expect([]).not_to be_blank_tuple
end
it 'should not pass be_comment_tuple' do
expect([]).not_to 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
expect(@tuple).to be_section_tuple
end
it 'should pass be_section_tuple("key")' do
expect(@tuple).to be_section_tuple("key")
end
it 'should fail be_section_tuple("invalid")' do
expect(@tuple).not_to be_section_tuple("invalid")
end
it 'should pass be_section_tuple("key", {:opt => "val"})' do
expect(@tuple).to be_section_tuple("key", {:opt => "val"})
end
it 'should not pass be_section_tuple("key", {:invalid => "val"})' do
expect(@tuple).not_to be_section_tuple("key", {:invalid => "val"})
end
it 'should not pass be_section_tuple("key", {:opt => "invalid"})' do
expect(@tuple).not_to be_section_tuple("key", {:opt => "invalid"})
end
it 'should fail be_option_tuple' do
expect(@tuple).not_to be_option_tuple
end
it 'should fail be_blank_tuple' do
expect(@tuple).not_to be_blank_tuple
end
it 'should fail be_comment_tuple' do
expect(@tuple).not_to 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
expect(@tuple).not_to be_section_tuple
end
it 'should pass be_option_tuple' do
expect(@tuple).to be_option_tuple
end
it 'should pass be_option_tuple("key")' do
expect(@tuple).to be_option_tuple("key")
end
it 'should fail be_option_tuple("invalid")' do
expect(@tuple).not_to be_option_tuple("invalid")
end
it 'should pass be_option_tuple("key", "val")' do
expect(@tuple).to be_option_tuple("key", "val")
end
it 'should pass be_option_tuple(:any, "val")' do
expect(@tuple).to be_option_tuple(:any, "val")
end
it 'should fail be_option_tuple("key", "invalid")' do
expect(@tuple).not_to be_option_tuple("key", "invalid")
end
it 'should pass be_option_tuple("key", "val", { :opt => "val" })' do
expect(@tuple).to be_option_tuple("key", "val", { :opt => "val" })
end
it 'should fail be_option_tuple("key", "val", { :invalid => "val" })' do
expect(@tuple).not_to be_option_tuple("key", "val", { :invalid => "val" })
end
it 'should fail be_option_tuple("key", "val", { :opt => "invalid" })' do
expect(@tuple).not_to be_option_tuple("key", "val", { :opt => "invalid" })
end
it 'should fail be_blank_tuple' do
expect(@tuple).not_to be_blank_tuple
end
it 'should fail be_comment_tuple' do
expect(@tuple).not_to be_comment_tuple
end
end
# --
# ============================================================================
# Blank tuple.
# ============================================================================
# ++
describe 'Line tuple [:blank]' do
before(:all) { @tuple = [:blank] }
it 'should fail be_section_tuple' do
expect(@tuple).not_to be_section_tuple
end
it 'should fail be_option_tuple' do
expect(@tuple).not_to be_option_tuple
end
it 'should pass be_blank_tuple' do
expect(@tuple).to be_blank_tuple
end
it 'should fail be_comment_tuple' do
expect(@tuple).not_to 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
expect(@tuple).not_to be_section_tuple
end
it 'should fail be_option_tuple' do
expect(@tuple).not_to be_option_tuple
end
it 'should fail be_blank_tuple' do
expect(@tuple).not_to be_blank_tuple
end
it 'should pass be_comment_tuple' do
expect(@tuple).to be_comment_tuple
end
it 'should pass be_comment_tuple("A comment")' do
expect(@tuple).to be_comment_tuple("A comment")
end
it 'should fail be_comment_tuple("Invalid")' do
expect(@tuple).not_to be_comment_tuple("Invalid")
end
it 'should pass be_comment_tuple("A comment", {:opt => "val"})' do
expect(@tuple).to be_comment_tuple("A comment", {:opt => "val"})
end
it 'should fail be_comment_tuple("A comment", {:invalid => "val"})' do
expect(@tuple).not_to be_comment_tuple("A comment", {:invalid => "val"})
end
it 'should fail be_comment_tuple("A comment", {:opt => "invalid"})' do
expect(@tuple).not_to be_comment_tuple("A comment", {:opt => "invalid"})
end
end