2018-12-21 14:08:14 +08:00
|
|
|
/**
|
|
|
|
* 编译系统
|
|
|
|
*
|
2022-04-28 13:54:51 +08:00
|
|
|
* @author yutent<yutent.io@gmail.com>
|
2018-12-21 14:08:14 +08:00
|
|
|
* @date 2018/12/20 11:37:54
|
|
|
|
*/
|
|
|
|
|
|
|
|
const vsc = require('vscode')
|
|
|
|
const exec = require('child_process').exec
|
|
|
|
const path = require('path')
|
|
|
|
const os = require('os')
|
|
|
|
const kill = require('tree-kill')
|
|
|
|
|
|
|
|
const log = console.log
|
|
|
|
const std = vsc.window.createOutputChannel('build-system')
|
2022-04-28 13:54:51 +08:00
|
|
|
std.out = function (msg) {
|
2018-12-21 14:08:14 +08:00
|
|
|
std.appendLine(msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
const EXTS = {
|
|
|
|
'.bat': 'cmd /c',
|
|
|
|
'.dart': 'dart',
|
|
|
|
'.go': 'go run',
|
|
|
|
'.js': 'node',
|
2020-09-18 14:11:30 +08:00
|
|
|
'.cjs': 'node',
|
|
|
|
'.mjs': 'node',
|
2018-12-21 17:12:58 +08:00
|
|
|
'.json': 'npm start',
|
2022-04-28 13:54:51 +08:00
|
|
|
'.py': 'python3 -u',
|
2019-01-05 04:34:41 +08:00
|
|
|
'.php': 'php',
|
2018-12-21 14:08:14 +08:00
|
|
|
'.sh': 'bash',
|
|
|
|
'.swift': 'swift',
|
2020-11-04 21:59:49 +08:00
|
|
|
'.ts': 'ts-node'
|
2018-12-21 14:08:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const BuildSystem = {
|
|
|
|
build() {
|
|
|
|
let editor = vsc.window.activeTextEditor
|
|
|
|
|
|
|
|
if (this.__RUNNING__) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (editor) {
|
|
|
|
this.__DOC__ = editor.document
|
|
|
|
this.__CWD__ = path.dirname(this.__DOC__.fileName)
|
|
|
|
|
|
|
|
if (this.__DOC__.languageId === 'Log') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 先保存
|
|
|
|
if (this.__OPTION__.saveBeforeBuild) {
|
|
|
|
vsc.workspace
|
|
|
|
.saveAll()
|
|
|
|
.then(_ => {
|
|
|
|
if (this.__DOC__.isUntitled) {
|
|
|
|
if (!this.__DOC__.isDirty) {
|
|
|
|
return Promise.reject('空文件无法直接执行...')
|
|
|
|
}
|
|
|
|
return this.__DOC__.save()
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
.then(saved => {
|
|
|
|
if (saved) {
|
|
|
|
this.__start__()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(err => {
|
|
|
|
vsc.window.showInformationMessage('空文件无法直接执行...')
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
this.__start__()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
stop() {
|
|
|
|
if (this.__PROGRESS__) {
|
|
|
|
kill(this.__PROGRESS__.pid)
|
|
|
|
}
|
|
|
|
this.__RUNNING__ = false
|
|
|
|
// todo...
|
|
|
|
},
|
|
|
|
|
|
|
|
// 初始化 配置
|
|
|
|
__init__(opt) {
|
|
|
|
this.__OPTION__ = opt
|
|
|
|
},
|
|
|
|
|
|
|
|
__start__() {
|
|
|
|
this.__parseCmd__()
|
|
|
|
|
|
|
|
if (!this.__CMD__) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
this.__RUNNING__ = true
|
|
|
|
if (this.__OPTION__.runInTerminal) {
|
|
|
|
this.__runInTerminal__()
|
|
|
|
} else {
|
|
|
|
this.__output__()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
__parseCmd__() {
|
|
|
|
let firstLine = this.__DOC__.lineAt(0).text
|
|
|
|
let ext = path.extname(this.__DOC__.fileName)
|
2018-12-23 15:36:56 +08:00
|
|
|
let file = path.basename(this.__DOC__.fileName)
|
2018-12-21 14:08:14 +08:00
|
|
|
let lang = EXTS[ext]
|
2018-12-23 15:36:56 +08:00
|
|
|
|
2018-12-21 14:08:14 +08:00
|
|
|
if (firstLine.startsWith('#!')) {
|
|
|
|
lang = firstLine.slice(2)
|
|
|
|
}
|
|
|
|
if (!lang) {
|
|
|
|
this.__CMD__ = null
|
|
|
|
if (this.__OPTION__.runInTerminal) {
|
|
|
|
if (this.__TERMINAL__) {
|
|
|
|
vsc.commands.executeCommand('workbench.action.terminal.clear')
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
std.clear()
|
|
|
|
}
|
|
|
|
return vsc.window.showInformationMessage('不支持的语言...')
|
|
|
|
}
|
2018-12-23 15:36:56 +08:00
|
|
|
if (ext === '.json') {
|
|
|
|
this.__CMD__ = lang
|
|
|
|
} else {
|
|
|
|
this.__CMD__ = `${lang} "${file}"`
|
|
|
|
}
|
2018-12-21 14:08:14 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
// 在终端内运行
|
|
|
|
__runInTerminal__() {
|
|
|
|
let hasTerminal = vsc.window.terminals.some(it => it.name === 'BuildSystem')
|
|
|
|
|
|
|
|
if (hasTerminal) {
|
|
|
|
vsc.window.terminals.forEach(it => {
|
|
|
|
if (it.name === 'BuildSystem') {
|
|
|
|
this.__TERMINAL__ = it
|
|
|
|
}
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
this.__TERMINAL__ = vsc.window.createTerminal('BuildSystem')
|
|
|
|
}
|
|
|
|
this.__TERMINAL__.show()
|
|
|
|
|
|
|
|
if (hasTerminal) {
|
|
|
|
vsc.commands.executeCommand('workbench.action.terminal.clear').then(_ => {
|
|
|
|
this.__TERMINAL__.sendText(this.__CMD__)
|
|
|
|
this.__RUNNING__ = false
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
this.__TERMINAL__.sendText(this.__CMD__)
|
|
|
|
this.__RUNNING__ = false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// 直接输出
|
|
|
|
__output__() {
|
|
|
|
// 运行前先清除之前的输出
|
|
|
|
std.clear()
|
|
|
|
|
|
|
|
std.show(true)
|
|
|
|
|
|
|
|
let t1 = Date.now()
|
|
|
|
|
|
|
|
this.__PROGRESS__ = exec(this.__CMD__, { cwd: this.__CWD__ })
|
|
|
|
|
|
|
|
// 运行输出
|
|
|
|
this.__PROGRESS__.stdout.on('data', _ => {
|
|
|
|
std.append(_)
|
|
|
|
})
|
|
|
|
|
|
|
|
// 异常输出
|
|
|
|
this.__PROGRESS__.stderr.on('data', _ => {
|
|
|
|
std.append(_)
|
|
|
|
})
|
|
|
|
|
|
|
|
// 结束
|
|
|
|
this.__PROGRESS__.on('close', _ => {
|
|
|
|
let t2 = Date.now()
|
|
|
|
let time = (t2 - t1) / 1000
|
|
|
|
std.out('')
|
|
|
|
std.out('[Finished in ' + time + ' seconds]')
|
|
|
|
this.__PROGRESS__ = null
|
|
|
|
this.__RUNNING__ = false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = BuildSystem
|