Skip to content

Latest commit

 

History

History
356 lines (253 loc) · 7.8 KB

README.md

File metadata and controls

356 lines (253 loc) · 7.8 KB

iniparser - read / parse INI configuration, settings and data files into a hash (incl. named subsections)

Usage

INI.loadINI.load_file

Option 1) INI.load - load from string. Example:

hash = INI.load( <<TXT )
  title = Planet Open Data News

  [Open Street Map (OSM) News]
    feed = https://blog.openstreetmap.org/feed
TXT

Option 2) INI.load_file - load from file (shortcut). Example:

hash = INI.load_file( './planet.ini' )

All together now. Example:

require 'iniparser'

text = <<TXT
# comment
; another comment

key1 = hello
key2 = hi!

[section1]
key3 = salut    # end of line comment here

[section2]
key4  = hola    ; another end of line comment here
blank =
blank2

[section3 "http://example.com"]
# comment here
title  = A rose is a rose is a rose, eh?
; another comment here
title2 = A rose is a rose is a rose, eh?
TXT

hash = INI.load( text )
pp hash

resulting in:

{"key1"=>"hello",
 "key2"=>"hi!",
 "section1"=>{"key3"=>"salut"},
 "section2"=>{"key4"=>"hola", "blank"=>"", "blank2"=>""},
 "section3"=>{"http://example.com"=>{"title"=>"A rose is a rose is a rose, eh?",
                                     "title2"=>"A rose is a rose is a rose, eh?"}}}

to access use:

puts hash['key1']
#=> 'hello'
puts hash['key2']
#=> 'hi!'
puts hash['section1']['key3']
#=> 'salut'
puts hash['section2']['key4']
#=> 'hola'
puts hash['section2']['blank']
#=> ''
puts hash['section2']['blank2']
#=> ''
puts hash['section3']['http://example.com']['title']
#=> 'A rose is a rose is a rose, eh?'
puts hash['section3']['http://example.com']['title2']
#=> 'A rose is a rose is a rose, eh?'

Real World Example

Git Config

#
# This is the config file, and
# a '#' or ';' character indicates
# a comment
#

; core variables
[core]
  ; Don't trust file modes
  filemode = false

; Our diff algorithm
[diff]
  external = /usr/local/bin/diff-wrapper
  renames = true

; Proxy settings
[core]
  gitproxy=proxy-command for kernel.org
  gitproxy=default-proxy ; for all the rest

; HTTP
[http]
  sslVerify
[http "https://weak.example.com"]
  sslVerify = false
  cookieFile = /tmp/cookie.txt

resulting in a format warning:

WARN: line 20 - duplicate key >gitproxy< in section; will overwrite existing value

and:

{"core"=>{"filemode"=>"false", "gitproxy"=>"default-proxy"},
 "diff"=>{"external"=>"/usr/local/bin/diff-wrapper", "renames"=>"true"},
 "http"=>
  {"sslVerify"=>"",
   "https://weak.example.com"=>
    {"sslVerify"=>"false", "cookieFile"=>"/tmp/cookie.txt"}}}

"Classic" Windows INI Config

; last modified 1 April 2001 by John Doe
[owner]
name=John Doe
organization=Acme Widgets Inc.

[database]
; use IP address in case network name resolution is not working
server=192.0.2.62
port=143
file=payroll.dat

resulting in:

{"owner"=>{"name"=>"John Doe", "organization"=>"Acme Widgets Inc."},
 "database"=>{"server"=>"192.0.2.62", "port"=>"143", "file"=>"payroll.dat"}}

Planet Pluto Config

title = Planet Ruby

[Ruby Lang News]
  feed = http://www.ruby-lang.org/en/feeds/news.rss

[Rails Girls Summer of Code News]
  feed = https://railsgirlssummerofcode.org/blog.xml


[Benoit Daloze]
  feed     = https://eregon.me/blog/feed.xml
  location = Zürich › Switzerland

[Thomas Leitner]
  feed     = https://gettalong.org/posts.atom
  location = Vienna • Wien › Austria

[Paweł Świątkowski]
  feed     = https://rubytuesday.katafrakt.me/feed.xml
  location = Kraków › Poland

resulting in:

{"title"=>"Planet Ruby",
 "Ruby Lang News"=>
  {"feed"=>"http://www.ruby-lang.org/en/feeds/news.rss"},
 "Rails Girls Summer of Code News"=>
  {"feed"=>"https://railsgirlssummerofcode.org/blog.xml"},
 "Benoit Daloze"=>
  {"feed"=>"https://eregon.me/blog/feed.xml",
   "location"=>"Z\u00FCrich \u203A Switzerland"},
 "Thomas Leitner"=>
  {"feed"=>"https://gettalong.org/posts.atom",
   "location"=>"Vienna \u2022 Wien \u203A Austria"},
 "Pawe\u0142 \u015Awi\u0105tkowski"=>
  {"feed"=>"https://rubytuesday.katafrakt.me/feed.xml",
   "location"=>"Krak\u00F3w \u203A Poland"}}

Rosetta Stone - Read A Configuration File

# This is a configuration file in standard configuration file format
#
# Lines beginning with a hash or a semicolon are ignored by the application
# program. Blank lines are also ignored by the application program.

# This is the fullname parameter
FULLNAME Foo Barber

# This is a favourite fruit
FAVOURITEFRUIT banana

# This is a boolean that should be set
NEEDSPEELING

# This boolean is commented out
; SEEDSREMOVED

# Configuration option names are not case sensitive, but configuration parameter
# data is case sensitive and may be preserved by the application program.

# An optional equals sign can be used to separate configuration parameter data
# from the option name. This is dropped by the parser.

# A configuration option may take multiple parameters separated by commas.
# Leading and trailing whitespace around parameter names and parameter data fields
# are ignored by the application program.

OTHERFAMILY Rhu Barber, Harry Barber

resulting in:

{"FULLNAME"=>"Foo Barber",
 "FAVOURITEFRUIT"=>"banana",
 "NEEDSPEELING"=>"",
 "OTHERFAMILY"=>"Rhu Barber, Harry Barber"}

Frequently Asked Questions (FAQ) and Answers

Q: Why not use TOML (Tom's Obvious, Minimal Language)?

The IniParser returns a simple (nested) hash table and all values are always strings, period (no auto-magic type inference or casting) and you MUST always use strings "unquoted" e.g.

title = Planet Open Data News

instead of requiring "typed" quoted string values:

title = "Planet Open Data News"

Yes, TOML is great for more "advanced" INI configurations / settings that require (strong) data types, nested lists, inline arrays, and much more.

Q: Why not use IniFile - the most popular library (10+ million downloads and counting)?

Again the IniParser returns a simple (nested) "standard" hash table and all values are always strings, period (no auto-magic type inference or casting e.g. no conversion to bool (for true/false) or numbers (for 1,2, etc.). No wrapper around Hash or anything. Here be dragons ;-).

The popular IniFile CANNOT handle properties without values. Example:

[http]
  sslVerify

resulting in:

ERROR: Could not parse line: "  sslVerify" (IniFile::Error)

And parses "modern" named subsections into "flat" sections. Example:

[http]
  ; sslVerify
[http "https://weak.example.com"]
  sslVerify = false
  cookieFile = /tmp/cookie.txt

resulting in:

{"http"=>{},
 "http \"https://weak.example.com\""=>
  {"sslVerify"=>false, "cookieFile"=>"/tmp/cookie.txt"}}}

and NOT resulting in:

{"http"=>
  {"https://weak.example.com"=>
    {"sslVerify"=>false, "cookieFile"=>"/tmp/cookie.txt"}}}

Q: What are some known IniParser format quirks?

No quoted values (e.g. "Hello") or escapes (e.g. \# \n) or quoted values with escapes (e.g. "\n").

No multi-line support for values.

Inline end-of-line comments MUST start with at least one leading space (e.g. test.html#test is NOT an inline end-of-line comment but test.html #test is).

Property key names must match the text pattern / regular expression [a-zA-Z0-9_]([a-zA-Z0-9_-]*[a-zA-Z0-9_])?, that is, use a-z / A-Z, 0-9 or underscore (_) and dash (-) only inside BUT no dot (.) for now.

License

The iniparser scripts are dedicated to the public domain. Use it as you please with no restrictions whatsoever.