From 47fb4efd355686a9de81cab0abab12fdf427e335 Mon Sep 17 00:00:00 2001 From: Adrian Hesketh Date: Tue, 14 Nov 2023 20:18:08 +0000 Subject: [PATCH] feat: probe paths to look for templ executable --- .vscode/settings.json | 11 +++++++++++ package-lock.json | 14 ++++++++++++- package.json | 1 + src/main.ts | 46 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d652373 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "cSpell.words": [ + "GOPATH", + "gopls", + "GOROOT", + "hyangah", + "lookpath", + "pprof", + "templ" + ] +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 495ad45..029e18a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,8 +6,9 @@ "packages": { "": { "name": "templ", - "version": "0.0.14", + "version": "0.0.15", "dependencies": { + "lookpath": "^1.2.2", "vscode-languageclient": "9.0.1" }, "devDependencies": { @@ -2674,6 +2675,17 @@ "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true }, + "node_modules/lookpath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/lookpath/-/lookpath-1.2.2.tgz", + "integrity": "sha512-k2Gmn8iV6qdME3ztZC2spubmQISimFOPLuQKiPaLcVdRz0IpdxrNClVepMlyTJlhodm/zG/VfbkWERm3kUIh+Q==", + "bin": { + "lookpath": "bin/lookpath.js" + }, + "engines": { + "npm": ">=6.13.4" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", diff --git a/package.json b/package.json index 51979f8..ac290d5 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "webpack-cli": "5.1.4" }, "dependencies": { + "lookpath": "^1.2.2", "vscode-languageclient": "9.0.1" } } diff --git a/src/main.ts b/src/main.ts index ad7a242..cf82609 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,11 +10,15 @@ import { ProvideDocumentFormattingEditsSignature, ResponseError } from 'vscode-languageclient'; +import fs from 'fs/promises'; +import path from 'path'; import { LanguageClient } from 'vscode-languageclient/node'; +import { lookpath } from 'lookpath'; export async function activate(_ctx: vscode.ExtensionContext) { try { const lc = await buildLanguageClient() + vscode.window.showInformationMessage(`Returning config`) await lc.start() } catch (err) { const msg = err && err as Error ? (err as Error).message : 'unknown' @@ -41,6 +45,42 @@ const loadConfiguration = (): Configuration => { } } +const templLocations = [ + path.join(process.env.GOBIN ?? "", 'templ'), + path.join(process.env.GOBIN ?? "", 'templ.exe'), + path.join(process.env.GOPATH ?? "", 'bin', 'templ'), + path.join(process.env.GOPATH ?? "", 'bin', 'templ.exe'), + path.join(process.env.GOROOT || "", 'bin', 'templ'), + path.join(process.env.GOROOT || "", 'bin', 'templ.exe'), + path.join(process.env.HOME || "", 'bin', 'templ'), + path.join(process.env.HOME || "", 'bin', 'templ.exe'), + '/usr/local/bin/templ', + '/usr/bin/templ', + '/usr/local/go/bin/templ', + '/usr/local/share/go/bin/templ', + '/usr/share/go/bin/templ', +]; + +async function findTempl(): Promise { + const linuxName = await lookpath('templ'); + if (linuxName) { + return linuxName; + } + const windowsName = await lookpath('templ.exe'); + if (windowsName) { + return windowsName; + } + for (const exe of templLocations) { + try { + await fs.stat(exe); + return exe; + } catch (err) { + // ignore + } + } + throw new Error(`Could not find templ executable in path or in ${templLocations.join(', ')}`) +} + export async function buildLanguageClient(): Promise { const documentSelector = [ { language: 'templ', scheme: 'file' }, @@ -64,13 +104,15 @@ export async function buildLanguageClient(): Promise { args.push(`-http=${config.http}`) } + const templPath = await findTempl() + vscode.window.showInformationMessage(`Starting LSP: templ ${args.join(' ')}`) const c = new LanguageClient( 'templ', // id 'templ', { - command: 'templ', + command: templPath, args, }, { @@ -134,7 +176,7 @@ export async function buildLanguageClient(): Promise { // if filterText is falsy, the `label` should be used. // But we observed that's not the case. // Even if vscode picked the label value, that would - // cause to reorder candiates, which is not ideal. + // cause to reorder candidates, which is not ideal. // Force to use non-empty `label`. // https://github.com/golang/vscode-go/issues/441 hardcodedFilterText = items[0].label.toString();