uTools-quickcommand/src/pages/CodeRunner.vue
2022-03-31 10:23:50 +08:00

324 lines
9.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="q-pa-md">
<div class="row q-gutter-sm">
<div class="col-3">
<div style="max-width: 300px">
<q-select
dense
outlined
label-color="primary"
v-model="program"
:options="options"
label="编程语言"
>
<template v-slot:append>
<q-avatar rounded>
<img :src="'/logo/' + program + '.png'" />
</q-avatar>
</template>
<template v-slot:option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section avatar>
<img width="32" :src="'/logo/' + scope.opt + '.png'" />
</q-item-section>
<q-item-section>
<q-item-label v-html="scope.opt" />
</q-item-section>
</q-item>
</template>
</q-select>
</div>
</div>
<div class="col">
<div class="row q-gutter-sm" v-show="program === 'custom'">
<div class="col">
<q-input
dense
v-model="customOptions.bin"
stack-label
label="解释器路径"
/>
</div>
<div class="col">
<q-input
dense
v-model="customOptions.argv"
stack-label
label="解释器参数"
/>
</div>
<div class="col">
<q-input
dense
v-model="customOptions.ext"
@blur="matchLanguage"
label="后缀,不含."
stack-label
/>
</div>
</div>
</div>
<div class="col-auto doc-container">
<div class="row q-gutter-sm items-center justify-end">
<q-input
dense
outlined
style="width: 90px"
v-model="scptarg"
label="脚本参数"
v-show="program !== 'quickcommand'"
/>
<q-btn
color="primary"
label="文档"
@click="showHelp"
v-show="program === 'quickcommand'"
/>
<q-btn
color="primary"
label="编码设置"
@click="showCodingPage()"
v-show="program !== 'quickcommand'"
/>
<q-btn color="primary" @click="runCurrentCommand()" label="运行" />
</div>
</div>
</div>
<div class="row">
<div
id="monocaEditor"
style="
position: fixed;
bottom: 1px;
left: 1px;
right: 1px;
top: 70px;
border-radius: 4px;
border: 2px solid #3376cd;
"
/>
</div>
<q-dialog v-model="isResultShow" @hide="runResult = ''" position="bottom">
<q-card style="width: 90vh">
<q-toolbar>
<q-avatar>
<q-icon
:class="runResultStatus ? 'text-green' : 'text-red'"
style="font-size: 30px"
:name="runResultStatus ? 'task_alt' : 'error'"
></q-icon>
</q-avatar>
<q-toolbar-title
><span class="text-weight-bold">运行结果</span></q-toolbar-title
>
</q-toolbar>
<q-card-section class="row items-center">
<pre
:class="runResultStatus ? '' : 'text-red'"
v-html="runResult"
></pre>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="关闭" color="primary" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
</div>
</template>
<script>
import globalVars from "components/GlobalVars";
import * as monaco from "monaco-editor";
import { toRaw } from "vue";
import utoolsApi from "!raw-loader!../types/utools.api.d.ts";
import quickcommandApi from "!raw-loader!../types/quickcommand.api.d.ts";
import electronApi from "!raw-loader!../types/electron.d.ts";
import nodeApi from "!raw-loader!../types/node.api.d.ts";
import commonApi from "!raw-loader!../types/common.d.ts";
export default {
data() {
return {
options: Object.keys(globalVars.programs),
program: "quickcommand",
editor: null,
customOptions: { bin: "", argv: "", ext: "" },
scptarg: "",
scriptCode: "",
outputCode: "",
output: "",
isResultShow: false,
runResult: "",
runResultStatus: true,
resultMaxLength: 10000,
};
},
mounted() {
this.initEditor();
},
computed: {},
created() {},
watch: {
program(val) {
this.setLanguage(val);
},
},
methods: {
initEditor() {
let that = this;
this.editor = monaco.editor.create(
document.getElementById("monocaEditor"),
{
value: "",
language: "javascript",
automaticLayout: true,
foldingStrategy: "indentation",
autoClosingBrackets: true,
tabSize: 2,
minimap: {
enabled: false,
},
}
);
this.editor.addCommand(
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB,
function () {
that.runCurrentCommand();
}
);
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true,
noSyntaxValidation: false,
});
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES6,
allowNonTsExtensions: true,
allowJs: true,
lib: [],
});
monaco.languages.typescript.javascriptDefaults.addExtraLib(
quickcommandApi + utoolsApi + electronApi + nodeApi + commonApi,
"api.d.ts"
);
},
getEditorValue() {
return toRaw(this.editor).getValue();
},
matchLanguage() {
let language = Object.values(globalVars.programs).filter(
(program) => program.ext === this.customOptions.ext
);
if (language.length) {
this.setLanguage(language[0].name);
}
},
setLanguage(language) {
let highlight = globalVars.programs[language].highlight;
monaco.editor.setModelLanguage(
this.editor.getModel(),
highlight ? highlight : language
);
},
showHelp() {
utools.createBrowserWindow("./helps/quickcommand.html", {
width: 1280,
height: 920,
});
},
showCodingPage() {
quickcommand.showInputBox(
["文件编码", "输出编码"],
"编码设置",
["基于iconv-lite进行编码无乱码请留空", "无乱码请留空"],
(res) => {
if (res) [this.scriptCode, this.outputCode] = res;
}
);
},
async runCurrentCommand() {
let cmd = this.getEditorValue();
cmd = window.special(cmd);
cmd = await this.replaceTempInputVals(cmd);
let terminal = false;
let raw = true;
switch (this.output) {
case "html":
raw = false;
break;
case "terminal":
terminal = true;
break;
case "ignore":
utools.hideMainWindow();
break;
}
if (this.program === "quickcommand") {
window.runCodeInVm(cmd, (stdout, stderr) => {
if (stderr) return this.showRunResult(stderr, raw, false);
this.showRunResult(stdout, raw, true);
});
} else {
let option = globalVars.programs[this.program];
if (this.program === "custom")
option = {
bin: this.customOptions.bin,
argv: this.customOptions.argv,
ext: this.customOptions.ext,
};
option.scptarg = this.scptarg;
option.charset = {
scriptCode: this.scriptCode,
outputCode: this.outputCode,
};
window.runCodeFile(cmd, option, terminal, (stdout, stderr) => {
if (terminal) return;
if (stderr) return this.showRunResult(stderr, raw, false);
this.showRunResult(stdout, raw, true);
});
}
},
async replaceTempInputVals(cmd) {
let tempInputVals = [];
let specilaVals = [
"input",
"subinput",
"pwd",
"SelectFile",
"WindowInfo",
"MatchedFiles",
];
specilaVals.forEach((x) => {
let m = cmd.match(new RegExp("{{" + x + ".*?}}", "g"));
m &&
m.forEach((y) => tempInputVals.includes(y) || tempInputVals.push(y));
});
if (!tempInputVals.length) return cmd;
let inputs = await quickcommand.showInputBox(
tempInputVals,
"需要临时为以下变量赋值"
);
tempInputVals.forEach((t, n) => {
cmd = cmd.replace(new RegExp(t, "g"), inputs[n]);
});
return cmd;
},
showRunResult(content, raw, isSuccess) {
this.isResultShow = true;
this.runResultStatus = isSuccess;
let contlength = content.length;
if (contlength > this.resultMaxLength)
content =
content.slice(0, this.resultMaxLength - 100) +
`\n\n...\n${
contlength - this.resultMaxLength - 100
} 字省略\n...\n\n` +
content.slice(contlength - 100);
this.runResult += htmlEncode(content, raw);
},
},
};
</script>
<style scoped>
</style>