Getting started
dotReg uses key: value lines. Dots separate key elements. Headings group related keys, and explicit blocks hold multiline values.
This guide introduces the notation. The reference specification defines the core rules, and undecided matters lists the parts still open.
Start with file properties
Section titled “Start with file properties”Every complete file begins with this declaration and a blank line:
@dotReg 0.1
A.Code:001The declaration and blank line are required. @dotReg 0.1 is the only supported declaration. The first setting, A.Code, is on physical line 3.
The examples below are body fragments, so they omit the declaration and blank line. Add both when trying an example with a parser. See file property declarations for the detailed rules.
Start with a full key
Section titled “Start with a full key”A colon separates a key from its value. Dots separate key elements:
A.Code:001A.Count:42These lines set the strings 001 and 42 under A.Code and A.Count. Values do not become numbers automatically. A key can also have just one element, as in A: root.
To include a dot in one key element, quote the whole element: A."Display.Name": value. See key paths for other quoted names and key rules.
Group related settings
Section titled “Group related settings”A heading ends with a dot and supplies a shared prefix. Relative lines begin with a dot and are indented beneath the heading:
A. .Code:001 .Count:42This has the same result as the full-key example above. Include both examples in one file only when you want to record each value twice.
Use exactly two additional ASCII spaces for each heading level. Odd numbers of leading spaces are invalid on headings and value lines, and tabs cannot replace these spaces. The number of levels follows the headings you write, not the number of dots in a key:
A.B. .C. .Code:001A.B. is one heading level, so .C. has two leading spaces and .Code has four. The value belongs to A.B.C.Code.
Keep repeated values
Section titled “Keep repeated values”A key can appear more than once. Every value is retained in source order, including identical values:
A.Tag:redA.Tag:greenA.Tag:redThe values of A.Tag are red, green, red. An application can require a key to appear only once through its configuration schema. See repeated values and read state. The Go sample also shows collection and indexed retrieval.
Retrieve a group of settings
Section titled “Retrieve a group of settings”A consumer can retrieve every value at a key prefix and below it. For example, selecting ["ip", "filter"] collects ip.filter itself and numbered keys such as ip.filter.100099 and ip.filter.101000, including deeper descendants. The result preserves source order, repeated values, each value’s declared type and unset state. It provides both full keys and keys relative to the selected prefix. The prefix’s own values have relative path []; an empty-named child’s path is [""].
The prefix is a sequence of key elements, so ip.filter does not accidentally match ip.filters. A heading alone contributes no value, and * has no wildcard meaning. See prefix selection for the rules and a numbered-filter example, and the Go guide for library usage. The other sample ports cover syntax processing and common string decoding.
Write strings naturally
Section titled “Write strings naturally”After outer spaces and tabs are trimmed, a value that starts with " must be quoted in full. Escapes are decoded inside it. Any other starting character makes the whole value literal, including later quotes and backslashes:
A.Path: C:\temp\newA.Message: " hello "A.Saying: say "hello"A.Emoji: "\u{1F600}"A.Path keeps its backslashes, A.Message keeps its surrounding value spaces, and A.Saying keeps its embedded quotes. A.Emoji becomes 😀. See common escapes for the full escape list and single-line values for quoting details.
Write multiline strings
Section titled “Write multiline strings”Use triple quotes for multiline text that needs the same escapes as an ordinary quoted string:
A.Message: """ Hello, \u{1F600} second line """The closing marker goes on its own line. Its leading spaces set the margin removed from non-empty body lines. This margin is independent of heading indentation and may be odd or zero. The body decodes to Hello, 😀, a line break, and two spaces followed by second line.
Use a pipe block when the body should stay literal:
A.Literal: |C:\temp\new |"quotes" and \q stay literal |# this is contentA.Next: valueThe first pipe line must immediately follow the empty header and have more leading ASCII spaces than it. Pipe-body indentation is not subject to the two-space hierarchy rule: the single leading space in this example is sufficient. Each body line loses its indentation and first |; the remaining text is kept as written. A.Next is then read as a normal setting.
Neither block form adds a final line break automatically. See triple-quoted values and pipe blocks for exact indentation and line-ending rules.
Distinguish unset from empty
Section titled “Distinguish unset from empty”An empty right-hand side leaves the value unset unless the next physical line starts a pipe block. An empty quoted value explicitly sets an empty string, and the word null is an ordinary string:
A.Missing:A.Empty: ""A.NullText: nullAll three keys exist. When a string is requested and the declaration permits it, A.Missing is returned as an empty string; its unset state is still available. An omitted key or a heading alone has no value. Your application’s schema decides which keys are required and whether unset or empty values are allowed. See value interpretation.
Add types when a consumer supports them
Section titled “Add types when a consumer supports them”An optional type annotation goes between the key and colon:
A.Count(int):42A.Label:42Values are decoded as strings first. A declaration converts that occurrence to its declared type. Without a declaration, a consumer may request conversion when it reads the value:
| Setting | Requested type | Result |
|---|---|---|
A.Count(int):42 | int | Use the declared int conversion |
A.Count(int):42 | string | Type mismatch |
A.Label:42 | int | Try converting the string when read; failure is a type mismatch |
A.Label:42 | string | Return the string |
Each occurrence has its own annotation. The names and behaviour of standard types are still undecided; int and string here illustrate the rules and the Go sample’s experimental profile. See type annotation rules, type profiles and candidate types and the Go guide.
Try the sample parsers
Section titled “Try the sample parsers”Choose Go, Python, JavaScript, TypeScript, Java, C#, Rust or C++ in the sample parser set. Each language guide explains how to run its CLI and use its library API.
For example, with Go 1.22 or later, run these commands from the repository root:
cd implementations/gogo run ./cmd/configsample ../../examples/sample.dotregThe default mode prints the parsed entries, their unset state and decoded strings. It does not convert annotated values. See the Go sample guide for its conversion mode and library API, and explore the example configuration.
Return to the documentation index or the project introduction.