Status bar items and glslangValidator download

glslangValidator download done in client side
both client and server create status bar items to notify of progress etc
This commit is contained in:
Noah Santschi-Cooney 2020-02-16 23:56:41 +00:00
parent 46215f8a91
commit 36fd728533
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
3 changed files with 189 additions and 55 deletions

View file

@ -1,40 +1,72 @@
import * as path from 'path'
import * as vscode from 'vscode'
import * as vscodeLang from 'vscode-languageclient'
import { promptDownload, testExecutable } from './glslangValidator'
export const glslConfigParam = 'mcglsl.glslangValidatorPath'
export let outputChannel: vscode.OutputChannel
let statusBarItem: vscode.StatusBarItem
let globalContext: vscode.ExtensionContext
export async function activate(context: vscode.ExtensionContext) {
const outputChannel = vscode.window.createOutputChannel('vscode-mc-shader')
outputChannel = vscode.window.createOutputChannel('vscode-mc-shader')
globalContext = context
const clientOpts: vscodeLang.LanguageClientOptions = {
documentSelector: [{scheme: 'file', language: 'glsl'}],
outputChannel: outputChannel,
outputChannelName: 'vscode-mc-shader',
synchronize: {
configurationSection: 'mcglsl',
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{fsh,gsh,vsh,glsl}')
},
{
if (!testExecutable(vscode.workspace.getConfiguration().get(glslConfigParam))) {
await promptDownload()
} else {
outputChannel.appendLine('glslangValidator found!')
}
}
const serverOpts: vscodeLang.ServerOptions = {
command: context.asAbsolutePath(path.join('server', 'target', 'debug', 'vscode-mc-shader')),
}
outputChannel.appendLine('starting language server...')
const langServer = new vscodeLang.LanguageClient('vscode-mc-shader', serverOpts, clientOpts)
context.subscriptions.push(langServer.start())
await langServer.onReady()
{
langServer.onNotification('sampleText', (...nums: number[]) => {
outputChannel.appendLine(`got notif: ${nums.join(' ')}`)
})
const clientOpts: vscodeLang.LanguageClientOptions = {
documentSelector: [{scheme: 'file', language: 'glsl'}],
outputChannel: outputChannel,
outputChannelName: 'vscode-mc-shader',
synchronize: {
configurationSection: 'mcglsl',
fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{fsh,gsh,vsh,glsl}')
},
}
langServer.onNotification('update-config', (dir: string) => {
vscode.workspace.getConfiguration().update('mcglsl.glslangValidatorPath', dir, vscode.ConfigurationTarget.Global)
})
const serverOpts: vscodeLang.ServerOptions = {
command: context.asAbsolutePath(path.join('server', 'target', 'debug', 'vscode-mc-shader')),
}
outputChannel.appendLine('language server started!')
outputChannel.appendLine('starting language server...')
const langServer = new vscodeLang.LanguageClient('vscode-mc-shader', serverOpts, clientOpts)
context.subscriptions.push(langServer.start())
await langServer.onReady()
langServer.onNotification('updateConfig', (dir: string) => {
vscode.workspace.getConfiguration().update(glslConfigParam, dir, vscode.ConfigurationTarget.Global)
})
langServer.onNotification('status', updateStatus)
langServer.onNotification('clearStatus', clearStatus)
outputChannel.appendLine('language server started!')
}
}
export function updateStatus(icon: string, text: string) {
if(statusBarItem != null) statusBarItem.dispose()
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left)
statusBarItem.text = icon + " [Minecraft Shaders] " + text
statusBarItem.show()
globalContext.subscriptions.push(statusBarItem)
}
export function clearStatus() {
if(statusBarItem != null) statusBarItem.dispose()
}

View file

@ -0,0 +1,89 @@
import * as unzip from 'adm-zip'
import { execSync } from 'child_process'
import { writeFileSync } from 'fs'
import fetch from 'node-fetch'
import { platform } from 'os'
import * as vscode from 'vscode'
import { clearStatus, glslConfigParam, outputChannel, updateStatus } from './extension'
const url = {
'win32': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-windows-x64-Release.zip',
'linux': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-linux-Release.zip',
'darwin': 'https://github.com/KhronosGroup/glslang/releases/download/master-tot/glslang-master-osx-Release.zip'
}
const config = vscode.workspace.getConfiguration()
export async function promptDownload() {
const chosen = await vscode.window.showErrorMessage(
`[mc-glsl] glslangValidator not found at: '${config.get(glslConfigParam)}'.`,
{title: 'Download'},
{title: 'Cancel'}
)
if (!chosen || chosen.title !== 'Download') return
await installExecutable()
}
async function installExecutable() {
try {
updateStatus('$(cloud-download)', 'Downloading glslangValidator')
const glslangBin = '/glslangValidator' + (platform() === 'win32' ? '.exe' : '')
const glslangPath = config.get('mcglsl.shaderpacksPath') + glslangBin
const response = await fetch(url[platform()])
outputChannel.appendLine('glslangValidator download response status: ' + response.status )
const zip = new unzip(await response.buffer())
const bin = zip.readFile('bin' + glslangBin)
outputChannel.appendLine('buffer length ' + bin.length)
writeFileSync(glslangPath, bin, {encoding: null, mode: 0o755})
// Make sure download was successful
if (!testExecutable(glslangPath)) {
vscode.window.showErrorMessage(`Unexpected error occurred checking for binary at ${glslangPath}. Please try again`)
clearStatus()
throw new Error('failed to install glslangValidator')
}
// All done!
outputChannel.appendLine(`successfully downloaded glslangValidator to ${glslangPath}`)
vscode.window.showInformationMessage(
`glslangValidator has been downloaded to ${glslangPath}. Your config should be updated automatically.`
)
config.update('mcglsl.glslangValidatorPath', glslangPath, vscode.ConfigurationTarget.Global)
clearStatus()
} catch (e) {
outputChannel.appendLine(`failed downloading glslangValidator ${e}`)
vscode.window.showErrorMessage(`Failed to install glslangValidator: ${e}`)
clearStatus()
throw e
}
}
export function testExecutable(glslangPath?: string): boolean {
glslangPath = glslangPath || config.get(glslConfigParam)
let stdout = ''
try {
stdout = execSync(glslangPath, {
stdio: 'pipe',
}).toString()
} catch (e) {
stdout = (e.stdout.toString() as string)
}
outputChannel.appendLine('glslangValidator first line stdout: "' + stdout.split('\n')[0] + '"')
const success = stdout.startsWith('Usage')
if (success) {
outputChannel.appendLine(`glslangValidator found at ${glslangPath}`)
} else {
outputChannel.appendLine(`glslangValidator not found at ${glslangPath}`)
}
return success
}