!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 = `
匹 配
关键字
说 明
环 境
标 签
变 量
输 出
脚 本
${(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
});
}()