The *-merge Gem Family
The *-merge gem family provides intelligent, AST-based merging for various file formats. At the foundation is tree_haver, which provides a unified cross-Ruby parsing API that works seamlessly across MRI, JRuby, and TruffleRuby.
| Gem | Version / CI | Language / Format |
Parser Backend(s) | Description |
|---|---|---|---|---|
| tree_haver |
|
Multi | Supported Backends: MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus, Parslet | Foundation: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
| ast-merge |
|
Text | internal |
Infrastructure: Shared base classes and merge logic for all *-merge gems |
| bash-merge |
|
Bash | tree-sitter-bash (via tree_haver) | Smart merge for Bash scripts |
| commonmarker-merge |
|
Markdown | Commonmarker (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
| dotenv-merge |
|
Dotenv | internal | Smart merge for .env files |
| json-merge |
|
JSON | tree-sitter-json (via tree_haver) | Smart merge for JSON files |
| jsonc-merge |
|
JSONC | tree-sitter-jsonc (via tree_haver) | ⚠️ Proof of concept; Smart merge for JSON with Comments |
| markdown-merge |
|
Markdown | Commonmarker / Markly (via tree_haver), Parslet | Foundation: Shared base for Markdown mergers with inner code block merging |
| markly-merge |
|
Markdown | Markly (via tree_haver) | Smart merge for Markdown (CommonMark via cmark-gfm C) |
| prism-merge |
|
Ruby |
Prism (prism std lib gem) |
Smart merge for Ruby source files |
| psych-merge |
|
YAML |
Psych (psych std lib gem) |
Smart merge for YAML files |
| rbs-merge |
|
RBS |
tree-sitter-rbs (via tree_haver), RBS (rbs std lib gem) |
Smart merge for Ruby type signatures |
| toml-merge |
|
TOML | Parslet + toml, Citrus + toml-rb, tree-sitter-toml (all via tree_haver) | Smart merge for TOML files |
Backend Platform Compatibility
tree_haver supports multiple parsing backends, but not all backends work on all Ruby platforms:
| Platform 👉️ TreeHaver Backend 👇️ |
MRI | JRuby | TruffleRuby | Notes |
|---|---|---|---|---|
| MRI (ruby_tree_sitter) | ✅ | ❌ | ❌ | C extension, MRI only |
| Rust (tree_stump) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
| FFI (ffi) | ✅ | ✅ | ❌ | TruffleRuby’s FFI doesn’t support STRUCT_BY_VALUE
|
| Java (jtreesitter) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
| Prism (prism) | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
| Psych (psych) | ✅ | ✅ | ✅ | YAML parsing, stdlib |
| Citrus (citrus) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
| Parslet (parslet) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
| Commonmarker (commonmarker) | ✅ | ❌ | ❓ | Rust extension for Markdown (via commonmarker-merge) |
| Markly (markly) | ✅ | ❌ | ❓ | C extension for Markdown (via markly-merge) |
Legend: ✅ = Works, ❌ = Does not work, ❓ = Untested
Why some backends don’t work on certain platforms:
-
JRuby: Runs on the JVM; cannot load native C/Rust extensions (
.sofiles) -
TruffleRuby: Has C API emulation via Sulong/LLVM, but it doesn’t expose all MRI internals that native extensions require (e.g.,
RBasic.flags,rb_gc_writebarrier) - FFI on TruffleRuby: TruffleRuby’s FFI implementation doesn’t support returning structs by value, which tree-sitter’s C API requires
Example implementations for the gem templating use case:
| Gem | Purpose | Description |
|---|---|---|
| kettle-dev | Gem Development | Gem templating tool using *-merge gems |
| kettle-jem | Gem Templating | Gem template library with smart merge support |