Skip to content

Commit 2c7672d

Browse files
authored
Merge pull request #984 from hirosystems/chore/clarity-formatter
add clarity formatter guide
2 parents 823e5af + 3afbd37 commit 2c7672d

File tree

2 files changed

+279
-0
lines changed

2 files changed

+279
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
---
2+
title: Clarity Formatter
3+
description: Learn how to use the Clarity formatter to standardize the style of your smart contract code.
4+
---
5+
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion';
6+
7+
The Clarity formatter is a tool designed to automatically format your Clarity smart contract code according to a standardized style. Using a consistent style improves code readability and maintainability, making it easier for developers to understand, collaborate on, and learn from existing Clarity projects.
8+
9+
As Clarity is a relatively young language, establishing formatting standards helps reduce friction for both new and experienced developers, but these standards are still evolving! If you have suggestions for how we can improve the formatting rules, ping us on Discord or [add your thoughts here](https://github.com/hirosystems/clarinet/discussions/1689).
10+
11+
## Introduction
12+
13+
The Clarity formatter is integrated into two primary development tools:
14+
15+
1. **[Clarity VS Code Extension](https://marketplace.visualstudio.com/items?itemName=HiroSystems.clarity-lsp)**: Allows formatting directly within your editor.
16+
2. **Clarinet CLI**: Enables formatting via the command line, including the ability to format entire projects.
17+
18+
## Configuration
19+
20+
The formatter applies an opinionated standard with the following default settings:
21+
22+
- **Line Length**: Lines wrap at 80 characters.
23+
- **Indentation**: Uses 2 spaces for indentation.
24+
25+
These defaults are configurable to match your preferences, although the specific configuration method depends on whether you are using VS Code or Clarinet.
26+
27+
## Usage
28+
29+
### In VS Code
30+
31+
The [Clarity VS Code extension](https://marketplace.visualstudio.com/items?itemName=HiroSystems.clarity-lsp) provides several ways to format your code:
32+
33+
- **Format Document**: Formats the entire active file (Right-click -> Format Document or Shift+Option+F / Shift+Alt+F).
34+
- **Format Selection**: Formats only the highlighted code (Right-click -> Format Selection).
35+
- **Format On Save**: Automatically formats the file when you save it. This can be enabled in VS Code settings (`editor.formatOnSave`) and is off by default.
36+
37+
You can find the settings by searching "clarity-lsp" from the settings menu (Ctrl+, / Cmd+,) or using the settings.json directly.
38+
For example, you can configure format-on-save for all clarity files within the settings.json with this entry:
39+
40+
```terminal
41+
"[clarity]": {
42+
"editor.formatOnSave": true,
43+
},
44+
```
45+
46+
### With Clarinet CLI
47+
48+
The Clarinet CLI allows you to format contracts from the command line using `clarinet format` (or the alias `clarinet fmt`). You can format individual files or all contracts defined in your project's `Clarinet.toml` manifest.
49+
50+
**Format all checkable contracts and print the result without saving:**
51+
52+
```terminal
53+
$ clarinet format --dry-run
54+
(define-map counters
55+
principal
56+
uint
57+
)
58+
(define-public (count-up)
59+
(ok (map-set counters tx-sender (+ (get-count tx-sender) u1)))
60+
)
61+
62+
(define-read-only (get-count
63+
(who principal)
64+
)
65+
(default-to u0 (map-get? counters who))
66+
)
67+
```
68+
**Format all checkable contracts (`--in-place`):**
69+
70+
```terminal
71+
$ clarinet format --in-place
72+
```
73+
74+
**Format a specific file using tabs and print the result without saving (`--dry-run`):**
75+
76+
```terminal
77+
$ clarinet format -f contracts/my-contract.clar -t --dry-run
78+
```
79+
80+
**Format a specific file, overwriting it (`--in-place`) with 4-space indents and 120 max line length:**
81+
```terminal
82+
$ clarinet format -f contracts/my-contract.clar -i 4 -l 120 --in-place
83+
```
84+
85+
## Formatting Rules
86+
87+
Alongside these settings, the Clarity formatter introduces formatting rules for many basic Clarity constructs:
88+
89+
<Accordion type="single" collapsible className="w-full my-4">
90+
<AccordionItem value="formatted-constructs">
91+
<AccordionTrigger>View Formatted Constructs</AccordionTrigger>
92+
<AccordionContent>
93+
<ul className="list-disc pl-6 space-y-1 py-2">
94+
<li><code>let</code></li>
95+
<li><code>begin</code></li>
96+
<li><code>match</code></li>
97+
<li>tuples and map sugar</li>
98+
<li><code>if</code></li>
99+
<li><code>and</code>/<code>or</code></li>
100+
<li>comments</li>
101+
<li>public/read-only/private functions</li>
102+
<li>constant/persisted-variable/ft/nft/impl-trait/use-trait</li>
103+
<li><code>define-map</code></li>
104+
<li><code>define-trait</code></li>
105+
</ul>
106+
</AccordionContent>
107+
</AccordionItem>
108+
</Accordion>
109+
110+
The following sections provide examples of how common constructs are formatted.
111+
112+
### Basic Indentation & Line Wrapping
113+
114+
Code is indented using 2 spaces per level. Long expressions exceeding the configured line length (default 80 characters) are automatically broken across multiple lines.
115+
116+
```clarity
117+
;; Example of line wrapping
118+
(try! (unwrap!
119+
(complete-deposit-wrapper (get txid deposit) (get vout-index deposit))
120+
(err (+ ERR_DEPOSIT_INDEX_PREFIX (+ u10 index)))
121+
))
122+
```
123+
124+
### Function Definitions
125+
126+
Functions (`define-public`, `define-private`, `define-read-only`) always span multiple lines. Arguments are double-indented if there is more than one, and if a single argument fits on the first line, it remains there.
127+
128+
The function body is single-indented, aligning with the closing parenthesis of the arguments. A trailing newline is added after each function definition.
129+
130+
```clarity
131+
(define-public (my-func
132+
(amount uint)
133+
(sender principal)
134+
)
135+
(ok true)
136+
)
137+
138+
(define-read-only (get-balance (who principal))
139+
(ok u0)
140+
)
141+
```
142+
143+
### `let` Expressions
144+
145+
Bindings within a `let` expression are placed on separate lines, indented once. The body of the `let` expression is indented at the same level as the bindings.
146+
147+
```clarity
148+
(let (
149+
(a u1)
150+
(b u2)
151+
)
152+
(body-expression)
153+
)
154+
```
155+
156+
### `begin` Blocks
157+
158+
`begin` blocks are always formatted across multiple lines, even for a single expression. The expressions within the block are indented once.
159+
160+
```clarity
161+
(begin
162+
(ok true)
163+
)
164+
```
165+
166+
### Boolean Operators (`and`, `or`)
167+
168+
If an `and` or `or` expression contains more than two conditions, each condition is placed on a new line, indented once.
169+
170+
```clarity
171+
(or
172+
true
173+
(is-eq 1 2)
174+
false
175+
)
176+
```
177+
178+
### `if` Statements
179+
180+
The `then` and `else` branches of an `if` statement are always placed on separate lines, indented once.
181+
182+
```clarity
183+
(if (condition)
184+
(expression-true)
185+
(expression-false)
186+
)
187+
```
188+
189+
### `match` Expressions
190+
191+
`match` expressions are always multi-line. Each match arm (pattern and corresponding expression) is placed on a new line, with the pattern and expression aligned.
192+
193+
```clarity
194+
;; Option syntax
195+
(match opt
196+
value (ok (handle-new-value value))
197+
(ok 1)
198+
)
199+
200+
;; Response syntax
201+
(match (sbtc-transfer amount tx-sender (as-contract tx-sender))
202+
success (ok id)
203+
error (err (* error u1000)))))
204+
)
205+
```
206+
207+
### Tuples & Maps (Sugared Syntax)
208+
209+
Tuples defined using `(tuple ...)` are automatically converted to the sugared `{ key: value }` syntax.
210+
211+
```clarity
212+
;; Input: (tuple (n1 u1))
213+
;; Output:
214+
{ n1: u1 }
215+
```
216+
217+
Maps with multiple key-value pairs are broken across multiple lines. Each pair is indented once and followed by a comma (`,`), including the last pair.
218+
219+
```clarity
220+
{
221+
name: (buff 48),
222+
owner: principal,
223+
}
224+
```
225+
226+
### Nested Maps
227+
228+
Indentation is applied consistently for nested map structures.
229+
230+
```clarity
231+
{
232+
name: {
233+
first: "Hiro",
234+
last: "Protagonist",
235+
},
236+
age: u33,
237+
}
238+
```
239+
240+
### Trait Definitions (`define-trait`)
241+
242+
Trait definitions follow specific layout rules for function signatures within the trait body.
243+
244+
```clarity
245+
(define-trait token-trait
246+
(
247+
(transfer? (principal principal uint) (response uint uint))
248+
(get-balance (principal) (response uint uint))
249+
)
250+
)
251+
```
252+
253+
### Trailing Comments
254+
255+
Trailing comments (` ;; comment`) are preserved and placed after the expression on the same line. They do not count towards the maximum line length calculation.
256+
257+
```clarity
258+
(get-value key) ;; Retrieves the stored value
259+
```
260+
261+
## Ignoring Formatting
262+
263+
You can prevent the formatter from modifying specific sections of your code by adding a `;; @format-ignore` comment immediately before the block you wish to exclude.
264+
265+
```clarity
266+
;; @format-ignore
267+
(define-constant something (list
268+
1 2 3 ;; comment
269+
4 5 ))
270+
```
271+
272+
Refer to the [Clarity formatter readme](https://github.com/hirosystems/clarity-formatter/blob/main/README.md) for the full list of commands and options.
273+
274+
## Feedback & Further Information
275+
276+
The Clarity formatter is continually evolving based on community feedback. Please try it out and share your thoughts to help improve the standards for the ecosystem.
277+
278+
For more detailed information, please consult the [Clarity formatter readme](https://github.com/hirosystems/clarity-formatter/blob/main/README.md).

content/docs/stacks/clarinet/meta.json

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"index",
77
"quickstart",
88
"concepts",
9+
"clarity-formatter",
910
"---Guides---",
1011
"...guides"
1112
]

0 commit comments

Comments
 (0)