Skip to content

Repository files navigation

Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5structuredmerge Logo by Aboling0, CC BY-SA 4.0

StructuredMerge Ruby

StructuredMerge Ruby provides Ruby gems for building merge-aware tools that need portable structured-merge contracts, fixture-backed behavior, and Ruby-native integration points.

The monorepo includes the core AST/review contracts, parser substrate support, format-specific merge gems, binary/ZIP planning helpers, provider adapters, and a Ruby packaging recipe gem.

Project links:

Package Family

StructuredMerge Ruby is a layered gem family. The lower layers provide parser, range, AST, merge, and template contracts; format gems apply those contracts to specific languages and data formats; provider gems bind a format family to a parser or serializer; workflow gems package the behavior for Git drivers, release automation, and monorepo maintenance.

Package README files keep this section short and link here. This root guide is the implementation inventory for Ruby users who need to choose gems, understand backend coverage, or wire a focused backend into a test suite.

The family is intentionally layered:

Core and Workflow Gems

GemLayerWhat it provides
tree_haverParser substrateParser backend registry, byte ranges, node wrappers, source locations, binary tree contracts, and backend selection helpers.
ast-mergeMerge substrateAST merge contracts, diagnostics, structural edit plans, review/replay vocabulary, nested merge orchestration, backend provider registration, and shared spec helpers.
ast-templateTemplate substrateTemplate/session transport objects used by recipe tooling and language-specific templating layers.
ast-merge-gitGit integrationMerge-driver, diff-driver, conflict inspection, language registry, and command plumbing for smorg-rb.
smorg-rbCommand packageRuby implementation command packaging and executable entry points.
kettle-jemRecipe toolingTemplate recipes, monorepo root materialization, gem maintenance helpers, and StructuredMerge Ruby release support.

Transformation Gems

GemLayerWhat it provides
ast-crisprGeneric AST editsStructured document surgery recipes for generated blocks and template-owned regions.
ast-crispr-ruby-prismRuby AST editsPrism-backed Ruby source edits, including require insertion and template-managed Ruby regions.
ast-crispr-markdown-marklyMarkdown AST editsMarkly-backed Markdown block replacement and README recipe support.

Format Gems

GemFamilyWhat it provides
plain-mergeTextLine-backed TreeHaver parser registration, plain-text fallback contracts, and conflict-preserving merge behavior.
json-mergeJSON and JSONCObject/array-aware JSON merge behavior using the shared StructuredMerge merge substrate and tree-sitter JSON grammar coverage where the selected backend supplies it.
yaml-mergeYAMLYAML-family merge contracts, shared provider tags, and provider-neutral behavior.
toml-mergeTOMLTOML-family merge contracts and provider-neutral behavior.
dotenv-mergedotenvDotenv line parser registration and key/value configuration merge behavior built on the plain text substrate.
markdown-mergeMarkdownMarkdown-family merge contracts, heading/table/list matching, link-reference handling, fenced-code flow, and provider-neutral behavior.
ruby-mergeRuby sourceRuby source merge contracts and parser-backed source-language behavior.
rbs-mergeRBSRuby signature merge behavior, declaration matching, and template-owned signature updates using RBS and tree-sitter RBS grammar coverage where available.
bash-mergeBash sourceShell source merge contracts and parser-backed shell-language behavior using tree-sitter Bash where available.
go-mergeGo sourceGo source merge contracts for the cross-language StructuredMerge family.
rust-mergeRust sourceRust source merge contracts for the cross-language StructuredMerge family.
typescript-mergeTypeScript sourceTypeScript source merge contracts for the cross-language StructuredMerge family.
binary-mergeBinaryKaitai/binary-family substrate for byte-range ownership, preservation reports, unsafe diagnostics, and renderer planning.
zip-mergeArchivesZIP parser registration and archive-aware merge contracts built on the binary-family substrate.

Provider Gems

Provider gems register themselves with the backend tag system used by ast-merge and tree_haver. That registry lets a spec suite run against a single selected backend, lets a format gem ask for a capability instead of a hard dependency, and keeps parser-specific behavior out of provider-neutral merge gems.

GemProvidesRuntime notes
psych-mergeYAML providerUses Ruby's Psych parser and emitter.
citrus-toml-mergeTOML providerRegisters a TreeHaver TOML backend backed by a Citrus grammar, commonly paired with toml-rb style TOML data handling.
parslet-toml-mergeTOML providerRegisters a TreeHaver TOML backend backed by Parslet, commonly paired with toml style TOML data handling.
commonmarker-mergeMarkdown providerUses CommonMarker for CommonMark-oriented Markdown parsing.
kramdown-mergeMarkdown providerUses Kramdown for Ruby-native Markdown parsing.
markly-mergeMarkdown providerUses Markly for cmark-gfm-backed Markdown parsing and README templating support.
prism-mergeRuby providerUses Prism for Ruby source parsing and Ruby-specific merge refiners.

Ruby Backend Notes

Ruby has the broadest backend surface in the StructuredMerge implementation set. tree_haver owns the parser backend registry and byte-range contracts; ast-merge owns provider registration and merge orchestration. The backend tags are capability names, not package preferences.

Backend or provider pathUsed byNotes
:TSLPsource-family gemsUses tree-sitter-language-pack parser aggregation where available. This is the preferred tree-sitter provider path for broad language coverage.
:MRIsource-family gemsUses ruby_tree_sitter; retained as the MRI-native tree-sitter backend name.
:rustsource-family gemsUses tree_stump where that native Rust-backed parser path is selected.
:ffisource-family gemsUses FFI bindings to libtree-sitter; suitable where the runtime and native library support the needed ABI.
:javasource-family gemsUses JVM tree-sitter bindings through java-tree-sitter / jtreesitter for JRuby-oriented parser runs.
Prismruby-merge, prism-merge, ast-crispr-ruby-prismRuby-native parser path for Ruby source and structured Ruby source edits.
Psychyaml-merge, psych-mergeRuby standard YAML parser/emitter path.
RBSrbs-mergeRuby signature parser path.
CommonMarker, Markly, Kramdownmarkdown-merge providersMarkdown parser families with different CommonMark/GFM/Ruby-native tradeoffs.
Citrus, Parslettoml-merge providersPure-Ruby TOML parser families exposed as provider-specific TreeHaver backend paths.
Kaitai Structbinary-merge, zip-mergeSchema-oriented binary parsing support and shared binary-family merge behavior.

Backend Platform Compatibility

tree_haver supports multiple Ruby parser backends, but not every backend works on every Ruby runtime:

TreeHaver backendMRIJRubyTruffleRubyNotes
:TSLP (tree-sitter-language-pack)Aggregated tree-sitter provider used by StructuredMerge language-family gems where available.
:MRI (ruby_tree_sitter)C extension, MRI only.
:rust (tree_stump)Rust extension through Ruby native-extension tooling, MRI only.
:ffi (FFI + libtree-sitter)TruffleRuby FFI does not support the tree-sitter struct-by-value ABI.
:java (java-tree-sitter / jtreesitter)JRuby-oriented path that requires matching grammar JARs.
PrismRuby parser, standard library in Ruby 3.4+.
PsychYAML parser/emitter, standard library.
CitrusPure Ruby PEG parser.
ParsletPure Ruby PEG parser.
CommonMarkerNative Markdown parser used through commonmarker-merge.
MarklyNative cmark-gfm parser used through markly-merge.
KramdownPure Ruby Markdown parser.

Legend: ✅ = works, ❌ = does not work, ❓ = not part of the supported runtime claim.

Install

Install the gems your tool needs:

bundle add ast-merge json-merge

Command

The Ruby implementation ships the implementation-specific smorg-rb command. Use that name in git configuration unless a package manager or local install has provided a smorg symlink.

Package-manager formulas may expose the selected implementation as smorg. For a local user-created symlink:

ln -s "$(command -v smorg-rb)"~/.local/bin/smorg
git config merge.smorg-rb.driver 'smorg-rb merge-driver %O %A %B %P'
git config diff.smorg-rb.command 'smorg-rb diff-driver'
smorg-rb conflicts diff path/to/file-with-conflicts.go
smorg-rb languages --gitattributes

merge-driver updates Git's %A file by default, or writes to --output when used outside git. diff-driver accepts both the two-argument local form and the seven- or nine-argument forms Git passes to external diff commands. conflicts diff reports conflict-marker regions in a file that already contains Git conflict markers.

Semantic merge-driver coverage is fixture-backed for JSON. Other language and format paths are git-compatible command surfaces without semantic driver coverage.

Gems

Core and transformation gems:

  • tree_haver - parser substrate, byte ranges, backend adapters, and binary tree contracts.
  • ast-merge - AST merge contracts, diagnostics, planning, review, replay, and nested-merge vocabulary.
  • ast-template - template/session transport contracts.
  • ast-crispr - generic AST edit recipes for generated blocks and template-owned regions.
  • ast-crispr-ruby-prism - Prism-backed Ruby source edits.
  • ast-crispr-markdown-markly - Markly-backed Markdown source edits.

Format libraries:

Provider and recipe gems:

Portability

The Ruby gems are developed against the [shared StructuredMerge fixtures][structuredmerge-fixtures]. Those fixtures define the cross-language behavior expected from the Go, TypeScript, Rust, and Ruby implementations. Conformance checks live in gem specs and in the shared spec/fixture tooling rather than in a static status document.

Development

Use the family tooling from the monorepo root for broad checks:

bundle exec kettle-family install --execute
bundle exec kettle-family lint --execute
bundle exec kettle-family test --execute

For a single gem, run commands from that gem directory:

bundle exec kettle-test
bin/rake rubocop_gradual:autocorrect

Prefer kettle-test over direct rspec so local verification exercises the same parallel runner, worker isolation, filtering, and formatter behavior used by CI. Use direct rspec only for narrow debugging when kettle-test cannot express the probe, then rerun kettle-test before treating the suite as verified.

Bundler path gems are the default isolation mechanism inside this monorepo. When this repository needs to consume sibling workspace projects outside the monorepo itself, prefer nomono-driven Bundler wiring rather than manual Ruby load-path changes.

About

☯️ Ruby implementation of the StructuredMerge contract

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

18 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages