diff --git a/bin/tools/group.ml b/bin/tools/group.ml index 17d216dd21a..5fb8a14b2fb 100644 --- a/bin/tools/group.ml +++ b/bin/tools/group.ml @@ -33,4 +33,7 @@ end let doc = "Command group for wrapped tools." let info = Cmd.info ~doc "tools" -let group = Cmd.group info [ Exec.group; Install.group; Which.group ] + +let group = + Cmd.group info [ Exec.group; Install.group; Which.group; Tools_common.env_command ] +;; diff --git a/bin/tools/tools_common.ml b/bin/tools/tools_common.ml index 4ed3dd2c413..85adc3e9e60 100644 --- a/bin/tools/tools_common.ml +++ b/bin/tools/tools_common.ml @@ -1,10 +1,13 @@ open! Import module Pkg_dev_tool = Dune_rules.Pkg_dev_tool +let dev_tool_bin_dirs = + List.map Pkg_dev_tool.all ~f:(fun tool -> + Pkg_dev_tool.exe_path tool |> Path.Build.parent_exn |> Path.build) +;; + let add_dev_tools_to_path env = - List.fold_left Pkg_dev_tool.all ~init:env ~f:(fun acc tool -> - let dir = Pkg_dev_tool.exe_path tool |> Path.Build.parent_exn |> Path.build in - Env_path.cons acc ~dir) + List.fold_left dev_tool_bin_dirs ~init:env ~f:(fun acc dir -> Env_path.cons acc ~dir) ;; let dev_tool_exe_path dev_tool = Path.build @@ Pkg_dev_tool.exe_path dev_tool @@ -137,3 +140,40 @@ let exec_command dev_tool = in Cmd.v info term ;; + +let env_command = + let term = + let+ builder = Common.Builder.term + and+ fish = + Arg.( + value + & flag + & info [ "fish" ] ~doc:"Print command for the fish shell rather than POSIX shells") + in + let _ : Common.t * Dune_config.t = Common.init builder in + if fish + then ( + let space_separated_dev_tool_paths = + List.map dev_tool_bin_dirs ~f:Path.to_string_maybe_quoted + |> String.concat ~sep:" " + in + print_endline (sprintf "fish_add_path --prepend %s" space_separated_dev_tool_paths)) + else ( + let initial_path = Env.get Env.initial Env_path.var in + let new_path = + List.fold_left dev_tool_bin_dirs ~init:initial_path ~f:(fun acc bin_dir -> + Some (Bin.cons_path bin_dir ~_PATH:acc)) + in + match new_path with + | None -> () + | Some new_path -> print_endline (sprintf "export %s=%s" Env_path.var new_path)) + in + let info = + let doc = + "Print a command which can be eval'd to enter an environment where all dev tools \ + are runnable as commands." + in + Cmd.info "env" ~doc + in + Cmd.v info term +;; diff --git a/bin/tools/tools_common.mli b/bin/tools/tools_common.mli index bcdefc44f51..3009caad76c 100644 --- a/bin/tools/tools_common.mli +++ b/bin/tools/tools_common.mli @@ -13,3 +13,4 @@ val lock_build_and_run_dev_tool val which_command : Dune_pkg.Dev_tool.t -> unit Cmd.t val install_command : Dune_pkg.Dev_tool.t -> unit Cmd.t val exec_command : Dune_pkg.Dev_tool.t -> unit Cmd.t +val env_command : unit Cmd.t diff --git a/test/blackbox-tests/test-cases/pkg/ocamllsp/dev-tool-ocamllsp-basic.t b/test/blackbox-tests/test-cases/pkg/ocamllsp/dev-tool-ocamllsp-basic.t index 689bd044a22..7335aff74bc 100644 --- a/test/blackbox-tests/test-cases/pkg/ocamllsp/dev-tool-ocamllsp-basic.t +++ b/test/blackbox-tests/test-cases/pkg/ocamllsp/dev-tool-ocamllsp-basic.t @@ -30,3 +30,9 @@ a lockdir containing an "ocaml" lockfile. - ocaml-lsp-server.0.0.1 Running 'ocamllsp' hello from fake ocamllsp + +Make sure that after evaling the output of 'dune tools env', the first ocamllsp +executable in PATH is the one installed by dune as a dev tool. + $ DUNE_CONFIG__LOCK_DEV_TOOL=enabled eval $(dune tools env) + $ which ocamllsp + $TESTCASE_ROOT/_build/_private/default/.dev-tool/ocaml-lsp-server/ocaml-lsp-server/target/bin/ocamllsp