{"issue":{"created_at":"2011-11-29T07:28:12Z","state":"open","updated_at":"2011-11-30T07:47:54Z","comments":39,"user":{"gravatar_id":"7f5a1bfaf8b64cbcdfaf82a7de92506b","id":41495,"url":"https://api.github.com/users/Shougo","avatar_url":"https://secure.gravatar.com/avatar/7f5a1bfaf8b64cbcdfaf82a7de92506b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","login":"Shougo"},"body":"neocomplcacheを使っていると、register-.の値がおかしくなるので調べていたんですが、原因が分かりました。\r\n\r\nregister-.がおかしくなる条件は、「neocomplcacheで単語の一部を補完すること」です。\r\n\r\n例えば、hogeのhoの部分からhogeraを補完したとします。\r\nこのとき、register-.にはgeraが入って欲しいのですが、hogeraが入ってしまいます。\r\nこれはなぜそうなるかというと、補完位置がhogeの前となるからです。\r\n|hoge（|はカーソル）の位置で補完されるので、Vimからは「hogeraが入力された」と錯覚するのでしょう。\r\n\r\nちなみに、これはneocomplcacheでのみ発生する話ではありません。\r\nオムニ補完やユーザー定義補完でも同様に発生します。\r\nneocomplcacheの場合、毎回補完が発生するのでその現象に気付きやすいというだけです。\r\n\r\nneocomplcacheで対処しようと思いましたが、register-.は読みとり専用であり、\r\n今のところVim scriptから補完候補が選択されたということを知る術もないため対処が困難でした。\r\n\r\nちなみに、Vim組み込みの補完では問題ありません。\r\nまぁ、こちらは絶対にカーソルにマッチする候補しか出てこないので当然ですが……。\r\n\r\n改善する場合は、「a:baseにマッチする部分はregister-.から除外する」となると思います。\r\nつまり、先ほどの例では、hogeraはa:baseのhoにマッチするのでgeraとなる、ということです。\r\nこのマッチのとき、マッチには大文字小文字を区別しないほうが良いような気がします。","assignee":null,"id":2379792,"number":97,"pull_request":{"patch_url":null,"html_url":null,"diff_url":null},"labels":[{"name":"discuss","color":"AA55AA","url":"https://api.github.com/repos/vim-jp/issues/labels/discuss"}],"title":"補完時のregister-.の挙動の改善","html_url":"https://github.com/vim-jp/issues/issues/97","closed_at":null,"url":"https://api.github.com/repos/vim-jp/issues/issues/97","milestone":null},"action":"created","comment":{"created_at":"2011-11-30T07:47:54Z","updated_at":"2011-11-30T07:47:54Z","user":{"gravatar_id":"1ba93fd9e39ebf48777f217c38e768fd","id":10111,"url":"https://api.github.com/users/mattn","avatar_url":"https://secure.gravatar.com/avatar/1ba93fd9e39ebf48777f217c38e768fd?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","login":"mattn"},"body":"ちょっと解析してみました。\r\n\r\n例題は上記の `document` から `docua` への変更トリガ\r\n\r\n    1. document の m の部分(この時colは9)で cw で発動して neocomplcache#manual_complete が呼ばれる\r\n    2. neocomplcache#manual_complete は新仕様でalwaysを返している\r\n    3. この後自動で neocomplcache#auto_complete が呼ばれる\r\n    4. auto_complete から a:findstart = 1 として manual_complete が呼ばれる\r\n    5. 補完開始位置として cur_keyword_pos を 4 として返す\r\n\r\n今回おかしくなったのは、この9と4で差異が発生した為。ここからvimの内部の話。\r\nvimはユーザ補完もしくはオムニ補完が発動すると\r\n\r\n    6. 補完開始位置を貰ってそれを補完候補の表示開始位置にする\r\n    7. 補完中の入力位置(compl_pos)を 6 で設定した値で初期化\r\n\r\nここで問題なのが、通常の補完や以前の動きのままの場合はこの流れで良いのですが `always` が設定されるという事は、補完中の入力位置は度初期化(ins_compl_restart)したとしても変わるべきじゃないということ。\r\n`always` が設定される事で、昔の仕様としては正しかった 7 の部分の意味がおかしくなります。\r\n\r\n```diff\r\ndiff -r 379a6398d462 src/edit.c\r\n--- a/src/edit.c\tWed Oct 26 23:48:21 2011 +0200\r\n+++ b/src/edit.c\tWed Nov 30 16:30:51 2011 +0900\r\n@@ -5182,10 +5196,12 @@\r\n \t     * Reset extended parameters of completion, when start new\r\n \t     * completion.\r\n \t     */\r\n+\r\n+\t    if (col < 0 || compl_opt_refresh_always)\r\n+\t\tcol = curs_col;\r\n+\r\n \t    compl_opt_refresh_always = FALSE;\r\n \r\n-\t    if (col < 0)\r\n-\t\tcol = curs_col;\r\n \t    compl_col = col;\r\n \t    if (compl_col > curs_col)\r\n \t\tcompl_col = curs_col;\r\n```\r\n\r\nこの様に `always` が設定されていた場合には、補完継続中を意味するはずなのでユーザ補完関数から得た補完開始位置を信じずにカーソル位置で続行する様にすればうまく動きました。\r\n信じないようにするので、いっそユーザ補完関数を呼ばないという手もありますが、ひとまず解析結果を皆さんに周知。\r\n","id":2956237,"url":"https://api.github.com/repos/vim-jp/issues/issues/comments/2956237"}}