!function () { getDB = id => { var db = utools.db.get(id), dbData = db ? db.data : {}; return dbData; } putDB = (code, pushData, id) => { var db = utools.db.get(id); if (db) { var rev = db._rev var data = db.data data[code] = pushData; utools.db.put({ _id: id, data: data, _rev: rev }); } else { var data = {}; data[code] = pushData; utools.db.put({ _id: id, data: data }); } } let isJsonQc = obj => { var keys = ["features", "program", "cmd", "output"] if (keys.filter(x => typeof obj[x] == 'undefined').length) return false return true } // 判断是否为可导入的快捷命令 let quickCommandParser = json => { try { var qc = JSON.parse(json) } catch (error) { return false } if (isJsonQc(qc)) return { single: true, qc: qc } else if (!Object.values(qc).filter(q => !isJsonQc(q)).length) return { single: false, qc: qc } else return false } // 导入 importCommand = file => { var pushData, clipboardText = clipboardReadText() if (!file) pushData = quickCommandParser(clipboardText) if (!pushData) { var options = file ? { type: 'file', argvs: file } : { type: 'dialog', argvs: { filters: [{ name: 'json', extensions: ['json'] }] } } options.readfile = true var fileinfo = getFileInfo(options) if (!fileinfo) return pushData = quickCommandParser(fileinfo.data) if (!pushData) return false } // 单个命令导入 if (pushData.single) { var code = pushData.qc.features.code; putDB(code, pushData.qc, 'customFts'); // 多个命令导入 } else { for (var code of Object.keys(pushData.qc)) { putDB(code, pushData.qc[code], 'customFts'); } } return true } let exportAll = () => { let jsonQc = utools.db.get('customFts').data, options = { title: '选择保存位置', defaultPath: 'quickCommand', filters: [ { name: 'json', extensions: ['json'] }, ] }; if (!fofoCommon.isDev()) Object.keys(jsonQc).filter(k => jsonQc[k].tags && jsonQc[k].tags.includes('默认')).map(k => delete jsonQc[k]) window.saveFile(options, JSON.stringify(jsonQc)); } let clearAll = () => { quickcommand.showConfirmBox('将会清空所有命令,请确认!').then(() => { utools.db.remove('customFts'); clearAllFeatures(); showOptions(); }) } let overwriteConfirm = () => { } programs = { shell: { bin: 'bash', argv: '', ext: 'sh', color: '#89e051' }, applescript: { bin: 'osascript', argv: '', ext: 'scpt', color: '#101F1F' }, cmd: { bin: '', argv: '', ext: 'bat', codec: 'gbk', color: '#C1F12E' }, powershell: { bin: 'powershell', argv: '-NoProfile -File', ext: 'ps1', codec: utools.isWindows() ? 'gbk' : '', color: '#012456' }, python: { bin: 'python', argv: '-u', ext: 'py', codec: utools.isWindows() ? 'gbk' : '', color: '#3572A5' }, javascript: { bin: 'node', argv: '', ext: 'js', color: '#f1e05a' }, ruby: { bin: 'ruby', argv: '', ext: 'rb', color: '#701516' }, php: { bin: 'php', argv: '', ext: 'php', color: '#4F5D95' }, c: { bin: 'gcc', argv: '-o', ext: 'c', codec: utools.isWindows() ? 'gbk' : '', color: '#555555' }, csharp: { bin: 'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe', argv: '/Nologo', ext: 'cs', codec: 'gbk', color: '#178600' }, lua: { bin: 'lua', argv: '', ext: 'lua', color: '#000080' }, perl: { bin: 'perl', argv: '', ext: 'pl', color: '#0298c3' }, custom: { bin: '', argv: '', ext: '', codec: '', color: '#438eff' } } showOptions = (tag = "默认") => { $("#options").empty().fadeIn(); var currentFts = utools.getFeatures(), customFts = getDB('customFts'); var allTags = ["默认"] var featureList = `
`; Object.values(customFts).some(fts => { var features = fts.features; if (fts.tags) { fts.tags.map(t => !allTags.includes(t) && allTags.push(t)) } if (tag == "未分类") { if (fts.tags && fts.tags.length) return false } else { if (!fts.tags) return false if (!fts.tags.includes(tag)) return false } var cmds = '', rules = features.cmds[0].match; if (features.cmds[0].type == 'regex') { if (rules.length > 14) rules = rules.slice(0, 14) + '...'; cmds = `
正则
${rules}
`; } else if (features.cmds[0].type == 'window') { cmds += `
窗口
` if (!rules) { cmds += `所有窗口` } else if (rules.title || rules.class) { cmds += `${JSON.stringify(rules).slice(0, 14) + '...'}`; } else if (rules.app) { rules = rules.app.join(",") if(rules.length > 14) rules = rules.slice(0, 14) + '...'; rules.split(',').forEach(r => { cmds += `${r}`; }); } cmds += `
` } else if (features.cmds[0].type == 'files') { if (rules.length > 14) rules = rules.slice(0, 14) + '...'; cmds = `
文件
${rules}
`; } else { rules = features.cmds.join(",") if(rules.length > 14) rules = rules.slice(0, 14) + '...'; cmds += `
关键字
` rules.split(',').forEach(r => { cmds += `${r}`; }); cmds += `
` } var isChecked = ''; for(var c of currentFts){ if (c.code == features.code) { isChecked = 'checked'; break; } } var platformIcons if (features.platform) platformIcons = features.platform.map(x => ``) else platformIcons = ['', '', ''] featureList += `` }) featureList += `
${features.explain}
${fts.program} | ${platformIcons.join('')}
${cmds} ${(tag == "默认" && !fofoCommon.isDev()) ? "" : ` `}
` var sidebar = ` ` var footer = `
新建命令
导入命令
分享中心
查看帮助
全部导出
启用本页
清空数据
禁用本页
` $("#options").append(sidebar + featureList + footer) } let showCustomize = (readonly = false) => { $("#customize").remove(); let options = `` let allTags = [] $('.sidebar li').each(function () { let val = $(this).text() if (val != "默认" && val != "未分类") allTags.push(``) }) let customWindow = `

匹 配 关键字

说 明

环 境 标 签

变 量 输 出

脚 本 ﹢动作 ﹢按键 ?文档 格式化

${(readonly && !fofoCommon.isDev()) ? '' : ''}

` $("#options").append(customWindow) $("#icon").attr('src', 'logo/quickcommand.png'); getSpecialVars() createEditor() createProgramSelect2('40%') createTypeSelect2('40%') var singleSelectOpt = { width: '40%', minimumResultsForSearch: Infinity, dropdownParent: $("#customize") } $('#output').select2(singleSelectOpt); singleSelectOpt.placeholder = "插入特殊变量" $('#vars').select2(singleSelectOpt); $('#tags').select2({ width: '40%', placeholder: "选择或添加标签, 最多3个", tags: true, allowClear: true, tokenSeparators: [',', ' '], maximumSelectionLength: 3, dropdownParent: $("#customize") }).on("select2:unselecting", e => { (e.params.args.data.text == "默认") && !fofoCommon.isDev() && e.preventDefault(); }).on("select2:selecting", e => { (e.params.args.data.text == "默认" || e.params.args.data.text == "未分类") && !fofoCommon.isDev() && e.preventDefault(); }) } let getSelect2Option = (data, width, dropdownAutoWidth = false) => { var options = { data: data, minimumResultsForSearch: Infinity, dropdownParent: $("#customize"), dropdownAutoWidth: dropdownAutoWidth, escapeMarkup: markup => markup, templateSelection: data => data.text, templateResult: data => data.html } if (width) options.width = width return options } let createTypeSelect2 = (width = false) => { var data = [ { id: "key", text: "关键字", html: "关键字
在主输入框输入对应关键字进入插件,最通用的一种模式,关键字可以设置多个
" }, { id: "regex", text: "正则/划词", html: "正则/划词
正则匹配主输入框文本或唤出语音面板时选中的文本,可以获取输入框文本或选中文本作为变量
" }, { id: "window", text: "窗口/进程", html: "窗口/进程
匹配呼出uTools前或唤出语音面板时的活动窗口,可以获取窗口的信息或文件夹路径作为变量
" }, { id: "files", text: "复制/选中文件", html: "复制/选中文件
匹配拖入主输入框的文件或唤出语音面板时选中的文件,可以获取复制及选中的文件信息作为变量
" } ] $('#type').select2(getSelect2Option(data, width)); } let createProgramSelect2 = (width, dropdownAutoWidth = false) => { var programStyled = p => `${p}` var data = [{ id: "quickcommand", text: 'quickcommand', html: programStyled('quickcommand') }] data = data.concat(Object.keys(programs).map(x => { return { id: x, text: x, html: programStyled(x) } })) $('#program').select2(getSelect2Option(data, width, dropdownAutoWidth)); } let createEditor = () => { window.editor = CodeMirror.fromTextArea(document.getElementById("cmd"), { lineNumbers: true, matchBrackets: true, // lineWrapping: true, autoCloseBrackets: true, styleActiveLine: true, keyMap: "sublime", theme: utools.isDarkColors() ? 'material-darker' : "mdn-like", extraKeys: { "Alt-Enter": () => { $('.CodeMirror').hasClass('CodeMirror-fullscreen') && $('.CodeMirror').removeClass('CodeMirror-fullscreen') || $('.CodeMirror').addClass('CodeMirror-fullscreen') }, "Ctrl-B": () => { runCurrentCommand() }, "Ctrl-S": () => { SaveCurrentCommand() }, "Ctrl-Q": () => { quitCurrentCommand() }, "Shift-Alt-F": () => { beautifyCode() }, "Alt-Up": "swapLineUp", "Alt-Down": "swapLineDown", "Shift-Alt-Down": "duplicateLine" } }); window.editor.on("change", showHint); window.editor.setOption("mode", 'javascript'); } showHint = () => { editor.showHint({ completeSingle: false }); } let beautifyCode = () => { if ($("#customize").is(":parent")) { var cmd = window.editor.getValue() switch ($("#program").val()) { case "quickcommand": case "javascript": window.editor.setValue(js_beautify(cmd, { brace_style: "collapse,preserve-inline" })) break; case "python": py_beautify(cmd, data => { window.editor.setValue(data) }) break; default: quickcommand.showMessageBox('暂不支持该语言的格式化', 'error') break; } } } // 获取特殊变量 let getSpecialVars = () => { var specialVars = [] $("#vars option").each(i => { var selector = $("#vars option").eq(i) if (selector.css('display') != 'none') specialVars.push(selector.val()) }) localStorage['specialVars'] = specialVars } let typeCheck = () => { var type = $("#type").val(); switch (type) { case 'key': $("#ruleWord").html("关键字"); $(".var.regex, .var.window, .var.files").prop("disabled", true) $("#rule").prop("placeholder", '多个关键字用逗号隔开'); break; case 'regex': $("#ruleWord").html("正 则"); $(".var.window, .var.files").prop("disabled", true) $(".var.regex").prop("disabled", false) $("#rule").prop("placeholder", '匹配文本的正则,如 /.*?\\.exe$/i'); break; case 'files': $("#ruleWord").html("正 则"); $(".var.regex, .var.window").prop("disabled", true) $(".var.files").prop("disabled", false) $("#rule").prop("placeholder", '匹配文件的正则,如 /.*?\\.exe$/i'); break; case 'window': $("#ruleWord").html("进 程"); $(".var.regex, .var.files").prop("disabled", true) $(".var.window").prop("disabled", false) $("#rule").prop("placeholder", '多个窗口进程逗号隔开,留空匹配所有窗口'); break; default: break; } getSpecialVars() } let clearAllFeatures = () => { for (var fts of utools.getFeatures()) { utools.removeFeature(fts.code) } } let hasCustomIcon = () => { var src = $("#icon").attr('src'); var iconame = $("#iconame").val(); return /data:image\/png;base64,/.test(src) || iconame } let programCheck = () => { let mode = $('#program').val(); $('.customscript').hide(); $('.quickactions').hide(); $('#scptarg').show(); $('#showInTerm').prop("disabled", false); if (!hasCustomIcon()) $("#icon").attr('src', `logo/${mode}.png`); switch (mode) { case 'custom': $('.customscript').show(); var customext = $('#customext').val() customext && (mode = highlightIfKnown(customext)) break; case 'quickcommand': $('.quickactions').show(); $('#scptarg').hide(); $('#showInTerm').prop("disabled", true); mode = 'javascript'; break; case 'csharp': case 'c': mode = 'text/x-' + mode break; case 'python': getPythonMods() break; case 'cmd': getCmdCommand() break; case 'shell': getShellCommand() break; default: break; } window.editor.setOption("mode", mode); } // 合规性校验 let cmdCheck = (type, cmd) => { var blacklist switch (type) { case 'key': blacklist = cmd.match(/{{input}}|{{SelectFile}}|{{pwd}}|{{WindowInfo}}|{{MatchedFiles}}/g) break; case 'regex': blacklist = cmd.match(/{{SelectFile}}|{{WindowInfo}}|{{pwd}}|{{MatchedFiles}}/g) if (/^(|\/)\.[*+](|\/)$/.test($('#rule').val())) return quickcommand.showMessageBox('正则匹配 .* 和 .+ 已被uTools禁用!', 'error') break; case 'window': blacklist = cmd.match(/{{input}}|{{MatchedFiles}}/g) break; case 'files': blacklist = cmd.match(/{{input}}|{{SelectFile}}|{{pwd}}|{{WindowInfo}}/g) break; default: break; } if (blacklist) { quickcommand.showMessageBox(`当前模式无法使用${Array.from(new Set(blacklist)).join("、")}`, 'error') return false } else { return true } } // 开关 $("#options").on('change', 'input[type=checkbox]', function () { var customFts = getDB('customFts'), code = $(this).parents('tr').attr('id') if (!utools.removeFeature(code)) { utools.setFeature(customFts[code].features); } }); // 底部功能按钮 $("#options").on('click', '.footBtn', function () { switch ($(this).attr('id')) { case 'viewHelps': utools.createBrowserWindow('./helps/HELP.html', {width: 1280, height: 920}); break; case 'getShares': getSharedQCFromYuQue(); break; case 'add': showCustomize(); $("#customize").animate({ top: '0px' }); break; case 'import': var success = importCommand() if (success) showOptions() || quickcommand.showMessageBox("导入成功") else if (success == false) quickcommand.showMessageBox("导入失败,格式错误", "error") break; case 'enableAll': $(".checked-switch:not(:checked)").click(); break; case 'disableAll': $(".checked-switch:checked").click(); break; case 'exportAll': exportAll(); break; case 'clear': clearAll(); break; } }) let editCurrentCommand = data => { let code = data.features.code let cmds = data.features.cmds[0] let platform = data.features.platform let readonly = false let extraInfo = { authorName: data.authorName, authorId: data.authorId, fromShare: data.fromShare } if (data.tags && data.tags.includes("默认")) readonly = true showCustomize(readonly); $('#customize').data('extraInfo', extraInfo) data.tags && $('#tags').val(data.tags).trigger('change') platform && ["win32", "darwin", "linux"].map(x => (!platform.includes(x) && $(`#${x}`).addClass('disabled'))) $('#type').val(cmds.type).trigger("change") if (cmds.type == 'regex' || cmds.type == 'files') { $('#rule').val(cmds.match); } else if (cmds.type == 'window') { if (!cmds.match) $('#rule').val(''); else if (cmds.match.title || cmds.match.class) $('#rule').val(JSON.stringify(cmds.match)); else $('#rule').val(cmds.match.app); } else { $('#type').val('key').trigger("change") $('#rule').val(data.features.cmds.toString()); } $('#code').val(code); $('#program').val(data.program).trigger("change"); $('#output').val(data.output).trigger("change"); $('#desc').val(data.features.explain); $('#scptarg').val(data.scptarg); $("#icon").attr('src', data.features.icon); let mode = data.program; if (mode == 'custom') { $('#custombin').show().val(data.customOptions.bin); $('#customarg').show().val(data.customOptions.argv); $('#customext').show().val(data.customOptions.ext); $('#customcodec').show().val(data.customOptions.codec); } typeCheck(); programCheck(); // 分段载入,保障动画流畅 window.editor.setValue(data.cmd.slice(0, 2000)); $("#customize").animate({ top: '0px' }, () => { window.editor.replaceRange(data.cmd.slice(2000), {line: Infinity}); }); } // 编辑 $("#options").on('click', '.editBtn', function () { let code = $(this).parents('tr').attr('id') let data = utools.db.get("customFts").data[code] editCurrentCommand(data) }) // 添加模拟按键 $("#options").on('click', '#addKey', function () { $("#addKey").text("▶ 录制中").addClass('record') quickcommand.showMessageBox('开始录制按键,可连续录制', 'info') Mousetrap.record(sequence => { sequence.forEach(s => { var keys = s if (s.includes('+') && s.length > 1) keys = s.split('+').reverse().map(x=>x.trim().replace('meta', 'command')).join(`", "`) window.editor.replaceSelection(`keyTap("${keys}")\n`) }) $("#addKey").text("﹢按键").removeClass('record') }); }) // quickCommand的帮助 $("#options").on('click', '#showHelp', function () { utools.createBrowserWindow('./helps/quickcommand.html', {width: 1280, height: 920}) }) // 添加动作 $("#options").on('click', '#addAction', function () { var html = ` 加引号 ` Swal.fire({ title: "预设动作", onBeforeOpen: () => { $('#actionType').change(function () { $('#actionArgs').attr('placeholder', $(this).find(`[value=${$(this).val().replace('.', '\\.')}]`).attr('args')) }) }, html: html, showCancelButton: true, preConfirm: () => { var actionType = $("#actionType").val() var actionArgs = $("#actionArgs").val() if ($("#isString").is(':checked')) actionArgs = "String.raw\`" + actionArgs + "\`" var action = `${actionType}(${actionArgs})` if (actionType == 'utools.ubrowser.goto') action += `.run()` window.editor.replaceSelection(`${action}\n`) } }) }) let setYuQueToken = async () => { let yuQueToken = await quickcommand.showInputBox(["请输入 Token"]) if (!yuQueToken) return yuQueToken = yuQueToken[0] yuQueClient.defaults.headers['X-Auth-Token'] = yuQueToken try { let res = await yuQueClient('user') let authorId = res.data.data.account_id let authorName = res.data.data.name putDB('yuQueToken', yuQueToken, 'extraInfo') putDB('authorName', authorName, 'extraInfo') putDB('authorId', authorId, 'extraInfo') quickcommand.showMessageBox("设置成功~") } catch (e) { quickcommand.showMessageBox('Token 校验失败', "error") } } let createShareMenu = jsonQc => { let menu = ['复制到剪贴板', '导出到文件', '', '设置 Token'] let extraInfo = getDB('extraInfo') if (jsonQc.authorId) { if (jsonQc.authorId == extraInfo.authorId) menu[2] = '更新分享' else if (jsonQc.fromShare) menu[2] = '评论' else menu[2] = '分享自:' + jsonQc.authorName } else { if (extraInfo.yuQueToken) menu[2] = '分享命令' else menu[2] = '我要分享' } return menu } // 导出 $("#options").on('click', '.exportBtn', async function () { var code = $(this).parents('tr').attr('id') var jsonQc = getDB('customFts')[code] var stringifyQc = JSON.stringify(jsonQc, null, 4) var choise = await quickcommand.showButtonBox(createShareMenu(jsonQc)) switch (choise.text) { case '复制到剪贴板': utools.copyText(stringifyQc) && quickcommand.showMessageBox('已复制到剪贴板') break; case '导出到文件': window.saveFile({ title: '选择保存位置', defaultPath: `${jsonQc.features.explain}.json`, filters: [ { name: 'json', extensions: ['json'] }, ] }, stringifyQc) break; case '分享命令': case '更新分享': var result = await shareQCToYuQue(jsonQc) result && quickcommand.showMessageBox('分享成功,等待发布后即可在分享中心直接下载') break; case '我要分享': utools.createBrowserWindow('./helps/HELP.html?#分享命令', {width: 1280, height: 920}) break; case '评论': utools.shellOpenExternal(`https://www.yuque.com/fofolee/qcreleases/${code}`) break; case '设置 Token': await setYuQueToken() break; } }) // 一键分享到语雀 let shareQCToYuQue = async jsonQc => { let extraInfo = getDB('extraInfo') if (!extraInfo.yuQueToken) return quickcommand.showMessageBox("请先设置 Token,点击底部「查看帮助」可查看 Token 设置方法", "error") jsonQc.authorId = extraInfo.authorId jsonQc.authorName = extraInfo.authorName let stringifyQc = JSON.stringify(jsonQc, null, 4) if (stringifyQc.length > 5000000) return quickcommand.showMessageBox('命令大小超过5M无法分享,请检查图标或脚本内容是否过大', "error") let platform = jsonQc.platform ? platform.join(" ") : "win32 darwin linux" let type = jsonQc.features.cmds[0].type let tags = jsonQc.tags ? jsonQc.tags.join(' ') : "" type || (type = 'keywords') let parameters = { title: jsonQc.features.explain, slug: jsonQc.features.code, public: 1, format: "markdown", body: '```json\n' + stringifyQc + '\n```', custom_description: `作者:${jsonQc.authorName} | 环境:${jsonQc.program} | 匹配:${type} | 平台:${platform} | 标签:${tags}` } yuQueClient.defaults.headers['X-Auth-Token'] = extraInfo.yuQueToken let res, repo = extraInfo.authorId == 1496740 ? 'qcreleases' : 'qcshares' console.log(repo); try { res = await yuQueClient.post(`repos/fofolee/${repo}/docs`, parameters) if (!res.data.data) return quickcommand.showMessageBox("分享失败,不知道为啥", "error") let docId = res.data.data.id res = await yuQueClient.put(`repos/fofolee/${repo}/docs/${docId}`, parameters) if (!res.data.data) return quickcommand.showMessageBox("分享失败,不知道为啥", "error") putDB(jsonQc.features.code, jsonQc, 'customFts'); return jsonQc } catch (error) { return quickcommand.showMessageBox(error, "error") } } let getSharedQCFromYuQue = async () => { $('#options').hide() let extraInfo = getDB('extraInfo') if (extraInfo.yuQueToken) yuQueClient.defaults.headers['X-Auth-Token'] = extraInfo.yuQueToken let res = await yuQueClient('repos/fofolee/qcreleases/docs') let program, docs = res.data.data.map(d => { program = d.custom_description.match(/环境:(.*?) /) return { title: d.title, description: d.custom_description, slug: d.slug, icon: `logo/${program[1]}.png` } }) let choise = await quickcommand.showSelectList(docs, { optionType: 'json' }) let doc = await yuQueClient(`repos/fofolee/qcreleases/docs/${choise.slug}?raw=1`) let body = doc.data.data.body let stringifyQc = body.match(/```json([\s\S]*)```/)[1] let qc = JSON.parse(stringifyQc) $('#options').show() qc.fromShare = true editCurrentCommand(qc) utools.setExpendHeight(600) } $("#out").on('click', '#importSharedQc', function () { importCommand() ? quickcommand.showMessageBox("导入成功") : quickcommand.showMessageBox("导入失败,格式错误", "error") showOptions() utools.setExpendHeight(600) $('#out').empty() }) // 删除 $("#options").on('click', '.delBtn', function () { quickcommand.showConfirmBox('删除这个快捷命令').then(() => { var code = $(this).parents('tr').attr('id'), db = utools.db.get("customFts"), data = db.data; delete data[code]; utools.removeFeature(code); utools.db.put({ _id: "customFts", data: data, _rev: db._rev }); var currentTag = $('.currentTag').text() if ($('#featureList tr').length == 2) currentTag = "默认" showOptions(currentTag); }) }) // 选择图标 $("#options").on('click', '#icon', function () { var options = { buttonLabel: '选择', filters: [{ name: 'Images', extensions: ['png'] }, ] } var file = getFileInfo({ type: 'dialog', argvs: options, readfile: false }) if (file) { $("#iconame").val(file.name); $("#icon").attr('src', file.path); } }) let SaveCurrentCommand = async () => { if ($('#tags').is(":parent")) { var type = $('#type').val(), code = $("#code").val(), tags = $('#tags').val(), rule = $('#rule').val(), cmd = window.editor.getValue(); if (tags && tags.includes("默认") && !fofoCommon.isDev()) return if (type != "window" && !rule) return quickcommand.showMessageBox(`${$('#ruleWord').text().replace(" ", "")} 不能留空!`, 'error') if (!cmdCheck(type, cmd)) return if (!code) { // 生成唯一code var uid = Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36); var code = `${type}_${uid}`; } var output = $('#output').val(), scptarg = $('#scptarg').val(), program = $('#program').val(), desc = $('#desc').val(), iconame = $("#iconame").val(), iconpath = $("#icon").attr('src'), icon, base64ico, hasSubInput; if (!desc) desc = ' '; // 选择了图标的情况下 if (iconame) { base64ico = window.getBase64Ico(iconpath); icon = "data:image/png;base64," + base64ico; // 未自定义使用默认 } else { icon = iconpath; } if (type == 'key') { cmds = rule.split(",").map(x => x.trim()) } else if (type == 'regex') { if (!/^\/.*?\/[igm]*$/.test(rule)) { rule = "/" + rule + "/" } cmds = [{ "label": desc, "type": "regex", "match": rule, "minNum": 1 }]; } else if (type == 'window') { var cmdOfWin = { "label": desc, "type": "window" } if (rule) { try { cmdOfWin.match = JSON.parse(rule) } catch (error) { cmdOfWin.match = { "app": rule.split(',') } } } cmds = [cmdOfWin]; } else if (type == 'files') { if (!/^\/.*?\/[igm]*$/.test(rule)) { rule = "/" + rule + "/" } cmds = [{ "label": desc, "type": "files", "match": rule, "minNum": 1 }]; } // 需要子输入框 if (cmd.includes('{{subinput}}')) { hasSubInput = true; } else { hasSubInput = false; } // platform var platform = [] $('.platform').not('.disabled').each(function () { platform.push($(this).attr('id')) }) // 添加特性 var extraInfo = $('#customize').data('extraInfo') var pushData = { features: { "code": code, "explain": desc, "cmds": cmds, "icon": icon, "platform": platform }, program: program, cmd: cmd, output: output, hasSubInput: hasSubInput, scptarg: scptarg } if (extraInfo) Object.assign(pushData, extraInfo) if (tags) pushData.tags = tags if (program == 'custom') { pushData.customOptions = { "bin": $('#custombin').val(), "argv": $('#customarg').val(), "ext": $('#customext').val(), 'codec': $('#customcodec').val() } } putDB(code, pushData, 'customFts'); $("#customize").animate({ top: '100%' }, () => { // 保存后标签跳转处理 var redirectTag, currentTag = $('.currentTag').text() if (tags.length) { if (pushData.tags.includes(currentTag)) { redirectTag = currentTag } else { redirectTag = pushData.tags[0] } } else { redirectTag = "未分类" } showOptions(redirectTag); location.href = '#' + code $("#customize").empty() let checkSwitch = $(`#${code} .checked-switch`) checkSwitch.click() checkSwitch.is(':checked') || checkSwitch.click() }); } } // 显示运行结果 let showRunResult = (content, raw, success) => { var options, position, showClass, hideClass, maxlength = 100000 if ($("#vars").is(":parent")) { position = 'top' showClass = 'fadeInDownWindow' hideClass = 'fadeOutUpWindow' } else { position = 'bottom' showClass = 'fadeInUpWindow' hideClass = 'fadeOutDownWindow' } var preView = () => { var result = $('#swal2-content').text() result = htmlEncode(result, raw) $(".swal2-content").css("width", "100%") $('#swal2-content').html(`
${result}
`) $('.swal2-popup').addClass('swal2-toast') } var contlength = content.length if (contlength > maxlength) content = content.slice(0, maxlength - 100) + `\n\n...\n${contlength - maxlength - 100} 字省略\n...\n\n` + content.slice(contlength - 100) content += '\n' var outputchannel = $("#swal2-content > pre") if (outputchannel.is(":parent")) { outputchannel.append(htmlEncode(content, raw)) } else { options = { onBeforeOpen: preView, icon: success ? "success" : "error", text: content, position: position, width: 800, showConfirmButton: true, showClass: { popup: showClass }, hideClass: { popup: hideClass } } success ? swalOneByOne(options) : Swal.fire(options) } } let runCurrentCommand = async () => { if ($("#customize").is(":parent")) { var cmd = window.editor.getValue() cmd = special(cmd) var requireInputVal = ['{{input}}', '{{subinput}}', '{{pwd}}', '{{SelectFile}}'] .filter(x => cmd.includes(x)); if (requireInputVal.length) { var html = requireInputVal .map(r => ``) .join("") await Swal.fire({ title: "需要临时为以下变量赋值", html: html, focusConfirm: false, preConfirm: () => { requireInputVal.forEach(r => { cmd = cmd.replace(new RegExp(r, 'g'), document.getElementById(r).value) }) } }) } var program = $("#program").val() var output = $("#output").val() var terminal = false var raw = true switch (output) { case "html": raw = false break; case "terminal": terminal = true break; case "ignore": utools.hideMainWindow() break; } if (program == "quickcommand") { runCodeInVm(cmd, (stdout, stderr) => { if (stderr) return showRunResult(stderr, raw, false) showRunResult(stdout, raw, true) }); } else { var option = programs[program] if (program == "custom") option = { "bin": $('#custombin').val(), "argv": $('#customarg').val(), "ext": $('#customext').val(), 'codec': $('#customcodec').val() } option.scptarg = $('#scptarg').val() runCodeFile(cmd, option, terminal, (stdout, stderr) => { if (terminal) return if (stderr) return showRunResult(stderr, raw, false) showRunResult(stdout, raw, true) }) } } } let killCurrentCommand = () => { } let quitCurrentCommand = () => { if ($("#customize").is(":parent") && $("#featureList").is(":parent")) { $("#customize").animate({ top: '100%' }); $("#customize").empty() } } let highlightIfKnown = ext => { var lang = Object.keys(programs).filter(p => programs[p].ext == ext) if (lang.length) { if (lang[0] == 'python') getPythonMods() window.editor.setOption("mode", lang[0]) return lang[0] } } showCodeEditor = file => { var customWindow = `
运 行 格式化 ?文档
` $("#options").html(customWindow) createEditor() $(".CodeMirror").addClass('CodeMirror-coderunner') $("#customize").css({ top: '0px', padding: '0px' }); $("span.customscript > input").css({"height": "30px"}) var db = getDB('codeHistory') createProgramSelect2(140, true) if (file) { var fileinfo = getFileInfo({ type: 'file', argvs: file, readfile: true }) window.editor.setValue(fileinfo.data) var program = Object.keys(programs).filter(x => `.${programs[x].ext}` == fileinfo.ext) if (program) $('#program').val(program[0]).trigger('change') // runCurrentCommand() } else if(db.history){ window.editor.setValue(db.history.cmd) $('#program').val(db.history.program).trigger('change') $('#scptarg').val(db.history.scptarg) var custom = db.history.customoptions if (db.history.program = 'custom' && custom) { $('#custombin').val(custom.custombin) $('#customarg').val(custom.customarg) $('#customext').val(custom.customext) $('#customcodec').val(custom.customcodec) } } programCheck() $("#options").show() } // 输出搜索 let showSearchBox = () => { if ($('#options').is(':hidden') && $('#out').is(":parent")) { $('#out').append(`
`) $('#outputSearch').animate({ opacity: 1, top: '10px', }) document.getElementById('find-next').onclick = () => { utools.findInPage($('#outputSearch > input').val()) } document.getElementById('find-prev').onclick = () => { utools.findInPage($('#outputSearch > input').val(), { forward: false }) } document.getElementById('find-close').onclick = () => { utools.stopFindInPage() $('#outputSearch').animate({ opacity: 0, top: '-30px', }, () => { $('#outputSearch').remove() }) } } } // 切换TAGS $("#options").on('click', '.sidebar li', function () { showOptions($(this).text()); }) // 运行 $("#options").on('click', '.cmdBtn.run, #runCode', function () { runCurrentCommand() }) // 格式化 $("#options").on('click', '#beautifyCode', function () { beautifyCode() }) // 取消 $("#options").on('click', '.cmdBtn.cancel', function () { quitCurrentCommand() }) // 保存 $("#options").on('click', '.cmdBtn.save', function () { SaveCurrentCommand() }) // 语言选项改变时 $("#options").on('change', '#program', function () { programCheck() }) // 变量选项改变时 $("#options").on('change', '#vars', function () { $("#vars").css({'color':'black'}) window.editor.replaceSelection($("#vars").val()); }) $("#options").on('change', '#action', function () { $("#action").css({ 'color': 'black' }) }) // 方式选项改变时 $("#options").on('change', '#type', function () { // resetVars(); typeCheck(); }) $("#options").on('change', '#customext', function () { highlightIfKnown($('#customext').val()) }) // 平台按钮 $("#options").on('click', '.platform', function () { if ($(this).hasClass('disabled')){ $(this).removeClass('disabled') } else { if ($('.disabled').length == 2) quickcommand.showMessageBox('至少保留一个平台', 'error') else $(this).addClass('disabled') } }) Mousetrap.bind('ctrl+s', () => { SaveCurrentCommand() return false }); Mousetrap.bind('ctrl+q', () => { quitCurrentCommand() return false }); Mousetrap.bind('ctrl+b', () => { runCurrentCommand() return false }); Mousetrap.bind('ctrl+f', () => { showSearchBox() return false }); }()