Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,45 @@ In this example:
- The first `...` in `src/` has a comment and there ARE unmentioned files (lib.rs, utils.rs) - represents omitted existing items
- The second `...` in `phases/` has a comment but phase-01-scaffolding.md is the ONLY file - represents future items that don't exist yet

### Limited Choice Expansions

To keep related paths together while avoiding duplication, a single guide entry may include a *choice list* written with square
brackets. For example:

```
- FooCoordinator[.h, .cpp] # Coordinates foo interactions
```

is equivalent to writing:

```
- FooCoordinator.h # Coordinates foo interactions
- FooCoordinator.cpp # Coordinates foo interactions
```

Each entry may contain at most one choice list and it expands into one concrete item for every option in the brackets. The same
comment is attached to every expanded item.

Choice lists follow these rules:

- Whitespace inside the brackets is ignored unless it appears inside a quoted string.
- An empty string may be included by leaving an empty slot (e.g. `[, .local]`).
- Use a backslash to escape individual characters (e.g. `\,` for a literal comma, `\ ` for a literal space, `\[` for a literal
`[` character).
- Surround complex values with double quotes to preserve punctuation or embedded brackets. Within quotes, escape `"` to include
a literal quote character.

**Examples:**

```markdown
- FooCoordinator[.h, .cpp] # expands to FooCoordinator.h and FooCoordinator.cpp
- Config[, .local].json # expands to Config.json and Config.local.json
- src[/main, /lib].rs # expands to src/main.rs and src/lib.rs
```

These expansions are intended for small sets of closely related alternatives—typically filename suffixes or prefixes—so that
the guide stays concise without sacrificing clarity.

### Ignoring Guides

You can mark a navigation guide to be ignored during verification by adding an `ignore` attribute to the opening tag:
Expand Down
23 changes: 20 additions & 3 deletions Specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,26 @@ Here are the rules of the above format, spelled out in much fuller detail:
- symlinks *may* be represented as files, or with the referred-to location (e.g. `- latest.a # symlink to latest build`)
- items *may* include a "comment" after the item, separated by a `#` character (it is *not* an error to include multiple `#` characters in a comment)
- we allow arbitrary whitespace between the path and the comment (e.g. `src/ # source code`)
- we allow arbitrary whitespace between the comment and the end of the line
- we *do not* enforce a specific ordering within the unordered list
- we *do not* require completeness (i.e. it's ok to omit files and directories)
- we allow arbitrary whitespace between the comment and the end of the line
- we *do not* enforce a specific ordering within the unordered list
- we *do not* require completeness (i.e. it's ok to omit files and directories)

Each list item may optionally contain a *single* choice list to represent a handful of alternatives without repeating the base
path. The syntax uses square brackets to enumerate the choices:

```
- FooCoordinator[.h, .cpp] # Coordinates foo interactions
```

This expands to both `FooCoordinator.h` and `FooCoordinator.cpp`, each inheriting the same comment. Choice lists obey the
following rules:

- At most one bracketed choice list per line.
- Whitespace inside the brackets is ignored unless it occurs inside a quoted string.
- Empty choices are allowed by leaving an empty slot, e.g. `[, .local]` expands to both `Config` and `Config.local` when combined
with a suffix.
- A backslash escapes individual characters inside the list (`\,` for commas, `\ ` for spaces, `\[` for literal `[` characters).
- Surround complex options with double quotes; escape double quotes inside with `\"`.

For example, every line of the following is valid:

Expand Down
9 changes: 9 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ pub enum SyntaxError {
#[error("line {line}: invalid path format '{path}'")]
InvalidPathFormat { line: usize, path: String },

/// Invalid wildcard choice syntax
#[error("line {line}: invalid wildcard choice syntax in '{path}': {message}")]
InvalidWildcardSyntax {
line: usize,
path: String,
message: String,
},

/// Invalid comment format
#[error("line {line}: invalid comment format - comments must be separated by '#'")]
InvalidCommentFormat { line: usize },
Expand Down Expand Up @@ -161,6 +169,7 @@ impl SyntaxError {
| Self::InvalidIndentationLevel { line }
| Self::BlankLineInGuide { line }
| Self::InvalidPathFormat { line, .. }
| Self::InvalidWildcardSyntax { line, .. }
| Self::InvalidCommentFormat { line }
| Self::AdjacentPlaceholders { line }
| Self::PlaceholderWithChildren { line } => Some(*line),
Expand Down
Loading