Skip to content

Vim 'db' action deletes the character under the cursor #181

Closed

Description

@zhengqunkoo

What happened

I was clearing part of a line with 'dbdbdbdb' and realised that with every 'db', a single character under the cursor was being deleted, so that at the end of my action, a good chunk of the word under my cursor was gone.

Similar issue with 'cb'.

What you expected

In Vim a 'db' action clears text to the left of the cursor until the start of the word. However in Rune it clears text from the character under the cursor until the start of the word.

A test should be added for this issue.

Steps to reproduce

  1. Open a Vim editor in Rune
  2. Type some text and move around
  3. Delete it with 'db' and 'cb'

Area

Editor and text handling

Rune version

v1.3.0-beta.1-26-g4c964e0b

OS and architecture

Ubuntu 26.04

Shell

No response

Logs, crash report, or screenshots

Relevant configuration

Checks

  • I searched existing issues and this is not a duplicate.
  • I can reproduce this on the latest released version.

Activity

  1. dhruv1220 commented on Oct 6, 2026

    @dhruv1220

    I traced the code path for this (on current main) — posting in case it saves whoever picks it up some digging.

    Where it happens: handleMetaNormal in internal/text/vi/handler.go (the <op>wWeEbB idiosyncrasies switch). For db/cb the flow is:

    1. vi.cursor.Select() anchors a non-explicit selection at the cursor (before),
    2. handleNormal runs the b motion, moving the cursor to the word start (after),
    3. handleDelete calls DeleteSelection() on that selection.

    Why the cursor char is eaten: the vi handler sets RightInclusiveSemantics: true, and Cursor.SelectionRange() folds that in for non-explicit selections (to.X++). So the operator range is effectively [after, before] — right-inclusive — while Vim's b motion is exclusive and the range should be [after, before). Same root cause covers cb (change goes through the same operator path).

    Fix shape: in the case 'b', 'B' branch, shrink the anchor end by one so the character under the original cursor is excluded — e.g. reselect as SelectRange(after, before) (which is documented right-exclusive [start, end)), mirroring how selectWordOperatorRange already pulls the w endpoint back with MoveLeft() for the same class of exclusivity. The multi-line branch (before.Y > after.Y) would need the same treatment for the anchor end. A regression test in handler_test.go in the style of TestViOperatorGoLeftEndWordMotions (drive db/cb key events, assert buffer text keeps the char that was under the cursor) would cover it.

    Happy to turn this into a PR if a maintainer confirms the direction.

  2. added a commit that references this issue on Oct 7, 2026
    9f7bed2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions