diff --git a/content/docs/stacks/clarinet/clarity-formatter.mdx b/content/docs/stacks/clarinet/clarity-formatter.mdx new file mode 100644 index 000000000..9e1891c34 --- /dev/null +++ b/content/docs/stacks/clarinet/clarity-formatter.mdx @@ -0,0 +1,278 @@ +--- +title: Clarity Formatter +description: Learn how to use the Clarity formatter to standardize the style of your smart contract code. +--- +import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion'; + +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. + +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). + +## Introduction + +The Clarity formatter is integrated into two primary development tools: + +1. **[Clarity VS Code Extension](https://marketplace.visualstudio.com/items?itemName=HiroSystems.clarity-lsp)**: Allows formatting directly within your editor. +2. **Clarinet CLI**: Enables formatting via the command line, including the ability to format entire projects. + +## Configuration + +The formatter applies an opinionated standard with the following default settings: + +- **Line Length**: Lines wrap at 80 characters. +- **Indentation**: Uses 2 spaces for indentation. + +These defaults are configurable to match your preferences, although the specific configuration method depends on whether you are using VS Code or Clarinet. + +## Usage + +### In VS Code + +The [Clarity VS Code extension](https://marketplace.visualstudio.com/items?itemName=HiroSystems.clarity-lsp) provides several ways to format your code: + +- **Format Document**: Formats the entire active file (Right-click -> Format Document or Shift+Option+F / Shift+Alt+F). +- **Format Selection**: Formats only the highlighted code (Right-click -> Format Selection). +- **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. + +You can find the settings by searching "clarity-lsp" from the settings menu (Ctrl+, / Cmd+,) or using the settings.json directly. +For example, you can configure format-on-save for all clarity files within the settings.json with this entry: + +```terminal +"[clarity]": { + "editor.formatOnSave": true, + }, +``` + +### With Clarinet CLI + +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. + +**Format all checkable contracts and print the result without saving:** + +```terminal +$ clarinet format --dry-run +(define-map counters + principal + uint +) +(define-public (count-up) + (ok (map-set counters tx-sender (+ (get-count tx-sender) u1))) +) + +(define-read-only (get-count + (who principal) + ) + (default-to u0 (map-get? counters who)) +) +``` +**Format all checkable contracts (`--in-place`):** + +```terminal +$ clarinet format --in-place +``` + +**Format a specific file using tabs and print the result without saving (`--dry-run`):** + +```terminal +$ clarinet format -f contracts/my-contract.clar -t --dry-run +``` + +**Format a specific file, overwriting it (`--in-place`) with 4-space indents and 120 max line length:** +```terminal +$ clarinet format -f contracts/my-contract.clar -i 4 -l 120 --in-place +``` + +## Formatting Rules + +Alongside these settings, the Clarity formatter introduces formatting rules for many basic Clarity constructs: + + + + View Formatted Constructs + +
    +
  • let
  • +
  • begin
  • +
  • match
  • +
  • tuples and map sugar
  • +
  • if
  • +
  • and/or
  • +
  • comments
  • +
  • public/read-only/private functions
  • +
  • constant/persisted-variable/ft/nft/impl-trait/use-trait
  • +
  • define-map
  • +
  • define-trait
  • +
+
+
+
+ +The following sections provide examples of how common constructs are formatted. + +### Basic Indentation & Line Wrapping + +Code is indented using 2 spaces per level. Long expressions exceeding the configured line length (default 80 characters) are automatically broken across multiple lines. + +```clarity +;; Example of line wrapping +(try! (unwrap! + (complete-deposit-wrapper (get txid deposit) (get vout-index deposit)) + (err (+ ERR_DEPOSIT_INDEX_PREFIX (+ u10 index))) +)) +``` + +### Function Definitions + +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. + +The function body is single-indented, aligning with the closing parenthesis of the arguments. A trailing newline is added after each function definition. + +```clarity +(define-public (my-func + (amount uint) + (sender principal) + ) + (ok true) +) + +(define-read-only (get-balance (who principal)) + (ok u0) +) +``` + +### `let` Expressions + +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. + +```clarity +(let ( + (a u1) + (b u2) +) + (body-expression) +) +``` + +### `begin` Blocks + +`begin` blocks are always formatted across multiple lines, even for a single expression. The expressions within the block are indented once. + +```clarity +(begin + (ok true) +) +``` + +### Boolean Operators (`and`, `or`) + +If an `and` or `or` expression contains more than two conditions, each condition is placed on a new line, indented once. + +```clarity +(or + true + (is-eq 1 2) + false +) +``` + +### `if` Statements + +The `then` and `else` branches of an `if` statement are always placed on separate lines, indented once. + +```clarity +(if (condition) + (expression-true) + (expression-false) +) +``` + +### `match` Expressions + +`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. + +```clarity +;; Option syntax +(match opt + value (ok (handle-new-value value)) + (ok 1) +) + +;; Response syntax +(match (sbtc-transfer amount tx-sender (as-contract tx-sender)) + success (ok id) + error (err (* error u1000))))) +) +``` + +### Tuples & Maps (Sugared Syntax) + +Tuples defined using `(tuple ...)` are automatically converted to the sugared `{ key: value }` syntax. + +```clarity +;; Input: (tuple (n1 u1)) +;; Output: +{ n1: u1 } +``` + +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. + +```clarity +{ + name: (buff 48), + owner: principal, +} +``` + +### Nested Maps + +Indentation is applied consistently for nested map structures. + +```clarity +{ + name: { + first: "Hiro", + last: "Protagonist", + }, + age: u33, +} +``` + +### Trait Definitions (`define-trait`) + +Trait definitions follow specific layout rules for function signatures within the trait body. + +```clarity +(define-trait token-trait + ( + (transfer? (principal principal uint) (response uint uint)) + (get-balance (principal) (response uint uint)) + ) +) +``` + +### Trailing Comments + +Trailing comments (` ;; comment`) are preserved and placed after the expression on the same line. They do not count towards the maximum line length calculation. + +```clarity +(get-value key) ;; Retrieves the stored value +``` + +## Ignoring Formatting + +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. + +```clarity +;; @format-ignore +(define-constant something (list + 1 2 3 ;; comment + 4 5 )) +``` + +Refer to the [Clarity formatter readme](https://github.com/hirosystems/clarity-formatter/blob/main/README.md) for the full list of commands and options. + +## Feedback & Further Information + +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. + +For more detailed information, please consult the [Clarity formatter readme](https://github.com/hirosystems/clarity-formatter/blob/main/README.md). diff --git a/content/docs/stacks/clarinet/meta.json b/content/docs/stacks/clarinet/meta.json index ce65026d8..29705746d 100644 --- a/content/docs/stacks/clarinet/meta.json +++ b/content/docs/stacks/clarinet/meta.json @@ -6,6 +6,7 @@ "index", "quickstart", "concepts", + "clarity-formatter", "---Guides---", "...guides" ]