Created
July 16, 2019 14:04
-
-
Save msongz/5c1beeccd40a54fc44593e63ab734482 to your computer and use it in GitHub Desktop.
在编辑区域选中文字,然后在 keyboard maestro 的菜单栏里召唤空格之神
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
<plist version="1.0"> | |
<array> | |
<dict> | |
<key>Activate</key> | |
<string>Normal</string> | |
<key>CreationDate</key> | |
<real>531049276.55934</real> | |
<key>Macros</key> | |
<array> | |
<dict> | |
<key>Actions</key> | |
<array> | |
<dict> | |
<key>Action</key> | |
<string>Copy</string> | |
<key>IsDisclosed</key> | |
<false/> | |
<key>MacroActionType</key> | |
<string>CutCopyPaste</string> | |
<key>TimeOutAbortsMacro</key> | |
<true/> | |
</dict> | |
<dict> | |
<key>DisplayKind</key> | |
<string>Window</string> | |
<key>IncludeStdErr</key> | |
<false/> | |
<key>IsDisclosed</key> | |
<false/> | |
<key>MacroActionType</key> | |
<string>ExecuteJavaScriptForAutomation</string> | |
<key>NotifyOnFailure</key> | |
<false/> | |
<key>Path</key> | |
<string></string> | |
<key>StopOnFailure</key> | |
<false/> | |
<key>Text</key> | |
<string>'use strict'; | |
(function run() { | |
var app = Application.currentApplication() | |
app.includeStandardAdditions = true | |
var clipboardStr = app.theClipboard(); | |
//pangu start | |
const CJK = '\u2e80-\u2eff\u2f00-\u2fdf\u3040-\u309f\u30a0-\u30fa\u30fc-\u30ff\u3100-\u312f\u3200-\u32ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff'; | |
const ANY_CJK = new RegExp(`[${CJK}]`); | |
// the symbol part only includes ~ ! ; : , . ? but . only matches one character | |
const CONVERT_TO_FULLWIDTH_CJK_SYMBOLS_CJK = new RegExp(`([${CJK}])[ ]*([\\:]+|\\.)[ ]*([${CJK}])`, 'g'); | |
const CONVERT_TO_FULLWIDTH_CJK_SYMBOLS = new RegExp(`([${CJK}])[ ]*([~\\!;,\\?]+)[ ]*`, 'g'); | |
const DOTS_CJK = new RegExp(`([\\.]{2,}|\u2026)([${CJK}])`, 'g'); | |
const FIX_CJK_COLON_ANS = new RegExp(`([${CJK}])\\:([A-Z0-9\\(\\)])`, 'g'); | |
// the symbol part does not include ' | |
const CJK_QUOTE = new RegExp(`([${CJK}])([\`"\u05f4])`, 'g'); | |
const QUOTE_CJK = new RegExp(`([\`"\u05f4])([${CJK}])`, 'g'); | |
const FIX_QUOTE_ANY_QUOTE = /([`"\u05f4]+)[ ]*(.+?)[ ]*([`"\u05f4]+)/g; | |
const CJK_SINGLE_QUOTE_BUT_POSSESSIVE = new RegExp(`([${CJK}])('[^s])`, 'g'); | |
const SINGLE_QUOTE_CJK = new RegExp(`(')([${CJK}])`, 'g'); | |
const FIX_POSSESSIVE_SINGLE_QUOTE = new RegExp(`([A-Za-z0-9${CJK}])( )('s)`, 'g'); | |
const HASH_ANS_CJK_HASH = new RegExp(`([${CJK}])(#)([${CJK}]+)(#)([${CJK}])`, 'g'); | |
const CJK_HASH = new RegExp(`([${CJK}])(#([^ ]))`, 'g'); | |
const HASH_CJK = new RegExp(`(([^ ])#)([${CJK}])`, 'g'); | |
// the symbol part only includes + - * / = & | < > | |
const CJK_OPERATOR_ANS = new RegExp(`([${CJK}])([\\+\\-\\*\\/=&\\|<>])([A-Za-z0-9])`, 'g'); | |
const ANS_OPERATOR_CJK = new RegExp(`([A-Za-z0-9])([\\+\\-\\*\\/=&\\|<>])([${CJK}])`, 'g'); | |
const FIX_SLASH_AS = /([/]) ([a-z\-_\./]+)/g; | |
const FIX_SLASH_AS_SLASH = /([/\.])([A-Za-z\-_\./]+) ([/])/g; | |
// the bracket part only includes ( ) [ ] { } < > “ ” | |
const CJK_LEFT_BRACKET = new RegExp(`([${CJK}])([\\(\\[\\{<>\u201c])`, 'g'); | |
const RIGHT_BRACKET_CJK = new RegExp(`([\\)\\]\\}<>\u201d])([${CJK}])`, 'g'); | |
const FIX_LEFT_BRACKET_ANY_RIGHT_BRACKET = /([\(\[\{<\u201c]+)[ ]*(.+?)[ ]*([\)\]\}>\u201d]+)/; | |
const ANS_CJK_LEFT_BRACKET_ANY_RIGHT_BRACKET = new RegExp(`([A-Za-z0-9${CJK}])[ ]*([\u201c])([A-Za-z0-9${CJK}\\-_ ]+)([\u201d])`, 'g'); | |
const LEFT_BRACKET_ANY_RIGHT_BRACKET_ANS_CJK = new RegExp(`([\u201c])([A-Za-z0-9${CJK}\\-_ ]+)([\u201d])[ ]*([A-Za-z0-9${CJK}])`, 'g'); | |
const AN_LEFT_BRACKET = /([A-Za-z0-9])([\(\[\{])/g; | |
const RIGHT_BRACKET_AN = /([\)\]\}])([A-Za-z0-9])/g; | |
const CJK_ANS = new RegExp(`([${CJK}])([A-Za-z\u0370-\u03ff0-9@\\$%\\^&\\*\\-\\+\\\\=\\|/\u00a1-\u00ff\u2150-\u218f\u2700—\u27bf])`, 'g'); | |
const ANS_CJK = new RegExp(`([A-Za-z\u0370-\u03ff0-9~\\$%\\^&\\*\\-\\+\\\\=\\|/!;:,\\.\\?\u00a1-\u00ff\u2150-\u218f\u2700—\u27bf])([${CJK}])`, 'g'); | |
const S_A = /(%)([A-Za-z])/g; | |
const MIDDLE_DOT = /([ ]*)([\u00b7\u2022\u2027])([ ]*)/g; | |
class Pangu { | |
constructor() { | |
this.version = '4.0.7'; | |
} | |
convertToFullwidth(symbols) { | |
return symbols | |
.replace(/~/g, '~') | |
.replace(/!/g, '!') | |
.replace(/;/g, ';') | |
.replace(/:/g, ':') | |
.replace(/,/g, ',') | |
.replace(/\./g, '。') | |
.replace(/\?/g, '?'); | |
} | |
spacing(text) { | |
if (typeof text !== 'string') { | |
console.warn(`spacing(text) only accepts string but got ${typeof text}`); // eslint-disable-line no-console | |
return text; | |
} | |
if (text.length <= 1 || !ANY_CJK.test(text)) { | |
return text; | |
} | |
const self = this; | |
let newText = text; | |
// https://stackoverflow.com/questions/4285472/multiple-regex-replace | |
newText = newText.replace(CONVERT_TO_FULLWIDTH_CJK_SYMBOLS_CJK, (match, leftCjk, symbols, rightCjk) => { | |
const fullwidthSymbols = self.convertToFullwidth(symbols); | |
return `${leftCjk}${fullwidthSymbols}${rightCjk}`; | |
}); | |
newText = newText.replace(CONVERT_TO_FULLWIDTH_CJK_SYMBOLS, (match, cjk, symbols) => { | |
const fullwidthSymbols = self.convertToFullwidth(symbols); | |
return `${cjk}${fullwidthSymbols}`; | |
}); | |
newText = newText.replace(DOTS_CJK, '$1 $2'); | |
newText = newText.replace(FIX_CJK_COLON_ANS, '$1:$2'); | |
newText = newText.replace(CJK_QUOTE, '$1 $2'); | |
newText = newText.replace(QUOTE_CJK, '$1 $2'); | |
newText = newText.replace(FIX_QUOTE_ANY_QUOTE, '$1$2$3'); | |
newText = newText.replace(CJK_SINGLE_QUOTE_BUT_POSSESSIVE, '$1 $2'); | |
newText = newText.replace(SINGLE_QUOTE_CJK, '$1 $2'); | |
newText = newText.replace(FIX_POSSESSIVE_SINGLE_QUOTE, "$1's"); // eslint-disable-line quotes | |
newText = newText.replace(HASH_ANS_CJK_HASH, '$1 $2$3$4 $5'); | |
newText = newText.replace(CJK_HASH, '$1 $2'); | |
newText = newText.replace(HASH_CJK, '$1 $3'); | |
newText = newText.replace(CJK_OPERATOR_ANS, '$1 $2 $3'); | |
newText = newText.replace(ANS_OPERATOR_CJK, '$1 $2 $3'); | |
newText = newText.replace(FIX_SLASH_AS, '$1$2'); | |
newText = newText.replace(FIX_SLASH_AS_SLASH, '$1$2$3'); | |
newText = newText.replace(CJK_LEFT_BRACKET, '$1 $2'); | |
newText = newText.replace(RIGHT_BRACKET_CJK, '$1 $2'); | |
newText = newText.replace(FIX_LEFT_BRACKET_ANY_RIGHT_BRACKET, '$1$2$3'); | |
newText = newText.replace(ANS_CJK_LEFT_BRACKET_ANY_RIGHT_BRACKET, '$1 $2$3$4'); | |
newText = newText.replace(LEFT_BRACKET_ANY_RIGHT_BRACKET_ANS_CJK, '$1$2$3 $4'); | |
newText = newText.replace(AN_LEFT_BRACKET, '$1 $2'); | |
newText = newText.replace(RIGHT_BRACKET_AN, '$1 $2'); | |
newText = newText.replace(CJK_ANS, '$1 $2'); | |
newText = newText.replace(ANS_CJK, '$1 $2'); | |
newText = newText.replace(S_A, '$1 $2'); | |
newText = newText.replace(MIDDLE_DOT, '・'); | |
return newText; | |
} | |
spacingText(text, callback = () => {}) { | |
let newText; | |
try { | |
newText = this.spacing(text); | |
} catch (err) { | |
callback(err); | |
return; | |
} | |
callback(null, newText); | |
} | |
spacingTextSync(text) { | |
return this.spacing(text); | |
} | |
} | |
const pangu = new Pangu(); | |
// pangu stop | |
var someDataStr=pangu.spacing(clipboardStr); | |
app.setTheClipboardTo(someDataStr); | |
} | |
)();</string> | |
<key>TimeOutAbortsMacro</key> | |
<true/> | |
<key>TrimResults</key> | |
<true/> | |
<key>TrimResultsNew</key> | |
<true/> | |
<key>UseText</key> | |
<true/> | |
</dict> | |
<dict> | |
<key>KeyCode</key> | |
<integer>51</integer> | |
<key>MacroActionType</key> | |
<string>SimulateKeystroke</string> | |
<key>Modifiers</key> | |
<integer>0</integer> | |
<key>ReleaseAll</key> | |
<false/> | |
<key>TargetApplication</key> | |
<dict/> | |
<key>TargetingType</key> | |
<string>Front</string> | |
</dict> | |
<dict> | |
<key>Action</key> | |
<string>Paste</string> | |
<key>IsDisclosed</key> | |
<false/> | |
<key>MacroActionType</key> | |
<string>CutCopyPaste</string> | |
<key>TimeOutAbortsMacro</key> | |
<true/> | |
</dict> | |
<dict> | |
<key>MacroActionType</key> | |
<string>DeletePastClipboard</string> | |
<key>PastExpression</key> | |
<string>0</string> | |
</dict> | |
<dict> | |
<key>MacroActionType</key> | |
<string>DeletePastClipboard</string> | |
<key>PastExpression</key> | |
<string>0</string> | |
</dict> | |
</array> | |
<key>CreationDate</key> | |
<real>584973825.00902402</real> | |
<key>ModificationDate</key> | |
<real>584978115.41352105</real> | |
<key>Name</key> | |
<string>🈳️️空格之神</string> | |
<key>Triggers</key> | |
<array> | |
<dict> | |
<key>MacroTriggerType</key> | |
<string>StatusMenu</string> | |
</dict> | |
</array> | |
<key>UID</key> | |
<string>ED8A8D5E-85CE-4DBF-80F3-8E52F6273E98</string> | |
</dict> | |
</array> | |
<key>Name</key> | |
<string>songz</string> | |
<key>ToggleMacroUID</key> | |
<string>09D9F78A-2E11-4FF4-94DF-156446F2E2BE</string> | |
<key>UID</key> | |
<string>EAFD259B-45B8-41A1-AE2B-24DB2F3F0A0B</string> | |
</dict> | |
</array> | |
</plist> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
用上了,👍