Skip to content

Commit

Permalink
refactor: scopes in refmt command (#2836)
Browse files Browse the repository at this point in the history
  • Loading branch information
anmonteiro authored Feb 23, 2025
1 parent ee1333c commit b0af457
Showing 1 changed file with 90 additions and 89 deletions.
179 changes: 90 additions & 89 deletions src/refmt/refmt.ml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
(*
* Copyright (c) 2015-present, Facebook, Inc.
(* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
*)

module Cmdliner = Vendored_cmdliner
open Cmdliner
Expand Down Expand Up @@ -105,99 +104,101 @@ let refmt
(* FIXME: Reason_syntax_util.report_error Format.err_formatter exn; *)
exit 1

let split_lines s =
let rec loop ~last_is_cr ~acc i j =
if j = String.length s
then
let acc =
if j = i || (j = i + 1 && last_is_cr)
then acc
else String.sub s i (j - i) :: acc
let () =
let examples =
let split_lines s =
let rec loop ~last_is_cr ~acc i j =
if j = String.length s
then
let acc =
if j = i || (j = i + 1 && last_is_cr)
then acc
else String.sub s i (j - i) :: acc
in
List.rev acc
else
match s.[j] with
| '\r' -> loop ~last_is_cr:true ~acc i (j + 1)
| '\n' ->
let line =
let len = if last_is_cr then j - i - 1 else j - i in
String.sub s i len
in
loop ~acc:(line :: acc) (j + 1) (j + 1) ~last_is_cr:false
| _ -> loop ~acc i (j + 1) ~last_is_cr:false
in
List.rev acc
else
match s.[j] with
| '\r' -> loop ~last_is_cr:true ~acc i (j + 1)
| '\n' ->
let line =
let len = if last_is_cr then j - i - 1 else j - i in
String.sub s i len
loop ~acc:[] 0 0 ~last_is_cr:false
in
let[@tail_mod_cons] rec concat_map f = function
| [] -> []
| x :: xs -> prepend_concat_map (f x) f xs
and[@tail_mod_cons] prepend_concat_map ys f xs =
match ys with
| [] -> concat_map f xs
| y :: ys -> y :: prepend_concat_map ys f xs
in
function
| [] -> `Blocks []
| _ :: _ as examples ->
let block_of_example index (intro, ex) =
let prose = `I (string_of_int (index + 1) ^ ".", String.trim intro ^ ":")
and code_lines =
ex
|> String.trim
|> split_lines
|> concat_map (fun codeline ->
[ `Noblank; `Pre (" " ^ codeline) ])
(* suppress initial blank *)
|> List.tl
in
loop ~acc:(line :: acc) (j + 1) (j + 1) ~last_is_cr:false
| _ -> loop ~acc i (j + 1) ~last_is_cr:false
`Blocks (prose :: code_lines)
in
let example_blocks = examples |> List.mapi block_of_example in
`Blocks (`S "EXAMPLES" :: example_blocks)
in
loop ~acc:[] 0 0 ~last_is_cr:false

let[@tail_mod_cons] rec concat_map f = function
| [] -> []
| x :: xs -> prepend_concat_map (f x) f xs

and[@tail_mod_cons] prepend_concat_map ys f xs =
match ys with
| [] -> concat_map f xs
| y :: ys -> y :: prepend_concat_map ys f xs

let examples = function
| [] -> `Blocks []
| _ :: _ as examples ->
let block_of_example index (intro, ex) =
let prose = `I (string_of_int (index + 1) ^ ".", String.trim intro ^ ":")
and code_lines =
ex
|> String.trim
|> split_lines
|> concat_map (fun codeline -> [ `Noblank; `Pre (" " ^ codeline) ])
(* suppress initial blank *)
|> List.tl
let refmt_t =
let top_level_info =
let doc = "Reason's Parser & Pretty-printer" in
let man =
[ `S "DESCRIPTION"
; `P
"refmt lets you format Reason files, parse them, and convert them \
between OCaml syntax and Reason syntax."
; examples
[ "Initialise a new project named `foo'", "dune init project foo"
; "Format a Reason implementation file", "refmt file.re"
; "Format a Reason interface file", "refmt file.rei"
; ( "Format interface code from the command line"
, "echo 'let x: int' | refmt --interface=true" )
; "Convert an OCaml file to Reason", "refmt file.ml"
; "Convert a Reason file to OCaml", "refmt file.re --print ml"
; ( "Convert OCaml from the command line to Reason"
, "echo 'let x = 1' | refmt --parse ml" )
]
]
in
`Blocks (prose :: code_lines)
let version =
"Reason " ^ Package.version ^ " @ " ^ Package.git_short_version
in
Cmd.info "refmt" ~version ~doc ~man
in
let example_blocks = examples |> List.mapi block_of_example in
`Blocks (`S "EXAMPLES" :: example_blocks)

let top_level_info =
let doc = "Reason's Parser & Pretty-printer" in
let man =
[ `S "DESCRIPTION"
; `P
"refmt lets you format Reason files, parse them, and convert them \
between OCaml syntax and Reason syntax."
; examples
[ "Initialise a new project named `foo'", "dune init project foo"
; "Format a Reason implementation file", "refmt file.re"
; "Format a Reason interface file", "refmt file.rei"
; ( "Format interface code from the command line"
, "echo 'let x: int' | refmt --interface=true" )
; "Convert an OCaml file to Reason", "refmt file.ml"
; "Convert a Reason file to OCaml", "refmt file.re --print ml"
; ( "Convert OCaml from the command line to Reason"
, "echo 'let x = 1' | refmt --parse ml" )
]
]
in
let version =
"Reason " ^ Package.version ^ " @ " ^ Package.git_short_version
in
Cmd.info "refmt" ~version ~doc ~man

let refmt_t =
let open Term in
let open Refmt_args in
let term =
const refmt
$ interface
$ recoverable
$ explicit_arity
$ parse_ast
$ print
$ print_width
$ heuristics_file
$ in_place
$ input
let open Term in
let open Refmt_args in
let term =
const refmt
$ interface
$ recoverable
$ explicit_arity
$ parse_ast
$ print
$ print_width
$ heuristics_file
$ in_place
$ input
in
Cmd.v top_level_info (Term.ret term)
in
Cmd.v top_level_info (Term.ret term)

let () =
match Cmd.eval_value' refmt_t with
| `Exit 0 -> exit 0
| `Exit _ -> exit 1
Expand Down

0 comments on commit b0af457

Please sign in to comment.