Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read include directories from .ocp-index #79

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 27 additions & 14 deletions src/indexMain.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,40 @@ open Cmdliner

let common_opts = IndexOptions.common_opts ()

let man = [
`S "COPYRIGHT";
`P "Ocp-index is written by Louis Gesbert <[email protected]>, \
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";
`P "ocp-index is a simple and light-weight documentation extractor for \
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 "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 \"<dir>\"";
`P "where \"<dir>\" 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 | sed 's/.*/I \"&\"/g' > .ocp-index"
] @ man
in
let doc = "Explore the interfaces of installed OCaml libraries." in
Term.(ret (pure (fun _ -> `Help (`Pager, None)) $ common_opts)),
Expand Down Expand Up @@ -59,18 +84,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 <[email protected]>, \
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";
Expand Down
11 changes: 10 additions & 1 deletion src/indexMisc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,21 @@ 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 acc = ref [] in
try
while true do
acc := input_line ic :: !acc
done;
assert false
with End_of_file -> !acc

(* - 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
Expand Down
2 changes: 2 additions & 0 deletions src/indexMisc.mli
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 31 additions & 7 deletions src/indexOptions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 (recursively) 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 =
Expand All @@ -99,6 +101,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;
Expand Down Expand Up @@ -245,14 +251,32 @@ 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 =
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
[]
| None -> []
in
dirs @ extra_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
Expand Down Expand Up @@ -281,8 +305,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
)