Skip to content

Commit

Permalink
refactor: Restructure extension
Browse files Browse the repository at this point in the history
  • Loading branch information
josa42 committed Dec 8, 2020
1 parent 0a51e34 commit 2bd0e18
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 93 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"prepare": "yarn clean && yarn build",
"lint:fix": "eslint . --ext .ts,.js --fix",
"lint": "eslint . --ext .ts,.js",
"link": "coc-dev link",
"link": "yarn build && coc-dev link",
"unlink": "coc-dev unlink",
"test": "yarn lint"
},
Expand Down
16 changes: 12 additions & 4 deletions src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import path from "path"
import fs from "fs"
import path from "path"
import { getConfig } from "./utils/config"
import { installLuaLs } from "./utils/sumneko-lua-ls"
import { installLuaLsp } from "./utils/alloyed-lua-lsp"
import { workspace, LanguageClient } from "coc.nvim"
import { installLuaLsp } from "./utils/tools"

export async function version(): Promise<void> {
const { version } = JSON.parse(fs.readFileSync(path.resolve(__dirname, "..", "package.json"), "utf-8"))
workspace.showMessage(`Version: ${version}`, "more")
}

export async function updateLuaLsp(client: LanguageClient): Promise<void> {
await installLuaLsp(true)
export async function update(client: LanguageClient): Promise<void> {
const config = getConfig()

if (config.useSumnekoLs) {
await installLuaLs(true)
} else {
await installLuaLsp(true)
}

if (client.needsStop()) {
await client.stop()
Expand Down
71 changes: 37 additions & 34 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,69 @@ import {
services,
LanguageClientOptions,
} from "coc.nvim"
import { installLuaLsp, luaLspBin, commandExists } from "./utils/tools"
import { version, updateLuaLsp } from "./commands"
import { setStoragePath } from "./utils/config"

interface LuaConfig {
enable: boolean
commandPath: string
}
import { installLuaLsp, luaLspCommand } from "./utils/alloyed-lua-lsp"
import { installLuaLs, luaLsCommandAndArgs } from "./utils/sumneko-lua-ls"

import { commandExists } from "./utils/tools"
import { version, update } from "./commands"
import { setStoragePath, getConfig } from "./utils/config"

export async function activate(context: ExtensionContext): Promise<void> {
setStoragePath(context.storagePath)

const config = workspace.getConfiguration().get("lua", {}) as LuaConfig
const config = getConfig()
if (config.enable === false) {
return
}

const [command, args] = config.commandPath ? [config.commandPath, []] : await luaLspBin()
const client = config.useSumnekoLs
? await createClientSumnekoLs(context, config)
: await createClientAlloyedLsp(context, config)

const useSumnekoLs = workspace.getConfiguration().get("lua.useSumnekoLs", false)
context.subscriptions.push(
services.registLanguageClient(client),
commands.registerCommand("lua.version", () => version()),
commands.registerCommand("lua.update", async () => update(client))
)
}

const nameLong = useSumnekoLs ? "sumneko/lua-language-server" : "Alloyed/lua-lsp"
const name = useSumnekoLs ? "lua-ls" : "lua-lsp"
// TODO deprecate and remove once sumneko/lua-language-server is stable
async function createClientAlloyedLsp(context, config): Promise<LanguageClient> {
const command = config.commandPath || (await luaLspCommand())

if (!(await commandExists(command))) {
await showInstallStatus(nameLong, async () => {
await installLuaLsp()
})
await installLuaLsp()
}

const serverOptions: ServerOptions = { command, args }
const serverOptions: ServerOptions = { command }

const clientOptions: LanguageClientOptions = {
documentSelector: ["lua"],
}

const client = new LanguageClient("lua", name, serverOptions, clientOptions)
return new LanguageClient("lua", "lua", serverOptions, clientOptions)
}

context.subscriptions.push(
services.registLanguageClient(client),
commands.registerCommand("lua.version", () => version()),
commands.registerCommand("lua.update", async () =>
showInstallStatus(nameLong, async () => await updateLuaLsp(client))
async function createClientSumnekoLs(context, config): Promise<LanguageClient> {
if (config.commandPath) {
workspace.showMessage(
"[coc-lua] Wrong configuration: Cannot use both lua.commandPath and lua.useSumnekoLs",
"warning"
)
)
}
}

async function showInstallStatus(name: string, fn: () => Promise<void>) {
const statusItem = workspace.createStatusBarItem(90, { progress: true })
const [command, args] = await luaLsCommandAndArgs()

statusItem.text = `Installing '${name}'`
statusItem.show()
if (!(await commandExists(command))) {
await installLuaLs()
}

try {
await fn()
const serverOptions: ServerOptions = { command, args }

workspace.showMessage(`Installed '${name}'`)
} catch (err) {
workspace.showMessage(`Failed to install '${name}'`, "error")
const clientOptions: LanguageClientOptions = {
documentSelector: ["lua"],
}

statusItem.hide()
return new LanguageClient("lua", "lua", serverOptions, clientOptions)
}
46 changes: 46 additions & 0 deletions src/utils/alloyed-lua-lsp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import path from "path"
import fs from "fs"
import { workspace, LanguageClient } from "coc.nvim"
import { configDir } from "./config"
import { showInstallStatus } from "./tools"

export async function updateLuaLsp(client: LanguageClient): Promise<void> {
await installLuaLsp(true)

if (client.needsStop()) {
await client.stop()
client.start()
}
}

export async function installLuaLsp(force = false): Promise<void> {
if (!force && (await luaLspExists())) {
return
}

await showInstallStatus("Alloyed/lua-lsp", async () => {
const baseDir = await configDir("tools")
let installCmd = `luarocks install --tree ${baseDir} --server=http://luarocks.org/dev lua-lsp`

const luaVersion = workspace.getConfiguration().get("lua", {})["version"]
if (luaVersion) {
installCmd += ` --lua-version=${luaVersion}`
}

await workspace.runTerminalCommand(installCmd)
})
}

export async function luaLspCommand(): Promise<string> {
const baseDir = await configDir("tools")

// binary installed by luarocks under Windows has extension '.bat'
const bin = process.platform === "win32" ? "lua-lsp.bat" : "lua-lsp"

return path.join(baseDir, "bin", bin)
}

export async function luaLspExists(): Promise<boolean> {
const bin = await luaLspCommand()
return new Promise((resolve) => fs.open(bin, "r", (err) => resolve(err === null)))
}
30 changes: 21 additions & 9 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import fs from 'fs'
import os from 'os'
import path from 'path'
import fs from "fs"
import os from "os"
import path from "path"
import { workspace } from "coc.nvim"

interface LuaConfig {
commandPath: string
enable: boolean
useSumnekoLs: boolean
}

export function getConfig(): LuaConfig {
return workspace.getConfiguration().get("lua", {}) as LuaConfig
}

interface State {
storagePath?: string
Expand All @@ -13,16 +24,17 @@ export function setStoragePath(dir: string): void {
}

export async function configDir(...names: string[]): Promise<string> {
const storage = state.storagePath || ((): string => {
const home = os.homedir()
return path.join(home, '.config', 'coc', 'lua')
})()
const storage =
state.storagePath ||
((): string => {
const home = os.homedir()
return path.join(home, ".config", "coc", "lua")
})()

const dir = path.join(storage, ...names)

return new Promise((resolve) => {
fs.mkdirSync(dir, {recursive: true})
fs.mkdirSync(dir, { recursive: true })
resolve(dir)
})

}
39 changes: 39 additions & 0 deletions src/utils/sumneko-lua-ls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import fs from "fs"
import path from "path"
import { LanguageClient } from "coc.nvim"
import { configDir } from "./config"
import { osEnv, install } from "./installer"
import { showInstallStatus } from "./tools"

const luaLsDir = "sumneko_lua"

export async function updateLuaLs(client: LanguageClient): Promise<void> {
await installLuaLs(true)

if (client.needsStop()) {
await client.stop()
client.start()
}
}

export async function installLuaLs(force = false): Promise<void> {
if (!force && (await luaLsExists())) {
return
}

await showInstallStatus("sumneko/lua-language-server", async () => {
await install(await configDir("tools", luaLsDir))
})
}

export async function luaLsCommandAndArgs(): Promise<[string, string[]]> {
const baseDir = await configDir("tools")

const { bin } = osEnv()
return [path.join(baseDir, luaLsDir, bin), ["-E", path.join(baseDir, luaLsDir, "main.lua")]]
}

export async function luaLsExists(): Promise<boolean> {
const [bin] = await luaLsCommandAndArgs()
return new Promise((resolve) => fs.open(bin, "r", (err) => resolve(err === null)))
}
61 changes: 16 additions & 45 deletions src/utils/tools.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,24 @@
import path from "path"
import fs from "fs"
import { workspace } from "coc.nvim"
import which from "which"
import { configDir } from "./config"
import { osEnv, install } from "./installer"

const lspDir = "sumneko_lua"

export async function installLuaLsp(force = false): Promise<void> {
if (!force && (await luaLspExists())) {
return
}

const useSumnekoLs = workspace.getConfiguration().get("lua.useSumnekoLs", false)
if (useSumnekoLs) {
return install(await configDir("tools", lspDir))
}

const baseDir = await configDir("tools")
let installCmd = `luarocks install --tree ${baseDir} --server=http://luarocks.org/dev lua-lsp`

const luaVersion = workspace.getConfiguration().get("lua", {})["version"]
if (luaVersion) {
installCmd += ` --lua-version=${luaVersion}`
}
import { workspace } from "coc.nvim"

await workspace.runTerminalCommand(installCmd)
export async function commandExists(bin: string): Promise<boolean> {
return new Promise((resolve) => which(bin, (err) => resolve(err == null)))
}

export async function luaLspBin(): Promise<[string, string[]]> {
const baseDir = await configDir("tools")

const useSumnekoLs = workspace.getConfiguration().get("lua.useSumnekoLs", false)
if (useSumnekoLs) {
const { bin } = osEnv()
return [path.join(baseDir, lspDir, bin), ["-E", path.join(baseDir, lspDir, "main.lua")]]
}

// binary installed by luarocks under Windows has extension '.bat'
const bin = process.platform === "win32" ? "lua-lsp.bat" : "lua-lsp"
export async function showInstallStatus(name: string, fn: () => Promise<void>): Promise<void> {
const statusItem = workspace.createStatusBarItem(90, { progress: true })

return [path.join(baseDir, "bin", bin), []]
}
statusItem.text = `Installing '${name}'`
statusItem.show()

export async function luaLspExists(): Promise<boolean> {
const [bin] = await luaLspBin()
return new Promise((resolve) => fs.open(bin, "r", (err) => resolve(err === null)))
}
try {
await fn()
workspace.showMessage(`Installed '${name}'`)
} catch (err) {
workspace.showMessage(`Failed to install '${name}': ${err}`, "error")
statusItem.hide()
throw err
}

export async function commandExists(command: string): Promise<boolean> {
return new Promise((resolve) => which(command, (err) => resolve(err == null)))
statusItem.hide()
}

0 comments on commit 2bd0e18

Please sign in to comment.