diff --git a/.vscode/launch.json b/.vscode/launch.json index 201ae54..a61e974 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,22 +1,16 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", "configurations": [ - { - "name": ".NET Core Launch (console)", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - "program": "${workspaceFolder}/bin/Debug/netcoreapp3.1/FVim.dll", - "args": [], - "cwd": "${workspaceFolder}", - "stopAtEntry": false, - "console": "integratedTerminal", - "justMyCode": false, - "enableStepFiltering": false - } - + { + "name": "fvr daemon", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/bin/Debug/net6.0/FVim.dll", + "args": ["--daemon"], + "cwd": "${workspaceFolder}", + "stopAtEntry": false, + "console": "internalConsole" + } ] + } \ No newline at end of file diff --git a/README.md b/README.md index be94a0a..036c293 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,10 @@ Cross platform Neovim front-end UI, built with [F#](https://fsharp.org/) + [Aval - Arch Linux: [Install via AUR](https://aur.archlinux.org/packages/fvim/) - RPM-based distributions: `rpm -ivh fvim_package_name.rpm` - Fedora: `dnf install fvim_package_name.rpm` - - Compile from Source (having dotnet-sdk-5.0.x installed): + - Compile from Source (having dotnet-sdk-6.0.x installed): ``` - git clone https://github.com/yatli/fvim && cd fvim && dotnet publish -f net5.0 -c Release -r linux-x64 --self-contained + git clone https://github.com/yatli/fvim && cd fvim && dotnet publish -f net6.0 -c Release -r linux-x64 --self-contained ``` -- Note, currently FVim will treat all keyboards as en-US so characters and symbols are mapped incorrectly if you use a non en-US layout. [The issue is tracked here](https://github.com/yatli/fvim/issues/36). ### Features @@ -85,7 +84,7 @@ Detaching a window into an external OS window with `Ctrl-w ge`: Detach as many and span them over your monitors! ### Building from source -We're now targeting `net5.0` so make sure to install the latest preview SDK from the [.NET site](https://dotnet.microsoft.com/download/dotnet/5.0). +We're now targeting `net6.0` so make sure to install the latest preview SDK from the [.NET site](https://dotnet.microsoft.com/download/dotnet/6.0). We're actively tracking the head of `Avalonia`, and fetch the nightly packages from myget (see `NuGet.config`). Then, simply: diff --git a/daemon.fs b/daemon.fs index 152da1d..8cd005f 100644 --- a/daemon.fs +++ b/daemon.fs @@ -86,6 +86,8 @@ let newSession nvim stderrenc args svrpipe = sessions.[myid].exitHandle.Dispose() sessions.Remove(myid) |> ignore proc.Dispose() + try svrpipe.Dispose() + with dispose_ex -> trace "%O" dispose_ex ) } @@ -132,7 +134,8 @@ let serve nvim stderrenc (pipe: NamedPipeServerStream) = if rbuf.[0..3] <> FVR_MAGIC then trace "Incorrect handshake magic. Got: %A" rbuf.[0..3] return() - let len = rbuf.[4..7] |> toInt32LE + let lenbuf = rbuf.[4..7] + let len = lenbuf |> toInt32LE if len >= rbuf.Length || len <= 0 then trace "Invalid payload length %d" len return() @@ -158,10 +161,10 @@ let serve nvim stderrenc (pipe: NamedPipeServerStream) = trace "Request %A is attaching to session %d" request session.id do! fromInt32LE session.id |> readonlymemory |> write pipe do! serveSession session - finally - try - pipe.Dispose() - with ex -> trace "%O" ex + with ex -> + trace "%O" ex + try pipe.Dispose() + with dispose_ex -> trace "%O" dispose_ex } let daemon (pname: string option) (nvim: string) (stderrenc: Text.Encoding) = diff --git a/input.fs b/input.fs index ae9d72b..1dbdc3f 100644 --- a/input.fs +++ b/input.fs @@ -5,6 +5,7 @@ open neovim open Avalonia.Input open System +open System.Runtime.InteropServices open FSharp.Control.Reactive open Avalonia.Interactivity @@ -94,6 +95,7 @@ let DIR (dx: float, dy: float, horizontal: bool) = let mutable accumulatedX = 0.0 let mutable accumulatedY = 0.0 +let mutable blockNextTextInput = false // Avoid sending Rejected key as a sequence, e.g. "capslock" let RejectKeys = set [ @@ -285,7 +287,7 @@ let (|Special|Normal|Rejected|) (x: InputEvent) = // | ' | ' | รค | // | Ctrl-' | | | // - | Key(m, Key.Back) -> Special "BS" + | Key(_, Key.Back) -> Special "BS" | Key(_, Key.Tab) -> Special "Tab" | Key(_, Key.LineFeed) -> Special "NL" | Key(_, Key.Return) -> Special "CR" @@ -359,8 +361,14 @@ let (|Special|Normal|Rejected|) (x: InputEvent) = | Key(_, Key.Divide) -> Special("kDivide") | Key(_, Key.Separator) -> Special("kEnter") | Key(_, Key.Decimal) -> Special("kPoint") - | Key(NoFlag(KeyModifiers.Shift), x) -> Normal (x.ToString().ToLowerInvariant()) - | Key(_, x) -> Normal (x.ToString()) + | Key(NoFlag(KeyModifiers.Shift) as m, x) -> + if RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && m = KeyModifiers.Alt + then blockNextTextInput <- true + Normal (x.ToString().ToLowerInvariant()) + | Key(m, x) -> + if RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && m = (KeyModifiers.Alt ||| KeyModifiers.Shift) + then blockNextTextInput <- true + Normal (x.ToString()) | _ -> Rejected let rec ModifiersPrefix (x: InputEvent) = @@ -398,7 +406,11 @@ let onInput (nvim: Nvim) (input: IObservable) = match x with | TextInput txt -> ev.Handled <- true - if txt = "<" then Some "" else Some txt + if blockNextTextInput then + blockNextTextInput <- false + None + elif txt = "<" then Some "" + else Some txt | InputEvent.Key _ -> ev.Handled <- true let pref = ModifiersPrefix x