Awesome
CLARIFORM
"Painless linting & formatting for Clarity."
Clariform is a command-line tool for automatically correcting and formatting Clarity code.
This early version has limited functionality, but it's a start:
- Validate the syntax of a Clarity contract file
- Fix confusing indentation and dangling close-parens
- Normalize whitespace and decorative tokens
- Expand record shorthand notation
- Custom formatting of the output code
- Process contract from url
- Autofix multi-expression function bodies
- Distributed as npm package
- Github action to validate Clarity contracts in a repository
Usage
While Clariform isn't quite painless yet, it's getting there. Please give it a try and let us know what you think on the issue tracker.
Clariform is available as a pre-built Docker image that is distributed as a GitHub package. Docker will download and run the image for you. If you prefer to clone the repository and build your own, see the instructions in BUILD.md.
Prerequisites
Docker must be installed and running.
Pull the Clariform image (optional):
docker pull ghcr.io/prompteco/clariform
This will download Clariform and pre-build a Docker image. It may take some time and produce a lot of output. If you don't do this in advance, the image will be pulled the first time you run Clariform.
Quick Start
Run Clariform in a Docker container:
docker run ghcr.io/prompteco/clariform --help
Lint a Clarity contract from a URL and format it:
docker run ghcr.io/prompteco/clariform "https://raw.githubusercontent.com/njordhov/clariform/main/contracts/malformed.clar"
To process local contracts mount the current working directory as /home
and list files as arguments:
docker run -v `pwd`:/home ghcr.io/prompteco/clariform *.clar
This assumes that the current directory contains Clarity contracts with a ".clar" file extension.
The formatted contracts will be written to output.
Use the --output-dir
option to specify a directory for formatted contracts:
docker run -v `pwd`:/home ghcr.io/prompteco/clariform --output-dir "out" *.clar
Troubleshooting
If Clariform fails to open a file, make sure the directory containing the file is mounted and that the pathname of the file is relative to the mount.
If Clariform isn't working as expected, make sure you are running the latest version:
docker run ghcr.io/prompteco/clariform --version
To run a specific version of clariform, append the version at the end:
docker run ghcr.io/prompteco/clariform:v0.6.0 --version
To avoid running an older version of clariform, remove all cached clariform images using this command:
docker rmi --force $(docker images -q ghcr.io/prompteco/clariform)
Alternatively, open the Docker Desktop application to inspect or delete containers and images.
If these actions don't resolve your issue, please report it on the issue tracker.
Installation
To make it easier to use clariform, create a named container from the prebuilt image:
docker pull ghcr.io/prompteco/clariform
docker image tag ghcr.io/prompteco/clariform clariform
Run the container to execute clariform:
docker run clariform --help
Docker restricts filesystem access by default. To give Clariform access
to files, mount the current working directory as /home
:
docker run -v `pwd`:/home clariform .
This will traverse all Clarity contract files (".clar") in the working directory and either output an autocorrected indented version or report a syntax error.
Create Shortcut
To make it easier to use clariform, you can create a shortcut for the clariform command. On Mac/Unix, you can do this by creating an executable script or an alias:
alias clariform="docker run -v \`pwd\`:/home clariform"
To use the shortcut, run this command:
clariform --help
Features
The following instructions assume you have created a clariform alias. If you haven't, use this command in place of "clariform":
docker run -v `pwd`:/home ghcr.io/njordhov/clariform
Select Files
Clariform can open a contract from a URL:
clariform "https://raw.githubusercontent.com/njordhov/clariform/main/contracts/malformed.clar"
You can specify filenames and directories as arguments:
clariform *.clar
If the input contains multiple contracts, Clariform will concatenate the contracts in formatted output, prefixing each with their source location as a comment.
Check Validity
Clariform can check if a contract is valid Clarity code. If the contract is invalid, C
larity will report the error and exit. Use the --check
flag to activate validation:
clariform --check "https://raw.githubusercontent.com/njordhov/clariform/main/src/test/invalid.clar"
There will be no output if the contract is valid. When checking multiple contracts it will output the name of each contract before validation.
Formatting Options
The --format option allows you to specify the output formatting of Clarity code. The following options are available:
retain
: Preserves the original whitespace and formatting from the source.adjust
: Keeps the original formatting, but lines up dangling closing parentheses.indent
(default): Nests expressions and collapses dangling closing parentheses.auto
: Auto-indents for consistency and readability.align
: Removes whitespace from the start of each line (uses less space; can be re-indented with the indent option).tight
: Collapses each branch expression into a single line (ugly but accommodates test coverage tooling).spread
: Each expression on its own indented line (accommodates line oriented test coverage tooling).compact
: Collapses each top-level form into a single line (dense but useful for parsing by other tools).
Here are some examples of using the --format option:
clariform --format=adjust contracts/malformed.clar
clariform --format=indent contracts/malformed.clar
Validate Syntax
To validate that the contracts have strict Clarity syntax, add a --strict
flag:
clariform --strict "https://raw.githubusercontent.com/njordhov/clariform/main/contracts/malformed.clar"
Auto Correct
Clariform automatically fixes many common errors in Clarity contracts. You can use this to keep your contract files valid, or as a preprocessor to allow shorthand notations and more relaxed syntax during editing.
clariform "https://raw.githubusercontent.com/njordhov/clariform/main/contracts/malformed.clar"
Clariform inserts required whitespace in expressions and between them:
;; invalid clarity: missing whitespace
(*(+ 1 2)(+ 3 4))
=>
(* (+ 1 2) (+ 3 4))
Clariform fixes missing delimiters and incomplete properties in a record literal (aka "tuple"):
;; invalid clarity: missing property value and delimiters
{name,
age:5
address "home"}
=>
{name: name,
age: 5,
address: "home"}
Clariform wraps a multi-expression function body in a begin
form:
;; invalid clarity: multiple expressions in function definition
(define-read-only (half (digit int))
(asserts! (<= 0 digit 9))
(/ digit 2))
=>
(define-read-only (half (digit int))
(begin
(asserts! (<= 0 digit 9))
(/ digit 2)))
Clariform escapes unicode glyphs and ensures unicode/utf8 strings are prefixed:
"A special 🎁 for you"
=>
u"A special \u{1F381} for you"
Clariform formats let
bindings according to best practices (disabled when format
option is retain
or adjust
):
;; Confusing formatting making the binding resemble a function call
(let (
(foo (+ n 1))
)
foo)
=>
(let ((foo (+ n 1)))
foo)
Please submit a new issue if you have suggestions for improvements.