boop

Object-oriented programming for bash 4.3+ — real classes, objects, inheritance, and a standard library, in pure bash.


Project maintained by ydbxmhc Hosted on GitHub Pages

Config

Structured config file reader/writer. Parses two formats — flat key=value and sectioned INI — behind a single interface. Pure bash, zero forks.

Contents


Dependencies

. boop Config

Formats

Flat

# My app config
host=localhost
port=5432
debug=false

Keys are top-level. The = is the only required character per line. # comments and blank lines are ignored.

INI

# My app config

[server]
host=localhost
port=8080

[database]
host=db.internal
port=5432
name=myapp

Keys under a [section] header are stored as section.key. Keys before any header (top-level keys) have no prefix.

into=port  $cfg.get "server.port"     # "8080"
into=dbh   $cfg.get "database.host"   # "db.internal"
into=top   $cfg.get "topLevelKey"     # no prefix

Constructor

into=cfg Config.new          # empty config, no backing file

Config.new creates an empty Config. You can then call $cfg.set to add keys, or use one of the static loading constructors below instead.


Loading

All loaders are static constructors — they return a new Config object. There is no instance-method form of load.

From a file

into=cfg Config.load    settings.cfg   # flat key=value file
into=cfg Config.loadINI settings.ini   # INI file with [section] headers

Config.load parses flat key=value format only. For INI files, use Config.loadINI. The file and format properties are recorded automatically so $cfg.save can write back to the same file.

From a string

# Flat key=value string:
into=cfg Config.fromFlatString "host=localhost
port=9000"

# INI-format string:
into=cfg Config.fromString "[server]
host=localhost
port=8080"

fromFlatString parses flat format. fromString parses INI format (with [section] headers). Neither requires a backing file.


Reading Keys

into=host  $cfg.get "server.host"     # returns value or ""
into=port  $cfg.get "server.port"
into=debug $cfg.get "debug"

$cfg.has "server.host" && echo "configured"   # 0=exists, 1=absent

get returns an empty string for unknown keys — it does not crash. Use has to distinguish “not set” from “set to empty string”.

Listing keys

into=all  $cfg.keys               # all keys, newline-joined, insertion order

For INI configs, to get all keys in a section:

# Get all keys in a section using the section argument:
into=db_keys $cfg.keys database     # keys in [database], without the prefix

# Or filter the full key list manually:
into=all $cfg.keys
while IFS= read -r k; do
  [[ "$k" == database.* ]] && printf "%s\n" "$k"
done <<< "$all"

Listing sections (INI)

into=secs $cfg.sections    # unique section names, newline-joined
# e.g. "server\ndatabase"

Writing Keys

$cfg.set "server.port" "9090"       # creates or overwrites
$cfg.set "feature.enabled" "true"

Set does not validate key format. Any string is a valid key.


Saving

$cfg.save                    # writes to the file loaded from (errors if no file was loaded)
$cfg.save /path/to/new.ini   # saves to a different file; does not update $file

The format used is whatever $cfg.get format says — either flat or ini.

Serializing to string

into=s $cfg.toFlat   # "host=localhost\nport=5432\n..."
into=s $cfg.toINI    # "[server]\nhost=localhost\n..."

Full Example

. boop Config

# Load an INI file
into=cfg Config.loadINI /etc/myapp/config.ini

into=host  $cfg.get "database.host"
into=port  $cfg.get "database.port"
printf "Connecting to %s:%s\n" "$host" "$port"

# Modify and save back to the same file
$cfg.set "database.port" "5433"
$cfg.save

# Check sections
_EOL=" " into=secs $cfg.sections
printf "Sections: %s\n" "$secs"

Design Notes

No eval, no source. The parser is a while IFS= read -r loop that splits on the first = per line. Config files cannot execute code.

Insertion order preserved. Keys are stored in two arrays: an associative array for O(1) lookup, and an indexed array for ordered iteration. keys always returns keys in the order they were first seen.

Re-setting a key updates its value but not its position. The key stays where it was inserted in the order.

Two separate loaders, not auto-detection. Config.load always parses flat key=value format. Config.loadINI always parses INI with [section] headers. Choose the right loader for your file — there is no auto-detection.


↑ Site map