diff --git a/model.fs b/model.fs index a2819c1..b243294 100644 --- a/model.fs +++ b/model.fs @@ -31,6 +31,7 @@ module ModelImpl = let ev_flush = Event() let grids = hashmap[] let windows = hashmap[] + let mutable init = async { return () } let add_grid(grid: IGridUI) = let id = grid.Id @@ -216,147 +217,146 @@ let Start (serveropts, norc, debugMultigrid) = trace "commencing early initialization..." - async { - do! Async.SwitchToNewThread() - - let! api_info = nvim.call { method = "nvim_get_api_info"; parameters = [||] } - let api_query_result = - match api_info.result with - | Ok(ObjArray [| Integer32 _; metadata |]) -> Ok metadata - | _ -> Result.Error("nvim_get_api_info") - >?= fun metadata -> - match metadata with - | FindKV "ui_options" (P (|String|_|) ui_options) -> Ok(Set.ofArray ui_options) - | _ -> Result.Error("find ui_options") - >?= fun ui_options -> - trace "available ui options: %A" ui_options - ui_available_opts <- ui_options - Ok() - match api_query_result with - | Ok() -> - if not (ui_available_opts.Contains uiopt_ext_linegrid) || - not (ui_available_opts.Contains uiopt_rgb) then - failwithf "api_query_result: your NeoVim version is too low. fvim requires \"rgb\" and \"ext_linegrid\" options, got: %A" ui_available_opts - | Result.Error(msg) -> - failwithf "api_query_result: %s" msg - - // for remote, send open file args as edit commands - let remoteEditFiles = - match serveropts with - // for embedded & fvr new session, edit file args are passed thru to neovim - | Embedded _ - | FVimRemote(_, _, NewSession _, _) -> [] - | NeovimRemote(_, files) - | FVimRemote(_, _, _, files) -> files - for file in remoteEditFiles do - let! _ = nvim.edit file - in () + init <- async { + do! Async.SwitchToNewThread() + + let! api_info = nvim.call { method = "nvim_get_api_info"; parameters = [||] } + let api_query_result = + match api_info.result with + | Ok(ObjArray [| Integer32 _; metadata |]) -> Ok metadata + | _ -> Result.Error("nvim_get_api_info") + >?= fun metadata -> + match metadata with + | FindKV "ui_options" (P (|String|_|) ui_options) -> Ok(Set.ofArray ui_options) + | _ -> Result.Error("find ui_options") + >?= fun ui_options -> + trace "available ui options: %A" ui_options + ui_available_opts <- ui_options + Ok() + match api_query_result with + | Ok() -> + if not (ui_available_opts.Contains uiopt_ext_linegrid) || + not (ui_available_opts.Contains uiopt_rgb) then + failwithf "api_query_result: your NeoVim version is too low. fvim requires \"rgb\" and \"ext_linegrid\" options, got: %A" ui_available_opts + | Result.Error(msg) -> + failwithf "api_query_result: %s" msg + + // for remote, send open file args as edit commands + let remoteEditFiles = + match serveropts with + // for embedded & fvr new session, edit file args are passed thru to neovim + | Embedded _ + | FVimRemote(_, _, NewSession _, _) -> [] + | NeovimRemote(_, files) + | FVimRemote(_, _, _, files) -> files + for file in remoteEditFiles do + let! _ = nvim.edit file + in () - let clientId = nvim.Id.ToString() - let clientName = "FVim" - let clientVersion = - hashmap [ - "major", "0" - "minor", "2" - "prerelease", "dev" - ] - let clientType = "ui" - let clientMethods = hashmap [] - let clientAttributes = - hashmap [ - "InstanceId", clientId - ] - - let! _ = nvim.set_var "fvim_loaded" 1 - let! _ = nvim.set_client_info clientName clientVersion clientType clientMethods clientAttributes - let! channels = nvim.list_chans() - - let ch_finder ch = - FindKV("id") ch - >>= Integer32 - >>= fun chid -> - FindKV("client")ch - >>= fun client -> - match client with - | FindKV("name")(String name) when name = clientName -> Some client - | _ -> None - >>= FindKV("attributes") - >>= FindKV("InstanceId") - >>= IsString - >>= (fun iid -> Some(iid, chid)) - - let fvimChannels = Seq.choose ch_finder channels |> List.ofSeq - let _, myChannel = List.find (fun (iid, _) -> iid = clientId) fvimChannels - - trace "FVim connected clients: %A" fvimChannels - trace "FVim client channel is: %d" myChannel - - states.channel_id <- myChannel - - // Another instance is already up - if fvimChannels.Length > 1 then - Environment.Exit(0) - let! _ = nvim.set_var "fvim_channel" myChannel - - // Register clipboard provider by setting g:clipboard - let clipboard = """let g:clipboard = { - 'name': 'FVimClipboard', - 'copy': { - '+': {lines, regtype -> rpcrequest(g:fvim_channel, 'set-clipboard', lines, regtype)}, - '*': {lines, regtype -> rpcrequest(g:fvim_channel, 'set-clipboard', lines, regtype)}, - }, - 'paste': { - '+': {-> rpcrequest(g:fvim_channel, 'get-clipboard')}, - '*': {-> rpcrequest(g:fvim_channel, 'get-clipboard')}, - } + let clientId = nvim.Id.ToString() + let clientName = "FVim" + let clientVersion = + hashmap [ + "major", "0" + "minor", "2" + "prerelease", "dev" + ] + let clientType = "ui" + let clientMethods = hashmap [] + let clientAttributes = + hashmap [ + "InstanceId", clientId + ] + + let! _ = nvim.set_var "fvim_loaded" 1 + let! _ = nvim.set_client_info clientName clientVersion clientType clientMethods clientAttributes + let! channels = nvim.list_chans() + + let ch_finder ch = + FindKV("id") ch + >>= Integer32 + >>= fun chid -> + FindKV("client")ch + >>= fun client -> + match client with + | FindKV("name")(String name) when name = clientName -> Some client + | _ -> None + >>= FindKV("attributes") + >>= FindKV("InstanceId") + >>= IsString + >>= (fun iid -> Some(iid, chid)) + + let fvimChannels = Seq.choose ch_finder channels |> List.ofSeq + let _, myChannel = List.find (fun (iid, _) -> iid = clientId) fvimChannels + + trace "FVim connected clients: %A" fvimChannels + trace "FVim client channel is: %d" myChannel + + states.channel_id <- myChannel + + // Another instance is already up + if fvimChannels.Length > 1 then + Environment.Exit(0) + let! _ = nvim.set_var "fvim_channel" myChannel + + // Register clipboard provider by setting g:clipboard + let clipboard = """let g:clipboard = { +'name': 'FVimClipboard', +'copy': { + '+': {lines, regtype -> rpcrequest(g:fvim_channel, 'set-clipboard', lines, regtype)}, + '*': {lines, regtype -> rpcrequest(g:fvim_channel, 'set-clipboard', lines, regtype)}, + }, +'paste': { + '+': {-> rpcrequest(g:fvim_channel, 'get-clipboard')}, + '*': {-> rpcrequest(g:fvim_channel, 'get-clipboard')}, +} }""" - let! _ = nvim.command <| clipboard.Replace("\r", "").Replace("\n","").Replace(" ","") - - let! _ = nvim.``command!`` "FVimDetach" 0 "call rpcnotify(g:fvim_channel, 'remote.detach')" - let! _ = nvim.``command!`` "FVimToggleFullScreen" 0 "call rpcnotify(g:fvim_channel, 'ToggleFullScreen', 1)" - - let! _ = nvim.``command!`` "-complete=expression FVimCursorSmoothMove" 1 "call rpcnotify(g:fvim_channel, 'cursor.smoothmove', )" - let! _ = nvim.``command!`` "-complete=expression FVimCursorSmoothBlink" 1 "call rpcnotify(g:fvim_channel, 'cursor.smoothblink', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontLineHeight" 1 "call rpcnotify(g:fvim_channel, 'font.lineheight', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontAutoSnap" 1 "call rpcnotify(g:fvim_channel, 'font.autosnap', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontAntialias" 1 "call rpcnotify(g:fvim_channel, 'font.antialias', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontLigature" 1 "call rpcnotify(g:fvim_channel, 'font.ligature', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontDrawBounds" 1 "call rpcnotify(g:fvim_channel, 'font.drawBounds', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontAutohint" 1 "call rpcnotify(g:fvim_channel, 'font.autohint', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontSubpixel" 1 "call rpcnotify(g:fvim_channel, 'font.subpixel', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontHintLevel" 1 "call rpcnotify(g:fvim_channel, 'font.hintLevel', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontNormalWeight" 1 "call rpcnotify(g:fvim_channel, 'font.weight.normal', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontBoldWeight" 1 "call rpcnotify(g:fvim_channel, 'font.weight.bold', )" - let! _ = nvim.``command!`` "-complete=expression FVimFontNoBuiltinSymbols" 1 "call rpcnotify(g:fvim_channel, 'font.nonerd', )" - let! _ = nvim.``command!`` "-complete=expression FVimKeyDisableShiftSpace" 1 "call rpcnotify(g:fvim_channel, 'key.disableShiftSpace', )" - let! _ = nvim.``command!`` "-complete=expression FVimUIMultiGrid" 1 "call rpcnotify(g:fvim_channel, 'ui.multigrid', )" - let! _ = nvim.``command!`` "-complete=expression FVimUIPopupMenu" 1 "call rpcnotify(g:fvim_channel, 'ui.popupmenu', )" - let! _ = nvim.``command!`` "-complete=expression FVimUITabLine" 1 "call rpcnotify(g:fvim_channel, 'ui.tabline', )" - let! _ = nvim.``command!`` "-complete=expression FVimUICmdLine" 1 "call rpcnotify(g:fvim_channel, 'ui.cmdline', )" - let! _ = nvim.``command!`` "-complete=expression FVimUIWildMenu" 1 "call rpcnotify(g:fvim_channel, 'ui.wildmenu', )" - let! _ = nvim.``command!`` "-complete=expression FVimUIMessages" 1 "call rpcnotify(g:fvim_channel, 'ui.messages', )" - let! _ = nvim.``command!`` "-complete=expression FVimUITermColors" 1 "call rpcnotify(g:fvim_channel, 'ui.termcolors', )" - let! _ = nvim.``command!`` "-complete=expression FVimUIHlState" 1 "call rpcnotify(g:fvim_channel, 'ui.hlstate', )" - let! _ = nvim.``command!`` "-complete=expression FVimDrawFPS" 1 "call rpcnotify(g:fvim_channel, 'DrawFPS', )" - let! _ = nvim.``command!`` "-complete=expression FVimCustomTitleBar" 1 "call rpcnotify(g:fvim_channel, 'CustomTitleBar', )" - - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundOpacity" 1 "call rpcnotify(g:fvim_channel, 'background.opacity', )" - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundComposition" 1 "call rpcnotify(g:fvim_channel, 'background.composition', )" - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundAltOpacity" 1 "call rpcnotify(g:fvim_channel, 'background.altopacity', )" - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImage" 1 "call rpcnotify(g:fvim_channel, 'background.image.file', )" - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageOpacity" 1 "call rpcnotify(g:fvim_channel, 'background.image.opacity', )" - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageStretch" 1 "call rpcnotify(g:fvim_channel, 'background.image.stretch', )" - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageHAlign" 1 "call rpcnotify(g:fvim_channel, 'background.image.halign', )" - let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageVAlign" 1 "call rpcnotify(g:fvim_channel, 'background.image.valign', )" - - - // trigger ginit upon VimEnter - if not norc then - let! _ = nvim.command "if v:vim_did_enter | runtime! ginit.vim | else | execute \"autocmd VimEnter * runtime! ginit.vim\" | endif" - () + let! _ = nvim.command <| clipboard.Replace("\r", "").Replace("\n","") + + let! _ = nvim.``command!`` "FVimDetach" 0 "call rpcnotify(g:fvim_channel, 'remote.detach')" + let! _ = nvim.``command!`` "FVimToggleFullScreen" 0 "call rpcnotify(g:fvim_channel, 'ToggleFullScreen', 1)" + + let! _ = nvim.``command!`` "-complete=expression FVimCursorSmoothMove" 1 "call rpcnotify(g:fvim_channel, 'cursor.smoothmove', )" + let! _ = nvim.``command!`` "-complete=expression FVimCursorSmoothBlink" 1 "call rpcnotify(g:fvim_channel, 'cursor.smoothblink', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontLineHeight" 1 "call rpcnotify(g:fvim_channel, 'font.lineheight', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontAutoSnap" 1 "call rpcnotify(g:fvim_channel, 'font.autosnap', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontAntialias" 1 "call rpcnotify(g:fvim_channel, 'font.antialias', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontLigature" 1 "call rpcnotify(g:fvim_channel, 'font.ligature', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontDrawBounds" 1 "call rpcnotify(g:fvim_channel, 'font.drawBounds', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontAutohint" 1 "call rpcnotify(g:fvim_channel, 'font.autohint', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontSubpixel" 1 "call rpcnotify(g:fvim_channel, 'font.subpixel', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontHintLevel" 1 "call rpcnotify(g:fvim_channel, 'font.hintLevel', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontNormalWeight" 1 "call rpcnotify(g:fvim_channel, 'font.weight.normal', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontBoldWeight" 1 "call rpcnotify(g:fvim_channel, 'font.weight.bold', )" + let! _ = nvim.``command!`` "-complete=expression FVimFontNoBuiltinSymbols" 1 "call rpcnotify(g:fvim_channel, 'font.nonerd', )" + let! _ = nvim.``command!`` "-complete=expression FVimKeyDisableShiftSpace" 1 "call rpcnotify(g:fvim_channel, 'key.disableShiftSpace', )" + let! _ = nvim.``command!`` "-complete=expression FVimUIMultiGrid" 1 "call rpcnotify(g:fvim_channel, 'ui.multigrid', )" + let! _ = nvim.``command!`` "-complete=expression FVimUIPopupMenu" 1 "call rpcnotify(g:fvim_channel, 'ui.popupmenu', )" + let! _ = nvim.``command!`` "-complete=expression FVimUITabLine" 1 "call rpcnotify(g:fvim_channel, 'ui.tabline', )" + let! _ = nvim.``command!`` "-complete=expression FVimUICmdLine" 1 "call rpcnotify(g:fvim_channel, 'ui.cmdline', )" + let! _ = nvim.``command!`` "-complete=expression FVimUIWildMenu" 1 "call rpcnotify(g:fvim_channel, 'ui.wildmenu', )" + let! _ = nvim.``command!`` "-complete=expression FVimUIMessages" 1 "call rpcnotify(g:fvim_channel, 'ui.messages', )" + let! _ = nvim.``command!`` "-complete=expression FVimUITermColors" 1 "call rpcnotify(g:fvim_channel, 'ui.termcolors', )" + let! _ = nvim.``command!`` "-complete=expression FVimUIHlState" 1 "call rpcnotify(g:fvim_channel, 'ui.hlstate', )" + let! _ = nvim.``command!`` "-complete=expression FVimDrawFPS" 1 "call rpcnotify(g:fvim_channel, 'DrawFPS', )" + let! _ = nvim.``command!`` "-complete=expression FVimCustomTitleBar" 1 "call rpcnotify(g:fvim_channel, 'CustomTitleBar', )" + + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundOpacity" 1 "call rpcnotify(g:fvim_channel, 'background.opacity', )" + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundComposition" 1 "call rpcnotify(g:fvim_channel, 'background.composition', )" + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundAltOpacity" 1 "call rpcnotify(g:fvim_channel, 'background.altopacity', )" + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImage" 1 "call rpcnotify(g:fvim_channel, 'background.image.file', )" + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageOpacity" 1 "call rpcnotify(g:fvim_channel, 'background.image.opacity', )" + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageStretch" 1 "call rpcnotify(g:fvim_channel, 'background.image.stretch', )" + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageHAlign" 1 "call rpcnotify(g:fvim_channel, 'background.image.halign', )" + let! _ = nvim.``command!`` "-complete=expression FVimBackgroundImageVAlign" 1 "call rpcnotify(g:fvim_channel, 'background.image.valign', )" + + + // trigger ginit upon VimEnter + if not norc then + let! _ = nvim.command "if v:vim_did_enter | runtime! ginit.vim | else | execute \"autocmd VimEnter * runtime! ginit.vim\" | endif" + () } - |> Async.Start - |> ignore + Async.Start init let Flush = ev_flush.Publish @@ -386,8 +386,11 @@ let OnGridReady(gridui: IGridUI) = // Notify nvim about its presence trace "attaching to nvim on first grid ready signal. size = %A %A" gridui.GridWidth gridui.GridHeight - nvim.ui_attach gridui.GridWidth gridui.GridHeight - |> runAsync + async { + do! init + let! _ = nvim.ui_attach gridui.GridWidth gridui.GridHeight + in () + } |> runAsync let SelectPopupMenuItem (index: int) (insert: bool) (finish: bool) = trace "SelectPopupMenuItem: index=%d insert=%b finish=%b" index insert finish