This provides an opinionated source code formatter for the Spicy language.
Navigate to the latest release and run the mentioned installation script, e.g.,
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/bbannier/spicy-format/releases/download/v0.10.0/spicy-format-installer.sh | sh
Follow the printed instructions. This will install both the formatter
spicy-format
itself as well as an updater script spicy-format-update
which
can be used to update to newer releases.
Alternatively you can also download prebuilt binaries and updaters on the release page.
If no binaries are available for you platform you need to install from source. This requires a Rust installation, use e.g., rustup for setting one up.
You can then install the project with
cargo install --locked --git https://github.com/bbannier/spicy-format
It is strongly suggested to use --locked
to use dependency versions locked
in the project.
This formatter is implemented in Rust with
Topiary. It uses
tree-sitter-spicy for parsing
input source code into a tree-sitter CST. Formatting of that CST is done
through Topiary queries. The actual
queries are defined in src/query.scm
. Most of the time
changing the formatter should not require any changes to the Rust code, but
only to the query file.
To change formatting of certain nodes it might often be sufficient to inspect
the Spicy tree-sitter
grammar
and change formatting of the nodes in src/query.scm
.
To instead inspect the full parse trees of code samples check out tree-sitter-spicy and use it to parse the code, e.g.,
# Get Spicy tree-sitter grammar.
git clone https://github.com/bbannier/tree-sitter-spicy
$ cd tree-sitter-spicy
# If needed install the tree-sitter CLI.
$ npm install tree-sitter
# Use tree-sitter to parse a source file.
$ tree-sitter parse hello.spicy
(module [0, 0] - [3, 0]
entities: (module_decl [0, 0] - [0, 13]
name: (ident [0, 7] - [0, 12]
(name [0, 7] - [0, 12])))
entities: (statement [2, 0] - [2, 18]
(print [2, 0] - [2, 18]
(expression [2, 6] - [2, 17]
(string [2, 6] - [2, 17])))))
Use this information to write dedicated formatter queries.
If the grammar does not have support for constructs or incorrectly parses
them the grammar needs to be updated and bumped. The used version of the
grammar is specified in
Cargo.toml
,
[dependencies]
tree-sitter-spicy = { git = "https://github.com/bbannier/tree-sitter-spicy" }
...
You can specify a different repository here, or enforce a specific revision, e.g.,
tree-sitter-spicy = { git = "https://github.com/MY_FORK/tree-sitter-spicy", rev = "b9958baeda3dc77fa94af2ca2cd84723bd532d08" }
In order to use a unpublished local version you can replace the dependency with a path dependency, e.g.,
tree-sitter-spicy = { path = "path/to/local/version" }
Test cases are collected and automatically discovered by the test harness in
the corpus
/ directory. To execute the test harness run
cargo t
For each corpus/<INPUT>.spicy
the repository contains a matching expected
result baseline corpus/<INPUT>.spicy.expected
. To update the baselines
execute the test harness with the environment variable UPDATE_BASELINE
set.
UPDATE_BASELINE=1 cargo t
This will update or if needed create the outdated baselines. When adding new tests to the corpus, commit the baseline as well.
To run formatting against an external corpus run the test suite with
SPICY_FORMAT_EXTERNAL_CORPUS
set.
SPICY_FORMAT_EXTERNAL_CORPUS=<PATH TO SPICY CORPUS> cargo t corpus_external
The suite automatically filters out of some files in the Spicy test suite with known unsupported constructs.