Skip to content

Commit

Permalink
merlin: replace get/set context with flag
Browse files Browse the repository at this point in the history
Signed-off-by: Javier Chávarri <javier.chavarri@gmail.com>
  • Loading branch information
jchavarri committed Apr 8, 2024
1 parent ac73fa3 commit ac96149
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 72 deletions.
70 changes: 15 additions & 55 deletions bin/ocaml/ocaml_merlin.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Server : sig
(** Once started the server will wait for commands on stdin, read the
requested merlin dot file and return its content on stdout. The server
will halt when receiving EOF of a bad csexp. *)
val start : unit -> unit Fiber.t
val start : ctx_name:Context_name.t -> unit -> unit Fiber.t
end = struct
open Fiber.O

Expand All @@ -27,12 +27,6 @@ end = struct
| File of string
| Halt
| Unknown of string
| GetContexts
| SetContext of string

type selected_ctxt =
| Default
| Custom of Context_name.t

let read_input in_channel =
match Csexp.input_opt in_channel with
Expand All @@ -42,8 +36,6 @@ end = struct
(match sexp with
| Atom "Halt" -> Halt
| List [ Atom "File"; Atom path ] -> File path
| List [ Atom "GetContexts" ] -> GetContexts
| List [ Atom "SetContext"; Atom name ] -> SetContext name
| sexp ->
let msg = Printf.sprintf "Bad input: %s" (Sexp.to_string sexp) in
Unknown msg)
Expand Down Expand Up @@ -137,84 +129,48 @@ end = struct
|> error
;;

let to_local ~selected_context file =
let to_local ~ctx_name file =
match to_local file with
| Error s -> Fiber.return (Error s)
| Ok file ->
let module Context_name = Dune_engine.Context_name in
(match selected_context with
| Commands.Custom ctxt ->
Fiber.return (Ok (Path.Build.append_local (Context_name.build_dir ctxt) file))
| Default ->
let+ workspace = Memo.run (Workspace.workspace ()) in
(match workspace.merlin_context with
| None -> Error "no merlin context configured"
| Some context ->
Ok (Path.Build.append_local (Context_name.build_dir context) file)))
Fiber.return (Ok (Path.Build.append_local (Context_name.build_dir ctx_name) file))
;;

let print_merlin_conf ~selected_context file =
to_local ~selected_context file
let print_merlin_conf ~ctx_name file =
to_local ~ctx_name file
>>| (function
| Error s -> Merlin_conf.make_error s
| Ok file -> load_merlin_file file)
>>| Merlin_conf.to_stdout
;;

let dump s =
to_local ~selected_context:Default s
to_local ~ctx_name:Context_name.default s
>>| function
| Error mess -> Printf.eprintf "%s\n%!" mess
| Ok path -> get_merlin_files_paths path |> List.iter ~f:Merlin.Processed.print_file
;;

let dump_dot_merlin s =
to_local ~selected_context:Default s
to_local ~ctx_name:Context_name.default s
>>| function
| Error mess -> Printf.eprintf "%s\n%!" mess
| Ok path ->
let files = get_merlin_files_paths path in
Merlin.Processed.print_generic_dot_merlin files
;;

let start () =
let selected_context = ref Commands.Default in
let start ~ctx_name () =
let rec main () =
match Commands.read_input stdin with
| Halt -> Fiber.return ()
| File path ->
let* () = print_merlin_conf ~selected_context:!selected_context path in
let* () = print_merlin_conf ~ctx_name path in
main ()
| Unknown msg ->
Merlin_conf.to_stdout (Merlin_conf.make_error msg);
main ()
| GetContexts ->
let open Fiber.O in
let* setup = Import.Main.setup () in
let* setup = Memo.run setup in
let ctxts =
List.map
~f:(fun (name, _) -> Sexp.Atom (Context_name.to_string name))
(Context_name.Map.to_list setup.scontexts)
in
Merlin_conf.to_stdout Sexp.(List ctxts);
main ()
| SetContext name ->
let open Fiber.O in
let* setup = Import.Main.setup () in
let* setup = Memo.run setup in
let () =
let open Merlin_conf in
match Context_name.of_string_opt name with
| None -> to_stdout (make_error (Printf.sprintf "Invalid context name %S" name))
| Some ctxt_name ->
(match Context_name.Map.mem setup.scontexts ctxt_name with
| false ->
to_stdout
(make_error (Printf.sprintf "Can't find context with name %S" name))
| true -> selected_context := Custom ctxt_name)
in
main ()
in
main ()
;;
Expand Down Expand Up @@ -262,15 +218,19 @@ let man =
let start_session_info name = Cmd.info name ~doc ~man

let start_session_term =
let+ builder = Common.Builder.term in
let+ builder = Common.Builder.term
and+ ctx_name =
Common.context_arg
~doc:{|The Dune context in which the command will return information for.|}
in
let common, config =
let builder =
let builder = Common.Builder.forbid_builds builder in
Common.Builder.disable_log_file builder
in
Common.init builder
in
Scheduler.go ~common ~config Server.start
Scheduler.go ~common ~config (Server.start ~ctx_name)
;;

let command = Cmd.v (start_session_info "ocaml-merlin") start_session_term
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Showcase behavior of the GetContexts ocaml-merlin command
Showcase behavior when passing the `--context` flag to ocaml-merlin

$ cat >dune-project <<EOF
> (lang dune 3.14)
Expand All @@ -14,11 +14,6 @@ Showcase behavior of the GetContexts ocaml-merlin command
> (name alt)))
> EOF

$ printf "(11:GetContexts)" | dune ocaml-merlin
(3:alt7:default)

Showcase behavior of the SetContext ocaml-merlin command

$ lib1=foo
$ lib2=bar
$ cat >dune <<EOF
Expand All @@ -45,7 +40,7 @@ because by default Merlin rules are only created for the default context
$ printf '(4:File%d:%s)' ${#FILE2} $FILE2 | dune ocaml-merlin | grep -i "$lib2"
((5:ERROR58:No config found for file bar.ml. Try calling 'dune build'.))

$ printf '(10:SetContext3:alt)(4:File%d:%s)' ${#FILE2} $FILE2 | dune ocaml-merlin | grep -i "$lib2"
$ printf '(4:File%d:%s)' ${#FILE2} $FILE2 | dune ocaml-merlin --context alt | grep -i "$lib2"
((5:ERROR58:No config found for file bar.ml. Try calling 'dune build'.))

Let's use `generate_merlin_rules` to test these commands
Expand All @@ -63,24 +58,22 @@ Let's use `generate_merlin_rules` to test these commands

$ dune build

Request config for file in alt context before calling SetContext
Request config for file in alt context without using --context

$ printf '(4:File%d:%s)' ${#FILE2} $FILE2 | dune ocaml-merlin | grep -i "$lib2" | sed 's/^[^:]*:[^:]*://'
No config found for file bar.ml. Try calling 'dune build'.))

Request config for file in alt context after calling SetContext
Request config for file in alt contextusing --context

$ printf '(10:SetContext3:alt)(4:File%d:%s)' ${#FILE2} $FILE2 | dune ocaml-merlin | dune format-dune-file | grep -i "$lib2" | sed 's/^[^:]*:[^:]*://'
$ printf '(3:alt)(4:File%d:%s)' ${#FILE2} $FILE2 | dune ocaml-merlin --context alt | dune format-dune-file | grep -i "$lib2" | sed 's/^[^:]*:[^:]*://'
$TESTCASE_ROOT/_build/alt/.bar.objs/byte)

Both together
Request config for default context without using --context

$ printf '(4:File%d:%s)(10:SetContext3:alt)(4:File%d:%s)' ${#FILE2} $FILE2 ${#FILE2} $FILE2 | dune ocaml-merlin | dune format-dune-file | grep -i "$lib2" | sed 's/^[^:]*:[^:]*://'
No config found for file bar.ml. Try calling 'dune build'.))
$TESTCASE_ROOT/_build/alt/.bar.objs/byte)
$ printf '(4:File%d:%s)' ${#FILE1} $FILE1 | dune ocaml-merlin | dune format-dune-file | grep -i "$lib1" | sed 's/^[^:]*:[^:]*://'
$TESTCASE_ROOT/_build/default/.foo.objs/byte)

Request config for default context before and after calling SetContext
Request config for default context using --context

$ printf '(4:File%d:%s)(10:SetContext3:alt)(4:File%d:%s)' ${#FILE1} $FILE1 ${#FILE1} $FILE1 | dune ocaml-merlin | dune format-dune-file | grep -i "$lib1" | sed 's/^[^:]*:[^:]*://'
$TESTCASE_ROOT/_build/default/.foo.objs/byte)
$ printf '(4:File%d:%s)' ${#FILE1} $FILE1 | dune ocaml-merlin --context alt | dune format-dune-file | grep -i "$lib1" | sed 's/^[^:]*:[^:]*://'
No config found for file foo.ml. Try calling 'dune build'.))

0 comments on commit ac96149

Please sign in to comment.