package ppxlib
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Standard infrastructure for ppx rewriters
Install
dune-project
Dependency
Authors
Maintainers
Sources
ppxlib-0.35.0.tbz
sha256=d9d959fc9f84260487e45684dc741898a92fc5506b61a7f5cac65d21832db925
sha512=e428b1e3b89261c7efdaa18016264d1afbf067cb9b0d41124b04796c2487ac7ca8ee9a24a60d56f20d1774cb44aaa9ecf1512f17455812ba8d62d4ef93616ee7
doc/src/ppxlib/spellcheck.ml.html
Source file spellcheck.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(** Helpers to provide hints to PPX users for typos or spellchecks. *) open! Import exception Cutoff_met (* As found here http://rosettacode.org/wiki/Levenshtein_distance#OCaml *) let levenshtein_distance s t cutoff = let m = String.length s and n = String.length t in if cutoff = 0 || abs (m - n) >= cutoff then None else (* for all i and j, d.(i).(j) will hold the Levenshtein distance between the first i characters of s and the first j characters of t *) let d = Array.make_matrix ~dimx:(m + 1) ~dimy:(n + 1) 0 in for i = 0 to m do (* the distance of any first string to an empty second string *) d.(i).(0) <- i done; for j = 0 to n do (* the distance of any second string to an empty first string *) d.(0).(j) <- j done; (* the minimum of each line together with the column index will be used to notice cutoff exceeding and return early in that case *) let line_min = ref 0 in let distance = try for j = 1 to n do if !line_min >= cutoff - 1 && j >= cutoff - 1 then raise Cutoff_met; line_min := max m n; for i = 1 to m do let value = if Char.equal s.[i - 1] t.[j - 1] then d.(i - 1).(j - 1) (* no operation required *) else min (d.(i - 1).(j) + 1) (* a deletion *) (min (d.(i).(j - 1) + 1) (* an insertion *) (d.(i - 1).(j - 1) + 1) (* a substitution *)) in d.(i).(j) <- value; line_min := min !line_min value done done; if d.(m).(n) < cutoff then Some d.(m).(n) else None with Cutoff_met -> None in distance let spellcheck names name = let cutoff = match String.length name with | 1 | 2 -> 0 | 3 | 4 -> 1 | 5 | 6 -> 2 | _ -> 3 in let _, suggestions = List.fold_left names ~init:(Int.max_int, []) ~f:(fun ((best_distance, names_at_best_distance) as acc) registered_name -> match levenshtein_distance name registered_name cutoff with | None -> acc | Some dist -> if dist < best_distance then (dist, [ registered_name ]) else if dist > best_distance then acc else (dist, registered_name :: names_at_best_distance)) in match List.rev suggestions |> List.filter ~f:(String.( <> ) name) with | [] -> None | last :: rev_rest -> Some (Printf.sprintf "Hint: Did you mean %s%s%s?" (String.concat ~sep:", " (List.rev rev_rest)) (if List.is_empty rev_rest then "" else " or ") last)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>