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

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 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 and 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, 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:

topcoat fmt

Verify formatting in CI (check-only mode):

topcoat fmt --check

Format a specific crate or file:

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

Run quietly with verbose error reporting:

topcoat fmt --quiet

Formatting Results

Consider the following unformatted view! macro in src/views.rs:

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:

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:

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 with documentation in 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →