Skip to content

fix: preserve relative indent when pasting multi-line charwise blocks (]p/[p) - #14

Merged
nemanjamalesija merged 1 commit into
mainfrom
fix/charwise-block-reindent
Jun 30, 2026
Merged

nemanjamalesija merged 1 commit into
mainfrom
fix/charwise-block-reindent

Conversation

@nemanjamalesija

@nemanjamalesija nemanjamalesija commented Jun 30, 2026 •

Copy link
Copy Markdown
Owner

Fixes #11.

The real bug

<DateField.Group>
  <Button>Select Month</Button>
</DateField.Group>
<DateField.Group>
      <Button>Select Month</Button>   // before: over-indented
    </DateField.Group>                // before: over-indented

Cause

A charwise selection (e.g. ^v...y) drops the first line's leading whitespace, but the inner lines keep their absolute indent. The ]p/[p path then shifted every line by a single delta computed from the first line — so the inner lines got the block's original base indent counted twice. (Vim's native ]p has the same flaw; smart-paste should do better.)

"Copying the whole line" worked because that's a linewise yank, which keeps the first line's indent and goes through a different path.

Fix

When a block dedents back below its first inner line (a closing tag/brace — the normal shape of a JSX element, {}, () block), the first line is an opener whose true base equals the block's minimum inner indent. Reconstruct it to that base before shifting, so the block's relative structure is preserved.

Blocks that never dedent (e.g. if x: + body, where the first line genuinely sits at column 0) keep the first line at 0 — existing behavior is unchanged.

After:

<DateField.Group>
  <Button>Select Month</Button>
</DateField.Group>
<DateField.Group>
  <Button>Select Month</Button>   // matches the original
</DateField.Group>

Tests

  • indent_spec.lua: unit tests for the new rebase_charwise_block (dedenting block, non-dedenting block, single line).
  • charwise_paste_spec.lua: ]p of a multi-line block from a mid-line charwise selection now matches the original structure instead of over-indenting.

All existing specs and integration checks pass.

Charwise selections (e.g. `^v...y`) drop the first line's leading
whitespace but keep the inner lines' absolute indent. ]p / [p then
shifted every line by a single delta, which over-indented the inner
lines by the block's original base indent -- visible in JSX/TSX where
copying a `<Foo>...</Foo>` block and pasting it landed the children and
closing tag too deep.

When a block dedents back below its first inner line (a closing tag or
brace), reconstruct the first line's base from the block's minimum inner
indent before shifting, so the block's relative structure is preserved.
Blocks that never dedent (e.g. `if x:` + body) keep the first line at
column 0, matching previous behaviour.

Fixes #11
@nemanjamalesija
nemanjamalesija merged commit 85993bd into main Jun 30, 2026
6 checks passed
@nemanjamalesija
nemanjamalesija deleted the fix/charwise-block-reindent branch June 30, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect pasting indentation for tsx

1 participant