Source

ocaml-indent / main.ml

camlspotter 4aed057 
camlspotter 2b713d1 

camlspotter 341a5a9 
camlspotter d6bf8c4 


camlspotter c4779f8 

camlspotter d6bf8c4 
camlspotter 4f0aaaf 
camlspotter c4779f8 
camlspotter 2db6c9a 

camlspotter fd613df 
camlspotter 69ca6e2 

camlspotter d6bf8c4 
camlspotter 69ca6e2 
camlspotter 2b713d1 

camlspotter 69ca6e2 
camlspotter 2b713d1 
camlspotter c4779f8 
camlspotter 2db6c9a 


camlspotter 4f0aaaf 

camlspotter 2db6c9a 
camlspotter 4f0aaaf 
camlspotter 2db6c9a 
camlspotter 4f0aaaf 



camlspotter 2db6c9a 
camlspotter 4f0aaaf 





camlspotter d6bf8c4 
camlspotter 4f0aaaf 
camlspotter 2db6c9a 

camlspotter d6bf8c4 
camlspotter c4779f8 
camlspotter d6bf8c4 
camlspotter 2db6c9a 
camlspotter c4779f8 

camlspotter 2b713d1 
camlspotter c4779f8 

camlspotter 52b49b7 
camlspotter d6bf8c4 
camlspotter 2b713d1 
camlspotter d6bf8c4 

camlspotter c4779f8 

camlspotter 5287834 
camlspotter c4779f8 
camlspotter d6bf8c4 

camlspotter 69ca6e2 
camlspotter c4779f8 




camlspotter d31e732 
camlspotter c4779f8 
camlspotter 2b713d1 

camlspotter 6a6cb74 
camlspotter d6bf8c4 
camlspotter 2db6c9a 
camlspotter 2b713d1 
camlspotter 2db6c9a 


camlspotter d31e732 
camlspotter d6bf8c4 

camlspotter 2b713d1 







camlspotter d6bf8c4 
camlspotter c4779f8 
camlspotter d6bf8c4 


camlspotter 2b713d1 

camlspotter d6bf8c4 
camlspotter 2b713d1 




camlspotter 2db6c9a 







camlspotter 2b713d1 

camlspotter 2db6c9a 

camlspotter 2b713d1 

camlspotter 2db6c9a 



camlspotter 69ca6e2 
camlspotter 2b713d1 
camlspotter 2db6c9a 
camlspotter c4779f8 
camlspotter 2b713d1 
camlspotter 2db6c9a 
camlspotter 2b713d1 
camlspotter d6bf8c4 
camlspotter 2db6c9a 
camlspotter 2b713d1 
camlspotter 2db6c9a 
camlspotter d6bf8c4 

camlspotter 2db6c9a 

camlspotter 2b713d1 
camlspotter 2db6c9a 

camlspotter 2b713d1 

camlspotter 2db6c9a 
camlspotter 2b713d1 

camlspotter 17697e6 
camlspotter 2b713d1 



camlspotter 2db6c9a 



camlspotter c4779f8 


camlspotter fd613df 
camlspotter c4779f8 
open Pos
module State = Machine.State
module Stack = Machine.Stack

module Sexp = Sexplib.Sexp (* No open Sexplib, since Parser corrides with Sexplib.Parser *)

module Printer : sig
  val print_debug  : Lines.t -> int-> string -> unit
  val print_string : Lines.t -> int -> string -> unit
end = struct

  let print_debug t lnum s = match Lines.is_between 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.

      Currently it cannot print a string correctly if it has
      different number of lines from the original.
  *)
  let print_string t lnum s =
    let add_line t lnum s = match Lines.is_between lnum t with
      | `Before -> ()
      | `Over -> raise Exit
      | `Inside -> print_string s
    in
    let get_line s =
      try
        let pos = String.index s '\n' in
        String.sub s 0 (pos + 1),
        Some (String.sub s (pos + 1) (String.length s - pos - 1))
      with
      | Not_found -> s, None
    in
    let rec iter lnum s =
      let line, rest =  get_line s in
      add_line t lnum line;
      match rest with
      | Some s -> iter (lnum+1) s
      | None -> ()
    in
    try iter lnum s with Exit -> ()

end

open Tokenstr
open Planck.Lazylist

let indent_file path =
  let print_string = Printer.print_string Args.lines in
  let print_debug  = Printer.print_debug  Args.lines in

  let tkstr = if path = "" then Tokenstr.of_channel stdin else Tokenstr.of_path path in
  let stream = stream tkstr in

  let flush_remaining_space info =
    print_string (Region.lnum (fst info.space)) (snd info.space)
  in

  let rec loop last_orig_region state = function
    | lazy Null _ -> state

    | lazy Cons (({ token = Parser.EOF } as info), _, _) ->
        flush_remaining_space info;
        state

    | lazy Cons (({ token = t;
                    region = orig_region;
                    space = (_space_between_region, space_between);
                    substr } as info), 
                 _, str) ->

        match Lines.is_between (Region.lnum orig_region) Args.lines with
        | `Over ->
            (* The token is outside of our interest.
               Print the remaining things and go out *)
            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 at_new_line = last_line <>  current_line in (* Is this token at a new line? *)

            (* update the original indent if [at_new_line] *)
            let state =
              if at_new_line then { state with State.orig_indent = Region.columns orig_region }
              else state
            in

            (* Where the cursor move *)
            let _cursor_info = match Args.cursor with
              | None -> None
              | Some lines_cols ->
                  match
                    Region.contain_lines_cols last_orig_region lines_cols,
                    Region.contain_lines_cols orig_region lines_cols
                  with
                  | (`In | `Right), _ -> None                   (* far past *)
                  | `Left, `Right     -> None                   (* far future *)
                  | `Left, `Left      -> Some `In_space_between (* cursor in the space_between *)
                  | `Left, `In        -> Some `In_the_token     (* cursor on the token *)
                  | _                 -> assert false           (* It must be more tolerant, but for now... *)
            in

            let fix_indent = match line_status with
              | `Inside -> true
              | `Before -> false
              | `Over -> assert false
            in

            let pre, post = Machine.update_state state ~at_new_line ~fix_indent str orig_region t in

            (* printing *)

            if not at_new_line then print_string current_line space_between
            else begin
              (* the line 1 has no previous new line char *)
              let spaces = try String.sub space_between 0 (String.rindex space_between '\n' + 1) with _ -> "" in
              let indent_string = String.make (State.indent pre) ' ' in

              (* CR jfuruse: can be a bug. something from space_between_region *)
              print_string last_line spaces;

              if Args.debug then begin
                print_string current_line indent_string;
                if pre == post then
                  print_debug current_line
                    (Printf.sprintf "-- %s\n" (Sexp.to_string_mach (Stack.sexp_of_t pre.State.bases)))
                else
                  print_debug current_line
                    (Printf.sprintf "-- %s // %s\n"
                      (Sexp.to_string_mach (Stack.sexp_of_t pre.State.bases))
                      (Sexp.to_string_mach (Stack.sexp_of_t post.State.bases)))
              end;

              print_string current_line indent_string;
            end;

            print_string current_line substr;

            (* Now move to the next token *)
            (* CR jfuruse: last_token thing seems strange. The state machine should be able to
               access previous tokens freely. (But with risk of memory leak) *)
            let last_token = match t with Parser.COMMENT _ -> state.State.last_token | _ ->  Some t in
            let post = 
              { post with 
                State.last_token = last_token; 
                last_indent = if at_new_line then State.indent pre else post.State.last_indent }
            in

            loop orig_region post str
  in
  let final_state = loop Region.zero State.init stream in
  if Args.showstate then State.print final_state;
  Tokenstr.close tkstr

let () = List.iter indent_file Args.paths