Skip to content

Commit

Permalink
Add command wrapping ocamlformat (ocaml#10929)
Browse files Browse the repository at this point in the history
Adds a command `dune tools exec ocamlformat` which downloads and
builds ocamlformat as a dev tool before running it, passing all
positional arguments to the ocamlformat executable. This is intended
to be run by text editors.

Signed-off-by: Stephen Sherratt <stephen@sherra.tt>
  • Loading branch information
gridbugs authored Nov 1, 2024
1 parent 87f7775 commit 3ac95e5
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 1 deletion.
61 changes: 61 additions & 0 deletions bin/tools/ocamlformat.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
open! Import
module Pkg_dev_tool = Dune_rules.Pkg_dev_tool

let exe_path = Path.build @@ Pkg_dev_tool.exe_path Ocamlformat
let exe_name = Pkg_dev_tool.exe_name Ocamlformat

let run_dev_tool workspace_root ~args =
let exe_path_string = Path.to_string exe_path in
Console.print_user_message
(Dune_rules.Pkg_build_progress.format_user_message
~verb:"Running"
~object_:(User_message.command (String.concat ~sep:" " (exe_name :: args))));
Console.finish ();
restore_cwd_and_execve
workspace_root
exe_path_string
(exe_path_string :: args)
Env.initial
;;

let dev_tool_exe_exists () = Path.exists exe_path

let build_dev_tool common =
match dev_tool_exe_exists () with
| true ->
(* Avoid running the build system if the executable already exists
to reduce unnecessary latency in the common case. *)
Fiber.return ()
| false ->
let open Fiber.O in
let+ result =
Build_cmd.run_build_system ~common ~request:(fun _build_system ->
Action_builder.path exe_path)
in
(match result with
| Error `Already_reported -> raise Dune_util.Report_error.Already_reported
| Ok () -> ())
;;

let term =
let+ builder = Common.Builder.term
and+ args = Arg.(value & pos_all string [] (info [] ~docv:"ARGS")) in
let common, config = Common.init builder in
Scheduler.go ~common ~config (fun () ->
let open Fiber.O in
let* () = Lock_dev_tool.lock_ocamlformat () |> Memo.run in
let+ () = build_dev_tool common in
run_dev_tool (Common.root common) ~args)
;;

let info =
let doc =
{|Wrapper for running ocamlformat intended to be run automatically
by a text editor. All positional arguments will be passed to the
ocamlformat executable (pass flags to ocamlformat after the '--'
argument, such as 'dune ocamlformat -- --help').|}
in
Cmd.info "ocamlformat" ~doc
;;

let command = Cmd.v info term
3 changes: 3 additions & 0 deletions bin/tools/ocamlformat.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
open! Import

val command : unit Cmd.t
2 changes: 1 addition & 1 deletion bin/tools/tools.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ open! Import
module Exec = struct
let doc = "Command group for running wrapped tools."
let info = Cmd.info ~doc "exec"
let group = Cmd.group info [ Ocamllsp.command ]
let group = Cmd.group info [ Ocamlformat.command; Ocamllsp.command ]
end

let doc = "Command group for wrapped tools."
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Exercise running the ocamlformat wrapper command.

$ . ./helpers.sh
$ mkrepo

$ make_fake_ocamlformat "0.26.2"
$ make_ocamlformat_opam_pkg "0.26.2"
$ make_project_with_dev_tool_lockdir

$ dune tools exec ocamlformat
Solution for dev-tools.locks/ocamlformat:
- ocamlformat.0.26.2
Running 'ocamlformat'
formatted with version 0.26.2

0 comments on commit 3ac95e5

Please sign in to comment.