From 8af1ceebe6e8b6f69fd3da7942d789214f8b6a6b Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Tue, 29 Sep 2015 12:50:21 +0200 Subject: [PATCH 1/9] Read include directories from .ocp-index --- src/indexMisc.ml | 10 +++++++++- src/indexMisc.mli | 2 ++ src/indexOptions.ml | 24 ++++++++++++++++++------ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/indexMisc.ml b/src/indexMisc.ml index eee8666..3c3b7e6 100644 --- a/src/indexMisc.ml +++ b/src/indexMisc.ml @@ -110,12 +110,20 @@ let unique_subdirs ?(skip = fun _ -> false) dir_list = in remove_dups (List.fold_left subdirs [] dir_list) +let read_all_lines path = + let ic = open_in path in + let rec loop acc = + match input_line ic with + | l -> loop (l :: acc) + | exception End_of_file -> close_in ic; acc + in + loop [] (* - Project root finding - *) let build_roots = (* by increasing order of priority *) [ "_darcs"; ".hg"; ".git"; - "jengaroot.ml"; "omakeroot"; "_build"; "_obuild" ] + "jengaroot.ml"; "omakeroot"; "_build"; "_obuild"; ".ocp-index" ] let find_build_dir path = let ( / ) = Filename.concat in diff --git a/src/indexMisc.mli b/src/indexMisc.mli index df74234..fe777d1 100644 --- a/src/indexMisc.mli +++ b/src/indexMisc.mli @@ -43,6 +43,8 @@ val parent_type: IndexTypes.info -> IndexTypes.info option If directory basename verifies [skip], it is not descended nor returned. *) val unique_subdirs: ?skip:(string -> bool) -> string list -> string list +val read_all_lines: string -> string list + (** An heuristic to guess where the root directory of the current project. Returns (project_root, build_dir) *) val project_root: ?path:string -> unit -> string option * string option diff --git a/src/indexOptions.ml b/src/indexOptions.ml index d5b5d18..7b99c09 100644 --- a/src/indexOptions.ml +++ b/src/indexOptions.ml @@ -84,7 +84,7 @@ let common_opts ?(default_filter = default_filter) () : t Term.t = Arg.(value & flag & info ["no-opamlib"] ~doc); in let arg = - let doc = "OCaml directories to (recursively) load the libraries from." in + let doc = "OCaml directories to load the libraries from." in Arg.(value & opt_all (list string) [] & info ["I"] ~docv:"DIRS" ~doc) in let set_default no_stdlib no_opamlib includes = @@ -99,6 +99,10 @@ let common_opts ?(default_filter = default_filter) () : t Term.t = in Term.(pure set_default $ no_stdlib $ no_opamlib $ arg) in + let no_recursive : bool Term.t = + let doc = "Do not traverse include directories recursively." in + Arg.(value & flag & info ["no-recursive"] ~doc) + in let color : bool Term.t = let arg = let choices = Arg.enum [ "always", `Always; @@ -245,14 +249,22 @@ let common_opts ?(default_filter = default_filter) () : t Term.t = Arg.(value & opt (some filepos_converter) None & info ["context"] ~docv:"FILEPOS" ~doc) in - let lib_info ocamllib (_root,build) (opens,full_opens) context = + let lib_info ocamllib no_recursive (root,build) (opens,full_opens) context = let dirs = match build with | None -> ocamllib | Some d -> d :: ocamllib in + let dirs = match root with + | Some root when Sys.file_exists (Filename.concat root ".ocp-index") -> + dirs @ List.map (fun dir -> Filename.concat root dir) (IndexMisc.read_all_lines (Filename.concat root ".ocp-index")) + | _ -> dirs + in if dirs = [] then failwith "Failed to guess OCaml / opam lib dirs. Please use `-I'"; - let dirs = LibIndex.Misc.unique_subdirs dirs in + IndexMisc.debug "Scanning directories... "; + let chrono = IndexMisc.timer () in + let dirs = if no_recursive then dirs else LibIndex.Misc.unique_subdirs dirs in + IndexMisc.debug "%.3fs\n%!" (chrono ()); let info = LibIndex.load dirs in let info = List.fold_left (LibIndex.open_module ~cleanup_path:true) info opens @@ -281,8 +293,8 @@ let common_opts ?(default_filter = default_filter) () : t Term.t = in Term.( pure - (fun ocamllib project_dirs opens color filter context -> - { lib_info = lib_info ocamllib project_dirs opens context; + (fun ocamllib no_recursive project_dirs opens color filter context -> + { lib_info = lib_info ocamllib no_recursive project_dirs opens context; color; filter; project_root = fst project_dirs }) - $ ocamllib $ project_dirs $ open_modules $ color $ filter $ context + $ ocamllib $ no_recursive $ project_dirs $ open_modules $ color $ filter $ context ) From 4c16414461115a4fda662623108e42f354809573 Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Fri, 2 Oct 2015 09:27:03 +0200 Subject: [PATCH 2/9] Compile with 4.01. --- src/indexMisc.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/indexMisc.ml b/src/indexMisc.ml index 3c3b7e6..63ee26c 100644 --- a/src/indexMisc.ml +++ b/src/indexMisc.ml @@ -112,12 +112,12 @@ let unique_subdirs ?(skip = fun _ -> false) dir_list = let read_all_lines path = let ic = open_in path in - let rec loop acc = - match input_line ic with - | l -> loop (l :: acc) - | exception End_of_file -> close_in ic; acc + let acc = ref [] in + let rec loop () = + let l = input_line ic in + acc := l :: !acc in - loop [] + try loop (); assert false with End_of_file -> !acc (* - Project root finding - *) From 3b42abecca6ddff619efa53047f908a7779e9275 Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Fri, 2 Oct 2015 09:28:11 +0200 Subject: [PATCH 3/9] Fix typo. --- src/indexOptions.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indexOptions.ml b/src/indexOptions.ml index 7b99c09..d2d1fd6 100644 --- a/src/indexOptions.ml +++ b/src/indexOptions.ml @@ -65,7 +65,7 @@ let default_filter = [ `V ; `E ; `C ; `M ; `K ] let filter_to_string l = let pp = function - | `V -> "v" | `E -> "b" | `C -> "c" + | `V -> "v" | `E -> "e" | `C -> "c" | `M -> "m" | `K -> "k" | `S -> "s" | `T -> "t" in From eb4e76467b31513b4c322614c7cb3151a8cf5804 Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Fri, 2 Oct 2015 09:36:46 +0200 Subject: [PATCH 4/9] Fix man page. --- src/indexMain.ml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/indexMain.ml b/src/indexMain.ml index f15cd8e..bb32a58 100644 --- a/src/indexMain.ml +++ b/src/indexMain.ml @@ -19,6 +19,18 @@ open Cmdliner let common_opts = IndexOptions.common_opts () +let man = [ + `S "COPYRIGHT"; + `P "Ocp-index is written by Louis Gesbert , \ + copyright OCamlPro 2013-2014, \ + distributed under the terms of the LGPL v3 with linking exception. \ + Full source available at $(i,https://github.com/OCamlPro/ocp-index)"; + `S "BUGS"; + `P "Bugs are tracked at $(i,https://github.com/OCamlPro/ocp-index/issues)."; + `S "SEE ALSO"; + `P "ocp-grep, ocp-browser"; +] + let default_cmd = let man = [ `S "DESCRIPTION"; @@ -27,7 +39,7 @@ let default_cmd = It gathers information from .cmi (like ocamlbrowser) and \ .cmt/cmti files, including structure, location, type, and ocamldoc \ comments when available." - ] + ] @ man in let doc = "Explore the interfaces of installed OCaml libraries." in Term.(ret (pure (fun _ -> `Help (`Pager, None)) $ common_opts)), @@ -59,18 +71,6 @@ let format_man = interpreted:" ] @ List.map (fun (k, s) -> `I (Printf.sprintf "$(b,%s)" k, s)) formats -let man = [ - `S "COPYRIGHT"; - `P "Ocp-index is written by Louis Gesbert , \ - copyright OCamlPro 2013-2014, \ - distributed under the terms of the LGPL v3 with linking exception. \ - Full source available at $(i,https://github.com/OCamlPro/ocp-index)"; - `S "BUGS"; - `P "Bugs are tracked at $(i,https://github.com/OCamlPro/ocp-index/issues)."; - `S "SEE ALSO"; - `P "ocp-grep, ocp-browser"; -] - let complete_cmd = let man = [ `S "DESCRIPTION"; From f2ee9435409a1f2512b7cb77b7f7efcafd26808c Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Fri, 2 Oct 2015 19:00:20 +0200 Subject: [PATCH 5/9] WIP. --- src/indexMain.ml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/indexMain.ml b/src/indexMain.ml index bb32a58..aab67e1 100644 --- a/src/indexMain.ml +++ b/src/indexMain.ml @@ -38,7 +38,12 @@ let default_cmd = OCaml, for command-line or integrated use (e.g. for completion). \ It gathers information from .cmi (like ocamlbrowser) and \ .cmt/cmti files, including structure, location, type, and ocamldoc \ - comments when available." + comments when available."; + `S "USING AN .ocp-index FILE"; + `P "Instead of passing a list of include directories using the \ + $(b,`-I') option, it is also possible to pass them using a \ + file named $(b, .ocp-index) placed at the root of the project \ + directory. It should be" ] @ man in let doc = "Explore the interfaces of installed OCaml libraries." in From 21fbaa33dad32caf363550f0a174ece10903e3db Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Mon, 5 Oct 2015 10:21:40 +0200 Subject: [PATCH 6/9] Doc. --- src/indexMain.ml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/indexMain.ml b/src/indexMain.ml index aab67e1..623fde1 100644 --- a/src/indexMain.ml +++ b/src/indexMain.ml @@ -40,10 +40,17 @@ let default_cmd = .cmt/cmti files, including structure, location, type, and ocamldoc \ comments when available."; `S "USING AN .ocp-index FILE"; - `P "Instead of passing a list of include directories using the \ - $(b,`-I') option, it is also possible to pass them using a \ - file named $(b, .ocp-index) placed at the root of the project \ - directory. It should be" + `P "It is possible to specify some of the options for ocp-index in a file \ + called $(b, .ocp-index) placed at the root of the project directory. \ + Currently only the list of include directories can be specified in this way. \ + Each line of the .ocp-index file should be of the form"; + `P "I "; + `P "where is the name of a directory where ocp-index should look for \ + .cmt[i] files. Typically this way of specifying include directories would \ + be used in conjunction with the $(b,--no-recursive) options in order to \ + speed up directory scanning in those environments where the default \ + method is not fast enough (e.g. Cygwin). One can generate such a file by running"; + `P "find . -name '*.cmt*' -exec dirname {} \\\\; | sort | uniq > .ocp-index" ] @ man in let doc = "Explore the interfaces of installed OCaml libraries." in From 166167b5b726a9a8ebf07b890243c71a31dad326 Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Mon, 5 Oct 2015 10:46:56 +0200 Subject: [PATCH 7/9] Fix. --- src/indexMain.ml | 9 +++++---- src/indexMisc.ml | 11 ++++++----- src/indexOptions.ml | 18 ++++++++++++++---- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/indexMain.ml b/src/indexMain.ml index 623fde1..cb30546 100644 --- a/src/indexMain.ml +++ b/src/indexMain.ml @@ -44,13 +44,14 @@ let default_cmd = called $(b, .ocp-index) placed at the root of the project directory. \ Currently only the list of include directories can be specified in this way. \ Each line of the .ocp-index file should be of the form"; - `P "I "; - `P "where is the name of a directory where ocp-index should look for \ - .cmt[i] files. Typically this way of specifying include directories would \ + `P "I \"\""; + `P "where \"\" is the name of a directory (between double quotes) \ + where ocp-index should look for .cmt[i] files. Typically this way \ + of specifying include directories would \ be used in conjunction with the $(b,--no-recursive) options in order to \ speed up directory scanning in those environments where the default \ method is not fast enough (e.g. Cygwin). One can generate such a file by running"; - `P "find . -name '*.cmt*' -exec dirname {} \\\\; | sort | uniq > .ocp-index" + `P "find . -name '*.cmt*' -exec dirname {} \\\\; | sort | uniq | sed 's/.*/I \"&\"/g' > .ocp-index" ] @ man in let doc = "Explore the interfaces of installed OCaml libraries." in diff --git a/src/indexMisc.ml b/src/indexMisc.ml index 63ee26c..3f19ec3 100644 --- a/src/indexMisc.ml +++ b/src/indexMisc.ml @@ -113,11 +113,12 @@ let unique_subdirs ?(skip = fun _ -> false) dir_list = let read_all_lines path = let ic = open_in path in let acc = ref [] in - let rec loop () = - let l = input_line ic in - acc := l :: !acc - in - try loop (); assert false with End_of_file -> !acc + try + while true do + acc := input_line ic :: !acc + done; + assert false + with End_of_file -> !acc (* - Project root finding - *) diff --git a/src/indexOptions.ml b/src/indexOptions.ml index d2d1fd6..aa78a1c 100644 --- a/src/indexOptions.ml +++ b/src/indexOptions.ml @@ -254,10 +254,20 @@ let common_opts ?(default_filter = default_filter) () : t Term.t = | None -> ocamllib | Some d -> d :: ocamllib in - let dirs = match root with - | Some root when Sys.file_exists (Filename.concat root ".ocp-index") -> - dirs @ List.map (fun dir -> Filename.concat root dir) (IndexMisc.read_all_lines (Filename.concat root ".ocp-index")) - | _ -> dirs + let dirs = + let extra_dirs = match root with + | Some root -> + let make_absolute path = if Filename.is_relative path then Filename.concat root path else path in + let dot_ocp_index = Filename.concat root ".ocp-index" in + if Sys.file_exists dot_ocp_index then begin + let l = IndexMisc.read_all_lines dot_ocp_index in + List.map (fun s -> Scanf.sscanf s "I %S" make_absolute) l + end + else + [] + | _ -> [] + in + dirs @ extra_dirs in if dirs = [] then failwith "Failed to guess OCaml / opam lib dirs. Please use `-I'"; From 797c6bf5e27b93d361ef724bf8a4ee506d7a4fdb Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Mon, 5 Oct 2015 10:50:05 +0200 Subject: [PATCH 8/9] Fix man. --- src/indexOptions.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/indexOptions.ml b/src/indexOptions.ml index aa78a1c..e5e35ca 100644 --- a/src/indexOptions.ml +++ b/src/indexOptions.ml @@ -84,7 +84,9 @@ let common_opts ?(default_filter = default_filter) () : t Term.t = Arg.(value & flag & info ["no-opamlib"] ~doc); in let arg = - let doc = "OCaml directories to load the libraries from." in + let doc = "OCaml directories to load the libraries from. \ + By default, the directories are traversed recursively. \ + This can be changed by passing the $(b,--no-recursive) option." in Arg.(value & opt_all (list string) [] & info ["I"] ~docv:"DIRS" ~doc) in let set_default no_stdlib no_opamlib includes = From 1c7727cc5d1f12e8905243174754ff510d0acc88 Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Mon, 5 Oct 2015 10:51:24 +0200 Subject: [PATCH 9/9] Cleanup. --- src/indexOptions.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indexOptions.ml b/src/indexOptions.ml index e5e35ca..3237dad 100644 --- a/src/indexOptions.ml +++ b/src/indexOptions.ml @@ -267,7 +267,7 @@ let common_opts ?(default_filter = default_filter) () : t Term.t = end else [] - | _ -> [] + | None -> [] in dirs @ extra_dirs in