Skip to content

確定アンドゥした位置にカーソルを戻す - #261

Merged
Shougo merged 1 commit into
vim-skk:mainfrom
delphinus:feat/kakutei-undo-return-point
Sep 22, 2026
Merged

Shougo merged 1 commit into
vim-skk:mainfrom
delphinus:feat/kakutei-undo-return-point

Conversation

@delphinus

@delphinus delphinus commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

問題

#260 で確定アンドゥがカーソルを戻すようになったため、選び直した候補を確定した後、カーソルが行の途中に取り残されます。

各停する|     ここで <C-z>
▼各停|する
確定|する     選び直して確定。カーソルはそのまま

続きを打った後に使うのが #260 の狙いですが、そのために再確定後の手順が増えています。

直し方

確定アンドゥを実行した場所を覚えておき、選び直したものが書かれた後にそこへ戻します。長さの違う候補を選んだ場合はその差だけずらすので、カーソルは桁ではなく文章中の位置を保ちます。

カーソルを動かさなかった確定アンドゥでは戻す先が確定した文字列の末尾と重なるので、見た目には何も起きません。

実装としては、▼ からの確定は戻す先を HandleResult に載せてキー処理の戻り値と一緒に返し、補完での確定は既にバッファへ書かれた後なので skkeleton#restore_point() を直接呼びます。前者がこの PR で唯一、確定アンドゥ以外の戻り値に触る部分です。

ddskk との違い

ddskk にも skk-undo-kakutei-return-previous-point として存在します。2007 年に後から足されたユーザオプションで、デフォルトは nil です。長さの差だけずらす計算も skk-kakutei の中のものと同じにしました。

今回は確定アンドゥ自体実装したばかりですから、オプションにせず常に有効にしています。カーソルが飛ぶようにした以上、その後始末までで一つの機能だと考えました。

動作確認

  • deno task fmt-check / lint 指摘なし、deno check 通ります。
  • DENOPS_TEST_DENOPS_PATH を設定して全テストを実行し、続きを打った後でも確定アンドゥ出来るようにする #260 をマージした main で 118 passed / 0 failed → この PR で 126 passed / 0 failed。
  • 追加した実バッファ (Neovim) のテストは 8 本です。
    • テスト (9 バイト) を 試 (3 バイト) に選び直し、カーソルが行末 (桁 10) に戻ること、素直に確定した場合の桁 4 ではないこと。
    • ▼ から ▽ に戻して補完で確定した場合も戻ること。
    • 補完エンジンが選択中の候補を差し込んでも、覚えた桁が消えないこと。
    • 候補を選んだまま大文字キーで新しい変換を始めた場合、カーソルがそちらに残ること。
    • <C-g> で読みごと取り消した後は、無関係な確定でカーソルが動かないこと。
    • 同梱の completefunc でも、候補を選んだまま大文字キーを押したときカーソルが残ること。
    • ▼ から大文字キーで確定して新しい変換が始まったとき、カーソルがそちらに残ること。
    • <CR> の確定が改行を入れたとき、前の行の桁へ戻らないこと。

doc/skkeleton-functions.jax に記述を足しています。

🤖 Generated with Claude Code

@Shougo

Shougo commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

@delphinus #260 は既にマージしたので、こちらは rebase してください

Taking a kakutei back now walks the cursor to it, so confirming something
else leaves the cursor in the middle of the line rather than where the undo
was asked from. Typing on is the case the previous commit is for, which makes
this the common way out of it: notice the mis-conversion, undo, pick, and then
have to walk back by hand to carry on.

Remember where the undo was asked from and put the cursor there once the
replacement has been written. Something of another length shifts the column by
the difference, so the cursor keeps its place in the text rather than its
column.

ddskk has this as skk-undo-kakutei-return-previous-point and leaves it off by
default. It is on here, and not configurable, because the situation only
arises from the previous commit: before it, the undo could not move the cursor
at all, so there was nothing to come back from. The length adjustment is the
one skk-kakutei-subr does.

The place reaches Vim by two routes, because the text reaches the buffer by
two:

  - A kakutei out of a henkan is written by the keys the key handling returns,
    so the place rides along at the end of the same feedkeys(). That needs
    restoreLnum / restoreCol on the handle result -- the one part of this which
    touches the return path of every key handling rather than the undo alone.
  - A completion source has already written when it reports through
    completeCallback, so there are no keys to ride along with and
    skkeleton#restore_point() is called right away.

Three things have to hold for the cursor to be sent back.

The undo has to still own the spot. That is asked at the start of each key
handling, and before the pre-edit mismatch resets the state: a source which
writes the candidate it is only selecting makes the buffer disagree with the
pre-edit, and the reading it is about to complete is very much still pending.
Taking the reading all the way back with cancel does drop it.

Nothing else may have been started where the cursor now is. One key can
confirm and open a henkan after it -- an uppercase key does both -- and the
cursor belongs to the one it opened. For a kakutei out of a henkan that is
settled once the handling is over; for a completion the confirmation can
arrive later still, since CompleteDone fires after the mapping of the key
which ended the completion (measured) and an engine of its own may schedule
the report on top of that, so it is answered with whether skkeleton is done or
is still on the very reading being confirmed.

The cursor has to be on the line the undo happened on. A kakutei out of <CR>
inserts a newline unless eggLikeNewline is set, and a column of the line it
came from means nothing on the next one.

An undo which never moved the cursor records the column the kakutei ends at
anyway, so nothing visibly happens for it.

確認:
  deno task fmt-check / lint  指摘なし
  deno check main.ts  通る
  DENOPS_TEST_DENOPS_PATH を設定して全テスト
    前のコミット 118 passed / 0 failed
    このコミット 126 passed / 0 failed  (追加した 8 件ぶん)
  doc/skkeleton-functions.jax  追加分は表示幅 78 桁以内
  autoload/skkeleton.vim  Vim 9.1 / Neovim の双方で読める

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@delphinus
delphinus force-pushed the feat/kakutei-undo-return-point branch from 607a57d to 329ead1 Compare September 22, 2026 05:48
@delphinus
delphinus marked this pull request as ready for review September 22, 2026 05:49
@delphinus

Copy link
Copy Markdown
Contributor Author

@Shougo 直しました。ご確認ください。

@Shougo
Shougo merged commit 8998089 into vim-skk:main Sep 22, 2026
2 checks passed
@Shougo

Shougo commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

マージします

@delphinus
delphinus deleted the feat/kakutei-undo-return-point branch September 22, 2026 06:01
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.

2 participants