package vcaml
OCaml bindings for the Neovim API
Install
Dune Dependency
Authors
Maintainers
Sources
vcaml-v0.16.0.tar.gz
sha256=dd123302c46af7ca6eda8a7806c78236fd217a8c73a2e1cd7da85f1d69ed1ae4
doc/src/vcaml.debug/toplevel_client.ml.html
Source file toplevel_client.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
open Core module Unix = Core_unix module Parser = Angstrom.Buffered module Vcaml = struct open Vcaml (** We only use Vcaml for pretty-printing Neovim's Msgpack extensions. We don't use it anywhere else because the purpose of this tool is to see if a problem lies outside Vcaml. *) let pp = pp end include Vcaml type t = { socket : Unix.File_descr.t ; bytes : Bytes.t ; mutable state : Msgpack.t Angstrom.Buffered.state ; mutable channel : int ; mutable msgid : int ; mutable verbose : bool ; mutable closed : bool } let close t = Unix.close t.socket; t.closed <- true ;; let channel t = t.channel let verbose t value = t.verbose <- value let debug_send, debug_receive = let `Peer_1_to_2 send, `Peer_2_to_1 receive = Msgpack_debug.create_debug_printers ~pp ~color:true ~peer1:"OCaml" ~peer2:"Nvim" stdout in let send t msg = if t.verbose then send msg in let receive t msg = if t.verbose then receive msg in send, receive ;; let send t message = debug_send t message; let buf = Msgpack.string_of_t_exn message in let len = String.length buf in match t.closed with | true -> failwith "Failed to send message (connection is closed)" | false -> let bytes_written = Unix.single_write_substring ~pos:0 ~len t.socket ~buf in if bytes_written < len then failwith "Failed to send message" ;; let request t method_name params = t.msgid <- t.msgid + 1; let message = Msgpack.Array [ Integer 0; Integer t.msgid; String method_name; Array params ] in send t message ;; let notify t method_name params = let message = Msgpack.Array [ Integer 2; String method_name; Array params ] in send t message ;; let respond t ~msgid response = let message = match response with | Ok result -> Msgpack.Array [ Integer 1; Integer msgid; Nil; result ] | Error error -> Msgpack.Array [ Integer 1; Integer msgid; error; Nil ] in send t message ;; let rec receive t = match t.closed with | true -> `Connection_closed | false -> (match t.state with | Fail ({ buf; off; len }, marks, msg) -> (match off = len with | true -> close t; `Connection_closed | false -> let unconsumed = Bigstringaf.substring buf ~off ~len in raise_s [%message "Failed to parse message" msg (marks : string list) (unconsumed : String.Hexdump.Pretty.t)]) | Partial _ as state -> (match (Unix.select ~read:[ t.socket ] ~write:[] ~except:[] ~timeout:`Immediately ()) .read with | [] -> `Waiting_for_neovim | _ :: _ -> let input = match Unix.read ~pos:0 ~len:(Bytes.length t.bytes) t.socket ~buf:t.bytes with | 0 -> `Eof | bytes_read -> `String (Bytes.To_string.sub ~pos:0 ~len:bytes_read t.bytes) in t.state <- Parser.feed state input; receive t) | Done ({ buf; off; len }, message) -> debug_receive t message; let remaining_input = Bigstring.sub buf ~pos:off ~len in t.state <- Parser.feed (Parser.parse Msgpack.Internal.Parser.msg) (`Bigstring remaining_input); `Message message) ;; let receive_all_available t = let open Reversed_list in let rec aux t ~messages = match receive t with | `Connection_closed | `Waiting_for_neovim -> rev messages | `Message message -> aux t ~messages:(message :: messages) in aux t ~messages:[] ;; let open_ socketname = let socket = Unix.socket ~domain:PF_UNIX ~kind:SOCK_STREAM ~protocol:0 () in Unix.connect socket ~addr:(ADDR_UNIX socketname); let t = { socket ; bytes = Bytes.create 4096 ; state = Parser.parse Msgpack.Internal.Parser.msg ; channel = -1 ; msgid = 0 ; verbose = false ; closed = false } in request t "nvim_get_api_info" []; let rec wait_for_response t = function | 0 -> failwith "Timed out waiting for Neovim to respond" | n -> (match receive t with | `Connection_closed -> failwith "Connection to Neovim closed" | `Message message -> message | `Waiting_for_neovim -> ignore (Unix.nanosleep 0.1 : float); wait_for_response t (n - 1)) in let channel = match wait_for_response t 10 with | Array [ Integer 1; Integer msgid; Nil; Array [ Integer channel; _metadata ] ] when t.msgid = msgid -> channel | message -> raise_s [%message "Failed to parse [nvim_get_api_info] response" (message : Msgpack.t)] in t.channel <- channel; t ;;
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>