inifile 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +6 -0
- data/README.txt +5 -2
- data/lib/inifile.rb +74 -25
- data/test/data/browscap.ini +5 -0
- data/test/data/good.ini +3 -1
- data/test/data/multiline.ini +17 -0
- data/test/test_inifile.rb +38 -2
- metadata +59 -17
- data/.gitignore +0 -17
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -31,6 +31,8 @@ A typical INI file might look like this:
|
|
31
31
|
; some comment on section1
|
32
32
|
var1 = foo
|
33
33
|
var2 = doodle
|
34
|
+
var3 = "multiline
|
35
|
+
also possible"
|
34
36
|
|
35
37
|
[section2]
|
36
38
|
|
@@ -38,12 +40,13 @@ A typical INI file might look like this:
|
|
38
40
|
var1 = baz
|
39
41
|
var2 = shoodle
|
40
42
|
|
43
|
+
|
41
44
|
==== Format
|
42
45
|
|
43
46
|
This describes the elements of the INI file format:
|
44
47
|
|
45
48
|
* *Sections*: Section declarations start with '[' and end with ']' as in [section1] and [section2] above. And sections start with section declarations.
|
46
|
-
* *Parameters*: The "var1 = foo" above is an example of a parameter (also known as an item). Parameters are made up of a key ('var1'), equals sign ('='), and a value ('foo').
|
49
|
+
* *Parameters*: The "var1 = foo" above is an example of a parameter (also known as an item). Parameters are made up of a key ('var1'), equals sign ('='), and a value ('foo'). Multiline is support if value of parameter is enclosed by ".
|
47
50
|
* *Comments*: All the lines starting with a ';' are assumed to be comments, and are ignored.
|
48
51
|
|
49
52
|
==== Differences
|
@@ -64,7 +67,7 @@ This package supports the standard INI file format described in the *Format*
|
|
64
67
|
section above. The following differences are also supported:
|
65
68
|
|
66
69
|
* *Comments*: The comment character can be specified when an +IniFile+ is created. The comment character must be the first non-whitespace character on a line.
|
67
|
-
* *Backslashes*: Backslashes are not supported by this package.
|
70
|
+
* *Backslashes*: Backslashes are not supported by this package. But multilines are. Enclose the param's value by ".
|
68
71
|
* <b>Duplicate parameters</b>: Duplicate parameters are allowed in a single section. The last parameter value is the one that will be stored in the +IniFile+.
|
69
72
|
* <b>Duplicate sections</b>: Duplicate sections will be merged. Parameters duplicated between to the two sections follow the duplicate parameters rule above.
|
70
73
|
* *Parameters*: The parameter separator character can be specified when an +IniFile+ is created.
|
data/lib/inifile.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
# This class represents the INI file and can be used to parse, modify,
|
3
3
|
# and write INI files.
|
4
4
|
#
|
5
|
+
|
6
|
+
#encoding: UTF-8
|
7
|
+
|
5
8
|
class IniFile
|
6
9
|
|
7
10
|
# Inifile is enumerable.
|
@@ -9,7 +12,7 @@ class IniFile
|
|
9
12
|
|
10
13
|
# :stopdoc:
|
11
14
|
class Error < StandardError; end
|
12
|
-
VERSION = '0.
|
15
|
+
VERSION = '0.4.0'
|
13
16
|
# :startdoc:
|
14
17
|
|
15
18
|
#
|
@@ -38,16 +41,22 @@ class IniFile
|
|
38
41
|
#
|
39
42
|
# :comment => ';' The line comment character(s)
|
40
43
|
# :parameter => '=' The parameter / value separator
|
44
|
+
# :encoding => nil The encoding used for read/write (RUBY 1.9)
|
41
45
|
#
|
42
46
|
def initialize( filename, opts = {} )
|
43
47
|
@fn = filename
|
44
48
|
@comment = opts[:comment] || ';#'
|
45
49
|
@param = opts[:parameter] || '='
|
50
|
+
@encoding = opts[:encoding]
|
46
51
|
@ini = Hash.new {|h,k| h[k] = Hash.new}
|
47
52
|
|
48
53
|
@rgxp_comment = %r/\A\s*\z|\A\s*[#{@comment}]/
|
49
54
|
@rgxp_section = %r/\A\s*\[([^\]]+)\]/o
|
50
|
-
@rgxp_param = %r/\A([^#{@param}]+)#{@param}(
|
55
|
+
@rgxp_param = %r/\A([^#{@param}]+)#{@param}\s*"?([^"]*)"?\z/
|
56
|
+
|
57
|
+
@rgxp_multiline_start = %r/\A([^#{@param}]+)#{@param}\s*"+([^"]*)?\z/
|
58
|
+
@rgxp_multiline_value = %r/\A([^"]*)\z/
|
59
|
+
@rgxp_multiline_end = %r/\A([^"]*)"\z/
|
51
60
|
|
52
61
|
parse
|
53
62
|
end
|
@@ -60,11 +69,19 @@ class IniFile
|
|
60
69
|
# Write the INI file contents to the filesystem. The given _filename_
|
61
70
|
# will be used to write the file. If _filename_ is not given, then the
|
62
71
|
# named used when constructing this object will be used.
|
72
|
+
# The following _options_ can be passed to this method:
|
73
|
+
#
|
74
|
+
# :encoding => nil The encoding used for writing (RUBY 1.9)
|
63
75
|
#
|
64
|
-
def write( filename = nil )
|
76
|
+
def write( filename = nil, opts={} )
|
65
77
|
@fn = filename unless filename.nil?
|
66
78
|
|
67
|
-
|
79
|
+
encoding = opts[:encoding] || @encoding
|
80
|
+
mode = (RUBY_VERSION >= '1.9' && @encoding) ?
|
81
|
+
"w:#{encoding.to_s}" :
|
82
|
+
'w'
|
83
|
+
|
84
|
+
File.open(@fn, mode) do |f|
|
68
85
|
@ini.each do |section,hash|
|
69
86
|
f.puts "[#{section}]"
|
70
87
|
hash.each {|param,val| f.puts "#{param} #{@param} #{val}"}
|
@@ -279,34 +296,66 @@ class IniFile
|
|
279
296
|
#
|
280
297
|
def parse
|
281
298
|
return unless File.file?(@fn)
|
299
|
+
|
282
300
|
section = nil
|
301
|
+
tmp_value = ""
|
302
|
+
tmp_param = ""
|
303
|
+
|
304
|
+
fd = (RUBY_VERSION >= '1.9' && @encoding) ?
|
305
|
+
File.open(@fn, 'r', :encoding => @encoding) :
|
306
|
+
File.open(@fn, 'r')
|
307
|
+
|
308
|
+
while line = fd.gets
|
309
|
+
line = line.chomp
|
310
|
+
|
311
|
+
# mutline start
|
312
|
+
# create tmp variables to indicate that a multine has started
|
313
|
+
# and the next lines of the ini file will be checked
|
314
|
+
# against the other mutline rgxps.
|
315
|
+
if line =~ @rgxp_multiline_start then
|
283
316
|
|
284
|
-
|
285
|
-
|
286
|
-
line = line.chomp
|
317
|
+
tmp_param = $1.strip
|
318
|
+
tmp_value = $2 + "\n"
|
287
319
|
|
288
|
-
|
289
|
-
|
290
|
-
|
320
|
+
# the mutline end-delimiter is found
|
321
|
+
# clear the tmp vars and add the param / value pair to the section
|
322
|
+
elsif line =~ @rgxp_multiline_end && tmp_param != "" then
|
291
323
|
|
292
|
-
|
293
|
-
|
324
|
+
section[tmp_param] = tmp_value + $1
|
325
|
+
tmp_value, tmp_param = "", ""
|
294
326
|
|
295
|
-
|
296
|
-
|
297
|
-
begin
|
298
|
-
section[$1.strip] = $2.strip
|
299
|
-
rescue NoMethodError
|
300
|
-
raise Error, "parameter encountered before first section"
|
301
|
-
end
|
327
|
+
# anything else between multiline start and end
|
328
|
+
elsif line =~ @rgxp_multiline_value && tmp_param != "" then
|
302
329
|
|
303
|
-
|
304
|
-
|
330
|
+
tmp_value += $1 + "\n"
|
331
|
+
|
332
|
+
# ignore blank lines and comment lines
|
333
|
+
elsif line =~ @rgxp_comment then
|
334
|
+
|
335
|
+
next
|
336
|
+
|
337
|
+
# this is a section declaration
|
338
|
+
elsif line =~ @rgxp_section then
|
339
|
+
|
340
|
+
section = @ini[$1.strip]
|
341
|
+
|
342
|
+
# otherwise we have a parameter
|
343
|
+
elsif line =~ @rgxp_param then
|
344
|
+
|
345
|
+
begin
|
346
|
+
section[$1.strip] = $2.strip
|
347
|
+
rescue NoMethodError
|
348
|
+
raise Error, "parameter encountered before first section"
|
305
349
|
end
|
306
|
-
|
307
|
-
|
350
|
+
|
351
|
+
else
|
352
|
+
raise Error, "could not parse line '#{line}"
|
353
|
+
end
|
354
|
+
end # while
|
355
|
+
|
356
|
+
ensure
|
357
|
+
fd.close if defined? fd and fd
|
308
358
|
end
|
309
359
|
|
310
|
-
end #
|
360
|
+
end # IniFile
|
311
361
|
|
312
|
-
# EOF
|
data/test/data/good.ini
CHANGED
data/test/test_inifile.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
# classname: asrt / meth = ratio%
|
3
3
|
# Rini::IniFile: 0 / 9 = 0.00%
|
4
4
|
|
5
|
+
# encoding: UTF-8
|
6
|
+
|
5
7
|
begin
|
6
8
|
require 'inifile'
|
7
9
|
rescue LoadError
|
@@ -22,6 +24,7 @@ class TestIniFile < Test::Unit::TestCase
|
|
22
24
|
['section_one', 'one', '1'],
|
23
25
|
['section_one', 'two', '2'],
|
24
26
|
['section_two', 'three', '3'],
|
27
|
+
['section_two', 'multi', "multiline\nsupport"],
|
25
28
|
['section three', 'four', '4'],
|
26
29
|
['section three', 'five', '5'],
|
27
30
|
['section three', 'six', '6'],
|
@@ -192,7 +195,7 @@ class TestIniFile < Test::Unit::TestCase
|
|
192
195
|
}
|
193
196
|
assert_equal expected, @ini_file[:section_one]
|
194
197
|
|
195
|
-
expected = {'three' => '3'}
|
198
|
+
expected = {'three' => '3', 'multi' => "multiline\nsupport"}
|
196
199
|
assert_equal expected, @ini_file['section_two']
|
197
200
|
|
198
201
|
expected = {
|
@@ -330,6 +333,39 @@ class TestIniFile < Test::Unit::TestCase
|
|
330
333
|
ini_file[:foo] = {}
|
331
334
|
assert_equal ini_file["foo"], {}
|
332
335
|
end
|
336
|
+
|
337
|
+
def test_multiline_parsing
|
338
|
+
ini_file = IniFile.load('test/data/multiline.ini')
|
339
|
+
|
340
|
+
multiline = ini_file['section_three']
|
341
|
+
expected = {"three" => "hello\nmultiline", "other" => "stuff"}
|
342
|
+
assert_equal expected, multiline
|
343
|
+
|
344
|
+
multiple = ini_file['section_four']
|
345
|
+
expected = {"four" => "hello\nmultiple\nmultilines"}
|
346
|
+
assert_equal expected, multiple
|
347
|
+
|
348
|
+
end
|
349
|
+
|
350
|
+
if RUBY_VERSION >= '1.9'
|
351
|
+
def test_parse_encoding
|
352
|
+
ini_file = IniFile.new("test/data/browscap.ini", :encoding => 'ISO-8859-1')
|
353
|
+
assert_equal ini_file['www.substancia.com AutoHTTPAgent (ver *)']['Browser'], "Subst\xE2ncia".force_encoding('ISO-8859-1')
|
354
|
+
end
|
355
|
+
|
356
|
+
def test_write_encoding
|
357
|
+
tmp = 'test/data/tmp.ini'
|
358
|
+
File.delete tmp if Kernel.test(?f, tmp)
|
359
|
+
|
360
|
+
@ini_file = IniFile.new(tmp, :encoding => 'UTF-8')
|
361
|
+
@ini_file['testutf-8'] = {"utf-8" => "appr\u20accier"}
|
362
|
+
|
363
|
+
@ini_file.save tmp
|
364
|
+
|
365
|
+
test = File.open(tmp)
|
366
|
+
assert_equal test.external_encoding.to_s, 'UTF-8'
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
333
370
|
end
|
334
371
|
|
335
|
-
# EOF
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inifile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Tim Pease
|
@@ -9,30 +15,59 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2011-02-15 00:00:00 -07:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: bones-git
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
- 4
|
34
|
+
version: 1.2.4
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
25
37
|
- !ruby/object:Gem::Dependency
|
26
38
|
name: bones
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
30
42
|
requirements:
|
31
43
|
- - ">="
|
32
44
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
35
|
-
|
45
|
+
hash: 21
|
46
|
+
segments:
|
47
|
+
- 3
|
48
|
+
- 6
|
49
|
+
- 5
|
50
|
+
version: 3.6.5
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
description: |-
|
54
|
+
This is a native Ruby package for reading and writing INI files.
|
55
|
+
|
56
|
+
Although made popular by Windows, INI files can be used on any system thanks
|
57
|
+
to their flexibility. They allow a program to store configuration data, which
|
58
|
+
can then be easily parsed and changed. Two notable systems that use the INI
|
59
|
+
format are Samba and Trac.
|
60
|
+
|
61
|
+
== SYNOPSIS:
|
62
|
+
|
63
|
+
An initialization file, or INI file, is a configuration file that contains
|
64
|
+
configuration data for Microsoft Windows based applications. Starting with
|
65
|
+
Windows 95, the INI file format was superseded but not entirely replaced by
|
66
|
+
a registry database in Microsoft operating systems.
|
67
|
+
|
68
|
+
Although made popular by Windows, INI files can be used on any system thanks
|
69
|
+
to their flexibility. They allow a program to store configuration data, which
|
70
|
+
can then be easily parsed and changed.
|
36
71
|
email: tim.pease@gmail.com
|
37
72
|
executables: []
|
38
73
|
|
@@ -42,16 +77,17 @@ extra_rdoc_files:
|
|
42
77
|
- History.txt
|
43
78
|
- README.txt
|
44
79
|
files:
|
45
|
-
- .gitignore
|
46
80
|
- History.txt
|
47
81
|
- README.txt
|
48
82
|
- Rakefile
|
49
83
|
- lib/inifile.rb
|
50
84
|
- test/data/bad_1.ini
|
51
85
|
- test/data/bad_2.ini
|
86
|
+
- test/data/browscap.ini
|
52
87
|
- test/data/comment.ini
|
53
88
|
- test/data/good.ini
|
54
89
|
- test/data/mixed_comment.ini
|
90
|
+
- test/data/multiline.ini
|
55
91
|
- test/data/param.ini
|
56
92
|
- test/test_inifile.rb
|
57
93
|
has_rdoc: true
|
@@ -65,21 +101,27 @@ rdoc_options:
|
|
65
101
|
require_paths:
|
66
102
|
- lib
|
67
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
68
105
|
requirements:
|
69
106
|
- - ">="
|
70
107
|
- !ruby/object:Gem::Version
|
108
|
+
hash: 3
|
109
|
+
segments:
|
110
|
+
- 0
|
71
111
|
version: "0"
|
72
|
-
version:
|
73
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
74
114
|
requirements:
|
75
115
|
- - ">="
|
76
116
|
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
118
|
+
segments:
|
119
|
+
- 0
|
77
120
|
version: "0"
|
78
|
-
version:
|
79
121
|
requirements: []
|
80
122
|
|
81
123
|
rubyforge_project: inifile
|
82
|
-
rubygems_version: 1.3.
|
124
|
+
rubygems_version: 1.3.7
|
83
125
|
signing_key:
|
84
126
|
specification_version: 3
|
85
127
|
summary: INI file reader and writer
|
data/.gitignore
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# The list of files that should be ignored by Mr Bones.
|
2
|
-
# Lines that start with '#' are comments.
|
3
|
-
#
|
4
|
-
# A .gitignore file can be used instead by setting it as the ignore
|
5
|
-
# file in your Rakefile:
|
6
|
-
#
|
7
|
-
# PROJ.ignore_file = '.gitignore'
|
8
|
-
#
|
9
|
-
# For a project with a C extension, the following would be a good set of
|
10
|
-
# exclude patterns (uncomment them if you want to use them):
|
11
|
-
# *.[oa]
|
12
|
-
*~
|
13
|
-
*.sw[op]
|
14
|
-
announcement.txt
|
15
|
-
coverage
|
16
|
-
doc
|
17
|
-
pkg
|