ini-sections, ini-keys, ini-for-each added.
This commit is contained in:
+113
-37
@@ -3,30 +3,40 @@
|
||||
@(require
|
||||
scribble/example
|
||||
scribble/core
|
||||
racket/runtime-path
|
||||
(for-label racket/base
|
||||
racket/string
|
||||
racket/class
|
||||
racket/file))
|
||||
racket/file
|
||||
racket/serialize))
|
||||
|
||||
(define myeval
|
||||
(make-base-eval '(require simple-ini roos)))
|
||||
@(define-runtime-path main-rkt "../main.rkt")
|
||||
|
||||
@(define myeval
|
||||
(make-base-eval `(require (file ,(path->string main-rkt)) roos)))
|
||||
|
||||
@title[#:tag "ini-parser"]{INI File Parser and Writer}
|
||||
|
||||
@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]]
|
||||
|
||||
@defmodule[simple-ini]{This module provides simple facilities for reading and writing INI-style configuration files, allowing interpretation of numeric and boolean values, and modification of the parsed structure.}
|
||||
@defmodule[simple-ini]{This module provides simple facilities for reading and
|
||||
writing INI-style configuration files. It supports strings, numbers, booleans,
|
||||
paths, and serializable Racket values, and allows the parsed configuration to
|
||||
be queried and modified.}
|
||||
|
||||
@section{Creating and Parsing INI Files}
|
||||
|
||||
@defproc[(make-ini) mc-pair?]{
|
||||
Creates a new empty INI structure as a mutable cons pair. This is the base structure for manipulating INI contents.
|
||||
@defproc[(make-ini) is-ini?]{
|
||||
Creates a new, empty INI value. The representation of an INI value is
|
||||
private; use @racket[is-ini?] to recognize it and the procedures in this
|
||||
module to inspect or modify it.
|
||||
}
|
||||
|
||||
@defproc[(file->ini [file path-string?]) mc-pair?]{
|
||||
Reads an INI file from disk and parses it into an internal mutable cons pair (mc-pair) structure.
|
||||
If the file does noet exist, an empty ini structure is made.
|
||||
If file is a symbol?, the file will be constructed from the prefs-dir, the symbol and a suffix ".ini".
|
||||
@defproc[(file->ini [file (or/c path-string? symbol?)]) is-ini?]{
|
||||
Reads an INI file from disk and returns an INI value.
|
||||
If the file does not exist, an empty INI value is returned.
|
||||
If @racket[file] is a symbol, the path consists of the user's preferences
|
||||
directory and the symbol's name with an @filepath{.ini} suffix.
|
||||
|
||||
The parser supports:
|
||||
|
||||
@@ -37,17 +47,24 @@
|
||||
@item{Empty lines}
|
||||
]
|
||||
|
||||
An unrecognized non-empty line raises an exception that includes its line
|
||||
number and contents.
|
||||
|
||||
The keys are stored as symbols, and values are automatically interpreted as:
|
||||
@itemlist[
|
||||
@item{Numbers, if the value matches a number pattern}
|
||||
@item{Booleans, if the value is @tt{#t}, @tt{true}, @tt{#f}, or @tt{false} (case-insensitive)}
|
||||
@item{Paths written with the @tt{PATH:} prefix}
|
||||
@item{Explicit Racket-readable strings written with the @tt{VALUE:} prefix,
|
||||
including strings containing newlines}
|
||||
@item{Serializable Racket values written with the @tt{SER:} prefix}
|
||||
@item{Otherwise, as strings}
|
||||
]
|
||||
}
|
||||
|
||||
@defproc[(ini->file [ini mc-pair?] [file path-string?] [#:private? private? boolean? #f]) void?]{
|
||||
@defproc[(ini->file [ini is-ini?] [file path-string?] [#:private? private? boolean? #f]) void?]{
|
||||
Writes an INI structure (as produced by @racket[file->ini] or @racket[make-ini]) to the specified file.
|
||||
If file is a symbol?, the file will be constructed from the prefs-dir, the symbol and a suffix ".ini".
|
||||
Missing parent directories are created automatically.
|
||||
If @racket[private?] is @racket[#t], Unix-like systems restrict the file to mode @tt{0600} before the INI contents are written.
|
||||
|
||||
The output preserves:
|
||||
@@ -57,25 +74,72 @@
|
||||
@item{Comments (prefixed with @tt{;})}
|
||||
@item{Empty lines}
|
||||
]
|
||||
|
||||
Strings, paths, numbers, and booleans have dedicated encodings. Other values
|
||||
are written using @racket[serialize] and must therefore be serializable.
|
||||
}
|
||||
|
||||
@defproc[(get-ini-file [file (or/c path-string? symbol?)]) path?]{
|
||||
Resolves the file argument used by the API. A symbol is resolved in the
|
||||
user's preferences directory and receives an @filepath{.ini} suffix; a path
|
||||
string is converted to a path without otherwise changing its location.
|
||||
}
|
||||
|
||||
@defproc[(is-ini? [value any/c]) boolean?]{
|
||||
Returns @racket[#t] when @racket[value] is an INI value created by
|
||||
@racket[make-ini] or @racket[file->ini], and @racket[#f] otherwise.
|
||||
}
|
||||
|
||||
@section{Accessing and Modifying Values}
|
||||
|
||||
@defproc[(ini-get [ini mc-pair?]
|
||||
[section symbol?]
|
||||
[key symbol?]
|
||||
@defproc[(ini-get [ini is-ini?]
|
||||
[section (or/c symbol? string?)]
|
||||
[key (or/c symbol? string?)]
|
||||
[def-val any/c])
|
||||
any/c]{
|
||||
Retrieves the value associated with the given @racket[key] in the specified @racket[section] of the INI structure. If the key is not found, returns @racket[def-val].
|
||||
Retrieves the value associated with the given @racket[key] in the specified
|
||||
@racket[section]. Section and key matching is case-insensitive. If the key is
|
||||
not found, returns @racket[def-val].
|
||||
}
|
||||
|
||||
@defproc[(ini-set! [ini mc-pair?]
|
||||
[section symbol?]
|
||||
[key symbol?]
|
||||
@defproc[(ini-set! [ini is-ini?]
|
||||
[section (or/c symbol? string?)]
|
||||
[key (or/c symbol? string?)]
|
||||
[val any/c])
|
||||
mc-pair?]{
|
||||
is-ini?]{
|
||||
Sets the value of @racket[key] in the specified @racket[section] of the INI structure. If the section or key does not exist, it is created. Returns the modified INI structure.}
|
||||
|
||||
@section{Inspecting and Iterating over INI Values}
|
||||
|
||||
@defproc[(ini-sections [ini is-ini?]) (listof symbol?)]{
|
||||
Returns the named sections in source order. Key-value pairs before the first
|
||||
section header belong to the internal top-level section and are not included
|
||||
in this result.
|
||||
}
|
||||
|
||||
@defproc[(ini-keys [ini is-ini?] [section symbol?]) (listof symbol?)]{
|
||||
Returns the keys in @racket[section] in source order. If the section does not
|
||||
exist, returns the empty list. Use @racket['nil] to retrieve keys that occur
|
||||
before the first section header.
|
||||
}
|
||||
|
||||
@defproc[(ini-for-each [proc procedure?] [ini is-ini?]) void?]{
|
||||
Calls @racket[proc] with three arguments---the section, key, and value---for
|
||||
every key-value pair, in source order. Key-value pairs before the first
|
||||
section header use @racket['nil] as their section.
|
||||
|
||||
@examples[#:eval myeval
|
||||
(define settings (make-ini))
|
||||
(ini-set! settings 'server 'port 8080)
|
||||
(ini-set! settings 'server 'tls #t)
|
||||
(ini-sections settings)
|
||||
(ini-keys settings 'server)
|
||||
(ini-for-each
|
||||
(lambda (section key value)
|
||||
(printf "~a.~a = ~v~n" section key value))
|
||||
settings)]
|
||||
}
|
||||
|
||||
|
||||
@section{The @racket[ini%] Racket Class}
|
||||
|
||||
@@ -101,7 +165,7 @@ An OO wrapper around the ini functions.
|
||||
or if some non existing key is read.
|
||||
}
|
||||
|
||||
@defmethod*[([(get-file) path?])]{
|
||||
@defmethod*[([(get-file) (or/c path? #f)])]{
|
||||
Gets the current ini file. See constructor for more information.
|
||||
}
|
||||
|
||||
@@ -126,25 +190,30 @@ An OO wrapper around the ini functions.
|
||||
Enables or disables private file permissions for subsequent writes.
|
||||
}
|
||||
|
||||
@defmethod*[([(get-contents) list?])]{
|
||||
Gets the contents of the ini structure as stored in memory.
|
||||
@defmethod*[([(sections) (listof symbol?)])]{
|
||||
Returns the named sections in source order, as with @racket[ini-sections].
|
||||
}
|
||||
|
||||
@defmethod*[([(contents) list?])]{
|
||||
See get-contents.
|
||||
@defmethod*[([(keys [section symbol?]) (listof symbol?)])]{
|
||||
Returns the keys in @racket[section], as with @racket[ini-keys].
|
||||
}
|
||||
|
||||
@defmethod*[([(for-each [proc procedure?]) void?])]{
|
||||
Calls @racket[proc] with the section, key, and value of each key-value pair,
|
||||
as with @racket[ini-for-each].
|
||||
}
|
||||
|
||||
@defmethod*[([(reload) this])]{
|
||||
Reloads the ini file in memory, or empties the ini structure (eq? file #f).
|
||||
}
|
||||
|
||||
@defmethod*[([(set! [section (or/c symbol? string?)] [key (or/c symbol? string?)] [value any/c?]) this])]{
|
||||
@defmethod*[([(set! [section (or/c symbol? string?)] [key (or/c symbol? string?)] [value any/c]) this])]{
|
||||
Sets the value of the key in the given section. After the set! operation, the ini structure will be written to file.
|
||||
Note. Although ini files can be read from standard .ini formats, the simple-ini format will be enhanced. It wil store values in racket format, so that 'read' can be used to read in the racket value.
|
||||
}
|
||||
|
||||
@defmethod*[([(get [section (or/c symbol? string?)] [key (or/c symbol? string?)] [default-value any/c?]) any/c?]
|
||||
[(get [section (or/c symbol? string?)] [key (or/c symbol? string)]) any/c]
|
||||
@defmethod*[([(get [section (or/c symbol? string?)] [key (or/c symbol? string?)] [default-value any/c]) any/c]
|
||||
[(get [section (or/c symbol? string?)] [key (or/c symbol? string?)]) any/c]
|
||||
)]{
|
||||
Returns the value for the given section and key combination. If this combination does not exist in the ini structure, it will return the default-value. However, if default-value is not given, it will return #f.
|
||||
}
|
||||
@@ -188,7 +257,21 @@ If no file is provided, the object operates in-memory only. Subsequent @racket[s
|
||||
If the file does not exist, the content is reset to an empty INI structure.
|
||||
}
|
||||
|
||||
@defproc[(set! [section symbol?] [key symbol?] [val any/c]) ini]{
|
||||
@defproc[(sections) (listof symbol?)]{
|
||||
Returns the named sections in source order, as with
|
||||
@racket[ini-sections].
|
||||
}
|
||||
|
||||
@defproc[(keys [section symbol?]) (listof symbol?)]{
|
||||
Returns the keys in @racket[section], as with @racket[ini-keys].
|
||||
}
|
||||
|
||||
@defproc[(for-each [proc procedure?]) void?]{
|
||||
Calls @racket[proc] with the section, key, and value of each key-value
|
||||
pair, as with @racket[ini-for-each].
|
||||
}
|
||||
|
||||
@defproc[(set! [section (or/c symbol? string?)] [key (or/c symbol? string?)] [val any/c]) ini]{
|
||||
Sets the value in the INI structure for the given @racket[section] and @racket[key] to @racket[val].
|
||||
|
||||
If a file is associated with the object, the structure is saved to disk immediately.
|
||||
@@ -196,7 +279,7 @@ If no file is provided, the object operates in-memory only. Subsequent @racket[s
|
||||
Returns the INI object itself.
|
||||
}
|
||||
|
||||
@defproc[(get [section symbol?] [key symbol?] [def-val any/c] ...) any/c]{
|
||||
@defproc[(get [section (or/c symbol? string?)] [key (or/c symbol? string?)] [def-val any/c] ...) any/c]{
|
||||
Retrieves the value associated with the given @racket[section] and @racket[key].
|
||||
|
||||
If not found:
|
||||
@@ -206,10 +289,3 @@ If no file is provided, the object operates in-memory only. Subsequent @racket[s
|
||||
@item{Raises an error if @racket[fail] is enabled and no default is given}
|
||||
]
|
||||
}
|
||||
|
||||
@bold{Internal state:}
|
||||
@itemlist[
|
||||
@item{@racket[file*] — the filename (or @racket[#f])}
|
||||
@item{@racket[content] — the mutable INI structure}
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user