> [!warning] > 執筆当時の環境で起こっていたものであり、 #2025/04/06 時点の [[blink.cmp (Neovim)|blink.cmp]]、[[blink.compat (Neovim)|blink.compat]]、[[obsidian.nvim]]では発生しない。むしろこの対応のせいでバグになってしまっている。詳細は [[📜2025-04-06 obsidian.nvimをblink.cmpに対応]] を参照。 ## 事象 赤枠の選択肢を挿入すると **カーソル位置によって** 結果が変わる。 ![[Pasted image 20250323213309.png]] | 挿入場所 | 結果 | OK/NG | | ------- | ----------------------- | ----- | | \|あいうえお | `[[AIに関する雑記]]あいうえお` | OK | | あ\|いうえお | `あ[[[[AIに関する雑記]]えお` | NG | | あい\|うえお | `あい[[ai[[ai]]うえお` | NG | | あいう\|えお | `あいう[[ai[[AIに関する雑記]]えお` | NG | | あいうえ\|お | `あいうえ[[AIに関する雑記]]お` | OK | | あいうえお\| | `あいうえお[[AIに関する雑記]]` | OK | なお、[[ASCII]]の場合は問題は発生しない。 ### 環境 | 対象 | バージョン | | ----------------- | ------------------ | | [[Ubuntu]] | 24.04.1 LTS | | [[Neovim]] | 0.10.3 | | [[obsidian.nvim]] | `e5f4791` (fork版) | | [[nvim-cmp]] | ??? | ## 調査 [[Claude 3.7 Sonnet]]が言うには `can_complete` の中でマルチバイト文字が考慮されていないため、insert位置が不正になっているのが問題ではないかとのこと。 `あ|い` と `a|i` では `insert_start` が 3 or 1 で変わる。これはバイト数。 ```lua local insert_start = vim.str_byteindex(before_line, cursor_char_idx - input_char_len) ``` 一旦AIの結果を反映したがうまくいかない。一旦ログ仕込む。 ```lua M.can_complete = function(request) local input, search = find_search_start(request.context.cursor_before_line) if input == nil or search == nil then return false elseif string.len(search) == 0 or util.is_whitespace(search) then return false end -- マルチバイト文字考慮 local cursor_col = request.context.cursor.col local before_line = request.context.cursor_before_line if vim.startswith(input, "[[") then local suffix = string.sub(request.context.cursor_after_line, 1, 2) local insert_end_offset = suffix == "]]" and 1 or -1 -- 文字インデックスでの挿入開始位置を計算 local cursor_char_idx = vim.str_utfindex(before_line, #before_line) local input_char_len = vim.str_utfindex(input, #input) local insert_start = vim.str_byteindex(before_line, cursor_char_idx - input_char_len) local origin_insert_start = vim.str_utfindex(cursor_col - 1 - #input) print( string.format( "🪵 L55 suffix=%s, insert_end_offset=%s, cursor_char_idx=%s, input_char_len=%s, insert_start=%s, origin_insert_start=%s", suffix, insert_end_offset, cursor_char_idx, input_char_len, insert_start, origin_insert_start ) ) return true, search, insert_start, cursor_col + insert_end_offset, M.RefType.Wiki elseif vim.startswith(input, "[") then local suffix = string.sub(request.context.cursor_after_line, 1, 1) local insert_end_offset = suffix == "]" and 0 or -1 -- 文字インデックスでの挿入開始位置を計算 local cursor_char_idx = vim.str_utfindex(before_line, #before_line) local input_char_len = vim.str_utfindex(input, #input) local insert_start = vim.str_byteindex(before_line, cursor_char_idx - input_char_len) return true, search, insert_start, cursor_col + insert_end_offset, M.RefType.Markdown else return false end end ``` どうやら `origin_insert_start` の方が近そうなので ```lua if vim.startswith(input, "[[") then local suffix = string.sub(request.context.cursor_after_line, 1, 2) local cursor_col = request.context.cursor.col local insert_end_offset = suffix == "]]" and 1 or -1 return true, search, vim.str_utfindex(cursor_col - 1 - #input), cursor_col + insert_end_offset, M.RefType.Wiki elseif vim.startswith(input, "[") then local suffix = string.sub(request.context.cursor_after_line, 1, 1) local cursor_col = request.context.cursor.col local insert_end_offset = suffix == "]" and 0 or -1 return true, search, cursor_col - 1 - #input, cursor_col + insert_end_offset, M.RefType.Markdown else return false end ``` としたらスタートは正解になったが、補完後の2文字が今度は消えてしまう。 `insert_end` を byteで返してるのまずくない?? 文字数だよねそこ?? ## 最終的に バイト数を文字数にすべて変換した上で処理をしたら動いた。 ```lua ---@return boolean, string|?, integer|?, integer|?, obsidian.completion.RefType|? M.can_complete = function(request) local input, search = find_search_start(request.context.cursor_before_line) if input == nil or search == nil or string.len(search) == 0 or util.is_whitespace(search) then return false end local until_cursor_len = vim.str_utfindex(request.context.cursor_before_line, #request.context.cursor_before_line) local cursor_col = vim.str_utfindex(request.context.cursor.col) local input_len = vim.str_utfindex(input, #input) if vim.startswith(input, "[[") then return true, search, until_cursor_len - input_len, cursor_col, M.RefType.Wiki end if vim.startswith(input, "[") then return true, search, until_cursor_len - input_len, cursor_col, M.RefType.Markdown end return false end ``` ## コミット <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" /> <span class="link-card-v2-site-name">GitHub</span> </div> <div class="link-card-v2-title"> fix: Inserting completions into sentences containing multibyte charac… · tadashi-aikawa/obsidian.nvim@4812505 </div> <div class="link-card-v2-content"> …ters causes insertion positions and ranges to shift </div> <img class="link-card-v2-image" src="https://opengraph.githubassets.com/734818767bb12c9dece4669241954b20674aedf60ebf5f239704f1dc7b901117/tadashi-aikawa/obsidian.nvim/commit/4812505c499179d73fbb6778a3702d23e92a7a6d" /> <a href="https://github.com/tadashi-aikawa/obsidian.nvim/commit/4812505c499179d73fbb6778a3702d23e92a7a6d"></a> </div>