Skip to content

Latest commit

 

History

History
280 lines (226 loc) · 14.5 KB

commands.md

File metadata and controls

280 lines (226 loc) · 14.5 KB

Commands

dxn's commands are dxn <command> <file> ..., each working on a file written in dxn, the language of design and dimensions; language/guide.md teaches it and lists every diagnostic code. The usage block below is the same text that dxn help <command> and dxn <command> --help print, and a test keeps it in sync.

Global options

  • --dry-run makes attach, review and rename print the files they would write, without writing them.
  • -h, --help print the overview, or a command's usage when they come after a command.
  • -V, --version print {"version": "<version>"}.

Contents

check, fmt, states, tree, cases, validate, attach, status, review, rename

Usage

Usage: dxn <command> <file> [options]

dxn, the language of design and dimensions, which grows one concept at a
time: see docs/language/guide.md. A .dxn file declares enums, each a named
set of values; dimensions, each listing the values the environment varies
by; types with the dimensions they need, their states, rules for when a
state's value exists, a when for a state the world decides, and the
children they have; environments, each a product of dimensions; profiles,
each an instance of an environment; modifiers, accessories that change
some profiles; records, each a named group of typed fields; and
expectations, rules checked against the tree in place. A # starts a
comment, to the end of the line:

  # The wordmark's hover only exists with a mouse.
  enum Hover = rest | hovered
  dimension Pointer = mouse | touch
  type Wordmark needs Pointer {
    state hover: Hover
    hover = hovered only when Pointer = mouse
  }
  environment Device = Pointer
  profile Laptop: Device { Pointer = mouse }

Commands:
  check <file> [--expect <title>]    Parse and check a file; say what it declares,
                                     or report every problem it has. Warnings
                                     are printed, but do not fail. With
                                     --expect, run only the expectation with
                                     that title, and say whether it holds
  fmt <file>... [--check]            Write each file the one way a .dxn file is
                                     written, and name the files changed; with
                                     --check, write nothing, name the files not
                                     written that way, and fail if there are any
  states <file> <type>               Evaluate a type: the states it has in each
                                     profile, or without profiles under each
                                     combination of the dimensions it needs,
                                     as a Markdown table; or a child in place,
                                     given its path from a type, such as
                                     Toolbar.menu.toggle: where it is inside its
                                     parents, with the states they give it
  tree <file> [<type>]               Print the declared has tree of a type, or all
                                     containment roots when no type is named.
                                     Keep conditions and lists without evaluating
                                     state combinations; use --json for structure
                                     Use --identifiers to show child names too
  cases <file> <type>                List the cases a type, or a child in place,
        [--combinations]             has: those that can be told apart, each
                                     with what it covers where it covers more
                                     than one combination; with --combinations,
                                     every combination, as if nothing were
                                     alike
  validate <file>                    Check the stored records: each record's data is
                                     every JSON file in a folder named after it in
                                     kebab-case, next to the file, each a list of
                                     records with every field given, each of its
                                     type, and no others. Print what it checked, or
                                     every problem with its line, column and path
  attach <file> <path> --actor <name> --data <json> <key>=<value>...
                                     Record, as the actor, the record it records,
                                     for each combination the context's keys give
                                     (a|b lists several) that exists in place:
                                     --data gives its fields as JSON, and each
                                     PenNode's fingerprint is taken now, of its
                                     node or else its frame; a stored record for
                                     the same combination, actor and data is
                                     replaced; with --dry-run, say what it would
                                     write
  status <file> [--missing]          Count, for each record an actor records, the
                                     combinations of every element in the file's
                                     trees, in place, and those a stored record is
                                     about; with --missing, list the others
  review <file> [<type>] [--stale]   Write, for each tree and each record with a
                                     PenNode, a Markdown page of its combinations,
                                     each with its status and the picture of what
                                     was recorded, pictures/<node>.png beside the
                                     page; pages go in dxn's cache, outside the
                                     repository, and are named as they are
                                     written; with a type, only the trees it is
                                     in; with --stale, only what is stale or
                                     gone, on a page of its own
  rename <file> <name> <new>         Rename a declaration where the file uses it
                                     and where stored records name it, once both
                                     check: <name> as dxn writes it (Hover,
                                     Hover.rest, Toolbar.layout, Phone, ...;
                                     <kind>:<name> where one name names two), or
                                     <file>:<line>:<column> <new> by its place; a
                                     record's stored records move to the folder of
                                     its new name; with --dry-run, say what it
                                     would write

Options:
  --json                             Print one JSON document, for tools: the result
                                     and any warnings as "problems"; on a failure,
                                     the file and its problems; on a refusal or
                                     a usage error, {"error": "<message>"}, with
                                     any problems found before a refusal

Each command prints a readable answer by default, and one JSON document with --json. Every command prints the usage above with --help.

Commands

check

Says what a file declares, in one line, or prints each problem as <file>:<line>:<column>: <severity>: <code>: <message> and exits 1.

dxn check wordmark.dxn
dxn check wordmark.dxn --json

With --expect, it runs only the expectation with that title, written with or without its quotes, and says it holds, or reports why it fails. The rest of the file is still checked: an expectation cannot hold in a file with problems.

dxn check toolbar.dxn --expect "Escape closes the menu and returns focus to its button"

fmt

Writes each file the one way a .dxn file is written, as gofmt does for Go, and names the files it changed. There are no options: every file reads the same, and a diff shows a change to the model, not to its spacing.

  • Two spaces of indentation for each {; a line starting with } steps back, and one that goes on with |, and or or steps in one more.
  • One space between words and around =, -> and |; none before : or , and one after; none around . or +; none inside ( … ); one inside { … } on a line.
  • Comments kept as written; one after code, two spaces after it.
  • At most one blank line in a row, and none at the start of the file, after a { or before a }; line feeds, and one at the end.
  • Nothing reordered, joined or split. A file that does not parse is left alone, and its problems are reported.
dxn fmt toolbar.dxn
dxn fmt --check spec/*.dxn

With --check, it writes nothing, names the files that are not written that way, and exits 1 if there are any: for CI. The editor extensions format a file the same way when it is saved.

states

Prints a type's states in each profile or combination as a Markdown table; given a path from a type, a child's states in place.

dxn states wordmark.dxn Wordmark

tree

Prints the declared has tree of a type. With no type argument, prints all containment roots: types not placed by any other type. A shared type expands at each placement, showing only the type name by default. Use --identifiers to show identifier: Type labels. Nested types can be selected by their qualified names, such as Container.Inner; a nested declaration alone is not a has placement.

Conditions remain visible as only when expressions, and lists as [Type]. JSON retains placement names and paths, including tagged list members. This shows declared structure without filtering children by state combinations. The source must still pass normal language checks, including containment-cycle and expectation checks.

dxn tree docs/architecture/dxn-codebase.dxn ModifyDxnGrammar
dxn tree docs/architecture/dxn-codebase.dxn
dxn tree docs/architecture/dxn-codebase.dxn --identifiers
dxn tree docs/architecture/dxn-codebase.dxn ModifyDxnGrammar --json

With --json, returns file, trees, and problems. Each tree node has name, type, path, and children, with list and when when applicable. Text output separates roots with a blank line; a file with no types prints No types declared. and has an empty trees array in JSON.

cases

Lists the cases a type or a child in place has, those that can be told apart, with what each covers; with --combinations, every combination.

dxn cases button.dxn Button

validate

Checks every stored record, the JSON files in a kebab-case folder named after each record, next to the file; a problem in stored data also has its JSON path.

dxn validate evidence.dxn

attach

Records evidence for an element, by its path, in each combination the context's keys give, as an actor: the record that actor records, with the fields --data gives as JSON. Each PenNode field gets its fingerprint now, of its node, or of its frame when it has none; dxn status later tells, by it, whether the design still shows what was recorded.

dxn attach gazette.dxn Button --actor DesignAgent \
  --data '{"source": {"file": "gazette.pen", "frame": "IeCCz", "node": "uqEAm"}}' \
  style=primary interaction=pressed

status

Counts, for each record an actor records, the combinations of every element in the file's trees and those a stored record is about; --missing lists the others.

Stored records with errors are reported first, then set apart and said after the count, which counts every other stored record, as an editor's hints do; it then fails. A record none of whose stored records can be counted is said instead of a count. --json gives the problems and the counts together.

dxn status toolbar.dxn

review

Writes, for each tree and each record with a PenNode, a Markdown page to review its evidence by: a row for each combination, with its status as dxn status judges it, recorded, stale, gone or missing, and the picture of what was recorded. A stale row shows its drawing as it was when it was recorded, so it can be compared with the design as it is now. The pages go in dxn's cache, outside the repository: ~/Library/Caches/dxn/review/ on macOS, ~/.cache/dxn/review/ elsewhere, then the repository and the path of the record's folder in it. Each picture is pictures/<node>.png beside its page, or pictures/<frame>.png for a PenNode without a node; whoever attaches the evidence exports it there.

With a type, it writes only the pages of the trees the type is in: the one it is the root of, or those a type contains it in. With --stale, each page holds only what is stale or gone, the combinations whose evidence needs a decision, and is written beside the full one as <tree>.stale.md. A record made before its element gained a state or a dimension is outdated: each page lists it apart, with its picture and what it needs, and the --stale page includes it. A tree with nothing stale, gone or outdated gets no such page, and any from before is removed; dxn says so instead: Button: nothing is stale, gone or outdated.

dxn review gazette.dxn
dxn review gazette.dxn Button --stale
Wrote ~/Library/Caches/dxn/review/task-tree-1a2b3c4d/examples/gazette/pen-evidence/button.md

rename

Renames a declaration everywhere the file uses it, and everywhere stored records name it: in their contexts' paths, profiles, dimensions, parents and states, and in their fields. Renaming a record moves its stored records to the folder named after its new name.

A declaration is named as dxn writes it: an enum, a type, a dimension, a record, an environment, a profile or a modifier by its name, one declared inside a type by its full name (Menu.State), a value with its enum or dimension (Hover.rest, Breakpoint.sm), and a state, an action, an event or a child with its type (Toolbar.layout). Where one name names two, such as an event and an action, a kind before it says which (event:Menu.close). A name can also be given by its place in the file, as an editor does.

dxn rename evidence.dxn Hover.hovered over
dxn rename toolbar.dxn Toolbar.layout arrangement
dxn rename toolbar.dxn:96:9 arrangement
dxn rename toolbar.dxn Evidence Proof

A state that is provided is renamed with every state that receives it. The rename is refused, and nothing is written, when the file or the stored records do not check, before the rename or after it. An editor's rename, through the language server, refuses the same.