From 5c0b4ceccd9ac814c5db6ab0fd7b085ce3fbdece Mon Sep 17 00:00:00 2001 From: PizieDust Date: Thu, 14 Nov 2024 15:51:13 +0100 Subject: [PATCH 01/14] add construct implementation --- package.json | 11 +++- src/custom_requests.ml | 47 ++++++++++++++++++ src/custom_requests.mli | 19 +++++++ src/extension_commands.ml | 102 ++++++++++++++++++++++++++++++++++++++ src/extension_consts.ml | 2 + src/ocaml_lsp.ml | 6 +++ src/ocaml_lsp.mli | 2 + 7 files changed, 188 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8eede737a..af6e87416 100644 --- a/package.json +++ b/package.json @@ -252,6 +252,11 @@ "command": "ocaml.copy-type-under-cursor", "category": "OCaml", "title": "Copy Type Under Cursor" + }, + { + "command": "ocaml.construct", + "category": "OCaml", + "title": "Construct" } ], "configuration": { @@ -719,7 +724,7 @@ "args": { "kind": "construct" }, - "when": "editorLangId == ocaml" + "when": "editorLangId == ocaml || editorLangId == reason" }, { "command": "editor.action.codeAction", @@ -1040,6 +1045,10 @@ { "command": "ocaml.copy-type-under-cursor", "when": "editorLangId == ocaml || editorLangId == ocaml.interface || editorLangId == reason || editorLangId == ocaml.ocamllex" + }, + { + "command": "ocaml.construct", + "when": "editorLangId == ocaml || editorLangId == ocaml.interface || editorLangId == reason || editorLangId == ocaml.ocamllex" } ], "editor/title": [ diff --git a/src/custom_requests.ml b/src/custom_requests.ml index e30b7a1a6..2f82586a9 100644 --- a/src/custom_requests.ml +++ b/src/custom_requests.ml @@ -73,3 +73,50 @@ module Type_enclosing = struct let request = { meth = ocamllsp_prefixed "typeEnclosing"; encode_params; decode_response } end + +module Construct = struct + type params = + { uri : Uri.t + ; position : Position.t + ; depth : int option + ; with_values : [ `None | `Local ] option + } + + type response = + { position : Range.t + ; result : string list + } + + let encode_params { uri; position; depth; with_values } = + let open Jsonoo.Encode in + let uri = ("uri", string @@ Uri.toString uri ()) in + let position = ("position", Position.json_of_t position) in + let depth = + ("depth", Option.(value ~default:null (map ~f:(fun d -> int d) depth))) + in + let with_values = + ( "with_values" + , Option.( + value + ~default:null + (map + ~f:(fun w -> + match w with + | `None -> string "none" + | `Local -> string "local") + with_values)) ) + in + object_ [ uri; position; depth; with_values ] + + let decode_response response = + let open Jsonoo.Decode in + let position = field "position" Range.t_of_json response in + let result = field "result" (list string) response in + { position; result } + + let make ~uri ~position ?(depth = None) ?(with_values = None) () = + { uri; position; depth; with_values } + + let request = + { meth = ocamllsp_prefixed "construct"; encode_params; decode_response } +end diff --git a/src/custom_requests.mli b/src/custom_requests.mli index 216530c41..d16a24494 100644 --- a/src/custom_requests.mli +++ b/src/custom_requests.mli @@ -39,3 +39,22 @@ module Type_enclosing : sig val request : (params, response) custom_request end + +module Construct : sig + type params + + type response = + { position : Range.t + ; result : string list + } + + val make : + uri:Uri.t + -> position:Position.t + -> ?depth:int option + -> ?with_values:[ `None | `Local ] option + -> unit + -> params + + val request : (params, response) custom_request +end diff --git a/src/extension_commands.ml b/src/extension_commands.ml index 2dd462d12..c0e5a4a98 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -534,6 +534,108 @@ module Copy_type_under_cursor = struct command Extension_consts.Commands.copy_type_under_cursor handler end +module Construct = struct + let extension_name = "Construct" + + let is_valid_text_doc textdoc = + match TextDocument.languageId textdoc with + | "ocaml" | "ocaml.interface" | "reason" | "ocaml.ocamllex" -> true + | _ -> false + + let ocaml_lsp_doesnt_support_construct ocaml_lsp = + not (Ocaml_lsp.can_handle_construct ocaml_lsp) + + let get_construct_results position text_editor client = + let doc = TextEditor.document text_editor in + let uri = TextDocument.uri doc in + Custom_requests.( + send_request + client + Construct.request + (Construct.make ~uri ~position ~depth:None ~with_values:None ())) + + let rec display_results ~text_editor:_ ~position:_ + (results : Custom_requests.Construct.response) = + let quickPickItems = + List.map results.result ~f:(fun res -> + (QuickPickItem.create ~label:res (), (res, results.position))) + in + let quickPickOptions = + QuickPickOptions.create ~title:"Construct results" () + in + Window.showQuickPickItems + ~choices:quickPickItems + ~options:quickPickOptions + () + + and process_construct position text_editor client = + let open Promise.Syntax in + let* res = get_construct_results position text_editor client in + let+ selection = display_results ~text_editor ~position res in + match selection with + | Some (value, range) -> + insert_to_document text_editor range value; + let _ = + process_construct + (TextEditor.selection text_editor |> Selection.end_) + text_editor + client + in + () + | None -> () + + and insert_to_document text_editor range value = + let _ = + TextEditor.edit + text_editor + ~callback:(fun ~editBuilder -> + Vscode.TextEditorEdit.replace + editBuilder + ~location:(`Range range) + ~value) + () + in + () + + let _construct = + let handler (instance : Extension_instance.t) ~args:_ = + let construct () = + match Window.activeTextEditor () with + | None -> + Extension_consts.Command_errors.text_editor_must_be_active + extension_name + ~expl: + "The cursor position is used to determine the correct \ + environment and insert the result." + |> show_message `Error "%s" + | Some text_editor + when not (is_valid_text_doc (TextEditor.document text_editor)) -> + show_message + `Error + "Invalid file type. This command only works in ocaml files, ocaml \ + interface files, reason files or ocamllex files." + | Some text_editor -> ( + match Extension_instance.lsp_client instance with + | None -> show_message `Warn "ocamllsp is not running" + | Some (_client, ocaml_lsp) + when ocaml_lsp_doesnt_support_construct ocaml_lsp -> + show_message + `Warn + "The installed version of `ocamllsp` does not support construct \ + custom requests" + | Some (client, _) -> + let position = + TextEditor.selection text_editor |> Selection.active + in + let _ = process_construct position text_editor client in + ()) + in + let (_ : unit) = construct () in + () + in + command Extension_consts.Commands.construct handler +end + let register extension instance = function | Command { id; handler } -> let callback = handler instance in diff --git a/src/extension_consts.ml b/src/extension_consts.ml index 6c16f51f0..c733e0d57 100644 --- a/src/extension_consts.ml +++ b/src/extension_consts.ml @@ -68,6 +68,8 @@ module Commands = struct let ask_debug_program = ocaml_prefixed "ask-debug-program" let copy_type_under_cursor = ocaml_prefixed "copy-type-under-cursor" + + let construct = ocaml_prefixed "construct" end module Command_errors = struct diff --git a/src/ocaml_lsp.ml b/src/ocaml_lsp.ml index 3b9bfa47c..032029c04 100644 --- a/src/ocaml_lsp.ml +++ b/src/ocaml_lsp.ml @@ -45,6 +45,7 @@ module Experimental_capabilities = struct ; handleInferIntf : bool ; handleTypedHoles : bool ; handleTypeEnclosing : bool + ; handleConstruct : bool } let default = @@ -53,6 +54,7 @@ module Experimental_capabilities = struct ; handleInferIntf = false ; handleTypedHoles = false ; handleTypeEnclosing = false + ; handleConstruct = false } (** Creates [t] given a JSON of form [{ 'handleSwitchImplIntf' : true, .... }] *) @@ -68,11 +70,13 @@ module Experimental_capabilities = struct let handleInferIntf = has_capability "handleInferIntf" in let handleTypedHoles = has_capability "handleTypedHoles" in let handleTypeEnclosing = has_capability "handleTypeEnclosing" in + let handleConstruct = has_capability "handleConstruct" in { interfaceSpecificLangId ; handleSwitchImplIntf ; handleInferIntf ; handleTypedHoles ; handleTypeEnclosing + ; handleConstruct } with Jsonoo.Decode_error err -> show_message @@ -237,3 +241,5 @@ let can_handle_typed_holes t = t.experimental_capabilities.handleTypedHoles let can_handle_type_enclosing t = t.experimental_capabilities.handleTypeEnclosing + +let can_handle_construct t = t.experimental_capabilities.handleConstruct diff --git a/src/ocaml_lsp.mli b/src/ocaml_lsp.mli index 65754abb3..6f59c721d 100644 --- a/src/ocaml_lsp.mli +++ b/src/ocaml_lsp.mli @@ -15,6 +15,8 @@ val can_handle_typed_holes : t -> bool val can_handle_type_enclosing : t -> bool +val can_handle_construct : t -> bool + module OcamllspSettingEnable : sig include Ojs.T From d328cd3f625ccd9c0c903bd6d75b46b5b0e982f1 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 11:35:52 +0100 Subject: [PATCH 02/14] move cursor to hole and repeat --- src/extension_commands.ml | 49 +++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/extension_commands.ml b/src/extension_commands.ml index c0e5a4a98..f480582cc 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -571,31 +571,34 @@ module Construct = struct and process_construct position text_editor client = let open Promise.Syntax in let* res = get_construct_results position text_editor client in - let+ selection = display_results ~text_editor ~position res in - match selection with - | Some (value, range) -> - insert_to_document text_editor range value; - let _ = - process_construct - (TextEditor.selection text_editor |> Selection.end_) - text_editor - client - in - () - | None -> () + let* selected_result = display_results ~text_editor ~position res in + match selected_result with + | Some (value, range) -> ( + let* value_inserted = insert_to_document text_editor range value in + match value_inserted with + | true -> ( + let* hole_jump = + Vscode.Commands.executeCommand ~command:"ocaml.prev-hole" ~args:[] + in + match hole_jump with + | Some _range_ojs -> + let new_position = + TextEditor.selection text_editor |> Selection.active + in + process_construct new_position text_editor client + | None -> Promise.return ()) + | false -> Promise.return ()) + | None -> Promise.return () and insert_to_document text_editor range value = - let _ = - TextEditor.edit - text_editor - ~callback:(fun ~editBuilder -> - Vscode.TextEditorEdit.replace - editBuilder - ~location:(`Range range) - ~value) - () - in - () + TextEditor.edit + text_editor + ~callback:(fun ~editBuilder -> + Vscode.TextEditorEdit.replace + editBuilder + ~location:(`Range range) + ~value) + () let _construct = let handler (instance : Extension_instance.t) ~args:_ = From 2a592e12d8d596c37143bde2411784923de0ac81 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 12:50:47 +0100 Subject: [PATCH 03/14] expose new function to get hole location --- src/extension_commands.ml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/extension_commands.ml b/src/extension_commands.ml index f480582cc..083601e93 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -162,6 +162,9 @@ module Holes_commands : sig val _jump_to_prev_hole : t val _jump_to_next_hole : t + + val hole_position : + TextEditor.t -> LanguageClient.t -> [< `Next | `Prev ] -> Range.t Promise.t end = struct let hole_not_found_msg = "No typed hole was found in this file" @@ -197,6 +200,11 @@ end = struct ~revealType:TextEditorRevealType.InCenterIfOutsideViewport () + let send_request_to_lsp client text_editor = + let doc = TextEditor.document text_editor in + let uri = TextDocument.uri doc in + Custom_requests.send_request client Custom_requests.typedHoles uri + let jump_to_hole jump (instance : Extension_instance.t) ~args = (* this command is available (in the command palette) only when a file is open *) @@ -217,9 +225,7 @@ end = struct let doc = TextEditor.document text_editor in let uri = TextDocument.uri doc in let (_ : unit Promise.t) = - let+ holes = - Custom_requests.send_request client Custom_requests.typedHoles uri - in + let+ holes = send_request_to_lsp client text_editor in jump ~cmd_args:args text_editor @@ -363,6 +369,24 @@ end = struct select_hole_range text_editor hole)) end + let hole_position text_editor client direction = + let open Promise.Syntax in + let (range : Range.t Promise.t) = + let+ holes = send_request_to_lsp client text_editor in + let sorted_holes = List.sort holes ~compare:Range.compare in + let current_pos = current_cursor_pos text_editor in + match direction with + | `Prev -> + Prev_hole.pick_prev_hole + current_pos + ~sorted_non_empty_holes_list:sorted_holes + | `Next -> + Next_hole.pick_next_hole + current_pos + ~sorted_non_empty_holes_list:sorted_holes + in + range + let _jump_to_next_hole = command Extension_consts.Commands.next_hole (jump_to_hole Next_hole.jump) From 538ef5ef708a03d7bb542076a530986cbf6921d1 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 12:51:04 +0100 Subject: [PATCH 04/14] continously jump to hole to provide more constructs --- src/extension_commands.ml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/extension_commands.ml b/src/extension_commands.ml index 083601e93..65862c5e5 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -222,8 +222,6 @@ end = struct when not (Ocaml_lsp.can_handle_typed_holes ocaml_lsp) -> ocaml_lsp_doesn't_support_holes instance ocaml_lsp | Some (client, _ocaml_lsp) -> - let doc = TextEditor.document text_editor in - let uri = TextDocument.uri doc in let (_ : unit Promise.t) = let+ holes = send_request_to_lsp client text_editor in jump @@ -592,7 +590,7 @@ module Construct = struct ~options:quickPickOptions () - and process_construct position text_editor client = + and process_construct position text_editor client instance = let open Promise.Syntax in let* res = get_construct_results position text_editor client in let* selected_result = display_results ~text_editor ~position res in @@ -600,17 +598,11 @@ module Construct = struct | Some (value, range) -> ( let* value_inserted = insert_to_document text_editor range value in match value_inserted with - | true -> ( - let* hole_jump = - Vscode.Commands.executeCommand ~command:"ocaml.prev-hole" ~args:[] + | true -> + let* new_range = + Holes_commands.hole_position text_editor client `Prev in - match hole_jump with - | Some _range_ojs -> - let new_position = - TextEditor.selection text_editor |> Selection.active - in - process_construct new_position text_editor client - | None -> Promise.return ()) + process_construct (Range.end_ new_range) text_editor client instance | false -> Promise.return ()) | None -> Promise.return () @@ -654,7 +646,7 @@ module Construct = struct let position = TextEditor.selection text_editor |> Selection.active in - let _ = process_construct position text_editor client in + let _ = process_construct position text_editor client instance in ()) in let (_ : unit) = construct () in From a1699d1bb02973728b5bd4032f5a7a3f17dc5835 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 14:37:56 +0100 Subject: [PATCH 05/14] pass position --- src/extension_commands.ml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/extension_commands.ml b/src/extension_commands.ml index 65862c5e5..60e07c281 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -164,7 +164,11 @@ module Holes_commands : sig val _jump_to_next_hole : t val hole_position : - TextEditor.t -> LanguageClient.t -> [< `Next | `Prev ] -> Range.t Promise.t + Position.t + -> TextEditor.t + -> LanguageClient.t + -> [< `Next | `Prev ] + -> Range.t Promise.t end = struct let hole_not_found_msg = "No typed hole was found in this file" @@ -367,20 +371,19 @@ end = struct select_hole_range text_editor hole)) end - let hole_position text_editor client direction = + let hole_position position text_editor client direction = let open Promise.Syntax in let (range : Range.t Promise.t) = let+ holes = send_request_to_lsp client text_editor in let sorted_holes = List.sort holes ~compare:Range.compare in - let current_pos = current_cursor_pos text_editor in match direction with | `Prev -> Prev_hole.pick_prev_hole - current_pos + position ~sorted_non_empty_holes_list:sorted_holes | `Next -> Next_hole.pick_next_hole - current_pos + position ~sorted_non_empty_holes_list:sorted_holes in range @@ -600,7 +603,11 @@ module Construct = struct match value_inserted with | true -> let* new_range = - Holes_commands.hole_position text_editor client `Prev + Holes_commands.hole_position + (Range.start range) + text_editor + client + `Prev in process_construct (Range.end_ new_range) text_editor client instance | false -> Promise.return ()) From e77af02d5f500b952a5ed2a47634aee434511ab3 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 14:53:24 +0100 Subject: [PATCH 06/14] add changelog --- CHANGELOG.md | 3 ++- src/extension_commands.ml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fbe95813..c1c3e30af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,9 @@ # Unreleased -- Add `ocaml.copy-type-under-cursor` to copy, in the clipboard the type of +- Add `ocaml.copy-type-under-cursor` to copy, in the clipboard the type of the expression under the cursor (#1582) +- Add `ocaml.construct` to construct an expression from a typedhole. (#1646) ## 1.20.1 diff --git a/src/extension_commands.ml b/src/extension_commands.ml index 60e07c281..7fa16abb3 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -372,6 +372,7 @@ end = struct end let hole_position position text_editor client direction = + (* We aren't checking if there's the capability to handle typed holes *) let open Promise.Syntax in let (range : Range.t Promise.t) = let+ holes = send_request_to_lsp client text_editor in From a3f9ab614619bdabbed7384f33a6034e7f212944 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 15:04:08 +0100 Subject: [PATCH 07/14] find next hole --- src/extension_commands.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension_commands.ml b/src/extension_commands.ml index 7fa16abb3..64869e0be 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -608,7 +608,7 @@ module Construct = struct (Range.start range) text_editor client - `Prev + `Next in process_construct (Range.end_ new_range) text_editor client instance | false -> Promise.return ()) From e70d0dbe4d13ec27d1a942ba2d257144a07d1d9c Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 15:04:42 +0100 Subject: [PATCH 08/14] update yarn.lock --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e8c989d95..d4ded5345 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2645,9 +2645,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.5.41": - version: 1.5.57 - resolution: "electron-to-chromium@npm:1.5.57" - checksum: 10c0/42b969681985016be6069ae68cf29e84ba3f2191fcb7f9d3355e83e81da8dbd100e4b5c9d69b88637003e06dc1860125a50332ec0caee49fd9c2c4ab62feb288 + version: 1.5.60 + resolution: "electron-to-chromium@npm:1.5.60" + checksum: 10c0/934d8d1383ffee4f5f94586ebf0afd133c841002fa3b3cc60b8f6c2af62cd1a73b40cf9fd4cfabba854c3ea5f1df0ecb69f0f9d2e3f913e6b7df7461685b4955 languageName: node linkType: hard From 76c86664bd865d65f9b102820a0b0f44f2a8f4fe Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 15:05:17 +0100 Subject: [PATCH 09/14] change keybinding from code action to command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b25cc7c3e..afc6bbcf1 100644 --- a/package.json +++ b/package.json @@ -719,7 +719,7 @@ "when": "editorLangId == ocaml || editorLangId == reason" }, { - "command": "editor.action.codeAction", + "command": "ocaml.construct", "key": "Alt+C", "args": { "kind": "construct" From 89411451d358e67a7afd9b753bc2042b9b37b01e Mon Sep 17 00:00:00 2001 From: PizieDust Date: Fri, 15 Nov 2024 15:17:06 +0100 Subject: [PATCH 10/14] add command to treeview list --- src/treeview_commands.ml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/treeview_commands.ml b/src/treeview_commands.ml index d4164b6df..a2db23df9 100644 --- a/src/treeview_commands.ml +++ b/src/treeview_commands.ml @@ -43,7 +43,31 @@ let terminal_item = Vscode.TreeItem.set_command item command; item -let items = [ select_sandbox_item; terminal_item ] + + let construct_item = + let icon = + `LightDark + Vscode.TreeItem.LightDarkIcon. + { light = `String (Path.asset "collection-light.svg" |> Path.to_string) + ; dark = `String (Path.asset "collection-dark.svg" |> Path.to_string) + } + in + let label = + `TreeItemLabel + (Vscode.TreeItemLabel.create ~label:"Construct" ()) + in + let item = Vscode.TreeItem.make_label ~label () in + let command = + Vscode.Command.create + ~title:"Construct" + ~command:"ocaml.construct" + () + in + Vscode.TreeItem.set_iconPath item icon; + Vscode.TreeItem.set_command item command; + item + +let items = [ select_sandbox_item; terminal_item; construct_item ] let getTreeItem ~element = `Value element From ea9ac5ad33bc0a48d5a7ce368fe393d9b2478e6c Mon Sep 17 00:00:00 2001 From: PixieDust <111846546+PizieDust@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:11:46 +0100 Subject: [PATCH 11/14] Update src/treeview_commands.ml Co-authored-by: Ulysse <5031221+voodoos@users.noreply.github.com> --- src/treeview_commands.ml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/treeview_commands.ml b/src/treeview_commands.ml index a2db23df9..ed0c229d1 100644 --- a/src/treeview_commands.ml +++ b/src/treeview_commands.ml @@ -45,13 +45,7 @@ let terminal_item = let construct_item = - let icon = - `LightDark - Vscode.TreeItem.LightDarkIcon. - { light = `String (Path.asset "collection-light.svg" |> Path.to_string) - ; dark = `String (Path.asset "collection-dark.svg" |> Path.to_string) - } - in + let icon = `ThemeIcon (Vscode.ThemeIcon.make ~id:"tools" ()) in let label = `TreeItemLabel (Vscode.TreeItemLabel.create ~label:"Construct" ()) From e9c52a9107a3f948f54b168884f0593314b8b8e8 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Mon, 18 Nov 2024 13:58:27 +0100 Subject: [PATCH 12/14] rename command --- package.json | 2 +- src/treeview_commands.ml | 44 +++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index afc6bbcf1..667803ac1 100644 --- a/package.json +++ b/package.json @@ -256,7 +256,7 @@ { "command": "ocaml.construct", "category": "OCaml", - "title": "Construct" + "title": "List values that can fill the selected typed-hole" } ], "configuration": { diff --git a/src/treeview_commands.ml b/src/treeview_commands.ml index a2db23df9..1c56e41ec 100644 --- a/src/treeview_commands.ml +++ b/src/treeview_commands.ml @@ -43,29 +43,27 @@ let terminal_item = Vscode.TreeItem.set_command item command; item - - let construct_item = - let icon = - `LightDark - Vscode.TreeItem.LightDarkIcon. - { light = `String (Path.asset "collection-light.svg" |> Path.to_string) - ; dark = `String (Path.asset "collection-dark.svg" |> Path.to_string) - } - in - let label = - `TreeItemLabel - (Vscode.TreeItemLabel.create ~label:"Construct" ()) - in - let item = Vscode.TreeItem.make_label ~label () in - let command = - Vscode.Command.create - ~title:"Construct" - ~command:"ocaml.construct" - () - in - Vscode.TreeItem.set_iconPath item icon; - Vscode.TreeItem.set_command item command; - item +let construct_item = + let icon = + `LightDark + Vscode.TreeItem.LightDarkIcon. + { light = `String (Path.asset "collection-light.svg" |> Path.to_string) + ; dark = `String (Path.asset "collection-dark.svg" |> Path.to_string) + } + in + let label = + `TreeItemLabel + (Vscode.TreeItemLabel.create + ~label:"List values that can fill the selected typed-hole" + ()) + in + let item = Vscode.TreeItem.make_label ~label () in + let command = + Vscode.Command.create ~title:"Construct" ~command:"ocaml.construct" () + in + Vscode.TreeItem.set_iconPath item icon; + Vscode.TreeItem.set_command item command; + item let items = [ select_sandbox_item; terminal_item; construct_item ] From 2379869d1f0dab75c5e976bc5c2713644ab9df6c Mon Sep 17 00:00:00 2001 From: PizieDust Date: Mon, 18 Nov 2024 13:59:14 +0100 Subject: [PATCH 13/14] remove redundant labels and recursion --- src/extension_commands.ml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/extension_commands.ml b/src/extension_commands.ml index 64869e0be..d7769d59e 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -580,8 +580,7 @@ module Construct = struct Construct.request (Construct.make ~uri ~position ~depth:None ~with_values:None ())) - let rec display_results ~text_editor:_ ~position:_ - (results : Custom_requests.Construct.response) = + let display_results (results : Custom_requests.Construct.response) = let quickPickItems = List.map results.result ~f:(fun res -> (QuickPickItem.create ~label:res (), (res, results.position))) @@ -594,10 +593,20 @@ module Construct = struct ~options:quickPickOptions () - and process_construct position text_editor client instance = + let insert_to_document text_editor range value = + TextEditor.edit + text_editor + ~callback:(fun ~editBuilder -> + Vscode.TextEditorEdit.replace + editBuilder + ~location:(`Range range) + ~value) + () + + let rec process_construct position text_editor client instance = let open Promise.Syntax in let* res = get_construct_results position text_editor client in - let* selected_result = display_results ~text_editor ~position res in + let* selected_result = display_results res in match selected_result with | Some (value, range) -> ( let* value_inserted = insert_to_document text_editor range value in From 41cf20ca3569516394ef59913c0bf955819ae726 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Mon, 18 Nov 2024 13:59:28 +0100 Subject: [PATCH 14/14] rename holes function and return an option --- src/extension_commands.ml | 50 ++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/src/extension_commands.ml b/src/extension_commands.ml index d7769d59e..91fe3b525 100644 --- a/src/extension_commands.ml +++ b/src/extension_commands.ml @@ -163,12 +163,12 @@ module Holes_commands : sig val _jump_to_next_hole : t - val hole_position : + val closest_hole : Position.t -> TextEditor.t -> LanguageClient.t -> [< `Next | `Prev ] - -> Range.t Promise.t + -> Range.t option Promise.t end = struct let hole_not_found_msg = "No typed hole was found in this file" @@ -371,23 +371,20 @@ end = struct select_hole_range text_editor hole)) end - let hole_position position text_editor client direction = + let closest_hole position text_editor client direction = (* We aren't checking if there's the capability to handle typed holes *) let open Promise.Syntax in - let (range : Range.t Promise.t) = - let+ holes = send_request_to_lsp client text_editor in - let sorted_holes = List.sort holes ~compare:Range.compare in - match direction with - | `Prev -> - Prev_hole.pick_prev_hole - position - ~sorted_non_empty_holes_list:sorted_holes - | `Next -> - Next_hole.pick_next_hole - position - ~sorted_non_empty_holes_list:sorted_holes - in - range + let+ holes = send_request_to_lsp client text_editor in + let sorted_holes = List.sort holes ~compare:Range.compare in + match sorted_holes with + | [] -> None + | holes -> + Some + (match direction with + | `Prev -> + Prev_hole.pick_prev_hole position ~sorted_non_empty_holes_list:holes + | `Next -> + Next_hole.pick_next_hole position ~sorted_non_empty_holes_list:holes) let _jump_to_next_hole = command Extension_consts.Commands.next_hole (jump_to_hole Next_hole.jump) @@ -611,28 +608,21 @@ module Construct = struct | Some (value, range) -> ( let* value_inserted = insert_to_document text_editor range value in match value_inserted with - | true -> + | true -> ( let* new_range = - Holes_commands.hole_position + Holes_commands.closest_hole (Range.start range) text_editor client `Next in - process_construct (Range.end_ new_range) text_editor client instance + match new_range with + | Some range -> + process_construct (Range.end_ range) text_editor client instance + | None -> Promise.return ()) | false -> Promise.return ()) | None -> Promise.return () - and insert_to_document text_editor range value = - TextEditor.edit - text_editor - ~callback:(fun ~editBuilder -> - Vscode.TextEditorEdit.replace - editBuilder - ~location:(`Range range) - ~value) - () - let _construct = let handler (instance : Extension_instance.t) ~args:_ = let construct () =