# How to Use the topcoat fmt CLI to Format view! Macros

> Learn to use the topcoat fmt CLI to format view! macros. This tool reformats macro bodies with rustfmt and a custom pretty-printer for normalized HTML syntax.

- Repository: [Tokio/topcoat](https://github.com/tokio-rs/topcoat)
- Tags: how-to-guide
- Published: 2026-07-31

---

**The `topcoat fmt` command reformats Topcoat macro bodies by first piping them through `rustfmt` and then applying a custom pretty-printer to normalize HTML-like syntax in `view!` and related macros.**

The `topcoat fmt` CLI is the official formatting tool for the Topcoat UI framework, designed specifically to handle the unique syntax of declarative macros. According to the tokio-rs/topcoat source code, this tool performs a two-stage formatting process that applies standard Rust style rules followed by Topcoat-specific indentation and spacing conventions.

## How the Two-Stage Formatter Works

The formatter implemented in [`crates/topcoat-cli/src/fmt.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/src/fmt.rs) processes macro bodies through two distinct phases to ensure consistent output.

### Stage 1: Rust Code Formatting

First, the tool pipes the macro body through `rustfmt`, applying standard Rust style rules to all embedded Rust expressions. This ensures that control-flow constructs like `if`, `for`, `match`, and `let` blocks follow canonical Rust formatting.

### Stage 2: Topcoat-Specific Pretty-Printing

After `rustfmt` completes, a custom pretty-printer reformats the HTML-like syntax of `view!` blocks and related macros. This stage handles tag indentation, attribute spacing, and expression braces to produce consistent markup alignment. The implementation correctly manages interpolated Rust expressions (`{expr}`), nested components, and attribute forwarding.

## Supported Macros and Syntax

The formatter recognizes and reformats all Topcoat declarative macros, including:

- `view!` - Primary template macro for HTML-like markup
- `component!` - Component definition macro  
- `attributes!` - Attribute grouping macro
- `class!` - CSS class utility macro
- `props!` - Property declaration macro

As documented in [`crates/topcoat-view/macro/docs/view.md`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-view/macro/docs/view.md) and [`crates/topcoat-view/macro/docs/component.md`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-view/macro/docs/component.md), the formatter understands the specific grammar rules for each macro variant.

## Command-Line Options

The `topcoat fmt` command, registered in [`crates/topcoat-cli/src/main.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/src/main.rs), accepts several flags to control formatting behavior:

- **`--check`** - Verifies formatting without writing changes; exits with non-zero status if any macro body needs changes, making it ideal for CI pipelines
- **`--write`** - Formats files and writes changes back to disk (default behavior)
- **`--path <PATH>`** - Restricts formatting to a specific file or directory relative to the current working directory
- **`--quiet`** - Suppresses diagnostic output, printing only errors
- **`--verbose`** - Displays each file being processed during execution

By default, the command walks the entire Cargo workspace, but you can limit scope using the `--path` flag.

## Usage Examples

Format the entire workspace:

```bash
topcoat fmt

```

Verify formatting in CI (check-only mode):

```bash
topcoat fmt --check

```

Format a specific crate or file:

```bash
topcoat fmt --path examples/simple
topcoat fmt --path src/main.rs

```

Run quietly with verbose error reporting:

```bash
topcoat fmt --quiet

```

## Formatting Results

Consider the following unformatted `view!` macro in [`src/views.rs`](https://github.com/tokio-rs/topcoat/blob/main/src/views.rs):

```rust
view! {
  div class="container"{
    if let Some(user)=cx.user(){
        p {"Welcome, " {user.name} "!"}
    }else{
        p {"Please log in"}
    }
  }
}

```

After running `topcoat fmt`, the output becomes:

```rust
view! {
    div class = "container" {
        if let Some(user) = cx.user() {
            p { "Welcome, " { user.name } "!" }
        } else {
            p { "Please log in" }
        }
    }
}

```

The formatter applies consistent four-space indentation, adds spaces around assignment operators, and normalizes brace spacing for interpolated expressions.

## Key Implementation Files

The formatting logic is distributed across these critical paths in the tokio-rs/topcoat repository:

- **[`crates/topcoat-cli/src/fmt.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/src/fmt.rs)** - Core implementation of the `topcoat fmt` command, containing the argument parser, workspace walker, and two-stage formatting orchestration
- **[`crates/topcoat-cli/docs/fmt.md`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/docs/fmt.md)** - Official user documentation describing CLI flags and CI integration patterns
- **[`crates/topcoat-view/macro/docs/view.md`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-view/macro/docs/view.md)** - Syntax specification for `view!` macro formatting targets
- **[`crates/topcoat-view/macro/docs/component.md`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-view/macro/docs/component.md)** - Component macro syntax documentation
- **[`crates/topcoat-cli/src/main.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/src/main.rs)** - Binary entry point that registers the `fmt` subcommand

## Summary

- **Two-stage process**: `topcoat fmt` runs `rustfmt` first, then applies Topcoat-specific pretty-printing rules to macro bodies
- **Multi-macro support**: Handles `view!`, `component!`, `attributes!`, `class!`, and `props!` macros with syntax-aware formatting
- **CI integration**: Use `--check` for non-destructive verification in continuous integration pipelines
- **Flexible targeting**: Format entire workspaces or limit scope to specific files via `--path`
- **Source locations**: Implementation resides in [`crates/topcoat-cli/src/fmt.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/src/fmt.rs) with documentation in [`crates/topcoat-cli/docs/fmt.md`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/docs/fmt.md)

## Frequently Asked Questions

### Does topcoat fmt modify files in-place by default?

Yes, the default behavior is `--write`, which reformats and overwrites source files directly. To verify formatting without modifying files, use the `--check` flag, which reports violations without writing changes and exits with a non-zero status if formatting is needed.

### Can I use topcoat fmt in CI pipelines?

Absolutely. Run `topcoat fmt --check` in your CI workflow to enforce formatting standards. This command fails the build if any `view!` or related macro bodies do not match the expected format, preventing unformatted code from merging into your main branch.

### Which Topcoat macros does the formatter support?

The formatter supports all Topcoat declarative macros including `view!`, `component!`, `attributes!`, `class!`, and `props!`. As implemented in [`crates/topcoat-cli/src/fmt.rs`](https://github.com/tokio-rs/topcoat/blob/main/crates/topcoat-cli/src/fmt.rs), it recognizes these macro invocations and applies appropriate formatting rules for each syntax variant.

### How does topcoat fmt handle Rust expressions inside view! macros?

The tool correctly processes interpolated Rust expressions (`{expr}`) and control-flow constructs by first running them through `rustfmt`. This ensures that `if let`, `for` loops, `match` statements, and variable assignments inside macro bodies receive standard Rust formatting before the Topcoat pretty-printer applies markup-specific styling.