Skip to content

feat: handle insert mode#2

Open
abhinav wants to merge 1 commit intovito:mainfrom
abhinav:insert-mode
Open

feat: handle insert mode#2
abhinav wants to merge 1 commit intovito:mainfrom
abhinav:insert-mode

Conversation

@abhinav
Copy link
Copy Markdown

@abhinav abhinav commented Apr 2, 2026

Handle ANSI terminal mode 4 as terminal state,
so printable input inserts into the active row
instead of always overwriting content.

ANSI CSI 4 h enables insert mode,
and CSI 4 l restores normal overwrite mode.
If a program prints:

echo -ne 'abcde\r\033[3C\033[4h \033[4l\n'

# \r        = CR, move to column 0
# \033[3C   = CSI 3 C, move right 3 columns
# \033[4h   = CSI 4 h, enable insert mode
# " "       = insert a space at the cursor,
#             shifting existing text right
# \033[4l   = CSI 4 l, disable insert mode
# \n        = LF, move to the next line

a terminal should show:

abc de

The space is inserted at column 3,
and the existing de shifts one cell to the right.

Before this change,
midterm painted the space as a normal overwrite,
so it effectively read the sequence as:

abc e

(I ran into this bug while migrating a project to Bubble Tea v2.
Bubble Tea v2 uses insert mode to optimize rendering when relevant.)

The fix is relatively straightforward:
track and reset the insert mode bit as needed,
and shift the active row before writing runes when insert mode is enabled.

Handle ANSI terminal mode `4` as terminal state,
so printable input inserts into the active row
instead of always overwriting content.

ANSI `CSI 4 h` enables insert mode,
and `CSI 4 l` restores normal overwrite mode.
If a program prints:

    echo -ne 'abcde\r\033[3C\033[4h \033[4l\n'

    # \r        = CR, move to column 0
    # \033[3C   = CSI 3 C, move right 3 columns
    # \033[4h   = CSI 4 h, enable insert mode
    # " "       = insert a space at the cursor,
    #             shifting existing text right
    # \033[4l   = CSI 4 l, disable insert mode
    # \n        = LF, move to the next line

a terminal should show:

    abc de

The space is inserted at column 3,
and the existing `de` shifts one cell to the right.
Before this change,
midterm painted the space as a normal overwrite,
so it effectively read the sequence as:

    abc e

The bug showed up in Bubble Tea redraws
that briefly enabled insert mode around ordinary glyphs
during prompt updates.
midterm moved the cursor correctly
and printed the glyphs,
but it did not interpret `CSI 4 h`
when handling ordinary printable input.
That meant inserted glyphs overwrote the cell under the cursor
instead of shifting the remainder of the row right.

Fix printable input to honor insert mode
by shifting the active row at the cursor
before painting the rune,
and clear that state on reset
so overwrite mode is restored predictably.

(Also delete the unused 'eachFrame' function from terminal_test.go.)
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.

1 participant