logo
Kurashizu Blogwhere ideas flow
  • Home
  • News
  • Blog
  • About
  • Home
  • News
  • Blog
  • About

© 2026 Kurashizu. All rights reserved.

Admin·New Post·Service Status
Powered by Cloudflare·31.10.26
← Back to news

Magic Move for Code Snippets from first principles

Original article
rahulrav.com|10 points|0 comments|by rahulrav|Sep 7, 2026

Magic Move for Code Snippets from first principles

September 06, 2026, Monday

Introduction

Since its release, the Framework 16 has been my primary machine. For a significant period, I maintained a fragile truce by dual-booting Windows and Ubuntu. However, by late 2025, I decided to clear the slate entirely and migrate fully to CachyOS.

While the reasons for this switch deserve their own post, the summary is simple: I am thrilled. Lately, using macOS has felt like an exercise in frustration. I cannot fathom why Apple chose to sacrifice raw desktop performance in exchange for "Liquid Glass" aesthetics.

Fortunately, almost every tool in my workflow has a native Linux version, and where they don't, I've found excellent alternatives. There was, however, one significant loss that gave me pause: Apple Keynote, and specifically its Magic Move feature.

For a frequent conference speaker, presentation tools aren't just about aesthetics—they are the narrative scaffolding of a talk. Keynote allowed me to make dense, technical explanations appear seamless and effortless.

Magic Move, and Its Shortcomings

Despite its power, Magic Move possesses a critical flaw: it is terrible at animating code snippets.

If you have ever attempted to transition between two blocks of code in Keynote, you know the nightmare. You watch as a val from line 1 flies haphazardly across the screen to merge into the al of a calculate() function, while semicolons and brackets scramble like alphabet soup.

To achieve a professional look, you are forced into sane insane workarounds:

  • Creating invisible bounding boxes to split lines.
  • Inserting transparent "dummy" characters to trick the engine.
  • Manually pixel-nudging tokens to ensure a simple three-line refactor looks clean.

It is possible to make it look magical, but only through absolute brute force.

The reward for this effort is high. After nearly every presentation, the most common question isn't about the system architecture, but rather:

"How on earth did you create those amazing animations?"

As a member of the Jetpack Compose team—a UI toolkit that is now fully multiplatform—this topic is a recurring theme. It has become an annual tradition during Google I/O or other major events for a teammate to witness a broken transition and suggest: "Why don't we just build our entire slide deck in Compose so the code animates correctly?"

Some daring individuals have actually attempted this using Compose's Shared Element transitions.

  • Abandon WYSIWYG tools entirely.
  • Stick with Keynote for layout, typography, and non-code elements.
  • Fight Apple's increasing subscription-based template gatekeeping.

I personally wasn't brave enough to give up the layout efficiency of Keynote.

The Trigger

A few weeks ago, I encountered a project on Hacker News called Bento. It is an extensible, fully local, and offline presentation toolkit. The project is incredibly polished and definitely deserves your attention.

Bento already supports "morphing" for basic shapes and mathematical expressions. From my perspective, the only missing piece was the ability to morph code snippets.

Research

I decided to investigate what it would take to implement this. Naturally, I started by reviewing existing literature. Since "diffing" content is a foundational problem in computer science, there was plenty to find.

We interact with this daily as developers via git diff. The industry standards are typically Myers diff and Patience diff, both of which aim to find the shortest edit distance between two sequences. There have also been attempts within the Android/Kotlin community to recreate Magic Move using Compose.

Intuition: When Math Makes for Bad Animations

After reviewing these methods, I realized that Myers diff solves the wrong problem for visual animations.

Myers diff is mathematically elegant because it finds the absolute shortest sequence of edits to transform String A into String B. However, the mathematically "optimal" path is often visually jarring. If a variable is renamed or shifted, Myers might decide to delete three characters here and insert two there—potentially slicing an identifier in half—simply because it saves one edit step.

In the context of animation, human perception outweighs mathematical minimality. We don't want the fewest operations; we want visual continuity. We want tokens to glide smoothly to their new homes or fade out gracefully.

This led me to a 1978 paper by Paul Heckel: A technique for isolating differences between files (Communications of the ACM, Volume 21, Issue 4).

Heckel's approach is fundamentally different. The algorithm operates in linear time: Time Complexity: O(n)\text{Time Complexity: } O(n)Time Complexity: O(n)

It feels perfectly suited for animations. Given my experience with Kotlin and Jetpack Compose, I began experimenting with adapting this paper to compute differences between token streams rather than treating code as raw text.

Defining what to diff

The first step is converting a code snippet into a stream of tokens. The instinctive reaction is often: "Let's use an Abstract Syntax Tree (AST)!"

However, ASTs are a trap for presentation snippets because:

  1. Language Overhead: We want to support many languages without bundling massive compiler infrastructures.
  2. Fragility: Speakers often use partial snippets, omit imports, or use pseudo-code. A strict parser would crash on these.

Instead, we need a general representation of what tokens and fragments mean. This is the same challenge text editors face when providing fast, fault-tolerant syntax highlighting.

The industry standard for this is TextMate grammars. Originally created for the TextMate editor, this format was adopted by VS Code, Sublime Text, and Eclipse. Essentially, a grammar is a prioritized list of rules...


Conceptual Workflow

Comparison of Diffing Approaches

FeatureMyers DiffHeckel Algorithm
GoalShortest Edit DistanceIdentifying Unique Matches
ComplexityO(ND)O(ND)O(ND)O(n)O(n)O(n)
Visual ResultOften jarring/fragmentedHigh visual continuity
Best Use Casegit diff / PatchingUI Animations / Morphing

Example Token Stream Representation

// Conceptual representation of a tokenized line
data class Token(
    val text: String,
    val type: TokenType, // e.g., KEYWORD, IDENTIFIER, OPERATOR
    val position: Int
)

val stream = listOf(
    Token("val", TokenType.KEYWORD, 0),
    Token(" ", TokenType.WHITESPACE, 3),
    Token("x", TokenType.IDENTIFIER, 4)
)