Skip to content

Commit

Permalink
refactor: formatting helpers
Browse files Browse the repository at this point in the history
* inline most heplers as they are only used once.
* give more precise types to the function that does the action

Signed-off-by: Rudi Grinberg <[email protected]>
  • Loading branch information
rgrinberg committed May 7, 2022
1 parent 06c32bd commit 84f4ab8
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 46 deletions.
9 changes: 7 additions & 2 deletions bin/dune_init.ml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module File = struct
let content =
if not (Path.exists full_path) then []
else
match Dune_lang.Format.parse_file (Some full_path) with
match Io.with_lexbuf_from_file ~f:Dune_lang.Format.parse full_path with
| Dune_lang.Format.Sexps content -> content
| Dune_lang.Format.OCaml_syntax _ ->
User_error.raise
Expand All @@ -152,7 +152,12 @@ module File = struct
let version =
Dune_lang.Syntax.greatest_supported_version Dune_engine.Stanza.syntax
in
Dune_lang.Format.write_file ~version ~path dune_file.content
Io.with_file_out ~binary:true
(* Why do we pass [~binary:true] but not anywhere else when formatting? *)
path ~f:(fun oc ->
let fmt = Format.formatter_of_out_channel oc in
Format.fprintf fmt "%a%!" Pp.to_fmt
(Dune_lang.Format.pp_top_sexps ~version dune_file.content))

let write f =
let path = full_path f in
Expand Down
22 changes: 21 additions & 1 deletion bin/format_dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@ let man =

let info = Term.info "format-dune-file" ~doc ~man

let format_file ~version ~input =
let with_input =
match input with
| Some path -> fun f -> Io.with_lexbuf_from_file path ~f
| None ->
fun f ->
Exn.protect
~f:(fun () -> f (Lexing.from_channel stdin))
~finally:(fun () -> close_in_noerr stdin)
in
match with_input Dune_lang.Format.parse with
| Sexps sexps ->
Format.fprintf Format.std_formatter "%a%!" Pp.to_fmt
(Dune_lang.Format.pp_top_sexps ~version sexps)
| OCaml_syntax loc -> (
match input with
| None -> User_error.raise ~loc [ Pp.text "OCaml syntax is not supported." ]
| Some path ->
Io.with_file_in path ~f:(fun ic -> Io.copy_channels ic stdout))

let term =
let+ path_opt =
let docv = "FILE" in
Expand All @@ -28,6 +48,6 @@ let term =
Arg.(value & opt version default & info [ "dune-version" ] ~docv ~doc)
in
let input = Option.map ~f:Arg.Path.path path_opt in
Dune_lang.Format.format_file ~version ~input ~output:None
format_file ~version ~input

let command = (term, info)
3 changes: 1 addition & 2 deletions src/dune_engine/action_exec.ml
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,7 @@ let rec exec t ~ectx ~eenv =
| No_infer t -> exec t ~ectx ~eenv
| Pipe (outputs, l) -> exec_pipe ~ectx ~eenv outputs l
| Format_dune_file (version, src, dst) ->
Dune_lang.Format.format_file ~version ~input:(Some src)
~output:(Some (Path.build dst));
Dune_lang.Format.format_action ~version ~src ~dst;
Fiber.return Done
| Cram script ->
let+ () =
Expand Down
36 changes: 7 additions & 29 deletions src/dune_lang/format.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ type dune_file =
| OCaml_syntax of Loc.t
| Sexps of Cst.t list

let parse_lexbuf lb =
let parse lb =
if Dune_lexer.is_script lb then OCaml_syntax (Loc.of_lexbuf lb)
else Sexps (Parser.parse lb ~mode:Cst)

let parse_file path_opt =
match path_opt with
| Some path -> Io.with_lexbuf_from_file path ~f:parse_lexbuf
| None -> parse_lexbuf @@ Lexing.from_channel stdin

let can_be_displayed_wrapped =
List.for_all ~f:(fun (c : Cst.t) ->
match c with
Expand Down Expand Up @@ -66,35 +61,18 @@ let pp_top_sexp ~version sexp = pp_sexp ~version sexp ++ Pp.char '\n'
let pp_top_sexps ~version =
Pp.concat_map ~sep:Pp.newline ~f:(pp_top_sexp ~version)

let write_file ~version ~path sexps =
let f oc =
let fmt = Format.formatter_of_out_channel oc in
Format.fprintf fmt "%a%!" Pp.to_fmt (pp_top_sexps ~version sexps)
in
Io.with_file_out ~binary:true path ~f

let format_string ~version input =
match parse_lexbuf (Lexing.from_string input) with
match parse (Lexing.from_string input) with
| OCaml_syntax _ ->
User_error.raise [ Pp.text "OCaml syntax is not supported." ]
| Sexps sexps ->
Format.asprintf "%a%!" Pp.to_fmt (pp_top_sexps ~version sexps)

let format_file ~version ~input ~output =
let with_output f =
match output with
| None -> f stdout
| Some output -> Io.with_file_out output ~f
in
match parse_file input with
| OCaml_syntax loc -> (
match input with
| Some path ->
Io.with_file_in path ~f:(fun ic ->
with_output (fun oc -> Io.copy_channels ic oc))
| None -> User_error.raise ~loc [ Pp.text "OCaml syntax is not supported." ]
)
let format_action ~version ~src ~dst =
let dst = Path.build dst in
match Io.with_lexbuf_from_file src ~f:parse with
| OCaml_syntax _ -> Io.copy_file ~src ~dst ()
| Sexps sexps ->
with_output (fun oc ->
Io.with_file_out dst ~f:(fun oc ->
let oc = Format.formatter_of_out_channel oc in
Format.fprintf oc "%a%!" Pp.to_fmt (pp_top_sexps ~version sexps))
16 changes: 4 additions & 12 deletions src/dune_lang/format.mli
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,11 @@ type dune_file =

val format_string : version:Syntax.Version.t -> string -> string

(** Read a file into its concrete syntax *)
val parse_file : Path.t option -> dune_file
val parse : Lexing.lexbuf -> dune_file

(** Write the formatted concrete syntax to the file at [path] *)
val write_file : version:Syntax.Version.t -> path:Path.t -> Cst.t list -> unit

(** Reformat a dune file. [None] in [input] corresponds to stdin. [None] in
[output] corresponds to stdout. *)
val format_file :
version:Syntax.Version.t
-> input:Path.t option
-> output:Path.t option
-> unit
(** Reformat a dune file in a dune action *)
val format_action :
version:Syntax.Version.t -> src:Path.t -> dst:Path.Build.t -> unit

(** Pretty-print a list of toplevel s-expressions *)
val pp_top_sexps : version:Syntax.Version.t -> Cst.t list -> _ Pp.t

0 comments on commit 84f4ab8

Please sign in to comment.