camlspotter avatar camlspotter committed d6bf8c4

fix

Comments (0)

Files changed (5)

+let paths, debug, lines, showstate, cursor =
+  let rev_paths = ref [] in
+  let debug = ref false in
+  let lines = ref None in
+  let showstate = ref false in
+  let cursor = ref None in
+  Arg.parse [
+    ("-debug", Arg.Set debug, "debugging");
+    ("-lines", Arg.String (fun s ->
+      try
+        let pos = String.index s '-' in
+        let (start,end_) = (int_of_string (String.sub s 0 pos),
+                            int_of_string (String.sub s (pos+1) (String.length s - pos - 1))) in
+        if start <= 0 || end_ <= 0 || start > end_ then
+          failwith (Printf.sprintf "Wrong -lines specification: %s" s);
+        lines := Some (start, end_)
+      with
+      | _ -> failwith (Printf.sprintf "Wrong -lines specification: %s" s)),
+     "lines, ex. 10-12") ;
+    ("-cursor", Arg.String (fun s ->
+      try
+        let pos = String.index s ':' in
+        let (rows,cols) = (int_of_string (String.sub s 0 pos),
+                           int_of_string (String.sub s (pos+1) (String.length s - pos - 1))) in
+        if rows <= 0 || cols < 0 then
+          failwith (Printf.sprintf "Wrong -cursor specification: %s" s);
+        cursor := Some (rows, cols)
+      with
+      | _ -> failwith (Printf.sprintf "Wrong -cursor specification: %s" s)),
+     "cursor position, ex. 10:12") ;
+    ("-show-state", Arg.Set showstate, "show state at the last");
+  ] (fun s -> rev_paths := s :: !rev_paths) "indent paths";
+  let paths = List.rev !rev_paths in
+  let paths = if paths = [] then [""] else paths in (* CR jfuruse: ugly *)
+  begin match paths, !lines with
+  | [], _ -> assert false
+  | [_], _ -> ()
+  | _, Some _ -> failwith "Region can be specified with at most one file"
+  | _ -> ()
+  end;
+  paths, !debug, !lines, !showstate, !cursor
   | Some (i, _) when Region.lnum i.Tokenstr.region <> lnum -> false
   | Some (i, str) ->
       match i.Tokenstr.token with
-      | None | Some COMMENT -> lparen_read_ahead lnum str
-      | Some FUN -> false
-      | Some FUNCTION -> false
+      | COMMENT -> lparen_read_ahead lnum str
+      | FUN -> false
+      | FUNCTION -> false
       | _ -> true
 
 let rec lbrace_read_ahead lnum str =
   | Some (i, _) when Region.lnum i.Tokenstr.region <> lnum -> false
   | Some (i, str) ->
       match i.Tokenstr.token with
-      | None | Some COMMENT -> lparen_read_ahead lnum str
+      | COMMENT -> lparen_read_ahead lnum str
       | _ -> true
 
 let lbracket_read_ahead = lbrace_read_ahead
 open Pos
 open Machine
-
 open Args
 
-let check_lines l = function
+module Sexp = Sexplib.Sexp (* No open Sexplib, since Parser corrides with Sexplib.Parser *)
+
+(** [l] is in the interested area or not? *)
+let check_line l = function
   | None -> `Inside
   | Some (start, end_) ->
       if l < start then `Before
       else if l <= end_ then `Inside
       else `Over
 
-module Printer = struct
+module Printer : sig
+  type t = (int * int) option
+  val add_debug  : t -> int-> string -> unit
+  val add_string : t -> int -> string -> unit
+end = struct
 
   type t = (int * int) option
 
-  let add_debug t lnum s = match check_lines lnum t with
+  let add_debug t lnum s = match check_line lnum t with
     | `Before | `Over -> ()
     | `Inside -> print_string s
 
   (** Print a string [s] for the line number [lnum].
       If the printing text exceeds the interested region,
-      It stops printing and raises Exit
+      It stops printing.
 
       Currently it cannot print a string correctly if it has 
       different number of lines from the original. 
   *)
   let add_string t lnum s =
-    let add_line t lnum s = match check_lines lnum t with
+    let add_line t lnum s = match check_line lnum t with
       | `Before -> ()
       | `Over -> raise Exit
       | `Inside -> print_string s
       | Some s -> iter (lnum+1) s
       | None -> ()
     in
-    iter lnum s
+    try iter lnum s with Exit -> ()
 
 end
 
+open Tokenstr
+
 let indent_file path =
-  let printer = lines in
   let str = if path = "" then Tokenstr.of_channel stdin else Tokenstr.of_path path in
 
+  let flush_remaining_space info =
+    ignore (Printer.add_string lines (Region.lnum (fst info.space)) (snd info.space))
+  in
+
   let rec loop last_orig_region state str = match Tokenstr.destr str with
     | None -> state
 
-    | Some (({ Tokenstr.token = None } as i), str) ->
-        (* The token is white space *)
- 
+    | Some (({ token = Parser.EOF } as info), _) -> 
+        flush_remaining_space info;
+        state
 
-    | Some (({Tokenstr.token = Parser.EOF} as i), _) -> state
+    | Some (({ token = t; 
+               region = orig_region; 
+               space = (_space_between_region, space_between); 
+               substr } as info), str) ->
 
-    | Some ({ Tokenstr.token = t; region = orig_region; 
-              space = (space_between_region, space_between); substr }, str) ->
-
-        let last_line = Region.lnum last_orig_region in
-        let current_line = Region.lnum orig_region in
-        let new_line = last_line <>  current_line in (* Is this token at a new line? *)
-
-        (* Where the cursor move *)
-        let _cursor_info = match cursor with
-          | None -> None
-          | Some lines_cols ->
-              match
-                Pos.Region.contain_lines_cols last_orig_region lines_cols,
-                Pos.Region.contain_lines_cols orig_region lines_cols
-              with
-              | (`In | `Right), _ -> None (* far past *)
-              | `Left, `Right -> None (* far future *)
-              | `Left, `Left -> (* cursor in the space_between *)
-                  Some `In_space_between 
-              | `Left, `In -> (* cursor on the token *)
-                  Some `In_the_token
-              | _ -> assert false (* It must be more tolerant, but for now... *)
-        in
-
-        match check_lines (Region.lnum orig_region) lines with
+        match check_line (Region.lnum orig_region) lines with
         | `Over -> 
             (* The token is outside of our interest. 
                Print the remaining things and go out *)
-            (try Printer.add_string printer (Region.lnum space_between_region) space_between with Exit -> ());
+            flush_remaining_space info;
             state
         | (`Before | `Inside as line_status) -> 
             (*
               Format.eprintf "<%s %d>@."
             *)
 
+            let last_line = Region.lnum last_orig_region in
+            let current_line = Region.lnum orig_region in
+            let new_line = last_line <>  current_line in (* Is this token at a new line? *)
+    
+            (* Where the cursor move *)
+            let _cursor_info = match cursor with
+              | None -> None
+              | Some lines_cols ->
+                  match
+                    Pos.Region.contain_lines_cols last_orig_region lines_cols,
+                    Pos.Region.contain_lines_cols orig_region lines_cols
+                  with
+                  | (`In | `Right), _ -> None (* far past *)
+                  | `Left, `Right -> None     (* far future *)
+                  | `Left, `Left ->           (* cursor in the space_between *)
+                      Some `In_space_between 
+                  | `Left, `In ->             (* cursor on the token *)
+                      Some `In_the_token
+                  | _ -> assert false         (* It must be more tolerant, but for now... *)
+            in
+
             let state =
               if new_line then { state with State.orig_indent = Region.columns orig_region } else state
             in
               let indent_string = String.make (State.indent pre) ' ' in
 
               (* CR jfuruse: can be a bug. something from space_between_region *)
-              Printer.add_string printer last_line spaces;
+              Printer.add_string lines last_line spaces;
 
               if debug then begin
-                Printer.add_string printer current_line indent_string;
+                Printer.add_string lines current_line indent_string;
                 if pre == post then
-                  Printer.add_debug printer current_line
-                    (Printf.sprintf "-- %s\n" (Sexplib.Sexp.to_string_mach (Stack.sexp_of_t pre.State.bases)))
+                  Printer.add_debug lines current_line
+                    (Printf.sprintf "-- %s\n" (Sexp.to_string_mach (Stack.sexp_of_t pre.State.bases)))
                 else
-                  Printer.add_debug printer current_line
+                  Printer.add_debug lines current_line
                     (Printf.sprintf "-- %s // %s\n"
-                      (Sexplib.Sexp.to_string_mach (Stack.sexp_of_t pre.State.bases))
-                      (Sexplib.Sexp.to_string_mach (Stack.sexp_of_t post.State.bases)))
+                      (Sexp.to_string_mach (Stack.sexp_of_t pre.State.bases))
+                      (Sexp.to_string_mach (Stack.sexp_of_t post.State.bases)))
               end;
 
-              Printer.add_string printer current_line indent_string;
-              Printer.add_string printer current_line substr
+              Printer.add_string lines current_line indent_string;
+              Printer.add_string lines current_line substr
             end else begin
-              Printer.add_string printer current_line space_between;
-              Printer.add_string printer current_line substr;
+              Printer.add_string lines current_line space_between;
+              Printer.add_string lines current_line substr;
             end;
 
             (* Now move to the next token *)
               if new_line then
                 { post with
                   State.last_token = (if t <> Parser.COMMENT then Some t else state.State.last_token)
-                ; last_indent = State.indent pre
+                  ; last_indent = State.indent pre
                 }
               else
                 { post with
 and 'a t = 'a desc lazy_t
 
 type 'a info = {
-  token : 'a option; (* None means white space *)
+  token : 'a;
   region : Region.t;
   substr : string;
+  space : Region.t * string;
 }
 
 let close = function
       (* token's string *)
       let substr = LexReader.current_substring reader in
 
-      let space =
-        let space_between = 
-          let last_end = (snd last_region).Position.pos_cnum in
-          LexReader.substring 
-            reader last_end ((fst region).Position.pos_cnum - last_end)
-        in
-        if space_between = "" then None
-        else Some { token = None; 
-                    region = (snd last_region, fst region);
-                    substr = space_between }
+      let space_between = 
+        let last_end = (snd last_region).Position.pos_cnum in
+        LexReader.substring 
+          reader last_end ((fst region).Position.pos_cnum - last_end)
       in
+      let space_between_region = (snd last_region, fst region) in
 
-      let l = 
-        Cons ({ token = Some token ; region; substr },
-              begin match token with
-              | EOF -> 
-                  let null = Lazy.lazy_from_val (Null icoptref) in
-                  close null;
-                  null
-              | _ -> lazy (loop region)
-              end,
-              icoptref)
-      in
-      match space with
-      | None -> l
-      | Some space -> Cons ( space, Lazy.lazy_from_val l, icoptref )
+      Cons ({ token; region; substr; space = space_between_region, space_between },
+            begin match token with
+            | EOF -> 
+                let null = Lazy.lazy_from_val (Null icoptref) in
+                close null;
+                null
+            | _ -> lazy (loop region)
+            end,
+            icoptref)
     in
     lazy (loop Region.zero)
   with
 type 'a t
 
 type 'a info = {
-  token : 'a option; (** None means whilte space *)
+  token : 'a;
   region : Pos.Region.t;
   substr : string;
+  space : Pos.Region.t * string
 }
 
 val of_channel : in_channel -> Parser.token info t
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.