Collections (book / playlist)¶
This document defines the text format by which an ordered set of songs — a book or a playlist — is represented in a single neumaRk file.
A collection does not introduce a new language: it is a thin container layer around a sequence of songs, each of which is a standalone neumaRk document as already defined by the rest of the specification. The same parser reads single songs and collections; the distinction is made on the first line of the file.
1. Purpose and role¶
The collection format serves to export, share, and re-import a book
or a playlist as a single .nrk file — self-contained and readable.
The guiding principle is portability: the file is a self-sufficient snapshot of the collection. All songs are embedded as snapshots (frozen copies), so that the file can be opened and imported by anyone, even without access to the original songs and even if the originals change or disappear.
Everything that is product-specific (and not part of the musical language) — cover art, curated tags, sharing, roles, database identifiers — is not part of the file (see §7).
2. Collection and single song¶
A neumaRk file may represent:
- a single song, whose first line is the version declaration
nrk:<major>.<minor>(seeneumaRk_header.md§2); - a collection, whose first line is
nrk-book:<v>ornrk-playlist:<v>(§3).
The distinction is given by the content of the first line alone,
never by the file extension: a .nrk may contain either.
A file starting with nrk: is a single song; a file starting with
nrk-book: / nrk-playlist: is a collection. The two readings coexist
in the same parser.
The term collection is a conceptual umbrella used in this specification and in tooling; it never appears as a token in the file. The type (book or playlist) is written directly into the first-line marker.
3. Opening line and type¶
The first line of a collection is a version declaration that embeds the type:
nrk-book:0.6
or
nrk-playlist:0.6
Characteristics:
- it is mandatory and must be the first line of the file;
- the type (
book/playlist) is part of the marker: reading the first line tells you both that the file is a collection and which type; - the version follows the same
nrk:numbering of the language.
Functional difference between the two types:
- a book is a curated set of songs, without per-song overrides;
- a playlist is an executable sequence in which each song may carry a per-occurrence override (§6).
4. Collection header¶
After the opening line, and any blank lines, a collection header may
appear: a block of directives in the form key: value.
nrk-playlist:0.6
name: My Setlist
desc: live at the Blue Note
| Directive | Meaning | Mandatory |
|---|---|---|
name: |
collection name | no (recommended) |
desc: |
free description | no |
Header directives:
- use
:as the separator (same syntactic family asnrk:); - precede any song block;
- are part of neumaRk (as the
HT)title is for the song): the textual identity of the collection.
A header directive appearing after the first song block is out of
place (W155): it is ignored and does not enter the song that precedes it.
The same holds for a directive written between an item: line and its block:
the collection name does not change. Repeated before the first block, a
directive takes its last occurrence, with no diagnostics.
5. Song blocks¶
The body of the collection is a sequence of song blocks. Each block:
- is a standalone neumaRk document, starting with its own
nrk:<v>line and continuing with header and datapacks as usual; - is a self-sufficient snapshot (the musical content is embedded, not referenced);
- is copy-pasteable as a valid
.nrkfile on its own.
As in a single document, blank lines may stand between the block's nrk:<v>
line and its header, and the header may contain // comments on lines of
their own: neither is a field, and the title stays the one of HT) (or the
first line of the implicit header). The markers of the block header have the
meaning given in neumaRk_header.md §6.2: HC) carries the credits, and no
H…) marker becomes the song's style.
The song order is the order of the blocks in the file: there is no numeric ordering key.
nrk-playlist:0.6
name: My Setlist
nrk:0.6
First Tune (Author)
F 120bpm
F| Bb| C7| F|
nrk:0.6
Second Tune (Author)
Bb 90bpm
Bb| Eb| F7| Bb|
A collection with no song blocks is degenerate (W156).
6. Per-item override (playlist only)¶
In a playlist, each song may be preceded by an item: line declaring
its overrides for that occurrence in the setlist. The overrides
are not properties of the song (the same song in two playlists may
have different ones): they are a layer of the setlist entry.
item: transpose=+2 notes="capo 3" form=[Intro] [A|8]x2 [B|8] [A|8]
nrk:0.6
My Tune (Author)
…
Rules:
- the
item:line applies to the song block that immediately follows it (the nextnrk:); if it is not followed by any song block it produces warning W154; - it appears only if there is at least one override; its absence means "no overlay";
- it is allowed only in playlists. An
item:line in annrk-book:is out of context (W152).
6.1 Parameter syntax¶
Parameters are key=value pairs separated by spaces. The = sign
distinguishes the inline parameter from the header directive (:),
so that no symbol has a double role.
A value:
- is a simple token (no spaces), e.g.
transpose=+2; or - is quoted
"…"when it contains spaces (literal text, quote-aware as in the rest of neumaRk), e.g.notes="capo 3".
Allowed keys: transpose, notes, form. An unknown key is ignored
with diagnostic W153; a token without =value with W179.
| Key | Type | Meaning |
|---|---|---|
transpose |
signed integer | performance transposition (overlay, ± semitones) |
notes |
text | personal annotation for this entry |
form |
FORM grammar | performance form for this occurrence (§8) |
6.2 form= consumes the rest of the line¶
Since the FORM grammar itself uses "…" containers for labels (see §8),
the form= parameter is not quoted: it consumes everything that
follows up to end of line, verbatim. For this reason form=, when
present, is the last parameter of the item: line.
item: transpose=-1 form="Theme"[A|8]ff [B|4]x2 "Coda"[A|8]&fermata
The quotes here are internal to the FORM grammar (labels), not delimiters of the parameter. (A multi-line form is out of scope in this version.)
A null transpose (+0, no-op) and an empty notes are not errors. A
transpose that is not an integer (transpose=abc, transpose=1.5) is
ignored with W185.
7. Portability mode: inside and outside the file¶
The collection carries only music and minimal structure. Everything that is application product is reconstructed on import from defaults, as when creating a new collection.
In the file (it is neumaRk):
- the type (
nrk-book:/nrk-playlist:); name:/desc:;- the song order (= order of the blocks);
- for playlists: the
transpose/notes/formoverrides onitem:; - each song in full, as a snapshot.
Outside the file (it is not neumaRk):
- cover art, curated tags, subscriber count;
- sharing, roles, permissions;
- the songs' database identifiers;
- the dynamic vs snapshot distinction of playlist entries (on export every entry is resolved to a snapshot).
7.1 The file is intentionally anonymous¶
Consistent with the principle above, a collection file carries no origin identity: no database identifiers, no deduplication keys, no host tags. It is, by design, anonymous.
Consequence: a song's identity (deciding whether two songs are "the same") is not a property of the file — it is a host concern, to be derived from the music (see §7.2), never from an opaque tag stuck to the file. This is deliberate: the format does not carry data it cannot itself understand.
7.2 Import semantics (host behavior)¶
How a host re-imports a collection is not defined by neumaRk: it is host behavior, described in the documentation of the application that implements it. Two consequences of the file's anonymity (§7.1), however, hold for every host:
- re-importing the same file cannot recognize the songs already present by an identity: the file carries none;
- any recognition ("do I already have this song?") can only be based on the music (for example a melodic fingerprint), not on an exact key glued to the file; and it is, by nature, a suggestion rather than an automatism.
7.3 Header absorption on import (lossless)¶
Each block of the collection is a complete song, header included. An import that splits the header (the song's metadata) from the body (datapack) recovers it in full — title, credits, key, tempo, meter, style, subtitle, year, alternates, languages — and the body is the datapack with leading/trailing blank lines removed: the export→import round-trip is lossless.
Requirement: the split relies on the blank line between header and datapack (which conforming exporters always emit). On hand-written files without that separator, header and body cannot be told apart.
8. FORM at the collection level¶
The form parameter of a playlist entry (§6) uses the FORM)
grammar defined in neumaRk_play_and_form.md (section boxes,
informative durations |N, labels, dynamics, keywords, free prose).
8.1 Semantics: replacement¶
If a playlist entry carries a form, it replaces the FORM)
section possibly contained in the song's snapshot, for that
occurrence.
It serves to declare: "the form in which we perform this song tonight is this, regardless of the song's original form."
- override present → the item
formwins over the song'sFORM); - override absent → the song's
FORM)remains (if present).
It is a replacement, not a merge.
8.2 Why FORM and not PLAY¶
FORM) is position-independent (a single, descriptive section at
the end of the document; it is not executed): it lends itself to
being declared at the setlist level, where only a reference to a song
exists.
PLAY) instead is positional/inline: its effect depends on where
it is placed among the datapacks (see neumaRk_play_and_form.md §2.1).
At the setlist level there is no position inside the song into which to
inject it, so PLAY) is not expressible as an entry override. The
form override is therefore always descriptive (FORM), never
executed: it does not alter what is executed, but what the musicians read as
the form.
8.3 Reference resolution¶
The [NAME] boxes of the item form resolve against the M) markers
of the entry's song (the snapshot that follows), with the same model
as neumaRk_play_and_form.md §3.1. A box that matches no marker is
reference broken: rendered as non-executed text, with no error or
warning (neumaRk_play_and_form.md §7.3). This allows informal
setlist forms.
Box diagnostics (W141 duration, W142 repeat, W143 keyword) remain
applicable; document-placement ones (W140 multiple FORM), W145
FORM) not at the end) do not apply to the item form.
9. Parsing rules¶
9.1 Split before musical parsing¶
The collection file is split into blocks at the nrk: lines before
any musical analysis. The song parser receives only the text from
one nrk: line to the next.
Consequence: the collection tokens (nrk-book: / nrk-playlist:,
name: / desc:, item:) live in the segments outside the blocks
and cannot collide with musical content.
9.2 Recognition¶
- first line
nrk-book:→ book collection; - first line
nrk-playlist:→ playlist collection; - first line
nrk:→ single song.
In the exchanged file nrk: is the first line of the song
(neumaRk_header.md §2); nrk-book: / nrk-playlist: are the collection's
alternative first-line tokens. They are distinct literal prefixes:
recognition is additive and unambiguous.
Inside a collection the nrk: line is what separates one song from the next, so
every song block must open with its own. A song written without nrk: after
another block is merged into the previous song, and the parser reports it
with W183.
9.3 Blank lines and versions¶
- Blank lines separate the collection header from the blocks and the
blocks from one another, consistent with datapack delimitation
(
neumaRk_datapack.md§1). - The
%%NAME … %%endblock (song versions,neumaRk_versions.md) remains internal to the single song block: it is text the song parser sees, not a collection token. The collection layer does not use%%.
10. Diagnostics¶
| Code | Description |
|---|---|
| W152 | item: line in an nrk-book: collection (books have no per-item overrides) |
| W153 | Unknown override key in item: (allowed: transpose / notes / form) |
| W154 | item: line not followed by a song block (nrk:) |
| W155 | Collection header directive (name: / desc:) after the first song block, or between item: and its block: ignored |
| W156 | Collection with no song blocks |
| W179 | Token without =value in item: (e.g. item: transpose=+2 capo) |
| W183 | Song block without its nrk: line: merged into the previous song (§9.2) |
| W185 | item: transpose= that is not a signed integer: override ignored (§6.1) |
10.1 Non-errors¶
- a snapshot block whose
FORM)is replaced by the itemform(§8.1); - an item
formbox[NAME]with no matching marker (reference broken, §8.3); transpose=+0(no-op) and emptynotes;- extra blank lines in the header or between blocks.
11. Examples¶
11.1 Playlist with overrides¶
nrk-playlist:0.6
name: Friday Gig
desc: trio set
item: transpose=+2
nrk:0.6
Blue Bossa (Kenny Dorham)
Cm 140bpm
Cm| Fm| Dm7b5| G7| Cm|
item: form=[Intro|4] [A|16]x2 [Solos] [A|16] [Outro]&fermata
nrk:0.6
So What (Miles Davis)
M) [A]
C) | D-7 | % |
M) [Solos]
C) | D-7 | % |
M) [Outro]
C) | D-7 |
The first entry performs Blue Bossa transposed +2; the second declares a performance form that replaces the song's own.
11.2 Book (no overrides)¶
nrk-book:0.6
name: My Real Book — Vol. 1
nrk:0.6
Autumn Leaves (J. Kosma)
…
nrk:0.6
All The Things You Are (J. Kern)
…
11.3 Single-song collection¶
nrk-playlist:0.6
name: Solo Spot
nrk:0.6
Naima (J. Coltrane)
…
It degrades transparently: a collection with a single block is valid.
12. Summary¶
| Concept | Syntax | Section |
|---|---|---|
| Book opening | nrk-book:<v> |
§3 |
| Playlist opening | nrk-playlist:<v> |
§3 |
| Collection header | name: / desc: |
§4 |
| Song block | nrk:<v> … (snapshot) |
§5 |
| Order | order of the blocks in the file | §5 |
| Entry override | item: key=value … (playlist only) |
§6 |
| Entry parameters | transpose / notes / form |
§6.1 |
| Entry form | form= (FORM grammar, rest-of-line) |
§6.2, §8 |
| Form replacement | item form replaces the song's FORM) |
§8.1 |
| Split | at nrk: lines, before musical parsing |
§9.1 |
| Portability | all snapshot; cover/tags/roles outside | §7 |
This document defines collections (books and playlists) as
neumaRk's portable container layer, built by reuse around the
song documents and the song form (neumaRk_play_and_form.md).