BulletsForHumanity.Scribe
0.5.2
See the version list below for details.
dotnet add package BulletsForHumanity.Scribe --version 0.5.2
NuGet\Install-Package BulletsForHumanity.Scribe -Version 0.5.2
<PackageReference Include="BulletsForHumanity.Scribe" Version="0.5.2" />
<PackageVersion Include="BulletsForHumanity.Scribe" Version="0.5.2" />
<PackageReference Include="BulletsForHumanity.Scribe" />
paket add BulletsForHumanity.Scribe --version 0.5.2
#r "nuget: BulletsForHumanity.Scribe, 0.5.2"
#:package BulletsForHumanity.Scribe@0.5.2
#addin nuget:?package=BulletsForHumanity.Scribe&version=0.5.2
#tool nuget:?package=BulletsForHumanity.Scribe&version=0.5.2
Scribe
A mini DSL and toolkit for building Roslyn incremental source generators, code fix providers, and analyzers — resolving many common pain points around both.
Early development. Scribe is under active development and not yet at 1.0. APIs may change or break between releases. Until 1.0, breaking changes bump the minor version and non-breaking changes bump the patch version.
Scribe provides Quill, a fluent source builder that eliminates raw StringBuilder boilerplate, plus a set of utilities for naming, XML doc extraction, syntax predicates, namespace walking, and well-known type constants. It also ships build infrastructure for local multi-repo development workflows.
Getting Started
With the Scribe SDK (Recommended)
1. Add a global.json to your solution root:
{
"msbuild-sdks": {
"BulletsForHumanity.Scribe.Sdk": "0.3.0"
}
}
2. Create your analyzer/generator .csproj:
<Project Sdk="BulletsForHumanity.Scribe.Sdk">
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Include="BulletsForHumanity.Scribe" PrivateAssets="all" />
</ItemGroup>
</Project>
The SDK handles everything: netstandard2.0 targeting, LangVersion, analyzer packaging, Stubs.cs polyfills, and dependency bundling. See Project Setup for details.
Manual Setup (Without SDK)
dotnet add package BulletsForHumanity.Scribe
A minimal generator project without the SDK:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>14</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IncludeBuildOutput>false</IncludeBuildOutput>
<PackageType>Analyzer</PackageType>
<DebugType>embedded</DebugType>
<NoWarn>$(NoWarn);NU5128</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Include="BulletsForHumanity.Scribe" PrivateAssets="all" />
</ItemGroup>
</Project>
See Project Setup for a complete .csproj template.
Consumer projects reference the generator via NuGet (or a local package via LocalDev):
<PackageReference Include="MyGenerator" PrivateAssets="all" />
The generator runs inside Visual Studio and dotnet build automatically — any source it produces appears under the project's Analyzers node in Solution Explorer.
Quick Example
using Scribe;
var q = new Quill();
q.FileNamespace("MyApp.Generated");
q.Using("System");
using (q.Block("public partial record struct Amount : global::System.IParsable<Amount>")
.Summary("A strongly-typed decimal wrapper."))
{
using (q.Block("public static Amount Create(decimal value)")
.Summary("Creates a new Amount.")
.Param("value", "The underlying decimal value.")
.Exception("ArgumentException", "Thrown when value is default."))
{
q.Lines("""
if (value == default)
throw new global::System.ArgumentException("Value cannot be default.", nameof(value));
return new Amount(value);
""");
}
q.Summary("Extracts the underlying decimal value.");
q.Line("public static implicit operator decimal(Amount value) => value.Value;");
}
string source = q.Inscribe();
Output:
// <auto-generated/>
// I,
// ~ THE SCRIBE
#nullable enable
using System;
namespace MyApp.Generated;
/// <summary>A strongly-typed decimal wrapper.</summary>
public partial record struct Amount : IParsable<Amount>
{
/// <summary>Creates a new Amount.</summary>
/// <param name="value">The underlying decimal value.</param>
/// <exception cref="ArgumentException">Thrown when value is default.</exception>
public static Amount Create(decimal value)
{
if (value == default)
throw new ArgumentException("Value cannot be default.", nameof(value));
return new Amount(value);
}
/// <summary>Extracts the underlying decimal value.</summary>
public static implicit operator decimal(Amount value) => value.Value;
}
// I HAVE SPOKEN
global::System.IParsable and global::System.ArgumentException are automatically shortened to their simple names with using System; added — Quill resolves all global:: references at Inscribe() time.
ScribeHeader
Annotate your generator assembly to brand all generated files with a decorative page header:
// In your generator project's Scribe.cs:
[assembly: ScribeHeader("My Generator")]
Quill discovers the attribute automatically via Assembly.GetCallingAssembly() — no per-file configuration needed. Multi-line headers (with \n) are supported for including descriptions and URLs.
Local Development (LocalDev)
When developing a framework across multiple repositories, the usual pack-publish-restore cycle is slow. Scribe ships build infrastructure that automates it: build your framework once and consuming projects automatically resolve the locally-built NuGet package.
Setup: Point $(ScribeRoot) to the shared workspace root in your Directory.Build.props:
<PropertyGroup>
<ScribeRoot>$(MSBuildThisFileDirectory)..\..</ScribeRoot>
</PropertyGroup>
Activate: Select Debug (Local Scribe) in your IDE, or pass -p:IsLocalScribe=true:
dotnet build -p:IsLocalScribe=true
When active, the producer project auto-packs to a shared /.artifacts/packages/ directory and generates a version override file. Consumer projects automatically pick up the locally-built package — no manual version bumping or NuGet source registration needed.
See Project Setup & Infrastructure for the full configuration guide.
What's Included
| Component | Purpose |
|---|---|
| Scribe SDK | MSBuild SDK — zero-config project setup for analyzer/generator projects |
| Solution-Local Analyzers | Auto-pack intra-solution analyzers — no NuGet publishing needed |
| Quill | Fluent source builder — indentation, usings, namespaces, XML docs, type resolution |
| ScribeHeader | Assembly-level attribute for branding generated files with a decorative page header |
| Template | Minimal {{key}} marker substitution for structural shells |
| WellKnownFqns | Pre-defined global:: constants for common BCL types |
| Naming | PascalCase/kebab-case conversion, string escaping, XML summary extraction |
| XmlDoc | XML documentation extraction and normalisation from Roslyn doc comments |
| SyntaxPredicates | Ready-made predicates for CreateSyntaxProvider (IsPartialRecord, IsPartialClass, etc.) |
| NamespaceWalker | Recursive type visitor across compilation and referenced assemblies |
| Stubs | netstandard2.0 polyfills for init, record, required, nullable annotations |
| LocalDev | Build infrastructure for multi-repo NuGet package development |
Documentation
| Guide | What it covers |
|---|---|
| Writing Generators with Quill | How to structure a generator using the Transform → Register → Render pattern |
| Project Setup & Infrastructure | .csproj configuration, packaging, LocalDev multi-repo workflow |
| Solution-Local Analyzers | Setup guide for intra-solution analyzers and generators |
| Quill Feature Reference | Complete API reference for every Quill method and scope type |
| How Quill Works | Internal architecture — type resolution, indentation, XML doc insertion |
| How the Infrastructure Works | Build system internals — LocalDev props/targets, override file generation |
Feedback
Found a bug or have a feature request? Open an issue.
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on BulletsForHumanity.Scribe:
| Package | Downloads |
|---|---|
|
BulletsForHumanity.Scribe.Ink
Roslyn analyzers, code fix providers, and source generators for Scribe shapes. The scribe dips the quill in ink to mark, correct, and emend. |
GitHub repositories
This package is not used by any popular GitHub repositories.