Expand description
Declarative cd policies for strict navigation levels.
Several levels teach one exact movement command (cd .., cd ../../.., cd -, an
absolute path) and must reject anything else. Hand-written hooks all repeated the same
steps, and each had to remember the anti-soft-lock contract. A CdPolicy states only
what the level requires; the engine performs the contract, so the guarantee is
structural instead of a convention every author has to re-implement.
A policy has two kinds of clause:
- scope (
CdPolicy::from_dir,CdPolicy::target) decides whether the policy has anything to say about this move. A move outside the scope is allowed silently. - rules (
CdPolicy::exact,absolute,source,after,within,rule) decide whether an in-scope move is acceptable. They are checked in the order they were added, and the first failing rule blocks the move with its own message.
§The contract
The shell asks twice per cd: once before the move, once after it succeeded.
- Before the move (
CdPolicy::pre_move): a move out of scope is allowed. A move that is lifted is allowed: the level’scdmarker exists (the player has already shown the command), or the move’s destination is the level’s start directory (the recovery move: without it one extra step could leave a player in a directory from which every permitted move leads further away). Otherwise the first failing rule blocks. The engine only returns the decision; printing the red panel andCD_RECOVERY_TIPis the UI’s job. - After a successful move (
CdPolicy::post_move): the level’scdmarker is recorded when the move was in scope, every rule passes (judged with the real destination) and, if the policy has anarrivedirectory, the player landed there. Evidence comes from scope, rules andarriveonly: lifting waives blocking but never grants or denies evidence, socd -back to level 2.2’s start directory (a lifted move) still counts. A move that failed in the shell records nothing, because the shell never reports it. on_moveruns after every successful move, lifted or not, in scope or not. A level that needs its own bookkeeping (the 1.9 walk home) uses it together withmanual_evidence.
Directories are compared with soft_canonicalize on
both sides, so a workspace below a symlink (macOS /tmp) and a destination that does not
exist yet both compare correctly.
Structs§
- CdMove
- One attempted (or completed)
cd, with everything a clause may need to judge it. - CdPolicy
- A
cdpolicy; see the module documentation for the contract.
Enums§
- CdDecision
- What to do about a
cdthat is about to happen.
Functions§
- policy
- Start an empty policy:
policy().exact("..", "Použijte přesně příkaz 'cd ..'.").