Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions FIX_PROPOSAL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
To fix the issue, you need to apply the `count` value to widen the range in the `r + next-character` flow. Here's the exact code fix:

```typescript
// In VimMode.tsx, replace the lines 1854-1863 with the following code:
if (info.key === 'r') {
const count = vim.getEffectiveCount();
const range = new monaco.Range(
info.lineNumber,
info.column,
info.lineNumber,
Math.min(info.column + count, editor.getModel().getLineMaxColumn(info.lineNumber))
);
editor.executeEdits('vim-replace', [
{
range,
text: nextChar,
},
]);
Comment on lines +13 to +18
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Monaco Editor, when executeEdits replaces a range of N characters with a 1-character string, does it collapse the text length to 1? Please cite the official Monaco API/docs for ICodeEditor.executeEdits behavior.

💡 Result:

Yes, in Monaco Editor, when ICodeEditor.executeEdits replaces a range of N characters with a 1-character string, it replaces the entire range with exactly that 1-character string, collapsing the text length in that range to 1 character (net change of 1 - N characters).

Citations:


Use nextChar.repeat(actualCount) to preserve replacement width with multi-character ranges.

When executeEdits replaces a range spanning multiple columns with a single character, Monaco Editor collapses the text length to 1 character. For Vim's r command with count, each matched character should be replaced individually, not collapsed. Calculate the actual replacement count and repeat the character accordingly.

Suggested patch
-  editor.executeEdits('vim-replace', [
+  const endColumn = Math.min(
+    info.column + count,
+    editor.getModel().getLineMaxColumn(info.lineNumber)
+  );
+  const actualCount = Math.max(0, endColumn - info.column);
+  editor.executeEdits('vim-replace', [
     {
       range,
-      text: nextChar,
+      text: nextChar.repeat(actualCount),
     },
   ]);
-  setLastChange({ range, count });
+  setLastChange({ range, count: actualCount });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@FIX_PROPOSAL.md` around lines 13 - 18, The replacement collapses multi-column
ranges to a single character because editor.executeEdits is called with text:
nextChar; update the logic that handles the Vim 'r' command to compute the
actualCount of characters in the target range (e.g., using the range length or a
helper that counts columns) and pass text: nextChar.repeat(actualCount) to
editor.executeEdits so each position is replaced individually and the
replacement width is preserved; reference the variables/methods range, nextChar,
actualCount, and editor.executeEdits when making the change.

setLastChange({ range, count });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Persist the applied count, not the requested count.

At Line 19, storing count can be incorrect when Math.min(...) clips the range at EOL. Persist actualCount = range.endColumn - range.startColumn to keep repeat behavior accurate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@FIX_PROPOSAL.md` at line 19, You're persisting the requested count instead of
the actual applied count; change the call to setLastChange to save actualCount =
range.endColumn - range.startColumn (i.e., compute the applied width after the
Math.min/EOL clipping) rather than the incoming count so repeat behavior uses
the real applied range. Locate the code around setLastChange({ range, count })
and replace the persisted count with the computed actualCount derived from
range.endColumn - range.startColumn (ensure range is the post-clipping range
produced by the Math.min logic).

}
```

This code applies the `count` value to widen the range, replacing the specified number of characters. The `Math.min` function ensures that the replacement does not exceed the end of the line. The `setLastChange` function is also updated to reflect the correct count.
Comment on lines +1 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

PR currently ships a proposal, not the bug fix implementation.

Line 1 through Line 23 only add guidance text in FIX_PROPOSAL.md; no executable change to VimMode.tsx or tests is included here. This means the reported bug remains unfixed in this PR state.

🧰 Tools
🪛 LanguageTool

[style] ~1-~1: Consider using a different verb for a more formal wording.
Context: To fix the issue, you need to apply the `count...

(FIX_RESOLVE)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@FIX_PROPOSAL.md` around lines 1 - 23, The PR only added a proposal file and
didn't change VimMode.tsx; update the actual handler for the 'r' key in
VimMode.tsx so it uses vim.getEffectiveCount() to widen the replacement range:
compute a monaco.Range from info.lineNumber, info.column to Math.min(info.column
+ count, editor.getModel().getLineMaxColumn(info.lineNumber)), call
editor.executeEdits('vim-replace', [{ range, text: nextChar }]), and call
setLastChange({ range, count }) so the replacement applies the requested count
and respects line end bounds.