Commits

camlspotter  committed 74e0106

first attempt of going back from compile dir for Spot: tag

  • Participants
  • Parent commits 1cf15f4
  • Branches 4.01.0.2.2.0

Comments (0)

Files changed (9)

 name.cmo : name.cmi
 name.cmx : name.cmi
 ocamlspot.cmo : utils.cmi typeexpand.cmi spotfile.cmi spoteval.cmi \
-    spotconfig.cmi spot.cmi ext.cmo command.cmi cmt.cmi
+    spotconfig.cmi spot.cmi filepath.cmi ext.cmo compdir.cmi command.cmi \
+    cmt.cmi
 ocamlspot.cmx : utils.cmx typeexpand.cmx spotfile.cmx spoteval.cmx \
-    spotconfig.cmx spot.cmx ext.cmx command.cmx cmt.cmx
+    spotconfig.cmx spot.cmx filepath.cmx ext.cmx compdir.cmx command.cmx \
+    cmt.cmx
 pathreparse.cmo : utils.cmi spot.cmi locident.cmi ext.cmo pathreparse.cmi
 pathreparse.cmx : utils.cmx spot.cmx locident.cmx ext.cmx pathreparse.cmi
-spot.cmo : spot.cmi
-spot.cmx : spot.cmi
+record.cmo :
+record.cmx :
+spot.cmo : utils.cmi treeset.cmi ext.cmo cmt.cmi checksum.cmo spot.cmi
+spot.cmx : utils.cmx treeset.cmx ext.cmx cmt.cmx checksum.cmx spot.cmi
 spotconfig.cmo : utils.cmi spot.cmi ext.cmo spotconfig.cmi
 spotconfig.cmx : utils.cmx spot.cmx ext.cmx spotconfig.cmi
 spotconfig_intf.cmo : spot.cmi ext.cmo
 Setup
 ============================
 
-If you are Emacs user, see ``ocamlspot.el``. It explains how to set up
-and use it. ``M-x customiize-group`` => ``ocamlspot`` shows majour configurable
-options.
+Emacs users
+---------------
+
+Put ``ocamlspot.el`` somewhere, then edit your ``.emacs``::
+
+     ; load-path
+     (setq load-path (cons "WHERE-YOU-HAVE-INSTALLED-THIS-ELISP" load-path))
+     
+     (require 'ocamlspot)
+     
+     ; tuareg mode hook (use caml-mode-hook instead if you use caml-mode)
+     (add-hook 'tuareg-mode-hook
+       '(lambda ()
+         (local-set-key "\C-c;" 'ocamlspot-query)
+         (local-set-key "\C-c:" 'ocamlspot-query-interface)
+         (local-set-key "\C-c'" 'ocamlspot-query-uses)
+         (local-set-key "\C-c\C-t" 'ocamlspot-type)
+         (local-set-key "\C-c\C-i" 'ocamlspot-xtype)
+         (local-set-key "\C-c\C-y" 'ocamlspot-type-and-copy)
+         (local-set-key "\C-ct" 'caml-types-show-type)
+         (local-set-key "\C-cp" 'ocamlspot-pop-jump-stack)))
+     
+     ; set the path of the ocamlspot binary. If you did make opt, ocamlspot.opt is recommended.
+     (setq ocamlspot-command "WHERE-YOU-HAVE-INSTALLED-THE-BINARIES/ocamlspot")
+     
+     ; Optional: You can also change overlay colors as follows:
+     ;  (set-face-background 'ocamlspot-spot-face "#660000")
+     ;  (set-face-background 'ocamlspot-tree-face "#006600")
+
+
+``M-x customize-group`` => ``ocamlspot`` shows majour configurable options.
+
+Vim users
+-----------
 
 I have also written Vim script ``ocamlspot.vim``, but it is not tested at all.
 Sorry but I do not use Vim.
 
-
 How to use
 ===============================
 
 Compile your OCaml source code with ``-bin-annot`` option, 
 then it should create ``*.cmt`` and ``*.cmti`` files.
 
-Open the source code in your Emacs and move the cursor to an identifier
+Emacs users: Open the source code in your Emacs and move the cursor to an identifier
 usage, then type ``C-c ;``. If things are properly installed and set up,
 Emacs should display the definition of the identifier.
 
+Vim users: ...
+
 If something goes wrong
 ---------------------------------------------------------------------------
 
 * set OPAMKEEPBUILDDIR to keep your source code and ``.cmt*`` files
 * use ``spotinstall`` to install ``.cmt*`` files along with other object files.
 
+OCamlSpotter with multiple OCaml versions
+---------------------------------------------------
+
+OCamlSpotter is compiler version dependent. So, each version of OCaml compiler,
+the corresponding OCamlSpotter is required.
+
+Changing automatically from one to another OCamlSpotter, OPAM users may want to
+specify the following shell script as a wrapper. Change the OCamlSpotter location
+of your favorite editor config to this.::
+
+    #!/bin/sh
+    
+    # This is a sample shell script which tries to call the corresponding OCamlSpotter
+    # with the current OPAM switch.
+    
+    DIR=`opam config var bin`
+    
+    if [ -x $DIR/ocamlspot.opt ]; then 
+      $DIR/ocamlspot.opt $*
+    else 
+      if [ -x $DIR/ocamlspot ]; then 
+        $DIR/ocamlspot $*
+      else 
+        echo "ERROR: No ocamlspot.opt or ocamlspot found at $DIR"
+      fi
+    fi
+
 Reporting bugs
 ==============================
 
 
 module FP = Filepath
 
+let rec find_dot_ocamlspot fp = 
+  let open FP in
+  match
+    if Unix.is_dir (FP.to_string (fp ^/ "_build")) then Some (fp, "_build")
+    else
+      let dot_ocamlspot = fp ^/ ".ocamlspot" in
+      if Sys.file_exists (FP.to_string dot_ocamlspot) then
+        match (Dotfile.load (FP.to_string dot_ocamlspot)).Dotfile.build_dir with
+        | Some dir -> Some (fp, dir)
+        | None -> None
+      else None
+  with
+  | (Some _ as res) -> res
+  | None ->
+      if FP.is_root fp then None
+      else match FP.dirbase fp with
+      | dir, Some _ -> find_dot_ocamlspot dir
+      | _ -> None
+
 let comp_dir fp0 =
-  assert (FP.is_absolute fp0);
-  let rec f bases fp = 
-    let dir = FP.to_string fp in
-
-    let fix () =
-      let dot_ocamlspot = 
-        let dot_ocamlspot_path = dir ^/ ".ocamlspot" in
-        if Sys.file_exists dot_ocamlspot_path then
-          match (Dotfile.load dot_ocamlspot_path).Dotfile.build_dir with
-          | (Some _ as res) -> res
-          | None -> None
-        else None
-      in
-      match dot_ocamlspot with
-      | (Some _ as res) -> res
-      | None ->
-          let ocamlbuild_path = dir ^/ "_build" in
-          if Unix.is_dir ocamlbuild_path then Some "_build"
-          else None
-    in
-    match fix () with
-    | Some p -> Some (FP.(^/) fp (Filename.concats (p :: bases)))
-    | None -> 
-        if FP.is_root fp then Some fp0
-        else match FP.dirbase fp with
-        | dir, Some base -> f (base :: bases) dir
-        | _ -> assert false
-  in
-  Option.default (f [] fp0) (fun () -> fp0)
+  if not  (FP.is_absolute fp0) then fp0
+  else
+    match find_dot_ocamlspot fp0 with
+    | None -> fp0
+    | Some (dir, mv) ->
+        match FP.contains_abs dir fp0 with
+        | None -> fp0
+        | Some postfixes ->
+            match FP.contains_abs (FP.(^/) dir mv) fp0 with
+            | Some _ -> fp0 (* already in the comp dir *)
+            | None -> 
+                (* CR jfuruse: inefficient *)
+                FP.of_string (Filename.concats (FP.to_string dir :: mv :: postfixes))
 
 let comp_dir x =
   let y = comp_dir x in
-  Format.eprintf "comp_dir: %s => %s@." (FP.to_string x) (FP.to_string y);
+  if not (FP.equal x y) then
+    Format.eprintf "comp_dir: %s => %s@." (FP.to_string x) (FP.to_string y);
   y
 
 let comp_dir = Hashtbl.memoize (Hashtbl.create 107) comp_dir
 
 let src_dir fp0 =
-  assert (FP.is_absolute fp0);
+  if not (FP.is_absolute fp0) then fp0
+  else
+    match find_dot_ocamlspot fp0 with
+    | None -> fp0
+    | Some (dir, mv) ->
+        match FP.contains_abs (FP.(^/) dir mv) fp0 with
+        | None -> fp0
+        | Some postfixes -> 
+            (* CR jfuruse: inefficient *)
+            FP.of_string (Filename.concats (FP.to_string dir :: postfixes))
 
-  Debug.format "Compdir.src_dir: %s@." (FP.to_string fp0);
-
-  let rec f dirs fp = 
-    match FP.dirbase fp with
-    | dir, Some "_build" -> FP.(^/) dir (Filename.concats dirs)
-    | _, None -> fp0
-    | dir, Some x -> f (x::dirs) dir
-  in
-  
-  let res = f [] fp0 in
-  Debug.format "Compdir.src_dir => %s@." (FP.to_string res); 
-  res
+let src_dir x =
+  let y = src_dir x in
+  if not (FP.equal x y) then
+    Format.eprintf "src_dir: %s => %s@." (FP.to_string x) (FP.to_string y);
+  y
 
 let src_dir = Hashtbl.memoize (Hashtbl.create 107) src_dir
 (***********************************************************************)
 
 (** ocamlbuild compilation directory tweak *)
+
 val comp_dir : Filepath.t -> Filepath.t
+(** ocaml/camlp4/Camlp4Bin.ml => ocaml/_build/camlp4/Camlp4Bin.ml *)
+
 val src_dir : Filepath.t -> Filepath.t
+(** ocaml/_build/camlp4/Camlp4Bin.ml => ocaml/camlp4/Camlp4Bin.ml *)
 
 let compare t1 t2 = if equal t1 t2 then 0 else compare t1 t2
 
+let contains_abs (b1,dir) (b2,f) =
+  assert (b1 && b2);
+  let dir = List.rev dir in
+  let f = List.rev f in
+  let rec loop dir f = match dir, f with
+    | [], fs -> Some fs
+    | d::ds, f::fs when d = f -> loop ds fs
+    | _::_, _ -> None
+  in
+  loop dir f
+
+let () = 
+  assert (contains_abs (true, ["c"; "b"; "a"]) (true, ["e"; "d"; "c"; "b"; "a"]) =
+      Some ["d"; "e"])
+
 let of_string path = 
   let abs, xs = split path in
   abs, rev_normalize [] abs xs

File filepath.mli

 val compare : t -> t -> int
 val equal : t -> t -> bool
 
+val contains_abs : t -> t -> string list option
+(** contains_abs /a/b/c /a/b/c/d/e = Some ["d"; "e"] 
+    Only works for absolute paths
+*)
+
 val of_string : string -> t
 val to_string : t -> string
 val is_absolute : t -> bool

File ocamlspot.el

 ;      (require 'ocamlspot)
 ;     
 ;     ; tuareg mode hook (use caml-mode-hook instead if you use caml-mode)
-;        (add-hook 'tuareg-mode-hook
+;      (add-hook 'tuareg-mode-hook
 ;              '(lambda ()
 ;                 (local-set-key "\C-c;" 'ocamlspot-query)
 ;      	     (local-set-key "\C-c:" 'ocamlspot-query-interface)
 ;                 (local-set-key "\C-c\C-t" 'ocamlspot-type)
 ;                 (local-set-key "\C-c\C-i" 'ocamlspot-xtype)
 ;                 (local-set-key "\C-c\C-y" 'ocamlspot-type-and-copy)
-;                 (local-set-key "\C-cx" 'ocamlspot-expand)
-;                 (local-set-key "\C-c\C-u" 'ocamlspot-use)
 ;                 (local-set-key "\C-ct" 'caml-types-show-type)
 ;                 (local-set-key "\C-cp" 'ocamlspot-pop-jump-stack)))
 ;     
 ;     ; set the path of the ocamlspot binary. If you did make opt, ocamlspot.opt is recommended.
 ;      (setq ocamlspot-command "WHERE-YOU-HAVE-INSTALLED-THE-BINARIES/ocamlspot")
 ;     
-;     ; You can also change overlay colors as follows:
-;      (set-face-background 'ocamlspot-spot-face "#660000")
-;      (set-face-background 'ocamlspot-tree-face "#006600")
+;     ; Optional: You can also change overlay colors as follows:
+;     ;  (set-face-background 'ocamlspot-spot-face "#660000")
+;     ;  (set-face-background 'ocamlspot-tree-face "#006600")
 ;
 ;
 ; # Setup

File ocamlspot.ml

   (* CR jfuruse: In the case of a.mll => a.ml => a.cmt,
      a.ml often does not exist. ocamlspot should warn you when a.ml
      does not exist and propose creation of a.ml from a.mll. *)
+  module FP = Filepath
   let print_query_result kind = function
     | None -> printf "Spot: no spot@."
     | Some (pident, res) -> match res with
 	| File.File_itself ->
-            printf "Spot: <%s:all>@." pident.PIdent.path
+            let path = FP.to_string (Compdir.src_dir (FP.of_string pident.PIdent.path)) in
+            printf "Spot: <%s:all>@." path
 	| File.Found_at (path, region) ->
+            let path = FP.to_string (Compdir.src_dir (FP.of_string path)) in
             printf "Spot: <%s:%s>@."
               path
               (Region.to_string region)
 
 	(* Tree is an older format. XTree is a newer which is the same as one for Spot *)
         printf "Tree: %s@." (Region.to_string r);
-        (* Beware, the search target and file.Unit.path may be different *)
+
+        (* Beware, the search target and file.Unit.path may be different.
+           If _build dir is used, XTree points source file copied inside _build dir. 
+           ocamlspot.el does not use XTree but Tree, so it is ok.
+        *)
         printf "XTree: <%s:%s>@." file.Unit.path (Region.to_string r);
 
 	(* Find the innermost module *)

File tests/dot_ocamlspot/Makefile

-test: build/hello.cmo
+test: build/hello.cmo build/dir/dir2/bye.cmo
 	../../ocamlspot hello.ml:l5c8
 	../../ocamlspot dir/dir2/bye.ml:l2c12