sigil-stitch
Type-safe, import-aware, width-aware code generation for multiple languages.
sigil-stitch combines JavaPoet's builder + CodeBlock
model with Wadler-Lindig pretty printing
and multi-language support. Reference types with %T in format strings, and the library
tracks every import for you, resolves naming conflicts, and emits width-aware formatted output.
Quick Start
Requires Rust edition 2024, MSRV 1.88.0. Runtime dependencies: pretty (Wadler-Lindig formatting), serde with derive (every spec type implements Serialize/Deserialize out of the box, so you can round-trip specs as JSON or YAML), and snafu (structured errors).
Builder vs Macro
sigil-stitch offers two ways to build code. Both produce the same CodeBlock with
the same import tracking and rendering.
Builder API -- programmatic, good for dynamic code generation:
use *;
use StringLitArg;
let user_type = importable_type;
let mut cb = builder;
cb.add_statement;
cb.add_statement;
let body = cb.build.unwrap;
let file = builder
.add_code
.build
.unwrap;
let output = file.render.unwrap;
assert!;
assert!;
sigil_quote! macro -- inline target-language code, less ceremony:
use *;
use TypeScript;
let user_type = importable_type;
let body = sigil_quote!.unwrap;
The macro uses $T/$S/$N/$L/$C/$W interpolation markers that expand to
the equivalent %T/%S/%N/%L format specifiers at compile time.
Format Specifiers
| Specifier | Name | Argument Type | Purpose |
|---|---|---|---|
%T |
Type | TypeName |
Emit type reference, track import |
%N |
Name | NameArg |
Emit identifier name |
%S |
String | StringLitArg |
Emit escaped string literal |
%L |
Literal | &str, number, CodeBlock |
Emit raw value or nested block |
%W |
Wrap | (none) | Soft line break point |
%> |
Indent | (none) | Increase indent level |
%< |
Dedent | (none) | Decrease indent level |
%[ |
Statement begin | (none) | Start of statement |
%] |
Statement end | (none) | End of statement (appends ; if needed) |
Bare &str maps to %L. Use NameArg for %N and StringLitArg for %S.
See the Format Specifiers chapter for the full deep dive.
The Spec Layer
Build structured declarations with the spec builders:
| Spec | Purpose |
|---|---|
| ParameterSpec | Function parameter (name + type + default + variadic) |
| FieldSpec | Struct field / class property (visibility, static, readonly) |
| FunSpec | Function or method (params, return type, body, async, abstract) |
| TypeSpec | Class, struct, interface, trait, enum, type alias, or newtype |
| PropertySpec | Computed property with getter/setter |
| AnnotationSpec | @Override, #[derive(...)], [[nodiscard]] |
| EnumVariantSpec | Enum variant with optional value, tuple, or struct fields |
| ImportSpec | Explicit imports (aliased, side-effect, wildcard) |
| FileSpec | Top-level file with automatic import resolution |
| ProjectSpec | Multi-file project generation |
| CodeTemplate | Reusable parameterized templates with named parameters |
All specs emit CodeBlocks internally, so import tracking works everywhere.
See Building Functions & Fields, Building Types & Enums, and Files & Projects for examples and the full API.
Supported Languages
| Language | Extension | Semicolons | Import Style |
|---|---|---|---|
| TypeScript | .ts |
yes | ES modules |
| JavaScript | .js |
yes | ES modules |
| Rust | .rs |
yes | use paths |
| Go | .go |
no | package imports |
| Python | .py |
no | import/from |
| Java | .java |
yes | package imports |
| Kotlin | .kt |
no | package imports |
| Swift | .swift |
no | import module |
| Dart | .dart |
yes | package imports |
| Scala | .scala |
no | import paths |
| Haskell | .hs |
no | import module |
| OCaml | .ml |
no | open module |
| C | .c |
yes | #include |
| C++ | .cpp |
yes | #include/using |
| Bash | .bash |
no | source |
| Zsh | .zsh |
no | source |
Documentation
The sigil-stitch book covers everything in depth:
User Guide:
- Introduction -- what it is and how the pieces fit together
- Getting Started -- first CodeBlock, first FileSpec, first output
- Format Specifiers -- deep dive on
%T,%N,%S,%L,%W, and friends - TypeName -- type references, import tracking, cross-language rendering
- Building Functions & Fields -- ParameterSpec, FieldSpec, FunSpec
- Building Types & Enums -- TypeSpec, PropertySpec, AnnotationSpec, EnumVariantSpec
- Files & Projects -- ImportSpec, FileSpec, ProjectSpec
- sigil_quote! Macro -- inline code with
$T/$S/$N/$Linterpolation - Code Templates -- reusable
#{name:K}templates - Language Cookbook -- idiomatic recipes per language
Development Guide:
- Architecture -- four layers, three-pass pipeline, import resolution
- Type Presentation -- data-driven cross-language type rendering
- Adding a Language -- implementing the CodeLang trait step by step
MSRV
The minimum supported Rust version is 1.88.0 (edition 2024, let-chains).
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.