fzf#runのwindow引数にTSで作った関数を指定すると死ぬみたい
code:runner.vim
call fzf#run({
\ 'source': source,
\ 'sink*': function('s:handler_wrapper', handler),
\ 'options': options,
\ 'window': 'call FzfPreviewCreateFloatingWindow()', " <- TS実装
\ })
endfunction
で死ぬ。
code:error
Error detected while processing function remote#define#CommandBootstrap5..remote#define#request:
line 2:
Error invoking '/Users/yuki_yano/repos/github.com/yuki-ycino/fzf-preview.vim:command:TSFzfPreviewProjectFiles' on channel 7: ch 7 returned a response with an unknown request id. Ensure the client is properl synchronized
該当行はここ https://github.com/neovim/neovim/blob/bd5f0e9695cb21c8b97f844ce21432ee8d06b7ed/runtime/autoload/remote/define.vim#L196
Neovimの中だから大分面倒くさそう
code:define.vim
function! remote#define#request(chan, ...)
let s:busya:chan = get(s:busy, a:chan, 0)+1
let val = call('rpcrequest', a:chan+a:000)
let s:busya:chan -= 1
if s:busya:chan == 0
for msg in get(s:pending_notifications, a:chan, [])
call call('rpcnotify', a:chan + msg)
endfor
let s:pending_notificationsa:chan = []
endif
return val
endfunction
{sync: false} だと通るんだけど、Floating Windowの生成がfzfの実行後に行われてしまって、Floating Windowでない元のWindowでfzfが起動してしまう。
Floating Windowの操作とかautocmdの登録はできたので fzf#run が絡まない部分では色々とできそう。
code:window/create.ts
import { store, dispatch } from "@/store"
import { pluginCall, pluginGetOption, pluginCommand } from "@/plugin"
import { createGlobalVariableSelector } from "@/module/vim-variable"
import { loadStore } from "@/module/persist"
const createWindowBorderLine = (firstChar: string, innerChar: string, lastChar: string, width: number) => {
const center = ...Array(width - 2).map(() => innerChar)
return ${firstChar}${center.join("")}${lastChar}
}
export const createFloatingWindow = async () => {
await dispatch(loadStore())
const globalVariableSelector = createGlobalVariableSelector(store)
const floatingWindowRate = globalVariableSelector("fzfPreviewFloatingWindowRate")
if (typeof floatingWindowRate !== "number") {
throw new Error("g:fzf_preview_floating_window_rate must be Float variable")
}
const vimColumns = (await pluginGetOption("columns")) as number
const vimLines = (await pluginGetOption("lines")) as number
const width = Math.floor(vimColumns * floatingWindowRate)
const height = Math.floor(vimLines * floatingWindowRate)
const top = (vimLines - height) / 2 - 1
const left = (vimColumns - width) / 2
const backgroundOptions = {
relative: "editor",
row: top,
col: left,
width,
height,
style: "minimal"
}
const topLine = createWindowBorderLine("╭", "─", "╮", width)
const middleLine = createWindowBorderLine("│", " ", "│", width)
const bottomLine = createWindowBorderLine("╰", "─", "╯", width)
const lines = topLine.concat(Array(height - 2).fill(middleLine)).concat(bottomLine)
const backgroundBuffer = await pluginCall("nvim_create_buf", false, true)
await pluginCall("nvim_buf_set_lines", backgroundBuffer, 0, -1, true, lines)
const backgroundWindow = await pluginCall("nvim_open_win", backgroundBuffer, true, backgroundOptions)
await pluginCall("nvim_win_set_option", backgroundWindow, "winhighlight", "Normal:Floating")
const foregroundOptions = {
relative: "editor",
row: backgroundOptions.row + 1,
col: backgroundOptions.col + 2,
width: backgroundOptions.width - 4,
height: backgroundOptions.height - 2,
style: "minimal"
}
const foregroundBuffer = await pluginCall("nvim_create_buf", false, true)
await pluginCall("nvim_open_win", foregroundBuffer, true, foregroundOptions)
await pluginCommand("setlocal filetype=fzf")
await pluginCommand("setlocal nocursorcolumn")
await pluginCommand(autocmd WinLeave <buffer> silent! execute 'bdelete!' ${backgroundBuffer} ${foregroundBuffer})
}