├── .gitignore ├── .ocamlformat ├── LICENSE ├── README.md ├── db ├── db.ml ├── db.mli ├── dune ├── int_set.ml └── int_set.mli ├── dune-project ├── index ├── dune ├── index.ml ├── syntax.ml └── syntax.mli ├── regex ├── ast.ml ├── dune ├── lexer.mll ├── parser.mly ├── regex.ml ├── regex.mli ├── trie.ml └── trie.mli ├── scripts └── index.sh ├── sherlocode.opam ├── static ├── favicon.ico ├── robots.txt ├── style.css └── urls.tsv └── www ├── colorize.ml ├── dune ├── link.ml ├── link.mli ├── present.ml ├── search.ml ├── ui.ml └── www.ml /.gitignore: -------------------------------------------------------------------------------- 1 | *.annot 2 | *.cmo 3 | *.cma 4 | *.cmi 5 | *.a 6 | *.o 7 | *.cmx 8 | *.cmxs 9 | *.cmxa 10 | 11 | .merlin 12 | *.install 13 | *.coverage 14 | *.sw[a-z] 15 | 16 | _build/ 17 | _doc/ 18 | _coverage/ 19 | _opam/ 20 | -------------------------------------------------------------------------------- /.ocamlformat: -------------------------------------------------------------------------------- 1 | profile = janestreet 2 | let-binding-spacing = compact 3 | sequence-style = separator 4 | doc-comments = after-when-possible 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Arthur Wendling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Find it online at [sherlocode.com](https://sherlocode.com) for OCaml projects!** 2 | 3 | **And at [sherlocoq.sirref.org](https://sherlocoq.sirref.org) for Coq libraries!** (thanks to [patricoferris](https://github.com/patricoferris/sherlocode/tree/coq) <3) 4 | 5 | This is a straightforward implementation of [Regular Expression Matching with a Trigram Index](https://swtch.com/~rsc/regexp/regexp4.html) by Russ Cox. For each of the characters, bigrams and trigrams, we store the set of line numbers where they appear. To answer a query, we first approximate the regex by enumerating the ngrams that are required/optional: the intersection/union of their indexed set yields good line candidates against which we can match the query. 6 | -------------------------------------------------------------------------------- /db/db.ml: -------------------------------------------------------------------------------- 1 | module Int_set = Int_set 2 | 3 | module Ngrams = Hashtbl.Make (struct 4 | type t = string 5 | 6 | let hash = Hashtbl.hash 7 | let equal = String.equal 8 | end) 9 | 10 | module Int_tbl = Hashtbl.Make (struct 11 | type t = int 12 | 13 | let hash = Hashtbl.hash 14 | let equal = Int.equal 15 | end) 16 | 17 | module Int_map = Map.Make (struct 18 | type t = int 19 | 20 | let compare = compare 21 | end) 22 | 23 | module Alphabet = struct 24 | let is_alpha chr = chr = ' ' || (chr >= 'a' && chr <= 'z') 25 | 26 | let valid_char chr = 27 | is_alpha chr 28 | || (chr >= 'A' && chr <= 'Z') 29 | || (chr >= '0' && chr <= '9') 30 | || String.contains "-+*%~#()[]{}$@!&|/\\`=^:;.,_'\"<>?\n" chr 31 | 32 | let alphabet = Array.make 256 '\000' 33 | let indexes = Array.make 256 (-1) 34 | 35 | let length = 36 | let count = ref 0 in 37 | for i = 0 to Array.length indexes - 1 do 38 | if valid_char (Char.chr i) 39 | then ( 40 | indexes.(i) <- !count ; 41 | alphabet.(!count) <- Char.chr i ; 42 | incr count) 43 | done ; 44 | !count 45 | 46 | let index c = indexes.(Char.code c) 47 | let _chr i = alphabet.(i) 48 | let is_valid c = index c >= 0 49 | 50 | let is_valid_string s = 51 | let rec go i = if i >= String.length s then true else is_valid s.[i] && go (i + 1) in 52 | go 0 53 | end 54 | 55 | type t = 56 | { line_offsets : int Int_tbl.t 57 | ; ngrams : Int_set.t Ngrams.t 58 | ; file_map : (string * int) Int_map.t 59 | } 60 | 61 | let make () = 62 | { line_offsets = Int_tbl.create 16 63 | ; ngrams = 64 | Ngrams.create (Alphabet.length * (1 + (Alphabet.length * (1 + Alphabet.length)))) 65 | ; file_map = Int_map.empty 66 | } 67 | 68 | let set_file_ranges filename (start_at, end_at) t = 69 | { t with file_map = Int_map.add end_at (filename, start_at) t.file_map } 70 | 71 | let set_line_offset t line_num line_offset = 72 | Int_tbl.replace t.line_offsets line_num line_offset 73 | 74 | let find_ngram t key = Ngrams.find t.ngrams key 75 | let base_addr = 0x100000000000n 76 | 77 | type writer = 78 | { mutable write_shard : int 79 | ; ancient : Ancient.md 80 | } 81 | 82 | let open_out filename = 83 | let handle = Unix.openfile filename Unix.[ O_RDWR; O_TRUNC; O_CREAT ] 0o640 in 84 | let ancient = Ancient.attach handle base_addr in 85 | { write_shard = 0; ancient } 86 | 87 | let save ~db (t : t) = 88 | ignore (Ancient.share db.ancient db.write_shard t) ; 89 | db.write_shard <- db.write_shard + 1 90 | 91 | let close_out db = Ancient.detach db.ancient 92 | 93 | module Bigstring : sig 94 | type t 95 | 96 | val of_file : string -> t 97 | val sub : t -> int -> int -> string 98 | end = struct 99 | type t = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t 100 | 101 | let of_file filename = 102 | let h = Unix.openfile filename [ Unix.O_RDONLY ] 0 in 103 | let big = Unix.map_file h Bigarray.char Bigarray.c_layout false [| -1 |] in 104 | let big = Bigarray.array1_of_genarray big in 105 | Unix.close h ; 106 | big 107 | 108 | let sub t pos len = String.init len (fun i -> Bigarray.Array1.get t (pos + i)) 109 | end 110 | 111 | type reader = 112 | { shards : t array 113 | ; source : Bigstring.t 114 | } 115 | 116 | let load_shard md shard = 117 | match Ancient.get md shard with 118 | | t -> Some (Ancient.follow t) 119 | | exception _ -> None 120 | 121 | let load_shards md = 122 | let rec go i = 123 | match load_shard md i with 124 | | None -> [] 125 | | Some t -> t :: go (i + 1) 126 | in 127 | Array.of_list (go 0) 128 | 129 | let db_open_in ~source ~db : reader = 130 | let filename = db in 131 | let handle = Unix.openfile filename Unix.[ O_RDWR ] 0o640 in 132 | let md = Ancient.attach handle base_addr in 133 | let source = Bigstring.of_file source in 134 | { shards = load_shards md; source } 135 | 136 | type cursor = 137 | { db : reader 138 | ; shard : int 139 | ; offset : int 140 | ; count : int 141 | } 142 | 143 | let cursor_empty ~db = { db; shard = 0; offset = 0; count = 0 } 144 | let string_of_cursor c = Printf.sprintf "%i,%i,%i" c.count c.shard c.offset 145 | 146 | let cursor_of_string ~db str = 147 | match String.split_on_char ',' str with 148 | | [ count; shard; offset ] -> 149 | let int_of_string s = 150 | try int_of_string s with 151 | | _ -> 0 152 | in 153 | { db 154 | ; shard = int_of_string shard 155 | ; offset = int_of_string offset 156 | ; count = int_of_string count 157 | } 158 | | _ -> cursor_empty ~db 159 | 160 | let shards_stream ~cursor = 161 | let state = ref cursor in 162 | let f () = 163 | let cursor = !state in 164 | if cursor.shard >= Array.length cursor.db.shards 165 | then None 166 | else ( 167 | state := { cursor with shard = cursor.shard + 1; offset = 0 } ; 168 | let shard = cursor.db.shards.(cursor.shard) in 169 | Some (cursor, shard)) 170 | in 171 | Lwt_stream.from_direct f 172 | 173 | let get_shard cursor = cursor.db.shards.(cursor.shard) 174 | 175 | let fileloc_of_line ~cursor line = 176 | let shard = get_shard cursor in 177 | let _end_of_file, (filename, start_of_file) = 178 | Int_map.find_first (fun loc -> Int.compare loc line > 0) shard.file_map 179 | in 180 | filename, start_of_file 181 | 182 | let read_line ~cursor line_num = 183 | let shard = get_shard cursor in 184 | let line_offsets = shard.line_offsets in 185 | let start_of_line = Int_tbl.find line_offsets line_num in 186 | let end_of_line = Int_tbl.find line_offsets (line_num + 1) in 187 | let len = end_of_line - start_of_line - 1 in 188 | let line = Bigstring.sub cursor.db.source start_of_line len in 189 | line 190 | 191 | let total_lines ~cursor = 192 | Array.fold_left 193 | (fun acc shard -> 194 | let shard_size = Int_tbl.length shard.line_offsets in 195 | acc + shard_size) 196 | 0 197 | cursor.db.shards 198 | 199 | let total_lines_upto ~cursor = 200 | let total = ref 0 in 201 | for i = 0 to cursor.shard - 1 do 202 | let shard = cursor.db.shards.(i) in 203 | let shard_size = Int_tbl.length shard.line_offsets in 204 | total := !total + shard_size 205 | done ; 206 | !total + cursor.offset 207 | -------------------------------------------------------------------------------- /db/db.mli: -------------------------------------------------------------------------------- 1 | module Ngrams : Hashtbl.S with type key = string 2 | module Int_map : Map.S with type key = int 3 | module Int_tbl : Hashtbl.S with type key = int 4 | 5 | module Int_set : sig 6 | type t 7 | 8 | val cardinal : t -> int 9 | val make : unit -> t 10 | val add : t -> int -> unit 11 | val successor : t -> int -> int 12 | end 13 | 14 | module Alphabet : sig 15 | val is_valid : char -> bool 16 | val is_valid_string : string -> bool 17 | val is_alpha : char -> bool 18 | end 19 | 20 | type t = 21 | { line_offsets : int Int_tbl.t 22 | ; ngrams : Int_set.t Ngrams.t 23 | ; file_map : (string * int) Int_map.t 24 | } 25 | 26 | val make : unit -> t 27 | val set_file_ranges : string -> int * int -> t -> t 28 | val set_line_offset : t -> int -> int -> unit 29 | val find_ngram : t -> string -> Int_set.t 30 | 31 | type writer 32 | 33 | val open_out : string -> writer 34 | val save : db:writer -> t -> unit 35 | val close_out : writer -> unit 36 | 37 | type reader 38 | 39 | val db_open_in : source:string -> db:string -> reader 40 | 41 | type cursor = 42 | { db : reader 43 | ; shard : int 44 | ; offset : int 45 | ; count : int 46 | } 47 | 48 | val cursor_empty : db:reader -> cursor 49 | val string_of_cursor : cursor -> string 50 | val cursor_of_string : db:reader -> string -> cursor 51 | val shards_stream : cursor:cursor -> (cursor * t) Lwt_stream.t 52 | val fileloc_of_line : cursor:cursor -> int -> string * int 53 | val read_line : cursor:cursor -> int -> string 54 | val total_lines : cursor:cursor -> int 55 | val total_lines_upto : cursor:cursor -> int 56 | -------------------------------------------------------------------------------- /db/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name db) 3 | (libraries lwt.unix unix ancient)) 4 | -------------------------------------------------------------------------------- /db/int_set.ml: -------------------------------------------------------------------------------- 1 | let sparse_max_size = 32 2 | let base = 32 3 | let int_size = 63 4 | 5 | type s = 6 | | Zeroes 7 | | Dense of int array 8 | | Sparse of int array 9 | | Branch of s array 10 | 11 | type t = 12 | { mutable size : int 13 | ; mutable cardinal : int 14 | ; mutable s : s 15 | } 16 | 17 | let cardinal t = t.cardinal 18 | let make () = { size = base * int_size; cardinal = 0; s = Zeroes } 19 | 20 | let array_insert t i = 21 | assert (t.(Array.length t - 1) < i) ; 22 | Array.concat [ t; [| i |] ] 23 | 24 | let min_depth = base * int_size 25 | 26 | let dense_of_array t = 27 | let arr = Array.make base 0 in 28 | Array.iter 29 | (fun i -> 30 | let j = i / int_size in 31 | let i = i mod int_size in 32 | let v = arr.(j) in 33 | let v' = v lor (1 lsl i) in 34 | assert (v <> v') ; 35 | arr.(j) <- v') 36 | t ; 37 | arr 38 | 39 | let rec branch_of_array ~depth t = 40 | if Array.length t < sparse_max_size 41 | then Sparse t 42 | else if depth = min_depth 43 | then Dense (dense_of_array t) 44 | else ( 45 | let children = Array.make base [] in 46 | let depth = depth / base in 47 | for i = Array.length t - 1 downto 0 do 48 | let i = t.(i) in 49 | let j = i / depth in 50 | let i = i mod depth in 51 | children.(j) <- i :: children.(j) 52 | done ; 53 | let branches = 54 | Array.map 55 | (function 56 | | [] -> Zeroes 57 | | xs -> branch_of_array ~depth (Array.of_list xs)) 58 | children 59 | in 60 | Branch branches) 61 | 62 | let rec add_s ~depth t i = 63 | match t with 64 | | Zeroes -> Sparse [| i |] 65 | | Dense bs -> 66 | assert (depth = min_depth) ; 67 | let j = i / int_size in 68 | let b = bs.(j) in 69 | let i = i mod int_size in 70 | let b' = b lor (1 lsl i) in 71 | assert (b' <> b) ; 72 | bs.(j) <- b' ; 73 | t 74 | | Sparse arr -> 75 | let arr' = array_insert arr i in 76 | branch_of_array ~depth arr' 77 | | Branch arr -> 78 | assert (depth > 0) ; 79 | let depth = depth / Array.length arr in 80 | let j = i / depth in 81 | let child = arr.(j) in 82 | let i = i mod depth in 83 | let child' = add_s ~depth child i in 84 | arr.(j) <- child' ; 85 | t 86 | 87 | let rec grow ({ size; s; _ } as t) i = 88 | if i >= size 89 | then ( 90 | let children = Array.make base Zeroes in 91 | children.(0) <- s ; 92 | t.s <- Branch children ; 93 | t.size <- base * size ; 94 | grow t i) 95 | 96 | let add t i = 97 | grow t i ; 98 | t.s <- add_s ~depth:t.size t.s i ; 99 | t.cardinal <- t.cardinal + 1 100 | 101 | exception Found of int 102 | 103 | let rec successor_s ~depth t i = 104 | match t with 105 | | Zeroes -> () 106 | | Dense bs -> 107 | for real_i = i to (Array.length bs * int_size) - 1 do 108 | let i = real_i in 109 | let j = i / int_size in 110 | let i = i mod int_size in 111 | let b = bs.(j) in 112 | let v = b land (1 lsl i) in 113 | if v <> 0 then raise (Found real_i) 114 | done 115 | | Sparse arr -> Array.iter (fun v -> if v >= i then raise (Found v)) arr 116 | | Branch bs -> 117 | let depth = depth / base in 118 | let j = i / depth in 119 | let i = i mod depth in 120 | let () = 121 | try successor_s ~depth bs.(j) i with 122 | | Found c -> 123 | assert (c < depth) ; 124 | let c = (j * depth) + c in 125 | raise (Found c) 126 | in 127 | for k = j + 1 to Array.length bs - 1 do 128 | try successor_s ~depth bs.(k) 0 with 129 | | Found c -> 130 | assert (c < depth) ; 131 | let c = (k * depth) + c in 132 | raise (Found c) 133 | done 134 | 135 | let successor { size; s; _ } i = 136 | if i >= size 137 | then raise Not_found 138 | else ( 139 | try 140 | successor_s ~depth:size s i ; 141 | raise Not_found 142 | with 143 | | Found j -> j) 144 | -------------------------------------------------------------------------------- /db/int_set.mli: -------------------------------------------------------------------------------- 1 | type t 2 | 3 | val cardinal : t -> int 4 | val make : unit -> t 5 | val add : t -> int -> unit 6 | val successor : t -> int -> int 7 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 2.8) 2 | (using menhir 2.0) 3 | (generate_opam_files true) 4 | 5 | (name sherlocode) 6 | (source (github art-w/sherlocode)) 7 | (license MIT) 8 | (authors "Arthur Wendling") 9 | (maintainers "art.wendling@gmail.com") 10 | (version 0.1) 11 | 12 | (package 13 | (name sherlocode) 14 | (synopsis "Realtime grep for OCaml sources available on opam") 15 | (depends 16 | (ocaml (and (>= "4.08") (<= "4.13.0"))) 17 | (ancient (>= "0.9.1")) 18 | (cmdliner (>= "1.1.0")) 19 | (lwt (>= "4.5.2")) 20 | (higlo (>= "0.8")) 21 | (tyxml (>= "4.5.0")) 22 | (dream (= "1.0.0~alpha3")))) 23 | -------------------------------------------------------------------------------- /index/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (name index) 3 | (libraries cmdliner db)) 4 | -------------------------------------------------------------------------------- /index/index.ml: -------------------------------------------------------------------------------- 1 | module Ngrams = Db.Ngrams 2 | module Int_set = Db.Int_set 3 | 4 | let max_lines_per_shard = 1_000_000 5 | 6 | let string_drop_prefix ~prefix str = 7 | let n = String.length prefix in 8 | if String.length str < n 9 | then str 10 | else if String.sub str 0 n <> prefix 11 | then str 12 | else String.sub str n (String.length str - n) 13 | 14 | type t = 15 | { prefix : string 16 | ; db : Db.writer 17 | ; sources : out_channel 18 | ; offset : int 19 | ; nb_lines : int 20 | ; shard : Db.t 21 | } 22 | 23 | let make ~prefix ~ancient ~sources = 24 | { prefix 25 | ; db = Db.open_out ancient 26 | ; sources = open_out sources 27 | ; offset = 0 28 | ; nb_lines = 0 29 | ; shard = Db.make () 30 | } 31 | 32 | let set_file_ranges filename range t = 33 | let filename = string_drop_prefix ~prefix:t.prefix filename in 34 | { t with shard = Db.set_file_ranges filename range t.shard } 35 | 36 | let output_line t str = 37 | Db.set_line_offset t.shard t.nb_lines t.offset ; 38 | output_string t.sources str ; 39 | output_char t.sources '\n' ; 40 | { t with offset = t.offset + String.length str + 1; nb_lines = t.nb_lines + 1 } 41 | 42 | let store key value t = 43 | let bs = 44 | match Ngrams.find t.shard.ngrams key with 45 | | bs -> bs 46 | | exception Not_found -> 47 | let bs = Int_set.make () in 48 | Ngrams.add t.shard.ngrams key bs ; 49 | bs 50 | in 51 | Int_set.add bs value ; 52 | assert (Int_set.successor bs value = value) 53 | 54 | let get_ngrams str = 55 | let ngrams = Ngrams.create (String.length str) in 56 | for i = 0 to String.length str - 1 do 57 | let chr = str.[i] in 58 | if not (Db.Alphabet.is_alpha chr) 59 | then ( 60 | let single = String.make 1 chr in 61 | Ngrams.replace ngrams single ()) 62 | done ; 63 | for len = 2 to 3 do 64 | for i = 0 to String.length str - len do 65 | let shingle = String.sub str i len in 66 | if Db.Alphabet.is_valid_string shingle then Ngrams.replace ngrams shingle () 67 | done 68 | done ; 69 | ngrams 70 | 71 | let fold_lines f acc filename = 72 | try 73 | let h = open_in filename in 74 | let rec go acc = 75 | match input_line h with 76 | | line -> 77 | let acc = f acc line in 78 | go acc 79 | | exception End_of_file -> 80 | close_in h ; 81 | acc 82 | in 83 | go acc 84 | with 85 | | Sys_error _ -> acc 86 | 87 | let index filename t = 88 | let start_at = t.nb_lines in 89 | let t, _ = 90 | fold_lines 91 | (fun (t, parse_state) str -> 92 | let parse_state, str = Syntax.clean_line ~state:parse_state str in 93 | if String.length str > 256 94 | then t, parse_state 95 | else ( 96 | Ngrams.iter (fun ngram () -> store ngram t.nb_lines t) (get_ngrams str) ; 97 | let t = output_line t str in 98 | t, parse_state)) 99 | (t, Syntax.empty) 100 | filename 101 | in 102 | if t.nb_lines > start_at then set_file_ranges filename (start_at, t.nb_lines) t else t 103 | 104 | let save t = 105 | let () = Db.save ~db:t.db t.shard in 106 | Printf.printf "Created shard: %i lines\n%!" t.nb_lines ; 107 | let t = { t with shard = Db.make (); nb_lines = 0 } in 108 | Gc.compact () ; 109 | t 110 | 111 | let rec fold_stdin f z = 112 | match read_line () with 113 | | filename -> 114 | let z = f z filename in 115 | fold_stdin f z 116 | | exception End_of_file -> z 117 | 118 | let db_create_stdin t = 119 | let t = 120 | fold_stdin 121 | (fun t filename -> 122 | let t = if t.nb_lines < max_lines_per_shard then t else save t in 123 | index filename t) 124 | t 125 | in 126 | if t.nb_lines > 0 then save t else t 127 | 128 | let main prefix path = 129 | let ancient = path ^ "/ancient.db" in 130 | let sources = path ^ "/source.txt" in 131 | let t0 = Unix.gettimeofday () in 132 | let t = make ~prefix ~ancient ~sources in 133 | let t = db_create_stdin t in 134 | Db.close_out t.db ; 135 | flush t.sources ; 136 | close_out t.sources ; 137 | let t1 = Unix.gettimeofday () in 138 | Printf.printf "Indexing in %fs\n%!" (t1 -. t0) 139 | 140 | open Cmdliner 141 | 142 | let prefix = 143 | let doc = "Directory prefix that should be stripped from indexed files" in 144 | Arg.(value & opt string "./" & info [ "prefix" ] ~docv:"PREFIX" ~doc) 145 | 146 | let target = 147 | let doc = "Directory where the db will be stored" in 148 | Arg.(required & pos 0 (some dir) None & info [] ~docv:"TARGET" ~doc) 149 | 150 | let index = Term.(const main $ prefix $ target) 151 | 152 | let cmd = 153 | let doc = "Index the files provided on stdin" in 154 | let info = Cmd.info "index" ~doc in 155 | Cmd.v info index 156 | 157 | let () = exit (Cmd.eval cmd) 158 | -------------------------------------------------------------------------------- /index/syntax.ml: -------------------------------------------------------------------------------- 1 | type ctx = Comment 2 | type t = ctx list 3 | 4 | let empty : t = [] 5 | let char0 = Char.chr 0 6 | 7 | module String = struct 8 | let length = String.length 9 | let get t i = if i >= String.length t then char0 else String.unsafe_get t i 10 | end 11 | 12 | let clean_line ~state line = 13 | let len = String.length line in 14 | let buf = Buffer.create len in 15 | let rec go state i = 16 | if i >= len 17 | then state 18 | else ( 19 | match line.[i], line.[i + 1], line.[i + 2] with 20 | | '(', '*', ')' -> 21 | (match state with 22 | | [] -> Buffer.add_string buf "(*)" 23 | | _ -> ()) ; 24 | go state (i + 3) 25 | | '(', '*', _ -> go (Comment :: state) (i + 2) 26 | | '*', ')', _ -> 27 | (match state with 28 | | Comment :: state -> go state (i + 2) 29 | | [] -> 30 | Buffer.add_char buf '*' ; 31 | go state (i + 1)) 32 | | chr, _, _ -> 33 | (match state with 34 | | [] when chr = '\t' -> Buffer.add_string buf " " 35 | | [] when Db.Alphabet.is_valid chr -> Buffer.add_char buf chr 36 | | _ -> ()) ; 37 | go state (i + 1)) 38 | in 39 | let state = go state 0 in 40 | state, Buffer.contents buf 41 | -------------------------------------------------------------------------------- /index/syntax.mli: -------------------------------------------------------------------------------- 1 | type t 2 | 3 | val empty : t 4 | val clean_line : state:t -> string -> t * string 5 | -------------------------------------------------------------------------------- /regex/ast.ml: -------------------------------------------------------------------------------- 1 | module Char_set = Set.Make (Char) 2 | 3 | type t = 4 | | Empty 5 | | Any 6 | | Char of char 7 | | Char_set of Char_set.t 8 | | Or of t * t 9 | | And of t * t 10 | | Star0 of t 11 | | Star1 of t 12 | | Maybe of t 13 | | Line_start 14 | | Line_end 15 | | Word_boundary 16 | 17 | let enum a b = 18 | let a, b = if a < b then a, b else b, a in 19 | Array.fold_left (fun acc x -> Char_set.add x acc) Char_set.empty 20 | @@ Array.init (Char.code b - Char.code a + 1) (fun i -> Char.chr (Char.code a + i)) 21 | 22 | let alphanum = 23 | List.fold_left 24 | Char_set.union 25 | (enum 'A' 'Z') 26 | [ enum 'a' 'z'; enum '0' '9'; Char_set.singleton '_'; Char_set.singleton '\'' ] 27 | 28 | let alphabet = 29 | List.fold_left (fun acc chr -> Char_set.add chr acc) Char_set.empty 30 | @@ List.filter (fun c -> Db.Alphabet.is_valid c && c <> '\n') 31 | @@ List.init 256 Char.chr 32 | 33 | let inv cs = Char_set.diff alphabet cs 34 | -------------------------------------------------------------------------------- /regex/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name regex) 3 | (libraries str db)) 4 | 5 | (ocamllex lexer) 6 | 7 | (menhir 8 | (modules parser) 9 | (flags --explain)) 10 | 11 | (env 12 | (dev 13 | (flags 14 | (:standard -w -39)))) 15 | 16 | ; menhir unused-rec-flag 17 | -------------------------------------------------------------------------------- /regex/lexer.mll: -------------------------------------------------------------------------------- 1 | { 2 | open Parser 3 | } 4 | 5 | rule token = parse 6 | | "\\|" { OR } 7 | | "\\(" { PAR_OPEN } 8 | | "\\)" { PAR_CLOSE } 9 | | "\\*" { STAR } 10 | | "\\+" { PLUS } 11 | | "\\?" { OPTIONAL } 12 | | "\\." { ANY } 13 | | "-" { RANGE } 14 | | "\\[" { RANGE_START } 15 | | "\\[^" { RANGE_EXCL_START } 16 | | "\\]" { RANGE_END } 17 | | "\\^" { LINE_START } 18 | | "\\$" { LINE_END } 19 | | "\\b" { WORD_BOUNDARY } 20 | | "\\w" { ALPHANUM } 21 | | "\\\\" { CHAR '\\' } 22 | | _ as s { CHAR s } 23 | | eof { EOF } 24 | -------------------------------------------------------------------------------- /regex/parser.mly: -------------------------------------------------------------------------------- 1 | %{ 2 | open Ast 3 | %} 4 | 5 | %token EOF 6 | %token ANY 7 | %token CHAR 8 | %token PAR_OPEN PAR_CLOSE 9 | %token RANGE_START RANGE_EXCL_START RANGE RANGE_END 10 | %token OR 11 | %token STAR PLUS OPTIONAL 12 | %token ALPHANUM 13 | %token LINE_START LINE_END 14 | %token WORD_BOUNDARY 15 | 16 | %start main 17 | %type main 18 | 19 | %% 20 | 21 | main: 22 | | r=regex EOF { r } 23 | 24 | regex: 25 | | r = disjunction { r } 26 | 27 | disjunction: 28 | | a = disjunction OR b = concat { Or(a, b) } 29 | | a = disjunction OR EOF { a } 30 | | r = concat {r} 31 | 32 | concat: 33 | | a = concat b = repetition { And(a, b) } 34 | | r = repetition {r} 35 | 36 | repetition: 37 | | r = repetition STAR { Star0 r } 38 | | r = repetition PLUS { Star1 r } 39 | | r = repetition OPTIONAL { Maybe r } 40 | | r = atom { r } 41 | 42 | atom: 43 | | PAR_OPEN PAR_CLOSE { Empty } 44 | | PAR_OPEN r = regex PAR_CLOSE { r } 45 | | PAR_OPEN EOF { Empty } 46 | | PAR_OPEN r = regex EOF { r } 47 | | c = char { Char c } 48 | | ANY { Any } 49 | | r=range { r } 50 | | LINE_START { Line_start } 51 | | LINE_END { Line_end } 52 | | WORD_BOUNDARY { Word_boundary } 53 | 54 | range: 55 | | ALPHANUM { Char_set Ast.alphanum } 56 | | RANGE_START r=range_contents { Char_set r } 57 | | RANGE_EXCL_START r=range_contents { Char_set (inv r) } 58 | 59 | range_contents: 60 | | a=CHAR RANGE b=CHAR xs=range_contents { Char_set.union (enum a b) xs } 61 | | a=char xs=range_contents { Char_set.add a xs } 62 | | RANGE_END { Char_set.empty } 63 | 64 | char: 65 | | a=CHAR { a } 66 | | RANGE { '-' } 67 | -------------------------------------------------------------------------------- /regex/regex.ml: -------------------------------------------------------------------------------- 1 | open Ast 2 | 3 | type t = Ast.t 4 | 5 | type query = 6 | | True 7 | | False 8 | | Exact of string 9 | | And of query list 10 | | Or of query list 11 | 12 | let rec interleave xs ys = 13 | match xs with 14 | | [] -> ys 15 | | x :: xs -> x :: interleave ys xs 16 | 17 | let conj a b = 18 | match a, b with 19 | | False, _ | _, False -> False 20 | | True, t | t, True -> t 21 | | And xs, And ys -> And (interleave xs ys) 22 | | And xs, t | t, And xs -> And (t :: xs) 23 | | _ -> And [ a; b ] 24 | 25 | let conjunction = function 26 | | [] -> True 27 | | [ t ] -> t 28 | | xs -> And xs 29 | 30 | let diff xs ys = 31 | let rec go shared xs_only ys_only xs ys = 32 | match xs, ys with 33 | | x :: xs, y :: ys when x = y -> go (x :: shared) xs_only ys_only xs ys 34 | | x :: xs, y :: ys when x < y -> go shared (x :: xs_only) ys_only xs (y :: ys) 35 | | x :: xs, y :: ys -> go shared xs_only (y :: ys_only) (x :: xs) ys 36 | | [], [] -> shared, xs_only, ys_only 37 | | [], ys -> shared, xs_only, interleave ys ys_only 38 | | xs, [] -> shared, interleave xs xs_only, ys_only 39 | in 40 | go [] [] [] (List.sort Stdlib.compare xs) (List.sort Stdlib.compare ys) 41 | 42 | let disj a b = 43 | match a, b with 44 | | False, t | t, False -> t 45 | | True, _ | _, True -> True 46 | | Or xs, Or ys -> Or (interleave xs ys) 47 | | Or xs, t | t, Or xs -> Or (t :: xs) 48 | | And xs, And ys -> 49 | let shared, xs, ys = diff xs ys in 50 | conj (conjunction shared) (Or (interleave xs ys)) 51 | | _ -> Or [ a; b ] 52 | 53 | let disjunction = function 54 | | [] -> True 55 | | xs when List.mem True xs -> True 56 | | [ x ] -> x 57 | | x :: xs -> 58 | let xs = List.filter (( <> ) False) xs in 59 | List.fold_right disj xs x 60 | 61 | let truncate cs = Trie.truncate 2 cs 62 | let disj_of_trie cs = disjunction @@ List.map (fun str -> Exact str) @@ Trie.to_list cs 63 | 64 | let query_of_cs cs = 65 | let rec go depth cs = 66 | if Trie.compare_length_with cs 111 < 0 67 | then disj_of_trie cs 68 | else if depth = 0 69 | then True 70 | else go (depth - 1) (Trie.truncate depth cs) 71 | in 72 | go 2 cs 73 | 74 | let rec make_query previous t = 75 | match t with 76 | | Empty | Line_end | Word_boundary -> True, previous 77 | | Line_start -> True, Trie.single 78 | | Any -> True, Trie.alphabet 79 | | Maybe r -> 80 | let _, previous1 = make_query previous r in 81 | let previous = Trie.union previous previous1 in 82 | True, previous 83 | | Star0 r -> 84 | let _, previous1 = make_query previous r in 85 | let _, previous2 = make_query previous1 r in 86 | let _, previous3 = make_query previous2 r in 87 | let previous = Trie.union_list [ previous; previous1; previous2; previous3 ] in 88 | True, previous 89 | | Star1 r -> 90 | let s, previous1 = make_query previous r in 91 | let _, previous2 = make_query previous1 r in 92 | let _, previous3 = make_query previous2 r in 93 | let previous = Trie.union_list [ previous1; previous2; previous3 ] in 94 | s, previous 95 | | And (a, b) -> 96 | let req_a, previous = make_query previous a in 97 | let req_b, previous = make_query previous b in 98 | conj req_a req_b, previous 99 | | Or (a, b) -> 100 | let req_a, previous_a = make_query previous a in 101 | let req_b, previous_b = make_query previous b in 102 | let previous = Trie.union previous_a previous_b in 103 | disj req_a req_b, previous 104 | | Char c -> 105 | let req = Trie.prefix c previous in 106 | query_of_cs req, truncate req 107 | | Char_set cs -> 108 | let req = Trie.prefixes cs previous in 109 | query_of_cs req, truncate req 110 | 111 | let to_query r = 112 | let q, _ = make_query Trie.single r in 113 | q 114 | 115 | let parse s = 116 | try Parser.main Lexer.token (Lexing.from_string s) with 117 | | _ -> Empty 118 | 119 | let reserved_chars = "$^\\.*+?[]" 120 | let is_reserved c = String.index_from_opt reserved_chars 0 c <> None 121 | 122 | let rec to_regex = function 123 | | Empty -> "" 124 | | Any -> "." 125 | | Char c when is_reserved c -> Printf.sprintf "\\%c" c 126 | | Char c -> Printf.sprintf "%c" c 127 | | Char_set cs -> 128 | let buf = Buffer.create (Char_set.cardinal cs) in 129 | Buffer.add_char buf '[' ; 130 | if Char_set.mem ']' cs then Buffer.add_char buf ']' ; 131 | Char_set.iter 132 | (fun c -> if not (c = ']' || c = '-' || c = '^') then Buffer.add_char buf c) 133 | cs ; 134 | if Char_set.mem '^' cs then Buffer.add_char buf '^' ; 135 | if Char_set.mem '-' cs then Buffer.add_char buf '-' ; 136 | Buffer.add_char buf ']' ; 137 | Buffer.contents buf 138 | | Or (a, b) -> "\\(" ^ to_regex a ^ "\\|" ^ to_regex b ^ "\\)" 139 | | And (a, b) -> to_regex a ^ to_regex b 140 | | Star0 r -> to_regex_parens r ^ "*" 141 | | Star1 r -> to_regex_parens r ^ "+" 142 | | Maybe r -> to_regex_parens r ^ "?" 143 | | Line_start -> "^" 144 | | Line_end -> "$" 145 | | Word_boundary -> "\\b" 146 | 147 | and to_regex_parens r = 148 | match r with 149 | | Empty | Any | Char _ | Char_set _ -> to_regex r 150 | | _ -> "\\(" ^ to_regex r ^ "\\)" 151 | 152 | let to_regex r = Str.regexp (to_regex r) 153 | -------------------------------------------------------------------------------- /regex/regex.mli: -------------------------------------------------------------------------------- 1 | type t 2 | 3 | val parse : string -> t 4 | 5 | type query = 6 | | True 7 | | False 8 | | Exact of string 9 | | And of query list 10 | | Or of query list 11 | 12 | val to_query : t -> query 13 | val to_regex : t -> Str.regexp 14 | -------------------------------------------------------------------------------- /regex/trie.ml: -------------------------------------------------------------------------------- 1 | module Char_set = Ast.Char_set 2 | module Char_map = Map.Make (Char) 3 | 4 | type t = 5 | { eos : bool 6 | ; children : t Char_map.t 7 | } 8 | 9 | let empty = { eos = false; children = Char_map.empty } 10 | let single = { eos = true; children = Char_map.empty } 11 | let prefix chr t = { eos = false; children = Char_map.singleton chr t } 12 | 13 | let prefixes cs t = 14 | { eos = false 15 | ; children = 16 | Char_set.fold (fun chr children -> Char_map.add chr t children) cs Char_map.empty 17 | } 18 | 19 | let alphabet = prefixes Ast.alphabet single 20 | 21 | let rec union a b = 22 | { eos = a.eos || b.eos 23 | ; children = 24 | Char_map.merge 25 | (fun _ ox oy -> 26 | match ox, oy with 27 | | None, t | t, None -> t 28 | | Some x, Some y -> Some (union x y)) 29 | a.children 30 | b.children 31 | } 32 | 33 | let union_list lst = List.fold_left union empty lst 34 | 35 | let fold f t z = 36 | let rec go prefix z t = 37 | let z = if t.eos then f prefix z else z in 38 | Char_map.fold 39 | (fun chr child z -> 40 | let prefix = String.make 1 chr ^ prefix in 41 | go prefix z child) 42 | t.children 43 | z 44 | in 45 | go "" z t 46 | 47 | let rec truncate n t = 48 | if n = 0 49 | then { eos = true; children = Char_map.empty } 50 | else ( 51 | let n = n - 1 in 52 | { t with children = Char_map.map (fun t -> truncate n t) t.children }) 53 | 54 | let to_list t = fold (fun s z -> s :: z) t [] 55 | 56 | exception Abort 57 | 58 | let compare_length_with t n = 59 | try 60 | let size = 61 | fold 62 | (fun _ z -> 63 | let z = z + 1 in 64 | if z > n then raise Abort else z) 65 | t 66 | 0 67 | in 68 | compare size n 69 | with 70 | | Abort -> 1 71 | -------------------------------------------------------------------------------- /regex/trie.mli: -------------------------------------------------------------------------------- 1 | type t 2 | 3 | val empty : t 4 | val single : t 5 | val alphabet : t 6 | val prefix : char -> t -> t 7 | val prefixes : Ast.Char_set.t -> t -> t 8 | val truncate : int -> t -> t 9 | val to_list : t -> string list 10 | val union : t -> t -> t 11 | val union_list : t list -> t 12 | val compare_length_with : t -> int -> int 13 | -------------------------------------------------------------------------------- /scripts/index.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ]; then 4 | echo 'missing source directory' 5 | exit 1 6 | fi 7 | 8 | if [ -z "$2" ]; then 9 | echo 'missing target directory' 10 | exit 1 11 | fi 12 | 13 | dune build index/index.exe 14 | 15 | find "$1" -name '*.ml*' \ 16 | | sort -R \ 17 | | dune exec -- index/index.exe --prefix="$1" "$2" 18 | -------------------------------------------------------------------------------- /sherlocode.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | version: "0.1" 4 | synopsis: "Realtime grep for OCaml sources available on opam" 5 | maintainer: ["art.wendling@gmail.com"] 6 | authors: ["Arthur Wendling"] 7 | license: "MIT" 8 | homepage: "https://github.com/art-w/sherlocode" 9 | bug-reports: "https://github.com/art-w/sherlocode/issues" 10 | depends: [ 11 | "dune" {>= "2.8"} 12 | "ocaml" {>= "4.08" & <= "4.13.0"} 13 | "ancient" {>= "0.9.1"} 14 | "cmdliner" {>= "1.1.0"} 15 | "lwt" {>= "4.5.2"} 16 | "higlo" {>= "0.8"} 17 | "tyxml" {>= "4.5.0"} 18 | "dream" {= "1.0.0~alpha3"} 19 | "odoc" {with-doc} 20 | ] 21 | build: [ 22 | ["dune" "subst"] {dev} 23 | [ 24 | "dune" 25 | "build" 26 | "-p" 27 | name 28 | "-j" 29 | jobs 30 | "@install" 31 | "@runtest" {with-test} 32 | "@doc" {with-doc} 33 | ] 34 | ] 35 | dev-repo: "git+https://github.com/art-w/sherlocode.git" 36 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/art-w/sherlocode/d87e61f4d55c2a56f525a9fcd51e9f2c19c05223/static/favicon.ico -------------------------------------------------------------------------------- /static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: /$ 3 | Disallow: / 4 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | margin-bottom: 2rem; 4 | padding: 0; 5 | 6 | --hl-color: #FBE180; 7 | --lightbg: #DEF2F1; 8 | --bg: #FEFFFF; 9 | --darkgreen: #00262A; 10 | --yellow: #FFF9C7; 11 | --green: #016670; 12 | --bluetxt: #00434A; 13 | --grey: #9CADAD; 14 | 15 | background: var(--bg); 16 | } 17 | 18 | mark { 19 | background: var(--hl-color); 20 | font-style: normal; 21 | font-weight: bold; 22 | 23 | position: relative; 24 | } 25 | mark::after { 26 | content: ''; 27 | position: absolute; 28 | top: 0; 29 | left: 0; 30 | width: 100%; 31 | height: 100%; 32 | outline: 1px solid var(--hl-color); 33 | z-index: -1; 34 | } 35 | 36 | .header { 37 | top: 0; 38 | position: sticky; 39 | z-index: 999; 40 | 41 | padding: 1vmax 0; 42 | padding-left: 2.5rem; 43 | padding-right: 1vmax; 44 | 45 | background: var(--green); 46 | border-bottom: 2px solid var(--darkgreen); 47 | } 48 | .header form { 49 | margin: 0; 50 | padding: 0; 51 | display: flex; 52 | flex-flow: row nowrap; 53 | } 54 | 55 | input[name='q'] { 56 | font-family: monospace; 57 | font-size: 1.25em; 58 | 59 | display: block; 60 | flex: 1; 61 | min-width: 0; 62 | max-width: 40rem; 63 | 64 | -webkit-appearance: none; 65 | -moz-appearance: none; 66 | -ms-appearance: none; 67 | -o-appearance: none; 68 | appearance: none; 69 | 70 | padding: 0.25rem 0.5rem; 71 | 72 | border: 2px solid var(--darkgreen); 73 | background: var(--bg); 74 | } 75 | 76 | input[name='q']::placeholder { 77 | color: #2B7A77; 78 | opacity: 1; 79 | } 80 | 81 | input[name='q']:focus { 82 | background: var(--lightbg); 83 | } 84 | 85 | input[type='submit'] { 86 | flex-shrink: 0; 87 | font-size: 1em; 88 | 89 | -webkit-appearance: none; 90 | -moz-appearance: none; 91 | -ms-appearance: none; 92 | -o-appearance: none; 93 | appearance: none; 94 | 95 | background: var(--darkgreen); 96 | 97 | color: var(--yellow); 98 | outline: none; 99 | border: none; 100 | 101 | line-height: 1.5rem; 102 | 103 | border: 2px solid var(--darkgreen); 104 | 105 | margin-right: 1em; 106 | } 107 | 108 | h3 { 109 | font-size: 1em; 110 | margin: 0; 111 | padding: 0; 112 | font-family: monospace; 113 | margin-top: 1.25rem; 114 | margin-bottom: 0.25rem; 115 | margin-left: 1px; 116 | padding-left: 3rem; 117 | font-weight: bold; 118 | } 119 | 120 | .ln { 121 | display: block; 122 | width: 2rem; 123 | min-width: 2rem; 124 | 125 | color: var(--grey); 126 | text-align: right; 127 | font-family: monospace; 128 | padding-right: 0.5rem; 129 | margin-right: 0.5rem; 130 | border-right: 2px solid var(--grey); 131 | 132 | -webkit-touch-callout: none; 133 | -webkit-user-select: none; 134 | -khtml-user-select: none; 135 | -moz-user-select: none; 136 | -ms-user-select: none; 137 | user-select: none; 138 | } 139 | 140 | .result { 141 | line-height: 1em; 142 | margin: 0; 143 | padding: 0; 144 | 145 | line-height: 1em; 146 | 147 | display: flex; 148 | align-items: stretch; 149 | } 150 | 151 | .result code { 152 | display: block; 153 | width: 100%; 154 | white-space: pre-wrap; 155 | z-index: 1; 156 | } 157 | 158 | .result:hover { 159 | background: var(--lightbg); 160 | z-index: -2; 161 | } 162 | 163 | .result:hover .ln { 164 | color: #300F0A; 165 | } 166 | 167 | 168 | 169 | .string { color: var(--darkgreen); } 170 | .comment { color: var(--darkgreen); font-style: italic } 171 | 172 | .ident { color: black } 173 | 174 | .symbol, .numeric, .directive, .constant, .escape, .kw { 175 | color: var(--green); 176 | } 177 | 178 | a { 179 | text-decoration: none; 180 | color: var(--bluetxt); 181 | } 182 | 183 | a:hover { 184 | text-decoration: underline; 185 | } 186 | 187 | p, table { 188 | margin: 0.5rem 1vmax; 189 | margin-left: 3rem; 190 | font-family: sans-serif; 191 | color: #1F240A; 192 | font-size: 1.1rem; 193 | } 194 | table td:nth-child(1) { 195 | padding-left: 2rem; 196 | padding-right: 1rem; 197 | text-align: right; 198 | } 199 | table td:nth-child(1) code { 200 | background: var(--yellow); 201 | padding: 0.1rem 0.5rem; 202 | } 203 | td { 204 | padding: 0.25rem 0; 205 | } 206 | 207 | a.example { 208 | background: var(--lightbg); 209 | margin: 0 0.1rem; 210 | padding: 0.1rem 0.5rem; 211 | border-radius: 1rem; 212 | } 213 | a.example:hover { 214 | text-decoration: none; 215 | background: var(--green); 216 | color: var(--yellow); 217 | } 218 | 219 | h1 { 220 | margin: 0 1vmax; 221 | margin-top: 2rem; 222 | margin-bottom: 1rem; 223 | margin-left: 3rem; 224 | font-family: monospace; 225 | font-family: serif; 226 | font-size: 3em; 227 | } 228 | 229 | .projects { 230 | line-height: 1.75rem; 231 | margin-right: 3.5rem; 232 | font-family: monospace; 233 | margin: 2rem 1vmax; 234 | column-count: 4; 235 | column-width: 20rem; 236 | column-gap: 2rem; 237 | } 238 | 239 | a.project { 240 | padding: 0.3em 0.5em; 241 | background: var(--lightbg); 242 | margin: 0; 243 | white-space: nowrap; 244 | color: var(--bluetxt); 245 | } 246 | 247 | a.project:hover { 248 | background: var(--darkgreen); 249 | color: var(--yellow); 250 | text-decoration: none; 251 | font-weight: bold; 252 | } 253 | 254 | .category { 255 | break-inside: avoid-column; 256 | page-break-inside: avoid; 257 | display: inline-block; 258 | margin-bottom: 1rem; 259 | } 260 | 261 | .category h3 { 262 | padding: 0; 263 | margin: 0; 264 | font-size: 1.25em; 265 | float: left; 266 | margin-right: 1rem; 267 | } 268 | 269 | .ln.break_below { 270 | border-bottom-right-radius: 5px; 271 | } 272 | .ln.break_above { 273 | border-top-right-radius: 5px; 274 | } 275 | 276 | #results p { 277 | margin-top: 2rem; 278 | } 279 | 280 | .btn { 281 | padding: 0.25rem 1rem; 282 | 283 | background: var(--darkgreen); 284 | 285 | color: var(--yellow); 286 | outline: none; 287 | border: none; 288 | 289 | line-height: 1.5rem; 290 | 291 | border: 2px solid var(--darkgreen); 292 | } 293 | 294 | h2 { 295 | margin: 0; 296 | padding: 0; 297 | padding: 0.5rem; 298 | padding-left: 3rem; 299 | font-size: 1rem; 300 | background: var(--yellow); 301 | background: var(--lightbg); 302 | border-bottom: 1px solid #BFDEDC; 303 | } 304 | 305 | h2 code { 306 | background: var(--bg); 307 | margin-left: 0.25rem; 308 | padding: 0.1rem 0.75rem; 309 | border-radius: 1rem; 310 | } 311 | 312 | p.hero { 313 | font-size: 1.5rem; 314 | } 315 | 316 | .hero .new { 317 | font-style: italic; 318 | font-size: 1rem; 319 | background: var(--yellow); 320 | vertical-align: top; 321 | } 322 | 323 | .hero .new a { 324 | font-weight: bold; 325 | text-decoration: underline; 326 | } 327 | 328 | .ad { 329 | padding-top: 3rem; 330 | font-family: monospace; 331 | font-style: italic; 332 | } 333 | 334 | .ad svg { vertical-align: middle; margin-right: 0.5rem } 335 | 336 | .header a, .header a:visited { 337 | display: inline-block; 338 | color: var(--lightbg); 339 | margin: 0 2em; 340 | padding: 0.25em 0; 341 | text-decoration: none; 342 | font-size: 1rem; 343 | font-style: italic; 344 | border-bottom: 2px solid var(--lightbg); 345 | align-self: center; 346 | } 347 | 348 | .header a:hover { 349 | color: var(--yellow); 350 | border-bottom: 2px solid var(--yellow); 351 | } 352 | -------------------------------------------------------------------------------- /static/urls.tsv: -------------------------------------------------------------------------------- 1 | 0install github.com/0install/0install 2 | aacplus github.com/savonet/ocaml-aacplus 3 | abella github.com/abella-prover/abella 4 | absolute github.com/mpelleau/AbSolute 5 | accessor github.com/janestreet/accessor 6 | accessor_async github.com/janestreet/accessor_async 7 | accessor_base github.com/janestreet/accessor_base 8 | accessor_core github.com/janestreet/accessor_core 9 | acgtk gitlab.inria.fr/ACG/dev/ACGtk 10 | acme github.com/raphael-proust/ocaml-acme 11 | acpc github.com/UnixJunkie/ACPC 12 | advi github.com/diremy/advi 13 | afl-persistent github.com/stedolan/ocaml-afl-persistent 14 | ago github.com/lindig/ocaml-ago 15 | agrid github.com/ocamlpro/agrid 16 | ahrocksdb github.com/ahrefs/ocaml-ahrocksdb 17 | aifad github.com/mmottl/aifad 18 | alba github.com/hbr/albatross 19 | albatross github.com/roburio/albatross 20 | alberto github.com/selectel/alberto 21 | alcotest github.com/mirage/alcotest 22 | alg_structs github.com/shonfeder/alg_structs 23 | aliases github.com/besport/ocaml-aliases 24 | alsa github.com/savonet/ocaml-alsa 25 | alt-ergo github.com/OCamlPro/alt-ergo 26 | amf github.com/briancaine/ocaml-amf 27 | amqp-client github.com/andersfugmann/amqp-client 28 | ancient github.com/UnixJunkie/ocaml-ancient 29 | angstrom github.com/inhabitedtype/angstrom 30 | annot github.com/avsm/ocaml-annot 31 | ansi-parse github.com/jdjakub/ansi-parse 32 | ANSITerminal github.com/Chris00/ANSITerminal 33 | anthill github.com/martindemello/anthill 34 | anycache gitlab.com/edwintorok/ocaml-anycache 35 | ao github.com/savonet/ocaml-ao 36 | aperf github.com/philipdexter/aperf 37 | apero-core github.com/atolab/apero-core 38 | apero-net github.com/atolab/apero-net 39 | apero-time github.com/atolab/apero-time 40 | apron github.com/antoinemine/apron 41 | apronext github.com/ghilesZ/apronext 42 | arakoon github.com/openvstorage/arakoon 43 | archetype github.com/edukera/archetype-lang 44 | archi github.com/anmonteiro/archi 45 | archsat scm.gforge.inria.fr/anonscm/git/archsat/archsat 46 | argon2 github.com/Khady/ocaml-argon2 47 | arp github.com/mirage/arp 48 | art github.com/dinosaure/art 49 | asak github.com/nobrakal/asak 50 | ascii85 github.com/lindig/ascii85 51 | asetmap erratique.ch/repos/asetmap 52 | ask github.com/uzh/ask 53 | asl github.com/mirage/ocaml-asl 54 | asli github.com/alastairreid/asl-interpreter 55 | asn1-combinators github.com/mirleft/ocaml-asn1-combinators 56 | assertions github.com/bennn/assertions 57 | assimp github.com/def-lkb/assimp 58 | astring erratique.ch/repos/astring 59 | async github.com/janestreet/async 60 | async_core github.com/janestreet/async_core 61 | async_durable github.com/janestreet/async_durable 62 | async_extended github.com/janestreet/async_extended 63 | async_extra github.com/janestreet/async_extra 64 | async_find github.com/janestreet/async_find 65 | async_graphics github.com/lpw25/async_graphics 66 | async_inotify github.com/janestreet/async_inotify 67 | iasync_interactive github.com/janestreet/async_interactive 68 | async_js github.com/janestreet/async_js 69 | async_kernel github.com/janestreet/async_kernel 70 | async-mvar github.com/rgrinberg/async-mvar 71 | async_parallel github.com/janestreet/async_parallel 72 | async_rpc_kernel github.com/janestreet/async_rpc_kernel 73 | async_sendfile github.com/janestreet/async_sendfile 74 | async_shell github.com/janestreet/async_shell 75 | async_smtp github.com/janestreet/async_smtp 76 | async_ssl github.com/janestreet/async_ssl 77 | async_udp github.com/janestreet/async_udp 78 | async_unix github.com/janestreet/async_unix 79 | async-uri github.com/vbmithr/async-uri 80 | async_websocket github.com/janestreet/async_websocket 81 | async-zmq github.com/rgrinberg/async-zmq 82 | atable github.com/ocamlpro/atable 83 | atd github.com/ahrefs/atd 84 | atd2cconv github.com/smondet/atd2cconv 85 | atdj github.com/esperco/atdj 86 | augeas git.annexia.org/ocaml-augeas 87 | avroc github.com/sidharthkuruvila/ocaml-avroc 88 | awa github.com/mirage/awa-ssh 89 | aws github.com/inhabitedtype/ocaml-aws 90 | aws-s3 github.com/andersfugmann/aws-s3 91 | azblob github.com/kkazuo/azblob 92 | azure-cosmos-db bitbucket.org/knaack/azure-cosmos-db 93 | b0 erratique.ch/repos/b0 94 | baardskeerder github.com/Incubaid/baardskeerder 95 | bag github.com/backtracking/bag 96 | balancer github.com/xnukernpoll/ocaml-balancers 97 | bamboo github.com/pirapira/bamboo 98 | bap github.com/BinaryAnalysisPlatform/bap/ 99 | bap-emacs-dot github.com/ivg/emacs-dot/ 100 | bap-emacs-mode github.com/fkie-cad/bap-mode 101 | bap-ida-python github.com/BinaryAnalysisPlatform/bap-ida-python/ 102 | bap-saluki github.com/BinaryAnalysisPlatform/bap-plugins/ 103 | bap-server github.com/BinaryAnalysisPlatform/bap-server/ 104 | bap-veri github.com/BinaryAnalysisPlatform/bap-veri/ 105 | bark github.com/justinlubin/bark 106 | base github.com/janestreet/base 107 | base58 github.com/sylvarant/base58 108 | base64 github.com/mirage/ocaml-base64 109 | base_bigstring github.com/janestreet/base_bigstring 110 | base_quickcheck github.com/janestreet/base_quickcheck 111 | bastet github.com/Risto-Stevcev/bastet 112 | bastet_async github.com/Risto-Stevcev/bastet-async 113 | bastet_lwt github.com/Risto-Stevcev/bastet-lwt 114 | batch_jaro_winkler github.com/dbousque/batch_jaro_winkler 115 | batsat github.com/c-cube/batsat-ocaml 116 | batsh github.com/BYVoid/Batsh 117 | batteries github.com/ocaml-batteries-team/batteries-included 118 | bau github.com/rleonid/bau 119 | bear github.com/hcarty/bear 120 | bech32 github.com/vbmithr/ocaml-bech32 121 | bechamel github.com/dinosaure/bechamel 122 | beluga github.com/Beluga-lang/Beluga 123 | benchmark github.com/Chris00/ocaml-benchmark 124 | benchpress github.com/sneeuwballen/benchpress 125 | bencode github.com/rgrinberg/bencode 126 | bentov github.com/barko/bentov 127 | BetterErrors github.com/chenglou/BetterErrors 128 | bheap github.com/backtracking/bheap 129 | bibtex2html github.com/backtracking/bibtex2html 130 | bigarray-compat github.com/mirage/bigarray-compat 131 | bigarray-overlap github.com/dinosaure/overlap 132 | bignum github.com/janestreet/bignum 133 | bigstring github.com/c-cube/ocaml-bigstring 134 | bigstringaf github.com/inhabitedtype/bigstringaf 135 | bimage github.com/zshipko/ocaml-bimage 136 | binaryen github.com/grain-lang/binaryen.ml 137 | bindlib github.com/rlepigre/ocaml-bindlib 138 | biniou github.com/mjambon/biniou 139 | binning github.com/pveber/binning 140 | bin_prot github.com/janestreet/bin_prot 141 | biocaml github.com/biocaml/biocaml 142 | bisect_ppx github.com/aantron/bisect_ppx 143 | bisect_ppx-ocamlbuild github.com/aantron/bisect_ppx-ocamlbuild 144 | bisect-summary github.com/lindig/bisect-summary 145 | bistro github.com/pveber/bistro 146 | bitcoin github.com/darioteixeira/ocaml-bitcoin 147 | bitcoinml github.com/dakk/bitcoinml 148 | bitmasks github.com/metastack/bitmasks 149 | bitstring github.com/xguerin/bitstring 150 | bitv github.com/backtracking/bitv 151 | bjack github.com/savonet/ocaml-bjack 152 | blahcaml github.com/darioteixeira/blahcaml 153 | blake2 gitlab.com/nomadic-labs/ocaml-blake2 154 | blake3 github.com/proof-ninja/ocaml-blake3 155 | bloomf github.com/mirage/bloomf 156 | bls12-381 gitlab.com/dannywillems/ocaml-bls12-381 157 | bn128 github.com/runtimeverification/bn128-ml 158 | bnfgen github.com/dmbaturin/bnfgen 159 | bogue github.com/sanette/bogue 160 | bonsai github.com/janestreet/bonsai 161 | bookaml github.com/darioteixeira/bookaml 162 | boomerang github.com/SolomonAduolMaina/boomerang 163 | bpf github.com/ygrek/ocaml-bpf 164 | bracetax github.com/smondet/bracetax 165 | broken github.com/michipili/broken 166 | brotli github.com/fxfactorial/reasonml-brotli 167 | brozip github.com/fxfactorial/brozip 168 | brr erratique.ch/repos/brr 169 | bsbnative github.com/bucklescript/bucklescript 170 | bsdowl github.com/michipili/bsdowl 171 | bson2 github.com/nosman/Bson2 172 | bst github.com/UnixJunkie/bisec-tree 173 | buffer-pool github.com/cjen1/buffer-pool 174 | build_path_prefix_map gitlab.com/gasche/build_path_prefix_map 175 | bulletml github.com/emillon/bulletml 176 | bun github.com/yomimono/ocaml-bun 177 | bwrap github.com/Chris00/ocaml-bwrap 178 | bytearray github.com/UnixJunkie/bytearray 179 | bytepdf github.com/Drup/bytepdf 180 | c3 github.com/djs55/ocaml-c3 181 | ca-certs github.com/mirage/ca-certs 182 | ca-certs-nss github.com/mirage/ca-certs-nss 183 | cairo2 github.com/Chris00/ocaml-cairo 184 | calculon github.com/c-cube/calculon 185 | calendar github.com/ocaml-community/calendar 186 | calendars github.com/geneweb/calendars 187 | callipyge github.com/oklm-wsh/callipyge 188 | camelot github.com/upenn-cis1xx/camelot 189 | camels github.com/yomimono/camels 190 | camelsnakekebab github.com/swuecho/camelsnakekebab 191 | caml2html github.com/mjambon/caml2html 192 | camlbz2 gitlab.com/irill/camlbz2 193 | camlhighlight github.com/darioteixeira/camlhighlight 194 | camlidl github.com/xavierleroy/camlidl 195 | camlimages gitlab.com/camlspotter/camlimages 196 | caml-mode github.com/ocaml/ocaml 197 | camlon gitlab.com/camlspotter/camlon 198 | camlp4 github.com/camlp4/camlp4 199 | camlp5 github.com/camlp5/camlp5 200 | camltc github.com/toolslive/camltc 201 | camomile github.com/yoriyuki/Camomile 202 | camyll github.com/alan-j-hu/camyll 203 | capnp github.com/capnproto/capnp-ocaml 204 | capnp-rpc github.com/mirage/capnp-rpc 205 | captureio github.com/sylvarant/captureio 206 | caqti github.com/paurkedal/ocaml-caqti 207 | caradoc github.com/ANSSI-FR/caradoc 208 | carton github.com/mirage/ocaml-git 209 | catala github.com/CatalaLang/catala 210 | cbat-explicit-edge github.com/draperlaboratory/cbat_tools 211 | cca github.com/codinuum/cca 212 | cconv github.com/c-cube/cconv 213 | ccss github.com/darioteixeira/ccss 214 | cdrom github.com/xapi-project/cdrom 215 | certify github.com/yomimono/ocaml-certify 216 | cf github.com/mirage/ocaml-cf 217 | cfg github.com/mmottl/cfg 218 | cfgen github.com/dmbaturin/bnfgen 219 | cfstream github.com/biocaml/cfstream 220 | cgi github.com/rixed/ocaml-cgi 221 | cgroups github.com/Gbury/ocaml-cgroups 222 | chacha github.com/abeaumont/ocaml-chacha 223 | channel github.com/mirage/mirage-channel 224 | charrua github.com/mirage/charrua 225 | charrua-core github.com/mirage/charrua-core 226 | chartjs github.com/monstasat/chartjs-ocaml 227 | chase github.com/ramsdell/chase 228 | checkseum github.com/mirage/checkseum 229 | choice github.com/c-cube/choice 230 | cinaps github.com/ocaml-ppx/cinaps 231 | clangml gitlab.inria.fr/memcad/clangml 232 | clangml-transforms gitlab.inria.fr/memcad/clangml-transforms 233 | clap github.com/rbardou/clap 234 | clarity github.com/IndiscriminateCoding/clarity 235 | clarity-lang github.com/weavery/clarity.ml 236 | clim github.com/Ninjapouet/clim 237 | cloudi github.com/CloudI/cloudi_api_ocaml 238 | cmarker github.com/pablo-meier/ocaml-cmark 239 | cmdtui gitlab.com/edwintorok/cmdtui 240 | coclobas github.com/hammerlab/coclobas 241 | codept github.com/Octachron/codept 242 | cohttp github.com/mirage/ocaml-cohttp 243 | coin github.com/mirage/coin 244 | colombe github.com/mirage/colombe 245 | color github.com/anuragsoni/color 246 | color-brewery github.com/Chris00/color_brewery 247 | combinat github.com/jfeser/combinat 248 | combine github.com/backtracking/combine 249 | comby github.com/comby-tools/comby 250 | command_rpc github.com/janestreet/command_rpc 251 | commonjs_of_ocaml github.com/angrylawyer/commonjs_of_ocaml 252 | comparelib github.com/janestreet/comparelib 253 | conduit github.com/mirage/ocaml-conduit 254 | conex github.com/hannesm/conex 255 | conf-capnproto github.com/capnproto/capnproto 256 | conf-gobject-introspection gitlab.gnome.org/GNOME/gobject-introspection 257 | configuration github.com/michipili/configuration 258 | configurator github.com/janestreet/configurator 259 | conf-libpcre github.com/mmottl/pcre-ocaml 260 | conf-libudev github.com/systemd/systemd 261 | conf-netsnmp www.github.com/stevebleazard/ocaml-conf-netsnmp 262 | conf-numa www.github.com/stevebleazard/ocaml-conf-numa 263 | conformist github.com/oxidizing/conformist 264 | conf-postgresql github.com/mmottl/postgresql-ocaml 265 | conf-protoc github.com/protocolbuffers/protobuf 266 | conf-qt github.com/Kakadu/lablqml 267 | conf-secp256k1 github.com/dakk/conf-secp256k1 268 | conf-sqlite3 github.com/mmottl/sqlite3-ocaml 269 | containers github.com/c-cube/ocaml-containers 270 | cookie github.com/ulrikstrid/ocaml-cookie 271 | cookies github.com/lemaetech/cookies 272 | coq github.com/coq/coq 273 | coq-of-ocaml github.com/clarus/coq-of-ocaml 274 | coq-serapi github.com/ejgallego/coq-serapi 275 | cordova github.com/dannywillems/ocaml-cordova 276 | cordova-plugin-fcm github.com/dannywillems/ocaml-cordova-plugin-fcm 277 | cordova-plugin-file github.com/dannywillems/ocaml-cordova-plugin-file 278 | cordova-plugin-push-notifications github.com/dannywillems/ocaml-cordova-plugin-push 279 | cordova-plugin-sms github.com/dannywillems/ocaml-cordova-plugin-sms 280 | core github.com/janestreet/core 281 | core_bench github.com/janestreet/core_bench 282 | corecount github.com/fxfactorial/ocaml-corecount 283 | core_extended github.com/janestreet/core_extended 284 | core_kernel github.com/janestreet/core_kernel 285 | core_profiler github.com/janestreet/core_profiler 286 | cosovo github.com/barko/cosovo 287 | cow github.com/mirage/ocaml-cow 288 | cowabloga github.com/mirage/cowabloga 289 | cpm github.com/UnixJunkie/cpmlib 290 | cppo github.com/ocaml-community/cppo 291 | cpu github.com/UnixJunkie/cpu 292 | cpuid github.com/pqwy/cpuid 293 | craml github.com/realworldocaml/craml 294 | crc github.com/xapi-project/ocaml-crc 295 | crdt-ml github.com/ergl/crdt-ml 296 | crlibm github.com/Chris00/ocaml-crlibm 297 | crowbar github.com/stedolan/crowbar 298 | crunch github.com/mirage/ocaml-crunch 299 | cry github.com/savonet/ocaml-cry 300 | cryptohash github.com/fdopen/cryptohash 301 | csexp github.com/ocaml-dune/csexp 302 | css-parser github.com/astrada/ocaml-css-parser 303 | cstruct github.com/mirage/ocaml-cstruct 304 | csv github.com/Chris00/ocaml-csv 305 | csvfields github.com/janestreet/csvfields 306 | csvprovider github.com/nv-vn/OCamlCsvProvider 307 | ctypes-build github.com/yallop/ocaml-ctypes-build 308 | ctypes-zarith github.com/fdopen/ctypes-zarith 309 | cubicle github.com/cubicle-model-checker/cubicle 310 | cudf scm.gforge.inria.fr/anonscm/git/cudf/cudf 311 | cumulus github.com/paurkedal/ocaml-cumulus 312 | curly github.com/rgrinberg/curly 313 | current github.com/ocurrent/ocurrent 314 | current_ocluster github.com/ocurrent/ocluster 315 | curses github.com/mbacarella/curses 316 | curve-sampling github.com/Chris00/ocaml-curve-sampling 317 | custom_printf github.com/janestreet/custom_printf 318 | cviode github.com/mseri/ocaml-cviode 319 | cwe_checker github.com/fkie-cad/cwe_checker 320 | d3 github.com/seliopou/ocaml-d3 321 | daft github.com/UnixJunkie/daft 322 | data-encoding gitlab.com/nomadic-labs/data-encoding 323 | dataframe github.com/LaurentMazare/ocaml-dataframe 324 | datakit github.com/moby/datakit 325 | daypack-lib github.com/daypack-dev/daypack-lib 326 | dbf github.com/pveber/dbf 327 | dbm github.com/ocaml/dbm 328 | dead_code_analyzer github.com/LexiFi/dead_code_analyzer 329 | debian-formats github.com/gildor478/ocaml-debian-formats 330 | decimal github.com/yawaramin/ocaml-decimal 331 | decoders github.com/mattjbray/ocaml-decoders 332 | decompress github.com/mirage/decompress 333 | dedukti github.com/Deducteam/Dedukti 334 | delimited_parsing github.com/janestreet/delimited_parsing 335 | depyt github.com/samoht/depyt 336 | deriving github.com/ocsigen/deriving 337 | dht www.github.com/nojb/ocaml-dht 338 | diet github.com/mirage/ocaml-diet 339 | digestif github.com/mirage/digestif 340 | directories github.com/ocamlpro/directories 341 | dirsift github.com/darrenldl/dirsift 342 | disml gitlab.com/Mishio595/disml 343 | dispatch github.com/inhabitedtype/ocaml-dispatch 344 | distributed github.com/essdotteedot/distributed 345 | distwit github.com/let-def/distwit 346 | diy github.com/herd/herdtools7 347 | dkim github.com/dinosaure/ocaml-dkim 348 | dlm github.com/xapi-project/ocaml-dlm 349 | dns github.com/mirage/ocaml-dns 350 | dns-forward github.com/mirage/ocaml-dns-forward 351 | dnssd github.com/mirage/ocaml-osx-dnssd 352 | docker-api github.com/Chris00/ocaml-docker 353 | dockerfile github.com/avsm/ocaml-dockerfile 354 | docteur github.com/dinosaure/docteur 355 | dog github.com/samoht/dog 356 | doi2bib github.com/mseri/doi2bib 357 | dokeysto github.com/UnixJunkie/dokeysto 358 | dolmen github.com/Gbury/dolmen 359 | dolog github.com/UnixJunkie/dolog 360 | domain-name github.com/hannesm/domain-name 361 | dotenv github.com/thatportugueseguy/ocaml-dotenv 362 | merlin github.com/ocaml/merlin 363 | down erratique.ch/repos/down 364 | DrawGrammar github.com/jacquev6/DrawGrammar 365 | dream github.com/aantron/dream 366 | drom github.com/ocamlpro/drom 367 | dropbox github.com/Chris00/ocaml-dropbox 368 | dryunit github.com/gersonmoraes/dryunit 369 | dsfo github.com/rleonid/dsfo 370 | dssi github.com/savonet/ocaml-dssi 371 | dtoa github.com/flowtype/ocaml-dtoa 372 | dtools github.com/savonet/ocaml-dtools 373 | dual github.com/drjdn/ocaml_dual 374 | duff github.com/mirage/duff 375 | dum github.com/mjambon/dum 376 | dumpast github.com/samoht/ocaml-dumpast 377 | dune github.com/ocaml/dune 378 | dune-deps github.com/mjambon/dune-deps 379 | dune-release github.com/ocamllabs/dune-release 380 | dune_watch gitlab.com/camlspotter/dune_watch 381 | duppy github.com/savonet/ocaml-duppy 382 | duration github.com/hannesm/duration 383 | earley github.com/rlepigre/ocaml-earley 384 | earley-ocaml github.com/rlepigre/ocaml-earley-ocaml 385 | earlybird github.com/hackwaly/ocamlearlybird 386 | easy-format github.com/mjambon/easy-format 387 | easy_logging github.com/sapristi/easy_logging 388 | easy_xlsx github.com/brendanlong/ocaml-ooxml 389 | ecaml github.com/janestreet/ecaml 390 | edn github.com/prepor/ocaml-edn 391 | eigen github.com/owlbarn/eigen 392 | either github.com/mirage/either 393 | elasticsearch-cli github.com/cyborgize/es-cli 394 | electrod github.com/grayswandyr/electrod 395 | electrumAnalyzer github.com/grayswandyr/electrumAnalyzer 396 | elina github.com/eth-srl/ELINA 397 | eliom github.com/ocsigen/eliom 398 | elpi github.com/LPCIC/elpi 399 | email_message github.com/janestreet/email_message 400 | embedded_ocaml_templates github.com/EmileTrotignon/embedded_ocaml_templates 401 | emile github.com/dinosaure/emile 402 | emoji github.com/fxfactorial/ocaml-emoji 403 | encore github.com/mirage/encore 404 | enumerate github.com/janestreet/enumerate 405 | enumerators github.com/cryptosense/enumerators 406 | eqaf github.com/mirage/eqaf 407 | erlang github.com/AbstractMachinesLab/caramel 408 | esgg github.com/ahrefs/esgg 409 | ethernet github.com/mirage/ethernet 410 | expect github.com/gildor478/ocaml-expect 411 | expect_test_helpers github.com/janestreet/expect_test_helpers 412 | expect_test_helpers_async github.com/janestreet/expect_test_helpers_async 413 | expect_test_helpers_core github.com/janestreet/expect_test_helpers_core 414 | expect_test_helpers_kernel github.com/janestreet/expect_test_helpers_kernel 415 | extunix github.com/ygrek/extunix 416 | ez_api github.com/ocamlpro/ez_api 417 | ez_cmdliner github.com/ocamlpro/ez_cmdliner 418 | ez_config github.com/ocamlpro/ez_config 419 | ez_file github.com/ocamlpro/ez_file 420 | ezgzip github.com/hcarty/ezgzip 421 | ez_hash github.com/OcamlPro/ocaml-solidity 422 | ezirmin github.com/kayceesrk/ezirmin 423 | ezjs_ace github.com/ocamlpro/ezjs_ace 424 | ezjs_blockies github.com/ocamlpro/ezjs_blockies 425 | ezjs_cleave github.com/ocamlpro/ezjs_cleave 426 | ezjs_crypto github.com/ocamlpro/ezjs_crypto 427 | ezjs_cytoscape github.com/ocamlpro/ezjs_cytoscape 428 | ezjs_d3pie github.com/ocamlpro/ezjs_d3pie 429 | ezjs_extension github.com/ocamlpro/ezjs_extension 430 | ezjs_fetch github.com/ocamlpro/ezjs_fetch 431 | ezjs_idb github.com/ocamlpro/ezjs_idb 432 | ezjs_jquery github.com/ocamlpro/ezjs_jquery 433 | ezjs_min github.com/ocamlpro/ezjs_min 434 | ezjs_odometer github.com/ocamlpro/ezjs_odometer 435 | ezjsonm github.com/mirage/ezjsonm 436 | ezjs_push github.com/ocamlpro/ezjs_push 437 | ezjs_qrcode github.com/ocamlpro/ezjs_qrcode 438 | ezjs_recaptcha github.com/ocamlpro/ezjs_recaptcha 439 | ezjs_timeline github.com/ocamlpro/ezjs_timeline 440 | ez_opam_file github.com/ocamlpro/ez_opam_file 441 | ez_pgocaml github.com/ocamlpro/ez_pgocaml 442 | ezresto gitlab.com/nomadic-labs/resto 443 | ezsqlite github.com/zshipko/ocaml-ezsqlite 444 | ez_subst github.com/ocamlpro/ez_subst 445 | ezxenstore github.com/xapi-project/ezxenstore 446 | ezxmlm github.com/mirage/ezxmlm 447 | faad github.com/savonet/ocaml-faad 448 | facebook-sdk github.com/CREATe-centre/sociaml-facebook-api 449 | facteur github.com/dinosaure/facteur 450 | fadbadml github.com/fadbadml-dev/FADBADml 451 | faraday github.com/inhabitedtype/faraday 452 | farfadet github.com/oklm-wsh/Farfadet 453 | fat-filesystem github.com/mirage/ocaml-fat 454 | fdkaac github.com/savonet/ocaml-fdkaac 455 | fd-send-recv github.com/xapi-project/ocaml-fd-send-recv 456 | feat gitlab.inria.fr/fpottier/feat 457 | febusy gitlab.com/smondet/febusy 458 | ff gitlab.com/dannywillems/ocaml-ff 459 | ffmpeg github.com/savonet/ocaml-ffmpeg 460 | fftw3 github.com/Chris00/fftw-ocaml 461 | fiat-p256 github.com/mirage/fiat 462 | fieldslib github.com/janestreet/fieldslib 463 | fileutils github.com/gildor478/ocaml-fileutils 464 | finch github.com/roddyyaga/finch 465 | findlib_top github.com/janestreet/findlib_top 466 | fix gitlab.inria.fr/fpottier/fix 467 | flac github.com/savonet/ocaml-flac 468 | flex-array github.com/backtracking/flex-array 469 | flock github.com/simonjbeaumont/ocaml-flock 470 | flow github.com/facebook/flow 471 | fluent-logger github.com/komamitsu/fluent-logger-ocaml 472 | fmlib github.com/hbr/fmlib 473 | fmt erratique.ch/repos/fmt 474 | fpath erratique.ch/repos/fpath 475 | frama-c-base github.com/Frama-C/Frama-C-snapshot 476 | frama-c-metacsl git.frama-c.com/pub/meta 477 | freetds github.com/kennknowles/ocaml-freetds 478 | frei0r github.com/savonet/ocaml-frei0r 479 | frenetic github.com/frenetic-lang/frenetic 480 | FrontC github.com/BinaryAnalysisPlatform/FrontC 481 | fsevents github.com/mirage/ocaml-fsevents 482 | fsml github.com/jserot/fsml 483 | fstreams github.com/tel/ocaml-fstreams 484 | functoria github.com/mirage/functoria 485 | funfields github.com/fccm/ocaml-funfields 486 | future github.com/solvuu/future 487 | gamepad github.com/emillon/gamepad_of_ocaml 488 | gammu github.com/Chris00/ocaml-gammu 489 | gapi-ocaml github.com/astrada/gapi-ocaml 490 | gappa gitlab.inria.fr/gappa/gappa 491 | gasoline github.com/michipili/gasoline 492 | gavl github.com/savonet/ocaml-gavl 493 | gd github.com/savonet/gd4o 494 | gdal github.com/hcarty/ocaml-gdal 495 | gdbprofiler github.com/copy/gdbprofiler 496 | gemini github.com/struktured/ocaml-gemini 497 | gen github.com/c-cube/gen 498 | gen-bs github.com/0zat/gen-bs 499 | General github.com/jacquev6/General 500 | gen_js_api github.com/LexiFi/gen_js_api 501 | genprint github.com/progman1/genprintlib 502 | genspio github.com/hammerlab/genspio 503 | genspir github.com/UnixJunkie/genspir 504 | gensqlite github.com/j0sh/ocaml-gensqlite 505 | getopts github.com/michipili/getopts 506 | gettext github.com/gildor478/ocaml-gettext 507 | github github.com/mirage/ocaml-github 508 | github-hooks github.com/dsheets/ocaml-github-hooks 509 | glfw-ocaml github.com/SylvainBoilard/GLFW-OCaml 510 | glical github.com/pw374/glical 511 | glMLite github.com/fccm/glMLite 512 | glpk github.com/smimram/ocaml-glpk 513 | gluten github.com/anmonteiro/gluten 514 | gmap github.com/hannesm/gmap 515 | gmp github.com/mirage/ocaml-gmp 516 | gnuplot github.com/c-cube/ocaml-gnuplot 517 | gobba github.com/0x0f0f0f/gobba 518 | gobject-introspection github.com/cedlemo/OCaml-GObject-Introspection 519 | goblint github.com/goblint/analyzer 520 | goblint-cil github.com/goblint/cil/ 521 | google-drive-ocamlfuse github.com/astrada/google-drive-ocamlfuse 522 | gopcaml-mode gitlab.com/gopiandcode/gopcaml-mode 523 | gpr github.com/mmottl/gpr 524 | gpx github.com/rundat/ocaml-gpx 525 | gr github.com/mseri/ocaml-gr 526 | grain_wasm_spec github.com/grain-lang/wasm-spec 527 | graphics github.com/ocaml/graphics 528 | graphql github.com/andreas/ocaml-graphql-server 529 | graphql_ppx github.com/reasonml-community/graphql-ppx 530 | gremlin github.com/bramford/ocaml-gremlin 531 | grenier github.com/let-def/grenier 532 | gsl github.com/mmottl/gsl-ocaml 533 | gstreamer github.com/savonet/ocaml-gstreamer 534 | GT github.com/JetBrains-Research/GT 535 | GuaCaml gitlab.com/boreal-ldd/guacaml 536 | gufo github.com/Piervit/gufo 537 | h2 github.com/anmonteiro/ocaml-h2 538 | hack_parallel github.com/rvantonder/hack_parallel 539 | hacl gitlab.com/nomadic-labs/ocaml-hacl 540 | hacl-star github.com/project-everest/hacl-star 541 | hacl_x25519 github.com/mirage/hacl 542 | hamt github.com/rgrinberg/ocaml-hamt 543 | hardcaml github.com/janestreet/hardcaml 544 | hardcaml-affirm github.com/ujamjar/hardcaml-affirm 545 | hardcaml-bloop github.com/ujamjar/hardcaml-bloop 546 | hardcaml-examples github.com/ujamjar/hardcaml-examples 547 | hardcaml-framework github.com/ujamjar/hardcaml-framework 548 | hardcaml-llvmsim github.com/ujamjar/hardcaml-llvmsim 549 | hardcaml-reedsolomon github.com/ujamjar/hardcaml-reedsolomon 550 | hardcaml-vpi github.com/ujamjar/hardcaml-vpi 551 | hardcaml-waveterm github.com/ujamjar/hardcaml-waveterm 552 | hardcaml_waveterm github.com/janestreet/hardcaml_waveterm 553 | hardcaml-yosys github.com/ujamjar/hardcaml-yosys 554 | hashcons github.com/backtracking/ocaml-hashcons 555 | hashids github.com/jacquev6/hashids-ocaml 556 | hashset github.com/UnixJunkie/hashset 557 | haxe github.com/HaxeFoundation/haxe 558 | headache github.com/Frama-C/headache 559 | herelib github.com/janestreet/herelib 560 | hevea github.com/maranget/hevea 561 | hex github.com/mirage/ocaml-hex 562 | hidapi github.com/vbmithr/ocaml-hidapi 563 | higher github.com/ocamllabs/higher 564 | higher_kinded github.com/janestreet/higher_kinded 565 | higlo github.com/zoggy/higlo 566 | hiredis github.com/zshipko/ocaml-hiredis 567 | hkdf github.com/hannesm/ocaml-hkdf 568 | hlarp github.com/hammerlab/hlarp 569 | horned_worm github.com/kkazuo/horned_worm 570 | hts_shrink github.com/UnixJunkie/hts_shrink 571 | http2https github.com/avsm/http2https 572 | httpaf github.com/inhabitedtype/httpaf 573 | httpaf_caged github.com/thedufer/httpaf_caged 574 | http-cookie github.com/lemaetech/http-cookie 575 | http-multipart-formdata github.com/lemaetech/http-mutlipart-formdata 576 | huffman github.com/jdrprod/huffman 577 | humane-re github.com/rgrinberg/humane-re 578 | hvsock github.com/mirage/ocaml-hvsock 579 | hxd github.com/dinosaure/hxd 580 | i3ipc github.com/Armael/ocaml-i3ipc 581 | ibx bitbucket.org/ogu/ibx 582 | icalendar github.com/roburio/icalendar 583 | idd github.com/netkat-lang/idd 584 | idds github.com/netkat-lang/idds 585 | igvxml github.com/hammerlab/igvxml 586 | imagelib github.com/rlepigre/ocaml-imagelib 587 | imap www.github.com/nojb/ocaml-imap 588 | incr_dom github.com/janestreet/incr_dom 589 | incr_dom_interactive github.com/janestreet/incr_dom_interactive 590 | incr_dom_keyboard github.com/janestreet/incr_dom_keyboard 591 | incr_dom_partial_render github.com/janestreet/incr_dom_partial_render 592 | incr_dom_sexp_form github.com/janestreet/incr_dom_sexp_form 593 | incr_dom_widgets github.com/janestreet/incr_dom_widgets 594 | incremental github.com/janestreet/incremental 595 | incremental_kernel github.com/janestreet/incremental_kernel 596 | incr_map github.com/janestreet/incr_map 597 | incr_select github.com/janestreet/incr_select 598 | index github.com/mirage/index 599 | inferno gitlab.inria.fr/fpottier/inferno 600 | integers github.com/ocamllabs/ocaml-integers 601 | integers_stubs_js github.com/o1-labs/integers_stubs_js 602 | integration1d github.com/Chris00/integration1d 603 | interval github.com/Chris00/ocaml-interval 604 | interval-map github.com/dgllghr/interval-map 605 | inuit github.com/let-def/inuit 606 | io github.com/rizo/flow 607 | iocaml github.com/andrewray/iocamlserver 608 | iocamljs-kernel github.com/andrewray/iocamljs 609 | iocaml-kernel github.com/andrewray/iocaml 610 | io-page github.com/mirage/io-page 611 | ipaddr github.com/mirage/ocaml-ipaddr 612 | ipv6-multicast github.com/vbmithr/ocaml-ipv6-multicast 613 | iri github.com/zoggy/ocaml-iri 614 | irmin github.com/mirage/irmin 615 | irmin-indexeddb github.com/talex5/irmin-indexeddb 616 | irmin-watcher github.com/mirage/irmin-watcher 617 | irrlicht github.com/fccm/OCaml-Irrlicht 618 | iso639 github.com/paurkedal/ocaml-iso639 619 | ISO8601 github.com/ocaml-community/ISO8601.ml 620 | iter github.com/c-cube/iter 621 | jane-street-headers github.com/janestreet/jane-street-headers 622 | jane-street-tests github.com/janestreet/jane-street-tests 623 | javalib github.com/javalib-team/javalib 624 | javascriptcore github.com/fxfactorial/ocaml-javascriptcore 625 | jekyll-format github.com/avsm/jekyll-format 626 | jenga github.com/janestreet/jenga 627 | jerboa github.com/StrykerKKD/Jerboa 628 | jhupllib github.com/JHU-PL-Lab/jhu-pl-lib 629 | jingoo github.com/tategakibunko/jingoo 630 | jitsu github.com/mirage/jitsu 631 | jose github.com/ulrikstrid/reason-jose 632 | js-build-tools github.com/janestreet/js-build-tools 633 | JsOfOCairo github.com/jacquev6/JsOfOCairo 634 | js_of_ocaml github.com/ocsigen/js_of_ocaml 635 | js_of_ocaml-webgpu github.com/tari3x/webgpu 636 | json-data-encoding gitlab.com/nomadic-labs/json-data-encoding 637 | json_decoder github.com/dagoof/ocaml-json-decoder 638 | json-derivers github.com/rgrinberg/json-derivers 639 | json_of_jsonm www.github.com/stevebleazard/ocaml-json-of-jsonm 640 | jsonoo github.com/mnxn/jsonoo 641 | jsonrpc github.com/ocaml/ocaml-lsp 642 | jsoo_router github.com/xvw/jsoo_router 643 | jsoo_storage github.com/xvw/jsoo_storage 644 | jst-config github.com/janestreet/jst-config 645 | junit github.com/Khady/ocaml-junit 646 | jupyter github.com/akabe/ocaml-jupyter 647 | jupyter-kernel github.com/ocaml-jupyter/jupyter-kernel 648 | jwt github.com/besport/ocaml-jwt 649 | jwto github.com/sporto/jwto 650 | kafka github.com/didier-wenzek/ocaml-kafka 651 | kappa-agents github.com/Kappa-Dev/KappaTools 652 | KaSim github.com/Kappa-Dev/KaSim 653 | ke github.com/mirage/ke 654 | ketrew github.com/hammerlab/ketrew 655 | key-parsers github.com/cryptosense/key-parsers 656 | kicadsch github.com/jnavila/plotkicadsch 657 | kind2 github.com/kind2-mc/kind2 658 | kinetic-client github.com/openvstorage/kinetic-ocaml-client 659 | kqueue github.com/anuragsoni/kqueue-ml 660 | kubecaml github.com/andrenth/kubecaml 661 | kyotocabinet github.com/didier-wenzek/ocaml-kyotocabinet 662 | lablgl github.com/garrigue/lablgl 663 | lablgtk github.com/garrigue/lablgtk 664 | lablgtk-extras github.com/zoggy/lablgtk-extras 665 | lablgtkosx github.com/pirbo/lablGtkOSXApplication 666 | lablqt github.com/Kakadu/lablqt 667 | labltk github.com/garrigue/labltk 668 | labrys github.com/kit-ty-kate/labrys 669 | lacaml github.com/mmottl/lacaml 670 | ladspa github.com/savonet/ocaml-ladspa 671 | lambda github.com/dakk/lambda 672 | lambda-runtime github.com/anmonteiro/aws-lambda-ocaml-runtime 673 | lambdasoup github.com/aantron/lambdasoup 674 | lambda_streams github.com/Risto-Stevcev/lambda-streams 675 | lambdoc github.com/darioteixeira/lambdoc 676 | lame github.com/savonet/ocaml-lame 677 | landmarks github.com/LexiFi/landmarks 678 | lascar github.com/jserot/lascar 679 | lastfm github.com/savonet/ocaml-lastfm 680 | launchd github.com/mirage/ocaml-launchd 681 | lazy-trie github.com/mirage/ocaml-lazy-trie 682 | lbfgs github.com/Chris00/L-BFGS-ocaml 683 | lbvs_consent github.com/UnixJunkie/consent 684 | ldap github.com/kit-ty-kate/ocamldap 685 | learn-ocaml github.com/ocaml-sf/learn-ocaml 686 | ledgerwallet github.com/vbmithr/ocaml-ledger-wallet 687 | ledit github.com/chetmurthy/ledit 688 | lem github.com/rems-project/lem 689 | lemonade github.com/michipili/lemonade 690 | lemonade-sqlite github.com/michipili/lemonade-sqlite 691 | lens github.com/pdonadeo/ocaml-lens 692 | let-if github.com/reynir/let-if 693 | letsencrypt github.com/mmaker/ocaml-letsencrypt 694 | letters github.com/oxidizing/letters 695 | leveldb github.com/mfp/ocaml-leveldb 696 | levenshtein gitlab.com/camlspotter/ocaml_levenshtein 697 | libdash /github.com/mgree/libdash 698 | libssh github.com/fxfactorial/ocaml-libssh 699 | libsvm github.com/pveber/libsvm-ocaml 700 | libudev github.com/Armael/ocaml-libudev 701 | libzipperposition github.com/sneeuwballen/zipperposition 702 | lilac github.com/shnewto/lilac 703 | lilis github.com/Drup/LILiS 704 | linenoise github.com/ocaml-community/ocaml-linenoise 705 | line-up-words github.com/janestreet/line-up-words 706 | linkage github.com/stedolan/linkage 707 | links github.com/links-lang/links 708 | linksem github.com/rems-project/linksem 709 | linol github.com/c-cube/linol 710 | linwrap github.com/UnixJunkie/linwrap 711 | lipsum github.com/lindig/lipsum 712 | liquidsoap github.com/savonet/liquidsoap 713 | liquidsoap-daemon github.com/savonet/liquidsoap-daemon 714 | litiom github.com/darioteixeira/litiom 715 | llvmgraph github.com/Drup/llvmgraph 716 | lmdb github.com/Drup/ocaml-lmdb 717 | lo github.com/savonet/ocaml-lo 718 | loga github.com/yutopp/loga 719 | logger-p5 github.com/dboulytchev/logger 720 | logical github.com/StrykerKKD/Logical 721 | logs erratique.ch/repos/logs 722 | logs-async github.com/vbmithr/logs-async 723 | logs-ppx github.com/ulrikstrid/logs-ppx 724 | logs-syslog github.com/hannesm/logs-syslog 725 | lp github.com/ktahar/ocaml-lp 726 | lpi github.com/baxtersa/lambda-pi 727 | lru github.com/pqwy/lru 728 | lru-cache github.com/zoggy/ocaml-lru-cache 729 | lua-ml github.com/lindig/lua-ml 730 | lua_parser github.com/drjdn/ocaml_lua_parser 731 | lutils gricad-gitlab.univ-grenoble-alpes.fr/verimag/synchrone/lutils 732 | luv github.com/aantron/luv 733 | lwd github.com/let-def/lwd 734 | lwt github.com/ocsigen/lwt 735 | lwt_camlp4 github.com/aantron/lwt_camlp4 736 | lwt-canceler gitlab.com/nomadic-labs/lwt-canceler 737 | lwt-dllist github.com/mirage/lwt-dllist 738 | lwt-exit gitlab.com/nomadic-labs/lwt-exit 739 | lwt_glib github.com/ocsigen/lwt_glib 740 | lwt_log github.com/ocsigen/lwt_log 741 | lwt_named_threads github.com/ahrefs/lwt_named_threads 742 | lwt-parallel github.com/ivg/parallel 743 | lwt-pipe github.com/c-cube/lwt-pipe 744 | lwt-pipeline gitlab.com/nomadic-labs/lwt_pipeline 745 | lwt_ssl github.com/ocsigen/lwt_ssl 746 | lwt-watcher gitlab.com/nomadic-labs/lwt-watcher 747 | lwt-zmq github.com/hcarty/lwt-zmq 748 | lymp github.com/dbousque/lymp 749 | lz4_chans github.com/UnixJunkie/lz4-chans 750 | macaque github.com/ocsigen/macaque 751 | macaroons www.github.com/nojb/ocaml-macaroons 752 | mad github.com/savonet/ocaml-mad 753 | magic-mime github.com/mirage/ocaml-magic-mime 754 | maki github.com/c-cube/maki 755 | malfunction github.com/stedolan/malfunction 756 | mariadb github.com/andrenth/ocaml-mariadb 757 | markdown github.com/gildor478/ocaml-markdown 758 | markup github.com/aantron/markup.ml 759 | matplotlib github.com/LaurentMazare/ocaml-matplotlib 760 | mc2 github.com/c-cube/mc2 761 | mccs github.com/AltGr/ocaml-mccs 762 | md2mld github.com/mseri/md2mld 763 | mdx github.com/realworldocaml/mdx 764 | mecab github.com/akabe/ocaml-mecab 765 | mechaml github.com/yannham/mechaml 766 | memcad github.com/Antique-team/memcad 767 | memprof-limits gitlab.com/gadmm/memprof-limits 768 | memtrace github.com/janestreet/memtrace 769 | memtrace_viewer github.com/janestreet/memtrace_viewer 770 | menhir gitlab.inria.fr/fpottier/menhir 771 | mergeable-vector github.com/kayceesrk/mergeable-vector 772 | merge-fmt github.com/hhugo/merge-fmt 773 | merge-queues github.com/mirage/merge-queues 774 | merge-ropes github.com/mirage/merge-ropes 775 | merlin-extend github.com/let-def/merlin-extend 776 | mesh github.com/Chris00/mesh 777 | metapp github.com/thierry-martinez/metapp 778 | metaquot github.com/thierry-martinez/metaquot 779 | metrics github.com/mirage/metrics 780 | mew github.com/kandu/mew 781 | mew_vi github.com/kandu/mew_vi 782 | milter github.com/andrenth/ocaml-milter 783 | mimic github.com/dinosaure/mimic 784 | mindstorm github.com/Chris00/ocaml-mindstorm 785 | minicaml github.com/0x0f0f0f/minicaml 786 | minicli github.com/UnixJunkie/minicli 787 | minima-theme github.com/avsm/ocaml-minima-theme 788 | minios-xen github.com/talex5/mini-os 789 | minisat github.com/c-cube/ocaml-minisat 790 | minivpt github.com/UnixJunkie/vp-tree 791 | mirage github.com/mirage/mirage 792 | mirage-block github.com/mirage/mirage-block 793 | mirage-block-ccm github.com/sg2342/mirage-block-ccm 794 | mirage-block-ramdisk github.com/mirage/mirage-block-ramdisk 795 | mirage-block-solo5 github.com/mirage/mirage-block-solo5 796 | mirage-block-unix github.com/mirage/mirage-block-unix 797 | mirage-block-xen github.com/mirage/mirage-block-xen 798 | mirage-bootvar-solo5 github.com/mirage/mirage-bootvar-solo5 799 | mirage-bootvar-unix github.com/mirage/mirage-bootvar-unix 800 | mirage-bootvar-xen github.com/mirage/mirage-bootvar-xen 801 | mirage-btrees github.com/ruhatch/mirage-btrees 802 | mirage-clock github.com/mirage/mirage-clock 803 | mirage-console github.com/mirage/mirage-console 804 | mirage-console-solo5 github.com/mirage/mirage-console-solo5 805 | mirage-crypto github.com/mirage/mirage-crypto 806 | mirage-device github.com/mirage/mirage-device 807 | mirage-entropy github.com/mirage/mirage-entropy 808 | mirage-flow github.com/mirage/mirage-flow 809 | mirage-flow-rawlink github.com/mirage/mirage-flow-rawlink 810 | mirage-fs github.com/mirage/mirage-fs 811 | mirage-fs-mem github.com/roburio/mirage-fs-mem 812 | mirage-fs-unix github.com/mirage/mirage-fs-unix 813 | mirage-kv github.com/mirage/mirage-kv 814 | mirage-kv-mem github.com/mirage/mirage-kv-mem 815 | mirage-kv-unix github.com/mirage/mirage-kv-unix 816 | mirage-logs github.com/mirage/mirage-logs 817 | mirage-nat github.com/mirage/mirage-nat 818 | mirage-net github.com/mirage/mirage-net 819 | mirage-net-fd github.com/mirage/mirage-net-fd 820 | mirage-net-flow github.com/mirage/mirage-net-flow 821 | mirage-net-macosx github.com/mirage/mirage-net-macosx 822 | mirage-net-solo5 github.com/mirage/mirage-net-solo5 823 | mirage-net-unix github.com/mirage/mirage-net-unix 824 | mirage-net-xen github.com/mirage/mirage-net-xen 825 | mirage-os-shim github.com/mirage/mirage-os-shim 826 | mirage-profile github.com/mirage/mirage-profile 827 | mirage-protocols github.com/mirage/mirage-protocols 828 | mirage-qubes github.com/mirage/mirage-qubes 829 | mirage-random github.com/mirage/mirage-random 830 | mirage-random-stdlib github.com/mirage/mirage-random-stdlib 831 | mirage-random-test github.com/mirage/mirage-random-test 832 | mirage-seal github.com/mirage/mirage-seal 833 | mirage-stack github.com/mirage/mirage-stack 834 | mirage-tc github.com/mirage/mirage-tc 835 | mirage-time github.com/mirage/mirage-time 836 | mirage-unix github.com/mirage/mirage-unix 837 | mirage-vnetif github.com/mirage/mirage-vnetif 838 | mirage-xen github.com/mirage/mirage-xen 839 | mirage-xen-minios github.com/mirage/mirage-xen-minios 840 | mirage-xen-ocaml github.com/mirage/mirage-platform 841 | mirror github.com/avsm/opam-mirror 842 | misuja gitlab.com/smondet/misuja 843 | mixture github.com/michipili/mixture 844 | ml2mxml github.com/yetanotherion/ml2mxml 845 | mlbdd github.com/arlencox/mlbdd 846 | mld github.com/disteph/mld 847 | mldonkey github.com/ygrek/mldonkey 848 | mlfenv github.com/thvnx/mlfenv 849 | mlgmpidl github.com/nberth/mlgmpidl 850 | mlmpfr github.com/thvnx/mlmpfr 851 | lpost github.com/backtracking/mlpost 852 | mlt_parser github.com/janestreet/mlt_parser 853 | mm github.com/savonet/ocaml-mm 854 | mmap github.com/mirage/mmap 855 | mmdb github.com/issuu/ocaml-mmdb 856 | mock github.com/cryptosense/ocaml-mock 857 | modelica_ml github.com/choeger/modelica.ml 858 | modular-arithmetic github.com/sonologico/modular-arithmetic 859 | molenc github.com/UnixJunkie/molenc 860 | monadlib github.com/Chattered/ocaml-monad 861 | monolith gitlab.inria.fr/fpottier/monolith 862 | monomorphic github.com/kit-ty-kate/ocaml-monomorphic 863 | moss github.com/Chris00/ocaml-moss 864 | mparser github.com/murmour/mparser 865 | mpp github.com/ocaml/MPP-language-blender 866 | mrmime github.com/mirage/mrmime 867 | mrt-format github.com/mor1/mrt-format 868 | msat github.com/Gbury/mSAT 869 | msgpack github.com/msgpack/msgpack-ocaml 870 | msgpck github.com/vbmithr/ocaml-msgpck 871 | mssql github.com/arenadotio/ocaml-mssql 872 | mstruct github.com/mirage/ocaml-mstruct 873 | mtime erratique.ch/repos/mtime 874 | multipart_form github.com/dinosaure/multipart_form 875 | multipart-form-data github.com/cryptosense/multipart-form-data 876 | mustache github.com/rgrinberg/ocaml-mustache 877 | mutf8 github.com/wiml/ocaml-mutf8 878 | mwt github.com/hcarty/mwt 879 | mysql_protocol github.com/slegrand45/mysql_protocol 880 | naboris github.com/shawn-mcginty/naboris 881 | nacc github.com/codeanonorg/nacc 882 | named-pipe github.com/mirage/ocaml-named-pipe 883 | namespaces github.com/aantron/namespaces 884 | nbd github.com/xapi-project/nbd 885 | netkat github.com/netkat-lang/netkat 886 | netlink github.com/xapi-project/ocaml-netlink 887 | netml github.com/xguerin/netml 888 | netsnmp github.com/janestreet/netsnmp 889 | nice_parser github.com/smolkaj/ocaml-parsing 890 | nlp github.com/dave-tucker/ocaml-nlp 891 | nmea github.com/dakk/nmea 892 | noCanren github.com/Lozov-Petr/noCanren 893 | nocoiner github.com/marcoonroad/nocoiner 894 | nocrypto github.com/mirleft/ocaml-nocrypto 895 | noise github.com/emillon/ocaml-noise 896 | nosetup github.com/Leonidas-from-XIV/nosetup 897 | note erratique.ch/repos/note 898 | not-ocamlfind github.com/chetmurthy/not-ocamlfind 899 | notty github.com/pqwy/notty 900 | notty_async github.com/janestreet/notty_async 901 | np github.com/lehy/ocaml-sklearn 902 | nproc github.com/rizo/nproc 903 | npy github.com/LaurentMazare/npy-ocaml 904 | nsq github.com/ryanslade/nsq-ocaml 905 | num github.com/ocaml/num 906 | numalib www.github.com/stevebleazard/ocaml-numa 907 | nunchaku github.com/nunchaku-inria/nunchaku 908 | nuscr github.com/nuscr/nuscr 909 | oasis2opam github.com/ocaml/oasis2opam 910 | obandit github.com/freuk/obandit 911 | obeam github.com/yutopp/obeam 912 | obelisk github.com/Lelio-Brun/obelisk 913 | obi github.com/ocaml/obi 914 | objsize github.com/ygrek/objsize 915 | obuild github.com/ocaml-obuild/obuild 916 | obuilder github.com/ocurrent/obuilder 917 | obus github.com/ocaml-community/obus 918 | oc45 github.com/tobast/OC4.5 919 | ocal github.com/mor1/ocal 920 | ocaml github.com/ocaml/ocaml 921 | ocamlapi github.com/nosman/Ocamlapi 922 | ocaml_at_p github.com/tsubame-sp/ocaml_at_p 923 | ocaml-basics github.com/advanced-schema/ocaml-basics 924 | ocamlbuild-atdgen github.com/rgrinberg/ocamlbuild-atdgen 925 | ocamlbuild-pkg github.com/kit-ty-kate/ocamlbuild-pkg 926 | ocamlbuild-protoc github.com/Khady/ocamlbuild-protoc 927 | ocamlcodoc gitlab.inria.fr/tmartine/ocamlcodoc 928 | ocaml-compiler-libs github.com/janestreet/ocaml-compiler-libs 929 | ocamldot github.com/zoggy/ocamldot 930 | ocaml-expat github.com/whitequark/ocaml-expat 931 | ocamlfind github.com/ocaml/ocamlfind 932 | ocamlformat github.com/ocaml-ppx/ocamlformat 933 | ocamlformat_support github.com/ocaml-ppx/ocamlformat 934 | ocaml-freestanding github.com/mirage/ocaml-freestanding 935 | ocaml-gist github.com/SanderSpies/ocaml-gist 936 | ocamlgraph github.com/backtracking/ocamlgraph 937 | ocaml-http github.com/sacerdot/ocaml-http 938 | ocaml-js-stdlib github.com/dannywillems/ocaml-js-stdlib 939 | ocamllint github.com/cryptosense/ocamllint 940 | ocaml-lua github.com/pdonadeo/ocaml-lua 941 | ocaml-makefile github.com/mmottl/ocaml-makefile 942 | ocaml-migrate-parsetree github.com/ocaml-ppx/ocaml-migrate-parsetree 943 | ocaml-migrate-parsetree-ocamlbuild github.com/let-def/ocaml-migrate-parsetree 944 | ocaml-monadic github.com/zepalmer/ocaml-monadic 945 | ocamlnet gitlab.com/gerdstolpmann/lib-ocamlnet3 946 | ocaml_plugin github.com/janestreet/ocaml_plugin 947 | ocaml-print-intf github.com/avsm/ocaml-print-intf 948 | ocaml-protoc github.com/mransan/ocaml-protoc 949 | ocaml-protoc-plugin github.com/issuu/ocaml-protoc-plugin 950 | ocaml-protoc-yojson github.com/mransan/ocaml-protoc-yojson 951 | ocaml-r github.com/pveber/ocaml-r 952 | ocamlsdl2 github.com/fccm/OCamlSDL2 953 | ocamlsdl2-image github.com/fccm/OCamlSDL2_Image 954 | ocamlsdl2-ttf github.com/fccm/OCamlSDL2_TTF 955 | ocamlspot gitlab.com/camlspotter/ocamlspot 956 | ocaml-syntax-shims github.com/ocaml-ppx/ocaml-syntax-shims 957 | ocaml-systemd github.com/juergenhoetzel/ocaml-systemd 958 | ocaml-top github.com/OCamlPro/ocaml-top 959 | ocaml-topexpect github.com/let-def/topexpect 960 | ocaml-variants github.com/ocaml/ocaml 961 | ocaml-vdom github.com/LexiFi/ocaml-vdom 962 | ocaml-version github.com/ocurrent/ocaml-version 963 | ocaml-xdg-basedir github.com/gildor478/ocaml-xdg-basedir 964 | OCanren github.com/JetBrains-Research/OCanren 965 | ocb github.com/OCamlPro/ocb 966 | ocb-stubblr github.com/pqwy/ocb-stubblr 967 | ocephes github.com/rleonid/ocephes 968 | ocf github.com/zoggy/ocf 969 | oci github.com/bobot/oci 970 | ocolor github.com/marc-chevalier/ocolor 971 | ocp-browser github.com/OCamlPro/ocp-index 972 | ocp-build github.com/OCamlPro/typerex-build 973 | ocp-indent github.com/OCamlPro/ocp-indent 974 | ocp-indent-nlfork github.com/OCamlPro/ocp-indent 975 | ocp-index-top github.com/reynir/ocp-index-top 976 | ocplib-concur github.com/OCamlPro/ocplib-concur 977 | ocplib-endian github.com/OCamlPro/ocplib-endian 978 | ocplib-json-typed github.com/ocamlpro/ocplib-json-typed 979 | ocplib-resto github.com/OCamlPro/ocplib-resto 980 | ocplib-simplex github.com/OCamlPro-Iguernlala/ocplib-simplex 981 | ocplib_stuff github.com/ocamlpro/ocplib_stuff 982 | ocp-pp github.com/OCamlPro/ocp-build 983 | ocsigen-i18n github.com/besport/ocsigen-i18n 984 | ocsigenserver github.com/ocsigen/ocsigenserver 985 | ocsigen-start github.com/ocsigen/ocsigen-start 986 | ocsigen-toolkit github.com/ocsigen/ocsigen-toolkit 987 | coctavius github.com/ocaml-doc/octavius 988 | ocveralls github.com/sagotch/ocveralls 989 | odash github.com/roryqueue/odash 990 | odate github.com/hhugo/odate 991 | odds github.com/raphael-proust/odds 992 | odepack github.com/Chris00/ocaml-odepack 993 | odig erratique.ch/repos/odig 994 | odnnr github.com/UnixJunkie/odnnr 995 | odoc github.com/ocaml/odoc 996 | offheap github.com/nandor/offheap 997 | ofx github.com/mvalle/ocaml-ofx 998 | ogen github.com/nv-vn/ogen 999 | ogg github.com/savonet/ocaml-ogg 1000 | oidc github.com/ulrikstrid/ocaml-oidc 1001 | ojquery github.com/ocsigen/ojquery 1002 | ojs-base github.com/zoggy/ojs-base 1003 | olinq github.com/c-cube/olinq 1004 | ollvm-tapir github.com/nholland94/ollvm-tapir 1005 | olmi github.com/xvw/olmi 1006 | oloop github.com/ocaml/oloop 1007 | omake github.com/ocaml-omake/omake 1008 | omd github.com/ocaml/omd 1009 | omigrate github.com/tmattio/omigrate 1010 | oml github.com/hammerlab/oml 1011 | omlr github.com/UnixJunkie/omlr 1012 | omonad github.com/yallop/omonad 1013 | opaca github.com/spreadLink/opaca 1014 | opal github.com/pyrocat101/opal 1015 | opam-0install github.com/ocaml-opam/opam-0install-solver 1016 | opam2web github.com/ocaml/opam2web 1017 | opam-bin github.com/ocamlpro/opam-bin 1018 | opam-bundle github.com/AltGr/opam-bundle 1019 | opam-client github.com/ocaml/opam 1020 | opam-compiler github.com/ocaml-opam/opam-compiler 1021 | opamconfig github.com/michipili/opamconfig 1022 | opam-depext github.com/ocaml/opam-depext 1023 | opam-dune-lint github.com/ocurrent/opam-dune-lint 1024 | opam-ed github.com/AltGr/opam-ed 1025 | opam-file-format github.com/ocaml/opam-file-format 1026 | opamfu github.com/ocamllabs/opamfu 1027 | opam-lock github.com/AltGr/opam-lock 1028 | opam-monorepo github.com/ocamllabs/opam-monorepo 1029 | opam_of_packagejson github.com/bsansouci/opam_of_packagejson 1030 | opam-package-upgrade github.com/AltGr/opam-package-upgrade 1031 | opam-publish github.com/ocaml/opam-publish 1032 | opam-sync-github-prs github.com/avsm/opam-sync-github-prs 1033 | opasswd github.com/xapi-project/ocaml-opasswd 1034 | open github.com/smolkaj/ocaml-open 1035 | openQASM github.com/inQWIRE/openqasm-parser 1036 | opium-graphql github.com/rgrinberg/opium 1037 | oplot github.com/sanette/oplot 1038 | oplsr github.com/UnixJunkie/oplsr 1039 | opomodoro github.com/m-laniakea/opomodoro 1040 | optal github.com/ocamlpro/optal 1041 | opti github.com/magnusjonsson/opti 1042 | optimization1d github.com/Chris00/optimization1d 1043 | optint github.com/mirage/optint 1044 | opus github.com/savonet/ocaml-opus 1045 | oraft github.com/komamitsu/oraft 1046 | orandforest github.com/tobast/ORandForest 1047 | oranger github.com/UnixJunkie/oranger 1048 | order-i3-xfce github.com/EmileTrotignon/order-i3-xfce 1049 | orec github.com/Octachron/orec 1050 | orewa github.com/Leonidas-from-XIV/orewa 1051 | orm github.com/mirage/orm 1052 | orocksdb github.com/domsj/orocksdb 1053 | orpie github.com/pelzlpj/orpie 1054 | orrandomForest github.com/UnixJunkie/orrandomForest 1055 | orsetto bitbucket.org/jhw/orsetto 1056 | orsvm_e1071 github.com/UnixJunkie/orsvm-e1071 1057 | orun github.com/shakthimaan/orun 1058 | orxgboost github.com/UnixJunkie/orxgboost 1059 | osbx github.com/darrenldl/ocaml-SeqBox 1060 | oseq github.com/c-cube/oseq 1061 | oskel github.com/CraigFe/oskel 1062 | ostap github.com/Kakadu/ostap 1063 | osx-acl github.com/dsheets/ocaml-osx-acl 1064 | osx-attr github.com/dsheets/ocaml-osx-attr 1065 | osx-cf github.com/dsheets/ocaml-osx-cf 1066 | osx-fsevents github.com/dsheets/ocaml-osx-fsevents 1067 | osx-membership github.com/dsheets/ocaml-osx-membership 1068 | osx-mount github.com/dsheets/ocaml-osx-mount 1069 | osx-plutil github.com/dsheets/ocaml-osx-plutil 1070 | osx-secure-transport github.com/toots/ocaml-osx-secure-transport 1071 | osx-xattr github.com/dsheets/ocaml-osx-xattr 1072 | otetris github.com/vzaliva/otetris 1073 | otf gitlab.com/pictyeye/otf 1074 | otfm erratique.ch/repos/otfm 1075 | otr github.com/hannesm/ocaml-otr 1076 | ott github.com/ott-lang/ott 1077 | otto github.com/jrraymond/otto 1078 | ounit github.com/gildor478/ounit 1079 | owebl github.com/eatonphil/owebl 1080 | owee github.com/let-def/owee 1081 | owl github.com/owlbarn/owl 1082 | owl-jupyter github.com/owlbarn/owl_jupyter 1083 | owl-ode github.com/owlbarn/owl_ode 1084 | owl-opt github.com/owlbarn/owl_opt 1085 | owl-symbolic github.com/owlbarn/owl_symbolic 1086 | owork github.com/jeffa5/owork 1087 | oxylc gitlab.com/selfReferentialName/oxylc 1088 | p4pp github.com/cornell-netlab/p4pp/ 1089 | pa_bench github.com/janestreet/pa_bench 1090 | pa_bin_prot github.com/janestreet/pa_bin_prot 1091 | pacomb github.com/craff/pacomb 1092 | paf github.com/dinosaure/paf-le-chien 1093 | pa_fields_conv github.com/janestreet/pa_fields_conv 1094 | pam github.com/janestreet/pam 1095 | pandoc github.com/smimram/ocaml-pandoc 1096 | pa_ounit github.com/janestreet/pa_ounit 1097 | papi github.com/pqwy/ocaml-papi 1098 | pa_ppx github.com/camlp5/pa_ppx 1099 | pa_ppx_ag github.com/camlp5/pa_ppx_ag 1100 | pa_ppx_hashcons github.com/camlp5/pa_ppx_hashcons 1101 | pa_ppx_migrate github.com/camlp5/pa_ppx_migrate 1102 | pa_ppx_q_ast github.com/camlp5/pa_ppx_q_ast 1103 | pa_ppx_unique github.com/camlp5/pa_ppx_unique 1104 | parany github.com/UnixJunkie/parany 1105 | pardi github.com/UnixJunkie/pardi 1106 | pareto github.com/superbobry/pareto 1107 | parmap github.com/rdicosmo/parmap 1108 | parse-argv github.com/mirage/parse-argv 1109 | parsexp github.com/janestreet/parsexp 1110 | parsexp_io github.com/janestreet/parsexp_io 1111 | parsley github.com/ghilesZ/parsley 1112 | partition_map github.com/rleonid/partition_map 1113 | pa_sexp_conv github.com/janestreet/pa_sexp_conv 1114 | pa_sqlexpr github.com/mfp/ocaml-sqlexpr 1115 | passmaker github.com/darioteixeira/passmaker 1116 | pa_structural_sexp github.com/janestreet/pa_structural_sexp 1117 | patch github.com/hannesm/patch 1118 | patdiff github.com/janestreet/patdiff 1119 | pa_test github.com/janestreet/pa_test 1120 | path_glob gitlab.com/gasche/path_glob 1121 | patience_diff github.com/janestreet/patience_diff 1122 | pattern github.com/thierry-martinez/pattern 1123 | pa_typerep_conv github.com/janestreet/pa_typerep_conv 1124 | pa_variants_conv github.com/janestreet/pa_variants_conv 1125 | pb github.com/yallop/ocaml-pb 1126 | pbkdf github.com/abeaumont/ocaml-pbkdf 1127 | pcap-format github.com/mirage/ocaml-pcap 1128 | pci github.com/simonjbeaumont/ocaml-pci 1129 | pds-reachability github.com/JHU-PL-Lab/pds-reachability 1130 | pecu github.com/mirage/pecu 1131 | petr4 github.com/cornell-netlab/petr4/ 1132 | pfff github.com/returntocorp/pfff 1133 | pf-qubes github.com/roburio/ocaml-pf 1134 | pgocaml github.com/darioteixeira/pgocaml 1135 | pg_query github.com/roddyyaga/pg_query-ocaml 1136 | pgx github.com/arenadotio/pgx 1137 | phantom-algebra github.com/Octachron/phantom_algebra 1138 | phashtbl github.com/UnixJunkie/phashtbl 1139 | phonetic github.com/geneweb/phonetic 1140 | phox github.com/craff/phox 1141 | piaf github.com/anmonteiro/piaf 1142 | picasso github.com/ghilesZ/picasso 1143 | pilat github.com/Stevendeo/Pilat 1144 | pipebang github.com/janestreet/pipebang 1145 | pixel_pusher github.com/mbacarella/pixel_pusher 1146 | pkcs11 github.com/cryptosense/pkcs11 1147 | pla github.com/modlfo/pla 1148 | plist github.com/fxfactorial/ocaml-plist 1149 | plist-xml github.com/alan-j-hu/ocaml-plist-xml 1150 | plplot github.com/hcarty/ocaml-plplot 1151 | polyglot github.com/dsheets/polyglot 1152 | polynomial gitlab.com/dannywillems/ocaml-polynomial 1153 | pomap github.com/mmottl/pomap 1154 | portaudio github.com/savonet/ocaml-portaudio 1155 | portaudio_c_bindings github.com/wlitwin/portaudio_c_bindings 1156 | portia github.com/rixed/portia 1157 | posixat github.com/janestreet/posixat 1158 | posix-base github.com/savonet/ocaml-posix 1159 | postgres_async github.com/janestreet/postgres_async 1160 | pp github.com/ocaml-dune/pp 1161 | ppx_accessor github.com/janestreet/ppx_accessor 1162 | ppx_assert github.com/janestreet/ppx_assert 1163 | ppx_ast github.com/janestreet/ppx_ast 1164 | ppx_bap github.com/BinaryAnalysisPlatform/ppx_bap 1165 | ppx_base github.com/janestreet/ppx_base 1166 | ppx_bench github.com/janestreet/ppx_bench 1167 | ppx_bigarray github.com/akabe/ppx_bigarray 1168 | ppx_bin_prot github.com/janestreet/ppx_bin_prot 1169 | ppx_blob github.com/johnwhitington/ppx_blob 1170 | ppx_bsx github.com/cxa/ppx_bsx 1171 | ppx_cold github.com/janestreet/ppx_cold 1172 | ppx_compare github.com/janestreet/ppx_compare 1173 | ppx_compose github.com/paurkedal/ppx_compose 1174 | ppx_const github.com/mcclure/ppx_const 1175 | ppx_conv_func github.com/janestreet/ppx_conv_func 1176 | ppx_core github.com/janestreet/ppx_core 1177 | ppx_cstubs github.com/fdopen/ppx_cstubs 1178 | ppx_csv_conv github.com/janestreet/ppx_csv_conv 1179 | ppx_custom_printf github.com/janestreet/ppx_custom_printf 1180 | ppx_debugger github.com/xvw/ppx_debugger 1181 | ppx_defer github.com/hcarty/ppx_defer 1182 | ppx_deriving github.com/ocaml-ppx/ppx_deriving 1183 | ppx_deriving_argparse github.com/masashi-y/ppx_deriving_argparse 1184 | ppx_deriving_cmdliner github.com/hammerlab/ppx_deriving_cmdliner 1185 | ppx_deriving_crowbar github.com/yomimono/ppx_deriving_crowbar 1186 | ppx_deriving_hardcaml github.com/janestreet/ppx_deriving_hardcaml 1187 | ppx_deriving_protobuf github.com/ocaml-ppx/ppx_deriving_protobuf 1188 | ppx_deriving_protocol github.com/andersfugmann/ppx_protocol_conv 1189 | ppx_deriving_yaml github.com/patricoferris/ppx_deriving_yaml 1190 | ppx_deriving_yojson github.com/ocaml-ppx/ppx_deriving_yojson 1191 | ppx_distr_guards github.com/vogler/ppx_distr_guards 1192 | ppx_driver github.com/janestreet/ppx_driver 1193 | ppx_enum github.com/cryptosense/ppx_enum 1194 | ppx_enumerate github.com/janestreet/ppx_enumerate 1195 | ppx_expect github.com/janestreet/ppx_expect 1196 | ppx_factory github.com/cryptosense/ppx_factory 1197 | ppx_fail github.com/janestreet/ppx_fail 1198 | ppx_fields_conv github.com/janestreet/ppx_fields_conv 1199 | ppxfind github.com/jeremiedimino/ppxfind 1200 | ppx_fixed_literal github.com/janestreet/ppx_fixed_literal 1201 | ppx_fun github.com/little-arhat/ppx_fun 1202 | ppx_gen_rec github.com/flowtype/ocaml-ppx_gen_rec 1203 | ppx_getenv github.com/ocaml-ppx/ppx_getenv 1204 | ppx_graphql github.com/andreas/ppx_graphql 1205 | ppx_hardcaml github.com/xguerin/ppx_hardcaml 1206 | ppx_hash github.com/janestreet/ppx_hash 1207 | ppx_here github.com/janestreet/ppx_here 1208 | ppx_import github.com/ocaml-ppx/ppx_import 1209 | ppx_inline_test github.com/janestreet/ppx_inline_test 1210 | ppx_jane github.com/janestreet/ppx_jane 1211 | ppx_json_types github.com/nv-vn/otp 1212 | ppx_js_style github.com/janestreet/ppx_js_style 1213 | ppx_let github.com/janestreet/ppx_let 1214 | ppxlib github.com/ocaml-ppx/ppxlib 1215 | ppx_log github.com/janestreet/ppx_log 1216 | ppx_measure github.com/xvw/ppx_measure 1217 | ppx_meta_conv gitlab.com/camlspotter/ppx_meta_conv 1218 | ppx_metaquot github.com/janestreet/ppx_metaquot 1219 | ppx_module_timer github.com/janestreet/ppx_module_timer 1220 | ppx_monoid github.com/bobatkey/ppx-monoid 1221 | ppx_mysql github.com/issuu/ppx_mysql 1222 | ppx_nanocaml github.com/nanocaml/nanocaml 1223 | ppx_netblob github.com/chrismamo1/ppx_netblob 1224 | ppx_optcomp github.com/janestreet/ppx_optcomp 1225 | ppx_optional github.com/janestreet/ppx_optional 1226 | ppx_pattern_bind github.com/janestreet/ppx_pattern_bind 1227 | ppx_pipebang github.com/janestreet/ppx_pipebang 1228 | ppx_python github.com/janestreet/ppx_python 1229 | ppx_rapper github.com/roddyyaga/ppx_rapper 1230 | ppx_regexp github.com/paurkedal/ppx_regexp 1231 | ppx_repr github.com/mirage/repr 1232 | ppx_sexp_conv github.com/janestreet/ppx_sexp_conv 1233 | ppx_sexp_message github.com/janestreet/ppx_sexp_message 1234 | ppx_sexp_value github.com/janestreet/ppx_sexp_value 1235 | ppx_show github.com/thierry-martinez/ppx_show 1236 | ppx_stable github.com/janestreet/ppx_stable 1237 | ppx_string github.com/janestreet/ppx_string 1238 | ppx_string_interpolation github.com/bloomberg/ppx_string_interpolation 1239 | ppx_test gitlab.com/camlspotter/ppx_test 1240 | ppx_there github.com/NathanReb/ppx_there 1241 | ppx_tools github.com/ocaml-ppx/ppx_tools 1242 | ppx_traverse github.com/janestreet/ppx_traverse 1243 | ppx_traverse_builtins github.com/janestreet/ppx_traverse_builtins 1244 | ppx_type_conv github.com/janestreet/ppx_type_conv 1245 | ppx_typerep_conv github.com/janestreet/ppx_typerep_conv 1246 | ppx_variants_conv github.com/janestreet/ppx_variants_conv 1247 | ppx_view github.com/ocaml-ppx/ppx_view 1248 | ppx_where github.com/nv-vn/ppx_where 1249 | ppxx gitlab.com/camlspotter/ppxx 1250 | ppx_xml_conv github.com/janestreet/ppx_xml_conv 1251 | ppx_yojson github.com/NathanReb/ppx_yojson 1252 | ppx_yojson_conv github.com/janestreet/ppx_yojson_conv 1253 | ppx_yojson_conv_lib github.com/janestreet/ppx_yojson_conv_lib 1254 | pratter github.com/gabrielhdt/pratter 1255 | prbnmcn-clustering github.com/igarnier/prbnmcn-clustering 1256 | prbnmcn-mcts github.com/igarnier/prbnmcn-mcts 1257 | prbnmcn-ucb1 gitlab.com/igarnier/monorepo 1258 | prettiest github.com/andreasfrom/prettiest 1259 | prettym github.com/dinosaure/prettym 1260 | primes github.com/KitFreddura/OCaml-Primes 1261 | printbox github.com/c-cube/printbox 1262 | process github.com/dsheets/ocaml-process 1263 | progress github.com/CraigFe/progress 1264 | prom github.com/vbmithr/ocaml-prometheus 1265 | prometheus github.com/mirage/prometheus 1266 | promise github.com/aantron/promise 1267 | promise_jsoo github.com/mnxn/promise_jsoo 1268 | protocell github.com/martinslota/protocell 1269 | protocol-9p github.com/mirage/ocaml-9p 1270 | protocol_version_header github.com/janestreet/protocol_version_header 1271 | psq github.com/pqwy/psq 1272 | psyche github.com/0918nobita/psyche 1273 | ptmap github.com/backtracking/ptmap 1274 | ptset github.com/backtracking/ptset 1275 | publish github.com/ocaml/opam-publish 1276 | pulseaudio github.com/savonet/ocaml-pulseaudio 1277 | pumping github.com/Drup/pumping 1278 | pure-splitmix github.com/Lysxia/pure-splitmix 1279 | pxp gitlab.camlcity.org/gerd/lib-pxp 1280 | py github.com/zshipko/ocaml-py 1281 | pyml github.com/thierry-martinez/pyml 1282 | pythonlib github.com/janestreet/pythonlib 1283 | qbf github.com/c-cube/ocaml-qbf 1284 | qcheck github.com/c-cube/qcheck 1285 | qcow github.com/mirage/ocaml-qcow 1286 | qcstm github.com/jmid/qcstm 1287 | qinap github.com/guillecosta/qinap 1288 | qiskit github.com/dakk/caml_qiskit 1289 | qrc erratique.ch/repos/qrc 1290 | qrencode github.com/vbmithr/qrencode-ocaml 1291 | quest github.com/lindig/quest 1292 | quests github.com/roddyyaga/quests 1293 | radare2 github.com/fxfactorial/ocaml-radare2 1294 | radis github.com/dinosaure/radis 1295 | randomconv github.com/hannesm/randomconv 1296 | range github.com/aldrikfr/range 1297 | ranger github.com/rgrinberg/ranger 1298 | rankers github.com/UnixJunkie/rankers 1299 | rashell github.com/michipili/rashell 1300 | rawlink github.com/haesbaert/rawlink 1301 | raygun4ocaml github.com/lidcore/raygun4ocaml 1302 | raylib github.com/tjammer/raylib-ocaml 1303 | rdbg gricad-gitlab.univ-grenoble-alpes.fr/verimag/synchrone/rdbg 1304 | re github.com/ocaml/ocaml-re 1305 | re2 github.com/janestreet/re2 1306 | re2_stable github.com/janestreet/re2_stable 1307 | reactiveData github.com/ocsigen/reactiveData 1308 | reanalyze github.com/rescript-association/reanalyze 1309 | reason-standard github.com/dean177/reason-standard 1310 | receive-mail github.com/CREATe-centre/receive-mail 1311 | record_builder github.com/janestreet/record_builder 1312 | records github.com/cryptosense/records 1313 | reddit_api_async github.com/leviroth/ocaml-reddit-api 1314 | redirect github.com/thierry-martinez/redirect 1315 | redis github.com/0xffea/ocaml-redis 1316 | reedsolomon github.com/ujamjar/reedsolomon 1317 | reed-solomon-erasure gitlab.com/darrenldl/ocaml-reed-solomon-erasure 1318 | regenerate github.com/regex-generate/regenerate 1319 | reparse github.com/lemaetech/reparse 1320 | res github.com/mmottl/res 1321 | resource_cache github.com/janestreet/resource_cache 1322 | resource-pooling github.com/ocsigen/resource-pooling 1323 | resp github.com/zshipko/resp 1324 | result github.com/janestreet/result 1325 | rfc6287 github.com/sg2342/ocaml-rfc6287 1326 | rfc7748 github.com/burgerdev/ocaml-rfc7748 1327 | rfsm github.com/jserot/rfsm 1328 | rhythm github.com/decent-algorithms/rhythm 1329 | riakc_ppx github.com/struktured/riakc_ppx 1330 | ringo gitlab.com/nomadic-labs/ringo 1331 | river github.com/kayceesrk/river 1332 | rlp github.com/pirapira/rlp-ocaml 1333 | rmlbuild github.com/reactiveml/rmlbuild 1334 | roman github.com/johnwhitington/roman 1335 | root1d github.com/Chris00/root1d 1336 | rope github.com/Chris00/ocaml-rope 1337 | rosetta github.com/mirage/rosetta 1338 | rotor gitlab.com/trustworthy-refactoring/refactorer 1339 | routes github.com/anuragsoni/routes 1340 | rpc_parallel github.com/janestreet/rpc_parallel 1341 | rubytt github.com/chenyukang/rubytt 1342 | rungen github.com/shakthimaan/rungen 1343 | rusage github.com/CraigFe/ocaml-rusage 1344 | safepass github.com/darioteixeira/ocaml-safepass 1345 | sail github.com/rems-project/sail 1346 | salsa20 github.com/abeaumont/ocaml-salsa20 1347 | salsa20-core github.com/abeaumont/ocaml-salsa20-core 1348 | samplerate github.com/savonet/ocaml-samplerate 1349 | sanddb github.com/StrykerKKD/SandDB 1350 | sanlock github.com/simonjbeaumont/ocaml-sanlock 1351 | sattools github.com/ujamjar/sattools 1352 | satyrographos github.com/na4zagin3/satyrographos 1353 | scgi github.com/bikallem/ocaml-scgi 1354 | schroedinger github.com/savonet/ocaml-schroedinger 1355 | scrypt github.com/constfun/ocaml-scrypt 1356 | scrypt-kdf github.com/abeaumont/ocaml-scrypt-kdf 1357 | secp256k1 github.com/dakk/secp256k1-ml 1358 | secp256k1-internal gitlab.com/nomadic-labs/ocaml-secp256k1-internal 1359 | sedlex github.com/ocaml-community/sedlex 1360 | sek gitlab.inria.fr/fpottier/sek 1361 | selective github.com/snowleopard/selective-ocaml 1362 | semaphore-compat github.com/mirage/semaphore-compat 1363 | semver github.com/rgrinberg/ocaml-semver 1364 | semver2 github.com/dividat/ocaml-semver 1365 | sendmsg github.com/pqwy/sendmsg 1366 | sentry github.com/brendanlong/sentry-ocaml 1367 | sequencer_table github.com/janestreet/sequencer_table 1368 | sequoia github.com/andrenth/sequoia 1369 | serial github.com/m-laniakea/oserial 1370 | session github.com/inhabitedtype/ocaml-session 1371 | sessions github.com/essdotteedot/sessions 1372 | setcore github.com/UnixJunkie/setcore 1373 | setr github.com/arlencox/SETr 1374 | sexp github.com/janestreet/sexp 1375 | sexp_diff_kernel github.com/janestreet/sexp_diff_kernel 1376 | sexplib github.com/janestreet/sexplib 1377 | sexplib0 github.com/janestreet/sexplib0 1378 | sexp_macro github.com/janestreet/sexp_macro 1379 | sexp_pretty github.com/janestreet/sexp_pretty 1380 | sexp_select github.com/janestreet/sexp_select 1381 | sfml github.com/fccm/ocaml-sfml 1382 | sha github.com/djs55/ocaml-sha 1383 | shapefile github.com/cyril-allignol/ocaml-shapefile 1384 | shared-block-ring github.com/mirage/shared-block-ring 1385 | shared-memory-ring github.com/mirage/shared-memory-ring 1386 | shared-secret github.com/marcoonroad/shared-secret 1387 | shcaml github.com/tov/shcaml 1388 | shell github.com/janestreet/shell 1389 | shexp github.com/janestreet/shexp 1390 | shine github.com/savonet/ocaml-shine 1391 | sibylfs github.com/sibylfs/sibylfs_src 1392 | sid gitlab.com/phgsng/ocaml-sid 1393 | sihl github.com/oxidizing/sihl 1394 | sill github.com/ISANobody/sill 1395 | simple63 github.com/barko/simple63 1396 | simple-diff github.com/gjaldon/simple_diff 1397 | skkserv-lite github.com/anyakichi/ocaml-skkserv-lite 1398 | slack-backup github.com/Khady/slack-backup 1399 | slap github.com/akabe/slap 1400 | smbc github.com/c-cube/smbc 1401 | smtlib-utils github.com/c-cube/smtlib-utils 1402 | Snowflake gitlab.com/boreal-ldd/snowflake 1403 | socialpeek github.com/erizocosmico/ocaml-socialpeek 1404 | sociaml-facebook-api github.com/dominicjprice/sociaml-facebook-api 1405 | sociaml-oauth-client github.com/CREATe-centre/sociaml-oauth-client 1406 | sociaml-tumblr-api github.com/CREATe-centre/sociaml-tumblr-api 1407 | socket-daemon github.com/zoggy/ocaml-socket-daemon 1408 | sodium github.com/dsheets/ocaml-sodium 1409 | solo5-bindings-genode github.com/solo5/solo5 1410 | solvuu-build github.com/solvuu/solvuu-build 1411 | solvuu_build github.com/solvuu/solvuu_build 1412 | sosa github.com/hammerlab/sosa 1413 | soundtouch github.com/savonet/ocaml-soundtouch 1414 | soupault github.com/dmbaturin/soupault 1415 | space-search github.com/konne88/SpaceSearch 1416 | sparrow github.com/ropas/sparrow 1417 | spawn github.com/janestreet/spawn 1418 | speex github.com/savonet/ocaml-speex 1419 | spf github.com/andrenth/ocaml-spf 1420 | sphinxcontrib-ocaml github.com/jacquev6/sphinxcontrib-ocaml 1421 | spin github.com/tmattio/spin 1422 | spirv github.com/nholland94/spirv-ocaml 1423 | splay_tree github.com/janestreet/splay_tree 1424 | splittable_random github.com/janestreet/splittable_random 1425 | spoc github.com/mathiasbourgoin/SPOC 1426 | spotlib gitlab.com/camlspotter/spotlib 1427 | sqlgg github.com/ygrek/sqlgg 1428 | sqlite3_utils github.com/c-cube/sqlite3_utils 1429 | srs github.com/andrenth/ocaml-srs 1430 | srt github.com/savonet/ocaml-srt 1431 | ssh-agent github.com/reynir/ocaml-ssh-agent 1432 | ssl github.com/savonet/ocaml-ssl 1433 | sslconf github.com/awuersch/sslconf 1434 | stationary github.com/imeckler/stationary 1435 | statmemprof-emacs github.com/jhjourdan/statmemprof-emacs 1436 | stb_image github.com/let-def/stb_image 1437 | stb_image_write github.com/def-lkb/stb_image_write 1438 | stb_truetype github.com/let-def/stb_truetype 1439 | stdcompat github.com/thierry-martinez/stdcompat 1440 | stdint github.com/andrenth/ocaml-stdint 1441 | stdio github.com/janestreet/stdio 1442 | stdlib-diff github.com/jhrdina/ocaml-diff 1443 | stdlib-shims github.com/ocaml/stdlib-shims 1444 | stitch github.com/cryptosense/ocaml-stitch 1445 | streaming github.com/odis-labs/streaming 1446 | string_dict github.com/janestreet/string_dict 1447 | stringext github.com/rgrinberg/stringext 1448 | sturgeon github.com/let-def/sturgeon 1449 | subscriptions-transport-ws github.com/anmonteiro/ocaml-subscriptions-transport-ws 1450 | subtype-refinement github.com/marcoonroad/subtype-refinement 1451 | swagger github.com/andrenth/ocaml-swagger 1452 | syndic github.com/Cumulus/Syndic 1453 | syslog-message github.com/verbosemode/syslog-message 1454 | syslog-rfc5424 github.com/vbmithr/ocaml-syslog-rfc5424 1455 | sys-socket github.com/toots/ocaml-sys-socket 1456 | systemverilog github.com/xguerin/ocaml-systemverilog 1457 | taglib github.com/savonet/ocaml-taglib 1458 | taglog github.com/zoggy/ocaml-taglog 1459 | tallgeese github.com/fxfactorial/tallgeese 1460 | tar github.com/mirage/ocaml-tar 1461 | tcpip github.com/mirage/mirage-tcpip 1462 | tdk github.com/frenetic-lang/ocaml-tdk 1463 | teash github.com/neochrome/teash 1464 | telegraml github.com/nv-vn/telegraml 1465 | telltime github.com/daypack-dev/telltime 1466 | tensorboard github.com/LaurentMazare/ocaml-tensorboard 1467 | tensorflow github.com/LaurentMazare/tensorflow-ocaml 1468 | terminal_size github.com/cryptosense/terminal_size 1469 | testrunner github.com/zoggy/ocaml-testrunner 1470 | text github.com/vbmithr/ocaml-text 1471 | textmate-language github.com/alan-j-hu/ocaml-textmate-language 1472 | textrazor github.com/Richard-Degenne/ocaml-textrazor 1473 | textutils github.com/janestreet/textutils 1474 | textutils_kernel github.com/janestreet/textutils_kernel 1475 | textwrap github.com/superbobry/ocaml-textwrap 1476 | tezos gitlab.com/tezos/tezos 1477 | tezos-rust-libs gitlab.com/tezos/tezos-rust-libs 1478 | tftp github.com/mor1/ocaml-tftp 1479 | theora github.com/savonet/ocaml-theora 1480 | timed github.com/rlepigre/ocaml-timed 1481 | time_now github.com/janestreet/time_now 1482 | timere github.com/daypack-dev/timere 1483 | timezone github.com/janestreet/timezone 1484 | tiny_httpd github.com/c-cube/tiny_httpd 1485 | tiny_json gitlab.com/camlspotter/tiny_json 1486 | tip-parser github.com/c-cube/tip-parser 1487 | tjr_simple_earley github.com/tomjridge/tjr_simple_earley 1488 | tldr github.com/RosalesJ/tldr-ocaml 1489 | tls github.com/mirleft/ocaml-tls 1490 | tlstunnel github.com/hannesm/tlstunnel 1491 | toml github.com/ocaml-toml/To.ml 1492 | toml-cconv github.com/mackwic/To.ml 1493 | topkg-care erratique.ch/repos/topkg 1494 | topkg-jbuilder github.com/samoht/topkg-jbuilder 1495 | toplevel_backend github.com/janestreet/toplevel_backend 1496 | toplevel_expect_test github.com/janestreet/toplevel_expect_test 1497 | topological_sort github.com/janestreet/topological_sort 1498 | torch github.com/LaurentMazare/ocaml-torch 1499 | touist github.com/touist/touist 1500 | tplib scm.gforge.inria.fr/anonscm/git/tplib/tplib 1501 | tqdm github.com/LaurentMazare/ocaml-tqdm 1502 | traildb github.com/didier-wenzek/ocaml-traildb 1503 | trakeva github.com/smondet/trakeva 1504 | transept github.com/d-plaindoux/transept 1505 | transmission-rpc github.com/bataille/ocaml-transmission-rpc 1506 | traverse github.com/thierry-martinez/traverse 1507 | travesty github.com/MattWindsor91/travesty 1508 | travis-opam github.com/ocaml/ocaml-ci-scripts 1509 | trax github.com/mjambon/trax 1510 | tree_layout github.com/Drup/tree_layout 1511 | treeprint gitlab.com/camlspotter/treeprint 1512 | tsdl erratique.ch/repos/tsdl 1513 | tsdl-image github.com/tokenrove/tsdl-image 1514 | tsdl-mixer github.com/tokenrove/tsdl-mixer 1515 | tsdl-ttf github.com/tokenrove/tsdl-ttf 1516 | tsort github.com/dmbaturin/ocaml-tsort 1517 | tuareg github.com/ocaml/tuareg 1518 | tube github.com/alinpopa/tube 1519 | tuntap github.com/mirage/ocaml-tuntap 1520 | type-beat github.com/oklm-wsh/TypeBeat 1521 | typebeat github.com/mirage/typebeat 1522 | type_conv github.com/janestreet/type_conv 1523 | typerep github.com/janestreet/typerep 1524 | typerep_extended github.com/janestreet/typerep_extended 1525 | typerex-attic github.com/OCamlPro/typerex-attic 1526 | typerex-binutils github.com/OCamlPro/typerex-binutils 1527 | typerex-clibs github.com/OCamlPro/typerex-clibs 1528 | typerex-lldb github.com/OCamlPro/typerex-lldb 1529 | typerex-system github.com/OCamlPro/typerex-system 1530 | tyre github.com/Drup/tyre 1531 | tyxml github.com/ocsigen/tyxml 1532 | ubase github.com/sanette/ubase 1533 | ubpf github.com/ahrefs/ocaml-ubpf 1534 | uchar github.com/ocaml/uchar 1535 | ucorelib github.com/yoriyuki/ucorelib 1536 | uecc gitlab.com/nomadic-labs/ocaml-uecc 1537 | uint github.com/andrenth/ocaml-uint 1538 | ulex-camlp5 github.com/whitequark/ulex 1539 | ulid github.com/stripedpajamas/ocaml-ulid 1540 | unidecode github.com/geneweb/unidecode 1541 | unionFind gitlab.inria.fr/fpottier/unionFind 1542 | unix-dirent github.com/dsheets/ocaml-unix-dirent 1543 | unix-errno github.com/dsheets/ocaml-unix-errno 1544 | unix-fcntl github.com/dsheets/ocaml-unix-fcntl 1545 | unix-sys-resource github.com/dsheets/ocaml-unix-sys-resource 1546 | unix-sys-stat github.com/dsheets/ocaml-unix-sys-stat 1547 | unix-time github.com/dsheets/ocaml-unix-time 1548 | unix-type-representations github.com/yallop/ocaml-unix-type-representations 1549 | unix-unistd github.com/dsheets/ocaml-unix-unistd 1550 | unmagic gitlab.com/camlspotter/unmagic 1551 | unstrctrd github.com/dinosaure/unstrctrd 1552 | uri github.com/mirage/ocaml-uri 1553 | usb github.com/letoh/ocaml-usb 1554 | usbmux github.com/onlinemediagroup/ocaml-usbmux 1555 | user-agent-parser github.com/issuu/uap-ocaml 1556 | user-setup github.com/OCamlPro/opam-user-setup 1557 | utop github.com/ocaml-community/utop 1558 | utp www.github.com/nojb/ocaml-utp 1559 | uuidm erratique.ch/repos/uuidm 1560 | uuseg erratique.ch/repos/uuseg 1561 | uuuu github.com/mirage/uuuu 1562 | uwt github.com/fdopen/uwt 1563 | valentine github.com/fxfactorial/valentine 1564 | variantslib github.com/janestreet/variantslib 1565 | varint github.com/XnuKernPoll/ocaml-varint 1566 | vcaml github.com/janestreet/vcaml 1567 | vcardgen github.com/vzaliva/vcardgen 1568 | vchan github.com/mirage/ocaml-vchan 1569 | vec github.com/aionescu/vec 1570 | vecosek gitlab.com/smondet/vecosek 1571 | vg erratique.ch/repos/vg 1572 | vimebac gitlab.com/smondet/vimebac 1573 | virtual_dom github.com/janestreet/virtual_dom 1574 | visitors gitlab.inria.fr/fpottier/visitors 1575 | vlq github.com/flowtype/ocaml-vlq 1576 | vmnet github.com/mirage/ocaml-vmnet 1577 | voaacenc github.com/savonet/ocaml-voaacenc 1578 | volt github.com/codinuum/volt 1579 | voqc github.com/inQWIRE/mlvoqc 1580 | vorbis github.com/savonet/ocaml-vorbis 1581 | vpnkit github.com/moby/vpnkit 1582 | vue-jsoo gitlab.com/o-labs/vue-jsoo 1583 | wall github.com/let-def/wall 1584 | wamp github.com/vbmithr/ocaml-wamp 1585 | wasm github.com/WebAssembly/spec 1586 | wasmtime github.com/LaurentMazare/ocaml-wasmtime 1587 | wayland github.com/talex5/ocaml-wayland 1588 | waylaunch github.com/kit-ty-kate/waylaunch 1589 | wcs github.com/IBM/wcs-ocaml 1590 | weberizer github.com/Chris00/weberizer 1591 | webidl github.com/0zat/webidl 1592 | webmachine github.com/inhabitedtype/ocaml-webmachine 1593 | websocketaf github.com/inhabitedtype/websocketaf 1594 | websocket-async github.com/vbmithr/ocaml-websocket 1595 | websocketml github.com/ismailbennani/websocketml 1596 | why scm.gforge.inria.fr/anonscm/git/why/why 1597 | why3 gitlab.inria.fr/why3/why3 1598 | wikitext github.com/geneanet/ocaml-wikitext 1599 | win-error github.com/mirage/ocaml-win-error 1600 | win-eventlog github.com/mirage/ocaml-win-eventlog 1601 | winsvc github.com/savonet/ocaml-winsvc 1602 | ws github.com/dozzman/ws 1603 | ws-server github.com/roddyyaga/ws-server 1604 | wtf8 github.com/flowtype/ocaml-wtf8 1605 | wxOCaml github.com/OCamlPro/ocplib-wxOCaml 1606 | x509 github.com/mirleft/ocaml-x509 1607 | xapi-libs-transitional github.com/xapi-project/xen-api-libs-transitional 1608 | xapi-rrd github.com/xapi-project/xcp-rrd 1609 | xapi-rrdd github.com/xapi-project/xcp-rrdd 1610 | xapi-rrd-transport github.com/xapi-project/rrd-transport 1611 | xenctrl github.com/xapi-project/ocaml-xen-lowlevel-libs 1612 | xen-evtchn github.com/mirage/ocaml-evtchn 1613 | xen-gnt github.com/mirage/ocaml-gnt 1614 | xenstore github.com/mirage/ocaml-xenstore 1615 | xmlplaylist github.com/savonet/ocaml-xmlplaylist 1616 | yara github.com/XVilka/yara-ocaml 1617 | yices2 github.com/maelvalais/ocamlyices2 1618 | yojson github.com/ocaml-community/yojson 1619 | yurt github.com/zshipko/yurt 1620 | yuscii github.com/mirage/yuscii 1621 | yuujinchou github.com/favonia/yuujinchou 1622 | z3 github.com/Z3prover/z3 1623 | zarith github.com/ocaml/Zarith 1624 | zarith-ppx github.com/Drup/Zarith-ppx 1625 | zarith_stubs_js github.com/janestreet/zarith_stubs_js 1626 | zeit github.com/emillon/ocaml-zeit 1627 | zelus github.com/INRIA/zelus 1628 | zenon github.com/zenon-prover/zenon 1629 | zlib github.com/madroach/ocaml-zlib 1630 | zlist github.com/hakuch/zlist 1631 | zstandard github.com/janestreet/zstandard 1632 | zxcvbn github.com/cryptosense/ocaml-zxcvbn 1633 | -------------------------------------------------------------------------------- /www/colorize.ml: -------------------------------------------------------------------------------- 1 | module H = Tyxml.Html 2 | module Higlo = Higlo.Lang 3 | 4 | let span cl s = H.span ~a:[ H.a_class [ cl ] ] [ H.txt s ] 5 | 6 | let html_of_token = function 7 | | Higlo.Text str -> H.txt str 8 | | Symbol (_, s) -> span "symbol" s 9 | | String s -> span "string" s 10 | | Numeric s -> span "numeric" s 11 | | Lcomment s -> span "comment" s 12 | | Bcomment s -> span "comment" s 13 | | Keyword (_, s) -> span "kw" s 14 | | Escape s -> span "escape" s 15 | | Directive s -> span "directive" s 16 | | Constant s -> span "constant" s 17 | | Id s -> span "ident" s 18 | 19 | let string_of_token = function 20 | | Higlo.Text s 21 | | Symbol (_, s) 22 | | String s 23 | | Numeric s 24 | | Lcomment s 25 | | Bcomment s 26 | | Keyword (_, s) 27 | | Escape s 28 | | Directive s 29 | | Constant s 30 | | Id s -> s 31 | 32 | let token_replace s = function 33 | | Higlo.Text _ -> Higlo.Text s 34 | | Symbol (n, _) -> Symbol (n, s) 35 | | String _ -> String s 36 | | Numeric _ -> Numeric s 37 | | Lcomment _ -> Lcomment s 38 | | Bcomment _ -> Bcomment s 39 | | Keyword (n, _) -> Keyword (n, s) 40 | | Escape _ -> Escape s 41 | | Directive _ -> Directive s 42 | | Constant _ -> Constant s 43 | | Id _ -> Id s 44 | 45 | let string_split i str = String.sub str 0 i, String.sub str i (String.length str - i) 46 | 47 | let rec take acc n = function 48 | | [] -> List.rev acc, [] 49 | | t :: ts -> 50 | let txt = string_of_token t in 51 | let txt_len = String.length txt in 52 | if n > txt_len 53 | then take (t :: acc) (n - txt_len) ts 54 | else ( 55 | let txt_before, txt_after = string_split n txt in 56 | let tok_before = token_replace txt_before t in 57 | let tok_after = token_replace txt_after t in 58 | List.rev (tok_before :: acc), tok_after :: ts) 59 | 60 | let take n ts = take [] n ts 61 | 62 | let to_html line = 63 | let tokens = Higlo.parse ~lang:"ocaml" line in 64 | List.map html_of_token tokens 65 | 66 | let to_html_highlight ~mark line (start_at, end_at) = 67 | let tokens = Higlo.parse ~lang:"ocaml" line in 68 | let start, rest = take start_at tokens in 69 | let inside, rest = take (end_at - start_at) rest in 70 | List.map html_of_token start 71 | @ [ mark @@ List.map html_of_token inside ] 72 | @ List.map html_of_token rest 73 | -------------------------------------------------------------------------------- /www/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (name www) 3 | (libraries cmdliner lwt dream higlo str tyxml db regex)) 4 | -------------------------------------------------------------------------------- /www/link.ml: -------------------------------------------------------------------------------- 1 | let is_prefix ~prefix str = 2 | let n = String.length prefix in 3 | if String.length str < n then false else prefix = String.sub str 0 n 4 | 5 | let link url filename line_number = 6 | match String.split_on_char '/' url with 7 | | "github.com" :: _ | "www.github.com" :: _ -> 8 | Printf.sprintf "https://%s/blob/master/%s#L%i" url filename line_number 9 | | domain :: _ when is_prefix ~prefix:"gitlab" domain -> 10 | Printf.sprintf "https://%s/-/blob/master/%s#L%i" url filename line_number 11 | | "bitbucket.org" :: _ -> 12 | Printf.sprintf "https://%s/src/master/%s#lines-%i" url filename line_number 13 | | "forge.ocamlcore.org" :: _ -> "https://forge.ocamlcore.org" 14 | | "erratique.ch" :: _ -> 15 | Printf.sprintf "https://%s/tree/%s#n%i" url filename line_number 16 | | "git.annexia.org" :: proj -> 17 | Printf.sprintf 18 | "https://%s/?p=%s.git;f=%s#l%i" 19 | url 20 | (String.concat "/" proj) 21 | filename 22 | line_number 23 | | "gforge.inria.fr" :: "git" :: user :: proj 24 | | "scm.gforge.inria.fr" :: user :: "git" :: proj -> 25 | Printf.sprintf 26 | "https://%s/%s/gitweb?p=%s.git;f=%s#l%i" 27 | url 28 | user 29 | (String.concat "/" proj) 30 | filename 31 | line_number 32 | | "gricad-gitlab.univ-grenoble-alpes.fr" :: _ | "git.frama-c.com" :: _ -> 33 | Printf.sprintf "https://%s/-/blob/master/%s#L%i" url filename line_number 34 | | "cavale.enseeiht.fr" :: _ -> "" 35 | | "framagit.org" :: _ -> "" 36 | | _ -> "" 37 | 38 | module H = Hashtbl.Make (struct 39 | type t = string 40 | 41 | let hash = Hashtbl.hash 42 | let equal = String.equal 43 | end) 44 | 45 | let mapping = H.create 0 46 | 47 | let parse_line line = 48 | match String.split_on_char '\t' line with 49 | | [ project; remote ] -> H.add mapping project remote 50 | | _ -> Printf.printf "Link.parse_line error: %S\n%!" line 51 | 52 | let load filename = 53 | let h = open_in filename in 54 | let rec go () = 55 | match input_line h with 56 | | exception End_of_file -> () 57 | | line -> 58 | parse_line line ; 59 | go () 60 | in 61 | go () ; 62 | close_in h 63 | 64 | let split_project filename = 65 | let at = String.index filename '/' in 66 | let project = String.sub filename 0 at in 67 | let at = at + 1 in 68 | let file = String.sub filename at (String.length filename - at) in 69 | project, file 70 | 71 | let url filename line_number = 72 | try 73 | let project, filename = split_project filename in 74 | let remote = H.find mapping project in 75 | link remote filename line_number 76 | with 77 | | _ -> "" 78 | 79 | let url filename line_number = 80 | match url filename line_number with 81 | | "" -> "#unknown" 82 | | x -> x 83 | -------------------------------------------------------------------------------- /www/link.mli: -------------------------------------------------------------------------------- 1 | val load : string -> unit 2 | val url : string -> int -> string 3 | -------------------------------------------------------------------------------- /www/present.ml: -------------------------------------------------------------------------------- 1 | open Tyxml.Html 2 | open Search 3 | 4 | let group_results_by_filename results = 5 | let rec go current_filename acc = function 6 | | [] -> [ List.rev acc ] 7 | | r :: rs when r.filename = current_filename -> go current_filename (r :: acc) rs 8 | | r :: rs -> List.rev acc :: go1 r rs 9 | and go1 r rs = go r.filename [ r ] rs in 10 | match results with 11 | | [] -> [] 12 | | r :: rs -> go1 r rs 13 | 14 | let indentation str = 15 | let rec go i = if i < String.length str && str.[i] = ' ' then go (i + 1) else i in 16 | go 0 17 | 18 | let find_context_line ~previous m = 19 | let line_indent = indentation m.line in 20 | if line_indent = 0 21 | then [] 22 | else ( 23 | let cursor = m.cursor in 24 | let rec go nb_found line_num line_indent = 25 | if nb_found >= 3 || line_indent = 0 || line_num <= previous 26 | then [] 27 | else ( 28 | let line = Db.read_line ~cursor line_num in 29 | let new_indent = indentation line in 30 | if new_indent < String.length line && new_indent < line_indent 31 | then (line_num, line) :: go (nb_found + 1) (line_num - 1) new_indent 32 | else go nb_found (line_num - 1) line_indent) 33 | in 34 | go 0 (m.offset - 1) line_indent) 35 | 36 | let present_match ~previous m = 37 | let mark h = mark [ a ~a:[ a_href (Link.url m.filename (m.line_num + 1)) ] h ] in 38 | let hlmatch = Colorize.to_html_highlight ~mark m.line m.range in 39 | let contexts_list = find_context_line ~previous m in 40 | let contexts = List.map (fun (ln, str) -> ln, Colorize.to_html str) contexts_list in 41 | let results = (m.offset, hlmatch) :: contexts in 42 | m.offset, results 43 | 44 | let present_line_numbers ~filename matches = 45 | let rec fold prev_line_num = function 46 | | [] -> [] 47 | | (ln, hlmatch) :: rest -> 48 | let cont_above = prev_line_num + 1 = ln in 49 | let cont_below = 50 | match rest with 51 | | (ln', _) :: _ -> ln + 1 = ln' 52 | | _ -> false 53 | in 54 | Ui.result_html ~cont_above ~cont_below filename ln hlmatch :: fold ln rest 55 | in 56 | fold (-2) matches 57 | 58 | let present_file ~filename ~start_of_file matches = 59 | let _, matches = 60 | List.fold_left 61 | (fun (previous, acc) m -> 62 | let ofs, lines = present_match ~previous m in 63 | ofs, lines :: acc) 64 | (start_of_file - 1, []) 65 | matches 66 | in 67 | let matches = 68 | List.map (fun (ln, str) -> ln - start_of_file, str) 69 | @@ List.fold_left (fun acc lines -> List.rev_append lines acc) [] matches 70 | in 71 | let header = Ui.link_file filename in 72 | header :: present_line_numbers ~filename matches 73 | 74 | let present_file matches = 75 | match matches with 76 | | [] -> assert false 77 | | hd :: _ -> 78 | let _, start_of_file = Db.fileloc_of_line ~cursor:hd.cursor hd.offset in 79 | present_file ~filename:hd.filename ~start_of_file matches 80 | 81 | let present_results results = 82 | let groups = group_results_by_filename results in 83 | List.concat @@ List.map present_file groups 84 | 85 | let estimated_count ~start ~stop count = 86 | let total = Db.total_lines ~cursor:start in 87 | let upto_stop = 88 | match stop with 89 | | None -> total 90 | | Some stop -> Db.total_lines_upto ~cursor:stop 91 | in 92 | let seen = upto_stop in 93 | if seen < total 94 | then true, total * (start.count + count) / seen 95 | else false, start.count + count 96 | 97 | let pretty_count (is_approx, count) = 98 | let m = 1_000_000 in 99 | let k = 1_000 in 100 | if count / m >= 1 101 | then Printf.sprintf "%.1fm results" (float count /. float m) 102 | else if count / k >= 1 103 | then Printf.sprintf "%.1fk results" (float count /. float k) 104 | else if is_approx 105 | then Printf.sprintf "~%i results" count 106 | else if count = 0 107 | then "no results" 108 | else if count = 1 109 | then "1 result" 110 | else Printf.sprintf "%i results" count 111 | 112 | let more_url query cursor = 113 | "/?q=" ^ Uri.pct_encode ~component:`Query query ^ "&ofs=" ^ Db.string_of_cursor cursor 114 | 115 | let btn_more ~cursor query = 116 | p [ a ~a:[ a_class [ "btn" ]; a_href (more_url query cursor) ] [ txt "More »" ] ] 117 | 118 | let present ~query ~start ~stop results = 119 | let nb_results = List.length results in 120 | let results = present_results results in 121 | let more_link = 122 | match stop with 123 | | None -> [] 124 | | Some cursor -> 125 | let cursor = { cursor with Db.count = start.Db.count + nb_results } in 126 | [ btn_more ~cursor query ] 127 | in 128 | let count = estimated_count ~start ~stop nb_results in 129 | let title = 130 | [ txt (Printf.sprintf "%s for " (pretty_count count)); code [ txt query ] ] 131 | in 132 | div ((h2 title :: results) @ more_link) 133 | -------------------------------------------------------------------------------- /www/search.ml: -------------------------------------------------------------------------------- 1 | open Lwt.Syntax 2 | module Int_set = Db.Int_set 3 | 4 | let max_to_find = 200 5 | 6 | type q = 7 | | QInt_set of Int_set.t 8 | | QTrue 9 | | QFalse 10 | | QAnd of q list 11 | | QOr of q list 12 | 13 | let is_int_set = function 14 | | QInt_set _ -> true 15 | | _ -> false 16 | 17 | let cardinal = function 18 | | QInt_set s -> Int_set.cardinal s 19 | | _ -> assert false 20 | 21 | let sort lst = List.sort (fun a b -> compare (cardinal a) (cardinal b)) lst 22 | 23 | let rec compile ~shard = function 24 | | Regex.True -> QTrue 25 | | False -> QFalse 26 | | Exact str -> 27 | (try QInt_set (Db.find_ngram shard str) with 28 | | Not_found -> 29 | (match String.length str with 30 | | 0 -> QTrue 31 | | 1 when Db.Alphabet.is_alpha str.[0] -> QTrue 32 | | _ -> QFalse)) 33 | | And xs -> 34 | let xs = List.map (compile ~shard) xs in 35 | let xs = List.filter (( <> ) QTrue) xs in 36 | if xs = [] 37 | then QTrue 38 | else if List.mem QFalse xs 39 | then QFalse 40 | else ( 41 | let xs0, xs1 = List.partition is_int_set xs in 42 | QAnd (sort xs0 @ xs1)) 43 | | Or xs -> 44 | let xs = List.map (compile ~shard) xs in 45 | let xs = List.filter (( <> ) QFalse) xs in 46 | if xs = [] 47 | then QFalse 48 | else if List.mem QTrue xs 49 | then QTrue 50 | else ( 51 | let xs0, xs1 = List.partition is_int_set xs in 52 | QOr (sort xs0 @ xs1)) 53 | 54 | let rec query_successor i = function 55 | | QTrue -> i 56 | | QFalse -> raise Not_found 57 | | QAnd [] -> i 58 | | QInt_set bs -> Int_set.successor bs i 59 | | QAnd xs -> 60 | let rec go = function 61 | | [] -> i 62 | | x :: xs -> 63 | let j = query_successor i x in 64 | if j > i then j else go xs 65 | in 66 | go xs 67 | | QOr [] -> raise Not_found 68 | | QOr (x :: xs) -> 69 | let rec go acc = function 70 | | [] -> 71 | (match acc with 72 | | None -> raise Not_found 73 | | Some j -> j) 74 | | x :: xs -> 75 | let j = query_successor_opt i x in 76 | let acc = 77 | match acc, j with 78 | | Some acc, Some j -> Some (min acc j) 79 | | None, t | t, None -> t 80 | in 81 | go acc xs 82 | in 83 | go (query_successor_opt i x) xs 84 | 85 | and query_successor_opt i q = 86 | try Some (query_successor i q) with 87 | | Not_found -> None 88 | 89 | let stream_of_query ~from q = 90 | let shard = ref from in 91 | let go () = 92 | let rec search i = 93 | match query_successor i q with 94 | | j when j = i -> 95 | shard := i + 1 ; 96 | Lwt.return (Some j) 97 | | j -> 98 | let* () = Lwt.pause () in 99 | search j 100 | | exception Not_found -> Lwt.return None 101 | in 102 | search !shard 103 | in 104 | Lwt_stream.from go 105 | 106 | let search ~cursor ~shard query = 107 | let from = cursor.Db.offset in 108 | stream_of_query ~from (compile ~shard query) 109 | 110 | type query = 111 | { regex : Str.regexp 112 | ; ngrams : Regex.query 113 | } 114 | 115 | let query_of_string s = 116 | let q = Regex.parse s in 117 | let regex = Regex.to_regex q in 118 | let ngrams = Regex.to_query q in 119 | { regex; ngrams } 120 | 121 | let is_match query str = 122 | match Str.search_forward query.regex str 0 with 123 | | exception Not_found -> None 124 | | start_at -> 125 | let end_at = Str.match_end () in 126 | Some (start_at, end_at) 127 | 128 | type result = 129 | { line : string 130 | ; range : int * int 131 | ; filename : string 132 | ; line_num : int 133 | ; offset : int 134 | ; cursor : Db.cursor 135 | } 136 | 137 | let search_results ~cursor ~shard query = 138 | let candidates = search ~cursor ~shard query.ngrams in 139 | Lwt_stream.filter_map_s 140 | (fun offset -> 141 | let line = Db.read_line ~cursor offset in 142 | match is_match query line with 143 | | None -> Lwt.return None 144 | | Some (hl_start_at, hl_end_at) -> 145 | let filename, start_of_file = Db.fileloc_of_line ~cursor offset in 146 | let cursor = { cursor with Db.offset } in 147 | let line_num = offset - start_of_file in 148 | let result = 149 | { line; range = hl_start_at, hl_end_at; filename; line_num; offset; cursor } 150 | in 151 | Lwt.return (Some result)) 152 | candidates 153 | 154 | let search_results ~cursor query = 155 | Lwt_stream.concat 156 | @@ Lwt_stream.map (fun (cursor, shard) -> search_results ~cursor ~shard query) 157 | @@ Db.shards_stream ~cursor 158 | 159 | let api ~cursor query = 160 | let query = query_of_string query in 161 | let stream = search_results ~cursor query in 162 | let+ results = Lwt_stream.nget (max_to_find + 1) stream in 163 | let nb_results = List.length results in 164 | let last_cursor, results = 165 | match List.rev results with 166 | | last :: results when nb_results > max_to_find -> 167 | let c = { last.cursor with Db.count = cursor.count + nb_results - 1 } in 168 | Some c, List.rev results 169 | | _ -> None, results 170 | in 171 | results, last_cursor 172 | -------------------------------------------------------------------------------- /www/ui.ml: -------------------------------------------------------------------------------- 1 | open Tyxml.Html 2 | 3 | let link_to url pattern = 4 | a ~a:[ a_class [ "example" ]; a_href url ] [ code [ txt pattern ] ] 5 | 6 | let link_example pattern = 7 | link_to (Uri.to_string @@ Uri.of_string ("/?q=" ^ pattern)) pattern 8 | 9 | let link_file file = h3 [ a ~a:[ a_href (Link.url file 0) ] [ txt file ] ] 10 | 11 | let explain_regex_syntax = 12 | div 13 | [ br () 14 | ; p 15 | [ txt {| The pattern is exact by default. Try |} 16 | ; link_example {|[@@deriving|} 17 | ; txt {| or |} 18 | ; link_example {|List.rev_append (List.rev|} 19 | ; txt " for example." 20 | ] 21 | ; p [ txt {|The antislash \ provides support for regular expressions: |} ] 22 | ; table 23 | [ tr 24 | [ td [ code [ txt "\\." ] ] 25 | ; td [ txt " to match any single character: "; link_example {|.(\.)|} ] 26 | ] 27 | ; tr 28 | [ td [ code [ txt "a\\?" ] ] 29 | ; td 30 | [ txt " to optionally match the character a: " 31 | ; link_example {|fold_left2\? ~f|} 32 | ; txt " or " 33 | ; link_example {|type (\?!'|} 34 | ] 35 | ] 36 | ; tr 37 | [ td [ code [ txt "a\\*" ] ] 38 | ; td [ txt " to match zero or more times: "; link_example {| 1_0\*|} ] 39 | ] 40 | ; tr 41 | [ td [ code [ txt "a\\+" ] ] 42 | ; td [ txt " to match one or more times: "; link_to {|/?q=>\%2B||} ">\\+|" ] 43 | ] 44 | ; tr 45 | [ td [ code [ txt "\\(a\\)" ] ] 46 | ; td [ txt " to group a pattern: "; link_example {|let\( rec\)\? fold_left|} ] 47 | ] 48 | ; tr 49 | [ td [ code [ txt "a\\|b" ] ] 50 | ; td [ txt " to match either a or b: "; link_example {|match\|function|} ] 51 | ] 52 | ; tr 53 | [ td [ code [ txt "\\[aA\\]" ] ] 54 | ; td 55 | [ txt " and ranges " 56 | ; code [ txt "\\[a-z\\]" ] 57 | ; txt " to match a character from a set: " 58 | ; link_example {|(val \[A-Z\]\[a-z_0-9\]\*|} 59 | ] 60 | ] 61 | ; tr 62 | [ td [ code [ txt "\\w" ] ] 63 | ; td 64 | [ txt " is a shortcut for any alphanumeric character " 65 | ; code [ txt "\\[A-Za-z0-9_'\\]" ] 66 | ; txt ". Try " 67 | ; link_example {|| \[A-Z\]\w\* : |} 68 | ; txt " to search for GADTs!" 69 | ] 70 | ] 71 | ] 72 | ] 73 | 74 | let result_html ~cont_above ~cont_below filename line_num hlmatch = 75 | let line_num = line_num + 1 in 76 | let url = Link.url filename line_num in 77 | let classes = 78 | (if cont_below then [] else [ "break_below" ]) 79 | @ if cont_above then [] else [ "break_above" ] 80 | in 81 | div 82 | ~a:[ a_class [ "result" ] ] 83 | [ a ~a:[ a_class ("ln" :: classes); a_href url ] [ txt @@ string_of_int line_num ] 84 | ; code hlmatch 85 | ] 86 | 87 | let explain_indexing = 88 | p 89 | [ txt 90 | {|The search will proceed on all .ml and .mli, stripped of their comments, on either the package release or the git repository where available.|} 91 | ] 92 | 93 | let github_icon = 94 | let open Tyxml.Svg in 95 | Tyxml.Html.svg 96 | ~a:[ a_width (16., None); a_height (16.0, None); a_viewBox (0., 0., 16., 16.) ] 97 | [ path 98 | ~a: 99 | [ a_d 100 | "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 \ 101 | 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 \ 102 | 1.08.58 1.23.82.72 1.21 1.87.87 \ 103 | 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 \ 104 | 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 \ 105 | 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 \ 106 | 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 \ 107 | 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 \ 108 | 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z" 109 | ] 110 | [] 111 | ] 112 | 113 | let link_to_repo = 114 | p 115 | ~a:[ a_class [ "ad" ] ] 116 | [ txt {|(* Read the source, fork and contribute to |} 117 | ; a 118 | ~a:[ a_href "https://github.com/art-w/sherlocode" ] 119 | [ github_icon; txt "art-w/sherlocode" ] 120 | ; txt " *)" 121 | ] 122 | 123 | let sherlodoc_link = 124 | a 125 | ~a: 126 | [ a_href "https://doc.sherlocode.com" 127 | ; a_title "Fuzzy type/name search for OCaml documentation (Hoogle for Odoc)" 128 | ] 129 | [ txt "Sherlodoc" ] 130 | 131 | let sherlocoq_link = 132 | a 133 | ~a: 134 | [ a_href "https://sherlocoq.sirref.org" 135 | ; a_title "Search across Coq libraries available on opam!" 136 | ] 137 | [ txt "Sherlocoq" ] 138 | 139 | let frontpage = 140 | div 141 | [ h1 [ txt "Sherlocode" ] 142 | ; p 143 | ~a:[ a_class [ "hero" ] ] 144 | [ txt "Search across 17 million lines of OCaml available on opam! " 145 | ; span 146 | ~a:[ a_class [ "new" ] ] 147 | [ txt " NEW: also available for Coq with "; sherlocoq_link; txt "!" ] 148 | ] 149 | ; explain_regex_syntax 150 | ; explain_indexing 151 | ; link_to_repo 152 | ] 153 | 154 | let search_form query = 155 | div 156 | ~a:[ a_class [ "header" ] ] 157 | [ form 158 | [ input 159 | ~a: 160 | [ a_input_type `Text 161 | ; a_id "q" 162 | ; a_name "q" 163 | ; a_value query 164 | ; a_placeholder "Search..." 165 | ; a_autofocus () 166 | ; a_autocomplete false 167 | ] 168 | () 169 | ; input ~a:[ a_input_type `Submit; a_value "Search" ] () 170 | ; sherlodoc_link 171 | ; sherlocoq_link 172 | ] 173 | ] 174 | 175 | let ajax_reload = 176 | {js| 177 | var latest = 0; 178 | var current = 0; 179 | document.getElementById('q').addEventListener('input', function(e) { 180 | 181 | var param = encodeURIComponent(e.target.value); 182 | ++latest; 183 | var self = latest; 184 | 185 | var req = new XMLHttpRequest(); 186 | req.onreadystatechange = function() { 187 | if (this.readyState === 4 && current < self) { 188 | current = self; 189 | document.getElementById('results').innerHTML = this.response; 190 | } 191 | }; 192 | req.open('GET', '/api?q=' + param, true); 193 | req.send(); 194 | 195 | var url = param === '' ? '/' : '/?q=' + param; 196 | history.replaceState(null, 'Sherlocode', url); 197 | }); 198 | |js} 199 | 200 | let template query contents = 201 | let open Tyxml.Html in 202 | html 203 | ~a:[ a_lang "en" ] 204 | (head 205 | (title (txt "Sherlocode")) 206 | [ meta ~a:[ a_charset "UTF-8" ] () 207 | ; meta ~a:[ a_name "viewport"; a_content "width=device-width, initial-scale=1" ] () 208 | ; link ~rel:[ `Stylesheet ] ~href:"/s.css" () 209 | ; link ~rel:[ `Icon ] ~href:"favicon.ico" () 210 | ]) 211 | @@ body 212 | [ search_form query 213 | ; script (Unsafe.data ajax_reload) 214 | ; div ~a:[ a_id "results" ] [ contents ] 215 | ] 216 | -------------------------------------------------------------------------------- /www/www.ml: -------------------------------------------------------------------------------- 1 | open Lwt.Syntax 2 | 3 | let api ~cursor query = 4 | let+ results, stop = Search.api ~cursor query in 5 | Present.present ~query ~start:cursor ~stop results 6 | 7 | let api ~cursor query = if query = "" then Lwt.return Ui.frontpage else api ~cursor query 8 | let get_query params = Option.value ~default:"" (Dream.query params "q") 9 | 10 | let get_cursor ~db params = 11 | match Dream.query params "ofs" with 12 | | None -> Db.cursor_empty ~db 13 | | Some shard_offset -> Db.cursor_of_string ~db shard_offset 14 | 15 | let root ~db fn params = 16 | let query = get_query params in 17 | let cursor = get_cursor ~db params in 18 | let* result = fn ~cursor query in 19 | Dream.html result 20 | 21 | let string_of_tyxml html = Format.asprintf "%a" (Tyxml.Html.pp ()) html 22 | let string_of_tyxml' html = Format.asprintf "%a" (Tyxml.Html.pp_elt ()) html 23 | 24 | let cache : int -> Dream.middleware = 25 | fun max_age f req -> 26 | let+ response = f req in 27 | Dream.add_header response "Cache-Control" ("public, max-age=" ^ string_of_int max_age) ; 28 | response 29 | 30 | let webserver ~db ~max_age = 31 | Dream.run ~interface:"127.0.0.1" ~port:8888 32 | @@ Dream.logger 33 | @@ cache max_age 34 | @@ Dream.router 35 | [ Dream.get 36 | "/" 37 | (root ~db (fun ~cursor q -> 38 | let+ result = api ~cursor q in 39 | string_of_tyxml @@ Ui.template q result)) 40 | ; Dream.get 41 | "/api" 42 | (root ~db (fun ~cursor q -> 43 | let+ result = api ~cursor q in 44 | string_of_tyxml' result)) 45 | ; Dream.get "/s.css" (Dream.from_filesystem "static" "style.css") 46 | ; Dream.get "/robots.txt" (Dream.from_filesystem "static" "robots.txt") 47 | ; Dream.get "/favicon.ico" (Dream.from_filesystem "static" "favicon.ico") 48 | ] 49 | 50 | let main path url_tsv max_age = 51 | Link.load url_tsv ; 52 | let source_file = path ^ "/source.txt" in 53 | let ancient_file = path ^ "/ancient.db" in 54 | let db = Db.db_open_in ~source:source_file ~db:ancient_file in 55 | webserver ~db ~max_age 56 | 57 | open Cmdliner 58 | 59 | let path = 60 | let doc = "Directory where the db is available" in 61 | Arg.(required & pos 0 (some dir) None & info [] ~docv:"DB" ~doc) 62 | 63 | let cache_max_age = 64 | let doc = "HTTP cache max age (in seconds)" in 65 | Arg.(value & opt int 3600 & info [ "c"; "cache" ] ~docv:"MAX_AGE" ~doc) 66 | 67 | let url = 68 | let doc = "URL of the sources for each project (tab separated file)" in 69 | Arg.(value & opt file "static/urls.tsv" & info [ "u"; "url" ] ~docv:"MAX_AGE" ~doc) 70 | 71 | let www = Term.(const main $ path $ url $ cache_max_age) 72 | 73 | let cmd = 74 | let doc = "Webserver for sherlocode" in 75 | let info = Cmd.info "www" ~doc in 76 | Cmd.v info www 77 | 78 | let () = exit (Cmd.eval cmd) 79 | --------------------------------------------------------------------------------