From ebd7324ffcaae8cb4f4019838d04ec230bb0bf14 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Sat, 24 Feb 2024 06:23:04 +0200 Subject: [PATCH 1/3] + if nimlangserver is not found, ask the user before attempting to 'nimble install' it. --- src/nimLsp.nim | 29 +++++++++++++++++++++-------- src/platform/vscodeApi.nim | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/nimLsp.nim b/src/nimLsp.nim index f295ebb..4b6b111 100644 --- a/src/nimLsp.nim +++ b/src/nimLsp.nim @@ -119,14 +119,27 @@ proc startLanguageServer(tryInstall: bool, state: ExtensionState) {.async.} = if tryInstall and not state.installPerformed: let command = getNimbleExecPath() & " install nimlangserver --accept" vscode.window.showInformationMessage( - cstring(fmt "Unable to find nimlangserver, trying to install it via '{command}'")) - state.installPerformed = true - discard cp.exec( - command, - ExecOptions{}, - proc(err: ExecError, stdout: cstring, stderr: cstring): void {.async.} = - console.log("Nimble install finished, validating by checking if nimlangserver is present.") - await startLanguageServer(false, state)) + cstring(fmt "Unable to find nimlangserver. Do you want me to attempt to install it via '{command}'?"), + VscodeMessageOptions( + detail: cstring(""), + modal: false + ), + VscodeMessageItem(title: cstring("Yes"), isCloseAffordance: false), + VscodeMessageItem(title: cstring("No"), isCloseAffordance: true)) + .then( + onfulfilled = proc(value: JsRoot): JsRoot = + if value.JsObject.to(VscodeMessageItem).title == "Yes": + discard cp.exec( + command, + ExecOptions{}, + proc(err: ExecError, stdout: cstring, stderr: cstring): void {.async.} = + console.log("Nimble install finished, validating by checking if nimlangserver is present.") + await startLanguageServer(false, state)) + value + , + onrejected = proc(reason: JsRoot): JsRoot = + reason + ) else: let cantInstallInfoMesssage: cstring = "Unable to find/install `nimlangserver`. You can attempt to install it by running `nimble install nimlangserver` or downloading the binaries from https://github.com/nim-lang/langserver/releases." vscode.window.showInformationMessage(cantInstallInfoMesssage) diff --git a/src/platform/vscodeApi.nim b/src/platform/vscodeApi.nim index fefcd26..b2337c0 100644 --- a/src/platform/vscodeApi.nim +++ b/src/platform/vscodeApi.nim @@ -6,6 +6,9 @@ export jsffi, jsPromise, jsNode ## TODO: Move from JsObject to JsRoot for more explict errors type + VscodeThenable* = ref VscodeThenableObj + VscodeThenableObj {.importc.} = object of JsRoot + VscodeMarkdownString* = ref VscodeMarkdownStringObj VscodeMarkdownStringObj {.importc.} = object of JsObject value*: cstring @@ -184,6 +187,8 @@ type VscodeMarkedString* = ref VscodeMarkedStringObj VscodeMarkedStringObj {.importc.} = object of JsObject +proc then*(self: VscodeThenable, onfulfilled: proc(value: JsRoot): JsRoot, onrejected: proc(reason: JsRoot): JsRoot): VscodeThenable {.importcpp, discardable.} + proc cstringToMarkedString(s: cstring): VscodeMarkedString {.importcpp: "#".} converter toVscodeMarkedString*(s: cstring): VscodeMarkedString = s.cstringToMarkedString() proc hoverLabelToMarkedString(s: VscodeHoverLabel): VscodeMarkedString {. @@ -492,6 +497,16 @@ type activeTextEditor*: VscodeTextEditor visibleTextEditors*: Array[VscodeTextEditor] + VscodeMessageItem* = ref VscodeMessageItemObj + VscodeMessageItemObj {.importc.} = object of JsRoot + isCloseAffordance*: bool + title*: cstring + + VscodeMessageOptions* = ref VscodeMessageOptionsObj + VscodeMessageOptionsObj {.importc.} = object of JsRoot + detail*: cstring + modal*: bool + VscodeCommands* = ref VscodeCommandsObj VscodeCommandsObj {.importc.} = object of JsObject @@ -622,6 +637,7 @@ proc with*(uri: VscodeUri, change: VscodeUriChange): VscodeUri {.importcpp.} # Output proc showInformationMessage*(win: VscodeWindow, msg: cstring) {.importcpp.} +proc showInformationMessage*(win: VscodeWindow, message: cstring, options: VscodeMessageOptions): VscodeThenable {.importcpp, varargs, discardable.} ## shows an informational message proc showErrorMessage*(win: VscodeWindow, message: cstring) {.importcpp.} From a26ea5e66b85006ff9cfdeb36e5c61e3761ff2ad Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Sat, 24 Feb 2024 06:44:27 +0200 Subject: [PATCH 2/3] + protection against running 'nimble install nimlangserver' twice --- src/nimLsp.nim | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/nimLsp.nim b/src/nimLsp.nim index 4b6b111..8b102f7 100644 --- a/src/nimLsp.nim +++ b/src/nimLsp.nim @@ -129,12 +129,14 @@ proc startLanguageServer(tryInstall: bool, state: ExtensionState) {.async.} = .then( onfulfilled = proc(value: JsRoot): JsRoot = if value.JsObject.to(VscodeMessageItem).title == "Yes": - discard cp.exec( - command, - ExecOptions{}, - proc(err: ExecError, stdout: cstring, stderr: cstring): void {.async.} = - console.log("Nimble install finished, validating by checking if nimlangserver is present.") - await startLanguageServer(false, state)) + if not state.installPerformed: + state.installPerformed = true + discard cp.exec( + command, + ExecOptions{}, + proc(err: ExecError, stdout: cstring, stderr: cstring): void {.async.} = + console.log("Nimble install finished, validating by checking if nimlangserver is present.") + await startLanguageServer(false, state)) value , onrejected = proc(reason: JsRoot): JsRoot = From 2e7093a8ba0c5f646c22014c5de404260c15af7f Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Sat, 24 Feb 2024 06:56:41 +0200 Subject: [PATCH 3/3] + if user clicks "Yes" on install nimlangserver, show information message to indicate to the user that nimlangserver is being installed. --- src/nimLsp.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nimLsp.nim b/src/nimLsp.nim index 8b102f7..2701562 100644 --- a/src/nimLsp.nim +++ b/src/nimLsp.nim @@ -131,6 +131,8 @@ proc startLanguageServer(tryInstall: bool, state: ExtensionState) {.async.} = if value.JsObject.to(VscodeMessageItem).title == "Yes": if not state.installPerformed: state.installPerformed = true + vscode.window.showInformationMessage( + cstring(fmt "Trying to install nimlangserver via '{command}'")) discard cp.exec( command, ExecOptions{},