pub struct ProjectConfig {Show 14 fields
pub dialect: Option<Dialect>,
pub types: Option<TypePolicy>,
pub lints: BTreeMap<String, LintLevel>,
pub deny_warnings: Option<bool>,
pub fix: BTreeMap<String, FixPolicy>,
pub unprune_dirs: Vec<String>,
pub indent: Option<u8>,
pub drafts: Vec<String>,
pub prose_dialect: Option<ProseDialect>,
pub prose_enable: Option<bool>,
pub prose_dictionary: Vec<String>,
pub conventions: Option<String>,
pub dialogue: Option<DialogueConfig>,
pub entry: Option<String>,
}Fields§
§dialect: Option<Dialect>[project] dialect, if set.
types: Option<TypePolicy>[project] types, if set.
lints: BTreeMap<String, LintLevel>[lints] per-code severity overrides, keyed by the raw code string
as written in the file (e.g. "E063") — this crate doesn’t validate
codes against the real DiagnosticCode set (#1234 dependency-free
constraint); resolving unknown/non-overridable codes is
brink-analyzer’s job. Sorted (BTreeMap) for deterministic
iteration.
deny_warnings: Option<bool>[lints] deny-warnings, if set.
fix: BTreeMap<String, FixPolicy>[fix] per-code policy overrides (docs/autofix-spec.md §6.1, issue
#3419), keyed by the raw code string as written in the file — this
crate doesn’t validate codes against the real DiagnosticCode set,
same as Self::lints. A code absent from this map resolves to
FixPolicy::Ask via Self::effective_fix_policy, never to a
default invented at the call site. Sorted (BTreeMap) for
deterministic iteration.
unprune_dirs: Vec<String>[project] unprune-dirs, if set: directory names discovery must not
prune, layered on top of the standing
brink_source_tree::IGNORED_DIR_NAMES policy (issue #1407’s escape
hatch). Empty (the default) means “the standing policy applies with
no override” — same “unset means untouched” convention as lints.
Raw strings as written in the file; a name outside
brink_source_tree::IGNORED_DIR_NAMES parses fine (this crate
stays dependency-free of anything beyond brink_source_tree, and
there is nothing wrong in principle with naming a directory that
isn’t pruned in the first place) but is a no-op, so parse_str_at
warns about it rather than silently accepting a likely typo (e.g.
"node-modules" instead of "node_modules").
indent: Option<u8>[project] indent, if set: the number of spaces one indent level
occupies. THE single source for indentation across the project
(decision log 2026-08-27) — the formatter emits it, the editor’s
indentUnit adopts it, and the indent guides position against it.
No component may keep its own default, because the failure mode is
disagreement: a formatter writing four spaces while guides are drawn
every two looks like a rendering glitch rather than a config
mismatch, and the author cannot tell which component is wrong.
None means unset — callers apply DEFAULT_INDENT.
drafts: Vec<String>[project] drafts, if set: path globs (see globs) naming
work-in-progress the author has deliberately not wired into the story
— scratch scenes, cut material, notes.
A match here is only HALF of draft status. Ruled 2026-08-27
(“reachability wins”): a file is a draft when it matches one of these
globs and is not reachable from the entry. A marked file the entry
still INCLUDEs is not a draft at all — it compiles normally. That is
deliberately a deleted state rather than a diagnosed one: draft status
can then never exclude a file the story actually reaches, so it can
never break a divert. This crate carries only the glob half, because
reachability is the compile closure’s answer and lives in the analysis
roads; see EditorSession::draft_paths for the conjunction.
Empty (the default) means no file is ever a draft.
prose_dialect: Option<ProseDialect>[prose] dialect, if set. None means unset — callers apply
ProseDialect::default.
prose_enable: Option<bool>[prose] enable, if set: whether prose checking runs at all.
Its own key rather than “unregister the checker”, because those are
different decisions by different people: an embedder decides whether
the engine is available at all (it is a separate 6.5 MB module), and
this decides whether a project that has it wants its prose checked.
None means unset — callers apply their own default.
prose_dictionary: Vec<String>[prose] dictionary — the author’s own word list: place names,
in-world jargon, a character who is never a cue.
In brink.toml rather than a sidecar because a character’s name is a
fact about the manuscript, not about one machine — so it is shared by
collaborators and survives a fresh clone (decision log, “Spellcheck:
prose only, squiggles always, dictionary in brink.toml”).
Empty and absent are the same thing here, unlike the two options above: there is no behaviour a project could want from “declared but empty” that it does not get from “absent”.
conventions: Option<String>[project] conventions, if set (docs/prose-dialect-spec.md §3.4’s
pointer mechanism): either a built-in preset name ("screenplay")
or a project-relative path to a .brink conventions module
("conventions.brink", "scenes/conventions.brink"). This crate
only carries the raw string — it doesn’t know the closed preset-name
set or validate the path exists, for the same dependency-free
reason lints doesn’t validate codes (#1234); resolving it (and, if
it names a project path, checking that pattern-claiming handlers
only live in that one file, issue #1844’s confinement rule) is
brink-analyzer/brink-db’s job.
Renamed from elements by issue #2180 (the key predates the split
of @[element] from @[convention], docs/decision-log.md’s
2026-08-03 ruling, and now names a module of the latter, not the
former). parse_str_at still accepts the old [project] elements
spelling as a deprecated alias — see its own doc comment for the
precedence/warning rules — but every in-memory representation past
parsing uses only this field; there is no separate elements field
to keep in sync.
dialogue: Option<DialogueConfig>[dialogue] (or the string form dialogue = "path.json"), if the
file declares one — see DialogueConfig. None = no dialect.
entry: Option<String>[project] entry, if set (issue #2331, ruled 2026-08-07 “[project] entry beats mountStudio’s entryFile”): a project-relative path
naming the project’s entry file (e.g. "story.ink",
"chapters/main.brink"). Same shape as Self::conventions — this
crate only carries the raw string, without checking the path exists
or resolving it against a real project tree (kept dependency-free,
#1234); that is each mount’s own job (e.g. ProjectSession in
packages/ink-editor/src/project-session.ts, which knows the
project’s actual file set).
The ruling: when both this key and a host’s own entry-file argument
are present, this key WINS — the host argument is only the fallback
for a configless project (one with no brink.toml, or a
brink.toml that doesn’t set entry). Unlike dialect/types,
there is no “explicit API call always wins” precedence tier here:
the host argument was never an explicit override API in the first
place, just a constructor-time default that had nowhere better to
come from before this field existed.
Implementations§
Source§impl ProjectConfig
impl ProjectConfig
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
True if the file set nothing at all (an all-default/empty
[project]/[lints] table, or neither table present).
Sourcepub fn effective_fix_policy(
&self,
code: &str,
app_ceiling: Option<FixPolicy>,
) -> FixPolicy
pub fn effective_fix_policy( &self, code: &str, app_ceiling: Option<FixPolicy>, ) -> FixPolicy
The effective [fix] policy for code (docs/autofix-spec.md §6,
issue #3419): the project’s own [fix] entry (or FixPolicy::Ask
when it doesn’t mention code), narrowed by an optional app-scope
app_ceiling (§6.2, TENTATIVE ruling) — a personal “how far may the
editor go on save” setting the host passes in, kept in the same
FixPolicy space.
app_ceiling only LOWERS the result, never raises it past what the
project allows: None means “no app opinion”, so the project entry
alone decides. This is the one function §6.2 asks to keep singular so
the still-tentative ceiling relationship can change in one place.
This crate doesn’t validate code against the real DiagnosticCode
set (dependency-free, #1234, same split as Self::lints) — an
unknown code resolves through the same default/ceiling math as a real
one here; surfacing “this code doesn’t exist” as a diagnostic is a
downstream crate’s job, the same as [lints]’s validate_lint_code.
Trait Implementations§
Source§impl Clone for ProjectConfig
impl Clone for ProjectConfig
Source§fn clone(&self) -> ProjectConfig
fn clone(&self) -> ProjectConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ProjectConfig
impl Debug for ProjectConfig
Source§impl Default for ProjectConfig
impl Default for ProjectConfig
Source§fn default() -> ProjectConfig
fn default() -> ProjectConfig
impl Eq for ProjectConfig
Source§impl PartialEq for ProjectConfig
impl PartialEq for ProjectConfig
impl StructuralPartialEq for ProjectConfig
Auto Trait Implementations§
impl Freeze for ProjectConfig
impl RefUnwindSafe for ProjectConfig
impl Send for ProjectConfig
impl Sync for ProjectConfig
impl Unpin for ProjectConfig
impl UnsafeUnpin for ProjectConfig
impl UnwindSafe for ProjectConfig
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.