diff --git a/src/assets/index.js b/src/assets/index.js
index e6b14db..29c7ba9 100644
--- a/src/assets/index.js
+++ b/src/assets/index.js
@@ -1,4 +1,5 @@
!function () {
+ // 暗黑模式
if (utools.isDarkColors()) {
!$('#darkmode').length && $('head').append(`
@@ -6,7 +7,7 @@
} else {
$('#darkmode').length && $('#darkmode, #darkswal').remove()
}
-
+ // 进入插件
utools.onPluginEnter(async ({ code, type, payload }) => {
if (fofoCommon.isRunningAtFirstTime()) {
fofoCommon.showChangeLog()
@@ -124,7 +125,6 @@
}
});
-
let runQuickCommand = (cmd, option, output, autoScroll = false, autoHeight = true) => {
// 不需要输出的,提前关闭窗口
if (['ignore', 'clip', 'send', 'notice', 'terminal'].indexOf(output) !== -1) {
@@ -237,7 +237,8 @@
})
}
- importDefaultCommands = () => {
+ // 导入默认命令
+ let importDefaultCommands = () => {
let customFts = fofoCommon.getDB('customFts')
let qc = Object.keys(customFts)
let defaultCommands = getDefaultCommands()
@@ -245,4 +246,1307 @@
if (!qc.includes(d)) importCommand(defaultCommands[d])
})
}
+
+ // 是否含有 quickcommand 键值
+ 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
+ }
+
+ // 导入
+ let 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;
+ fofoCommon.putDB(code, pushData.qc, 'customFts');
+ // 多个命令导入
+ } else {
+ for (var code of Object.keys(pushData.qc)) {
+ fofoCommon.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(x => {
+ if (!x) return
+ utools.db.remove('customFts');
+ importDefaultCommands();
+ clearAllFeatures();
+ showOptions();
+ })
+ }
+
+ // 环境
+ const 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'
+ }
+ }
+
+ // 显示设置界面
+ let showOptions = (tag = "默认") => {
+ $("#options").empty().fadeIn();
+ var currentFts = utools.getFeatures(),
+ customFts = fofoCommon.getDB('customFts');
+ var allTags = ["默认"]
+ var featureList = `
+
+
+ 匹 配
+
+ 关键字
+
说 明
+
+
+
+ 环 境
+
+ 标 签
+
+
+
+
+ 变 量
+
+ 输 出
+
+
+
+ 脚 本
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${(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 = fofoCommon.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
+ fofoCommon.putDB('yuQueToken', yuQueToken, 'extraInfo')
+ fofoCommon.putDB('authorName', authorName, 'extraInfo')
+ fofoCommon.putDB('authorId', authorId, 'extraInfo')
+ quickcommand.showMessageBox("设置成功~")
+ } catch (e) {
+ quickcommand.showMessageBox('Token 校验失败', "error")
+ }
+ }
+
+ let createShareMenu = jsonQc => {
+ let menu = ['复制到剪贴板', '导出到文件', '', '设置 Token']
+ let extraInfo = fofoCommon.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 = fofoCommon.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 = fofoCommon.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)
+ console.log(jsonQc);
+ if (stringifyQc.length > 5000000) return quickcommand.showMessageBox('命令大小超过5M无法分享,请检查图标或脚本内容是否过大', "error")
+ let platform = jsonQc.features.platform ? jsonQc.features.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'
+ 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")
+ fofoCommon.putDB(jsonQc.features.code, jsonQc, 'customFts');
+ return jsonQc
+ } catch (error) {
+ return quickcommand.showMessageBox(error, "error")
+ }
+ }
+
+ let getSharedQCFromYuQue = async () => {
+ $('#options').hide()
+ let extraInfo = fofoCommon.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(x => {
+ if (!x) return
+ 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,
+ hasSubInput;
+ if (!desc) desc = ' ';
+ // 选择了图标的情况下
+ if (iconame) {
+ icon = await window.getBase64Ico(iconpath);
+ // 未自定义使用默认
+ } 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()
+ }
+ }
+ fofoCommon.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]
+ }
+ }
+
+ let 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 = fofoCommon.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
+ });
+
}()
diff --git a/src/assets/options.js b/src/assets/options.js
deleted file mode 100644
index a22210a..0000000
--- a/src/assets/options.js
+++ /dev/null
@@ -1,1299 +0,0 @@
-!function () {
- 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;
- fofoCommon.putDB(code, pushData.qc, 'customFts');
- // 多个命令导入
- } else {
- for (var code of Object.keys(pushData.qc)) {
- fofoCommon.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(x => {
- if (!x) return
- utools.db.remove('customFts');
- importDefaultCommands();
- clearAllFeatures();
- showOptions();
- })
- }
-
- 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 = fofoCommon.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 += `
-  |
-
- ${features.explain}
-
-
- ●
- ${fts.program} | ${platformIcons.join('')}
-
- |
- ${cmds} |
-
-
- |
-
-
- ${(tag == "默认" && !fofoCommon.isDev()) ? "" : ` `}
- | `
- })
- featureList += `
`
- 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 = fofoCommon.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
- fofoCommon.putDB('yuQueToken', yuQueToken, 'extraInfo')
- fofoCommon.putDB('authorName', authorName, 'extraInfo')
- fofoCommon.putDB('authorId', authorId, 'extraInfo')
- quickcommand.showMessageBox("设置成功~")
- } catch (e) {
- quickcommand.showMessageBox('Token 校验失败', "error")
- }
- }
-
- let createShareMenu = jsonQc => {
- let menu = ['复制到剪贴板', '导出到文件', '', '设置 Token']
- let extraInfo = fofoCommon.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 = fofoCommon.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 = fofoCommon.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)
- console.log(jsonQc);
- if (stringifyQc.length > 5000000) return quickcommand.showMessageBox('命令大小超过5M无法分享,请检查图标或脚本内容是否过大', "error")
- let platform = jsonQc.features.platform ? jsonQc.features.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'
- 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")
- fofoCommon.putDB(jsonQc.features.code, jsonQc, 'customFts');
- return jsonQc
- } catch (error) {
- return quickcommand.showMessageBox(error, "error")
- }
- }
-
- let getSharedQCFromYuQue = async () => {
- $('#options').hide()
- let extraInfo = fofoCommon.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(x => {
- if (!x) return
- 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) {
- icon = await window.getBase64Ico(iconpath);
- // 未自定义使用默认
- } 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()
- }
- }
- fofoCommon.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 = fofoCommon.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
- });
-}()
diff --git a/src/index.html b/src/index.html
index 8f7a284..17f28c0 100755
--- a/src/index.html
+++ b/src/index.html
@@ -22,7 +22,6 @@