diff --git a/src/cljConnection.ts b/src/cljConnection.ts index 30ccf7b..eae3759 100644 --- a/src/cljConnection.ts +++ b/src/cljConnection.ts @@ -72,77 +72,81 @@ const stopLoadingAnimation = () => { } }; -const manuallyConnect = (): void => { +const manuallyConnect = async (): Promise => { if (loadingHandler) { - vscode.window.showWarningMessage('Already starting a nREPL. Disconnect first.'); + vscode.window.showWarningMessage( + 'Already starting a nREPL. Disconnect first.'); return; } if (isConnected()) { - vscode.window.showWarningMessage('Already connected to nREPL. Disconnect first.'); + vscode.window.showWarningMessage( + 'Already connected to nREPL. Disconnect first.'); return; } let host: string; let port: number; - vscode.window.showInputBox({ prompt: 'nREPL host', value: DEFAULT_LOCAL_IP }) - .then(hostFromUser => { - if (!hostFromUser) - return Promise.reject({ connectionError: 'Host must be informed.' }); - - host = hostFromUser; - - const portNumberPromptOptions: vscode.InputBoxOptions = { prompt: 'nREPL port number' }; - - if (hostFromUser === DEFAULT_LOCAL_IP || hostFromUser.toLowerCase() === 'localhost') { - const localPort = getLocalNReplPort(); - if (localPort) - portNumberPromptOptions.value = String(localPort); - } - - return >vscode.window.showInputBox(portNumberPromptOptions); // cast needed to chain promises - }) - .then(portFromUser => { - if (!portFromUser) - return Promise.reject({ connectionError: 'Port number must be informed.' }); - - const intPort = Number.parseInt(portFromUser); - if (!intPort) - return Promise.reject({ connectionError: 'Port number must be an integer.' }); - - port = intPort; - }) - .then(() => nreplClient.test({ host, port })) - .then(() => { - saveConnection({ host, port }); - } - , ({ connectionError }) => { - if (!connectionError) - connectionError = "Can't connect to the nREPL."; - vscode.window.showErrorMessage(connectionError); - }); + // Getting host. + const hostFromUser = await vscode.window.showInputBox( + { prompt: 'nREPL host', value: DEFAULT_LOCAL_IP }); + + if (!hostFromUser) + throw new Error('Host must be informed.'); + + host = hostFromUser; + + const portNumberPromptOptions: vscode.InputBoxOptions = { prompt: 'nREPL port number' }; + + if (hostFromUser === DEFAULT_LOCAL_IP || hostFromUser.toLowerCase() === 'localhost') { + const localPort = getLocalNReplPort(); + if (localPort) + portNumberPromptOptions.value = String(localPort); + } + + // Getting port. + const portFromUser = await vscode.window.showInputBox(portNumberPromptOptions); + + if (!portFromUser) + throw new Error("Port number must be informed."); + + const intPort = Number.parseInt(portFromUser); + if (!intPort) + throw new Error("Port number must be an integer."); + + port = intPort; + + // Check if we are able to connect with the given host and port. + const succesfullyConnected = await nreplClient.test({ host, port }); + if (succesfullyConnected) { + saveConnection({ host, port}); + } + else { + vscode.window.showErrorMessage("Can't connect to the nREPL."); + } }; -const startNRepl = (): void => { +const startNRepl = async (): Promise => { if (isConnected()) { - vscode.window.showWarningMessage('Already connected to nREPL. Disconnect first.'); + vscode.window.showWarningMessage( + "Already connected to nREPL. Disconnect first."); return; } startLoadingAnimation(); - let nreplConnection: CljConnectionInformation; - nreplController.start() - .then(connectionInfo => nreplConnection = connectionInfo) - .then(() => nreplClient.test(nreplConnection)) - .then(stopLoadingAnimation) - .then(() => saveConnection(nreplConnection), ({ nreplError }) => { - stopLoadingAnimation(); - if (!nreplError) - nreplError = "Can't start nREPL."; - disconnect(false); - vscode.window.showErrorMessage(nreplError); - }); + let nreplConnection: CljConnectionInformation = await nreplController.start(); + const succesfullyConnected = nreplClient.test(nreplConnection); + + stopLoadingAnimation(); + + if (succesfullyConnected) { + saveConnection(nreplConnection); + } + else { + disconnect(false); + vscode.window.showErrorMessage("Can't start nREPL."); + } }; const disconnect = (showMessage: boolean = true): void => { diff --git a/src/clojureFormat.ts b/src/clojureFormat.ts index df8c1c5..8416712 100644 --- a/src/clojureFormat.ts +++ b/src/clojureFormat.ts @@ -18,10 +18,10 @@ function slashUnescape(contents: string) { } -export const formatFile = (document: vscode.TextDocument, range: vscode.Range): Promise => { - +export const formatFile = async (document: vscode.TextDocument, range: vscode.Range): Promise => { if (!cljConnection.isConnected()) { - return Promise.reject("Formatting functions don't work, connect to nREPL first."); + throw new Error( + "Formatting functions don't work, connect to nREPL first."); } let contents: string = document.getText(range); @@ -29,31 +29,26 @@ export const formatFile = (document: vscode.TextDocument, range: vscode.Range): // Escaping the string before sending it to nREPL contents = slashEscape(contents) - let cljfmtParams = vscode.workspace.getConfiguration('clojureVSCode').cljfmtParameters; cljfmtParams = cljfmtParams.isEmpty ? "nil" : "{"+cljfmtParams+"}"; - // Running "(require 'cljfmt.core)" in right after we have checked we are connected to nREPL // would be a better option but in this case "cljfmt.core/reformat-string" fails the first // time it is called. I have no idea what causes this behavior so I decided to put the require // statement right here - don't think it does any harm. If someone knows how to fix it // please send a pull request with a fix. - return nreplClient.evaluate(`(require 'cljfmt.core) (cljfmt.core/reformat-string "${contents}" ${cljfmtParams})`) - .then(value => { - if ('ex' in value[0]) { - return Promise.reject(value[1].err); - }; - if (('value' in value[1]) && (value[1].value != 'nil')) { - let new_content: string = value[1].value.slice(1, -1); - new_content = slashUnescape(new_content); - return Promise.resolve([vscode.TextEdit.replace(range, new_content)]); - }; - }); + const value = await nreplClient.evaluate( + `(require 'cljfmt.core) (cljfmt.core/reformat-string "${contents}" ${cljfmtParams})`); + if ('ex' in value[0]) throw new Error(value[1].err); + if (('value' in value[1]) && (value[1].value != 'nil')) { + let newContent: string = value[1].value.slice(1, -1); + newContent = slashUnescape(newContent); + return [vscode.TextEdit.replace(range, newContent)] + } } -export const maybeActivateFormatOnSave = () => { +export const maybeActivateFormatOnSave = (): void => { vscode.workspace.onWillSaveTextDocument(e => { const document = e.document; if (document.languageId !== "clojure") { diff --git a/src/nreplClient.ts b/src/nreplClient.ts index 9584a12..e4403db 100644 --- a/src/nreplClient.ts +++ b/src/nreplClient.ts @@ -52,27 +52,40 @@ interface nREPLCloseMessage { session?: string; } -const complete = (symbol: string, ns: string): Promise => { +const complete = async (symbol: string, ns: string): Promise => { const msg: nREPLCompleteMessage = { op: 'complete', symbol, ns }; - return send(msg).then(respObjs => respObjs[0]); + const respObjs = await send(msg); + return respObjs[0]; }; -const info = (symbol: string, ns: string, session?: string): Promise => { +const info = async (symbol: string, ns: string, session?: string): Promise => { const msg: nREPLInfoMessage = { op: 'info', symbol, ns, session }; - return send(msg).then(respObjs => respObjs[0]); + const respObjs = await send(msg); + return respObjs[0]; }; -const evaluate = (code: string, session?: string): Promise => clone(session).then((session_id) => { - const msg: nREPLSingleEvalMessage = { op: 'eval', code: code, session: session_id }; - return send(msg); -}); +const evaluate = async (code: string, session?: string): Promise => { + const sessionId = await clone(session); + const msg: nREPLSingleEvalMessage = { + op: 'eval', + code: code, session: sessionId + }; + return await send(msg); +}; -const evaluateFile = (code: string, filepath: string, session?: string): Promise => clone(session).then((session_id) => { - const msg: nREPLEvalMessage = { op: 'load-file', file: code, 'file-path': filepath, session: session_id }; - return send(msg); -}); +const evaluateFile = async (code: string, filepath: string, session?: string): Promise => { + const sessionId = await clone(session); + const msg: nREPLEvalMessage = { + op: 'load-file', + file: code, + 'file-path': filepath, + session: sessionId + }; + return await send(msg); +}; -const stacktrace = (session: string): Promise => send({ op: 'stacktrace', session: session }); +const stacktrace = (session: string): Promise => + send({ op: 'stacktrace', session: session }); const runTests = function (namespace: string | undefined): Promise { const message: TestMessage = { @@ -81,24 +94,21 @@ const runTests = function (namespace: string | undefined): Promise { 'load?': 1 } return send(message); -} - +}; -const clone = (session?: string): Promise => send({ op: 'clone', session: session }).then(respObjs => respObjs[0]['new-session']); +const clone = async (session?: string): Promise => { + const respObjs = await send({ op: 'clone', session: session }); + return respObjs[0]['new-session']; +}; -const test = (connectionInfo: CljConnectionInformation): Promise => { - return send({ op: 'clone' }, connectionInfo) - .then(respObjs => respObjs[0]) - .then(response => { - if (!('new-session' in response)) - return Promise.reject(false); - else { - return Promise.resolve([]); - } - }); +const test = async (connectionInfo: CljConnectionInformation): Promise => { + const respObjs = await send({ op: 'clone' }, connectionInfo); + const response = respObjs[0]; + return 'new-session' in response; }; -const close = (session?: string): Promise => send({ op: 'close', session: session }); +const close = (session?: string): Promise => + send({ op: 'close', session: session }); const listSessions = (): Promise<[string]> => { return send({ op: 'ls-sessions' }).then(respObjs => {