[Bug] Exiting Visual mode at end of line leaves the Normal-mode cursor past the final character
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 65/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- javascript, vim
- 領域
- devtools
調査の方向性
The bug is in the exitVisualMode function in packages/codemirror-vim-core/vim.js. Start by reading the reproduction steps and the provided code snippet to understand the cursor behavior. Examine the clipCursorToContent helper and how visual mode flags are cleared. The candidate fix shows the necessary reordering of operations. Test the fix with the provided minimal setup and check edge cases like empty lines and supplementary characters.
索引モデルが issue の本文から書いたものです。
説明
Related: #38 reports entering an invalid end-of-line cursor position by clicking with the mouse. This report reproduces a similar symptom entirely through Vim keys and identifies a separate path in exitVisualMode.
Versions and environment
@replit/codemirror-vim: 6.4.0@replit/codemirror-vim-core: 0.1.0@codemirror/state: 6.7.5@codemirror/view: 6.43.12- Reproduced in native macOS WebKit, both with a bare CodeMirror editor and in an application integration.
Reproduction
- Start with a single line containing
alpha, with the cursor onain Normal mode. - Press
v, then presslfive times to reach the position after the final character. - Press Escape.
- Press
lonce more.
After step 3, the Normal-mode cursor remains at zero-based column 5, after the final a. Step 4 moves it backward to column 4 despite being a rightward motion.
Expected: Escape should leave the Normal-mode cursor at column 4 immediately, and the following l should not move it. Unconfigured Vim behaves this way.
Minimal setup and programmatic reproduction:
import { EditorView, drawSelection } from '@codemirror/view';
import { vim, Vim, getCM } from '@replit/codemirror-vim';
const view = new EditorView({
doc: 'alpha',
extensions: [vim(), drawSelection()],
parent: document.body,
});
const cm = getCM(view);
for (const key of ['v', 'l', 'l', 'l', 'l', 'l', '<Esc>']) {
Vim.handleKey(cm, key, 'user');
}
console.log(cm.getCursor()); // Actual: { line: 0, ch: 5 }; expected ch: 4
Vim.handleKey(cm, 'l', 'user');
console.log(cm.getCursor()); // { line: 0, ch: 4 }
Apparent cause and candidate fix
In packages/codemirror-vim-core/vim.js, exitVisualMode calls clipCursorToContent before clearing vim.visualMode. That helper permits the line-break position while Visual mode is active, so it uses Visual-mode bounds for the resulting Normal-mode cursor.
Moving the cursor-clipping block after clearing the Visual-mode flags corrects this reproduction. updateLastSelection must still run before clearing the flags so gv retains the previous selection:
function exitVisualMode(cm, moveHead) {
var vim = cm.state.vim;
updateLastSelection(cm, vim);
vim.visualMode = false;
vim.visualLine = false;
vim.visualBlock = false;
if (moveHead !== false) {
cm.setCursor(clipCursorToContent(cm, vim.sel.head));
}
if (!vim.insertMode) CM.signal(cm, "vim-mode-change", {mode: "normal"});
}
Local checks with that change covered nonempty and empty lines, a supplementary-plane emoji, gv, visual yank, linewise put, and undo.
- 主要言語
- JavaScript
- スター
- 477
- フォーク
- 55
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
replit/codemirror-vim のほかの issue
-
難易度 4/5 3〜5日 初心者へのやさしさ 50/100
replit/codemirror-vim#276 ·
-
Curly Brace deletion behaving unexpectedly対応中かも @deepanshupal が 15 日前に担当しました。 オープン
難易度 3/5 1〜2日 初心者へのやさしさ 68/100
replit/codemirror-vim#264 ·
-
`vim-mode-change` not fired on command mode enter/exit対応中かも @oller が 1 日前に担当しました。 オープン
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
replit/codemirror-vim#251 · コメント 1 件 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
replit/codemirror-vim#243 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
replit/codemirror-vim#239 ·
replit/codemirror-vim の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 79/100
SACGF/variantgrid#2341 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
Unsampled pageload span is profiled when profileLifecycle is 'trace' (browser UI profiling)対応中かも @Jxxunnn が今日担当しました。 オープンBrowser Waiting for: Product Owner
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
getsentry/sentry-javascript#25497 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
external-plugin needs-review:HIGH ready-for-review
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
github/awesome-copilot#5162 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信