From de6246110c0b3084fc49550f9df37dad9ab1b7d0 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 3 Sep 2019 10:38:33 +0800 Subject: [PATCH] ui options configuration ok. --- README.md | 10 +++++++ common.fs | 5 ++++ neovim/neovim.def.fs | 11 -------- neovim/neovim.model.fs | 34 +++++++++++++++++++++--- neovim/neovim.process.fs | 31 +++++++++++++++++----- states.fs | 57 ++++++++++++++++++++++++++++++++++++---- 6 files changed, 122 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 27ab170..cdf89eb 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,16 @@ FVimFontBoldWeight 700 " Font debugging -- draw bounds around each glyph FVimFontDrawBounds v:true +" UI options (all default to v:false) +FVimUIMultiGrid v:false " per-window grid system -- work in progress +FVimUIPopupMenu v:true " external popup menu +FVimUITabLine v:false " external tabline -- not implemented +FVimUICmdLine v:false " external cmdline -- not implemented +FVimUIWildMenu v:false " external wildmenu -- not implemented +FVimUIMessages v:false " external messages -- not implemented +FVimUITermColors v:false " not implemented +FVimUIHlState v:false " not implemented + " Detach from a remote session without killing the server " If this command is executed on a standalone instance, " the embedded process will be terminated anyway. diff --git a/common.fs b/common.fs index d81d4dc..ef99dc3 100644 --- a/common.fs +++ b/common.fs @@ -100,6 +100,11 @@ let inline (>>=) (x: 'a option) (f: 'a -> 'b option) = | Some x -> f x | _ -> None +let inline (>?=) (x: Result<'a, 'e>) (f: 'a -> Result<'b, 'e>) = + match x with + | Ok result -> f result + | Error err -> Error err + [] module internal helpers = let _d x = Option.defaultValue x diff --git a/neovim/neovim.def.fs b/neovim/neovim.def.fs index 3fd2bca..49fc855 100644 --- a/neovim/neovim.def.fs +++ b/neovim/neovim.def.fs @@ -301,17 +301,6 @@ type RedrawCommand = //| UpdateSp of Color | UnknownCommand of data: obj -let uiopt_rgb = "rgb" -let uiopt_ext_linegrid = "ext_linegrid" -let uiopt_ext_multigrid = "ext_multigrid" -let uiopt_ext_popupmenu = "ext_popupmenu" -let uiopt_ext_tabline = "ext_tabline" -let uiopt_ext_cmdline = "ext_cmdline" -let uiopt_ext_wildmenu = "ext_wildmenu" -let uiopt_ext_messages = "ext_messages" -let uiopt_ext_hlstate = "ext_hlstate" -let uiopt_ext_termcolors = "ext_termcolors" - type EventParseException(data: obj) = inherit exn() member __.Input = data diff --git a/neovim/neovim.model.fs b/neovim/neovim.model.fs index e649358..0df9b3f 100644 --- a/neovim/neovim.model.fs +++ b/neovim/neovim.model.fs @@ -288,6 +288,16 @@ let Detach() = nvim.stop(0) States.Shutdown(0) +let UpdateUICapabilities() = + let opts = hashmap[] + States.PopulateUIOptions opts + trace "UpdateUICapabilities: %A" <| String.Join(", ", Seq.map (fun (KeyValue(k, v)) -> sprintf "%s=%b" k v) opts) + async { + for KeyValue(k, v) in opts do + let! _ = Async.AwaitTask <| nvim.call { method="nvim_ui_set_option"; parameters = mkparams2 k v } + in () + } |> Async.RunSynchronously + /// /// Call this once at initialization. /// @@ -315,8 +325,17 @@ let Start opts = States.Register.Bool "cursor.smoothblink" States.Register.Bool "cursor.smoothmove" States.Register.Bool "key.disableShiftSpace" - - ignore(States.Register.Notify "remote.detach" (fun _ -> Detach())) + States.Register.Bool "ui.multigrid" + States.Register.Bool "ui.popupmenu" + States.Register.Bool "ui.tabline" + States.Register.Bool "ui.cmdline" + States.Register.Bool "ui.wildmenu" + States.Register.Bool "ui.messages" + States.Register.Bool "ui.termcolors" + States.Register.Bool "ui.hlstate" + + States.Register.Notify "remote.detach" (fun _ -> Detach()) + States.Register.Watch "ui" UpdateUICapabilities States.Register.Request "set-clipboard" (fun [| P(|String|_|)lines; String regtype |] -> async { States.clipboard_lines <- lines @@ -389,6 +408,8 @@ let Start opts = trace "FVim connected clients: %A" fvimChannels trace "FVim client channel is: %d" myChannel + FVim.States.channel_id <- myChannel + // Another instance is already up if fvimChannels.Length > 1 then Environment.Exit(0) @@ -426,6 +447,14 @@ let Start opts = let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimFontNormalWeight" 1 (sprintf "call rpcnotify(%d, 'font.weight.normal', )" myChannel)) let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimFontBoldWeight" 1 (sprintf "call rpcnotify(%d, 'font.weight.bold', )" myChannel)) let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimKeyDisableShiftSpace" 1 (sprintf "call rpcnotify(%d, 'key.disableShiftSpace', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUIMultiGrid" 1 (sprintf "call rpcnotify(%d, 'ui.multigrid', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUIPopupMenu" 1 (sprintf "call rpcnotify(%d, 'ui.popupmenu', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUITabLine" 1 (sprintf "call rpcnotify(%d, 'ui.tabline', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUICmdLine" 1 (sprintf "call rpcnotify(%d, 'ui.cmdline', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUIWildMenu" 1 (sprintf "call rpcnotify(%d, 'ui.wildmenu', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUIMessages" 1 (sprintf "call rpcnotify(%d, 'ui.messages', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUITermColors" 1 (sprintf "call rpcnotify(%d, 'ui.termcolors', )" myChannel)) + let! _ = Async.AwaitTask(nvim.``command!`` "-complete=expression FVimUIHlState" 1 (sprintf "call rpcnotify(%d, 'ui.hlstate', )" myChannel)) () } @@ -466,7 +495,6 @@ let SelectPopupMenuItem (index: int) (insert: bool) (finish: bool) = let! _ = nvim.command (sprintf "call nvim_select_popupmenu_item(%d, %s, %s, {})" index insert finish) in () } |> ignore - let OnTerminated (args) = trace "terminating nvim..." diff --git a/neovim/neovim.process.fs b/neovim/neovim.process.fs index 34b950d..0d808a0 100644 --- a/neovim/neovim.process.fs +++ b/neovim/neovim.process.fs @@ -264,13 +264,30 @@ type Nvim() = m_call { method = "nvim_ui_try_resize"; parameters = mkparams2 w h } member __.ui_attach (w:int) (h:int) = - let opts = hashmap[] - opts.[uiopt_rgb] <- true - opts.[uiopt_ext_linegrid] <- true - opts.[uiopt_ext_popupmenu] <- true - (*opts.[uiopt_ext_multigrid] <- true*) - - m_call { method = "nvim_ui_attach"; parameters = mkparams3 w h opts } + task { + let! api_info = m_call { method = "nvim_get_api_info"; parameters = [||] } + let opts = hashmap[] + let result = + match api_info.result with + | Ok(ObjArray [| Integer32 chid; metadata |]) -> Ok metadata + | _ -> Result.Error("nvim_get_api_info") + >?= fun metadata -> + opts.[uiopt_rgb] <- true + opts.[uiopt_ext_linegrid] <- true + 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 + PopulateUIOptions opts + Ok() + match result with + | Result.Ok() -> return! m_call { method = "nvim_ui_attach"; parameters = mkparams3 w h opts } + | Result.Error msg -> + trace "ui_attach error: %s" msg + return { result = Result.Error(box msg) } + } member __.exists (var: string) = task { diff --git a/states.fs b/states.fs index 206f12c..55596ec 100644 --- a/states.fs +++ b/states.fs @@ -48,6 +48,9 @@ type LineHeightOption = | Add of float | Default +// channel +let mutable channel_id = 1 + // keyboard mapping let mutable key_disableShiftSpace = false @@ -71,18 +74,62 @@ let mutable font_weight_normal = SKFontStyleWeight.Normal let mutable font_weight_bold = SKFontStyleWeight.Bold let mutable font_lineheight = LineHeightOption.Default +// ui +let mutable ui_available_opts = Set.empty +let mutable ui_multigrid = false +let mutable ui_popupmenu = false +let mutable ui_tabline = false +let mutable ui_cmdline = false +let mutable ui_wildmenu = false +let mutable ui_messages = false +let mutable ui_termcolors = false +let mutable ui_hlstate = false + +[] +let uiopt_rgb = "rgb" +[] +let uiopt_ext_linegrid = "ext_linegrid" +[] +let uiopt_ext_multigrid = "ext_multigrid" +[] +let uiopt_ext_popupmenu = "ext_popupmenu" +[] +let uiopt_ext_tabline = "ext_tabline" +[] +let uiopt_ext_cmdline = "ext_cmdline" +[] +let uiopt_ext_wildmenu = "ext_wildmenu" +[] +let uiopt_ext_messages = "ext_messages" +[] +let uiopt_ext_hlstate = "ext_hlstate" +[] +let uiopt_ext_termcolors = "ext_termcolors" + +/// !Note does not include rgb and ext_linegrid +let PopulateUIOptions (opts: hashmap<_,_>) = + let c k v = + if ui_available_opts.Contains k then + opts.[k] <- v + c uiopt_ext_popupmenu ui_popupmenu + c uiopt_ext_multigrid ui_multigrid + c uiopt_ext_tabline ui_tabline + c uiopt_ext_cmdline ui_cmdline + c uiopt_ext_wildmenu ui_wildmenu + c uiopt_ext_messages ui_messages + c uiopt_ext_hlstate ui_hlstate + c uiopt_ext_termcolors ui_termcolors + module private Helper = type Foo = A let _StatesModuleType = typeof.DeclaringType.DeclaringType let SetProp name v = - trace "states" "module name = %s" _StatesModuleType.FullName let propDesc = _StatesModuleType.GetProperty(name, BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) if propDesc <> null then propDesc.SetValue(null, v) else error "states" "The property %s is not found" name let GetProp name = - trace "states" "module name = %s" _StatesModuleType.FullName let propDesc = _StatesModuleType.GetProperty(name, BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) if propDesc <> null then Some <| propDesc.GetValue(null) @@ -160,9 +207,9 @@ module Register = try fn objs with x -> error "Notify" "exception thrown: %A" <| x.ToString()) - let Watch name fn = + let Watch (name: string) fn = _stateChangeEvent.Publish - |> Observable.filter (fun x -> x = name) + |> Observable.filter (fun x -> x.StartsWith(name)) |> Observable.subscribe (fun _ -> fn()) let Prop<'T> (parser: obj -> 'T option) (fullname: string) = @@ -174,7 +221,7 @@ module Register = match parser(v) with | Some v -> Helper.SetProp fieldName v - _stateChangeEvent.Trigger section + _stateChangeEvent.Trigger fullname | None -> () | _ -> ()) |> ignore