rokdocs
v0.1

9.1. rokc CLI interface

This section defines the command-line interface of the compiler rokc. The toolchain consists of three binaries.

BinaryRole
rokcCompiler (the counterpart of rustc). Contains build, run, test, formatter, linter, REPL and LSP (this section)
rokCargo-style front-end. Owns the manifest, dependencies, environments and toolchain pin, and invokes rokc (9.10)
roklsLSP server executable for editors. Equivalent to rok lsp

The runtime is librokr.a (rokr). There are no separate tools (rok-fmt etc.). rokc does not resolve dependencies; dependency packages are passed by rok via --extern (9.2.3).

9.1.1. General form

rokc is invoked in the following general form.

rokc <subcommand> [options] [args]

As grammar rules:

cli_invocation  ::= "rokc" subcommand option* arg*
subcommand      ::= "build" | "emit" | "run" | "test" | "bench" | "check"
                  | "fmt" | "lint" | "doc" | "repl" | "jupyter" | "lsp"
                  | "clean" | "profdata" | "bindgen" | "demangle" | "rokhir-text" | "inspect" | "version" | "help"
option          ::= "--" identifier ("=" value)?
                  | "-" letter

--name value is equivalent to --name=value. Global options (9.1.5) may appear before or after the subcommand.

AreaSubcommands
Build / runbuild, emit, run, test, bench, check
Packageclean
Toolsfmt, lint, doc, lsp, profdata, bindgen
Interactiverepl, jupyter
Debug / diagnosticdemangle, rokhir-text, inspect
Otherversion, help

Package selection (path)

The [path] of build / run / test / check / clean is one of the following. If omitted, it is the current directory.

pathPackage
Package directoryThat directory. If it has no src/main.rok or src/lib.rok, the search moves upward (9.2.2)
File in a package's src/That package: the first directory containing src/main.rok / src/lib.rok, walking upward from the file
Any other fileAn anonymous executable package consisting of that single file (4.16.8), including a .rok file in a package directory outside its src/

It is an error if a directory is given and no package is found walking upward. An anonymous package's file submodules (mod foo;) are beside its file (4.16.8).

The package name (the output name) is the name of the package directory; for an anonymous package it is the file name without .rok.

9.1.2. Core subcommands

rokc build: AOT build

rokc build builds a package AOT.

rokc build [path]

[path] follows the package selection rules above. Output is placed in the per-profile target/ of 9.2.15. src/main.rok produces target/<profile>/<name>; src/lib.rok produces target/<profile>/lib<name>.a plus the interface target/<profile>/<name>.rokhir (9.4); a package with both produces both. The profile is release for -O2 / -O3 / -Os (including --release) and debug otherwise; with --target=<target> the directory is target/<name>/<profile>/. If --target-dir=<dir> or ROKC_TARGET_DIR is set, that directory is used instead of target/.

Options:

  • --release performs an optimized build (equivalent to -O2) in the release profile; the default is a debug build (-O0) in the debug profile. The profiles differ as 9.2.15 describes.
  • --target-dir=<dir> relocates target/ (equivalent to ROKC_TARGET_DIR).
  • --extern <name>=<dir | src/lib.rok | <name>.rokhir | lib<name>.a> mounts one dependency package at the top-level path name (9.2.3). Source (dir / src/lib.rok) is compiled together in the same build; a prebuilt package (.rokhir / .a; given one, its sibling is located) has its ROKHIR read and its archive linked. May be given multiple times and is normally filled in by rok. name is an identifier: the package name with - replaced by _ (9.10.3). rok is reserved for the standard library: --extern rok=.. is a usage error, and a library package named rok is rejected. So are a keyword and a path start (pkg, sup), as name and as the name of a library or of a package with one (9.10.3).
  • --extern-feature <name>=<f> builds the source dependency name with cfg(feature = "<f>"). Repeatable, one per feature. A dependency sees only these: the feature keys of --cfg belong to the package being compiled. Normally filled in by rok.
  • --name <n> sets the package name (naming rules of 9.10.3). The outputs are lib<n>.a / <n>.rokhir and the mount name is the name with - replaced by _. The default is the directory name. --extern a-b=.. is likewise bound as a_b.
  • --bootstrap <file> gives a standard library root to preload (may be repeated); --rokr <lib> gives the runtime to link. The defaults are the sysroot's lib/rok/{core,std,bare}/src/lib.rok and lib/librokr.a (9.2.19). A bootstrap root's tier is the name of the directory above its src/; given core/src/lib.rok without a bare root, bare/src/lib.rok beside it is loaded too. If not found, it is an error that lists the paths searched.
  • -O0 / -O1 / -O2 / -O3 / -Os select the optimization level explicitly. -O0 uses the native backend, the others the MLIR → LLVM backend (9.2.10).
  • --target=<target> selects the target platform: a built-in name such as the 15 Tier 1 targets of Platform targets, or a <name>.rokon target specification file (0.6.5). Any target can be built from any host (0.2.4).
  • -L <dir> adds a library search directory for #[link] (5.9.9), searched before LIBRARY_PATH. May be repeated.
  • -l [static=|dylib=]<name> links the library <name> (searched like #[link]), and --native-runtime <file> names a shared library to ship beside the executable (9.2.14). Both may be repeated; rok passes them for native packages (9.10.4b).
  • -o / --out=<path> selects the output location.
  • --cfg <flag> / --cfg <key>=<value> sets a cfg flag for conditional compilation. May be repeated.
  • --emit=<kind>[,<kind>..] writes intermediate output (ast, hir, mir, mlir, llvmir, asm, obj, expanded) to target/<profile>/build/<name>.<ext> (9.9.1). Several kinds may be given at once separated by commas; in that case -o cannot be used. With --emit, no executable or archive is produced.
  • --load-mlir-plugin <path|name> loads an MLIR dialect plugin, --load-mlir-pass-plugin <path|name> loads a pass plugin (both into rokc's MLIR; built against the same pinned LLVM, on Windows linked against rokc.exe's import library), and --mlir-pass <pass> runs that pass before conversion to the LLVM dialect (rok::bare::mlir::plugin). All may be repeated, and rok passes them through unchanged.
  • -g adds debug information to a release profile build: DWARF, or CodeView in a PDB for Windows targets (9.9.6). A debug profile build always has it.
  • -C overflow-checks[=yes|no] turns overflow checks (panic) for fixed-width integer arithmetic on or off. The default is on only at -O0. An omitted value means yes. Operations on constant operands that cannot overflow skip the check.
  • -C backend=native|llvm overrides the backend the optimization level selects (9.2.10).
  • -C target-cpu=<cpu>|native targets that CPU instead of the triple's baseline (0.6.4); native is the CPU of the build machine. -C target-feature=+f1,-f2,.. turns individual features (+avx2, ...) on or off. The resulting binary may not run on CPUs without them. With the native backend (-O0) the options are noted (a warning) and code is built for the baseline. native is accepted only when the target is the host platform.
  • -C subsystem=console|windows selects the Windows subsystem: console (default, mainCRTStartup) or windows (GUI, WinMainCRTStartup; 9.5.9).
  • -C profile-generate[=<dir>] instruments the program and its source dependencies for profile-guided optimization. Running it writes a raw profile <dir>/default_%m.profraw (default <dir>: the working directory at run time; LLVM_PROFILE_FILE overrides the path). An instrumented executable links the profile runtime the toolchain ships for the target (9.2.19). Not supported for wasm32-unknown-unknown (no file system).
  • -C cs-profile-generate[=<dir>], with -C profile-use, instruments again after inlining (context-sensitive); merging its runs with that profile gives the one profile -C profile-use reads.
  • -C profile-use=<file> optimizes with an indexed profile from rokc profdata merge. A missing file is an error. Functions whose control flow changed since the profile was recorded are optimized without it, and one warning gives their count.
  • Both select the MLIR → LLVM backend at every level, and with them -C backend=native is an error. The standard library is compiled with the program (not taken from the cache), so it is profiled and optimized too. The REPL rejects both.

rokc build reports the package's lint diagnostics as rokc check does (6.2.9): warnings are printed and the build goes on; a deny lint fails it. If nothing has changed since the previous build, rokc build / rokc run print Fresh, print that build's warnings again, and skip the build (9.2.16).

rokc profdata merge: profile merge

rokc profdata merge [-o <file>] <file | dir>...

Merges raw (.profraw), indexed (.profdata) and text (.proftext, LLVM's text profile format) profiles into one indexed profile (default default.profdata) for -C profile-use. A directory stands for those files in it; empty raw profiles are skipped. It runs in process. Merge warnings (counter overflow, mismatched counters) are reported and the merge still writes its output.

rokc profdata show: profile summary

rokc profdata show [--all-functions] [--topn N] <file>

Prints a summary of a profile in llvm-profdata show form: the instrumentation level and the number of functions shown and in total. --all-functions adds each function's hash and counters; --topn N lists the N functions with the largest internal block counts.

rokc emit: intermediate output

rokc emit [path] [--emit=<kind>[,<kind>..]]

Equivalent to rokc build --emit=... If --emit is omitted, it is mlir.

rokc run: build and run

rokc run runs the output immediately after building.

rokc run [path] [-- args...]

It builds an executable package and runs it at once; arguments after -- are passed to the executable unchanged. Options are the same as rokc build. A library package has nothing to run, so it is an error.

A package is built to target/<profile>/<name>; an anonymous package (single file) is built in a temporary directory, so no target/ is created next to the file. rokc build <file>.rok builds even an anonymous package into target/.

rokc run hello.rok -- arg1 arg2

The exit code of rokc run is the exit code of the program. If the program terminates by signal n, it is 128 + n.

rokc test: tests

rokc test collects test functions and builds the test harness; rok test (9.10) runs it.

rokc test [path] [filter]

It collects functions marked #[test] and builds a test executable (the harness). #[test] implies #[cfg(test)] (6.2.5), so test functions are not part of a normal build. Tests are collected both from src/ (under #[cfg(test)]) and from the tests/ directory (0.3.5). A test build uses an entry point that selects tests instead of the package's entry point.

rokc does not run the harness. --emit-harness <file> writes the built executables and the tests in them - the manifest rok test runs - to <file>; without it the built executables are named on standard error. Running the harness (selecting tests, the process isolation, parallelism and reporting below) is the rok test runner (9.10).

If there is a single argument and it is not an existing path, it is taken as filter. filter matches the test name including its module path (math::adds).

  • It is a small regular expression using ^ $ . * + ? and \ escapes. The search is unanchored, so without ^ / $ it may match any part of the name.
  • Without these characters it is equivalent to a plain substring search.

Each test runs in its own process. If a test panics (exit code 101) or ends with an uncaught error (exit code 1), only that test fails and the rest keep running. Termination by signal is also a failure.

Options are the same as rokc build, plus two more:

  • --threads=N sets the number of test processes run concurrently. The default is ROKC_NUM_JOBS, or the CPU count if that is unset.
  • --show-output also shows the stdout / stderr of passing tests. Output of failing tests is always shown.

Output goes to stdout in the following form.

running 3 tests
test math::adds ... ok
test math::subs ... FAILED
test util::trims ... ok

failures:

---- math::subs ----
<stdout / stderr of that test>
(panicked (exit 101))

failures:
    math::subs

test result: FAILED. 2 passed; 1 failed; 0 filtered out; finished in 0.12s

If any test fails, the exit code is 1.

In a package with both root files, the library's tests run first, then the executable's (built against the library without its tests); a failing library run ends the command. run and bench work the same way.

rokc bench: benchmarks

rokc bench [path] [filter]

Collects functions marked #[bench] and builds them in an optimized build (-O2 unless -O is given); rok bench (9.10) runs the harness and measures them (9.9.11). Like #[test], #[bench] implies #[cfg(test)], and benches are collected both from src/ and from the benches/ directory (0.3.5). The path, filter and --emit-harness rules are the same as rokc test.

A benchmark takes a Bench handle and times a closure, so setup stays out of the measurement:

#[bench]
fn parse_1kb(b: Bench) {
    let input = sample(1024);               // setup: run once, not timed
    b.bytes(1024);                          // optional: report throughput
    b.iter(|| parse(black_box(input)));     // the timed region
}

b.iter(f) performs the whole measurement (calibrate, warm up, sample); its result is black-boxed. black_box (rok::core) is an identity the optimizer cannot see through - apply it to the inputs and result of the timed region so the work is neither hoisted out nor folded away. b.bytes(n) / b.items(n) add a throughput column. Bench, black_box and the statistics are library API; the method is defined in 9.9.11.

  • --iters=N fixes the number of calls per sample instead of calibrating.
  • --samples=N is the number of samples measured (default 100).

Benchmarks run one at a time. Terminal output is one aligned line per benchmark, in human units; when stdout is not a terminal a stable machine form is written for regression tools.

  json::parse_1kb     1.84 us +/- 0.03 us   543 MiB/s   [2 outliers]

rokc repl: terminal REPL

rokc repl launches an interactive shell in the terminal.

rokc repl [path]

This mode runs as a terminal interactive shell. Cell semantics follow the rules of 9.7.0: each cell runs exactly once, top-level let bindings and items carry over to later cells, and a failed cell leaves no trace in the bindings. An expression cell prints type: value.

  • The default mode compiles each cell with the native backend and hands the code to a JIT host process that lives for the session; the host loads it and runs it once (9.6). Bindings, static state and any values carry over between cells. A binding whose type cannot be named at top level (closures, private types, etc.) is rejected when created.
  • Diagnostics and panic locations name <repl>:line:col over the cell's own text.
  • Input has line editing and history; the history persists in $ROK_HOME/repl_history.
  • Without a path the session starts empty. A program path (a lone .rok file or a package with src/main.rok) is loaded and run, top-level statements as cells and fn main as the entry, and the session continues (9.7.10). A library package path (src/lib.rok) is added as a dependency and use <name>::*; is the first cell, again after :reset.
  • More than one path is a usage error. - is not accepted; standard input is the cell input.

A package with both root files is a program path; its library is a dependency of the session. rok and rok repl (9.10) run the same REPL with dependencies attached.

REPL commands (:type, :reset, :add, :help, :quit) and debugging aids are in 9.9.9.

rokc jupyter: Jupyter kernel

rokc jupyter provides the kernel mode invoked by Jupyter.

rokc jupyter [--connection-file <path>]

This command is the kernel mode invoked by Jupyter, so users do not run it directly. --connection-file takes the path of the ZMQ connection file provided by Jupyter, and build options such as --extern are accepted as well. The kernel runs on the same cell session as the REPL (9.7.0). To run with dependencies resolved, use rok jupyter --connection-file <path> (9.10). Integration details are defined in Jupyter integration.

The kernel is registered by rok jupyter install [--env <name>] (9.8.3).

rokc fmt: formatter

rokc fmt applies the standard format.

rokc fmt [path]

[path] accepts files or directories (several allowed; the current directory if omitted) and rewrites them in place to the standard format. A directory that is a package (9.2.2) is formatted as its src/ and tests/ directories and its rok.rokon; other files in it are left alone. Directories are searched recursively for .rok files, skipping target/ and directories beginning with .. .rokon files (ROKON) are checked for being ROKON and only re-indented (they are not rewritten in canonical form, so comments are preserved).

Options:

  • --check does not modify files; it prints the files that would change and their diff. If any file would change, the exit code is 1; suitable for CI.
  • --diff does not modify files and prints only the diff.

A file with lexical errors is left untouched and the error is reported, with exit code 1.

rokc check: diagnostics

rokc check [path] [--check-library]

Runs the front end through type checking and MIR building, plus lints, and reports diagnostics. No code generation (no MLIR) is performed. Options are the same as rokc build. --check-library lowers and checks every body of a library regardless of reachability, and checks every generic body against its bounds (2.10.9). A package with both root files checks its library, then, if the library has no error, its executable with the library compiled in; each warning is reported once.

rokc lint: linter

rokc lint [path] [--list]

rokc check without code generation. Every compiling command reports the same lints (6.2.9); lint runs only them and the front end. The diagnostic format is 9.1.8; lint diagnostics have code E503. The list of lints and groups is in 6.2.9. --list prints the lints, groups and default levels.

Lint levels are set by the global options -A / -W / -D (9.1.5) and by attributes in code. If any deny-level lint fires, the exit code is 1.

rokc doc: documentation generation

rokc doc [path] [--std]

Generates HTML API documentation in target/doc/ from the public items and docs (///, //!, #[doc], 6.2.8) of the package's library (its executable when it has none) (and --extern dependency packages).

target/doc/
├── index.html                 # package list
├── <pkg>/<mod>/index.html     # one page per module
└── search-index.js            # search index

--std also documents the standard library tiers into rok-core/, rok-std/, rok-bare/; without a path it documents only them, into ./target/doc/.

Doc text is interpreted as a subset of markdown (headings, fenced code blocks, inline code, links, **bold**, lists, paragraphs).

rokc lsp: LSP server

rokc lsp runs in Language Server Protocol server mode.

rokc lsp

This mode is designed to be invoked from LSP clients such as VS Code, Vim and Emacs. The standalone editor binary rokls is equivalent to rok lsp (that is, rokc lsp). .rokon buffers are checked for syntax only. In a package with both root files, a file the library's module tree reaches is checked as part of the library, any other as part of the executable, which sees the library's open buffers. The features are listed in 9.9.13.

9.1.3. Debug / diagnostic subcommands

rokc bindgen: C header bindings

rokc bindgen <header> [--target <t>] [-o <file>] [-- <clang args>]

Writes the declarations of std 1.7.6 for <header> to standard output (or to -o <file>). Without the toolchain's libclang (9.2.19) it is an error (exit 1) naming where it looked.

rokc demangle: symbol demangle

rokc demangle decodes mangled symbols into a human-readable form.

rokc demangle <symbol>...

For each symbol it prints a block in the 9.5.4 format, separated by blank lines (9.9.3). If any argument is not a rok symbol, the exit code is 1.

rokc rokhir-text: ROKHIR text output

rokc rokhir-text prints the ROKHIR of a prebuilt library as text.

rokc rokhir-text path/to/foo.rokhir      # or libfoo.a - reads the sibling foo.rokhir

It prints the header fields, producer, meta and interface files; the format is described in ROKHIR format.

rokc inspect: package inspection

rokc inspect gives an overview of an archive's contents.

rokc inspect path/to/libfoo.a        # or foo.rokhir

It shows the package name and hash, rokc version, ROKHIR version, GC type id range, exports, generic items, and archive members with their sizes (9.9.14).

9.1.4. Auxiliary subcommands

rokc clean: remove build output

rokc clean removes build output.

rokc clean [path]

Deletes the package's whole target/ directory (including all profiles and cross builds; the --target-dir / ROKC_TARGET_DIR directory if set). Does nothing if it does not exist.

rokc version: version

rokc version
rokc --version            # = -V
rokc -V -v                # adds host line

Prints one line rokc <version> (<commit> <date>) to stdout. With -v, host: <triple> and llvm: <version> lines are appended.

rokc --print cfg: active cfg

rokc --print cfg [--target=<target>] [-O<n>] [--cfg ..]

Prints the cfg of the build the options describe (6.3), one per line: a flag as flag, a key as key="value" (as rustc does). The keys include target_env, and debug_assertions is set at -O0.

debug_assertions
target_arch="aarch64"
target_endian="little"
target_family="unix"
target_os="macos"
target_pointer_width="64"

rokc --print target-list / target-spec: targets

rokc --print target-list
rokc --print target-spec [--target=<target>]

target-list prints the built-in target names, one per line. target-spec prints the target's specification as ROKON (0.6.5); without --target, the host's.

rokc --print lldbinit: lldb formatters

Prints one line, command script import '<path>', that loads the lldb formatters of this toolchain (9.9.6): <sysroot>/lib/rok/lldb/rok_lldb.py.

rokc help: help

rokc help [subcommand]
rokc <subcommand> --help

Given a subcommand, shows the help for that command.

9.1.5. Global options

The global options are listed below. They may appear before or after the subcommand.

OptionMeaning
--verbose / -vShow per-phase timing (9.9.5)
-vvMore detailed logging: Reading <file> and Specialized <path>(sig) lines (9.9.5)
--quiet / -qDo not print progress lines (diagnostics are still printed)
--color=auto|always|neverColored diagnostic output
--no-colorEquivalent to --color=never
--cwd=<path>Change working directory before running
--print cfg|target-list|target-spec|lldbinitPrint the active cfg, the built-in target names, a target's specification, or the lldb command loading rok's formatters (9.1.4)
--message-format=human|jsonDiagnostic format. json writes one line per diagnostic to stdout (9.1.8)
-A / -W / -D <lint | group>Lint level (--allow / --warn / --deny). Applies to every command that compiles the package (build, run, test, bench, emit, check, lint, lsp). May be repeated; the later one wins

The lint level is determined in the order: the lint's default level < -A / -W / -D < #[allow(..)] / #[warn(..)] / #[deny(..)] in code (innermost wins). rok prepends the manifest's lints as these flags (9.10.1).

--color=auto (the default) uses color when stderr is a terminal and the environment variable NO_COLOR is not set.

Examples:

rokc --verbose build
rokc test -q
rokc --cwd=examples/hello run

9.1.6. Exit codes

Exit codes are defined as follows.

CodeMeaning
0Success
1User code error (compile error / test failure, etc.)
2Usage error (invalid option, unknown subcommand, etc.)
101rokc internal error (panic)

rokc does not read ROK_HOME (the sysroot is relative to the executable). If rokc itself panics (internal compiler error), it prints a message and exits with 101. rokc lsp, rokc repl and rokc jupyter survive it: the language server reports it as an error diagnostic of the analyzed buffer, the REPL / kernel fails that cell (9.7.5); both keep serving. rokc run exits with the exit code of the program it ran (9.1.2).

If standard output or standard error is a pipe whose reader has gone, rokc stops without a message: on Unix it is terminated by SIGPIPE (a shell reports 141); on Windows it exits with 1. This is not an internal error.

9.1.7. Environment variables

The environment variables that affect rokc are:

VariableMeaning
ROK_CCOptional C compiler driver that performs the final link instead of the embedded lld (9.2.14)
ROK_BACKENDnative or llvm; same as -C backend=
ROKC_VERBOSEEquivalent to --verbose
ROK_TIME_PASSESPer-pass wall time on stderr when 1 (9.9.5)
LLVM_PROFILE_FILERead by instrumented programs (-C profile-generate): the raw profile path
ROKC_TARGET_DIRLocation of target/ (default: inside the package)
ROKC_INCREMENTALWhere the front end keeps the package's parses and lowered bodies (default target/<profile>/incremental/; 0: nowhere); the library's collected items are kept in lib/rok-cache/library/ (9.2.16)
ROKC_INCR_VERIFY1: lower every body again and fail on a difference (9.2.16)
ROKC_NUM_JOBSDefault for rokc test --threads (CPU core count if unset)
NO_COLORIf set, --color=auto does not use color

An unset or empty variable has its default. A value outside those listed prints one warning line on stderr naming the variable, the value and the accepted values, and the variable has its default.

9.1.8. Output format

Diagnostic messages

Diagnostic messages are printed in the following format.

error[E100]: cannot find value `count` in this scope
  --> src/main.rok:5:13
   |
 2 |     let counter = 0;
   |         ------- similar name defined here
...
 5 |     let x = count + 1;
   |             ^^^^^ not found in this scope
   |
   = help: did you mean `counter`?

Diagnostics use the file + line + column units defined in Source files.

The header is <severity>[<code>]: <message> and --> path:line:col gives the primary location. The primary span is underlined with ^, secondary spans with -; a secondary span in another file is introduced by ::: path:line:col. Trailing = note: lines add context and = help: lines suggest a fix.

Build progress

Progress is shown on stderr with right-aligned verbs. Nothing is printed with -q.

   Compiling foo (path/to/foo)
    Building target/debug/foo
    Finished in 1.23s
     Running `target/debug/foo`
VerbWhen
CompilingFront end starts (package name and directory)
BuildingExecutable / archive produced (build)
WroteOne --emit output written
FinishedBuild done (elapsed time)
RunningProgram run (run)
CreatedPackage created (new)
Removedtarget/ deleted (clean)

JSON output (for tool integration)

For tool integration, output can also be produced as JSON.

rokc build --message-format=json

In this mode each diagnostic becomes one line of JSON object on stdout, easy for IDEs and CI tools to parse. The shape of the object is defined in 9.9.4.

9.1.9. Standard input

Writing - in an argument position, as in rokc check -, means standard input, for use with pipes or scripts. Source from standard input is checked as the main.rok of an anonymous executable package.

9.1.10. Compatibility with external tools

rokc is a low-level compiler; dependency resolution is the job of the front-end rok (9.10). rok invokes rokc, passing the roots of resolved dependency packages via --extern (9.2.3). Other build systems may integrate by invoking rokc directly in the same way. Changes that break CLI compatibility are managed under SemVer rules.

9.1.11. Standard format (rokc fmt)

The standard format of rokc fmt is a token-preserving layout rule. It does not change tokens or comments within a line; it only sets line indentation and blank lines. rokc fmt has no configuration by design: there is one standard format for all rok code.

  1. Indentation is 4 spaces per bracket (( [ { #[) depth. A line beginning with a closing bracket takes the depth of the line that opened it. Tabs become spaces.
  2. A continuation line, i.e. one whose preceding token is not ; , or a bracket (such as a line splitting a long expression), keeps the amount by which it was indented beyond the block indentation in the original file.
  3. Trailing whitespace is removed.
  4. Consecutive blank lines are collapsed to one, and blank lines at the start of the file are removed.
  5. The file ends with exactly one newline.

The formatter does not move tokens between lines, does not split or join lines, and does not change spacing within a line. Comments therefore stay exactly as written and the token sequence is unchanged. The interior of multi-line strings and block comments is also left as is.

Edit this page on GitHub