From 0cd878adfbb5cc7576fccb7d44b47a7fdb272602 Mon Sep 17 00:00:00 2001 From: fofolee Date: Sun, 10 Apr 2022 12:01:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20{{py}}=20=E5=92=8C=20{{js}?= =?UTF-8?q?}=20=E4=B8=A4=E4=B8=AA=E7=89=B9=E6=AE=8A=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/preload.js | 19 +++++++- src/components/CommandRunResult.vue | 4 +- src/js/options/specialVars.js | 70 ++++++++++++++++++----------- 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/public/preload.js b/public/preload.js index 35b2f5a..fd96912 100644 --- a/public/preload.js +++ b/public/preload.js @@ -4,7 +4,8 @@ const child_process = require("child_process") const iconv = require('iconv-lite') const electron = require('electron') const { - NodeVM + NodeVM, + VM } = require('./lib/vm2') const path = require("path") const util = require("util") @@ -187,6 +188,18 @@ if (process.platform == 'win32') quickcommand.runVbs = function(script) { }) } +// python -c +runPythonCommand = py => { + try { + return child_process.execFileSync("python", ["-c", py], { + windowsHide: true, + }) + } catch (e) { + utools.showNotification(e) + return "" + } +} + // 在终端中执行 if (process.platform !== 'linux') quickcommand.runInTerminal = function(cmdline, dir) { @@ -347,6 +360,10 @@ let parseItem = item => { let parseStdout = stdout => stdout.map(x => parseItem(x)).join("\n") +VmEval = (cmd, sandbox = {}) => new VM({ + sandbox: sandbox +}).run(cmd) + // The vm module of Node.js is deprecated in the renderer process and will be removed runCodeInVm = (cmd, cb) => { const vm = createNodeVM() diff --git a/src/components/CommandRunResult.vue b/src/components/CommandRunResult.vue index e7446c2..2b7a8e1 100644 --- a/src/components/CommandRunResult.vue +++ b/src/components/CommandRunResult.vue @@ -119,7 +119,7 @@ export default { assignSpecialVars(cmd) { let spVars = _.filter(specialVars, (sp) => sp.repl); _.forIn(spVars, (val, key) => { - if (cmd.includes(val.label.slice(0, 12))) { + if (cmd.includes(val.label.slice(0, -2))) { cmd = cmd.replace(val.match, (x) => val.repl(x)); } }); @@ -180,7 +180,7 @@ export default { showRunResult(content, isSuccess, action) { this.isResultShow = true; this.runResultStatus = isSuccess; - let contlength = content.length; + let contlength = content?.length || 0; if (contlength > this.resultMaxLength) content = content.slice(0, this.resultMaxLength - 100) + diff --git a/src/js/options/specialVars.js b/src/js/options/specialVars.js index dd30cdc..135b46b 100644 --- a/src/js/options/specialVars.js +++ b/src/js/options/specialVars.js @@ -8,21 +8,21 @@ let escapeItem = item => { return item.replace('$', '$$$') } -let parseTheFirstLayerOfObjects = obj => { - let matched = /{{(\w+)(\[(\d+)\]){0,1}\.(\w+)}}/.exec(obj); - return matched ? { - obj: matched[1], - index: matched[3], - prop: matched[4], - } : {}; +let handlingJsonVar = (jsonVar, name) => { + try { + return escapeItem(window.VmEval(jsonVar.slice(2, -2), { + [name]: quickcommand.enterData.payload + })) + } catch { + return "" + } } -let handlingJsonVar = (jsonVar, srcObj) => { +let handlingJsExpression = js => { try { - let parsed = parseTheFirstLayerOfObjects(jsonVar); - if (!parsed.obj) return escapeItem(srcObj) - else if (!parsed.index) return escapeItem(srcObj[parsed.prop]) - else return escapeItem(srcObj[parsed.index][parsed.prop]) + return window.VmEval(js.slice(5, -2), { + utools: window.getuToolsLite(), + }) } catch { return "" } @@ -63,10 +63,9 @@ const specialVars = { }, subinput: { name: "subinput", - label: "{{subinput}}", + label: "{{subinput:请输入}}", disabledType: [], - tooltip: `可以自定义占位符,如{{subinput:请输入}}`, - desc: "子输入框的文本", + desc: "子输入框的文本,冒号后为占位符", match: /{{subinput(:.+?){0,1}}}/mg, }, input: { @@ -86,11 +85,10 @@ const specialVars = { WindowInfo: { name: "WindowInfo", label: "{{WindowInfo}}", - desc: "当前窗口信息,JSON格式字符串", - tooltip: `可以选择性读取其中的某一个属性,如{{WindowInfo.id}}`, + desc: "当前窗口信息,JSON格式,可以指定键值,如{{WindowInfo.id}}", type: "json", - match: /{{WindowInfo(\.\w{1,7}){0,1}}}/mg, - repl: jsonVar => handlingJsonVar(jsonVar, quickcommand.enterData.payload) + match: /{{WindowInfo(.*?)}}/mg, + repl: jsonVar => handlingJsonVar(jsonVar, "WindowInfo") }, SelectFile: { name: "SelectFile", @@ -102,25 +100,43 @@ const specialVars = { MatchedFiles: { name: "MatchedFiles", label: "{{MatchedFiles}}", - tooltip: `可以选择性读取其中的某一个属性,如{{MatchedFiles[0].path}}`, - desc: "匹配的文件,JSON格式字符串", + desc: "匹配的文件,JSON格式,可以指定键值,如{{MatchedFiles[0].path}}", type: "json", - match: /{{MatchedFiles(\[\d+\]){0,1}(\.\w{1,11}){0,1}}}/mg, - repl: jsonVar => handlingJsonVar(jsonVar, quickcommand.enterData.payload) + match: /{{MatchedFiles(.*?)}}/mg, + repl: jsonVar => handlingJsonVar(jsonVar, "MatchedFiles") }, type: { name: "type", label: "{{type}}", - desc: "专业模式的type", + desc: "onPluginEnter的type,匹配的类型", match: /{{type}}/mg, repl: () => quickcommand.enterData.type }, payload: { name: "payload", label: "{{payload}}", - desc: "专业模式的payload", - match: /{{payload}}/mg, - repl: () => escapeItem(quickcommand.enterData.payload) + desc: "onPluginEnter的payload,当为JSON时可以指定键值,如{{payload.id}}", + type: "json", + match: /{{payload(.*?)}}/mg, + repl: jsonVar => handlingJsonVar(jsonVar, "payload") + }, + js: { + name: "js", + label: "{{js:}}", + desc: "获取js表达式的值,如{{js:utools.isMacOs()}}", + tooltip: "注意,必须为表达式而非语句,类似Vue的文本插值。不支持异步/Node", + type: "command", + match: /{{js:(.*?)}}/mg, + repl: js => handlingJsExpression(js) + }, + python: { + name: "python", + label: "{{py:}}", + desc: "模拟python -c,并获取返回值,如{{py:print(1)}}", + tooltip: "只支持单行语句", + type: "command", + match: /{{py:(.*?)}}/mg, + repl: py => window.runPythonCommand(py.slice(5, -2)) } }