package coq-lsp
Language Server Protocol native server for Coq
Install
Dune Dependency
Authors
Maintainers
Sources
coq-lsp-0.1.5.8.16.tbz
sha256=5a0819d6ceb18cf031ece2c466eefd27f018d85c1c7472038bbb7c2663714b6e
sha512=be97b25db922014681dce75a68566b887f692c60208b698f03ce8b2fc0c1a2eab5c0c563d698eeb1d21dea5405468e958e67cce9a6c94a3106529f1b4ebfce13
doc/src/coq-lsp.fleche/contents.ml.html
Source file contents.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
(************************************************************************) (* Flèche => document manager: Document Contents *) (* Copyright 2019-2023 Inria -- Dual License LGPL 2.1 / GPL3+ *) (* Written by: Emilio J. Gallego Arias *) (************************************************************************) module R = struct (** We want to replace the string by a proper diagnostic we can send to the client *) type 'a t = | Ok of 'a | Error of string let map ~f = function | Ok x -> Ok (f x) | Error e -> Error e end module Util = struct (** Builds a string that contains the right white-space padding between two points *) let build_whitespace prev cur = let l_p, c_p, o_p = Lang.Point.(prev.line, prev.character, prev.offset) in let l_c, c_c, o_c = Lang.Point.(cur.line, cur.character, cur.offset) in let nl = l_c - l_p in let nc, padding = if l_p = l_c then (c_c - c_p, 0) else (c_c, o_c - o_p) in String.make padding ' ' ^ String.make nl '\n' ^ String.make nc ' ' end module Markdown = struct let gen l = String.make (String.length l) ' ' let rec md_map_lines coq l = match l with | [] -> [] | l :: ls -> (* opening vs closing a markdown block *) let code_marker = if coq then "```" else "```coq" in if String.equal code_marker l then gen l :: md_map_lines (not coq) ls else (if coq then l else gen l) :: md_map_lines coq ls let process text = let lines = String.split_on_char '\n' text in let lines = md_map_lines false lines in String.concat "\n" lines end module WaterProof = struct open Fleche_waterproof.Json let wp_error msg = R.Error (Format.asprintf "Waterproof parsing: %s" msg) let code_block block = match block with | { CAst.v = Assoc dict; _ } -> ( match find "type" dict with | Some { CAst.v = String "code"; _ } -> ( match find "text" dict with | Some { CAst.v = String coq_span; range } -> Some (range, coq_span) | _ -> None) | _ -> None) | _ -> None (* Needed to support "text": "\nfoo. bar." in Waterproof files *) let new_to_space = function | '\n' -> ' ' | x -> x let coq_block_to_span (contents, last_point) (range, coq) = let range_text = Util.build_whitespace last_point range.Lang.Range.start in let last_point = range.Lang.Range.end_ in let coq = String.map new_to_space coq in (contents ^ range_text ^ coq, last_point) let block_pos (range, _) = Format.asprintf "%a" Lang.Range.pp range let waterproof_debug = false let from_blocks blocks = let start_point = Lang.Point.{ line = 0; character = 0; offset = 0 } in let code_blocks = List.filter_map code_block blocks in let code_pos = List.map block_pos code_blocks in let contents, _ = List.fold_left coq_block_to_span ("", start_point) code_blocks in (if waterproof_debug then let msg = "pos:\n" ^ String.concat "\n" code_pos ^ "\nContents:\n" ^ contents in Io.Log.trace "waterproof" msg); R.Ok contents let from_json json = match json with | CAst.{ v = Assoc dict; _ } -> ( match find "blocks" dict with | None -> wp_error "blocks field not found" | Some blocks -> ( match blocks with | { CAst.v = List blocks; _ } -> from_blocks blocks | _ -> wp_error "blocks not a list")) | _ -> wp_error "top-level object not a dictionary" let process raw = let lexbuf = Lexing.from_string raw in match Fleche_waterproof.(Ljson.prog Tjson.read) lexbuf with | None -> R.Ok "" | Some json -> from_json json | exception _ -> wp_error "parsing failed" end let process_contents ~uri ~raw = let ext = Lang.LUri.File.extension uri in match ext with | ".v" -> R.Ok raw | ".mv" -> R.Ok (Markdown.process raw) | ".wpn" -> WaterProof.process raw | _ -> R.Error "unknown file format" type t = { raw : string (** That's the original, unprocessed document text *) ; text : string (** That's the text to be sent to the prover, already processed, encoded in UTF-8 *) ; last : Lang.Point.t (** Last point of [text] *) ; lines : string Array.t (** [text] split in lines *) } let get_last_text text = let offset = String.length text in let lines = CString.split_on_char '\n' text |> Array.of_list in let n_lines = Array.length lines in let last_line = if n_lines < 1 then "" else Array.get lines (n_lines - 1) in let character = Coq.Utf8.length last_line in (Lang.Point.{ line = n_lines - 1; character; offset }, lines) let make ~uri ~raw = match process_contents ~uri ~raw with | R.Error e -> R.Error e | R.Ok text -> let last, lines = get_last_text text in R.Ok { raw; text; last; lines }
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>