├── .konrad.noon ├── bin ├── kappo-starter.app │ └── Contents │ │ ├── PkgInfo │ │ ├── MacOS │ │ └── applet │ │ ├── Resources │ │ ├── applet.icns │ │ ├── applet.rsrc │ │ ├── Scripts │ │ │ └── main.scpt │ │ └── description.rtfd │ │ │ └── TXT.rtf │ │ └── Info.plist ├── appswitch ├── Quick_Any2Ico.exe ├── kappo-starter.scpt ├── dmg.sh ├── inst.sh ├── dmg.noon ├── release.sh ├── buildmac.sh ├── inno.iss └── ignore.noon ├── img ├── app.icns ├── app.ico ├── dmg.png ├── menu.png ├── about.png ├── banner.png ├── broken.png ├── dmg@2x.png ├── kappo.pxm ├── menu@2x.png ├── readme.png ├── innolarge.bmp ├── innosmall.bmp ├── terminal.png └── screenshot.png ├── scripts ├── sleep.png ├── recycle.png ├── restart.png └── shutdown.png ├── README.md ├── .gitignore ├── js ├── css │ ├── dark.css │ ├── bright.css │ └── style.css ├── index.html ├── winpaste.js ├── winlaunch.js ├── appfind.js ├── scripts.js ├── appicon.js ├── exefind.js ├── exeicon.js ├── main.js └── kappo.js ├── pug ├── index.html └── index.pug ├── styl ├── dark.styl ├── bright.styl └── style.styl ├── package.json ├── package.noon └── coffee ├── appfind.coffee ├── appicon.coffee ├── scripts.coffee ├── exefind.coffee ├── exeicon.coffee ├── main.coffee └── kappo.coffee /.konrad.noon: -------------------------------------------------------------------------------- 1 | ignore 2 | /.*-x64/ -------------------------------------------------------------------------------- /bin/kappo-starter.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPLaplt -------------------------------------------------------------------------------- /img/app.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/app.icns -------------------------------------------------------------------------------- /img/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/app.ico -------------------------------------------------------------------------------- /img/dmg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/dmg.png -------------------------------------------------------------------------------- /img/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/menu.png -------------------------------------------------------------------------------- /bin/appswitch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/bin/appswitch -------------------------------------------------------------------------------- /img/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/about.png -------------------------------------------------------------------------------- /img/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/banner.png -------------------------------------------------------------------------------- /img/broken.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/broken.png -------------------------------------------------------------------------------- /img/dmg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/dmg@2x.png -------------------------------------------------------------------------------- /img/kappo.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/kappo.pxm -------------------------------------------------------------------------------- /img/menu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/menu@2x.png -------------------------------------------------------------------------------- /img/readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/readme.png -------------------------------------------------------------------------------- /img/innolarge.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/innolarge.bmp -------------------------------------------------------------------------------- /img/innosmall.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/innosmall.bmp -------------------------------------------------------------------------------- /img/terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/terminal.png -------------------------------------------------------------------------------- /scripts/sleep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/scripts/sleep.png -------------------------------------------------------------------------------- /img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/img/screenshot.png -------------------------------------------------------------------------------- /scripts/recycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/scripts/recycle.png -------------------------------------------------------------------------------- /scripts/restart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/scripts/restart.png -------------------------------------------------------------------------------- /scripts/shutdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/scripts/shutdown.png -------------------------------------------------------------------------------- /bin/Quick_Any2Ico.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/bin/Quick_Any2Ico.exe -------------------------------------------------------------------------------- /bin/kappo-starter.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/bin/kappo-starter.scpt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![readme](img/readme.png) 3 |





4 | ![screenshot](img/screenshot.png) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | watch/Build 3 | watch/DerivedData 4 | Icon? 5 | bin/*.json 6 | *.dmg 7 | *-x64 8 | -------------------------------------------------------------------------------- /bin/kappo-starter.app/Contents/MacOS/applet: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/bin/kappo-starter.app/Contents/MacOS/applet -------------------------------------------------------------------------------- /bin/kappo-starter.app/Contents/Resources/applet.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/bin/kappo-starter.app/Contents/Resources/applet.icns -------------------------------------------------------------------------------- /bin/kappo-starter.app/Contents/Resources/applet.rsrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/bin/kappo-starter.app/Contents/Resources/applet.rsrc -------------------------------------------------------------------------------- /bin/kappo-starter.app/Contents/Resources/Scripts/main.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monsterkodi/kappo/HEAD/bin/kappo-starter.app/Contents/Resources/Scripts/main.scpt -------------------------------------------------------------------------------- /bin/kappo-starter.app/Contents/Resources/description.rtfd/TXT.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf400 2 | {\fonttbl} 3 | {\colortbl;\red255\green255\blue255;} 4 | {\*\expandedcolortbl;;} 5 | } -------------------------------------------------------------------------------- /js/css/dark.css: -------------------------------------------------------------------------------- 1 | #main { 2 | background: #181818; 3 | } 4 | #appname { 5 | color: #ccc; 6 | } 7 | #appname b { 8 | color: #fff; 9 | } 10 | .appdot { 11 | background: #444; 12 | } 13 | .appdot.current { 14 | background: #888; 15 | } 16 | -------------------------------------------------------------------------------- /bin/dmg.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cd `dirname $0`/.. 3 | 4 | NAME=`sds productName` 5 | VERSION=`sds version` 6 | 7 | npm rebuild 8 | rm -f $NAME-*.dmg 9 | 10 | ./node_modules/.bin/appdmg ./bin/dmg.json $NAME-$VERSION.dmg 11 | 12 | open $NAME-$VERSION.dmg -------------------------------------------------------------------------------- /js/css/bright.css: -------------------------------------------------------------------------------- 1 | #main { 2 | background: #fff; 3 | } 4 | #appname { 5 | background: #fff; 6 | color: #333; 7 | } 8 | #appname b { 9 | color: #000; 10 | } 11 | .appdot { 12 | background: #eee; 13 | } 14 | .appdot.current { 15 | background: #000; 16 | } 17 | -------------------------------------------------------------------------------- /bin/inst.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cd `dirname $0`/.. 3 | 4 | NAME=`sds productName` 5 | 6 | 2>/dev/null 1>/dev/null killall $NAME 7 | 2>/dev/null 1>/dev/null killall $NAME 8 | 9 | rm -rf /Applications/$NAME.app 10 | cp -R $NAME-darwin-x64/$NAME.app /Applications 11 | 12 | open /Applications/$NAME.app 13 | -------------------------------------------------------------------------------- /bin/dmg.noon: -------------------------------------------------------------------------------- 1 | title kappo 2 | icon ../img/kappo.icns 3 | background ../img/dmg.png 4 | window 5 | position 6 | x 200 7 | y 600 8 | contents 9 | . 10 | x 100 11 | y 180 12 | type link 13 | path /Applications 14 | . 15 | x 100 16 | y 70 17 | type file 18 | path ../kappo-darwin-x64/kappo.app 19 | -------------------------------------------------------------------------------- /bin/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cd `dirname $0`/.. 3 | 4 | NAME=`sds productName` 5 | USER=`sds author` 6 | VERSION=`sds version` 7 | VVERSION=v$VERSION 8 | DMG=$NAME-$VERSION.dmg 9 | 10 | echo 'creating release ...' 11 | github-release release -s $GH_TOKEN -u $USER -r $NAME -t $VVERSION -n $VVERSION 12 | echo 'uploading dmg ...' 13 | github-release upload -s $GH_TOKEN -u $USER -r $NAME -t $VVERSION -n $DMG -f $DMG 14 | 15 | -------------------------------------------------------------------------------- /pug/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | kappo 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /styl/dark.styl: -------------------------------------------------------------------------------- 1 | 2 | // 0000000 0000000 00000000 000 000 3 | // 000 000 000 000 000 000 000 000 4 | // 000 000 000000000 0000000 0000000 5 | // 000 000 000 000 000 000 000 000 6 | // 0000000 000 000 000 000 000 000 7 | 8 | #main 9 | background #181818 10 | 11 | #appname 12 | color #ccc 13 | & b 14 | color #fff 15 | 16 | .appdot 17 | background #444 18 | &.current 19 | background #888 20 | -------------------------------------------------------------------------------- /pug/index.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html(lang="en") 3 | head 4 | meta(charset='utf-8') 5 | title kappo 6 | meta(http-equiv='Content-Security-Policy' content="default-src * 'unsafe-inline' 'unsafe-eval'") 7 | link(rel='stylesheet' href='css/style.css' type='text/css') 8 | link(rel='stylesheet' href='css/dark.css' type='text/css', id='style-link') 9 | body#body 10 | #main(tabindex="0") 11 | #app 12 | #appicon 13 | #appname 14 | #appdots 15 | script. 16 | require('./kappo') 17 | 18 | -------------------------------------------------------------------------------- /bin/buildmac.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR=`dirname $0` 4 | BIN=$DIR/../node_modules/.bin 5 | cd $DIR/.. 6 | 7 | if rm -rf kappo-darwin-x64; then 8 | 9 | if $BIN/konrad; then 10 | 11 | IGNORE="(.*\.dmg$|Icon$|.*\.lock$|img/banner\.png|img/dmg|img/shot|img/.*\.pxm)" 12 | 13 | if $BIN/electron-packager . --overwrite --icon=img/app.icns --darwinDarkModeSupport --ignore=$IGNORE; then 14 | 15 | rm -rf /Applications/kappo.app 16 | cp -R kappo-darwin-x64/kappo.app /Applications 17 | 18 | open /Applications/kappo.app 19 | fi 20 | fi 21 | fi -------------------------------------------------------------------------------- /styl/bright.styl: -------------------------------------------------------------------------------- 1 | 2 | // 0000000 00000000 000 0000000 000 000 000000000 3 | // 000 000 000 000 000 000 000 000 000 4 | // 0000000 0000000 000 000 0000 000000000 000 5 | // 000 000 000 000 000 000 000 000 000 000 6 | // 0000000 000 000 000 0000000 000 000 000 7 | 8 | #main 9 | background #fff 10 | 11 | #appname 12 | background #fff 13 | color #333 14 | & b 15 | color #000 16 | 17 | .appdot 18 | background #eee 19 | &.current 20 | background #000 21 | -------------------------------------------------------------------------------- /js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | kappo 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kappo", 3 | "productName": "kappo", 4 | "version": "1.18.0", 5 | "description": "application opener", 6 | "author": "monsterkodi", 7 | "license": "Unlicense", 8 | "main": "js/main.js", 9 | "repository": "github:monsterkodi/kappo", 10 | "files": [ 11 | "bin/*", 12 | "js/*", 13 | "scripts/*", 14 | "img/*" 15 | ], 16 | "bugs": { 17 | "url": "https://github.com/monsterkodi/kappo/issues" 18 | }, 19 | "build": { 20 | "asar": false, 21 | "mac": { 22 | "icon": "img/app.icns" 23 | } 24 | }, 25 | "scripts": { 26 | "mac": "bash ./bin/buildmac.sh", 27 | "win": "bash ./bin/buildwin.sh" 28 | }, 29 | "dependencies": { 30 | "fuzzaldrin": "^2.1.0", 31 | "fuzzy": "^0.1.3", 32 | "kxk": "^0.422.0" 33 | }, 34 | "optionalDependencies": { 35 | "osascript": "^1.2.0", 36 | "simple-plist": "^1.3.0", 37 | "wxw": "^1.89.0" 38 | }, 39 | "devDependencies": { 40 | "electron": "^15.3.1", 41 | "electron-builder": "^22.13.1", 42 | "konrad": "^0.192.0", 43 | "node-abi": "^3.3.0" 44 | } 45 | } -------------------------------------------------------------------------------- /package.noon: -------------------------------------------------------------------------------- 1 | name kappo 2 | productName kappo 3 | version 1.18.0 4 | description application opener 5 | author monsterkodi 6 | license Unlicense 7 | main js/main.js 8 | repository github:monsterkodi/kappo 9 | files 10 | bin/* 11 | js/* 12 | scripts/* 13 | img/* 14 | bugs 15 | url https://github.com/monsterkodi/kappo/issues 16 | build 17 | asar false 18 | mac 19 | icon img/app.icns 20 | scripts 21 | mac bash ./bin/buildmac.sh 22 | win bash ./bin/buildwin.sh 23 | dependencies 24 | fuzzaldrin ^2.1.0 25 | fuzzy ^0.1.3 26 | kxk ^0.422.0 27 | optionalDependencies 28 | osascript ^1.2.0 29 | simple-plist ^1.3.0 30 | wxw ^1.89.0 31 | devDependencies 32 | electron ^15.3.1 33 | electron-builder ^22.13.1 34 | konrad ^0.192.0 35 | node-abi ^3.3.0 -------------------------------------------------------------------------------- /bin/inno.iss: -------------------------------------------------------------------------------- 1 | #define MyAppName "kappo" 2 | #define MyAppVersion "1.31.0" 3 | #define MyAppPublisher "monsterkodi" 4 | #define MyAppURL "https://github.com/monsterkodi/kappo" 5 | #define MyAppExeName "kappo.exe" 6 | 7 | [Setup] 8 | AppId={{BD8B6481-558F-4842-A51B-41D08AEEE053} 9 | AppName={#MyAppName} 10 | AppVersion={#MyAppVersion} 11 | AppPublisher={#MyAppPublisher} 12 | AppPublisherURL={#MyAppURL} 13 | AppSupportURL={#MyAppURL} 14 | AppUpdatesURL={#MyAppURL} 15 | DefaultDirName={pf}\{#MyAppName} 16 | DefaultGroupName={#MyAppName} 17 | AllowNoIcons=yes 18 | OutputDir=..\inno 19 | OutputBaseFilename={#MyAppName}-{#MyAppVersion}-setup 20 | SetupIconFile=..\img\app.ico 21 | Compression=lzma 22 | SolidCompression=yes 23 | WizardImageFile=..\img\innolarge.bmp 24 | WizardSmallImageFile=..\img\innosmall.bmp 25 | WizardImageStretch=no 26 | 27 | [Languages] 28 | Name: "english"; MessagesFile: "compiler:Default.isl" 29 | 30 | [Tasks] 31 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 32 | 33 | [Files] 34 | Source: "..\{#MyAppName}-win32-x64\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 35 | 36 | [Icons] 37 | Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 38 | Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon 39 | 40 | [Run] 41 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent 42 | 43 | -------------------------------------------------------------------------------- /coffee/appfind.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | 0000000 00000000 00000000 00000000 000 000 000 0000000 3 | 000 000 000 000 000 000 000 000 0000 000 000 000 4 | 000000000 00000000 00000000 000000 000 000 0 000 000 000 5 | 000 000 000 000 000 000 000 0000 000 000 6 | 000 000 000 000 000 000 000 000 0000000 7 | ### 8 | 9 | { walkdir, prefs, slash, last, log, _ } = require 'kxk' 10 | 11 | appFind = (cb) -> 12 | 13 | apps = {} 14 | apps['Finder'] = "/System/Library/CoreServices/Finder.app" 15 | appFolders = [ 16 | "/Applications" 17 | "/Applications/Utilities" 18 | "/System/Applications" 19 | "/System/Applications/Utilities" 20 | "~" 21 | ] 22 | appFolders = appFolders.concat prefs.get 'dirs', [] 23 | foldersLeft = appFolders.length 24 | 25 | for appFolder in appFolders 26 | walkOpt = prefs.get 'walk', no_recurse: false, max_depth: 4 27 | walk = walkdir slash.resolve(appFolder), walkOpt 28 | walk.on 'error', (err) -> log "[ERROR] findApps -- #{err}" 29 | walk.on 'end', -> 30 | foldersLeft -= 1 31 | if foldersLeft == 0 32 | # log "found: #{_.size apps}" 33 | cb apps 34 | walk.on 'directory', (dir) -> 35 | if slash.ext(dir) == 'app' 36 | if not /(Helper$|NP$|EH$)/.test slash.base dir 37 | name = slash.base dir 38 | apps[name] = dir 39 | 40 | module.exports = appFind 41 | -------------------------------------------------------------------------------- /js/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | outline-width: 0; 3 | } 4 | body { 5 | position: absolute; 6 | bottom: 0; 7 | right: 0; 8 | left: 0; 9 | top: 0; 10 | margin: 0; 11 | overflow: hidden; 12 | font-family: "Avenir", "Varela Round", "Verdana"; 13 | font-size: 16px; 14 | cursor: pointer; 15 | -webkit-user-select: none; 16 | } 17 | #main { 18 | position: absolute; 19 | bottom: 0; 20 | right: 0; 21 | left: 0; 22 | top: 0; 23 | border-radius: 6px; 24 | overflow: hidden; 25 | pointer-events: auto; 26 | } 27 | .fade { 28 | animation: fadein 0.3s; 29 | animation-fill-mode: forwards; 30 | animation-timing-function: ease-in; 31 | } 32 | #app { 33 | position: absolute; 34 | bottom: 0; 35 | right: 0; 36 | left: 0; 37 | top: 0; 38 | } 39 | #appicon { 40 | position: absolute; 41 | margin: 0; 42 | top: 6%; 43 | left: 10%; 44 | width: 80%; 45 | height: 80%; 46 | background-size: 100% 100%; 47 | cursor: pointer; 48 | } 49 | #appname { 50 | text-align: center; 51 | position: absolute; 52 | left: 0; 53 | right: 0; 54 | bottom: 2%; 55 | } 56 | #appdots { 57 | position: absolute; 58 | bottom: 0; 59 | left: 0; 60 | right: 0; 61 | } 62 | #appdotr { 63 | position: relative; 64 | overflow: visible; 65 | text-align: center; 66 | white-space: nowrap; 67 | height: 6px; 68 | } 69 | .appdot { 70 | display: inline-block; 71 | position: relative; 72 | bottom: 12px; 73 | width: 6px; 74 | height: 6px; 75 | } 76 | @-moz-keyframes fadein { 77 | 0% { 78 | opacity: 0; 79 | } 80 | 50% { 81 | opacity: 0; 82 | } 83 | 100% { 84 | opacity: 1; 85 | } 86 | } 87 | @-webkit-keyframes fadein { 88 | 0% { 89 | opacity: 0; 90 | } 91 | 50% { 92 | opacity: 0; 93 | } 94 | 100% { 95 | opacity: 1; 96 | } 97 | } 98 | @-o-keyframes fadein { 99 | 0% { 100 | opacity: 0; 101 | } 102 | 50% { 103 | opacity: 0; 104 | } 105 | 100% { 106 | opacity: 1; 107 | } 108 | } 109 | @keyframes fadein { 110 | 0% { 111 | opacity: 0; 112 | } 113 | 50% { 114 | opacity: 0; 115 | } 116 | 100% { 117 | opacity: 1; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /coffee/appicon.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | 0000000 00000000 00000000 000 0000000 0000000 000 000 3 | 000 000 000 000 000 000 000 000 000 000 0000 000 4 | 000000000 00000000 00000000 000 000 000 000 000 0 000 5 | 000 000 000 000 000 000 000 000 000 0000 6 | 000 000 000 000 000 0000000 0000000 000 000 7 | ### 8 | 9 | { childp, fs, slash, error, log } = require 'kxk' 10 | 11 | plist = require 'simple-plist' 12 | 13 | class AppIcon 14 | 15 | @cache = {} 16 | 17 | @pngPath: (opt) -> 18 | 19 | slash.resolve slash.join opt.iconDir, slash.base(opt.appPath) + ".png" 20 | 21 | @get: (opt) -> 22 | 23 | pngPath = AppIcon.pngPath opt 24 | if AppIcon.cache[pngPath] 25 | opt.cb pngPath, opt.cbArg 26 | else 27 | fs.stat pngPath, (err, stat) -> 28 | if not err? and stat.isFile() 29 | AppIcon.cache[pngPath] = true 30 | opt.cb pngPath, opt.cbArg 31 | else 32 | AppIcon.getIcon opt 33 | 34 | @getIcon: (opt) -> 35 | 36 | appPath = opt.appPath 37 | infoPath = slash.join appPath, 'Contents', 'Info.plist' 38 | plist.readFile infoPath, (err, obj) -> 39 | if not err? 40 | if obj['CFBundleIconFile']? 41 | icnsPath = slash.join slash.dirname(infoPath), 'Resources', obj['CFBundleIconFile'] 42 | icnsPath += ".icns" if not icnsPath.endsWith '.icns' 43 | AppIcon.saveIcon icnsPath, opt 44 | else 45 | AppIcon.brokenIcon opt 46 | else 47 | error "getIcon: #{err}" 48 | AppIcon.brokenIcon opt 49 | 50 | @saveIcon: (icnsPath, opt) -> 51 | 52 | pngPath = AppIcon.pngPath opt 53 | childp.exec "/usr/bin/sips -Z #{opt.size} -s format png \"#{icnsPath}\" --out \"#{pngPath}\"", (err) -> 54 | if not err? 55 | opt.cb pngPath, opt.cbArg 56 | else 57 | error "saveIcon: #{err}" 58 | AppIcon.brokenIcon opt 59 | 60 | @brokenIcon: (opt) -> 61 | 62 | brokenPath = slash.join __dirname, '..', 'img', 'broken.png' 63 | opt.cb brokenPath, opt.cbArg 64 | 65 | module.exports = AppIcon 66 | -------------------------------------------------------------------------------- /coffee/scripts.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | 0000000 0000000 00000000 000 00000000 000000000 0000000 3 | 000 000 000 000 000 000 000 000 000 4 | 0000000 000 0000000 000 00000000 000 0000000 5 | 000 000 000 000 000 000 000 000 6 | 0000000 0000000 000 000 000 000 000 0000000 7 | ### 8 | 9 | { prefs, slash, log } = require 'kxk' 10 | 11 | winRecycle = -> 12 | 13 | wxw = require 'wxw' 14 | wxw 'trash' 'empty' 15 | 16 | winScripts = () -> 17 | 18 | scripts = 19 | recycle: 20 | cb: winRecycle 21 | img: slash.resolve "#{__dirname}/../scripts/recycle.png" 22 | sleep: 23 | exec: 'shutdown /h' 24 | img: slash.resolve "#{__dirname}/../scripts/sleep.png" 25 | shutdown: 26 | exec: 'shutdown /s /t 0' 27 | img: slash.resolve "#{__dirname}/../scripts/shutdown.png" 28 | restart: 29 | exec: 'shutdown /r /t 0' 30 | img: slash.resolve "#{__dirname}/../scripts/restart.png" 31 | terminal: 32 | # exec: "C:/msys64/usr/bin/mintty.exe -i \"#{slash.resolve "#{__dirname}/../scripts/terminal.ico"}\" -o 'AppLaunchCmd=C:\msys64\mingw64.exe' -o 'AppID=MSYS2.Shell.MINGW64.9' -p 950,0 -t 'fish' -- /usr/bin/sh -lc fish" 33 | exec: "C:/msys64/usr/bin/mintty.exe -o 'AppLaunchCmd=C:\msys64\mingw64.exe' -o 'AppID=MSYS2.Shell.MINGW64.9' -p 950,0 -t 'fish' -- /usr/bin/sh -lc fish" 34 | img: slash.resolve "#{__dirname}/../img/terminal.png" 35 | foreground: "C:/msys64/usr/bin/mintty.exe" 36 | scripts 37 | 38 | macScripts = () -> 39 | 40 | scripts = 41 | sleep: 42 | exec: "pmset sleepnow" 43 | img: "#{__dirname}/../scripts/sleep.png" 44 | shutdown: 45 | exec: "osascript -e 'tell app \"System Events\" to shut down'" 46 | img: "#{__dirname}/../scripts/shutdown.png" 47 | restart: 48 | exec: "osascript -e 'tell app \"System Events\" to restart'" 49 | img: "#{__dirname}/../scripts/restart.png" 50 | 51 | if prefs.get 'confirmShutdown' 52 | scripts.shutdown.exec = "osascript -e 'tell app \"loginwindow\" to «event aevtrsdn»'" 53 | if prefs.get 'confirmRestart' 54 | scripts.restart.exec = "osascript -e 'tell app \"loginwindow\" to «event aevtrrst»'" 55 | scripts 56 | 57 | module.exports = 58 | macScripts: macScripts 59 | winScripts: winScripts 60 | -------------------------------------------------------------------------------- /coffee/exefind.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | 00000000 000 000 00000000 00000000 000 000 000 0000000 3 | 000 000 000 000 000 000 0000 000 000 000 4 | 0000000 00000 0000000 000000 000 000 0 000 000 000 5 | 000 000 000 000 000 000 000 0000 000 000 6 | 00000000 000 000 00000000 000 000 000 000 0000000 7 | ### 8 | 9 | { post, slash, walkdir, prefs, klog, _ } = require 'kxk' 10 | 11 | exeFind = (cb) -> 12 | 13 | appl = prefs.get 'apps' [] 14 | 15 | apps = {} 16 | appl.map (a) -> apps[slash.base a] = slash.resolve a 17 | 18 | apps['cmd'] = "C:/Windows/System32/cmd.exe" 19 | apps['calc'] = "C:/Windows/System32/calc.exe" 20 | apps['Taskmgr'] = "C:/Windows/System32/Taskmgr.exe" 21 | apps['regedit'] = "C:/Windows/regedit.exe" 22 | apps['explorer'] = "C:/Windows/explorer.exe" 23 | 24 | dirs = _.clone prefs.get 'dirs' [] 25 | 26 | dirs.push "C:/Program Files" 27 | dirs.push "C:/Program Files (x86)" 28 | dirs.push slash.resolve '~/AppData/Local' 29 | dirs.push slash.resolve '~/' 30 | 31 | ignoreDefaults = require '../bin/ignore' 32 | 33 | ignoredByName = (file) -> 34 | file = file.toLowerCase() 35 | for start in ignoreDefaults.startsWith 36 | return true if file.startsWith start 37 | for contains in ignoreDefaults.contains 38 | return true if file.indexOf(contains) >= 0 39 | for match in ignoreDefaults.matches 40 | return true if file == match 41 | false 42 | 43 | ignoredByPath = (file) -> 44 | for path in ignoreDefaults.path 45 | return true if file.indexOf(path) >= 0 46 | false 47 | 48 | ignore = prefs.get 'ignore' [] 49 | foldersLeft = dirs.length 50 | 51 | for exeFolder in dirs 52 | 53 | walkOpt = prefs.get 'walk' no_recurse: false max_depth: 4 54 | walk = walkdir slash.resolve(exeFolder), walkOpt 55 | 56 | walk.on 'error' (err) -> 57 | post.toWins 'mainlog' "walk error #{err.stack}" 58 | log "[ERROR] findExes -- #{err}" 59 | 60 | walk.on 'end' -> 61 | 62 | foldersLeft -= 1 63 | if foldersLeft == 0 64 | # post.toWins 'mainlog' "apps #{apps}" 65 | # klog 'apps' apps 66 | cb? apps 67 | 68 | walk.on 'file' (file) -> 69 | 70 | file = slash.resolve file 71 | if slash.ext(file) == 'exe' 72 | name = slash.base file 73 | if file not in ignore and not ignoredByName(name) and not ignoredByPath(file) 74 | if not apps[name]? 75 | apps[name] = file 76 | 77 | module.exports = exeFind 78 | -------------------------------------------------------------------------------- /bin/kappo-starter.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleAllowMixedLocalizations 6 | 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | applet 11 | CFBundleIconFile 12 | applet 13 | CFBundleIdentifier 14 | com.apple.ScriptEditor.id.kappo-starter 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | kappo-starter 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | aplt 25 | LSMinimumSystemVersionByArchitecture 26 | 27 | x86_64 28 | 10.6 29 | 30 | LSRequiresCarbon 31 | 32 | NSAppleEventsUsageDescription 33 | This script needs to control other applications to run. 34 | NSAppleMusicUsageDescription 35 | This script needs access to your music to run. 36 | NSCalendarsUsageDescription 37 | This script needs access to your calendars to run. 38 | NSCameraUsageDescription 39 | This script needs access to your camera to run. 40 | NSContactsUsageDescription 41 | This script needs access to your contacts to run. 42 | NSHomeKitUsageDescription 43 | This script needs access to your HomeKit Home to run. 44 | NSMicrophoneUsageDescription 45 | This script needs access to your microphone to run. 46 | NSPhotoLibraryUsageDescription 47 | This script needs access to your photos to run. 48 | NSRemindersUsageDescription 49 | This script needs access to your reminders to run. 50 | NSSiriUsageDescription 51 | This script needs access to Siri to run. 52 | NSSystemAdministrationUsageDescription 53 | This script needs access to administer this system to run. 54 | WindowState 55 | 56 | bundleDividerCollapsed 57 | 58 | bundlePositionOfDivider 59 | 0.0 60 | dividerCollapsed 61 | 62 | eventLogLevel 63 | 2 64 | name 65 | ScriptWindowState 66 | positionOfDivider 67 | 355 68 | savedFrame 69 | 555 35 700 672 0 0 1680 1027 70 | selectedTab 71 | description 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /coffee/exeicon.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | 0000000 000 000 00000000 000 0000000 0000000 000 000 3 | 00 000 000 000 000 000 000 000 0000 000 4 | 000000 00000 0000000 000 000 000 000 000 0 000 5 | 00 000 000 000 000 000 000 000 000 0000 6 | 0000000 000 000 00000000 000 0000000 0000000 000 000 7 | ### 8 | 9 | { slash, empty, fs, childp, kerror, klog } = require 'kxk' 10 | 11 | class ExeIcon 12 | 13 | @cache = {} 14 | 15 | @pngPath: (opt) -> 16 | 17 | slash.resolve slash.join opt.iconDir, slash.base(opt.appPath) + ".png" 18 | 19 | @get: (opt) -> 20 | 21 | pngPath = ExeIcon.pngPath opt 22 | if ExeIcon.cache[pngPath] 23 | opt.cb pngPath, opt.cbArg 24 | else 25 | fs.stat pngPath, (err, stat) -> 26 | if not err? and stat.isFile() 27 | ExeIcon.cache[pngPath] = true 28 | opt.cb pngPath, opt.cbArg 29 | else 30 | ExeIcon.getIcon opt 31 | 32 | @getIcon: (opt) -> 33 | 34 | appPath = slash.resolve opt.appPath 35 | pngPath = ExeIcon.pngPath opt 36 | 37 | klog 'getIcon', appPath, pngPath 38 | 39 | any2Ico = slash.path __dirname + '/../bin/Quick_Any2Ico.exe' 40 | 41 | if false #slash.isFile any2Ico 42 | 43 | childp.exec "\"#{any2Ico}\" -formats=512 -res=\"#{appPath}\" -icon=\"#{pngPath}\"", opt, (err,stdout,stderr) -> 44 | if not err 45 | # log stdout 46 | opt.cb pngPath, opt.cbArg 47 | else 48 | if slash.ext(appPath)!= 'lnk' 49 | kerror stdout, stderr, err 50 | ExeIcon.brokenIcon opt 51 | 52 | else 53 | wxw = require 'wxw' 54 | wxw 'icon' appPath, pngPath 55 | opt.cb pngPath, opt.cbArg 56 | 57 | @saveIconData: (data, opt) -> 58 | 59 | pngPath = ExeIcon.pngPath opt 60 | fs.writeFile pngPath, data, (err) -> 61 | if not err? 62 | opt.cb pngPath, opt.cbArg 63 | else 64 | kerror "saveIconData: #{err}" 65 | ExeIcon.brokenIcon opt 66 | 67 | @saveIconBase64: (data, opt) -> 68 | 69 | pngPath = ExeIcon.pngPath opt 70 | fs.writeFile pngPath, data, {encoding: 'base64'}, (err) -> 71 | if not err? 72 | opt.cb pngPath, opt.cbArg 73 | else 74 | kerror "saveIconBase64: #{err}" 75 | ExeIcon.brokenIcon opt 76 | 77 | @brokenIcon: (opt) -> 78 | 79 | brokenPath = slash.join __dirname, '..', 'img', 'broken.png' 80 | opt.cb brokenPath, opt.cbArg 81 | 82 | module.exports = ExeIcon 83 | -------------------------------------------------------------------------------- /bin/ignore.noon: -------------------------------------------------------------------------------- 1 | path 2 | /ASUS/ 3 | /bin/ 4 | /Bin/ 5 | /ClientX64/ 6 | /HDA/ 7 | /IDE/ 8 | /LANDesk/ 9 | /rempl/ 10 | /Symantec/Symantec 11 | /usr/libexec/ 12 | /VcXsrv/ 13 | anaconda3/Scripts/ 14 | ASUS/AMDA/ 15 | Microsoft/OneDrive/ 16 | Office/root/ 17 | scoop/shims 18 | shared/ClickToRun/ 19 | shared/ink/ 20 | Tools/ 21 | contains 22 | authentication 23 | cache 24 | configuration 25 | crash 26 | inst 27 | plugin 28 | service 29 | setup 30 | update 31 | startsWith 32 | 3dvision 33 | ait 34 | appcert 35 | beservice 36 | bss 37 | clink 38 | compil 39 | conemu- 40 | config 41 | dotfus 42 | dp 43 | geforce 44 | git- 45 | gld 46 | gs 47 | hlp 48 | hpmclient_ 49 | ie 50 | ii 51 | islz 52 | jhi 53 | mc 54 | mercurial 55 | microsoft. 56 | minidump 57 | mp 58 | ms 59 | myprog 60 | ndi 61 | nm 62 | nv 63 | ocenaudio_c 64 | ocenvst 65 | outofprocess 66 | python 67 | qt 68 | rm 69 | rtk 70 | rtl 71 | sense 72 | sign 73 | sm 74 | sql 75 | steamerr 76 | stree 77 | tamper 78 | teamviewer_ 79 | tf 80 | tv_ 81 | unins 82 | unpack 83 | vbox 84 | vc 85 | vs 86 | vulkan 87 | w9x 88 | wab 89 | wm 90 | x64 91 | x86 92 | matches 93 | 7z 94 | 7zg 95 | add_path 96 | agcp 97 | amd64 98 | analyzer 99 | appcmd 100 | askpass 101 | browsercore 102 | builder 103 | buildtools_full 104 | bzip2 105 | cccc 106 | chocolateygui 107 | chrome_proxy 108 | cleanup 109 | consoleexecutor 110 | container 111 | coregen 112 | crashreporter 113 | dotnet 114 | exclusivemodetool 115 | extexport 116 | elevate 117 | greenshotocrcommand 118 | gameoverlayui 119 | gen 120 | gup 121 | getopt 122 | git 123 | gui 124 | handle 125 | helper 126 | helixmfa 127 | hg 128 | hhc 129 | imagingdevices 130 | inkview 131 | instool 132 | intelpttekrecertification 133 | iscc 134 | link 135 | lms 136 | maintenanceservice 137 | makeappx 138 | nissrv 139 | offlinescannershell 140 | openssl 141 | p4 142 | p4_parallel 143 | p4admin 144 | p4d 145 | p4vc 146 | patch 147 | pdnrepair 148 | pingsender 149 | pipanel 150 | py 151 | pyw 152 | repair 153 | rg 154 | shellintegration 155 | slideshow 156 | sllauncher 157 | socketheciserver 158 | squirrel 159 | streaming_client 160 | supportwizard 161 | tsc 162 | ui 163 | un_a 164 | vswhere 165 | wdnsfltr 166 | wininfo 167 | writeminidump 168 | wsenable 169 | wslbridge 170 | xinputtest 171 | -------------------------------------------------------------------------------- /styl/style.styl: -------------------------------------------------------------------------------- 1 | 2 | // 0000000 000000000 000 000 000 3 | // 000 000 000 000 000 4 | // 0000000 000 00000 000 5 | // 000 000 000 000 6 | // 0000000 000 000 0000000 7 | 8 | font = "Avenir", "Varela Round", "Verdana" 9 | 10 | fill-abs() 11 | position absolute 12 | bottom 0 13 | right 0 14 | left 0 15 | top 0 16 | 17 | // 0000000 0000000 0000000 000 000 18 | // 000 000 000 000 000 000 000 000 19 | // 0000000 000 000 000 000 00000 20 | // 000 000 000 000 000 000 000 21 | // 0000000 0000000 0000000 000 22 | 23 | * 24 | outline-width 0 25 | 26 | body 27 | fill-abs() 28 | margin 0 29 | overflow hidden 30 | font-family font 31 | font-size 16px 32 | cursor pointer 33 | -webkit-user-select none 34 | 35 | // 00 00 0000000 000 000 000 36 | // 000 000 000 000 000 0000 000 37 | // 000000000 000000000 000 000 0 000 38 | // 000 0 000 000 000 000 000 0000 39 | // 000 000 000 000 000 000 000 40 | 41 | #main 42 | fill-abs() 43 | border-radius 6px 44 | overflow hidden 45 | pointer-events auto 46 | 47 | // 00000000 0000000 0000000 00000000 48 | // 000 000 000 000 000 000 49 | // 000000 000000000 000 000 0000000 50 | // 000 000 000 000 000 000 51 | // 000 000 000 0000000 00000000 52 | 53 | @keyframes fadein 54 | 0% 55 | opacity 0 56 | 50% 57 | opacity 0 58 | 100% 59 | opacity 1 60 | 61 | .fade 62 | animation fadein 0.3s 63 | animation-fill-mode forwards 64 | animation-timing-function ease-in 65 | 66 | // 0000000 00000000 00000000 67 | // 000 000 000 000 000 000 68 | // 000000000 00000000 00000000 69 | // 000 000 000 000 70 | // 000 000 000 000 71 | 72 | #app 73 | fill-abs() 74 | 75 | #appicon 76 | position absolute 77 | margin 0 78 | top 6% 79 | left 10% 80 | width 80% 81 | height 80% 82 | background-size 100% 100% 83 | cursor pointer 84 | 85 | #appname 86 | text-align center 87 | position absolute 88 | left 0 89 | right 0 90 | bottom 2% 91 | 92 | #appdots 93 | position absolute 94 | bottom 0 95 | left 0 96 | right 0 97 | 98 | #appdotr 99 | position relative 100 | overflow visible 101 | text-align center 102 | white-space nowrap 103 | height 6px 104 | 105 | .appdot 106 | display inline-block 107 | position relative 108 | bottom 12px 109 | width 6px 110 | height 6px 111 | -------------------------------------------------------------------------------- /js/winpaste.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // var keydownCtrl = new KeybdInput() 3 | // keydownCtrl.type = 1 4 | // keydownCtrl.wVk = 0x0011 5 | // keydownCtrl.wScan = 0 6 | // keydownCtrl.dwFlags = 0x0000 7 | // keydownCtrl.time = 0 8 | // keydownCtrl.dwExtraInfo = 0 9 | 10 | // var keyupCtrl = new KeybdInput() 11 | // keyupCtrl.type = 1 12 | // keyupCtrl.wVk = 0x0011 13 | // keyupCtrl.wScan = 0 14 | // keyupCtrl.dwFlags = 0x0002 15 | // keyupCtrl.time = 0 16 | // keyupCtrl.dwExtraInfo = 0 17 | 18 | // var keydownV = new KeybdInput() 19 | // keydownV.type = 1 20 | // keydownV.wVk = 0x0056 21 | // keydownV.wScan = 0 22 | // keydownV.dwFlags = 0x0000 23 | // keydownV.time = 0 24 | // keydownV.dwExtraInfo = 0 25 | 26 | // var keyupV = new KeybdInput() 27 | // keyupV.type = 1 28 | // keyupV.wVk = 0x0056 29 | // keyupV.wScan = 0 30 | // keyupV.dwFlags = 0x0002 31 | // keyupV.time = 0 32 | // keyupV.dwExtraInfo = 0 33 | 34 | // var r1 = user32.SendInput (1, keydownCtrl.ref() , 28) 35 | // var r2 = user32.SendInput (1, keydownV.ref() , 28) 36 | // var r3 = user32.SendInput (1, keyupV.ref() , 28) 37 | // var r4 = user32.SendInput (1, keyupCtrl.ref() , 28) 38 | 39 | 40 | }).call(this); 41 | 42 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lucGFzdGUuanMiLCJzb3VyY2VSb290IjoiLi4iLCJzb3VyY2VzIjpbImpzL3dpbnBhc3RlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSIsInNvdXJjZXNDb250ZW50IjpbIiMgICAgICAgdmFyIGtleWRvd25DdHJsID0gbmV3IEtleWJkSW5wdXQoKVxyXG4jICAgICAgIGtleWRvd25DdHJsLnR5cGUgPSAxXHJcbiMgICAgICAga2V5ZG93bkN0cmwud1ZrID0gMHgwMDExXHJcbiMgICAgICAga2V5ZG93bkN0cmwud1NjYW4gPSAwXHJcbiMgICAgICAga2V5ZG93bkN0cmwuZHdGbGFncyA9IDB4MDAwMFxyXG4jICAgICAgIGtleWRvd25DdHJsLnRpbWUgPSAwXHJcbiMgICAgICAga2V5ZG93bkN0cmwuZHdFeHRyYUluZm8gPSAwXHJcbiMgXHIgIFxuIyAgICAgICB2YXIga2V5dXBDdHJsID0gbmV3IEtleWJkSW5wdXQoKVxyXG4jICAgICAgIGtleXVwQ3RybC50eXBlID0gMVxyXG4jICAgICAgIGtleXVwQ3RybC53VmsgPSAweDAwMTFcclxuIyAgICAgICBrZXl1cEN0cmwud1NjYW4gPSAwXHJcbiMgICAgICAga2V5dXBDdHJsLmR3RmxhZ3MgPSAweDAwMDJcclxuIyAgICAgICBrZXl1cEN0cmwudGltZSA9IDBcclxuIyAgICAgICBrZXl1cEN0cmwuZHdFeHRyYUluZm8gPSAwXHJcbiMgXHIgIFxuIyAgICAgICB2YXIga2V5ZG93blYgPSBuZXcgS2V5YmRJbnB1dCgpXHJcbiMgICAgICAga2V5ZG93blYudHlwZSA9IDFcclxuIyAgICAgICBrZXlkb3duVi53VmsgPSAweDAwNTZcclxuIyAgICAgICBrZXlkb3duVi53U2NhbiA9IDBcclxuIyAgICAgICBrZXlkb3duVi5kd0ZsYWdzID0gMHgwMDAwXHJcbiMgICAgICAga2V5ZG93blYudGltZSA9IDBcclxuIyAgICAgICBrZXlkb3duVi5kd0V4dHJhSW5mbyA9IDBcclxuIyBcciAgXG4jICAgICAgIHZhciBrZXl1cFYgPSBuZXcgS2V5YmRJbnB1dCgpXHJcbiMgICAgICAga2V5dXBWLnR5cGUgPSAxXHJcbiMgICAgICAga2V5dXBWLndWayA9IDB4MDA1NlxyXG4jICAgICAgIGtleXVwVi53U2NhbiA9IDBcclxuIyAgICAgICBrZXl1cFYuZHdGbGFncyA9IDB4MDAwMlxyXG4jICAgICAgIGtleXVwVi50aW1lID0gMFxyXG4gICAjIGtleXVwVi5kd0V4dHJhSW5mbyA9IDBcblxuICAgIyB2YXIgcjEgPSB1c2VyMzIuU2VuZElucHV0ICgxLCBrZXlkb3duQ3RybC5yZWYoKSAsIDI4KVxyXG4jICAgICAgICAgICAgIHZhciByMiA9IHVzZXIzMi5TZW5kSW5wdXQgKDEsIGtleWRvd25WLnJlZigpICwgMjgpXHJcbiMgICAgICAgICAgICAgdmFyIHIzID0gdXNlcjMyLlNlbmRJbnB1dCAoMSwga2V5dXBWLnJlZigpICwgMjgpXHJcbiMgICAgICAgICAgICAgdmFyIHI0ID0gdXNlcjMyLlNlbmRJbnB1dCAoMSwga2V5dXBDdHJsLnJlZigpICwgMjgpXHJcbiJdfQ== 43 | //# sourceURL=C:/Users/kodi/s/kappo/coffee/winpaste.coffee -------------------------------------------------------------------------------- /js/winlaunch.js: -------------------------------------------------------------------------------- 1 | var childp, empty, error, foreground, log, ref, slash, winLaunch; 2 | 3 | ref = require('kxk'), slash = ref.slash, childp = ref.childp, empty = ref.empty, error = ref.error, log = ref.log; 4 | 5 | foreground = require('wxw').foreground; 6 | 7 | winLaunch = function(exePath) { 8 | var focusWins, subprocess; 9 | focusWins = foreground(exePath); 10 | if (!empty(focusWins)) { 11 | return { 12 | focusWins: focusWins 13 | }; 14 | } 15 | if ("cmd" === slash.base(exePath)) { 16 | childp.exec("start cmd /k"); 17 | return; 18 | } 19 | subprocess = childp.spawn("\"" + exePath + "\"", [], { 20 | detached: true, 21 | stdio: 'ignore', 22 | shell: true 23 | }); 24 | subprocess.on('error', function(err) { 25 | return error("winLaunch -- failed to start subprocess " + exePath + " " + (args.join(' ')) + "."); 26 | }); 27 | return { 28 | subprocess: subprocess 29 | }; 30 | }; 31 | 32 | module.exports = winLaunch; 33 | 34 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lubGF1bmNoLmpzIiwic291cmNlUm9vdCI6Ii4iLCJzb3VyY2VzIjpbIiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPQSxJQUFBOztBQUFBLE1BQXVDLE9BQUEsQ0FBUSxLQUFSLENBQXZDLEVBQUUsaUJBQUYsRUFBUyxtQkFBVCxFQUFpQixpQkFBakIsRUFBd0IsaUJBQXhCLEVBQStCOztBQUU3QixhQUFlLE9BQUEsQ0FBUSxLQUFSOztBQUVqQixTQUFBLEdBQVksU0FBQyxPQUFEO0FBRVIsTUFBQTtFQUFBLFNBQUEsR0FBWSxVQUFBLENBQVcsT0FBWDtFQUVaLElBQUcsQ0FBSSxLQUFBLENBQU0sU0FBTixDQUFQO0FBRUksV0FBTztNQUFBLFNBQUEsRUFBVSxTQUFWO01BRlg7O0VBSUEsSUFBRyxLQUFBLEtBQVMsS0FBSyxDQUFDLElBQU4sQ0FBVyxPQUFYLENBQVo7SUFDSSxNQUFNLENBQUMsSUFBUCxDQUFZLGNBQVo7QUFDQSxXQUZKOztFQUlBLFVBQUEsR0FBYSxNQUFNLENBQUMsS0FBUCxDQUFhLElBQUEsR0FBSyxPQUFMLEdBQWEsSUFBMUIsRUFBK0IsRUFBL0IsRUFBbUM7SUFBQSxRQUFBLEVBQVUsSUFBVjtJQUFnQixLQUFBLEVBQU8sUUFBdkI7SUFBaUMsS0FBQSxFQUFPLElBQXhDO0dBQW5DO0VBQ2IsVUFBVSxDQUFDLEVBQVgsQ0FBYyxPQUFkLEVBQXVCLFNBQUMsR0FBRDtXQUNuQixLQUFBLENBQU0sMENBQUEsR0FBMkMsT0FBM0MsR0FBbUQsR0FBbkQsR0FBcUQsQ0FBQyxJQUFJLENBQUMsSUFBTCxDQUFVLEdBQVYsQ0FBRCxDQUFyRCxHQUFvRSxHQUExRTtFQURtQixDQUF2QjtBQUdBLFNBQU87SUFBQSxVQUFBLEVBQVcsVUFBWDs7QUFoQkM7O0FBa0JaLE1BQU0sQ0FBQyxPQUFQLEdBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiXG4jIDAwMCAgIDAwMCAgMDAwICAwMDAgICAwMDAgIDAwMCAgICAgICAwMDAwMDAwICAgMDAwICAgMDAwICAwMDAgICAwMDAgICAwMDAwMDAwICAwMDAgICAwMDBcbiMgMDAwIDAgMDAwICAwMDAgIDAwMDAgIDAwMCAgMDAwICAgICAgMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMDAgIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMFxuIyAwMDAwMDAwMDAgIDAwMCAgMDAwIDAgMDAwICAwMDAgICAgICAwMDAwMDAwMDAgIDAwMCAgIDAwMCAgMDAwIDAgMDAwICAwMDAgICAgICAgMDAwMDAwMDAwXG4jIDAwMCAgIDAwMCAgMDAwICAwMDAgIDAwMDAgIDAwMCAgICAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgIDAwMDAgIDAwMCAgICAgICAwMDAgICAwMDBcbiMgMDAgICAgIDAwICAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgMDAwICAgMDAwICAgMDAwMDAwMCAgIDAwMCAgIDAwMCAgIDAwMDAwMDAgIDAwMCAgIDAwMFxuXG57IHNsYXNoLCBjaGlsZHAsIGVtcHR5LCBlcnJvciwgbG9nIH0gPSByZXF1aXJlICdreGsnXG5cbnsgZm9yZWdyb3VuZCB9ID0gcmVxdWlyZSAnd3h3J1xuXG53aW5MYXVuY2ggPSAoZXhlUGF0aCkgLT5cbiAgICBcbiAgICBmb2N1c1dpbnMgPSBmb3JlZ3JvdW5kIGV4ZVBhdGhcbiAgICAgICAgXG4gICAgaWYgbm90IGVtcHR5IGZvY3VzV2luc1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGZvY3VzV2luczpmb2N1c1dpbnNcbiAgICAgICAgXG4gICAgaWYgXCJjbWRcIiA9PSBzbGFzaC5iYXNlIGV4ZVBhdGhcbiAgICAgICAgY2hpbGRwLmV4ZWMgXCJzdGFydCBjbWQgL2tcIlxuICAgICAgICByZXR1cm5cbiAgICAgICAgXG4gICAgc3VicHJvY2VzcyA9IGNoaWxkcC5zcGF3biBcIlxcXCIje2V4ZVBhdGh9XFxcIlwiLCBbXSwgZGV0YWNoZWQ6IHRydWUsIHN0ZGlvOiAnaWdub3JlJywgc2hlbGw6IHRydWVcbiAgICBzdWJwcm9jZXNzLm9uICdlcnJvcicsIChlcnIpIC0+XG4gICAgICAgIGVycm9yIFwid2luTGF1bmNoIC0tIGZhaWxlZCB0byBzdGFydCBzdWJwcm9jZXNzICN7ZXhlUGF0aH0gI3thcmdzLmpvaW4gJyAnfS5cIlxuICAgICAgICBcbiAgICByZXR1cm4gc3VicHJvY2VzczpzdWJwcm9jZXNzXG5cbm1vZHVsZS5leHBvcnRzID0gd2luTGF1bmNoXG4iXX0= 35 | //# sourceURL=../coffee/winlaunch.coffee -------------------------------------------------------------------------------- /js/appfind.js: -------------------------------------------------------------------------------- 1 | // koffee 1.12.0 2 | 3 | /* 4 | 0000000 00000000 00000000 00000000 000 000 000 0000000 5 | 000 000 000 000 000 000 000 000 0000 000 000 000 6 | 000000000 00000000 00000000 000000 000 000 0 000 000 000 7 | 000 000 000 000 000 000 000 0000 000 000 8 | 000 000 000 000 000 000 000 000 0000000 9 | */ 10 | var _, appFind, last, log, prefs, ref, slash, walkdir; 11 | 12 | ref = require('kxk'), walkdir = ref.walkdir, prefs = ref.prefs, slash = ref.slash, last = ref.last, log = ref.log, _ = ref._; 13 | 14 | appFind = function(cb) { 15 | var appFolder, appFolders, apps, foldersLeft, i, len, results, walk, walkOpt; 16 | apps = {}; 17 | apps['Finder'] = "/System/Library/CoreServices/Finder.app"; 18 | appFolders = ["/Applications", "/Applications/Utilities", "/System/Applications", "/System/Applications/Utilities", "~"]; 19 | appFolders = appFolders.concat(prefs.get('dirs', [])); 20 | foldersLeft = appFolders.length; 21 | results = []; 22 | for (i = 0, len = appFolders.length; i < len; i++) { 23 | appFolder = appFolders[i]; 24 | walkOpt = prefs.get('walk', { 25 | no_recurse: false, 26 | max_depth: 4 27 | }); 28 | walk = walkdir(slash.resolve(appFolder), walkOpt); 29 | walk.on('error', function(err) { 30 | return console.log("[ERROR] findApps -- " + err); 31 | }); 32 | walk.on('end', function() { 33 | foldersLeft -= 1; 34 | if (foldersLeft === 0) { 35 | return cb(apps); 36 | } 37 | }); 38 | results.push(walk.on('directory', function(dir) { 39 | var name; 40 | if (slash.ext(dir) === 'app') { 41 | if (!/(Helper$|NP$|EH$)/.test(slash.base(dir))) { 42 | name = slash.base(dir); 43 | return apps[name] = dir; 44 | } 45 | } 46 | })); 47 | } 48 | return results; 49 | }; 50 | 51 | module.exports = appFind; 52 | 53 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwZmluZC5qcyIsInNvdXJjZVJvb3QiOiIuLi9jb2ZmZWUiLCJzb3VyY2VzIjpbImFwcGZpbmQuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7Ozs7Ozs7QUFBQSxJQUFBOztBQVFBLE1BQTBDLE9BQUEsQ0FBUSxLQUFSLENBQTFDLEVBQUUscUJBQUYsRUFBVyxpQkFBWCxFQUFrQixpQkFBbEIsRUFBeUIsZUFBekIsRUFBK0IsYUFBL0IsRUFBb0M7O0FBRXBDLE9BQUEsR0FBVSxTQUFDLEVBQUQ7QUFFTixRQUFBO0lBQUEsSUFBQSxHQUFPO0lBQ1AsSUFBSyxDQUFBLFFBQUEsQ0FBTCxHQUFpQjtJQUNqQixVQUFBLEdBQWEsQ0FDVCxlQURTLEVBRVQseUJBRlMsRUFHVCxzQkFIUyxFQUlULGdDQUpTLEVBS1QsR0FMUztJQU9iLFVBQUEsR0FBYSxVQUFVLENBQUMsTUFBWCxDQUFrQixLQUFLLENBQUMsR0FBTixDQUFVLE1BQVYsRUFBa0IsRUFBbEIsQ0FBbEI7SUFDYixXQUFBLEdBQWMsVUFBVSxDQUFDO0FBRXpCO1NBQUEsNENBQUE7O1FBQ0ksT0FBQSxHQUFVLEtBQUssQ0FBQyxHQUFOLENBQVUsTUFBVixFQUFrQjtZQUFBLFVBQUEsRUFBWSxLQUFaO1lBQW1CLFNBQUEsRUFBVyxDQUE5QjtTQUFsQjtRQUNWLElBQUEsR0FBTyxPQUFBLENBQVEsS0FBSyxDQUFDLE9BQU4sQ0FBYyxTQUFkLENBQVIsRUFBa0MsT0FBbEM7UUFDUCxJQUFJLENBQUMsRUFBTCxDQUFRLE9BQVIsRUFBaUIsU0FBQyxHQUFEO21CQUFPLE9BQUEsQ0FBRSxHQUFGLENBQU0sc0JBQUEsR0FBdUIsR0FBN0I7UUFBUCxDQUFqQjtRQUNBLElBQUksQ0FBQyxFQUFMLENBQVEsS0FBUixFQUFlLFNBQUE7WUFDWCxXQUFBLElBQWU7WUFDZixJQUFHLFdBQUEsS0FBZSxDQUFsQjt1QkFFSSxFQUFBLENBQUcsSUFBSCxFQUZKOztRQUZXLENBQWY7cUJBS0EsSUFBSSxDQUFDLEVBQUwsQ0FBUSxXQUFSLEVBQXFCLFNBQUMsR0FBRDtBQUNqQixnQkFBQTtZQUFBLElBQUcsS0FBSyxDQUFDLEdBQU4sQ0FBVSxHQUFWLENBQUEsS0FBa0IsS0FBckI7Z0JBQ0ksSUFBRyxDQUFJLG1CQUFtQixDQUFDLElBQXBCLENBQXlCLEtBQUssQ0FBQyxJQUFOLENBQVcsR0FBWCxDQUF6QixDQUFQO29CQUNJLElBQUEsR0FBTyxLQUFLLENBQUMsSUFBTixDQUFXLEdBQVg7MkJBQ1AsSUFBSyxDQUFBLElBQUEsQ0FBTCxHQUFhLElBRmpCO2lCQURKOztRQURpQixDQUFyQjtBQVRKOztBQWRNOztBQTZCVixNQUFNLENBQUMsT0FBUCxHQUFpQiIsInNvdXJjZXNDb250ZW50IjpbIiMjI1xuIDAwMDAwMDAgICAwMDAwMDAwMCAgIDAwMDAwMDAwICAgMDAwMDAwMDAgIDAwMCAgMDAwICAgMDAwICAwMDAwMDAwICAgIFxuMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgICAgIDAwMCAgMDAwMCAgMDAwICAwMDAgICAwMDAgIFxuMDAwMDAwMDAwICAwMDAwMDAwMCAgIDAwMDAwMDAwICAgMDAwMDAwICAgIDAwMCAgMDAwIDAgMDAwICAwMDAgICAwMDAgIFxuMDAwICAgMDAwICAwMDAgICAgICAgIDAwMCAgICAgICAgMDAwICAgICAgIDAwMCAgMDAwICAwMDAwICAwMDAgICAwMDAgIFxuMDAwICAgMDAwICAwMDAgICAgICAgIDAwMCAgICAgICAgMDAwICAgICAgIDAwMCAgMDAwICAgMDAwICAwMDAwMDAwICAgIFxuIyMjXG5cbnsgd2Fsa2RpciwgcHJlZnMsIHNsYXNoLCBsYXN0LCBsb2csIF8gfSA9IHJlcXVpcmUgJ2t4aydcblxuYXBwRmluZCA9IChjYikgLT5cblxuICAgIGFwcHMgPSB7fVxuICAgIGFwcHNbJ0ZpbmRlciddID0gXCIvU3lzdGVtL0xpYnJhcnkvQ29yZVNlcnZpY2VzL0ZpbmRlci5hcHBcIlxuICAgIGFwcEZvbGRlcnMgPSBbXG4gICAgICAgIFwiL0FwcGxpY2F0aW9uc1wiXG4gICAgICAgIFwiL0FwcGxpY2F0aW9ucy9VdGlsaXRpZXNcIlxuICAgICAgICBcIi9TeXN0ZW0vQXBwbGljYXRpb25zXCJcbiAgICAgICAgXCIvU3lzdGVtL0FwcGxpY2F0aW9ucy9VdGlsaXRpZXNcIlxuICAgICAgICBcIn5cIlxuICAgICAgICBdXG4gICAgYXBwRm9sZGVycyA9IGFwcEZvbGRlcnMuY29uY2F0IHByZWZzLmdldCAnZGlycycsIFtdXG4gICAgZm9sZGVyc0xlZnQgPSBhcHBGb2xkZXJzLmxlbmd0aFxuICAgIFxuICAgIGZvciBhcHBGb2xkZXIgaW4gYXBwRm9sZGVyc1xuICAgICAgICB3YWxrT3B0ID0gcHJlZnMuZ2V0ICd3YWxrJywgbm9fcmVjdXJzZTogZmFsc2UsIG1heF9kZXB0aDogNFxuICAgICAgICB3YWxrID0gd2Fsa2RpciBzbGFzaC5yZXNvbHZlKGFwcEZvbGRlciksIHdhbGtPcHRcbiAgICAgICAgd2Fsay5vbiAnZXJyb3InLCAoZXJyKSAtPiBsb2cgXCJbRVJST1JdIGZpbmRBcHBzIC0tICN7ZXJyfVwiXG4gICAgICAgIHdhbGsub24gJ2VuZCcsIC0+XG4gICAgICAgICAgICBmb2xkZXJzTGVmdCAtPSAxXG4gICAgICAgICAgICBpZiBmb2xkZXJzTGVmdCA9PSAwXG4gICAgICAgICAgICAgICAgIyBsb2cgXCJmb3VuZDogI3tfLnNpemUgYXBwc31cIlxuICAgICAgICAgICAgICAgIGNiIGFwcHNcbiAgICAgICAgd2Fsay5vbiAnZGlyZWN0b3J5JywgKGRpcikgLT5cbiAgICAgICAgICAgIGlmIHNsYXNoLmV4dChkaXIpID09ICdhcHAnIFxuICAgICAgICAgICAgICAgIGlmIG5vdCAvKEhlbHBlciR8TlAkfEVIJCkvLnRlc3Qgc2xhc2guYmFzZSBkaXJcbiAgICAgICAgICAgICAgICAgICAgbmFtZSA9IHNsYXNoLmJhc2UgZGlyXG4gICAgICAgICAgICAgICAgICAgIGFwcHNbbmFtZV0gPSBkaXJcblxubW9kdWxlLmV4cG9ydHMgPSBhcHBGaW5kICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgIl19 54 | //# sourceURL=../coffee/appfind.coffee -------------------------------------------------------------------------------- /js/scripts.js: -------------------------------------------------------------------------------- 1 | // koffee 1.12.0 2 | 3 | /* 4 | 0000000 0000000 00000000 000 00000000 000000000 0000000 5 | 000 000 000 000 000 000 000 000 000 6 | 0000000 000 0000000 000 00000000 000 0000000 7 | 000 000 000 000 000 000 000 000 8 | 0000000 0000000 000 000 000 000 000 0000000 9 | */ 10 | var log, macScripts, prefs, ref, slash, winRecycle, winScripts; 11 | 12 | ref = require('kxk'), prefs = ref.prefs, slash = ref.slash, log = ref.log; 13 | 14 | winRecycle = function() { 15 | var wxw; 16 | wxw = require('wxw'); 17 | return wxw('trash', 'empty'); 18 | }; 19 | 20 | winScripts = function() { 21 | var scripts; 22 | scripts = { 23 | recycle: { 24 | cb: winRecycle, 25 | img: slash.resolve(__dirname + "/../scripts/recycle.png") 26 | }, 27 | sleep: { 28 | exec: 'shutdown /h', 29 | img: slash.resolve(__dirname + "/../scripts/sleep.png") 30 | }, 31 | shutdown: { 32 | exec: 'shutdown /s /t 0', 33 | img: slash.resolve(__dirname + "/../scripts/shutdown.png") 34 | }, 35 | restart: { 36 | exec: 'shutdown /r /t 0', 37 | img: slash.resolve(__dirname + "/../scripts/restart.png") 38 | }, 39 | terminal: { 40 | exec: "C:/msys64/usr/bin/mintty.exe -o 'AppLaunchCmd=C:\msys64\mingw64.exe' -o 'AppID=MSYS2.Shell.MINGW64.9' -p 950,0 -t 'fish' -- /usr/bin/sh -lc fish", 41 | img: slash.resolve(__dirname + "/../img/terminal.png"), 42 | foreground: "C:/msys64/usr/bin/mintty.exe" 43 | } 44 | }; 45 | return scripts; 46 | }; 47 | 48 | macScripts = function() { 49 | var scripts; 50 | scripts = { 51 | sleep: { 52 | exec: "pmset sleepnow", 53 | img: __dirname + "/../scripts/sleep.png" 54 | }, 55 | shutdown: { 56 | exec: "osascript -e 'tell app \"System Events\" to shut down'", 57 | img: __dirname + "/../scripts/shutdown.png" 58 | }, 59 | restart: { 60 | exec: "osascript -e 'tell app \"System Events\" to restart'", 61 | img: __dirname + "/../scripts/restart.png" 62 | } 63 | }; 64 | if (prefs.get('confirmShutdown')) { 65 | scripts.shutdown.exec = "osascript -e 'tell app \"loginwindow\" to «event aevtrsdn»'"; 66 | } 67 | if (prefs.get('confirmRestart')) { 68 | scripts.restart.exec = "osascript -e 'tell app \"loginwindow\" to «event aevtrrst»'"; 69 | } 70 | return scripts; 71 | }; 72 | 73 | module.exports = { 74 | macScripts: macScripts, 75 | winScripts: winScripts 76 | }; 77 | 78 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0cy5qcyIsInNvdXJjZVJvb3QiOiIuLi9jb2ZmZWUiLCJzb3VyY2VzIjpbInNjcmlwdHMuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7Ozs7Ozs7QUFBQSxJQUFBOztBQVFBLE1BQXdCLE9BQUEsQ0FBUSxLQUFSLENBQXhCLEVBQUUsaUJBQUYsRUFBUyxpQkFBVCxFQUFnQjs7QUFFaEIsVUFBQSxHQUFjLFNBQUE7QUFFVixRQUFBO0lBQUEsR0FBQSxHQUFNLE9BQUEsQ0FBUSxLQUFSO1dBQ04sR0FBQSxDQUFJLE9BQUosRUFBWSxPQUFaO0FBSFU7O0FBS2QsVUFBQSxHQUFhLFNBQUE7QUFFVCxRQUFBO0lBQUEsT0FBQSxHQUNJO1FBQUEsT0FBQSxFQUNJO1lBQUEsRUFBQSxFQUFRLFVBQVI7WUFDQSxHQUFBLEVBQVEsS0FBSyxDQUFDLE9BQU4sQ0FBaUIsU0FBRCxHQUFXLHlCQUEzQixDQURSO1NBREo7UUFHQSxLQUFBLEVBQ0k7WUFBQSxJQUFBLEVBQVEsYUFBUjtZQUNBLEdBQUEsRUFBUSxLQUFLLENBQUMsT0FBTixDQUFpQixTQUFELEdBQVcsdUJBQTNCLENBRFI7U0FKSjtRQU1BLFFBQUEsRUFDSTtZQUFBLElBQUEsRUFBUSxrQkFBUjtZQUNBLEdBQUEsRUFBUSxLQUFLLENBQUMsT0FBTixDQUFpQixTQUFELEdBQVcsMEJBQTNCLENBRFI7U0FQSjtRQVNBLE9BQUEsRUFDSTtZQUFBLElBQUEsRUFBUSxrQkFBUjtZQUNBLEdBQUEsRUFBUSxLQUFLLENBQUMsT0FBTixDQUFpQixTQUFELEdBQVcseUJBQTNCLENBRFI7U0FWSjtRQVlBLFFBQUEsRUFFSTtZQUFBLElBQUEsRUFBUSxtSkFBUjtZQUNBLEdBQUEsRUFBUSxLQUFLLENBQUMsT0FBTixDQUFpQixTQUFELEdBQVcsc0JBQTNCLENBRFI7WUFFQSxVQUFBLEVBQVksOEJBRlo7U0FkSjs7V0FpQko7QUFwQlM7O0FBc0JiLFVBQUEsR0FBYSxTQUFBO0FBRVQsUUFBQTtJQUFBLE9BQUEsR0FDSTtRQUFBLEtBQUEsRUFDSTtZQUFBLElBQUEsRUFBUSxnQkFBUjtZQUNBLEdBQUEsRUFBVyxTQUFELEdBQVcsdUJBRHJCO1NBREo7UUFHQSxRQUFBLEVBQ0k7WUFBQSxJQUFBLEVBQVEsd0RBQVI7WUFDQSxHQUFBLEVBQVcsU0FBRCxHQUFXLDBCQURyQjtTQUpKO1FBTUEsT0FBQSxFQUNJO1lBQUEsSUFBQSxFQUFRLHNEQUFSO1lBQ0EsR0FBQSxFQUFXLFNBQUQsR0FBVyx5QkFEckI7U0FQSjs7SUFVSixJQUFHLEtBQUssQ0FBQyxHQUFOLENBQVUsaUJBQVYsQ0FBSDtRQUNJLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBakIsR0FBd0IsOERBRDVCOztJQUVBLElBQUcsS0FBSyxDQUFDLEdBQU4sQ0FBVSxnQkFBVixDQUFIO1FBQ0ksT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFoQixHQUF1Qiw4REFEM0I7O1dBRUE7QUFqQlM7O0FBbUJiLE1BQU0sQ0FBQyxPQUFQLEdBQ0k7SUFBQSxVQUFBLEVBQVksVUFBWjtJQUNBLFVBQUEsRUFBWSxVQURaIiwic291cmNlc0NvbnRlbnQiOlsiIyMjXG4gMDAwMDAwMCAgIDAwMDAwMDAgIDAwMDAwMDAwICAgMDAwICAwMDAwMDAwMCAgIDAwMDAwMDAwMCAgIDAwMDAwMDBcbjAwMCAgICAgICAwMDAgICAgICAgMDAwICAgMDAwICAwMDAgIDAwMCAgIDAwMCAgICAgMDAwICAgICAwMDBcbjAwMDAwMDAgICAwMDAgICAgICAgMDAwMDAwMCAgICAwMDAgIDAwMDAwMDAwICAgICAgMDAwICAgICAwMDAwMDAwXG4gICAgIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwICAwMDAgICAgICAgICAgIDAwMCAgICAgICAgICAwMDBcbjAwMDAwMDAgICAgMDAwMDAwMCAgMDAwICAgMDAwICAwMDAgIDAwMCAgICAgICAgICAgMDAwICAgICAwMDAwMDAwXG4jIyNcblxueyBwcmVmcywgc2xhc2gsIGxvZyB9ID0gcmVxdWlyZSAna3hrJ1xuXG53aW5SZWN5Y2xlICA9IC0+XG4gICAgXG4gICAgd3h3ID0gcmVxdWlyZSAnd3h3J1xuICAgIHd4dyAndHJhc2gnICdlbXB0eSdcbiAgICBcbndpblNjcmlwdHMgPSAoKSAtPlxuICAgIFxuICAgIHNjcmlwdHMgPSBcbiAgICAgICAgcmVjeWNsZTpcbiAgICAgICAgICAgIGNiOiAgICAgd2luUmVjeWNsZVxuICAgICAgICAgICAgaW1nOiAgICBzbGFzaC5yZXNvbHZlIFwiI3tfX2Rpcm5hbWV9Ly4uL3NjcmlwdHMvcmVjeWNsZS5wbmdcIlxuICAgICAgICBzbGVlcDpcbiAgICAgICAgICAgIGV4ZWM6ICAgJ3NodXRkb3duIC9oJ1xuICAgICAgICAgICAgaW1nOiAgICBzbGFzaC5yZXNvbHZlIFwiI3tfX2Rpcm5hbWV9Ly4uL3NjcmlwdHMvc2xlZXAucG5nXCJcbiAgICAgICAgc2h1dGRvd246XG4gICAgICAgICAgICBleGVjOiAgICdzaHV0ZG93biAvcyAvdCAwJ1xuICAgICAgICAgICAgaW1nOiAgICBzbGFzaC5yZXNvbHZlIFwiI3tfX2Rpcm5hbWV9Ly4uL3NjcmlwdHMvc2h1dGRvd24ucG5nXCJcbiAgICAgICAgcmVzdGFydDpcbiAgICAgICAgICAgIGV4ZWM6ICAgJ3NodXRkb3duIC9yIC90IDAnXG4gICAgICAgICAgICBpbWc6ICAgIHNsYXNoLnJlc29sdmUgXCIje19fZGlybmFtZX0vLi4vc2NyaXB0cy9yZXN0YXJ0LnBuZ1wiXG4gICAgICAgIHRlcm1pbmFsOlxuICAgICAgICAgICAgIyBleGVjOiAgIFwiQzovbXN5czY0L3Vzci9iaW4vbWludHR5LmV4ZSAtaSBcXFwiI3tzbGFzaC5yZXNvbHZlIFwiI3tfX2Rpcm5hbWV9Ly4uL3NjcmlwdHMvdGVybWluYWwuaWNvXCJ9XFxcIiAtbyAnQXBwTGF1bmNoQ21kPUM6XFxtc3lzNjRcXG1pbmd3NjQuZXhlJyAtbyAnQXBwSUQ9TVNZUzIuU2hlbGwuTUlOR1c2NC45JyAtcCA5NTAsMCAtdCAnZmlzaCcgLS0gIC91c3IvYmluL3NoIC1sYyBmaXNoXCJcbiAgICAgICAgICAgIGV4ZWM6ICAgXCJDOi9tc3lzNjQvdXNyL2Jpbi9taW50dHkuZXhlIC1vICdBcHBMYXVuY2hDbWQ9QzpcXG1zeXM2NFxcbWluZ3c2NC5leGUnIC1vICdBcHBJRD1NU1lTMi5TaGVsbC5NSU5HVzY0LjknIC1wIDk1MCwwIC10ICdmaXNoJyAtLSAgL3Vzci9iaW4vc2ggLWxjIGZpc2hcIlxuICAgICAgICAgICAgaW1nOiAgICBzbGFzaC5yZXNvbHZlIFwiI3tfX2Rpcm5hbWV9Ly4uL2ltZy90ZXJtaW5hbC5wbmdcIlxuICAgICAgICAgICAgZm9yZWdyb3VuZDogXCJDOi9tc3lzNjQvdXNyL2Jpbi9taW50dHkuZXhlXCJcbiAgICBzY3JpcHRzXG5cbm1hY1NjcmlwdHMgPSAoKSAtPlxuICAgIFxuICAgIHNjcmlwdHMgPVxuICAgICAgICBzbGVlcDpcbiAgICAgICAgICAgIGV4ZWM6ICAgXCJwbXNldCBzbGVlcG5vd1wiXG4gICAgICAgICAgICBpbWc6ICAgIFwiI3tfX2Rpcm5hbWV9Ly4uL3NjcmlwdHMvc2xlZXAucG5nXCJcbiAgICAgICAgc2h1dGRvd246XG4gICAgICAgICAgICBleGVjOiAgIFwib3Nhc2NyaXB0IC1lICd0ZWxsIGFwcCBcXFwiU3lzdGVtIEV2ZW50c1xcXCIgdG8gc2h1dCBkb3duJ1wiXG4gICAgICAgICAgICBpbWc6ICAgIFwiI3tfX2Rpcm5hbWV9Ly4uL3NjcmlwdHMvc2h1dGRvd24ucG5nXCJcbiAgICAgICAgcmVzdGFydDpcbiAgICAgICAgICAgIGV4ZWM6ICAgXCJvc2FzY3JpcHQgLWUgJ3RlbGwgYXBwIFxcXCJTeXN0ZW0gRXZlbnRzXFxcIiB0byByZXN0YXJ0J1wiXG4gICAgICAgICAgICBpbWc6ICAgIFwiI3tfX2Rpcm5hbWV9Ly4uL3NjcmlwdHMvcmVzdGFydC5wbmdcIlxuXG4gICAgaWYgcHJlZnMuZ2V0ICdjb25maXJtU2h1dGRvd24nXG4gICAgICAgIHNjcmlwdHMuc2h1dGRvd24uZXhlYyA9IFwib3Nhc2NyaXB0IC1lICd0ZWxsIGFwcCBcXFwibG9naW53aW5kb3dcXFwiIHRvIMKrZXZlbnQgYWV2dHJzZG7CuydcIlxuICAgIGlmIHByZWZzLmdldCAnY29uZmlybVJlc3RhcnQnXG4gICAgICAgIHNjcmlwdHMucmVzdGFydC5leGVjID0gXCJvc2FzY3JpcHQgLWUgJ3RlbGwgYXBwIFxcXCJsb2dpbndpbmRvd1xcXCIgdG8gwqtldmVudCBhZXZ0cnJzdMK7J1wiXG4gICAgc2NyaXB0c1xuXG5tb2R1bGUuZXhwb3J0cyA9IFxuICAgIG1hY1NjcmlwdHM6IG1hY1NjcmlwdHNcbiAgICB3aW5TY3JpcHRzOiB3aW5TY3JpcHRzXG4gICAgIl19 79 | //# sourceURL=../coffee/scripts.coffee -------------------------------------------------------------------------------- /js/appicon.js: -------------------------------------------------------------------------------- 1 | // koffee 1.3.0 2 | 3 | /* 4 | 0000000 00000000 00000000 000 0000000 0000000 000 000 5 | 000 000 000 000 000 000 000 000 000 000 0000 000 6 | 000000000 00000000 00000000 000 000 000 000 000 0 000 7 | 000 000 000 000 000 000 000 000 000 0000 8 | 000 000 000 000 000 0000000 0000000 000 000 9 | */ 10 | var AppIcon, childp, error, fs, log, plist, ref, slash; 11 | 12 | ref = require('kxk'), childp = ref.childp, fs = ref.fs, slash = ref.slash, error = ref.error, log = ref.log; 13 | 14 | plist = require('simple-plist'); 15 | 16 | AppIcon = (function() { 17 | function AppIcon() {} 18 | 19 | AppIcon.cache = {}; 20 | 21 | AppIcon.pngPath = function(opt) { 22 | return slash.resolve(slash.join(opt.iconDir, slash.base(opt.appPath) + ".png")); 23 | }; 24 | 25 | AppIcon.get = function(opt) { 26 | var pngPath; 27 | pngPath = AppIcon.pngPath(opt); 28 | if (AppIcon.cache[pngPath]) { 29 | return opt.cb(pngPath, opt.cbArg); 30 | } else { 31 | return fs.stat(pngPath, function(err, stat) { 32 | if ((err == null) && stat.isFile()) { 33 | AppIcon.cache[pngPath] = true; 34 | return opt.cb(pngPath, opt.cbArg); 35 | } else { 36 | return AppIcon.getIcon(opt); 37 | } 38 | }); 39 | } 40 | }; 41 | 42 | AppIcon.getIcon = function(opt) { 43 | var appPath, infoPath; 44 | appPath = opt.appPath; 45 | infoPath = slash.join(appPath, 'Contents', 'Info.plist'); 46 | return plist.readFile(infoPath, function(err, obj) { 47 | var icnsPath; 48 | if (err == null) { 49 | if (obj['CFBundleIconFile'] != null) { 50 | icnsPath = slash.join(slash.dirname(infoPath), 'Resources', obj['CFBundleIconFile']); 51 | if (!icnsPath.endsWith('.icns')) { 52 | icnsPath += ".icns"; 53 | } 54 | return AppIcon.saveIcon(icnsPath, opt); 55 | } else { 56 | return AppIcon.brokenIcon(opt); 57 | } 58 | } else { 59 | console.error("getIcon: " + err); 60 | return AppIcon.brokenIcon(opt); 61 | } 62 | }); 63 | }; 64 | 65 | AppIcon.saveIcon = function(icnsPath, opt) { 66 | var pngPath; 67 | pngPath = AppIcon.pngPath(opt); 68 | return childp.exec("/usr/bin/sips -Z " + opt.size + " -s format png \"" + icnsPath + "\" --out \"" + pngPath + "\"", function(err) { 69 | if (err == null) { 70 | return opt.cb(pngPath, opt.cbArg); 71 | } else { 72 | console.error("saveIcon: " + err); 73 | return AppIcon.brokenIcon(opt); 74 | } 75 | }); 76 | }; 77 | 78 | AppIcon.brokenIcon = function(opt) { 79 | var brokenPath; 80 | brokenPath = slash.join(__dirname, '..', 'img', 'broken.png'); 81 | return opt.cb(brokenPath, opt.cbArg); 82 | }; 83 | 84 | return AppIcon; 85 | 86 | })(); 87 | 88 | module.exports = AppIcon; 89 | 90 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwaWNvbi5qcyIsInNvdXJjZVJvb3QiOiIuIiwic291cmNlcyI6WyIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7OztBQUFBLElBQUE7O0FBUUEsTUFBb0MsT0FBQSxDQUFRLEtBQVIsQ0FBcEMsRUFBRSxtQkFBRixFQUFVLFdBQVYsRUFBYyxpQkFBZCxFQUFxQixpQkFBckIsRUFBNEI7O0FBRTVCLEtBQUEsR0FBUSxPQUFBLENBQVEsY0FBUjs7QUFFRjs7O0lBRUYsT0FBQyxDQUFBLEtBQUQsR0FBUzs7SUFFVCxPQUFDLENBQUEsT0FBRCxHQUFVLFNBQUMsR0FBRDtlQUVOLEtBQUssQ0FBQyxPQUFOLENBQWMsS0FBSyxDQUFDLElBQU4sQ0FBVyxHQUFHLENBQUMsT0FBZixFQUF3QixLQUFLLENBQUMsSUFBTixDQUFXLEdBQUcsQ0FBQyxPQUFmLENBQUEsR0FBMEIsTUFBbEQsQ0FBZDtJQUZNOztJQUlWLE9BQUMsQ0FBQSxHQUFELEdBQU0sU0FBQyxHQUFEO0FBRUYsWUFBQTtRQUFBLE9BQUEsR0FBVSxPQUFPLENBQUMsT0FBUixDQUFnQixHQUFoQjtRQUNWLElBQUcsT0FBTyxDQUFDLEtBQU0sQ0FBQSxPQUFBLENBQWpCO21CQUNJLEdBQUcsQ0FBQyxFQUFKLENBQU8sT0FBUCxFQUFnQixHQUFHLENBQUMsS0FBcEIsRUFESjtTQUFBLE1BQUE7bUJBR0ksRUFBRSxDQUFDLElBQUgsQ0FBUSxPQUFSLEVBQWlCLFNBQUMsR0FBRCxFQUFNLElBQU47Z0JBQ2IsSUFBTyxhQUFKLElBQWEsSUFBSSxDQUFDLE1BQUwsQ0FBQSxDQUFoQjtvQkFDSSxPQUFPLENBQUMsS0FBTSxDQUFBLE9BQUEsQ0FBZCxHQUF5QjsyQkFDekIsR0FBRyxDQUFDLEVBQUosQ0FBTyxPQUFQLEVBQWdCLEdBQUcsQ0FBQyxLQUFwQixFQUZKO2lCQUFBLE1BQUE7MkJBSUksT0FBTyxDQUFDLE9BQVIsQ0FBZ0IsR0FBaEIsRUFKSjs7WUFEYSxDQUFqQixFQUhKOztJQUhFOztJQWFOLE9BQUMsQ0FBQSxPQUFELEdBQVUsU0FBQyxHQUFEO0FBRU4sWUFBQTtRQUFBLE9BQUEsR0FBVSxHQUFHLENBQUM7UUFDZCxRQUFBLEdBQVcsS0FBSyxDQUFDLElBQU4sQ0FBVyxPQUFYLEVBQW9CLFVBQXBCLEVBQWdDLFlBQWhDO2VBQ1gsS0FBSyxDQUFDLFFBQU4sQ0FBZSxRQUFmLEVBQXlCLFNBQUMsR0FBRCxFQUFNLEdBQU47QUFDckIsZ0JBQUE7WUFBQSxJQUFPLFdBQVA7Z0JBQ0ksSUFBRywrQkFBSDtvQkFDSSxRQUFBLEdBQVcsS0FBSyxDQUFDLElBQU4sQ0FBVyxLQUFLLENBQUMsT0FBTixDQUFjLFFBQWQsQ0FBWCxFQUFvQyxXQUFwQyxFQUFpRCxHQUFJLENBQUEsa0JBQUEsQ0FBckQ7b0JBQ1gsSUFBdUIsQ0FBSSxRQUFRLENBQUMsUUFBVCxDQUFrQixPQUFsQixDQUEzQjt3QkFBQSxRQUFBLElBQVksUUFBWjs7MkJBQ0EsT0FBTyxDQUFDLFFBQVIsQ0FBaUIsUUFBakIsRUFBMkIsR0FBM0IsRUFISjtpQkFBQSxNQUFBOzJCQUtJLE9BQU8sQ0FBQyxVQUFSLENBQW1CLEdBQW5CLEVBTEo7aUJBREo7YUFBQSxNQUFBO2dCQVFHLE9BQUEsQ0FBQyxLQUFELENBQU8sV0FBQSxHQUFZLEdBQW5CO3VCQUNDLE9BQU8sQ0FBQyxVQUFSLENBQW1CLEdBQW5CLEVBVEo7O1FBRHFCLENBQXpCO0lBSk07O0lBZ0JWLE9BQUMsQ0FBQSxRQUFELEdBQVcsU0FBQyxRQUFELEVBQVcsR0FBWDtBQUVQLFlBQUE7UUFBQSxPQUFBLEdBQVUsT0FBTyxDQUFDLE9BQVIsQ0FBZ0IsR0FBaEI7ZUFDVixNQUFNLENBQUMsSUFBUCxDQUFZLG1CQUFBLEdBQW9CLEdBQUcsQ0FBQyxJQUF4QixHQUE2QixtQkFBN0IsR0FBZ0QsUUFBaEQsR0FBeUQsYUFBekQsR0FBc0UsT0FBdEUsR0FBOEUsSUFBMUYsRUFBK0YsU0FBQyxHQUFEO1lBQzNGLElBQU8sV0FBUDt1QkFDSSxHQUFHLENBQUMsRUFBSixDQUFPLE9BQVAsRUFBZ0IsR0FBRyxDQUFDLEtBQXBCLEVBREo7YUFBQSxNQUFBO2dCQUdHLE9BQUEsQ0FBQyxLQUFELENBQU8sWUFBQSxHQUFhLEdBQXBCO3VCQUNDLE9BQU8sQ0FBQyxVQUFSLENBQW1CLEdBQW5CLEVBSko7O1FBRDJGLENBQS9GO0lBSE87O0lBVVgsT0FBQyxDQUFBLFVBQUQsR0FBYSxTQUFDLEdBQUQ7QUFFVCxZQUFBO1FBQUEsVUFBQSxHQUFhLEtBQUssQ0FBQyxJQUFOLENBQVcsU0FBWCxFQUFzQixJQUF0QixFQUE0QixLQUE1QixFQUFtQyxZQUFuQztlQUNiLEdBQUcsQ0FBQyxFQUFKLENBQU8sVUFBUCxFQUFtQixHQUFHLENBQUMsS0FBdkI7SUFIUzs7Ozs7O0FBS2pCLE1BQU0sQ0FBQyxPQUFQLEdBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiIyMjXG4gMDAwMDAwMCAgIDAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAgICAwMDAwMDAwICAgMDAwMDAwMCAgIDAwMCAgIDAwMCAgXG4wMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMDAgIDAwMCAgXG4wMDAwMDAwMDAgIDAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAwIDAwMCAgXG4wMDAgICAwMDAgIDAwMCAgICAgICAgMDAwICAgICAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAgMDAwMCAgXG4wMDAgICAwMDAgIDAwMCAgICAgICAgMDAwICAgICAgICAwMDAgICAwMDAwMDAwICAgMDAwMDAwMCAgIDAwMCAgIDAwMCAgXG4jIyNcblxueyBjaGlsZHAsIGZzLCBzbGFzaCwgZXJyb3IsIGxvZyB9ID0gcmVxdWlyZSAna3hrJ1xuXG5wbGlzdCA9IHJlcXVpcmUgJ3NpbXBsZS1wbGlzdCdcblxuY2xhc3MgQXBwSWNvblxuICAgIFxuICAgIEBjYWNoZSA9IHt9XG4gICAgXG4gICAgQHBuZ1BhdGg6IChvcHQpIC0+XG4gICAgICAgIFxuICAgICAgICBzbGFzaC5yZXNvbHZlIHNsYXNoLmpvaW4gb3B0Lmljb25EaXIsIHNsYXNoLmJhc2Uob3B0LmFwcFBhdGgpICsgXCIucG5nXCJcblxuICAgIEBnZXQ6IChvcHQpIC0+XG4gICAgICAgIFxuICAgICAgICBwbmdQYXRoID0gQXBwSWNvbi5wbmdQYXRoIG9wdFxuICAgICAgICBpZiBBcHBJY29uLmNhY2hlW3BuZ1BhdGhdXG4gICAgICAgICAgICBvcHQuY2IgcG5nUGF0aCwgb3B0LmNiQXJnXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGZzLnN0YXQgcG5nUGF0aCwgKGVyciwgc3RhdCkgLT5cbiAgICAgICAgICAgICAgICBpZiBub3QgZXJyPyBhbmQgc3RhdC5pc0ZpbGUoKVxuICAgICAgICAgICAgICAgICAgICBBcHBJY29uLmNhY2hlW3BuZ1BhdGhdID0gdHJ1ZVxuICAgICAgICAgICAgICAgICAgICBvcHQuY2IgcG5nUGF0aCwgb3B0LmNiQXJnXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBBcHBJY29uLmdldEljb24gb3B0XG4gICAgICAgICBcbiAgICBAZ2V0SWNvbjogKG9wdCkgLT5cbiAgICAgICAgXG4gICAgICAgIGFwcFBhdGggPSBvcHQuYXBwUGF0aFxuICAgICAgICBpbmZvUGF0aCA9IHNsYXNoLmpvaW4gYXBwUGF0aCwgJ0NvbnRlbnRzJywgJ0luZm8ucGxpc3QnXG4gICAgICAgIHBsaXN0LnJlYWRGaWxlIGluZm9QYXRoLCAoZXJyLCBvYmopIC0+XG4gICAgICAgICAgICBpZiBub3QgZXJyP1xuICAgICAgICAgICAgICAgIGlmIG9ialsnQ0ZCdW5kbGVJY29uRmlsZSddP1xuICAgICAgICAgICAgICAgICAgICBpY25zUGF0aCA9IHNsYXNoLmpvaW4gc2xhc2guZGlybmFtZShpbmZvUGF0aCksICdSZXNvdXJjZXMnLCBvYmpbJ0NGQnVuZGxlSWNvbkZpbGUnXVxuICAgICAgICAgICAgICAgICAgICBpY25zUGF0aCArPSBcIi5pY25zXCIgaWYgbm90IGljbnNQYXRoLmVuZHNXaXRoICcuaWNucydcbiAgICAgICAgICAgICAgICAgICAgQXBwSWNvbi5zYXZlSWNvbiBpY25zUGF0aCwgb3B0XG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBBcHBJY29uLmJyb2tlbkljb24gb3B0XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgZXJyb3IgXCJnZXRJY29uOiAje2Vycn1cIlxuICAgICAgICAgICAgICAgIEFwcEljb24uYnJva2VuSWNvbiBvcHRcbiAgICAgICAgICAgICAgICBcbiAgICBAc2F2ZUljb246IChpY25zUGF0aCwgb3B0KSAtPlxuICAgICAgICBcbiAgICAgICAgcG5nUGF0aCA9IEFwcEljb24ucG5nUGF0aCBvcHRcbiAgICAgICAgY2hpbGRwLmV4ZWMgXCIvdXNyL2Jpbi9zaXBzIC1aICN7b3B0LnNpemV9IC1zIGZvcm1hdCBwbmcgXFxcIiN7aWNuc1BhdGh9XFxcIiAtLW91dCBcXFwiI3twbmdQYXRofVxcXCJcIiwgKGVycikgLT5cbiAgICAgICAgICAgIGlmIG5vdCBlcnI/XG4gICAgICAgICAgICAgICAgb3B0LmNiIHBuZ1BhdGgsIG9wdC5jYkFyZ1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIGVycm9yIFwic2F2ZUljb246ICN7ZXJyfVwiXG4gICAgICAgICAgICAgICAgQXBwSWNvbi5icm9rZW5JY29uIG9wdFxuICAgICBcbiAgICBAYnJva2VuSWNvbjogKG9wdCkgLT5cbiAgICAgICAgXG4gICAgICAgIGJyb2tlblBhdGggPSBzbGFzaC5qb2luIF9fZGlybmFtZSwgJy4uJywgJ2ltZycsICdicm9rZW4ucG5nJ1xuICAgICAgICBvcHQuY2IgYnJva2VuUGF0aCwgb3B0LmNiQXJnXG4gICAgICAgIFxubW9kdWxlLmV4cG9ydHMgPSBBcHBJY29uXG4iXX0= 91 | //# sourceURL=../coffee/appicon.coffee -------------------------------------------------------------------------------- /js/exefind.js: -------------------------------------------------------------------------------- 1 | // koffee 1.12.0 2 | 3 | /* 4 | 00000000 000 000 00000000 00000000 000 000 000 0000000 5 | 000 000 000 000 000 000 0000 000 000 000 6 | 0000000 00000 0000000 000000 000 000 0 000 000 000 7 | 000 000 000 000 000 000 000 0000 000 000 8 | 00000000 000 000 00000000 000 000 000 000 0000000 9 | */ 10 | var _, exeFind, klog, post, prefs, ref, slash, walkdir, 11 | indexOf = [].indexOf; 12 | 13 | ref = require('kxk'), post = ref.post, slash = ref.slash, walkdir = ref.walkdir, prefs = ref.prefs, klog = ref.klog, _ = ref._; 14 | 15 | exeFind = function(cb) { 16 | var appl, apps, dirs, exeFolder, foldersLeft, i, ignore, ignoreDefaults, ignoredByName, ignoredByPath, len, results, walk, walkOpt; 17 | appl = prefs.get('apps', []); 18 | apps = {}; 19 | appl.map(function(a) { 20 | return apps[slash.base(a)] = slash.resolve(a); 21 | }); 22 | apps['cmd'] = "C:/Windows/System32/cmd.exe"; 23 | apps['calc'] = "C:/Windows/System32/calc.exe"; 24 | apps['Taskmgr'] = "C:/Windows/System32/Taskmgr.exe"; 25 | apps['regedit'] = "C:/Windows/regedit.exe"; 26 | apps['explorer'] = "C:/Windows/explorer.exe"; 27 | dirs = _.clone(prefs.get('dirs', [])); 28 | dirs.push("C:/Program Files"); 29 | dirs.push("C:/Program Files (x86)"); 30 | dirs.push(slash.resolve('~/AppData/Local')); 31 | dirs.push(slash.resolve('~/')); 32 | ignoreDefaults = require('../bin/ignore'); 33 | ignoredByName = function(file) { 34 | var contains, i, j, k, len, len1, len2, match, ref1, ref2, ref3, start; 35 | file = file.toLowerCase(); 36 | ref1 = ignoreDefaults.startsWith; 37 | for (i = 0, len = ref1.length; i < len; i++) { 38 | start = ref1[i]; 39 | if (file.startsWith(start)) { 40 | return true; 41 | } 42 | } 43 | ref2 = ignoreDefaults.contains; 44 | for (j = 0, len1 = ref2.length; j < len1; j++) { 45 | contains = ref2[j]; 46 | if (file.indexOf(contains) >= 0) { 47 | return true; 48 | } 49 | } 50 | ref3 = ignoreDefaults.matches; 51 | for (k = 0, len2 = ref3.length; k < len2; k++) { 52 | match = ref3[k]; 53 | if (file === match) { 54 | return true; 55 | } 56 | } 57 | return false; 58 | }; 59 | ignoredByPath = function(file) { 60 | var i, len, path, ref1; 61 | ref1 = ignoreDefaults.path; 62 | for (i = 0, len = ref1.length; i < len; i++) { 63 | path = ref1[i]; 64 | if (file.indexOf(path) >= 0) { 65 | return true; 66 | } 67 | } 68 | return false; 69 | }; 70 | ignore = prefs.get('ignore', []); 71 | foldersLeft = dirs.length; 72 | results = []; 73 | for (i = 0, len = dirs.length; i < len; i++) { 74 | exeFolder = dirs[i]; 75 | walkOpt = prefs.get('walk', { 76 | no_recurse: false, 77 | max_depth: 4 78 | }); 79 | walk = walkdir(slash.resolve(exeFolder), walkOpt); 80 | walk.on('error', function(err) { 81 | post.toWins('mainlog', "walk error " + err.stack); 82 | return console.log("[ERROR] findExes -- " + err); 83 | }); 84 | walk.on('end', function() { 85 | foldersLeft -= 1; 86 | if (foldersLeft === 0) { 87 | return typeof cb === "function" ? cb(apps) : void 0; 88 | } 89 | }); 90 | results.push(walk.on('file', function(file) { 91 | var name; 92 | file = slash.resolve(file); 93 | if (slash.ext(file) === 'exe') { 94 | name = slash.base(file); 95 | if (indexOf.call(ignore, file) < 0 && !ignoredByName(name) && !ignoredByPath(file)) { 96 | if (apps[name] == null) { 97 | return apps[name] = file; 98 | } 99 | } 100 | } 101 | })); 102 | } 103 | return results; 104 | }; 105 | 106 | module.exports = exeFind; 107 | 108 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlZmluZC5qcyIsInNvdXJjZVJvb3QiOiIuLi9jb2ZmZWUiLCJzb3VyY2VzIjpbImV4ZWZpbmQuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7Ozs7Ozs7QUFBQSxJQUFBLGtEQUFBO0lBQUE7O0FBUUEsTUFBMkMsT0FBQSxDQUFRLEtBQVIsQ0FBM0MsRUFBRSxlQUFGLEVBQVEsaUJBQVIsRUFBZSxxQkFBZixFQUF3QixpQkFBeEIsRUFBK0IsZUFBL0IsRUFBcUM7O0FBRXJDLE9BQUEsR0FBVSxTQUFDLEVBQUQ7QUFFTixRQUFBO0lBQUEsSUFBQSxHQUFPLEtBQUssQ0FBQyxHQUFOLENBQVUsTUFBVixFQUFpQixFQUFqQjtJQUVQLElBQUEsR0FBTztJQUNQLElBQUksQ0FBQyxHQUFMLENBQVMsU0FBQyxDQUFEO2VBQU8sSUFBSyxDQUFBLEtBQUssQ0FBQyxJQUFOLENBQVcsQ0FBWCxDQUFBLENBQUwsR0FBcUIsS0FBSyxDQUFDLE9BQU4sQ0FBYyxDQUFkO0lBQTVCLENBQVQ7SUFFQSxJQUFLLENBQUEsS0FBQSxDQUFMLEdBQW1CO0lBQ25CLElBQUssQ0FBQSxNQUFBLENBQUwsR0FBbUI7SUFDbkIsSUFBSyxDQUFBLFNBQUEsQ0FBTCxHQUFtQjtJQUNuQixJQUFLLENBQUEsU0FBQSxDQUFMLEdBQW1CO0lBQ25CLElBQUssQ0FBQSxVQUFBLENBQUwsR0FBbUI7SUFFbkIsSUFBQSxHQUFPLENBQUMsQ0FBQyxLQUFGLENBQVEsS0FBSyxDQUFDLEdBQU4sQ0FBVSxNQUFWLEVBQWlCLEVBQWpCLENBQVI7SUFFUCxJQUFJLENBQUMsSUFBTCxDQUFVLGtCQUFWO0lBQ0EsSUFBSSxDQUFDLElBQUwsQ0FBVSx3QkFBVjtJQUNBLElBQUksQ0FBQyxJQUFMLENBQVUsS0FBSyxDQUFDLE9BQU4sQ0FBYyxpQkFBZCxDQUFWO0lBQ0EsSUFBSSxDQUFDLElBQUwsQ0FBVSxLQUFLLENBQUMsT0FBTixDQUFjLElBQWQsQ0FBVjtJQUVBLGNBQUEsR0FBaUIsT0FBQSxDQUFRLGVBQVI7SUFFakIsYUFBQSxHQUFnQixTQUFDLElBQUQ7QUFDWixZQUFBO1FBQUEsSUFBQSxHQUFPLElBQUksQ0FBQyxXQUFMLENBQUE7QUFDUDtBQUFBLGFBQUEsc0NBQUE7O1lBQ0ksSUFBZSxJQUFJLENBQUMsVUFBTCxDQUFnQixLQUFoQixDQUFmO0FBQUEsdUJBQU8sS0FBUDs7QUFESjtBQUVBO0FBQUEsYUFBQSx3Q0FBQTs7WUFDSSxJQUFlLElBQUksQ0FBQyxPQUFMLENBQWEsUUFBYixDQUFBLElBQTBCLENBQXpDO0FBQUEsdUJBQU8sS0FBUDs7QUFESjtBQUVBO0FBQUEsYUFBQSx3Q0FBQTs7WUFDSSxJQUFlLElBQUEsS0FBUSxLQUF2QjtBQUFBLHVCQUFPLEtBQVA7O0FBREo7ZUFFQTtJQVJZO0lBVWhCLGFBQUEsR0FBZ0IsU0FBQyxJQUFEO0FBQ1osWUFBQTtBQUFBO0FBQUEsYUFBQSxzQ0FBQTs7WUFDSSxJQUFlLElBQUksQ0FBQyxPQUFMLENBQWEsSUFBYixDQUFBLElBQXNCLENBQXJDO0FBQUEsdUJBQU8sS0FBUDs7QUFESjtlQUVBO0lBSFk7SUFLaEIsTUFBQSxHQUFTLEtBQUssQ0FBQyxHQUFOLENBQVUsUUFBVixFQUFtQixFQUFuQjtJQUNULFdBQUEsR0FBYyxJQUFJLENBQUM7QUFFbkI7U0FBQSxzQ0FBQTs7UUFFSSxPQUFBLEdBQVUsS0FBSyxDQUFDLEdBQU4sQ0FBVSxNQUFWLEVBQWlCO1lBQUEsVUFBQSxFQUFZLEtBQVo7WUFBa0IsU0FBQSxFQUFXLENBQTdCO1NBQWpCO1FBQ1YsSUFBQSxHQUFPLE9BQUEsQ0FBUSxLQUFLLENBQUMsT0FBTixDQUFjLFNBQWQsQ0FBUixFQUFrQyxPQUFsQztRQUVQLElBQUksQ0FBQyxFQUFMLENBQVEsT0FBUixFQUFnQixTQUFDLEdBQUQ7WUFDWixJQUFJLENBQUMsTUFBTCxDQUFZLFNBQVosRUFBc0IsYUFBQSxHQUFjLEdBQUcsQ0FBQyxLQUF4QzttQkFBK0MsT0FBQSxDQUMvQyxHQUQrQyxDQUMzQyxzQkFBQSxHQUF1QixHQURvQjtRQURuQyxDQUFoQjtRQUlBLElBQUksQ0FBQyxFQUFMLENBQVEsS0FBUixFQUFjLFNBQUE7WUFFVixXQUFBLElBQWU7WUFDZixJQUFHLFdBQUEsS0FBZSxDQUFsQjtrREFHSSxHQUFJLGVBSFI7O1FBSFUsQ0FBZDtxQkFRQSxJQUFJLENBQUMsRUFBTCxDQUFRLE1BQVIsRUFBZSxTQUFDLElBQUQ7QUFFWCxnQkFBQTtZQUFBLElBQUEsR0FBTyxLQUFLLENBQUMsT0FBTixDQUFjLElBQWQ7WUFDUCxJQUFHLEtBQUssQ0FBQyxHQUFOLENBQVUsSUFBVixDQUFBLEtBQW1CLEtBQXRCO2dCQUNJLElBQUEsR0FBTyxLQUFLLENBQUMsSUFBTixDQUFXLElBQVg7Z0JBQ1AsSUFBRyxhQUFZLE1BQVosRUFBQSxJQUFBLEtBQUEsSUFBdUIsQ0FBSSxhQUFBLENBQWMsSUFBZCxDQUEzQixJQUFtRCxDQUFJLGFBQUEsQ0FBYyxJQUFkLENBQTFEO29CQUNJLElBQU8sa0JBQVA7K0JBQ0ksSUFBSyxDQUFBLElBQUEsQ0FBTCxHQUFhLEtBRGpCO3FCQURKO2lCQUZKOztRQUhXLENBQWY7QUFqQko7O0FBeENNOztBQWtFVixNQUFNLENBQUMsT0FBUCxHQUFpQiIsInNvdXJjZXNDb250ZW50IjpbIiMjI1xuMDAwMDAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMDAgICAgICAgIDAwMDAwMDAwICAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMFxuMDAwICAgICAgICAwMDAgMDAwICAgMDAwICAgICAgICAgICAgIDAwMCAgICAgICAwMDAgIDAwMDAgIDAwMCAgMDAwICAgMDAwXG4wMDAwMDAwICAgICAwMDAwMCAgICAwMDAwMDAwICAgICAgICAgMDAwMDAwICAgIDAwMCAgMDAwIDAgMDAwICAwMDAgICAwMDBcbjAwMCAgICAgICAgMDAwIDAwMCAgIDAwMCAgICAgICAgICAgICAwMDAgICAgICAgMDAwICAwMDAgIDAwMDAgIDAwMCAgIDAwMFxuMDAwMDAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMDAgICAgICAgIDAwMCAgICAgICAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMFxuIyMjXG5cbnsgcG9zdCwgc2xhc2gsIHdhbGtkaXIsIHByZWZzLCBrbG9nLCBfIH0gPSByZXF1aXJlICdreGsnXG5cbmV4ZUZpbmQgPSAoY2IpIC0+XG5cbiAgICBhcHBsID0gcHJlZnMuZ2V0ICdhcHBzJyBbXVxuICAgIFxuICAgIGFwcHMgPSB7fVxuICAgIGFwcGwubWFwIChhKSAtPiBhcHBzW3NsYXNoLmJhc2UgYV0gPSBzbGFzaC5yZXNvbHZlIGFcbiAgICBcbiAgICBhcHBzWydjbWQnXSAgICAgID0gXCJDOi9XaW5kb3dzL1N5c3RlbTMyL2NtZC5leGVcIlxuICAgIGFwcHNbJ2NhbGMnXSAgICAgPSBcIkM6L1dpbmRvd3MvU3lzdGVtMzIvY2FsYy5leGVcIlxuICAgIGFwcHNbJ1Rhc2ttZ3InXSAgPSBcIkM6L1dpbmRvd3MvU3lzdGVtMzIvVGFza21nci5leGVcIlxuICAgIGFwcHNbJ3JlZ2VkaXQnXSAgPSBcIkM6L1dpbmRvd3MvcmVnZWRpdC5leGVcIlxuICAgIGFwcHNbJ2V4cGxvcmVyJ10gPSBcIkM6L1dpbmRvd3MvZXhwbG9yZXIuZXhlXCJcblxuICAgIGRpcnMgPSBfLmNsb25lIHByZWZzLmdldCAnZGlycycgW11cbiAgICBcbiAgICBkaXJzLnB1c2ggXCJDOi9Qcm9ncmFtIEZpbGVzXCJcbiAgICBkaXJzLnB1c2ggXCJDOi9Qcm9ncmFtIEZpbGVzICh4ODYpXCJcbiAgICBkaXJzLnB1c2ggc2xhc2gucmVzb2x2ZSAnfi9BcHBEYXRhL0xvY2FsJ1xuICAgIGRpcnMucHVzaCBzbGFzaC5yZXNvbHZlICd+LydcblxuICAgIGlnbm9yZURlZmF1bHRzID0gcmVxdWlyZSAnLi4vYmluL2lnbm9yZSdcblxuICAgIGlnbm9yZWRCeU5hbWUgPSAoZmlsZSkgLT5cbiAgICAgICAgZmlsZSA9IGZpbGUudG9Mb3dlckNhc2UoKVxuICAgICAgICBmb3Igc3RhcnQgaW4gaWdub3JlRGVmYXVsdHMuc3RhcnRzV2l0aFxuICAgICAgICAgICAgcmV0dXJuIHRydWUgaWYgZmlsZS5zdGFydHNXaXRoIHN0YXJ0XG4gICAgICAgIGZvciBjb250YWlucyBpbiBpZ25vcmVEZWZhdWx0cy5jb250YWluc1xuICAgICAgICAgICAgcmV0dXJuIHRydWUgaWYgZmlsZS5pbmRleE9mKGNvbnRhaW5zKSA+PSAwXG4gICAgICAgIGZvciBtYXRjaCBpbiBpZ25vcmVEZWZhdWx0cy5tYXRjaGVzXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZSBpZiBmaWxlID09IG1hdGNoXG4gICAgICAgIGZhbHNlXG4gICAgICAgIFxuICAgIGlnbm9yZWRCeVBhdGggPSAoZmlsZSkgLT5cbiAgICAgICAgZm9yIHBhdGggaW4gaWdub3JlRGVmYXVsdHMucGF0aFxuICAgICAgICAgICAgcmV0dXJuIHRydWUgaWYgZmlsZS5pbmRleE9mKHBhdGgpID49IDBcbiAgICAgICAgZmFsc2VcbiAgICAgICAgICAgIFxuICAgIGlnbm9yZSA9IHByZWZzLmdldCAnaWdub3JlJyBbXVxuICAgIGZvbGRlcnNMZWZ0ID0gZGlycy5sZW5ndGhcblxuICAgIGZvciBleGVGb2xkZXIgaW4gZGlyc1xuICAgICAgICBcbiAgICAgICAgd2Fsa09wdCA9IHByZWZzLmdldCAnd2Fsaycgbm9fcmVjdXJzZTogZmFsc2UgbWF4X2RlcHRoOiA0XG4gICAgICAgIHdhbGsgPSB3YWxrZGlyIHNsYXNoLnJlc29sdmUoZXhlRm9sZGVyKSwgd2Fsa09wdFxuXG4gICAgICAgIHdhbGsub24gJ2Vycm9yJyAoZXJyKSAtPiBcbiAgICAgICAgICAgIHBvc3QudG9XaW5zICdtYWlubG9nJyBcIndhbGsgZXJyb3IgI3tlcnIuc3RhY2t9XCJcbiAgICAgICAgICAgIGxvZyBcIltFUlJPUl0gZmluZEV4ZXMgLS0gI3tlcnJ9XCJcblxuICAgICAgICB3YWxrLm9uICdlbmQnIC0+XG5cbiAgICAgICAgICAgIGZvbGRlcnNMZWZ0IC09IDFcbiAgICAgICAgICAgIGlmIGZvbGRlcnNMZWZ0ID09IDBcbiAgICAgICAgICAgICAgICAjIHBvc3QudG9XaW5zICdtYWlubG9nJyBcImFwcHMgI3thcHBzfVwiXG4gICAgICAgICAgICAgICAgIyBrbG9nICdhcHBzJyBhcHBzXG4gICAgICAgICAgICAgICAgY2I/IGFwcHNcblxuICAgICAgICB3YWxrLm9uICdmaWxlJyAoZmlsZSkgLT5cblxuICAgICAgICAgICAgZmlsZSA9IHNsYXNoLnJlc29sdmUgZmlsZVxuICAgICAgICAgICAgaWYgc2xhc2guZXh0KGZpbGUpID09ICdleGUnXG4gICAgICAgICAgICAgICAgbmFtZSA9IHNsYXNoLmJhc2UgZmlsZVxuICAgICAgICAgICAgICAgIGlmIGZpbGUgbm90IGluIGlnbm9yZSBhbmQgbm90IGlnbm9yZWRCeU5hbWUobmFtZSkgYW5kIG5vdCBpZ25vcmVkQnlQYXRoKGZpbGUpXG4gICAgICAgICAgICAgICAgICAgIGlmIG5vdCBhcHBzW25hbWVdP1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwc1tuYW1lXSA9IGZpbGVcblxubW9kdWxlLmV4cG9ydHMgPSBleGVGaW5kXG4iXX0= 109 | //# sourceURL=../coffee/exefind.coffee -------------------------------------------------------------------------------- /js/exeicon.js: -------------------------------------------------------------------------------- 1 | // koffee 1.3.0 2 | 3 | /* 4 | 0000000 000 000 00000000 000 0000000 0000000 000 000 5 | 00 000 000 000 000 000 000 000 0000 000 6 | 000000 00000 0000000 000 000 000 000 000 0 000 7 | 00 000 000 000 000 000 000 000 000 0000 8 | 0000000 000 000 00000000 000 0000000 0000000 000 000 9 | */ 10 | var ExeIcon, childp, empty, fs, kerror, klog, ref, slash; 11 | 12 | ref = require('kxk'), slash = ref.slash, empty = ref.empty, fs = ref.fs, childp = ref.childp, kerror = ref.kerror, klog = ref.klog; 13 | 14 | ExeIcon = (function() { 15 | function ExeIcon() {} 16 | 17 | ExeIcon.cache = {}; 18 | 19 | ExeIcon.pngPath = function(opt) { 20 | return slash.resolve(slash.join(opt.iconDir, slash.base(opt.appPath) + ".png")); 21 | }; 22 | 23 | ExeIcon.get = function(opt) { 24 | var pngPath; 25 | pngPath = ExeIcon.pngPath(opt); 26 | if (ExeIcon.cache[pngPath]) { 27 | return opt.cb(pngPath, opt.cbArg); 28 | } else { 29 | return fs.stat(pngPath, function(err, stat) { 30 | if ((err == null) && stat.isFile()) { 31 | ExeIcon.cache[pngPath] = true; 32 | return opt.cb(pngPath, opt.cbArg); 33 | } else { 34 | return ExeIcon.getIcon(opt); 35 | } 36 | }); 37 | } 38 | }; 39 | 40 | ExeIcon.getIcon = function(opt) { 41 | var any2Ico, appPath, pngPath, wxw; 42 | appPath = slash.resolve(opt.appPath); 43 | pngPath = ExeIcon.pngPath(opt); 44 | klog('getIcon', appPath, pngPath); 45 | any2Ico = slash.path(__dirname + '/../bin/Quick_Any2Ico.exe'); 46 | if (false) { 47 | return childp.exec("\"" + any2Ico + "\" -formats=512 -res=\"" + appPath + "\" -icon=\"" + pngPath + "\"", opt, function(err, stdout, stderr) { 48 | if (!err) { 49 | return opt.cb(pngPath, opt.cbArg); 50 | } else { 51 | if (slash.ext(appPath) !== 'lnk') { 52 | kerror(stdout, stderr, err); 53 | } 54 | return ExeIcon.brokenIcon(opt); 55 | } 56 | }); 57 | } else { 58 | wxw = require('wxw'); 59 | wxw('icon', appPath, pngPath); 60 | return opt.cb(pngPath, opt.cbArg); 61 | } 62 | }; 63 | 64 | ExeIcon.saveIconData = function(data, opt) { 65 | var pngPath; 66 | pngPath = ExeIcon.pngPath(opt); 67 | return fs.writeFile(pngPath, data, function(err) { 68 | if (err == null) { 69 | return opt.cb(pngPath, opt.cbArg); 70 | } else { 71 | kerror("saveIconData: " + err); 72 | return ExeIcon.brokenIcon(opt); 73 | } 74 | }); 75 | }; 76 | 77 | ExeIcon.saveIconBase64 = function(data, opt) { 78 | var pngPath; 79 | pngPath = ExeIcon.pngPath(opt); 80 | return fs.writeFile(pngPath, data, { 81 | encoding: 'base64' 82 | }, function(err) { 83 | if (err == null) { 84 | return opt.cb(pngPath, opt.cbArg); 85 | } else { 86 | kerror("saveIconBase64: " + err); 87 | return ExeIcon.brokenIcon(opt); 88 | } 89 | }); 90 | }; 91 | 92 | ExeIcon.brokenIcon = function(opt) { 93 | var brokenPath; 94 | brokenPath = slash.join(__dirname, '..', 'img', 'broken.png'); 95 | return opt.cb(brokenPath, opt.cbArg); 96 | }; 97 | 98 | return ExeIcon; 99 | 100 | })(); 101 | 102 | module.exports = ExeIcon; 103 | 104 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlaWNvbi5qcyIsInNvdXJjZVJvb3QiOiIuIiwic291cmNlcyI6WyIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7OztBQUFBLElBQUE7O0FBUUEsTUFBNkMsT0FBQSxDQUFRLEtBQVIsQ0FBN0MsRUFBRSxpQkFBRixFQUFTLGlCQUFULEVBQWdCLFdBQWhCLEVBQW9CLG1CQUFwQixFQUE0QixtQkFBNUIsRUFBb0M7O0FBRTlCOzs7SUFFRixPQUFDLENBQUEsS0FBRCxHQUFTOztJQUVULE9BQUMsQ0FBQSxPQUFELEdBQVUsU0FBQyxHQUFEO2VBRU4sS0FBSyxDQUFDLE9BQU4sQ0FBYyxLQUFLLENBQUMsSUFBTixDQUFXLEdBQUcsQ0FBQyxPQUFmLEVBQXdCLEtBQUssQ0FBQyxJQUFOLENBQVcsR0FBRyxDQUFDLE9BQWYsQ0FBQSxHQUEwQixNQUFsRCxDQUFkO0lBRk07O0lBSVYsT0FBQyxDQUFBLEdBQUQsR0FBTSxTQUFDLEdBQUQ7QUFFRixZQUFBO1FBQUEsT0FBQSxHQUFVLE9BQU8sQ0FBQyxPQUFSLENBQWdCLEdBQWhCO1FBQ1YsSUFBRyxPQUFPLENBQUMsS0FBTSxDQUFBLE9BQUEsQ0FBakI7bUJBQ0ksR0FBRyxDQUFDLEVBQUosQ0FBTyxPQUFQLEVBQWdCLEdBQUcsQ0FBQyxLQUFwQixFQURKO1NBQUEsTUFBQTttQkFHSSxFQUFFLENBQUMsSUFBSCxDQUFRLE9BQVIsRUFBaUIsU0FBQyxHQUFELEVBQU0sSUFBTjtnQkFDYixJQUFPLGFBQUosSUFBYSxJQUFJLENBQUMsTUFBTCxDQUFBLENBQWhCO29CQUNJLE9BQU8sQ0FBQyxLQUFNLENBQUEsT0FBQSxDQUFkLEdBQXlCOzJCQUN6QixHQUFHLENBQUMsRUFBSixDQUFPLE9BQVAsRUFBZ0IsR0FBRyxDQUFDLEtBQXBCLEVBRko7aUJBQUEsTUFBQTsyQkFJSSxPQUFPLENBQUMsT0FBUixDQUFnQixHQUFoQixFQUpKOztZQURhLENBQWpCLEVBSEo7O0lBSEU7O0lBYU4sT0FBQyxDQUFBLE9BQUQsR0FBVSxTQUFDLEdBQUQ7QUFFTixZQUFBO1FBQUEsT0FBQSxHQUFVLEtBQUssQ0FBQyxPQUFOLENBQWMsR0FBRyxDQUFDLE9BQWxCO1FBQ1YsT0FBQSxHQUFVLE9BQU8sQ0FBQyxPQUFSLENBQWdCLEdBQWhCO1FBRVYsSUFBQSxDQUFLLFNBQUwsRUFBZ0IsT0FBaEIsRUFBeUIsT0FBekI7UUFFQSxPQUFBLEdBQVUsS0FBSyxDQUFDLElBQU4sQ0FBVyxTQUFBLEdBQVksMkJBQXZCO1FBRVYsSUFBRyxLQUFIO21CQUVJLE1BQU0sQ0FBQyxJQUFQLENBQVksSUFBQSxHQUFLLE9BQUwsR0FBYSx5QkFBYixHQUFzQyxPQUF0QyxHQUE4QyxhQUE5QyxHQUEyRCxPQUEzRCxHQUFtRSxJQUEvRSxFQUFvRixHQUFwRixFQUF5RixTQUFDLEdBQUQsRUFBSyxNQUFMLEVBQVksTUFBWjtnQkFDckYsSUFBRyxDQUFJLEdBQVA7MkJBRUksR0FBRyxDQUFDLEVBQUosQ0FBTyxPQUFQLEVBQWdCLEdBQUcsQ0FBQyxLQUFwQixFQUZKO2lCQUFBLE1BQUE7b0JBSUksSUFBRyxLQUFLLENBQUMsR0FBTixDQUFVLE9BQVYsQ0FBQSxLQUFxQixLQUF4Qjt3QkFDSSxNQUFBLENBQU8sTUFBUCxFQUFlLE1BQWYsRUFBdUIsR0FBdkIsRUFESjs7MkJBRUEsT0FBTyxDQUFDLFVBQVIsQ0FBbUIsR0FBbkIsRUFOSjs7WUFEcUYsQ0FBekYsRUFGSjtTQUFBLE1BQUE7WUFZSSxHQUFBLEdBQU0sT0FBQSxDQUFRLEtBQVI7WUFDTixHQUFBLENBQUksTUFBSixFQUFXLE9BQVgsRUFBb0IsT0FBcEI7bUJBQ0EsR0FBRyxDQUFDLEVBQUosQ0FBTyxPQUFQLEVBQWdCLEdBQUcsQ0FBQyxLQUFwQixFQWRKOztJQVRNOztJQXlCVixPQUFDLENBQUEsWUFBRCxHQUFlLFNBQUMsSUFBRCxFQUFPLEdBQVA7QUFFWCxZQUFBO1FBQUEsT0FBQSxHQUFVLE9BQU8sQ0FBQyxPQUFSLENBQWdCLEdBQWhCO2VBQ1YsRUFBRSxDQUFDLFNBQUgsQ0FBYSxPQUFiLEVBQXNCLElBQXRCLEVBQTRCLFNBQUMsR0FBRDtZQUN4QixJQUFPLFdBQVA7dUJBQ0ksR0FBRyxDQUFDLEVBQUosQ0FBTyxPQUFQLEVBQWdCLEdBQUcsQ0FBQyxLQUFwQixFQURKO2FBQUEsTUFBQTtnQkFHSSxNQUFBLENBQU8sZ0JBQUEsR0FBaUIsR0FBeEI7dUJBQ0EsT0FBTyxDQUFDLFVBQVIsQ0FBbUIsR0FBbkIsRUFKSjs7UUFEd0IsQ0FBNUI7SUFIVzs7SUFVZixPQUFDLENBQUEsY0FBRCxHQUFpQixTQUFDLElBQUQsRUFBTyxHQUFQO0FBRWIsWUFBQTtRQUFBLE9BQUEsR0FBVSxPQUFPLENBQUMsT0FBUixDQUFnQixHQUFoQjtlQUNWLEVBQUUsQ0FBQyxTQUFILENBQWEsT0FBYixFQUFzQixJQUF0QixFQUE0QjtZQUFDLFFBQUEsRUFBVSxRQUFYO1NBQTVCLEVBQWtELFNBQUMsR0FBRDtZQUM5QyxJQUFPLFdBQVA7dUJBQ0ksR0FBRyxDQUFDLEVBQUosQ0FBTyxPQUFQLEVBQWdCLEdBQUcsQ0FBQyxLQUFwQixFQURKO2FBQUEsTUFBQTtnQkFHSSxNQUFBLENBQU8sa0JBQUEsR0FBbUIsR0FBMUI7dUJBQ0EsT0FBTyxDQUFDLFVBQVIsQ0FBbUIsR0FBbkIsRUFKSjs7UUFEOEMsQ0FBbEQ7SUFIYTs7SUFVakIsT0FBQyxDQUFBLFVBQUQsR0FBYSxTQUFDLEdBQUQ7QUFFVCxZQUFBO1FBQUEsVUFBQSxHQUFhLEtBQUssQ0FBQyxJQUFOLENBQVcsU0FBWCxFQUFzQixJQUF0QixFQUE0QixLQUE1QixFQUFtQyxZQUFuQztlQUNiLEdBQUcsQ0FBQyxFQUFKLENBQU8sVUFBUCxFQUFtQixHQUFHLENBQUMsS0FBdkI7SUFIUzs7Ozs7O0FBS2pCLE1BQU0sQ0FBQyxPQUFQLEdBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiIyMjXG4wMDAwMDAwICAwMDAgICAwMDAgIDAwMDAwMDAwICAwMDAgICAwMDAwMDAwICAgMDAwMDAwMCAgIDAwMCAgIDAwMCAgXG4wMCAgICAgICAgMDAwIDAwMCAgIDAwMCAgICAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMDAgIDAwMCAgXG4wMDAwMDAgICAgIDAwMDAwICAgIDAwMDAwMDAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAwIDAwMCAgXG4wMCAgICAgICAgMDAwIDAwMCAgIDAwMCAgICAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAgMDAwMCAgXG4wMDAwMDAwICAwMDAgICAwMDAgIDAwMDAwMDAwICAwMDAgICAwMDAwMDAwICAgMDAwMDAwMCAgIDAwMCAgIDAwMCAgXG4jIyNcblxueyBzbGFzaCwgZW1wdHksIGZzLCBjaGlsZHAsIGtlcnJvciwga2xvZyB9ID0gcmVxdWlyZSAna3hrJ1xuICAgIFxuY2xhc3MgRXhlSWNvblxuICAgIFxuICAgIEBjYWNoZSA9IHt9XG4gICAgXG4gICAgQHBuZ1BhdGg6IChvcHQpIC0+XG4gICAgICAgIFxuICAgICAgICBzbGFzaC5yZXNvbHZlIHNsYXNoLmpvaW4gb3B0Lmljb25EaXIsIHNsYXNoLmJhc2Uob3B0LmFwcFBhdGgpICsgXCIucG5nXCJcblxuICAgIEBnZXQ6IChvcHQpIC0+XG4gICAgICAgIFxuICAgICAgICBwbmdQYXRoID0gRXhlSWNvbi5wbmdQYXRoIG9wdFxuICAgICAgICBpZiBFeGVJY29uLmNhY2hlW3BuZ1BhdGhdXG4gICAgICAgICAgICBvcHQuY2IgcG5nUGF0aCwgb3B0LmNiQXJnXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGZzLnN0YXQgcG5nUGF0aCwgKGVyciwgc3RhdCkgLT5cbiAgICAgICAgICAgICAgICBpZiBub3QgZXJyPyBhbmQgc3RhdC5pc0ZpbGUoKVxuICAgICAgICAgICAgICAgICAgICBFeGVJY29uLmNhY2hlW3BuZ1BhdGhdID0gdHJ1ZVxuICAgICAgICAgICAgICAgICAgICBvcHQuY2IgcG5nUGF0aCwgb3B0LmNiQXJnXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBFeGVJY29uLmdldEljb24gb3B0XG4gICAgICAgICAgICAgICAgICAgIFxuICAgIEBnZXRJY29uOiAob3B0KSAtPlxuICAgICAgICBcbiAgICAgICAgYXBwUGF0aCA9IHNsYXNoLnJlc29sdmUgb3B0LmFwcFBhdGhcbiAgICAgICAgcG5nUGF0aCA9IEV4ZUljb24ucG5nUGF0aCBvcHRcbiAgICAgICAgXG4gICAgICAgIGtsb2cgJ2dldEljb24nLCBhcHBQYXRoLCBwbmdQYXRoXG4gICAgICAgIFxuICAgICAgICBhbnkySWNvID0gc2xhc2gucGF0aCBfX2Rpcm5hbWUgKyAnLy4uL2Jpbi9RdWlja19BbnkySWNvLmV4ZSdcbiAgICAgICAgXG4gICAgICAgIGlmIGZhbHNlICNzbGFzaC5pc0ZpbGUgYW55Mkljb1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBjaGlsZHAuZXhlYyBcIlxcXCIje2FueTJJY299XFxcIiAtZm9ybWF0cz01MTIgLXJlcz1cXFwiI3thcHBQYXRofVxcXCIgLWljb249XFxcIiN7cG5nUGF0aH1cXFwiXCIsIG9wdCwgKGVycixzdGRvdXQsc3RkZXJyKSAtPiBcbiAgICAgICAgICAgICAgICBpZiBub3QgZXJyIFxuICAgICAgICAgICAgICAgICAgICAjIGxvZyBzdGRvdXRcbiAgICAgICAgICAgICAgICAgICAgb3B0LmNiIHBuZ1BhdGgsIG9wdC5jYkFyZ1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgaWYgc2xhc2guZXh0KGFwcFBhdGgpIT0gJ2xuaydcbiAgICAgICAgICAgICAgICAgICAgICAgIGtlcnJvciBzdGRvdXQsIHN0ZGVyciwgZXJyXG4gICAgICAgICAgICAgICAgICAgIEV4ZUljb24uYnJva2VuSWNvbiBvcHRcblxuICAgICAgICBlbHNlXG4gICAgICAgICAgICB3eHcgPSByZXF1aXJlICd3eHcnXG4gICAgICAgICAgICB3eHcgJ2ljb24nIGFwcFBhdGgsIHBuZ1BhdGhcbiAgICAgICAgICAgIG9wdC5jYiBwbmdQYXRoLCBvcHQuY2JBcmdcbiAgICAgICAgICAgICAgICBcbiAgICBAc2F2ZUljb25EYXRhOiAoZGF0YSwgb3B0KSAtPlxuICAgICAgICBcbiAgICAgICAgcG5nUGF0aCA9IEV4ZUljb24ucG5nUGF0aCBvcHRcbiAgICAgICAgZnMud3JpdGVGaWxlIHBuZ1BhdGgsIGRhdGEsIChlcnIpIC0+XG4gICAgICAgICAgICBpZiBub3QgZXJyP1xuICAgICAgICAgICAgICAgIG9wdC5jYiBwbmdQYXRoLCBvcHQuY2JBcmdcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBrZXJyb3IgXCJzYXZlSWNvbkRhdGE6ICN7ZXJyfVwiXG4gICAgICAgICAgICAgICAgRXhlSWNvbi5icm9rZW5JY29uIG9wdFxuXG4gICAgQHNhdmVJY29uQmFzZTY0OiAoZGF0YSwgb3B0KSAtPlxuICAgICAgICBcbiAgICAgICAgcG5nUGF0aCA9IEV4ZUljb24ucG5nUGF0aCBvcHRcbiAgICAgICAgZnMud3JpdGVGaWxlIHBuZ1BhdGgsIGRhdGEsIHtlbmNvZGluZzogJ2Jhc2U2NCd9LCAoZXJyKSAtPlxuICAgICAgICAgICAgaWYgbm90IGVycj9cbiAgICAgICAgICAgICAgICBvcHQuY2IgcG5nUGF0aCwgb3B0LmNiQXJnXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAga2Vycm9yIFwic2F2ZUljb25CYXNlNjQ6ICN7ZXJyfVwiXG4gICAgICAgICAgICAgICAgRXhlSWNvbi5icm9rZW5JY29uIG9wdFxuICAgICAgICAgICAgICAgIFxuICAgIEBicm9rZW5JY29uOiAob3B0KSAtPlxuICAgICAgICBcbiAgICAgICAgYnJva2VuUGF0aCA9IHNsYXNoLmpvaW4gX19kaXJuYW1lLCAnLi4nLCAnaW1nJywgJ2Jyb2tlbi5wbmcnXG4gICAgICAgIG9wdC5jYiBicm9rZW5QYXRoLCBvcHQuY2JBcmdcbiAgICAgICAgXG5tb2R1bGUuZXhwb3J0cyA9IEV4ZUljb25cbiJdfQ== 105 | //# sourceURL=../coffee/exeicon.coffee -------------------------------------------------------------------------------- /coffee/main.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | 00 00 0000000 000 000 000 3 | 000 000 000 000 000 0000 000 4 | 000000000 000000000 000 000 0 000 5 | 000 0 000 000 000 000 000 0000 6 | 000 000 000 000 000 000 000 7 | ### 8 | 9 | { about, app, args, childp, fs, klog, os, osascript, post, prefs, slash, srcmap, valid, win } = require 'kxk' 10 | 11 | pkg = require '../package.json' 12 | electron = require 'electron' 13 | 14 | app = electron.app 15 | BrowserWindow = electron.BrowserWindow 16 | Tray = electron.Tray 17 | Menu = electron.Menu 18 | clipboard = electron.clipboard 19 | iconDir = slash.resolve "#{app.getPath('userData')}/icons" 20 | 21 | win = null 22 | tray = null 23 | 24 | apps = {} 25 | scripts = {} 26 | allKeys = [] 27 | 28 | process.on 'uncaughtException' (err) -> 29 | srcmap.logErr err, '🔻' 30 | true 31 | 32 | klog.slog.icon = slash.fileUrl slash.resolve slash.join __dirname, '..' 'img' 'menu@2x.png' 33 | 34 | app.setName pkg.productName 35 | 36 | args = args.init """ 37 | verbose log verbose false 38 | debug log debug false -D 39 | """ 40 | 41 | # 00000000 0000000 0000000 000000000 42 | # 000 000 000 000 000 000 43 | # 00000000 000 000 0000000 000 44 | # 000 000 000 000 000 45 | # 000 0000000 0000000 000 46 | 47 | post.on 'winlog' (text) -> log ">>> " + text 48 | post.on 'runScript' (name) -> scripts[name].cb() 49 | post.on 'hideWin' -> win?.hide() 50 | post.on 'cancel' -> activateApp() 51 | post.on 'about' -> showAbout() 52 | post.on 'findApps' -> findApps() 53 | post.on 'devTools' -> win?.webContents.openDevTools mode:'detach' 54 | post.onGet 'apps' -> apps: apps, scripts:scripts, allKeys:allKeys 55 | 56 | electron.ipcMain.on 'getWinBounds' (e) -> e.returnValue = win?.getBounds() 57 | electron.ipcMain.on 'getScreenSize' (e) -> e.returnValue = electron.screen.getPrimaryDisplay().workAreaSize 58 | electron.ipcMain.on 'setWinBounds' (e,b) -> 59 | klog 'setWinBounds' win?, b 60 | win?.setBounds b 61 | 62 | # 00000000 000 000 000 0000000 0000000 00000000 00000000 0000000 63 | # 000 000 0000 000 000 000 000 000 000 000 000 000 000 64 | # 000000 000 000 0 000 000 000 000000000 00000000 00000000 0000000 65 | # 000 000 000 0000 000 000 000 000 000 000 000 66 | # 000 000 000 000 0000000 000 000 000 000 0000000 67 | 68 | findApps = -> 69 | 70 | sortKeys = -> 71 | 72 | allKeys = Object.keys(apps).concat Object.keys(scripts) 73 | allKeys.sort (a,b) -> a.toLowerCase().localeCompare b.toLowerCase() 74 | 75 | if win 76 | post.toWins 'appsFound' 77 | else 78 | createWindow() 79 | hideWin = -> win?.hide() 80 | if not args.debug 81 | setTimeout hideWin, 1000 82 | 83 | if slash.win() 84 | exeFind = require './exefind' 85 | exeFind (exes) -> 86 | if valid exes 87 | apps = exes 88 | sortKeys() 89 | else 90 | appFind = require './appfind' 91 | appFind (appl) -> 92 | apps = appl 93 | sortKeys() 94 | 95 | # 0000000 0000000 000000000 000 000 000 00000000 96 | #000 000 000 000 000 000 000 000 97 | #000000000 000 000 000 000 000 0000000 98 | #000 000 000 000 000 000 000 99 | #000 000 0000000 000 000 0 00000000 100 | 101 | appName = null 102 | activeApp = null 103 | activeWin = null 104 | 105 | getActiveApp = -> 106 | 107 | if slash.win() 108 | wxw = require 'wxw' 109 | top = wxw('info' 'top')[0] 110 | if top?.path? 111 | appName = activeApp = slash.base top.path 112 | else 113 | activeApp = childp.execSync "#{__dirname}/../bin/appswitch -P" encoding:'utf8' 114 | 115 | klog 'getActiveApp appName' appName, '-> activeApp' activeApp #? if args.verbose 116 | 117 | if win? 118 | if appName? 119 | klog 'getActiveApp post.currentApp' appName #if args.verbose 120 | post.toWins 'currentApp' appName 121 | else 122 | klog 'getActiveApp clearSearch' appName #if args.verbose 123 | post.toWins 'clearSearch' 124 | # klog 'getActiveApp fade' if args.verbose 125 | post.toWins 'fade' 126 | else 127 | createWindow() 128 | 129 | # 0000000 0000000 000000000 000 000 000 0000000 000000000 00000000 130 | # 000 000 000 000 000 000 000 000 000 000 000 131 | # 000000000 000 000 000 000 000 000000000 000 0000000 132 | # 000 000 000 000 000 000 000 000 000 000 133 | # 000 000 0000000 000 000 0 000 000 000 00000000 134 | 135 | activateApp = -> 136 | 137 | if slash.win() 138 | if activeWin 139 | wxw = require 'wxw' 140 | info = wxw('info' activeWin)[0] 141 | if info?.path 142 | klog 'activate' info.path 143 | wxw 'launch' info.path 144 | # wxw 'raise' info.path 145 | # wxw 'focus' info.path 146 | win?.hide() 147 | else 148 | if not activeApp? 149 | win?.hide() 150 | else 151 | childp.exec "#{__dirname}/../bin/appswitch -fp #{activeApp}" (err) -> win?.hide() 152 | 153 | #000 000 000 000 000 0000000 0000000 000 000 154 | #000 0 000 000 0000 000 000 000 000 000 000 0 000 155 | #000000000 000 000 0 000 000 000 000 000 000000000 156 | #000 000 000 000 0000 000 000 000 000 000 000 157 | #00 00 000 000 000 0000000 0000000 00 00 158 | 159 | toggleWindow = -> 160 | 161 | if win?.isVisible() 162 | if prefs.get 'hideOnDoubleActivation' false 163 | win.hide() 164 | else 165 | post.toWins 'openCurrent' 166 | # activateApp() if not slash.win() 167 | else 168 | if slash.win() 169 | if not win? 170 | createWindow() 171 | else 172 | getActiveApp() 173 | win.focus() 174 | else 175 | osascript = require('osascript').eval 176 | osascript """ 177 | tell application "System Events" 178 | set n to name of first application process whose frontmost is true 179 | end tell 180 | do shell script "echo " & n 181 | """, type:'AppleScript', (err,name) -> 182 | appName = String(name).trim() 183 | klog 'toggleWindow appName' appName 184 | if not win? 185 | createWindow() 186 | else 187 | getActiveApp() 188 | win.show() 189 | win.focus() 190 | 191 | reloadWindow = -> win.webContents.reloadIgnoringCache() 192 | 193 | # 0000000 00000000 00000000 0000000 000000000 00000000 194 | # 000 000 000 000 000 000 000 000 195 | # 000 0000000 0000000 000000000 000 0000000 196 | # 000 000 000 000 000 000 000 000 197 | # 0000000 000 000 00000000 000 000 000 00000000 198 | 199 | createWindow = -> 200 | 201 | return if win? 202 | 203 | win = new BrowserWindow 204 | width: 300 205 | height: 300 206 | center: true 207 | alwaysOnTop: true 208 | movable: true 209 | resizable: true 210 | transparent: true 211 | frame: false 212 | maximizable: false 213 | minimizable: false 214 | minWidth: 200 215 | minHeight: 200 216 | maxWidth: 600 217 | maxHeight: 600 218 | fullscreen: false 219 | show: false 220 | webPreferences: 221 | webSecurity: false 222 | contextIsolation: false 223 | nodeIntegration: true 224 | nodeIntegrationInWorker: true 225 | 226 | bounds = prefs.get 'bounds' 227 | win.setBounds bounds if bounds? 228 | win.loadURL "file://#{__dirname}/index.html" 229 | # win.on 'closed' -> win = null 230 | win.on 'resize' onWinResize 231 | win.on 'move' saveBounds 232 | win.on 'ready-to-show' -> 233 | getActiveApp() 234 | if args.debug 235 | win.webContents.openDevTools mode:'detach' 236 | win.show() 237 | win.focus() 238 | win 239 | 240 | saveBounds = -> if win? then prefs.set 'bounds' win.getBounds() 241 | 242 | squareTimer = null 243 | 244 | onWinResize = (event) -> 245 | 246 | clearTimeout squareTimer 247 | adjustSize = -> 248 | b = win.getBounds() 249 | if b.width != b.height 250 | b.width = b.height = Math.min b.width, b.height 251 | win.setBounds b 252 | saveBounds() 253 | squareTimer = setTimeout adjustSize, 300 254 | 255 | showAbout = -> 256 | 257 | if prefs.get('scheme' 'dark') == 'bright' 258 | color = '#fff' 259 | textc = '#ddd' 260 | highl = '#000' 261 | else 262 | textc = '#444' 263 | highl = '#fff' 264 | color = '#111' 265 | 266 | about 267 | img: "#{__dirname}/../img/about.png" 268 | color: textc 269 | highlight: highl 270 | background: color 271 | size: 200 272 | pkg: pkg 273 | 274 | app.on 'window-all-closed' (event) -> event.preventDefault() 275 | 276 | #00000000 00000000 0000000 0000000 000 000 277 | #000 000 000 000 000 000 000 000 000 278 | #0000000 0000000 000000000 000 000 00000 279 | #000 000 000 000 000 000 000 000 280 | #000 000 00000000 000 000 0000000 000 281 | 282 | app.on 'ready' -> 283 | 284 | if app.requestSingleInstanceLock? 285 | 286 | if app.requestSingleInstanceLock() 287 | app.on 'second-instance' toggleWindow 288 | else 289 | app.exit 0 290 | 291 | tray = new Tray "#{__dirname}/../img/menu.png" 292 | tray.on 'click' toggleWindow 293 | 294 | if os.platform() != 'darwin' 295 | tray.setContextMenu Menu.buildFromTemplate [ 296 | label: "Quit" 297 | click: -> app.exit 0; process.exit 0 298 | , 299 | label: "About" 300 | click: showAbout 301 | , 302 | label: "Activate" 303 | click: toggleWindow 304 | ] 305 | 306 | app.dock?.hide() 307 | 308 | # 00 00 00000000 000 000 000 000 309 | # 000 000 000 0000 000 000 000 310 | # 000000000 0000000 000 0 000 000 000 311 | # 000 0 000 000 000 0000 000 000 312 | # 000 000 00000000 000 000 0000000 313 | 314 | Menu.setApplicationMenu Menu.buildFromTemplate [ 315 | label: app.getName() 316 | submenu: [ 317 | label: "About #{pkg.name}" 318 | accelerator: 'CmdOrCtrl+.' 319 | click: -> showAbout() 320 | , 321 | type: 'separator' 322 | , 323 | label: 'Quit' 324 | accelerator: 'CmdOrCtrl+Q' 325 | click: -> 326 | saveBounds() 327 | app.exit 0 328 | process.exit 0 329 | ] 330 | , 331 | # 000 000 000 000 000 0000000 0000000 000 000 332 | # 000 0 000 000 0000 000 000 000 000 000 000 0 000 333 | # 000000000 000 000 0 000 000 000 000 000 000000000 334 | # 000 000 000 000 0000 000 000 000 000 000 000 335 | # 00 00 000 000 000 0000000 0000000 00 00 336 | 337 | label: 'Window' 338 | submenu: [ 339 | label: 'Close Window' 340 | accelerator: 'CmdOrCtrl+W' 341 | click: -> win?.close() 342 | , 343 | type: 'separator' 344 | , 345 | label: 'Reload Window' 346 | accelerator: 'CmdOrCtrl+Alt+L' 347 | click: -> reloadWindow() 348 | , 349 | label: 'Toggle DevTools' 350 | accelerator: 'CmdOrCtrl+Alt+I' 351 | click: -> win?.webContents.openDevTools() 352 | ] 353 | ] 354 | 355 | prefs.init defaults:shortcut:'F1' 356 | 357 | electron.globalShortcut.register prefs.get('shortcut'), toggleWindow 358 | 359 | fs.ensureDirSync iconDir 360 | 361 | scr = require './scripts' 362 | if slash.win() 363 | scripts = scr.winScripts() 364 | else 365 | scripts = scr.macScripts() 366 | 367 | findApps() 368 | 369 | -------------------------------------------------------------------------------- /coffee/kappo.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | 000 000 0000000 00000000 00000000 0000000 3 | 000 000 000 000 000 000 000 000 000 000 4 | 0000000 000000000 00000000 00000000 000 000 5 | 000 000 000 000 000 000 000 000 6 | 000 000 000 000 000 000 0000000 7 | ### 8 | 9 | { post, args, srcmap, childIndex, setStyle, stopEvent, keyinfo, history, valid, empty, childp, 10 | scheme, clamp, prefs, elem, fs, slash, open, klog, kerror, kpos, sw, $, _ } = require 'kxk' 11 | 12 | pkg = require '../package.json' 13 | fuzzy = require 'fuzzy' 14 | fuzzaldrin = require 'fuzzaldrin' 15 | electron = require 'electron' 16 | 17 | clipboard = electron.clipboard 18 | iconDir = slash.resolve "#{post.get('userData')}/icons" 19 | ipc = electron.ipcRenderer 20 | 21 | appHist = null 22 | results = [] 23 | apps = {} 24 | scripts = {} 25 | allKeys = [] 26 | search = '' 27 | currentName = '' 28 | currentIndex = 0 29 | 30 | post.on 'mainlog' (text) -> log ">>> " + text 31 | post.on 'appsFound' -> { apps, scripts, allKeys } = post.get 'apps' 32 | 33 | # 000 000 000 000 000 00 00 0000000 000 000 000 34 | # 000 0 000 000 0000 000 000 000 000 000 000 0000 000 35 | # 000000000 000 000 0 000 000000000 000000000 000 000 0 000 36 | # 000 000 000 000 0000 000 0 000 000 000 000 000 0000 37 | # 00 00 000 000 000 000 000 000 000 000 000 000 38 | 39 | winMain = -> 40 | 41 | window.onerror = (msg, source, line, col, err) -> 42 | srcmap.logErr err 43 | true 44 | 45 | klog.slog.icon = slash.fileUrl slash.join __dirname, '..' 'img' 'menu@2x.png' 46 | 47 | post.on 'fade' -> 48 | 49 | if not slash.win() 50 | # win.show() 51 | return 52 | 53 | # [x,y] = win.getPosition() # enable smooth fade on windows: 54 | # win.setPosition -10000,-10000 # move window offscreen before show 55 | # win.show() 56 | $('#main').classList.remove 'fade' 57 | $('#main').style.opacity = 0 58 | 59 | restore = -> 60 | 61 | # if x < -10 or y < -10 # key repeat hickup 'fix' 62 | # b = win.getBounds() 63 | # x = (screenSize().width - b.width)/2 64 | # y = 0 65 | # else 66 | # win.setPosition x,y 67 | 68 | $('#main').classList.add 'fade' 69 | 70 | setTimeout restore, 30 # give windows some time to do it's flickering 71 | 72 | prefs.init() 73 | 74 | { apps, scripts, allKeys } = post.get 'apps' 75 | 76 | appHist = new history 77 | list: prefs.get 'history' [] 78 | maxLength: prefs.get 'maxHistoryLength' 10 79 | 80 | scheme.set prefs.get 'scheme' 'bright' 81 | 82 | winHide = -> 83 | 84 | if not args.debug 85 | post.toMain 'hideWin' 86 | 87 | # 0000000 00000000 00000000 000 000 88 | # 000 000 000 000 000 0000 000 89 | # 000 000 00000000 0000000 000 0 000 90 | # 000 000 000 000 000 0000 91 | # 0000000 000 00000000 000 000 92 | 93 | openCurrent = -> 94 | 95 | ipc.send 'closeAbout' 96 | 97 | if currentIndex > 0 and search.length 98 | prefs.set "search:#{search}:#{currentName}", 1 + prefs.get "search:#{search}:#{currentName}" 0 99 | 100 | if currentIsApp() 101 | 102 | addToHistory() 103 | 104 | if slash.win() 105 | 106 | # klog 'launch' currentName, apps[currentName] 107 | wxw = require 'wxw' 108 | wxw 'launch' apps[currentName] 109 | winHide() 110 | 111 | else 112 | klog 'openCurrent' currentName 113 | childp.exec "open -a \"#{apps[currentName]}\"" (err) -> 114 | if err? then log "[ERROR] can't open #{apps[currentName]} #{err}" 115 | 116 | else if scripts[currentName]? 117 | 118 | if scripts[currentName].foreground? 119 | 120 | exe = slash.file scripts[currentName].foreground 121 | addToHistory() 122 | 123 | if slash.win() 124 | wxw = require 'wxw' 125 | info = wxw('info' exe)?[0] 126 | if info 127 | winHide() 128 | wxw 'show' exe 129 | wxw 'raise' exe 130 | wxw 'focus' exe 131 | return 132 | 133 | if scripts[currentName].exec? 134 | 135 | childp.exec scripts[currentName].exec, (err) -> 136 | if err? then log "[ERROR] can't execute script #{scripts[currentName]}: #{err}" 137 | 138 | else 139 | post.toMain 'runScript' currentName 140 | winHide() 141 | 142 | post.on 'openCurrent' openCurrent 143 | 144 | # 0000000 000 000 00000000 00000000 00000000 000 000 000000000 145 | # 000 000 000 000 000 000 000 000 0000 000 000 146 | # 000 000 000 0000000 0000000 0000000 000 0 000 000 147 | # 000 000 000 000 000 000 000 000 000 0000 000 148 | # 0000000 0000000 000 000 000 000 00000000 000 000 000 149 | 150 | currentApp = (appName) -> 151 | 152 | currentName = 'kappo' if empty currentName 153 | appName = 'kappo' if empty appName 154 | lastMatches = currentName.toLowerCase() == appName.toLowerCase() 155 | scriptMatches = scripts[currentName]?.foreground? and slash.base(scripts[currentName].foreground).toLowerCase() == appName.toLowerCase() 156 | 157 | if (lastMatches or scriptMatches) and appHist.previous() and prefs.get 'appToggle' true 158 | listHistory 1 159 | search = '' 160 | else 161 | klog "currentApp #{appName} -> #{currentName}" lastMatches, scriptMatches 162 | name = currentName 163 | doSearch '' 164 | selectName name if not empty name 165 | search = '' 166 | $('appname').innerHTML = name 167 | 168 | $('#main').classList.add 'fade' 169 | 170 | post.on 'currentApp' currentApp 171 | 172 | currentIsApp = => not currentIsScript() 173 | currentIsScript = -> results[currentIndex]?.script? 174 | 175 | # 000000000 0000000 0000000 0000000 000 00000000 176 | # 000 000 000 000 000 000 000 177 | # 000 000 000 000 0000 000 0000 000 0000000 178 | # 000 000 000 000 000 000 000 000 000 179 | # 000 0000000 0000000 0000000 0000000 00000000 180 | 181 | toggleAppToggle = -> 182 | 183 | prefs.set 'appToggle' not prefs.get 'appToggle' true 184 | 185 | toggleDoubleActivation = -> 186 | 187 | prefs.set 'hideOnDoubleActivation', not prefs.get 'hideOnDoubleActivation', false 188 | 189 | # 000 000 000 0000000 000000000 0000000 00000000 000 000 190 | # 000 000 000 000 000 000 000 000 000 000 000 191 | # 000000000 000 0000000 000 000 000 0000000 00000 192 | # 000 000 000 000 000 000 000 000 000 000 193 | # 000 000 000 0000000 000 0000000 000 000 000 194 | 195 | listHistory = (offset=0) -> 196 | klog "listHistory #{offset}" appHist.list 197 | results = [] 198 | if valid appHist 199 | for h in appHist.list 200 | result = _.clone h 201 | result.string ?= result.name 202 | results.push result 203 | index = results.length - 1 - offset 204 | klog "listHistory index #{index}" results 205 | select index 206 | showDots() 207 | 208 | addToHistory = -> 209 | 210 | return if empty results[currentIndex] 211 | 212 | result = _.clone results[currentIndex] 213 | delete result.string 214 | appHist.add result 215 | prefs.set 'history' appHist.list 216 | 217 | openInFinder = () -> 218 | 219 | childp.spawn 'osascript', [ 220 | '-e', 'tell application "Finder"', 221 | '-e', "reveal POSIX file \"#{apps[currentName]}\"", 222 | '-e', 'activate', 223 | '-e', 'end tell'] 224 | 225 | # 0000000 000 00000000 0000000 00000000 226 | # 000 000 000 000 000 000 000 227 | # 000 000 0000000 000000000 0000000 228 | # 000 000 000 000 000 000 000 229 | # 0000000 0000000 00000000 000 000 000 000 230 | 231 | clearSearch = -> 232 | 233 | if results.length 234 | search = '' 235 | results = [results[Math.min currentIndex, results.length-1]] 236 | results[0].string = currentName 237 | $('appname').innerHTML = currentName 238 | currentIndex = 0 239 | showDots() 240 | else 241 | doSearch '' 242 | 243 | post.on 'clearSearch' clearSearch 244 | 245 | # 000 0000000 0000000 000 000 246 | # 000 000 000 000 0000 000 247 | # 000 000 000 000 000 0 000 248 | # 000 000 000 000 000 0000 249 | # 000 0000000 0000000 000 000 250 | 251 | getScriptIcon = (scriptName) -> setIcon scripts[scriptName].img 252 | 253 | getAppIcon = (appName) -> 254 | 255 | if slash.win() 256 | appIcon = require './exeicon' 257 | else 258 | appIcon = require './appicon' 259 | 260 | appIcon.get 261 | appPath: apps[appName] 262 | iconDir: iconDir 263 | size: 512 264 | cb: setIcon 265 | 266 | setIcon = (iconPath) -> 267 | 268 | $('appicon').style.backgroundImage = "url(\"#{slash.fileUrl iconPath}\")" 269 | 270 | # 0000000 00000000 000 00000000 0000000 000000000 271 | # 000 000 000 000 000 000 272 | # 0000000 0000000 000 0000000 000 000 273 | # 000 000 000 000 000 000 274 | # 0000000 00000000 0000000 00000000 0000000 000 275 | 276 | select = (index) => 277 | currentIndex = (index + results.length) % results.length 278 | if empty results[currentIndex] 279 | log 'dafuk? index:', index, 'results:', results 280 | return 281 | currentName = results[currentIndex].name 282 | $('appname').innerHTML = results[currentIndex].string 283 | $('.current')?.classList.remove 'current' 284 | $("dot_#{currentIndex}")?.classList.add 'current' 285 | if currentIsApp() 286 | getAppIcon currentName 287 | else 288 | getScriptIcon currentName 289 | 290 | selectName = (name) -> 291 | 292 | return if empty name 293 | select results.findIndex (r) -> 294 | r?.name.toLowerCase() == name.toLowerCase() 295 | 296 | # 0000000 0000000 000000000 0000000 297 | # 000 000 000 000 000 000 298 | # 000 000 000 000 000 0000000 299 | # 000 000 000 000 000 000 300 | # 0000000 0000000 000 0000000 301 | 302 | showDots = -> 303 | 304 | dots =$ 'appdots' 305 | dots.innerHTML = '' 306 | 307 | winWidth = sw() 308 | setStyle '#appname' 'font-size' "#{parseInt 10+2*(winWidth-100)/100}px" 309 | 310 | return if results.length < 2 311 | 312 | dotr = elem id:'appdotr' 313 | dots.appendChild dotr 314 | 315 | s = winWidth / results.length 316 | s = clamp 1, winWidth/100, s 317 | s = parseInt s 318 | setStyle '.appdot', 'width', "#{s}px" 319 | setStyle '.appdot', 'height', "#{s}px" 320 | 321 | for i in [0...results.length] 322 | dot = elem 'span', class:'appdot', id: "dot_#{i}" 323 | if i == currentIndex 324 | dot.classList.add 'current' 325 | dotr.appendChild dot 326 | 327 | # 0000000 000 0000000 0000000 000 000 000 000 0000000 000000000 328 | # 000 000 000 000 000 000 000 000 000 000 000 000 329 | # 0000000 000 000000000 000 0000000 000 000 0000000 000 330 | # 000 000 000 000 000 000 000 000 000 000 000 000 331 | # 0000000 0000000 000 000 0000000 000 000 0000000 000 0000000 000 332 | 333 | blacklist = -> 334 | 335 | ignore = prefs.get 'ignore', [] 336 | 337 | _.pull ignore, apps[currentName] 338 | _.pull ignore, null 339 | if valid apps[currentName] 340 | ignore.push apps[currentName] 341 | else 342 | log "can't ignore '#{currentName}'" 343 | 344 | prefs.set 'ignore', ignore 345 | 346 | delete apps[currentName] 347 | 348 | results.splice currentIndex, 1 349 | 350 | select currentIndex 351 | 352 | # 0000000 00000000 0000000 00000000 0000000 000 000 353 | # 000 000 000 000 000 000 000 000 000 354 | # 0000000 0000000 000000000 0000000 000 000000000 355 | # 000 000 000 000 000 000 000 000 000 356 | # 0000000 00000000 000 000 000 000 0000000 000 000 357 | 358 | doSearch = (s) -> 359 | 360 | search = s 361 | names = allKeys 362 | fuzzied = fuzzy.filter search, names, pre: '', post: '' 363 | fuzzied = _.sortBy fuzzied, (o) -> 2 - fuzzaldrin.score o.original, search 364 | 365 | if search.length 366 | if ps = prefs.get "search:#{search}" 367 | fuzzied = _.sortBy fuzzied, (o) -> Number.MAX_SAFE_INTEGER - (ps[o.original] ? 0) 368 | 369 | results = [] 370 | for f in fuzzied 371 | r = name: f.original, string: f.string 372 | r.script = scripts[r.name] if scripts[r.name] 373 | results.push r 374 | 375 | if valid results 376 | if s == '' 377 | if slash.win() 378 | selectName 'terminal' 379 | else 380 | selectName 'Finder' 381 | else 382 | select 0 383 | showDots() 384 | else 385 | $('appdots').innerHTML = '' 386 | $('appname').innerHTML = "#{search}" 387 | 388 | complete = (key) -> doSearch search + key 389 | backspace = -> doSearch search.substr 0, search.length-1 390 | 391 | cancelSearchOrClose = -> 392 | 393 | ipc.send 'closeAbout' 394 | 395 | if search.length 396 | doSearch '' 397 | else 398 | post.toMain 'cancel' 399 | 400 | clickID = downID = 0 401 | window.onmousedown = (e) -> clickID += 1 ; downID = clickID 402 | window.onmouseup = (e) -> openCurrent() if downID == clickID 403 | window.onmousemove = (e) -> if e.buttons then downID = -1 404 | window.onunload = -> document.onkeydown = null 405 | window.onblur = -> winHide() 406 | window.onresize = -> showDots() 407 | 408 | wheelAccu = 0 409 | window.onwheel = (event) -> 410 | wheelAccu += (event.deltaX + event.deltaY)/44 411 | if wheelAccu > 1 412 | select currentIndex+1 % results.length 413 | while wheelAccu > 1 414 | wheelAccu -= 1 415 | else if wheelAccu < -1 416 | select currentIndex+results.length-1 % results.length 417 | while wheelAccu < -1 418 | wheelAccu += 1 419 | 420 | # 0000000 000 0000000 00000000 421 | # 000 000 000 000 422 | # 0000000 000 000 0000000 423 | # 000 000 000 000 424 | # 0000000 000 0000000 00000000 425 | 426 | openDevTools = -> post.toMain 'devTools' 427 | screenSize = -> ss = electron.ipcRenderer.sendSync 'getScreenSize'; klog 'screenSize' ss; ss 428 | 429 | clampBounds = (b) -> 430 | b.width = clamp 200, 600, b.width 431 | b.height = clamp 200, 600, b.height 432 | b.x = clamp 0, screenSize().width - b.width, b.x 433 | b.y = clamp 0, screenSize().height - b.height, b.y 434 | b 435 | 436 | getBounds = -> b = electron.ipcRenderer.sendSync 'getWinBounds'; klog 'getBounds' b; b 437 | setBounds = (b) -> electron.ipcRenderer.send 'setWinBounds' b; klog 'setBounds' b 438 | 439 | sizeWindow = (d) -> 440 | b = getBounds() 441 | cx = b.x + b.width/2 442 | b.width+=d 443 | b.height+=d 444 | clampBounds b 445 | b.x = cx - b.width/2 446 | setBounds clampBounds b 447 | 448 | moveWindow = (dx,dy) -> 449 | b = getBounds() 450 | b.x+=dx 451 | b.y+=dy 452 | setBounds clampBounds b 453 | 454 | biggerWindow = -> sizeWindow 50 455 | smallerWindow = -> sizeWindow -50 456 | minimizeWindow = -> setBounds x:screenSize().width/2-100, y:0, width:200, height:200 457 | maximizeWindow = -> setBounds x:screenSize().width/2-300, y:0, width:600, height:600 458 | toggleWindowSize = -> if getBounds().width > 200 then minimizeWindow() else maximizeWindow() 459 | 460 | preventKeyRepeat = -> log 'keyRepeat ahead!' 461 | 462 | # 000 000 00000000 000 000 463 | # 000 000 000 000 000 464 | # 0000000 0000000 00000 465 | # 000 000 000 000 466 | # 000 000 00000000 000 467 | 468 | document.onkeydown = (event) -> 469 | 470 | { mod, key, combo, char } = keyinfo.forEvent event 471 | 472 | klog combo #if args.verbose 473 | 474 | if char? and combo.length == 1 475 | complete key 476 | return 477 | 478 | switch combo 479 | when 'f1' then preventKeyRepeat() 480 | when 'delete' then blacklist() 481 | when 'backspace' then backspace() 482 | when 'command+backspace', 'ctrl+backspace' then doSearch '' 483 | when 'command+i', 'ctrl+i' then scheme.toggle() 484 | when 'esc' then cancelSearchOrClose() 485 | when 'down', 'right' then select currentIndex+1 486 | when 'up' , 'left' then select currentIndex-1 487 | when 'enter' then openCurrent() 488 | when 'command+alt+i', 'ctrl+alt+i' then openDevTools() 489 | when 'command+=', 'ctrl+=' then biggerWindow() 490 | when 'command+-', 'ctrl+-' then smallerWindow() 491 | when 'command+r', 'ctrl+r' then post.toMain 'findApps' 492 | when 'command+h', 'alt+h' then listHistory() 493 | when 'command+f', 'ctrl+f' then openInFinder() 494 | when 'command+t', 'ctrl+t' then toggleAppToggle() 495 | when 'command+d', 'ctrl+d' then toggleDoubleActivation() 496 | when 'alt+command+/', 'alt+ctrl+/' then post.toMain 'about' 497 | when 'command+,', 'ctrl+,' then open prefs.store.file 498 | when 'command+up', 'ctrl+up' then moveWindow 0,-20 499 | when 'command+down', 'ctrl+down' then moveWindow 0, 20 500 | when 'command+left', 'ctrl+left' then moveWindow -20, 0 501 | when 'command+right', 'ctrl+right' then moveWindow 20, 0 502 | when 'command+0','command+o', 'ctrl+0','ctrl+o' then toggleWindowSize() 503 | 504 | winMain() 505 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | // koffee 1.14.0 2 | 3 | /* 4 | 00 00 0000000 000 000 000 5 | 000 000 000 000 000 0000 000 6 | 000000000 000000000 000 000 0 000 7 | 000 0 000 000 000 000 000 0000 8 | 000 000 000 000 000 000 000 9 | */ 10 | var BrowserWindow, Menu, Tray, about, activateApp, activeApp, activeWin, allKeys, app, appName, apps, args, childp, clipboard, createWindow, electron, findApps, fs, getActiveApp, iconDir, klog, onWinResize, os, osascript, pkg, post, prefs, ref, reloadWindow, saveBounds, scripts, showAbout, slash, squareTimer, srcmap, toggleWindow, tray, valid, win; 11 | 12 | ref = require('kxk'), about = ref.about, app = ref.app, args = ref.args, childp = ref.childp, fs = ref.fs, klog = ref.klog, os = ref.os, osascript = ref.osascript, post = ref.post, prefs = ref.prefs, slash = ref.slash, srcmap = ref.srcmap, valid = ref.valid, win = ref.win; 13 | 14 | pkg = require('../package.json'); 15 | 16 | electron = require('electron'); 17 | 18 | app = electron.app; 19 | 20 | BrowserWindow = electron.BrowserWindow; 21 | 22 | Tray = electron.Tray; 23 | 24 | Menu = electron.Menu; 25 | 26 | clipboard = electron.clipboard; 27 | 28 | iconDir = slash.resolve((app.getPath('userData')) + "/icons"); 29 | 30 | win = null; 31 | 32 | tray = null; 33 | 34 | apps = {}; 35 | 36 | scripts = {}; 37 | 38 | allKeys = []; 39 | 40 | process.on('uncaughtException', function(err) { 41 | srcmap.logErr(err, '🔻'); 42 | return true; 43 | }); 44 | 45 | klog.slog.icon = slash.fileUrl(slash.resolve(slash.join(__dirname, '..', 'img', 'menu@2x.png'))); 46 | 47 | app.setName(pkg.productName); 48 | 49 | args = args.init("verbose log verbose false\ndebug log debug false -D"); 50 | 51 | post.on('winlog', function(text) { 52 | return console.log(">>> " + text); 53 | }); 54 | 55 | post.on('runScript', function(name) { 56 | return scripts[name].cb(); 57 | }); 58 | 59 | post.on('hideWin', function() { 60 | return win != null ? win.hide() : void 0; 61 | }); 62 | 63 | post.on('cancel', function() { 64 | return activateApp(); 65 | }); 66 | 67 | post.on('about', function() { 68 | return showAbout(); 69 | }); 70 | 71 | post.on('findApps', function() { 72 | return findApps(); 73 | }); 74 | 75 | post.on('devTools', function() { 76 | return win != null ? win.webContents.openDevTools({ 77 | mode: 'detach' 78 | }) : void 0; 79 | }); 80 | 81 | post.onGet('apps', function() { 82 | return { 83 | apps: apps, 84 | scripts: scripts, 85 | allKeys: allKeys 86 | }; 87 | }); 88 | 89 | electron.ipcMain.on('getWinBounds', function(e) { 90 | return e.returnValue = win != null ? win.getBounds() : void 0; 91 | }); 92 | 93 | electron.ipcMain.on('getScreenSize', function(e) { 94 | return e.returnValue = electron.screen.getPrimaryDisplay().workAreaSize; 95 | }); 96 | 97 | electron.ipcMain.on('setWinBounds', function(e, b) { 98 | klog('setWinBounds', win != null, b); 99 | return win != null ? win.setBounds(b) : void 0; 100 | }); 101 | 102 | findApps = function() { 103 | var appFind, exeFind, sortKeys; 104 | sortKeys = function() { 105 | var hideWin; 106 | allKeys = Object.keys(apps).concat(Object.keys(scripts)); 107 | allKeys.sort(function(a, b) { 108 | return a.toLowerCase().localeCompare(b.toLowerCase()); 109 | }); 110 | if (win) { 111 | return post.toWins('appsFound'); 112 | } else { 113 | createWindow(); 114 | hideWin = function() { 115 | return win != null ? win.hide() : void 0; 116 | }; 117 | if (!args.debug) { 118 | return setTimeout(hideWin, 1000); 119 | } 120 | } 121 | }; 122 | if (slash.win()) { 123 | exeFind = require('./exefind'); 124 | return exeFind(function(exes) { 125 | if (valid(exes)) { 126 | apps = exes; 127 | return sortKeys(); 128 | } 129 | }); 130 | } else { 131 | appFind = require('./appfind'); 132 | return appFind(function(appl) { 133 | apps = appl; 134 | return sortKeys(); 135 | }); 136 | } 137 | }; 138 | 139 | appName = null; 140 | 141 | activeApp = null; 142 | 143 | activeWin = null; 144 | 145 | getActiveApp = function() { 146 | var top, wxw; 147 | if (slash.win()) { 148 | wxw = require('wxw'); 149 | top = wxw('info', 'top')[0]; 150 | if ((top != null ? top.path : void 0) != null) { 151 | appName = activeApp = slash.base(top.path); 152 | } 153 | } else { 154 | activeApp = childp.execSync(__dirname + "/../bin/appswitch -P", { 155 | encoding: 'utf8' 156 | }); 157 | } 158 | klog('getActiveApp appName', appName, '-> activeApp', activeApp); 159 | if (win != null) { 160 | if (appName != null) { 161 | klog('getActiveApp post.currentApp', appName); 162 | post.toWins('currentApp', appName); 163 | } else { 164 | klog('getActiveApp clearSearch', appName); 165 | post.toWins('clearSearch'); 166 | } 167 | return post.toWins('fade'); 168 | } else { 169 | return createWindow(); 170 | } 171 | }; 172 | 173 | activateApp = function() { 174 | var info, wxw; 175 | if (slash.win()) { 176 | if (activeWin) { 177 | wxw = require('wxw'); 178 | info = wxw('info', activeWin)[0]; 179 | if (info != null ? info.path : void 0) { 180 | klog('activate', info.path); 181 | wxw('launch', info.path); 182 | } 183 | } 184 | return win != null ? win.hide() : void 0; 185 | } else { 186 | if (activeApp == null) { 187 | return win != null ? win.hide() : void 0; 188 | } else { 189 | return childp.exec(__dirname + "/../bin/appswitch -fp " + activeApp, function(err) { 190 | return win != null ? win.hide() : void 0; 191 | }); 192 | } 193 | } 194 | }; 195 | 196 | toggleWindow = function() { 197 | if (win != null ? win.isVisible() : void 0) { 198 | if (prefs.get('hideOnDoubleActivation', false)) { 199 | return win.hide(); 200 | } else { 201 | return post.toWins('openCurrent'); 202 | } 203 | } else { 204 | if (slash.win()) { 205 | if (win == null) { 206 | return createWindow(); 207 | } else { 208 | getActiveApp(); 209 | return win.focus(); 210 | } 211 | } else { 212 | osascript = require('osascript')["eval"]; 213 | return osascript("tell application \"System Events\"\n set n to name of first application process whose frontmost is true\nend tell\ndo shell script \"echo \" & n", { 214 | type: 'AppleScript' 215 | }, function(err, name) { 216 | appName = String(name).trim(); 217 | klog('toggleWindow appName', appName); 218 | if (win == null) { 219 | return createWindow(); 220 | } else { 221 | getActiveApp(); 222 | win.show(); 223 | return win.focus(); 224 | } 225 | }); 226 | } 227 | } 228 | }; 229 | 230 | reloadWindow = function() { 231 | return win.webContents.reloadIgnoringCache(); 232 | }; 233 | 234 | createWindow = function() { 235 | var bounds; 236 | if (win != null) { 237 | return; 238 | } 239 | win = new BrowserWindow({ 240 | width: 300, 241 | height: 300, 242 | center: true, 243 | alwaysOnTop: true, 244 | movable: true, 245 | resizable: true, 246 | transparent: true, 247 | frame: false, 248 | maximizable: false, 249 | minimizable: false, 250 | minWidth: 200, 251 | minHeight: 200, 252 | maxWidth: 600, 253 | maxHeight: 600, 254 | fullscreen: false, 255 | show: false, 256 | webPreferences: { 257 | webSecurity: false, 258 | contextIsolation: false, 259 | nodeIntegration: true, 260 | nodeIntegrationInWorker: true 261 | } 262 | }); 263 | bounds = prefs.get('bounds'); 264 | if (bounds != null) { 265 | win.setBounds(bounds); 266 | } 267 | win.loadURL("file://" + __dirname + "/index.html"); 268 | win.on('resize', onWinResize); 269 | win.on('move', saveBounds); 270 | win.on('ready-to-show', function() { 271 | getActiveApp(); 272 | if (args.debug) { 273 | win.webContents.openDevTools({ 274 | mode: 'detach' 275 | }); 276 | } 277 | win.show(); 278 | return win.focus(); 279 | }); 280 | return win; 281 | }; 282 | 283 | saveBounds = function() { 284 | if (win != null) { 285 | return prefs.set('bounds', win.getBounds()); 286 | } 287 | }; 288 | 289 | squareTimer = null; 290 | 291 | onWinResize = function(event) { 292 | var adjustSize; 293 | clearTimeout(squareTimer); 294 | adjustSize = function() { 295 | var b; 296 | b = win.getBounds(); 297 | if (b.width !== b.height) { 298 | b.width = b.height = Math.min(b.width, b.height); 299 | win.setBounds(b); 300 | } 301 | return saveBounds(); 302 | }; 303 | return squareTimer = setTimeout(adjustSize, 300); 304 | }; 305 | 306 | showAbout = function() { 307 | var color, highl, textc; 308 | if (prefs.get('scheme', 'dark') === 'bright') { 309 | color = '#fff'; 310 | textc = '#ddd'; 311 | highl = '#000'; 312 | } else { 313 | textc = '#444'; 314 | highl = '#fff'; 315 | color = '#111'; 316 | } 317 | return about({ 318 | img: __dirname + "/../img/about.png", 319 | color: textc, 320 | highlight: highl, 321 | background: color, 322 | size: 200, 323 | pkg: pkg 324 | }); 325 | }; 326 | 327 | app.on('window-all-closed', function(event) { 328 | return event.preventDefault(); 329 | }); 330 | 331 | app.on('ready', function() { 332 | var ref1, scr; 333 | if (app.requestSingleInstanceLock != null) { 334 | if (app.requestSingleInstanceLock()) { 335 | app.on('second-instance', toggleWindow); 336 | } else { 337 | app.exit(0); 338 | } 339 | } 340 | tray = new Tray(__dirname + "/../img/menu.png"); 341 | tray.on('click', toggleWindow); 342 | if (os.platform() !== 'darwin') { 343 | tray.setContextMenu(Menu.buildFromTemplate([ 344 | { 345 | label: "Quit", 346 | click: function() { 347 | app.exit(0); 348 | return process.exit(0); 349 | } 350 | }, { 351 | label: "About", 352 | click: showAbout 353 | }, { 354 | label: "Activate", 355 | click: toggleWindow 356 | } 357 | ])); 358 | } 359 | if ((ref1 = app.dock) != null) { 360 | ref1.hide(); 361 | } 362 | Menu.setApplicationMenu(Menu.buildFromTemplate([ 363 | { 364 | label: app.getName(), 365 | submenu: [ 366 | { 367 | label: "About " + pkg.name, 368 | accelerator: 'CmdOrCtrl+.', 369 | click: function() { 370 | return showAbout(); 371 | } 372 | }, { 373 | type: 'separator' 374 | }, { 375 | label: 'Quit', 376 | accelerator: 'CmdOrCtrl+Q', 377 | click: function() { 378 | saveBounds(); 379 | app.exit(0); 380 | return process.exit(0); 381 | } 382 | } 383 | ] 384 | }, { 385 | label: 'Window', 386 | submenu: [ 387 | { 388 | label: 'Close Window', 389 | accelerator: 'CmdOrCtrl+W', 390 | click: function() { 391 | return win != null ? win.close() : void 0; 392 | } 393 | }, { 394 | type: 'separator' 395 | }, { 396 | label: 'Reload Window', 397 | accelerator: 'CmdOrCtrl+Alt+L', 398 | click: function() { 399 | return reloadWindow(); 400 | } 401 | }, { 402 | label: 'Toggle DevTools', 403 | accelerator: 'CmdOrCtrl+Alt+I', 404 | click: function() { 405 | return win != null ? win.webContents.openDevTools() : void 0; 406 | } 407 | } 408 | ] 409 | } 410 | ])); 411 | prefs.init({ 412 | defaults: { 413 | shortcut: 'F1' 414 | } 415 | }); 416 | electron.globalShortcut.register(prefs.get('shortcut'), toggleWindow); 417 | fs.ensureDirSync(iconDir); 418 | scr = require('./scripts'); 419 | if (slash.win()) { 420 | scripts = scr.winScripts(); 421 | } else { 422 | scripts = scr.macScripts(); 423 | } 424 | return findApps(); 425 | }); 426 | 427 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIuLi9jb2ZmZWUiLCJzb3VyY2VzIjpbIm1haW4uY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7Ozs7Ozs7QUFBQSxJQUFBOztBQVFBLE1BQWdHLE9BQUEsQ0FBUSxLQUFSLENBQWhHLEVBQUUsaUJBQUYsRUFBUyxhQUFULEVBQWMsZUFBZCxFQUFvQixtQkFBcEIsRUFBNEIsV0FBNUIsRUFBZ0MsZUFBaEMsRUFBc0MsV0FBdEMsRUFBMEMseUJBQTFDLEVBQXFELGVBQXJELEVBQTJELGlCQUEzRCxFQUFrRSxpQkFBbEUsRUFBeUUsbUJBQXpFLEVBQWlGLGlCQUFqRixFQUF3Rjs7QUFFeEYsR0FBQSxHQUFnQixPQUFBLENBQVEsaUJBQVI7O0FBQ2hCLFFBQUEsR0FBZ0IsT0FBQSxDQUFRLFVBQVI7O0FBRWhCLEdBQUEsR0FBZ0IsUUFBUSxDQUFDOztBQUN6QixhQUFBLEdBQWdCLFFBQVEsQ0FBQzs7QUFDekIsSUFBQSxHQUFnQixRQUFRLENBQUM7O0FBQ3pCLElBQUEsR0FBZ0IsUUFBUSxDQUFDOztBQUN6QixTQUFBLEdBQWdCLFFBQVEsQ0FBQzs7QUFDekIsT0FBQSxHQUFnQixLQUFLLENBQUMsT0FBTixDQUFnQixDQUFDLEdBQUcsQ0FBQyxPQUFKLENBQVksVUFBWixDQUFELENBQUEsR0FBeUIsUUFBekM7O0FBRWhCLEdBQUEsR0FBZ0I7O0FBQ2hCLElBQUEsR0FBZ0I7O0FBRWhCLElBQUEsR0FBZ0I7O0FBQ2hCLE9BQUEsR0FBZ0I7O0FBQ2hCLE9BQUEsR0FBZ0I7O0FBRWhCLE9BQU8sQ0FBQyxFQUFSLENBQVcsbUJBQVgsRUFBK0IsU0FBQyxHQUFEO0lBQzNCLE1BQU0sQ0FBQyxNQUFQLENBQWMsR0FBZCxFQUFtQixJQUFuQjtXQUNBO0FBRjJCLENBQS9COztBQUlBLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBVixHQUFpQixLQUFLLENBQUMsT0FBTixDQUFjLEtBQUssQ0FBQyxPQUFOLENBQWMsS0FBSyxDQUFDLElBQU4sQ0FBVyxTQUFYLEVBQXNCLElBQXRCLEVBQTJCLEtBQTNCLEVBQWlDLGFBQWpDLENBQWQsQ0FBZDs7QUFFakIsR0FBRyxDQUFDLE9BQUosQ0FBWSxHQUFHLENBQUMsV0FBaEI7O0FBRUEsSUFBQSxHQUFPLElBQUksQ0FBQyxJQUFMLENBQVUsMEVBQVY7O0FBV1AsSUFBSSxDQUFDLEVBQUwsQ0FBUSxRQUFSLEVBQW9CLFNBQUMsSUFBRDtXQUFRLE9BQUEsQ0FBRSxHQUFGLENBQU0sTUFBQSxHQUFTLElBQWY7QUFBUixDQUFwQjs7QUFDQSxJQUFJLENBQUMsRUFBTCxDQUFRLFdBQVIsRUFBb0IsU0FBQyxJQUFEO1dBQVUsT0FBUSxDQUFBLElBQUEsQ0FBSyxDQUFDLEVBQWQsQ0FBQTtBQUFWLENBQXBCOztBQUNBLElBQUksQ0FBQyxFQUFMLENBQVEsU0FBUixFQUFtQixTQUFBO3lCQUFHLEdBQUcsQ0FBRSxJQUFMLENBQUE7QUFBSCxDQUFuQjs7QUFDQSxJQUFJLENBQUMsRUFBTCxDQUFRLFFBQVIsRUFBbUIsU0FBQTtXQUFHLFdBQUEsQ0FBQTtBQUFILENBQW5COztBQUNBLElBQUksQ0FBQyxFQUFMLENBQVEsT0FBUixFQUFtQixTQUFBO1dBQUcsU0FBQSxDQUFBO0FBQUgsQ0FBbkI7O0FBQ0EsSUFBSSxDQUFDLEVBQUwsQ0FBUSxVQUFSLEVBQW1CLFNBQUE7V0FBRyxRQUFBLENBQUE7QUFBSCxDQUFuQjs7QUFDQSxJQUFJLENBQUMsRUFBTCxDQUFRLFVBQVIsRUFBbUIsU0FBQTt5QkFBRyxHQUFHLENBQUUsV0FBVyxDQUFDLFlBQWpCLENBQThCO1FBQUEsSUFBQSxFQUFLLFFBQUw7S0FBOUI7QUFBSCxDQUFuQjs7QUFDQSxJQUFJLENBQUMsS0FBTCxDQUFXLE1BQVgsRUFBa0IsU0FBQTtXQUFHO1FBQUEsSUFBQSxFQUFNLElBQU47UUFBWSxPQUFBLEVBQVEsT0FBcEI7UUFBNkIsT0FBQSxFQUFRLE9BQXJDOztBQUFILENBQWxCOztBQUVBLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBakIsQ0FBb0IsY0FBcEIsRUFBbUMsU0FBQyxDQUFEO1dBQU8sQ0FBQyxDQUFDLFdBQUYsaUJBQWdCLEdBQUcsQ0FBRSxTQUFMLENBQUE7QUFBdkIsQ0FBbkM7O0FBQ0EsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFqQixDQUFvQixlQUFwQixFQUFvQyxTQUFDLENBQUQ7V0FBTyxDQUFDLENBQUMsV0FBRixHQUFnQixRQUFRLENBQUMsTUFBTSxDQUFDLGlCQUFoQixDQUFBLENBQW1DLENBQUM7QUFBM0QsQ0FBcEM7O0FBQ0EsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFqQixDQUFvQixjQUFwQixFQUFtQyxTQUFDLENBQUQsRUFBRyxDQUFIO0lBQy9CLElBQUEsQ0FBSyxjQUFMLEVBQW9CLFdBQXBCLEVBQTBCLENBQTFCO3lCQUNBLEdBQUcsQ0FBRSxTQUFMLENBQWUsQ0FBZjtBQUYrQixDQUFuQzs7QUFVQSxRQUFBLEdBQVcsU0FBQTtBQUVQLFFBQUE7SUFBQSxRQUFBLEdBQVcsU0FBQTtBQUVQLFlBQUE7UUFBQSxPQUFBLEdBQVUsTUFBTSxDQUFDLElBQVAsQ0FBWSxJQUFaLENBQWlCLENBQUMsTUFBbEIsQ0FBeUIsTUFBTSxDQUFDLElBQVAsQ0FBWSxPQUFaLENBQXpCO1FBQ1YsT0FBTyxDQUFDLElBQVIsQ0FBYSxTQUFDLENBQUQsRUFBRyxDQUFIO21CQUFTLENBQUMsQ0FBQyxXQUFGLENBQUEsQ0FBZSxDQUFDLGFBQWhCLENBQThCLENBQUMsQ0FBQyxXQUFGLENBQUEsQ0FBOUI7UUFBVCxDQUFiO1FBRUEsSUFBRyxHQUFIO21CQUNJLElBQUksQ0FBQyxNQUFMLENBQVksV0FBWixFQURKO1NBQUEsTUFBQTtZQUdJLFlBQUEsQ0FBQTtZQUNBLE9BQUEsR0FBVSxTQUFBO3FDQUFHLEdBQUcsQ0FBRSxJQUFMLENBQUE7WUFBSDtZQUNWLElBQUcsQ0FBSSxJQUFJLENBQUMsS0FBWjt1QkFDSSxVQUFBLENBQVcsT0FBWCxFQUFvQixJQUFwQixFQURKO2FBTEo7O0lBTE87SUFhWCxJQUFHLEtBQUssQ0FBQyxHQUFOLENBQUEsQ0FBSDtRQUNJLE9BQUEsR0FBVSxPQUFBLENBQVEsV0FBUjtlQUNWLE9BQUEsQ0FBUSxTQUFDLElBQUQ7WUFDSixJQUFHLEtBQUEsQ0FBTSxJQUFOLENBQUg7Z0JBQ0ksSUFBQSxHQUFPO3VCQUNQLFFBQUEsQ0FBQSxFQUZKOztRQURJLENBQVIsRUFGSjtLQUFBLE1BQUE7UUFPSSxPQUFBLEdBQVUsT0FBQSxDQUFRLFdBQVI7ZUFDVixPQUFBLENBQVEsU0FBQyxJQUFEO1lBQ0osSUFBQSxHQUFPO21CQUNQLFFBQUEsQ0FBQTtRQUZJLENBQVIsRUFSSjs7QUFmTzs7QUFpQ1gsT0FBQSxHQUFZOztBQUNaLFNBQUEsR0FBWTs7QUFDWixTQUFBLEdBQVk7O0FBRVosWUFBQSxHQUFlLFNBQUE7QUFFWCxRQUFBO0lBQUEsSUFBRyxLQUFLLENBQUMsR0FBTixDQUFBLENBQUg7UUFDSSxHQUFBLEdBQU0sT0FBQSxDQUFRLEtBQVI7UUFDTixHQUFBLEdBQU0sR0FBQSxDQUFJLE1BQUosRUFBVyxLQUFYLENBQWtCLENBQUEsQ0FBQTtRQUN4QixJQUFHLHlDQUFIO1lBQ0ksT0FBQSxHQUFVLFNBQUEsR0FBWSxLQUFLLENBQUMsSUFBTixDQUFXLEdBQUcsQ0FBQyxJQUFmLEVBRDFCO1NBSEo7S0FBQSxNQUFBO1FBTUksU0FBQSxHQUFZLE1BQU0sQ0FBQyxRQUFQLENBQW1CLFNBQUQsR0FBVyxzQkFBN0IsRUFBbUQ7WUFBQSxRQUFBLEVBQVMsTUFBVDtTQUFuRCxFQU5oQjs7SUFRQSxJQUFBLENBQUssc0JBQUwsRUFBNEIsT0FBNUIsRUFBcUMsY0FBckMsRUFBb0QsU0FBcEQ7SUFFQSxJQUFHLFdBQUg7UUFDSSxJQUFHLGVBQUg7WUFDSSxJQUFBLENBQUssOEJBQUwsRUFBb0MsT0FBcEM7WUFDQSxJQUFJLENBQUMsTUFBTCxDQUFZLFlBQVosRUFBeUIsT0FBekIsRUFGSjtTQUFBLE1BQUE7WUFJSSxJQUFBLENBQUssMEJBQUwsRUFBZ0MsT0FBaEM7WUFDQSxJQUFJLENBQUMsTUFBTCxDQUFZLGFBQVosRUFMSjs7ZUFPQSxJQUFJLENBQUMsTUFBTCxDQUFZLE1BQVosRUFSSjtLQUFBLE1BQUE7ZUFVSSxZQUFBLENBQUEsRUFWSjs7QUFaVzs7QUE4QmYsV0FBQSxHQUFjLFNBQUE7QUFFVixRQUFBO0lBQUEsSUFBRyxLQUFLLENBQUMsR0FBTixDQUFBLENBQUg7UUFDSSxJQUFHLFNBQUg7WUFDSSxHQUFBLEdBQU0sT0FBQSxDQUFRLEtBQVI7WUFDTixJQUFBLEdBQU8sR0FBQSxDQUFJLE1BQUosRUFBVyxTQUFYLENBQXNCLENBQUEsQ0FBQTtZQUM3QixtQkFBRyxJQUFJLENBQUUsYUFBVDtnQkFDSSxJQUFBLENBQUssVUFBTCxFQUFnQixJQUFJLENBQUMsSUFBckI7Z0JBQ0EsR0FBQSxDQUFJLFFBQUosRUFBYSxJQUFJLENBQUMsSUFBbEIsRUFGSjthQUhKOzs2QkFRQSxHQUFHLENBQUUsSUFBTCxDQUFBLFdBVEo7S0FBQSxNQUFBO1FBV0ksSUFBTyxpQkFBUDtpQ0FDSSxHQUFHLENBQUUsSUFBTCxDQUFBLFdBREo7U0FBQSxNQUFBO21CQUdJLE1BQU0sQ0FBQyxJQUFQLENBQWUsU0FBRCxHQUFXLHdCQUFYLEdBQW1DLFNBQWpELEVBQTZELFNBQUMsR0FBRDtxQ0FBUyxHQUFHLENBQUUsSUFBTCxDQUFBO1lBQVQsQ0FBN0QsRUFISjtTQVhKOztBQUZVOztBQXdCZCxZQUFBLEdBQWUsU0FBQTtJQUVYLGtCQUFHLEdBQUcsQ0FBRSxTQUFMLENBQUEsVUFBSDtRQUNJLElBQUcsS0FBSyxDQUFDLEdBQU4sQ0FBVSx3QkFBVixFQUFtQyxLQUFuQyxDQUFIO21CQUNJLEdBQUcsQ0FBQyxJQUFKLENBQUEsRUFESjtTQUFBLE1BQUE7bUJBR0ksSUFBSSxDQUFDLE1BQUwsQ0FBWSxhQUFaLEVBSEo7U0FESjtLQUFBLE1BQUE7UUFPSSxJQUFHLEtBQUssQ0FBQyxHQUFOLENBQUEsQ0FBSDtZQUNJLElBQU8sV0FBUDt1QkFDSSxZQUFBLENBQUEsRUFESjthQUFBLE1BQUE7Z0JBR0ksWUFBQSxDQUFBO3VCQUNBLEdBQUcsQ0FBQyxLQUFKLENBQUEsRUFKSjthQURKO1NBQUEsTUFBQTtZQU9JLFNBQUEsR0FBWSxPQUFBLENBQVEsV0FBUixDQUFvQixFQUFDLElBQUQ7bUJBQ2hDLFNBQUEsQ0FBVSxxSkFBVixFQUtTO2dCQUFBLElBQUEsRUFBSyxhQUFMO2FBTFQsRUFLNkIsU0FBQyxHQUFELEVBQUssSUFBTDtnQkFDckIsT0FBQSxHQUFVLE1BQUEsQ0FBTyxJQUFQLENBQVksQ0FBQyxJQUFiLENBQUE7Z0JBQ1YsSUFBQSxDQUFLLHNCQUFMLEVBQTRCLE9BQTVCO2dCQUNBLElBQU8sV0FBUDsyQkFDSSxZQUFBLENBQUEsRUFESjtpQkFBQSxNQUFBO29CQUdJLFlBQUEsQ0FBQTtvQkFDQSxHQUFHLENBQUMsSUFBSixDQUFBOzJCQUNBLEdBQUcsQ0FBQyxLQUFKLENBQUEsRUFMSjs7WUFIcUIsQ0FMN0IsRUFSSjtTQVBKOztBQUZXOztBQWdDZixZQUFBLEdBQWUsU0FBQTtXQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUMsbUJBQWhCLENBQUE7QUFBSDs7QUFRZixZQUFBLEdBQWUsU0FBQTtBQUVYLFFBQUE7SUFBQSxJQUFVLFdBQVY7QUFBQSxlQUFBOztJQUVBLEdBQUEsR0FBTSxJQUFJLGFBQUosQ0FDRjtRQUFBLEtBQUEsRUFBaUIsR0FBakI7UUFDQSxNQUFBLEVBQWlCLEdBRGpCO1FBRUEsTUFBQSxFQUFpQixJQUZqQjtRQUdBLFdBQUEsRUFBaUIsSUFIakI7UUFJQSxPQUFBLEVBQWlCLElBSmpCO1FBS0EsU0FBQSxFQUFpQixJQUxqQjtRQU1BLFdBQUEsRUFBaUIsSUFOakI7UUFPQSxLQUFBLEVBQWlCLEtBUGpCO1FBUUEsV0FBQSxFQUFpQixLQVJqQjtRQVNBLFdBQUEsRUFBaUIsS0FUakI7UUFVQSxRQUFBLEVBQWlCLEdBVmpCO1FBV0EsU0FBQSxFQUFpQixHQVhqQjtRQVlBLFFBQUEsRUFBaUIsR0FaakI7UUFhQSxTQUFBLEVBQWlCLEdBYmpCO1FBY0EsVUFBQSxFQUFpQixLQWRqQjtRQWVBLElBQUEsRUFBaUIsS0FmakI7UUFnQkEsY0FBQSxFQUNRO1lBQUEsV0FBQSxFQUF5QixLQUF6QjtZQUNBLGdCQUFBLEVBQXlCLEtBRHpCO1lBRUEsZUFBQSxFQUF5QixJQUZ6QjtZQUdBLHVCQUFBLEVBQXlCLElBSHpCO1NBakJSO0tBREU7SUF1Qk4sTUFBQSxHQUFTLEtBQUssQ0FBQyxHQUFOLENBQVUsUUFBVjtJQUNULElBQXdCLGNBQXhCO1FBQUEsR0FBRyxDQUFDLFNBQUosQ0FBYyxNQUFkLEVBQUE7O0lBQ0EsR0FBRyxDQUFDLE9BQUosQ0FBWSxTQUFBLEdBQVUsU0FBVixHQUFvQixhQUFoQztJQUVBLEdBQUcsQ0FBQyxFQUFKLENBQU8sUUFBUCxFQUFnQixXQUFoQjtJQUNBLEdBQUcsQ0FBQyxFQUFKLENBQU8sTUFBUCxFQUFnQixVQUFoQjtJQUNBLEdBQUcsQ0FBQyxFQUFKLENBQU8sZUFBUCxFQUF1QixTQUFBO1FBQ25CLFlBQUEsQ0FBQTtRQUNBLElBQUcsSUFBSSxDQUFDLEtBQVI7WUFDSSxHQUFHLENBQUMsV0FBVyxDQUFDLFlBQWhCLENBQTZCO2dCQUFBLElBQUEsRUFBSyxRQUFMO2FBQTdCLEVBREo7O1FBRUEsR0FBRyxDQUFDLElBQUosQ0FBQTtlQUNBLEdBQUcsQ0FBQyxLQUFKLENBQUE7SUFMbUIsQ0FBdkI7V0FNQTtBQXZDVzs7QUF5Q2YsVUFBQSxHQUFhLFNBQUE7SUFBRyxJQUFHLFdBQUg7ZUFBYSxLQUFLLENBQUMsR0FBTixDQUFVLFFBQVYsRUFBbUIsR0FBRyxDQUFDLFNBQUosQ0FBQSxDQUFuQixFQUFiOztBQUFIOztBQUViLFdBQUEsR0FBYzs7QUFFZCxXQUFBLEdBQWMsU0FBQyxLQUFEO0FBRVYsUUFBQTtJQUFBLFlBQUEsQ0FBYSxXQUFiO0lBQ0EsVUFBQSxHQUFhLFNBQUE7QUFDVCxZQUFBO1FBQUEsQ0FBQSxHQUFJLEdBQUcsQ0FBQyxTQUFKLENBQUE7UUFDSixJQUFHLENBQUMsQ0FBQyxLQUFGLEtBQVcsQ0FBQyxDQUFDLE1BQWhCO1lBQ0ksQ0FBQyxDQUFDLEtBQUYsR0FBVSxDQUFDLENBQUMsTUFBRixHQUFXLElBQUksQ0FBQyxHQUFMLENBQVMsQ0FBQyxDQUFDLEtBQVgsRUFBa0IsQ0FBQyxDQUFDLE1BQXBCO1lBQ3JCLEdBQUcsQ0FBQyxTQUFKLENBQWMsQ0FBZCxFQUZKOztlQUdBLFVBQUEsQ0FBQTtJQUxTO1dBTWIsV0FBQSxHQUFjLFVBQUEsQ0FBVyxVQUFYLEVBQXVCLEdBQXZCO0FBVEo7O0FBV2QsU0FBQSxHQUFZLFNBQUE7QUFFUixRQUFBO0lBQUEsSUFBRyxLQUFLLENBQUMsR0FBTixDQUFVLFFBQVYsRUFBbUIsTUFBbkIsQ0FBQSxLQUE4QixRQUFqQztRQUNJLEtBQUEsR0FBUTtRQUNSLEtBQUEsR0FBUTtRQUNSLEtBQUEsR0FBUSxPQUhaO0tBQUEsTUFBQTtRQUtJLEtBQUEsR0FBUTtRQUNSLEtBQUEsR0FBUTtRQUNSLEtBQUEsR0FBUSxPQVBaOztXQVNBLEtBQUEsQ0FDSTtRQUFBLEdBQUEsRUFBZSxTQUFELEdBQVcsbUJBQXpCO1FBQ0EsS0FBQSxFQUFZLEtBRFo7UUFFQSxTQUFBLEVBQVksS0FGWjtRQUdBLFVBQUEsRUFBWSxLQUhaO1FBSUEsSUFBQSxFQUFZLEdBSlo7UUFLQSxHQUFBLEVBQVksR0FMWjtLQURKO0FBWFE7O0FBbUJaLEdBQUcsQ0FBQyxFQUFKLENBQU8sbUJBQVAsRUFBMkIsU0FBQyxLQUFEO1dBQVcsS0FBSyxDQUFDLGNBQU4sQ0FBQTtBQUFYLENBQTNCOztBQVFBLEdBQUcsQ0FBQyxFQUFKLENBQU8sT0FBUCxFQUFlLFNBQUE7QUFFWCxRQUFBO0lBQUEsSUFBRyxxQ0FBSDtRQUVJLElBQUcsR0FBRyxDQUFDLHlCQUFKLENBQUEsQ0FBSDtZQUNJLEdBQUcsQ0FBQyxFQUFKLENBQU8saUJBQVAsRUFBeUIsWUFBekIsRUFESjtTQUFBLE1BQUE7WUFHSSxHQUFHLENBQUMsSUFBSixDQUFTLENBQVQsRUFISjtTQUZKOztJQU9BLElBQUEsR0FBTyxJQUFJLElBQUosQ0FBWSxTQUFELEdBQVcsa0JBQXRCO0lBQ1AsSUFBSSxDQUFDLEVBQUwsQ0FBUSxPQUFSLEVBQWdCLFlBQWhCO0lBRUEsSUFBRyxFQUFFLENBQUMsUUFBSCxDQUFBLENBQUEsS0FBaUIsUUFBcEI7UUFDSSxJQUFJLENBQUMsY0FBTCxDQUFvQixJQUFJLENBQUMsaUJBQUwsQ0FBdUI7WUFDdkM7Z0JBQUEsS0FBQSxFQUFPLE1BQVA7Z0JBQ0EsS0FBQSxFQUFPLFNBQUE7b0JBQUcsR0FBRyxDQUFDLElBQUosQ0FBUyxDQUFUOzJCQUFZLE9BQU8sQ0FBQyxJQUFSLENBQWEsQ0FBYjtnQkFBZixDQURQO2FBRHVDLEVBSXZDO2dCQUFBLEtBQUEsRUFBTyxPQUFQO2dCQUNBLEtBQUEsRUFBTyxTQURQO2FBSnVDLEVBT3ZDO2dCQUFBLEtBQUEsRUFBTyxVQUFQO2dCQUNBLEtBQUEsRUFBTyxZQURQO2FBUHVDO1NBQXZCLENBQXBCLEVBREo7OztZQVlRLENBQUUsSUFBVixDQUFBOztJQVFBLElBQUksQ0FBQyxrQkFBTCxDQUF3QixJQUFJLENBQUMsaUJBQUwsQ0FBdUI7UUFDM0M7WUFBQSxLQUFBLEVBQU8sR0FBRyxDQUFDLE9BQUosQ0FBQSxDQUFQO1lBQ0EsT0FBQSxFQUFTO2dCQUNMO29CQUFBLEtBQUEsRUFBTyxRQUFBLEdBQVMsR0FBRyxDQUFDLElBQXBCO29CQUNBLFdBQUEsRUFBYSxhQURiO29CQUVBLEtBQUEsRUFBTyxTQUFBOytCQUFHLFNBQUEsQ0FBQTtvQkFBSCxDQUZQO2lCQURLLEVBS0w7b0JBQUEsSUFBQSxFQUFNLFdBQU47aUJBTEssRUFPTDtvQkFBQSxLQUFBLEVBQU8sTUFBUDtvQkFDQSxXQUFBLEVBQWEsYUFEYjtvQkFFQSxLQUFBLEVBQU8sU0FBQTt3QkFDSCxVQUFBLENBQUE7d0JBQ0EsR0FBRyxDQUFDLElBQUosQ0FBUyxDQUFUOytCQUNBLE9BQU8sQ0FBQyxJQUFSLENBQWEsQ0FBYjtvQkFIRyxDQUZQO2lCQVBLO2FBRFQ7U0FEMkMsRUF1QjNDO1lBQUEsS0FBQSxFQUFPLFFBQVA7WUFDQSxPQUFBLEVBQVM7Z0JBQ0w7b0JBQUEsS0FBQSxFQUFhLGNBQWI7b0JBQ0EsV0FBQSxFQUFhLGFBRGI7b0JBRUEsS0FBQSxFQUFhLFNBQUE7NkNBQUcsR0FBRyxDQUFFLEtBQUwsQ0FBQTtvQkFBSCxDQUZiO2lCQURLLEVBS0w7b0JBQUEsSUFBQSxFQUFNLFdBQU47aUJBTEssRUFPTDtvQkFBQSxLQUFBLEVBQWEsZUFBYjtvQkFDQSxXQUFBLEVBQWEsaUJBRGI7b0JBRUEsS0FBQSxFQUFhLFNBQUE7K0JBQUcsWUFBQSxDQUFBO29CQUFILENBRmI7aUJBUEssRUFXTDtvQkFBQSxLQUFBLEVBQWEsaUJBQWI7b0JBQ0EsV0FBQSxFQUFhLGlCQURiO29CQUVBLEtBQUEsRUFBYSxTQUFBOzZDQUFHLEdBQUcsQ0FBRSxXQUFXLENBQUMsWUFBakIsQ0FBQTtvQkFBSCxDQUZiO2lCQVhLO2FBRFQ7U0F2QjJDO0tBQXZCLENBQXhCO0lBeUNBLEtBQUssQ0FBQyxJQUFOLENBQVc7UUFBQSxRQUFBLEVBQVM7WUFBQSxRQUFBLEVBQVMsSUFBVDtTQUFUO0tBQVg7SUFFQSxRQUFRLENBQUMsY0FBYyxDQUFDLFFBQXhCLENBQWlDLEtBQUssQ0FBQyxHQUFOLENBQVUsVUFBVixDQUFqQyxFQUF3RCxZQUF4RDtJQUVBLEVBQUUsQ0FBQyxhQUFILENBQWlCLE9BQWpCO0lBRUEsR0FBQSxHQUFNLE9BQUEsQ0FBUSxXQUFSO0lBQ04sSUFBRyxLQUFLLENBQUMsR0FBTixDQUFBLENBQUg7UUFDSSxPQUFBLEdBQVUsR0FBRyxDQUFDLFVBQUosQ0FBQSxFQURkO0tBQUEsTUFBQTtRQUdJLE9BQUEsR0FBVSxHQUFHLENBQUMsVUFBSixDQUFBLEVBSGQ7O1dBS0EsUUFBQSxDQUFBO0FBckZXLENBQWYiLCJzb3VyY2VzQ29udGVudCI6WyIjIyNcbjAwICAgICAwMCAgIDAwMDAwMDAgICAwMDAgIDAwMCAgIDAwMFxuMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgMDAwMCAgMDAwXG4wMDAwMDAwMDAgIDAwMDAwMDAwMCAgMDAwICAwMDAgMCAwMDBcbjAwMCAwIDAwMCAgMDAwICAgMDAwICAwMDAgIDAwMCAgMDAwMFxuMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgMDAwICAgMDAwXG4jIyNcblxueyBhYm91dCwgYXBwLCBhcmdzLCBjaGlsZHAsIGZzLCBrbG9nLCBvcywgb3Nhc2NyaXB0LCBwb3N0LCBwcmVmcywgc2xhc2gsIHNyY21hcCwgdmFsaWQsIHdpbiB9ID0gcmVxdWlyZSAna3hrJ1xuXG5wa2cgICAgICAgICAgID0gcmVxdWlyZSAnLi4vcGFja2FnZS5qc29uJ1xuZWxlY3Ryb24gICAgICA9IHJlcXVpcmUgJ2VsZWN0cm9uJ1xuXG5hcHAgICAgICAgICAgID0gZWxlY3Ryb24uYXBwXG5Ccm93c2VyV2luZG93ID0gZWxlY3Ryb24uQnJvd3NlcldpbmRvd1xuVHJheSAgICAgICAgICA9IGVsZWN0cm9uLlRyYXlcbk1lbnUgICAgICAgICAgPSBlbGVjdHJvbi5NZW51XG5jbGlwYm9hcmQgICAgID0gZWxlY3Ryb24uY2xpcGJvYXJkXG5pY29uRGlyICAgICAgID0gc2xhc2gucmVzb2x2ZSBcIiN7YXBwLmdldFBhdGgoJ3VzZXJEYXRhJyl9L2ljb25zXCJcblxud2luICAgICAgICAgICA9IG51bGxcbnRyYXkgICAgICAgICAgPSBudWxsXG5cbmFwcHMgICAgICAgICAgPSB7fVxuc2NyaXB0cyAgICAgICA9IHt9XG5hbGxLZXlzICAgICAgID0gW11cblxucHJvY2Vzcy5vbiAndW5jYXVnaHRFeGNlcHRpb24nIChlcnIpIC0+XG4gICAgc3JjbWFwLmxvZ0VyciBlcnIsICfwn5S7J1xuICAgIHRydWVcblxua2xvZy5zbG9nLmljb24gPSBzbGFzaC5maWxlVXJsIHNsYXNoLnJlc29sdmUgc2xhc2guam9pbiBfX2Rpcm5hbWUsICcuLicgJ2ltZycgJ21lbnVAMngucG5nJ1xuXG5hcHAuc2V0TmFtZSBwa2cucHJvZHVjdE5hbWVcblxuYXJncyA9IGFyZ3MuaW5pdCBcIlwiXCJcbiAgICB2ZXJib3NlICAgICBsb2cgdmVyYm9zZSAgICAgZmFsc2VcbiAgICBkZWJ1ZyAgICAgICBsb2cgZGVidWcgICAgICAgZmFsc2UgIC1EXG5cIlwiXCJcblxuIyAwMDAwMDAwMCAgICAwMDAwMDAwICAgIDAwMDAwMDAgIDAwMDAwMDAwMFxuIyAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgICAgICAgIDAwMCAgIFxuIyAwMDAwMDAwMCAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgICAgIDAwMCAgIFxuIyAwMDAgICAgICAgIDAwMCAgIDAwMCAgICAgICAwMDAgICAgIDAwMCAgIFxuIyAwMDAgICAgICAgICAwMDAwMDAwICAgMDAwMDAwMCAgICAgIDAwMCAgIFxuXG5wb3N0Lm9uICd3aW5sb2cnICAgICh0ZXh0KSAtPiBsb2cgXCI+Pj4gXCIgKyB0ZXh0XG5wb3N0Lm9uICdydW5TY3JpcHQnIChuYW1lKSAtPiBzY3JpcHRzW25hbWVdLmNiKClcbnBvc3Qub24gJ2hpZGVXaW4nICAtPiB3aW4/LmhpZGUoKVxucG9zdC5vbiAnY2FuY2VsJyAgIC0+IGFjdGl2YXRlQXBwKClcbnBvc3Qub24gJ2Fib3V0JyAgICAtPiBzaG93QWJvdXQoKVxucG9zdC5vbiAnZmluZEFwcHMnIC0+IGZpbmRBcHBzKClcbnBvc3Qub24gJ2RldlRvb2xzJyAtPiB3aW4/LndlYkNvbnRlbnRzLm9wZW5EZXZUb29scyBtb2RlOidkZXRhY2gnXG5wb3N0Lm9uR2V0ICdhcHBzJyAtPiBhcHBzOiBhcHBzLCBzY3JpcHRzOnNjcmlwdHMsIGFsbEtleXM6YWxsS2V5c1xuXG5lbGVjdHJvbi5pcGNNYWluLm9uICdnZXRXaW5Cb3VuZHMnIChlKSAtPiBlLnJldHVyblZhbHVlID0gd2luPy5nZXRCb3VuZHMoKVxuZWxlY3Ryb24uaXBjTWFpbi5vbiAnZ2V0U2NyZWVuU2l6ZScgKGUpIC0+IGUucmV0dXJuVmFsdWUgPSBlbGVjdHJvbi5zY3JlZW4uZ2V0UHJpbWFyeURpc3BsYXkoKS53b3JrQXJlYVNpemVcbmVsZWN0cm9uLmlwY01haW4ub24gJ3NldFdpbkJvdW5kcycgKGUsYikgLT4gXG4gICAga2xvZyAnc2V0V2luQm91bmRzJyB3aW4/LCBiXG4gICAgd2luPy5zZXRCb3VuZHMgYlxuXG4jIDAwMDAwMDAwICAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgICAgICAgICAgMDAwMDAwMCAgIDAwMDAwMDAwICAgMDAwMDAwMDAgICAgMDAwMDAwMCAgXG4jIDAwMCAgICAgICAwMDAgIDAwMDAgIDAwMCAgMDAwICAgMDAwICAgICAgICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAgICAgXG4jIDAwMDAwMCAgICAwMDAgIDAwMCAwIDAwMCAgMDAwICAgMDAwICAgICAgICAwMDAwMDAwMDAgIDAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAwMDAwICAgXG4jIDAwMCAgICAgICAwMDAgIDAwMCAgMDAwMCAgMDAwICAgMDAwICAgICAgICAwMDAgICAwMDAgIDAwMCAgICAgICAgMDAwICAgICAgICAgICAgIDAwMCAgXG4jIDAwMCAgICAgICAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgICAgICAgICAwMDAgICAwMDAgIDAwMCAgICAgICAgMDAwICAgICAgICAwMDAwMDAwICAgXG5cbmZpbmRBcHBzID0gLT5cblxuICAgIHNvcnRLZXlzID0gLT5cblxuICAgICAgICBhbGxLZXlzID0gT2JqZWN0LmtleXMoYXBwcykuY29uY2F0IE9iamVjdC5rZXlzKHNjcmlwdHMpXG4gICAgICAgIGFsbEtleXMuc29ydCAoYSxiKSAtPiBhLnRvTG93ZXJDYXNlKCkubG9jYWxlQ29tcGFyZSBiLnRvTG93ZXJDYXNlKClcbiAgICAgICAgXG4gICAgICAgIGlmIHdpblxuICAgICAgICAgICAgcG9zdC50b1dpbnMgJ2FwcHNGb3VuZCdcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgY3JlYXRlV2luZG93KClcbiAgICAgICAgICAgIGhpZGVXaW4gPSAtPiB3aW4/LmhpZGUoKVxuICAgICAgICAgICAgaWYgbm90IGFyZ3MuZGVidWdcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0IGhpZGVXaW4sIDEwMDBcbiAgICBcbiAgICBpZiBzbGFzaC53aW4oKVxuICAgICAgICBleGVGaW5kID0gcmVxdWlyZSAnLi9leGVmaW5kJ1xuICAgICAgICBleGVGaW5kIChleGVzKSAtPiBcbiAgICAgICAgICAgIGlmIHZhbGlkIGV4ZXNcbiAgICAgICAgICAgICAgICBhcHBzID0gZXhlc1xuICAgICAgICAgICAgICAgIHNvcnRLZXlzKClcbiAgICBlbHNlXG4gICAgICAgIGFwcEZpbmQgPSByZXF1aXJlICcuL2FwcGZpbmQnXG4gICAgICAgIGFwcEZpbmQgKGFwcGwpIC0+IFxuICAgICAgICAgICAgYXBwcyA9IGFwcGxcbiAgICAgICAgICAgIHNvcnRLZXlzKClcbiAgICAgICAgICAgIFxuIyAwMDAwMDAwICAgIDAwMDAwMDAgIDAwMDAwMDAwMCAgMDAwICAwMDAgICAwMDAgIDAwMDAwMDAwXG4jMDAwICAgMDAwICAwMDAgICAgICAgICAgMDAwICAgICAwMDAgIDAwMCAgIDAwMCAgMDAwXG4jMDAwMDAwMDAwICAwMDAgICAgICAgICAgMDAwICAgICAwMDAgICAwMDAgMDAwICAgMDAwMDAwMFxuIzAwMCAgIDAwMCAgMDAwICAgICAgICAgIDAwMCAgICAgMDAwICAgICAwMDAgICAgIDAwMFxuIzAwMCAgIDAwMCAgIDAwMDAwMDAgICAgIDAwMCAgICAgMDAwICAgICAgMCAgICAgIDAwMDAwMDAwXG5cbmFwcE5hbWUgICA9IG51bGxcbmFjdGl2ZUFwcCA9IG51bGxcbmFjdGl2ZVdpbiA9IG51bGxcblxuZ2V0QWN0aXZlQXBwID0gLT5cblxuICAgIGlmIHNsYXNoLndpbigpXG4gICAgICAgIHd4dyA9IHJlcXVpcmUgJ3d4dydcbiAgICAgICAgdG9wID0gd3h3KCdpbmZvJyAndG9wJylbMF1cbiAgICAgICAgaWYgdG9wPy5wYXRoP1xuICAgICAgICAgICAgYXBwTmFtZSA9IGFjdGl2ZUFwcCA9IHNsYXNoLmJhc2UgdG9wLnBhdGhcbiAgICBlbHNlXG4gICAgICAgIGFjdGl2ZUFwcCA9IGNoaWxkcC5leGVjU3luYyBcIiN7X19kaXJuYW1lfS8uLi9iaW4vYXBwc3dpdGNoIC1QXCIgZW5jb2Rpbmc6J3V0ZjgnXG5cbiAgICBrbG9nICdnZXRBY3RpdmVBcHAgYXBwTmFtZScgYXBwTmFtZSwgJy0+IGFjdGl2ZUFwcCcgYWN0aXZlQXBwICM/IGlmIGFyZ3MudmVyYm9zZVxuICAgICAgICBcbiAgICBpZiB3aW4/XG4gICAgICAgIGlmIGFwcE5hbWU/XG4gICAgICAgICAgICBrbG9nICdnZXRBY3RpdmVBcHAgcG9zdC5jdXJyZW50QXBwJyBhcHBOYW1lICNpZiBhcmdzLnZlcmJvc2VcbiAgICAgICAgICAgIHBvc3QudG9XaW5zICdjdXJyZW50QXBwJyBhcHBOYW1lXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGtsb2cgJ2dldEFjdGl2ZUFwcCBjbGVhclNlYXJjaCcgYXBwTmFtZSAjaWYgYXJncy52ZXJib3NlXG4gICAgICAgICAgICBwb3N0LnRvV2lucyAnY2xlYXJTZWFyY2gnXG4gICAgICAgICMga2xvZyAnZ2V0QWN0aXZlQXBwIGZhZGUnIGlmIGFyZ3MudmVyYm9zZVxuICAgICAgICBwb3N0LnRvV2lucyAnZmFkZSdcbiAgICBlbHNlXG4gICAgICAgIGNyZWF0ZVdpbmRvdygpXG5cbiMgIDAwMDAwMDAgICAgMDAwMDAwMCAgMDAwMDAwMDAwICAwMDAgIDAwMCAgIDAwMCAgIDAwMDAwMDAgICAwMDAwMDAwMDAgIDAwMDAwMDAwICBcbiMgMDAwICAgMDAwICAwMDAgICAgICAgICAgMDAwICAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAgICAwMDAgICAgIDAwMCAgICAgICBcbiMgMDAwMDAwMDAwICAwMDAgICAgICAgICAgMDAwICAgICAwMDAgICAwMDAgMDAwICAgMDAwMDAwMDAwICAgICAwMDAgICAgIDAwMDAwMDAgICBcbiMgMDAwICAgMDAwICAwMDAgICAgICAgICAgMDAwICAgICAwMDAgICAgIDAwMCAgICAgMDAwICAgMDAwICAgICAwMDAgICAgIDAwMCAgICAgICBcbiMgMDAwICAgMDAwICAgMDAwMDAwMCAgICAgMDAwICAgICAwMDAgICAgICAwICAgICAgMDAwICAgMDAwICAgICAwMDAgICAgIDAwMDAwMDAwICBcblxuYWN0aXZhdGVBcHAgPSAtPlxuXG4gICAgaWYgc2xhc2gud2luKClcbiAgICAgICAgaWYgYWN0aXZlV2luXG4gICAgICAgICAgICB3eHcgPSByZXF1aXJlICd3eHcnXG4gICAgICAgICAgICBpbmZvID0gd3h3KCdpbmZvJyBhY3RpdmVXaW4pWzBdXG4gICAgICAgICAgICBpZiBpbmZvPy5wYXRoXG4gICAgICAgICAgICAgICAga2xvZyAnYWN0aXZhdGUnIGluZm8ucGF0aFxuICAgICAgICAgICAgICAgIHd4dyAnbGF1bmNoJyBpbmZvLnBhdGhcbiAgICAgICAgICAgICAgICAjIHd4dyAncmFpc2UnIGluZm8ucGF0aFxuICAgICAgICAgICAgICAgICMgd3h3ICdmb2N1cycgaW5mby5wYXRoXG4gICAgICAgIHdpbj8uaGlkZSgpXG4gICAgZWxzZVxuICAgICAgICBpZiBub3QgYWN0aXZlQXBwP1xuICAgICAgICAgICAgd2luPy5oaWRlKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgY2hpbGRwLmV4ZWMgXCIje19fZGlybmFtZX0vLi4vYmluL2FwcHN3aXRjaCAtZnAgI3thY3RpdmVBcHB9XCIgKGVycikgLT4gd2luPy5oaWRlKClcblxuIzAwMCAgIDAwMCAgMDAwICAwMDAgICAwMDAgIDAwMDAwMDAgICAgIDAwMDAwMDAgICAwMDAgICAwMDBcbiMwMDAgMCAwMDAgIDAwMCAgMDAwMCAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwIDAgMDAwXG4jMDAwMDAwMDAwICAwMDAgIDAwMCAwIDAwMCAgMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMDAwMDAwMFxuIzAwMCAgIDAwMCAgMDAwICAwMDAgIDAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAwMDBcbiMwMCAgICAgMDAgIDAwMCAgMDAwICAgMDAwICAwMDAwMDAwICAgICAwMDAwMDAwICAgMDAgICAgIDAwXG5cbnRvZ2dsZVdpbmRvdyA9IC0+XG4gICAgXG4gICAgaWYgd2luPy5pc1Zpc2libGUoKVxuICAgICAgICBpZiBwcmVmcy5nZXQgJ2hpZGVPbkRvdWJsZUFjdGl2YXRpb24nIGZhbHNlXG4gICAgICAgICAgICB3aW4uaGlkZSgpXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHBvc3QudG9XaW5zICdvcGVuQ3VycmVudCdcbiAgICAgICAgICAgICMgYWN0aXZhdGVBcHAoKSBpZiBub3Qgc2xhc2gud2luKClcbiAgICBlbHNlXG4gICAgICAgIGlmIHNsYXNoLndpbigpXG4gICAgICAgICAgICBpZiBub3Qgd2luP1xuICAgICAgICAgICAgICAgIGNyZWF0ZVdpbmRvdygpXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgZ2V0QWN0aXZlQXBwKClcbiAgICAgICAgICAgICAgICB3aW4uZm9jdXMoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBvc2FzY3JpcHQgPSByZXF1aXJlKCdvc2FzY3JpcHQnKS5ldmFsXG4gICAgICAgICAgICBvc2FzY3JpcHQgXCJcIlwiXG4gICAgICAgICAgICAgICAgdGVsbCBhcHBsaWNhdGlvbiBcIlN5c3RlbSBFdmVudHNcIlxuICAgICAgICAgICAgICAgICAgICBzZXQgbiB0byBuYW1lIG9mIGZpcnN0IGFwcGxpY2F0aW9uIHByb2Nlc3Mgd2hvc2UgZnJvbnRtb3N0IGlzIHRydWVcbiAgICAgICAgICAgICAgICBlbmQgdGVsbFxuICAgICAgICAgICAgICAgIGRvIHNoZWxsIHNjcmlwdCBcImVjaG8gXCIgJiBuXG4gICAgICAgICAgICAgICAgXCJcIlwiLCB0eXBlOidBcHBsZVNjcmlwdCcsIChlcnIsbmFtZSkgLT5cbiAgICAgICAgICAgICAgICAgICAgYXBwTmFtZSA9IFN0cmluZyhuYW1lKS50cmltKClcbiAgICAgICAgICAgICAgICAgICAga2xvZyAndG9nZ2xlV2luZG93IGFwcE5hbWUnIGFwcE5hbWVcbiAgICAgICAgICAgICAgICAgICAgaWYgbm90IHdpbj9cbiAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZVdpbmRvdygpXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldEFjdGl2ZUFwcCgpXG4gICAgICAgICAgICAgICAgICAgICAgICB3aW4uc2hvdygpXG4gICAgICAgICAgICAgICAgICAgICAgICB3aW4uZm9jdXMoKVxuXG5yZWxvYWRXaW5kb3cgPSAtPiB3aW4ud2ViQ29udGVudHMucmVsb2FkSWdub3JpbmdDYWNoZSgpXG5cbiMgIDAwMDAwMDAgIDAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAwMDAwICAgMDAwMDAwMDAwICAwMDAwMDAwMCAgXG4jIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgICAgIDAwMCAgICAgMDAwICAgICAgIFxuIyAwMDAgICAgICAgMDAwMDAwMCAgICAwMDAwMDAwICAgMDAwMDAwMDAwICAgICAwMDAgICAgIDAwMDAwMDAgICBcbiMgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMCAgICAgMDAwICAgICAwMDAgICAgICAgXG4jICAwMDAwMDAwICAwMDAgICAwMDAgIDAwMDAwMDAwICAwMDAgICAwMDAgICAgIDAwMCAgICAgMDAwMDAwMDAgIFxuXG5jcmVhdGVXaW5kb3cgPSAtPlxuXG4gICAgcmV0dXJuIGlmIHdpbj9cblxuICAgIHdpbiA9IG5ldyBCcm93c2VyV2luZG93XG4gICAgICAgIHdpZHRoOiAgICAgICAgICAgMzAwXG4gICAgICAgIGhlaWdodDogICAgICAgICAgMzAwXG4gICAgICAgIGNlbnRlcjogICAgICAgICAgdHJ1ZVxuICAgICAgICBhbHdheXNPblRvcDogICAgIHRydWVcbiAgICAgICAgbW92YWJsZTogICAgICAgICB0cnVlXG4gICAgICAgIHJlc2l6YWJsZTogICAgICAgdHJ1ZVxuICAgICAgICB0cmFuc3BhcmVudDogICAgIHRydWVcbiAgICAgICAgZnJhbWU6ICAgICAgICAgICBmYWxzZVxuICAgICAgICBtYXhpbWl6YWJsZTogICAgIGZhbHNlXG4gICAgICAgIG1pbmltaXphYmxlOiAgICAgZmFsc2VcbiAgICAgICAgbWluV2lkdGg6ICAgICAgICAyMDBcbiAgICAgICAgbWluSGVpZ2h0OiAgICAgICAyMDBcbiAgICAgICAgbWF4V2lkdGg6ICAgICAgICA2MDBcbiAgICAgICAgbWF4SGVpZ2h0OiAgICAgICA2MDBcbiAgICAgICAgZnVsbHNjcmVlbjogICAgICBmYWxzZVxuICAgICAgICBzaG93OiAgICAgICAgICAgIGZhbHNlXG4gICAgICAgIHdlYlByZWZlcmVuY2VzOlxuICAgICAgICAgICAgICAgIHdlYlNlY3VyaXR5OiAgICAgICAgICAgICBmYWxzZVxuICAgICAgICAgICAgICAgIGNvbnRleHRJc29sYXRpb246ICAgICAgICBmYWxzZVxuICAgICAgICAgICAgICAgIG5vZGVJbnRlZ3JhdGlvbjogICAgICAgICB0cnVlXG4gICAgICAgICAgICAgICAgbm9kZUludGVncmF0aW9uSW5Xb3JrZXI6IHRydWVcblxuICAgIGJvdW5kcyA9IHByZWZzLmdldCAnYm91bmRzJ1xuICAgIHdpbi5zZXRCb3VuZHMgYm91bmRzIGlmIGJvdW5kcz9cbiAgICB3aW4ubG9hZFVSTCBcImZpbGU6Ly8je19fZGlybmFtZX0vaW5kZXguaHRtbFwiXG4gICAgIyB3aW4ub24gJ2Nsb3NlZCcgLT4gd2luID0gbnVsbFxuICAgIHdpbi5vbiAncmVzaXplJyBvbldpblJlc2l6ZVxuICAgIHdpbi5vbiAnbW92ZScgICBzYXZlQm91bmRzXG4gICAgd2luLm9uICdyZWFkeS10by1zaG93JyAtPlxuICAgICAgICBnZXRBY3RpdmVBcHAoKVxuICAgICAgICBpZiBhcmdzLmRlYnVnXG4gICAgICAgICAgICB3aW4ud2ViQ29udGVudHMub3BlbkRldlRvb2xzIG1vZGU6J2RldGFjaCdcbiAgICAgICAgd2luLnNob3coKVxuICAgICAgICB3aW4uZm9jdXMoKVxuICAgIHdpblxuXG5zYXZlQm91bmRzID0gLT4gaWYgd2luPyB0aGVuIHByZWZzLnNldCAnYm91bmRzJyB3aW4uZ2V0Qm91bmRzKClcblxuc3F1YXJlVGltZXIgPSBudWxsXG5cbm9uV2luUmVzaXplID0gKGV2ZW50KSAtPlxuICAgIFxuICAgIGNsZWFyVGltZW91dCBzcXVhcmVUaW1lclxuICAgIGFkanVzdFNpemUgPSAtPlxuICAgICAgICBiID0gd2luLmdldEJvdW5kcygpXG4gICAgICAgIGlmIGIud2lkdGggIT0gYi5oZWlnaHRcbiAgICAgICAgICAgIGIud2lkdGggPSBiLmhlaWdodCA9IE1hdGgubWluIGIud2lkdGgsIGIuaGVpZ2h0XG4gICAgICAgICAgICB3aW4uc2V0Qm91bmRzIGJcbiAgICAgICAgc2F2ZUJvdW5kcygpXG4gICAgc3F1YXJlVGltZXIgPSBzZXRUaW1lb3V0IGFkanVzdFNpemUsIDMwMFxuXG5zaG93QWJvdXQgPSAtPlxuICAgIFxuICAgIGlmIHByZWZzLmdldCgnc2NoZW1lJyAnZGFyaycpID09ICdicmlnaHQnXG4gICAgICAgIGNvbG9yID0gJyNmZmYnXG4gICAgICAgIHRleHRjID0gJyNkZGQnXG4gICAgICAgIGhpZ2hsID0gJyMwMDAnXG4gICAgZWxzZVxuICAgICAgICB0ZXh0YyA9ICcjNDQ0J1xuICAgICAgICBoaWdobCA9ICcjZmZmJ1xuICAgICAgICBjb2xvciA9ICcjMTExJ1xuICAgICAgICBcbiAgICBhYm91dFxuICAgICAgICBpbWc6ICAgICAgICBcIiN7X19kaXJuYW1lfS8uLi9pbWcvYWJvdXQucG5nXCJcbiAgICAgICAgY29sb3I6ICAgICAgdGV4dGNcbiAgICAgICAgaGlnaGxpZ2h0OiAgaGlnaGxcbiAgICAgICAgYmFja2dyb3VuZDogY29sb3JcbiAgICAgICAgc2l6ZTogICAgICAgMjAwXG4gICAgICAgIHBrZzogICAgICAgIHBrZ1xuXG5hcHAub24gJ3dpbmRvdy1hbGwtY2xvc2VkJyAoZXZlbnQpIC0+IGV2ZW50LnByZXZlbnREZWZhdWx0KClcblxuIzAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAwMDAwICAgMDAwMDAwMCAgICAwMDAgICAwMDBcbiMwMDAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgIDAwMCAwMDBcbiMwMDAwMDAwICAgIDAwMDAwMDAgICAwMDAwMDAwMDAgIDAwMCAgIDAwMCAgICAwMDAwMFxuIzAwMCAgIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAgICAwMDBcbiMwMDAgICAwMDAgIDAwMDAwMDAwICAwMDAgICAwMDAgIDAwMDAwMDAgICAgICAgMDAwXG5cbmFwcC5vbiAncmVhZHknIC0+XG5cbiAgICBpZiBhcHAucmVxdWVzdFNpbmdsZUluc3RhbmNlTG9jaz9cbiAgICAgICAgXG4gICAgICAgIGlmIGFwcC5yZXF1ZXN0U2luZ2xlSW5zdGFuY2VMb2NrKClcbiAgICAgICAgICAgIGFwcC5vbiAnc2Vjb25kLWluc3RhbmNlJyB0b2dnbGVXaW5kb3dcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgYXBwLmV4aXQgMFxuICAgIFxuICAgIHRyYXkgPSBuZXcgVHJheSBcIiN7X19kaXJuYW1lfS8uLi9pbWcvbWVudS5wbmdcIlxuICAgIHRyYXkub24gJ2NsaWNrJyB0b2dnbGVXaW5kb3dcbiAgICBcbiAgICBpZiBvcy5wbGF0Zm9ybSgpICE9ICdkYXJ3aW4nXG4gICAgICAgIHRyYXkuc2V0Q29udGV4dE1lbnUgTWVudS5idWlsZEZyb21UZW1wbGF0ZSBbXG4gICAgICAgICAgICBsYWJlbDogXCJRdWl0XCJcbiAgICAgICAgICAgIGNsaWNrOiAtPiBhcHAuZXhpdCAwOyBwcm9jZXNzLmV4aXQgMFxuICAgICAgICAsXG4gICAgICAgICAgICBsYWJlbDogXCJBYm91dFwiXG4gICAgICAgICAgICBjbGljazogc2hvd0Fib3V0XG4gICAgICAgICxcbiAgICAgICAgICAgIGxhYmVsOiBcIkFjdGl2YXRlXCJcbiAgICAgICAgICAgIGNsaWNrOiB0b2dnbGVXaW5kb3dcbiAgICAgICAgXVxuICAgICAgICBcbiAgICBhcHAuZG9jaz8uaGlkZSgpXG5cbiAgICAjIDAwICAgICAwMCAgMDAwMDAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwXG4gICAgIyAwMDAgICAwMDAgIDAwMCAgICAgICAwMDAwICAwMDAgIDAwMCAgIDAwMFxuICAgICMgMDAwMDAwMDAwICAwMDAwMDAwICAgMDAwIDAgMDAwICAwMDAgICAwMDBcbiAgICAjIDAwMCAwIDAwMCAgMDAwICAgICAgIDAwMCAgMDAwMCAgMDAwICAgMDAwXG4gICAgIyAwMDAgICAwMDAgIDAwMDAwMDAwICAwMDAgICAwMDAgICAwMDAwMDAwXG5cbiAgICBNZW51LnNldEFwcGxpY2F0aW9uTWVudSBNZW51LmJ1aWxkRnJvbVRlbXBsYXRlIFtcbiAgICAgICAgbGFiZWw6IGFwcC5nZXROYW1lKClcbiAgICAgICAgc3VibWVudTogW1xuICAgICAgICAgICAgbGFiZWw6IFwiQWJvdXQgI3twa2cubmFtZX1cIlxuICAgICAgICAgICAgYWNjZWxlcmF0b3I6ICdDbWRPckN0cmwrLidcbiAgICAgICAgICAgIGNsaWNrOiAtPiBzaG93QWJvdXQoKVxuICAgICAgICAsXG4gICAgICAgICAgICB0eXBlOiAnc2VwYXJhdG9yJ1xuICAgICAgICAsXG4gICAgICAgICAgICBsYWJlbDogJ1F1aXQnXG4gICAgICAgICAgICBhY2NlbGVyYXRvcjogJ0NtZE9yQ3RybCtRJ1xuICAgICAgICAgICAgY2xpY2s6IC0+XG4gICAgICAgICAgICAgICAgc2F2ZUJvdW5kcygpXG4gICAgICAgICAgICAgICAgYXBwLmV4aXQgMFxuICAgICAgICAgICAgICAgIHByb2Nlc3MuZXhpdCAwXG4gICAgICAgIF1cbiAgICAsXG4gICAgICAgICMgMDAwICAgMDAwICAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgICAgMDAwMDAwMCAgIDAwMCAgIDAwMFxuICAgICAgICAjIDAwMCAwIDAwMCAgMDAwICAwMDAwICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgMCAwMDBcbiAgICAgICAgIyAwMDAwMDAwMDAgIDAwMCAgMDAwIDAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMDAwXG4gICAgICAgICMgMDAwICAgMDAwICAwMDAgIDAwMCAgMDAwMCAgMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMFxuICAgICAgICAjIDAwICAgICAwMCAgMDAwICAwMDAgICAwMDAgIDAwMDAwMDAgICAgIDAwMDAwMDAgICAwMCAgICAgMDBcblxuICAgICAgICBsYWJlbDogJ1dpbmRvdydcbiAgICAgICAgc3VibWVudTogW1xuICAgICAgICAgICAgbGFiZWw6ICAgICAgICdDbG9zZSBXaW5kb3cnXG4gICAgICAgICAgICBhY2NlbGVyYXRvcjogJ0NtZE9yQ3RybCtXJ1xuICAgICAgICAgICAgY2xpY2s6ICAgICAgIC0+IHdpbj8uY2xvc2UoKVxuICAgICAgICAsXG4gICAgICAgICAgICB0eXBlOiAnc2VwYXJhdG9yJ1xuICAgICAgICAsXG4gICAgICAgICAgICBsYWJlbDogICAgICAgJ1JlbG9hZCBXaW5kb3cnXG4gICAgICAgICAgICBhY2NlbGVyYXRvcjogJ0NtZE9yQ3RybCtBbHQrTCdcbiAgICAgICAgICAgIGNsaWNrOiAgICAgICAtPiByZWxvYWRXaW5kb3coKVxuICAgICAgICAsXG4gICAgICAgICAgICBsYWJlbDogICAgICAgJ1RvZ2dsZSBEZXZUb29scydcbiAgICAgICAgICAgIGFjY2VsZXJhdG9yOiAnQ21kT3JDdHJsK0FsdCtJJ1xuICAgICAgICAgICAgY2xpY2s6ICAgICAgIC0+IHdpbj8ud2ViQ29udGVudHMub3BlbkRldlRvb2xzKClcbiAgICAgICAgXVxuICAgIF1cblxuICAgIHByZWZzLmluaXQgZGVmYXVsdHM6c2hvcnRjdXQ6J0YxJ1xuXG4gICAgZWxlY3Ryb24uZ2xvYmFsU2hvcnRjdXQucmVnaXN0ZXIgcHJlZnMuZ2V0KCdzaG9ydGN1dCcpLCB0b2dnbGVXaW5kb3dcblxuICAgIGZzLmVuc3VyZURpclN5bmMgaWNvbkRpclxuXG4gICAgc2NyID0gcmVxdWlyZSAnLi9zY3JpcHRzJ1xuICAgIGlmIHNsYXNoLndpbigpXG4gICAgICAgIHNjcmlwdHMgPSBzY3Iud2luU2NyaXB0cygpXG4gICAgZWxzZVxuICAgICAgICBzY3JpcHRzID0gc2NyLm1hY1NjcmlwdHMoKVxuICAgIFxuICAgIGZpbmRBcHBzKClcbiAgICAgICAgXG4gICAgICAgICAgICAiXX0= 428 | //# sourceURL=../coffee/main.coffee -------------------------------------------------------------------------------- /js/kappo.js: -------------------------------------------------------------------------------- 1 | // koffee 1.14.0 2 | 3 | /* 4 | 000 000 0000000 00000000 00000000 0000000 5 | 000 000 000 000 000 000 000 000 000 000 6 | 0000000 000000000 00000000 00000000 000 000 7 | 000 000 000 000 000 000 000 000 8 | 000 000 000 000 000 000 0000000 9 | */ 10 | var $, _, addToHistory, allKeys, appHist, apps, args, backspace, biggerWindow, blacklist, cancelSearchOrClose, childIndex, childp, clamp, clampBounds, clearSearch, clickID, clipboard, complete, currentApp, currentIndex, currentIsApp, currentIsScript, currentName, doSearch, downID, electron, elem, empty, fs, fuzzaldrin, fuzzy, getAppIcon, getBounds, getScriptIcon, history, iconDir, ipc, kerror, keyinfo, klog, kpos, listHistory, maximizeWindow, minimizeWindow, moveWindow, open, openCurrent, openDevTools, openInFinder, pkg, post, prefs, preventKeyRepeat, ref, results, scheme, screenSize, scripts, search, select, selectName, setBounds, setIcon, setStyle, showDots, sizeWindow, slash, smallerWindow, srcmap, stopEvent, sw, toggleAppToggle, toggleDoubleActivation, toggleWindowSize, valid, wheelAccu, winHide, winMain; 11 | 12 | ref = require('kxk'), post = ref.post, args = ref.args, srcmap = ref.srcmap, childIndex = ref.childIndex, setStyle = ref.setStyle, stopEvent = ref.stopEvent, keyinfo = ref.keyinfo, history = ref.history, valid = ref.valid, empty = ref.empty, childp = ref.childp, scheme = ref.scheme, clamp = ref.clamp, prefs = ref.prefs, elem = ref.elem, fs = ref.fs, slash = ref.slash, open = ref.open, klog = ref.klog, kerror = ref.kerror, kpos = ref.kpos, sw = ref.sw, $ = ref.$, _ = ref._; 13 | 14 | pkg = require('../package.json'); 15 | 16 | fuzzy = require('fuzzy'); 17 | 18 | fuzzaldrin = require('fuzzaldrin'); 19 | 20 | electron = require('electron'); 21 | 22 | clipboard = electron.clipboard; 23 | 24 | iconDir = slash.resolve((post.get('userData')) + "/icons"); 25 | 26 | ipc = electron.ipcRenderer; 27 | 28 | appHist = null; 29 | 30 | results = []; 31 | 32 | apps = {}; 33 | 34 | scripts = {}; 35 | 36 | allKeys = []; 37 | 38 | search = ''; 39 | 40 | currentName = ''; 41 | 42 | currentIndex = 0; 43 | 44 | post.on('mainlog', function(text) { 45 | return console.log(">>> " + text); 46 | }); 47 | 48 | post.on('appsFound', function() { 49 | var ref1; 50 | return ref1 = post.get('apps'), apps = ref1.apps, scripts = ref1.scripts, allKeys = ref1.allKeys, ref1; 51 | }); 52 | 53 | winMain = function() { 54 | var ref1; 55 | window.onerror = function(msg, source, line, col, err) { 56 | srcmap.logErr(err); 57 | return true; 58 | }; 59 | klog.slog.icon = slash.fileUrl(slash.join(__dirname, '..', 'img', 'menu@2x.png')); 60 | post.on('fade', function() { 61 | var restore; 62 | if (!slash.win()) { 63 | return; 64 | } 65 | $('#main').classList.remove('fade'); 66 | $('#main').style.opacity = 0; 67 | restore = function() { 68 | return $('#main').classList.add('fade'); 69 | }; 70 | return setTimeout(restore, 30); 71 | }); 72 | prefs.init(); 73 | ref1 = post.get('apps'), apps = ref1.apps, scripts = ref1.scripts, allKeys = ref1.allKeys; 74 | appHist = new history({ 75 | list: prefs.get('history', []), 76 | maxLength: prefs.get('maxHistoryLength', 10) 77 | }); 78 | return scheme.set(prefs.get('scheme', 'bright')); 79 | }; 80 | 81 | winHide = function() { 82 | if (!args.debug) { 83 | return post.toMain('hideWin'); 84 | } 85 | }; 86 | 87 | openCurrent = function() { 88 | var exe, info, ref1, wxw; 89 | ipc.send('closeAbout'); 90 | if (currentIndex > 0 && search.length) { 91 | prefs.set("search:" + search + ":" + currentName, 1 + prefs.get("search:" + search + ":" + currentName, 0)); 92 | } 93 | if (currentIsApp()) { 94 | addToHistory(); 95 | if (slash.win()) { 96 | wxw = require('wxw'); 97 | wxw('launch', apps[currentName]); 98 | return winHide(); 99 | } else { 100 | klog('openCurrent', currentName); 101 | return childp.exec("open -a \"" + apps[currentName] + "\"", function(err) { 102 | if (err != null) { 103 | return console.log("[ERROR] can't open " + apps[currentName] + " " + err); 104 | } 105 | }); 106 | } 107 | } else if (scripts[currentName] != null) { 108 | if (scripts[currentName].foreground != null) { 109 | exe = slash.file(scripts[currentName].foreground); 110 | addToHistory(); 111 | if (slash.win()) { 112 | wxw = require('wxw'); 113 | info = (ref1 = wxw('info', exe)) != null ? ref1[0] : void 0; 114 | if (info) { 115 | winHide(); 116 | wxw('show', exe); 117 | wxw('raise', exe); 118 | wxw('focus', exe); 119 | return; 120 | } 121 | } 122 | } 123 | if (scripts[currentName].exec != null) { 124 | return childp.exec(scripts[currentName].exec, function(err) { 125 | if (err != null) { 126 | return console.log("[ERROR] can't execute script " + scripts[currentName] + ": " + err); 127 | } 128 | }); 129 | } else { 130 | post.toMain('runScript', currentName); 131 | return winHide(); 132 | } 133 | } 134 | }; 135 | 136 | post.on('openCurrent', openCurrent); 137 | 138 | currentApp = function(appName) { 139 | var lastMatches, name, ref1, scriptMatches; 140 | if (empty(currentName)) { 141 | currentName = 'kappo'; 142 | } 143 | if (empty(appName)) { 144 | appName = 'kappo'; 145 | } 146 | lastMatches = currentName.toLowerCase() === appName.toLowerCase(); 147 | scriptMatches = (((ref1 = scripts[currentName]) != null ? ref1.foreground : void 0) != null) && slash.base(scripts[currentName].foreground).toLowerCase() === appName.toLowerCase(); 148 | if ((lastMatches || scriptMatches) && appHist.previous() && prefs.get('appToggle', true)) { 149 | listHistory(1); 150 | search = ''; 151 | } else { 152 | klog("currentApp " + appName + " -> " + currentName, lastMatches, scriptMatches); 153 | name = currentName; 154 | doSearch(''); 155 | if (!empty(name)) { 156 | selectName(name); 157 | } 158 | search = ''; 159 | $('appname').innerHTML = name; 160 | } 161 | return $('#main').classList.add('fade'); 162 | }; 163 | 164 | post.on('currentApp', currentApp); 165 | 166 | currentIsApp = (function(_this) { 167 | return function() { 168 | return !currentIsScript(); 169 | }; 170 | })(this); 171 | 172 | currentIsScript = function() { 173 | var ref1; 174 | return ((ref1 = results[currentIndex]) != null ? ref1.script : void 0) != null; 175 | }; 176 | 177 | toggleAppToggle = function() { 178 | return prefs.set('appToggle', !prefs.get('appToggle', true)); 179 | }; 180 | 181 | toggleDoubleActivation = function() { 182 | return prefs.set('hideOnDoubleActivation', !prefs.get('hideOnDoubleActivation', false)); 183 | }; 184 | 185 | listHistory = function(offset) { 186 | var h, index, j, len, ref1, result; 187 | if (offset == null) { 188 | offset = 0; 189 | } 190 | klog("listHistory " + offset, appHist.list); 191 | results = []; 192 | if (valid(appHist)) { 193 | ref1 = appHist.list; 194 | for (j = 0, len = ref1.length; j < len; j++) { 195 | h = ref1[j]; 196 | result = _.clone(h); 197 | if (result.string != null) { 198 | result.string; 199 | } else { 200 | result.string = result.name; 201 | } 202 | results.push(result); 203 | } 204 | } 205 | index = results.length - 1 - offset; 206 | klog("listHistory index " + index, results); 207 | select(index); 208 | return showDots(); 209 | }; 210 | 211 | addToHistory = function() { 212 | var result; 213 | if (empty(results[currentIndex])) { 214 | return; 215 | } 216 | result = _.clone(results[currentIndex]); 217 | delete result.string; 218 | appHist.add(result); 219 | return prefs.set('history', appHist.list); 220 | }; 221 | 222 | openInFinder = function() { 223 | return childp.spawn('osascript', ['-e', 'tell application "Finder"', '-e', "reveal POSIX file \"" + apps[currentName] + "\"", '-e', 'activate', '-e', 'end tell']); 224 | }; 225 | 226 | clearSearch = function() { 227 | if (results.length) { 228 | search = ''; 229 | results = [results[Math.min(currentIndex, results.length - 1)]]; 230 | results[0].string = currentName; 231 | $('appname').innerHTML = currentName; 232 | currentIndex = 0; 233 | return showDots(); 234 | } else { 235 | return doSearch(''); 236 | } 237 | }; 238 | 239 | post.on('clearSearch', clearSearch); 240 | 241 | getScriptIcon = function(scriptName) { 242 | return setIcon(scripts[scriptName].img); 243 | }; 244 | 245 | getAppIcon = function(appName) { 246 | var appIcon; 247 | if (slash.win()) { 248 | appIcon = require('./exeicon'); 249 | } else { 250 | appIcon = require('./appicon'); 251 | } 252 | return appIcon.get({ 253 | appPath: apps[appName], 254 | iconDir: iconDir, 255 | size: 512, 256 | cb: setIcon 257 | }); 258 | }; 259 | 260 | setIcon = function(iconPath) { 261 | return $('appicon').style.backgroundImage = "url(\"" + (slash.fileUrl(iconPath)) + "\")"; 262 | }; 263 | 264 | select = (function(_this) { 265 | return function(index) { 266 | var ref1, ref2; 267 | currentIndex = (index + results.length) % results.length; 268 | if (empty(results[currentIndex])) { 269 | console.log('dafuk? index:', index, 'results:', results); 270 | return; 271 | } 272 | currentName = results[currentIndex].name; 273 | $('appname').innerHTML = results[currentIndex].string; 274 | if ((ref1 = $('.current')) != null) { 275 | ref1.classList.remove('current'); 276 | } 277 | if ((ref2 = $("dot_" + currentIndex)) != null) { 278 | ref2.classList.add('current'); 279 | } 280 | if (currentIsApp()) { 281 | return getAppIcon(currentName); 282 | } else { 283 | return getScriptIcon(currentName); 284 | } 285 | }; 286 | })(this); 287 | 288 | selectName = function(name) { 289 | if (empty(name)) { 290 | return; 291 | } 292 | return select(results.findIndex(function(r) { 293 | return (r != null ? r.name.toLowerCase() : void 0) === name.toLowerCase(); 294 | })); 295 | }; 296 | 297 | showDots = function() { 298 | var dot, dotr, dots, i, j, ref1, results1, s, winWidth; 299 | dots = $('appdots'); 300 | dots.innerHTML = ''; 301 | winWidth = sw(); 302 | setStyle('#appname', 'font-size', (parseInt(10 + 2 * (winWidth - 100) / 100)) + "px"); 303 | if (results.length < 2) { 304 | return; 305 | } 306 | dotr = elem({ 307 | id: 'appdotr' 308 | }); 309 | dots.appendChild(dotr); 310 | s = winWidth / results.length; 311 | s = clamp(1, winWidth / 100, s); 312 | s = parseInt(s); 313 | setStyle('.appdot', 'width', s + "px"); 314 | setStyle('.appdot', 'height', s + "px"); 315 | results1 = []; 316 | for (i = j = 0, ref1 = results.length; 0 <= ref1 ? j < ref1 : j > ref1; i = 0 <= ref1 ? ++j : --j) { 317 | dot = elem('span', { 318 | "class": 'appdot', 319 | id: "dot_" + i 320 | }); 321 | if (i === currentIndex) { 322 | dot.classList.add('current'); 323 | } 324 | results1.push(dotr.appendChild(dot)); 325 | } 326 | return results1; 327 | }; 328 | 329 | blacklist = function() { 330 | var ignore; 331 | ignore = prefs.get('ignore', []); 332 | _.pull(ignore, apps[currentName]); 333 | _.pull(ignore, null); 334 | if (valid(apps[currentName])) { 335 | ignore.push(apps[currentName]); 336 | } else { 337 | console.log("can't ignore '" + currentName + "'"); 338 | } 339 | prefs.set('ignore', ignore); 340 | delete apps[currentName]; 341 | results.splice(currentIndex, 1); 342 | return select(currentIndex); 343 | }; 344 | 345 | doSearch = function(s) { 346 | var f, fuzzied, j, len, names, ps, r; 347 | search = s; 348 | names = allKeys; 349 | fuzzied = fuzzy.filter(search, names, { 350 | pre: '', 351 | post: '' 352 | }); 353 | fuzzied = _.sortBy(fuzzied, function(o) { 354 | return 2 - fuzzaldrin.score(o.original, search); 355 | }); 356 | if (search.length) { 357 | if (ps = prefs.get("search:" + search)) { 358 | fuzzied = _.sortBy(fuzzied, function(o) { 359 | var ref1; 360 | return Number.MAX_SAFE_INTEGER - ((ref1 = ps[o.original]) != null ? ref1 : 0); 361 | }); 362 | } 363 | } 364 | results = []; 365 | for (j = 0, len = fuzzied.length; j < len; j++) { 366 | f = fuzzied[j]; 367 | r = { 368 | name: f.original, 369 | string: f.string 370 | }; 371 | if (scripts[r.name]) { 372 | r.script = scripts[r.name]; 373 | } 374 | results.push(r); 375 | } 376 | if (valid(results)) { 377 | if (s === '') { 378 | if (slash.win()) { 379 | selectName('terminal'); 380 | } else { 381 | selectName('Finder'); 382 | } 383 | } else { 384 | select(0); 385 | } 386 | return showDots(); 387 | } else { 388 | $('appdots').innerHTML = ''; 389 | return $('appname').innerHTML = "" + search + ""; 390 | } 391 | }; 392 | 393 | complete = function(key) { 394 | return doSearch(search + key); 395 | }; 396 | 397 | backspace = function() { 398 | return doSearch(search.substr(0, search.length - 1)); 399 | }; 400 | 401 | cancelSearchOrClose = function() { 402 | ipc.send('closeAbout'); 403 | if (search.length) { 404 | return doSearch(''); 405 | } else { 406 | return post.toMain('cancel'); 407 | } 408 | }; 409 | 410 | clickID = downID = 0; 411 | 412 | window.onmousedown = function(e) { 413 | clickID += 1; 414 | return downID = clickID; 415 | }; 416 | 417 | window.onmouseup = function(e) { 418 | if (downID === clickID) { 419 | return openCurrent(); 420 | } 421 | }; 422 | 423 | window.onmousemove = function(e) { 424 | if (e.buttons) { 425 | return downID = -1; 426 | } 427 | }; 428 | 429 | window.onunload = function() { 430 | return document.onkeydown = null; 431 | }; 432 | 433 | window.onblur = function() { 434 | return winHide(); 435 | }; 436 | 437 | window.onresize = function() { 438 | return showDots(); 439 | }; 440 | 441 | wheelAccu = 0; 442 | 443 | window.onwheel = function(event) { 444 | var results1, results2; 445 | wheelAccu += (event.deltaX + event.deltaY) / 44; 446 | if (wheelAccu > 1) { 447 | select(currentIndex + 1 % results.length); 448 | results1 = []; 449 | while (wheelAccu > 1) { 450 | results1.push(wheelAccu -= 1); 451 | } 452 | return results1; 453 | } else if (wheelAccu < -1) { 454 | select(currentIndex + results.length - 1 % results.length); 455 | results2 = []; 456 | while (wheelAccu < -1) { 457 | results2.push(wheelAccu += 1); 458 | } 459 | return results2; 460 | } 461 | }; 462 | 463 | openDevTools = function() { 464 | return post.toMain('devTools'); 465 | }; 466 | 467 | screenSize = function() { 468 | var ss; 469 | ss = electron.ipcRenderer.sendSync('getScreenSize'); 470 | klog('screenSize', ss); 471 | return ss; 472 | }; 473 | 474 | clampBounds = function(b) { 475 | b.width = clamp(200, 600, b.width); 476 | b.height = clamp(200, 600, b.height); 477 | b.x = clamp(0, screenSize().width - b.width, b.x); 478 | b.y = clamp(0, screenSize().height - b.height, b.y); 479 | return b; 480 | }; 481 | 482 | getBounds = function() { 483 | var b; 484 | b = electron.ipcRenderer.sendSync('getWinBounds'); 485 | klog('getBounds', b); 486 | return b; 487 | }; 488 | 489 | setBounds = function(b) { 490 | electron.ipcRenderer.send('setWinBounds', b); 491 | return klog('setBounds', b); 492 | }; 493 | 494 | sizeWindow = function(d) { 495 | var b, cx; 496 | b = getBounds(); 497 | cx = b.x + b.width / 2; 498 | b.width += d; 499 | b.height += d; 500 | clampBounds(b); 501 | b.x = cx - b.width / 2; 502 | return setBounds(clampBounds(b)); 503 | }; 504 | 505 | moveWindow = function(dx, dy) { 506 | var b; 507 | b = getBounds(); 508 | b.x += dx; 509 | b.y += dy; 510 | return setBounds(clampBounds(b)); 511 | }; 512 | 513 | biggerWindow = function() { 514 | return sizeWindow(50); 515 | }; 516 | 517 | smallerWindow = function() { 518 | return sizeWindow(-50); 519 | }; 520 | 521 | minimizeWindow = function() { 522 | return setBounds({ 523 | x: screenSize().width / 2 - 100, 524 | y: 0, 525 | width: 200, 526 | height: 200 527 | }); 528 | }; 529 | 530 | maximizeWindow = function() { 531 | return setBounds({ 532 | x: screenSize().width / 2 - 300, 533 | y: 0, 534 | width: 600, 535 | height: 600 536 | }); 537 | }; 538 | 539 | toggleWindowSize = function() { 540 | if (getBounds().width > 200) { 541 | return minimizeWindow(); 542 | } else { 543 | return maximizeWindow(); 544 | } 545 | }; 546 | 547 | preventKeyRepeat = function() { 548 | return console.log('keyRepeat ahead!'); 549 | }; 550 | 551 | document.onkeydown = function(event) { 552 | var char, combo, key, mod, ref1; 553 | ref1 = keyinfo.forEvent(event), mod = ref1.mod, key = ref1.key, combo = ref1.combo, char = ref1.char; 554 | klog(combo); 555 | if ((char != null) && combo.length === 1) { 556 | complete(key); 557 | return; 558 | } 559 | switch (combo) { 560 | case 'f1': 561 | return preventKeyRepeat(); 562 | case 'delete': 563 | return blacklist(); 564 | case 'backspace': 565 | return backspace(); 566 | case 'command+backspace': 567 | case 'ctrl+backspace': 568 | return doSearch(''); 569 | case 'command+i': 570 | case 'ctrl+i': 571 | return scheme.toggle(); 572 | case 'esc': 573 | return cancelSearchOrClose(); 574 | case 'down': 575 | case 'right': 576 | return select(currentIndex + 1); 577 | case 'up': 578 | case 'left': 579 | return select(currentIndex - 1); 580 | case 'enter': 581 | return openCurrent(); 582 | case 'command+alt+i': 583 | case 'ctrl+alt+i': 584 | return openDevTools(); 585 | case 'command+=': 586 | case 'ctrl+=': 587 | return biggerWindow(); 588 | case 'command+-': 589 | case 'ctrl+-': 590 | return smallerWindow(); 591 | case 'command+r': 592 | case 'ctrl+r': 593 | return post.toMain('findApps'); 594 | case 'command+h': 595 | case 'alt+h': 596 | return listHistory(); 597 | case 'command+f': 598 | case 'ctrl+f': 599 | return openInFinder(); 600 | case 'command+t': 601 | case 'ctrl+t': 602 | return toggleAppToggle(); 603 | case 'command+d': 604 | case 'ctrl+d': 605 | return toggleDoubleActivation(); 606 | case 'alt+command+/': 607 | case 'alt+ctrl+/': 608 | return post.toMain('about'); 609 | case 'command+,': 610 | case 'ctrl+,': 611 | return open(prefs.store.file); 612 | case 'command+up': 613 | case 'ctrl+up': 614 | return moveWindow(0, -20); 615 | case 'command+down': 616 | case 'ctrl+down': 617 | return moveWindow(0, 20); 618 | case 'command+left': 619 | case 'ctrl+left': 620 | return moveWindow(-20, 0); 621 | case 'command+right': 622 | case 'ctrl+right': 623 | return moveWindow(20, 0); 624 | case 'command+0': 625 | case 'command+o': 626 | case 'ctrl+0': 627 | case 'ctrl+o': 628 | return toggleWindowSize(); 629 | } 630 | }; 631 | 632 | winMain(); 633 | 634 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2FwcG8uanMiLCJzb3VyY2VSb290IjoiLi4vY29mZmVlIiwic291cmNlcyI6WyJrYXBwby5jb2ZmZWUiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7OztBQUFBLElBQUE7O0FBUUEsTUFDZ0YsT0FBQSxDQUFRLEtBQVIsQ0FEaEYsRUFBRSxlQUFGLEVBQVEsZUFBUixFQUFjLG1CQUFkLEVBQXNCLDJCQUF0QixFQUFrQyx1QkFBbEMsRUFBNEMseUJBQTVDLEVBQXVELHFCQUF2RCxFQUFnRSxxQkFBaEUsRUFBeUUsaUJBQXpFLEVBQWdGLGlCQUFoRixFQUF1RixtQkFBdkYsRUFDRSxtQkFERixFQUNVLGlCQURWLEVBQ2lCLGlCQURqQixFQUN3QixlQUR4QixFQUM4QixXQUQ5QixFQUNrQyxpQkFEbEMsRUFDeUMsZUFEekMsRUFDK0MsZUFEL0MsRUFDcUQsbUJBRHJELEVBQzZELGVBRDdELEVBQ21FLFdBRG5FLEVBQ3VFLFNBRHZFLEVBQzBFOztBQUUxRSxHQUFBLEdBQWUsT0FBQSxDQUFRLGlCQUFSOztBQUNmLEtBQUEsR0FBZSxPQUFBLENBQVEsT0FBUjs7QUFDZixVQUFBLEdBQWUsT0FBQSxDQUFRLFlBQVI7O0FBQ2YsUUFBQSxHQUFlLE9BQUEsQ0FBUSxVQUFSOztBQUVmLFNBQUEsR0FBZSxRQUFRLENBQUM7O0FBQ3hCLE9BQUEsR0FBZSxLQUFLLENBQUMsT0FBTixDQUFnQixDQUFDLElBQUksQ0FBQyxHQUFMLENBQVMsVUFBVCxDQUFELENBQUEsR0FBc0IsUUFBdEM7O0FBQ2YsR0FBQSxHQUFlLFFBQVEsQ0FBQzs7QUFFeEIsT0FBQSxHQUFlOztBQUNmLE9BQUEsR0FBZTs7QUFDZixJQUFBLEdBQWU7O0FBQ2YsT0FBQSxHQUFlOztBQUNmLE9BQUEsR0FBZTs7QUFDZixNQUFBLEdBQWU7O0FBQ2YsV0FBQSxHQUFlOztBQUNmLFlBQUEsR0FBZTs7QUFFZixJQUFJLENBQUMsRUFBTCxDQUFRLFNBQVIsRUFBa0IsU0FBQyxJQUFEO1dBQVEsT0FB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UyxXQXhCVDtBQUFBLGFBd0JxQixXQXhCckI7QUFBQSxhQXdCb0MsUUF4QnBDO0FBQUEsYUF3QjZDLFFBeEI3QzttQkF3QjZELGdCQUFBLENBQUE7QUF4QjdEO0FBVmlCOztBQW9DckIsT0FBQSxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiIyMjXG4wMDAgICAwMDAgICAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAwMDAwMCAgICAwMDAwMDAwXG4wMDAgIDAwMCAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMFxuMDAwMDAwMCAgICAwMDAwMDAwMDAgIDAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAgICAwMDBcbjAwMCAgMDAwICAgMDAwICAgMDAwICAwMDAgICAgICAgIDAwMCAgICAgICAgMDAwICAgMDAwXG4wMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgICAgICAwMDAgICAgICAgICAwMDAwMDAwXG4jIyNcblxueyBwb3N0LCBhcmdzLCBzcmNtYXAsIGNoaWxkSW5kZXgsIHNldFN0eWxlLCBzdG9wRXZlbnQsIGtleWluZm8sIGhpc3RvcnksIHZhbGlkLCBlbXB0eSwgY2hpbGRwLFxuICBzY2hlbWUsIGNsYW1wLCBwcmVmcywgZWxlbSwgZnMsIHNsYXNoLCBvcGVuLCBrbG9nLCBrZXJyb3IsIGtwb3MsIHN3LCAkLCBfIH0gPSByZXF1aXJlICdreGsnXG5cbnBrZyAgICAgICAgICA9IHJlcXVpcmUgJy4uL3BhY2thZ2UuanNvbidcbmZ1enp5ICAgICAgICA9IHJlcXVpcmUgJ2Z1enp5J1xuZnV6emFsZHJpbiAgID0gcmVxdWlyZSAnZnV6emFsZHJpbidcbmVsZWN0cm9uICAgICA9IHJlcXVpcmUgJ2VsZWN0cm9uJ1xuXG5jbGlwYm9hcmQgICAgPSBlbGVjdHJvbi5jbGlwYm9hcmRcbmljb25EaXIgICAgICA9IHNsYXNoLnJlc29sdmUgXCIje3Bvc3QuZ2V0KCd1c2VyRGF0YScpfS9pY29uc1wiXG5pcGMgICAgICAgICAgPSBlbGVjdHJvbi5pcGNSZW5kZXJlclxuICAgIFxuYXBwSGlzdCAgICAgID0gbnVsbFxucmVzdWx0cyAgICAgID0gW11cbmFwcHMgICAgICAgICA9IHt9XG5zY3JpcHRzICAgICAgPSB7fVxuYWxsS2V5cyAgICAgID0gW11cbnNlYXJjaCAgICAgICA9ICcnXG5jdXJyZW50TmFtZSAgPSAnJ1xuY3VycmVudEluZGV4ID0gMFxuXG5wb3N0Lm9uICdtYWlubG9nJyAodGV4dCkgLT4gbG9nIFwiPj4+IFwiICsgdGV4dFxucG9zdC5vbiAnYXBwc0ZvdW5kJyAtPiB7IGFwcHMsIHNjcmlwdHMsIGFsbEtleXMgfSA9IHBvc3QuZ2V0ICdhcHBzJ1xuXG4jIDAwMCAgIDAwMCAgMDAwICAwMDAgICAwMDAgIDAwICAgICAwMCAgIDAwMDAwMDAgICAwMDAgIDAwMCAgIDAwMFxuIyAwMDAgMCAwMDAgIDAwMCAgMDAwMCAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAwMDAwICAwMDBcbiMgMDAwMDAwMDAwICAwMDAgIDAwMCAwIDAwMCAgMDAwMDAwMDAwICAwMDAwMDAwMDAgIDAwMCAgMDAwIDAgMDAwXG4jIDAwMCAgIDAwMCAgMDAwICAwMDAgIDAwMDAgIDAwMCAwIDAwMCAgMDAwICAgMDAwICAwMDAgIDAwMCAgMDAwMFxuIyAwMCAgICAgMDAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAwMDAgICAwMDBcblxud2luTWFpbiA9IC0+XG5cbiAgICB3aW5kb3cub25lcnJvciA9IChtc2csIHNvdXJjZSwgbGluZSwgY29sLCBlcnIpIC0+XG4gICAgICAgIHNyY21hcC5sb2dFcnIgZXJyXG4gICAgICAgIHRydWVcbiAgICBcbiAgICBrbG9nLnNsb2cuaWNvbiA9IHNsYXNoLmZpbGVVcmwgc2xhc2guam9pbiBfX2Rpcm5hbWUsICcuLicgJ2ltZycgJ21lbnVAMngucG5nJ1xuICAgIFxuICAgIHBvc3Qub24gJ2ZhZGUnIC0+XG4gICAgICAgIFxuICAgICAgICBpZiBub3Qgc2xhc2gud2luKClcbiAgICAgICAgICAgICMgd2luLnNob3coKVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICBcbiAgICAgICAgIyBbeCx5XSA9IHdpbi5nZXRQb3NpdGlvbigpICAgICAjIGVuYWJsZSBzbW9vdGggZmFkZSBvbiB3aW5kb3dzOlxuICAgICAgICAjIHdpbi5zZXRQb3NpdGlvbiAtMTAwMDAsLTEwMDAwICMgbW92ZSB3aW5kb3cgb2Zmc2NyZWVuIGJlZm9yZSBzaG93XG4gICAgICAgICMgd2luLnNob3coKVxuICAgICAgICAkKCcjbWFpbicpLmNsYXNzTGlzdC5yZW1vdmUgJ2ZhZGUnXG4gICAgICAgICQoJyNtYWluJykuc3R5bGUub3BhY2l0eSA9IDBcbiAgICAgICAgXG4gICAgICAgIHJlc3RvcmUgPSAtPiBcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgIyBpZiB4IDwgLTEwIG9yIHkgPCAtMTAgIyBrZXkgcmVwZWF0IGhpY2t1cCAnZml4J1xuICAgICAgICAgICAgICAgICMgYiA9IHdpbi5nZXRCb3VuZHMoKVxuICAgICAgICAgICAgICAgICMgeCA9IChzY3JlZW5TaXplKCkud2lkdGggLSBiLndpZHRoKS8yXG4gICAgICAgICAgICAgICAgIyB5ID0gMFxuICAgICAgICAgICAgIyBlbHNlXG4gICAgICAgICAgICAgICAgIyB3aW4uc2V0UG9zaXRpb24geCx5XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAkKCcjbWFpbicpLmNsYXNzTGlzdC5hZGQgJ2ZhZGUnXG4gICAgICAgICAgICBcbiAgICAgICAgc2V0VGltZW91dCByZXN0b3JlLCAzMCAjIGdpdmUgd2luZG93cyBzb21lIHRpbWUgdG8gZG8gaXQncyBmbGlja2VyaW5nXG4gICAgICAgIFxuICAgIHByZWZzLmluaXQoKVxuXG4gICAgeyBhcHBzLCBzY3JpcHRzLCBhbGxLZXlzIH0gPSBwb3N0LmdldCAnYXBwcydcblxuICAgIGFwcEhpc3QgPSBuZXcgaGlzdG9yeVxuICAgICAgICBsaXN0OiAgICAgIHByZWZzLmdldCAnaGlzdG9yeScgW11cbiAgICAgICAgbWF4TGVuZ3RoOiBwcmVmcy5nZXQgJ21heEhpc3RvcnlMZW5ndGgnIDEwXG5cbiAgICBzY2hlbWUuc2V0IHByZWZzLmdldCAnc2NoZW1lJyAnYnJpZ2h0J1xuICAgIFxud2luSGlkZSA9IC0+IFxuXG4gICAgaWYgbm90IGFyZ3MuZGVidWdcbiAgICAgICAgcG9zdC50b01haW4gJ2hpZGVXaW4nXG4gICAgXG4jICAwMDAwMDAwICAgMDAwMDAwMDAgICAwMDAwMDAwMCAgMDAwICAgMDAwXG4jIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAgICAgMDAwMCAgMDAwXG4jIDAwMCAgIDAwMCAgMDAwMDAwMDAgICAwMDAwMDAwICAgMDAwIDAgMDAwXG4jIDAwMCAgIDAwMCAgMDAwICAgICAgICAwMDAgICAgICAgMDAwICAwMDAwXG4jICAwMDAwMDAwICAgMDAwICAgICAgICAwMDAwMDAwMCAgMDAwICAgMDAwXG5cbm9wZW5DdXJyZW50ID0gLT5cblxuICAgIGlwYy5zZW5kICdjbG9zZUFib3V0J1xuICAgIFxuICAgIGlmIGN1cnJlbnRJbmRleCA+IDAgYW5kIHNlYXJjaC5sZW5ndGhcbiAgICAgICAgcHJlZnMuc2V0IFwic2VhcmNoOiN7c2VhcmNofToje2N1cnJlbnROYW1lfVwiLCAxICsgcHJlZnMuZ2V0IFwic2VhcmNoOiN7c2VhcmNofToje2N1cnJlbnROYW1lfVwiIDBcblxuICAgIGlmIGN1cnJlbnRJc0FwcCgpXG5cbiAgICAgICAgYWRkVG9IaXN0b3J5KClcbiAgICAgICAgXG4gICAgICAgIGlmIHNsYXNoLndpbigpXG5cbiAgICAgICAgICAgICMga2xvZyAnbGF1bmNoJyBjdXJyZW50TmFtZSwgYXBwc1tjdXJyZW50TmFtZV1cbiAgICAgICAgICAgIHd4dyA9IHJlcXVpcmUgJ3d4dydcbiAgICAgICAgICAgIHd4dyAnbGF1bmNoJyBhcHBzW2N1cnJlbnROYW1lXVxuICAgICAgICAgICAgd2luSGlkZSgpXG5cbiAgICAgICAgZWxzZVxuICAgICAgICAgICAga2xvZyAnb3BlbkN1cnJlbnQnIGN1cnJlbnROYW1lXG4gICAgICAgICAgICBjaGlsZHAuZXhlYyBcIm9wZW4gLWEgXFxcIiN7YXBwc1tjdXJyZW50TmFtZV19XFxcIlwiIChlcnIpIC0+XG4gICAgICAgICAgICAgICAgaWYgZXJyPyB0aGVuIGxvZyBcIltFUlJPUl0gY2FuJ3Qgb3BlbiAje2FwcHNbY3VycmVudE5hbWVdfSAje2Vycn1cIlxuICAgICAgICAgICAgICAgIFxuICAgIGVsc2UgaWYgc2NyaXB0c1tjdXJyZW50TmFtZV0/XG4gICAgICAgIFxuICAgICAgICBpZiBzY3JpcHRzW2N1cnJlbnROYW1lXS5mb3JlZ3JvdW5kP1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBleGUgPSBzbGFzaC5maWxlIHNjcmlwdHNbY3VycmVudE5hbWVdLmZvcmVncm91bmRcbiAgICAgICAgICAgIGFkZFRvSGlzdG9yeSgpXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIHNsYXNoLndpbigpXG4gICAgICAgICAgICAgICAgd3h3ID0gcmVxdWlyZSAnd3h3J1xuICAgICAgICAgICAgICAgIGluZm8gPSB3eHcoJ2luZm8nIGV4ZSk/WzBdXG4gICAgICAgICAgICAgICAgaWYgaW5mb1xuICAgICAgICAgICAgICAgICAgICB3aW5IaWRlKClcbiAgICAgICAgICAgICAgICAgICAgd3h3ICdzaG93JyAgZXhlXG4gICAgICAgICAgICAgICAgICAgIHd4dyAncmFpc2UnIGV4ZVxuICAgICAgICAgICAgICAgICAgICB3eHcgJ2ZvY3VzJyBleGVcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIFxuICAgICAgICBpZiBzY3JpcHRzW2N1cnJlbnROYW1lXS5leGVjP1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBjaGlsZHAuZXhlYyBzY3JpcHRzW2N1cnJlbnROYW1lXS5leGVjLCAoZXJyKSAtPlxuICAgICAgICAgICAgICAgIGlmIGVycj8gdGhlbiBsb2cgXCJbRVJST1JdIGNhbid0IGV4ZWN1dGUgc2NyaXB0ICN7c2NyaXB0c1tjdXJyZW50TmFtZV19OiAje2Vycn1cIlxuICAgICAgICAgICAgICAgIFxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBwb3N0LnRvTWFpbiAncnVuU2NyaXB0JyBjdXJyZW50TmFtZVxuICAgICAgICAgICAgd2luSGlkZSgpXG5cbnBvc3Qub24gJ29wZW5DdXJyZW50JyAgb3BlbkN1cnJlbnRcblxuIyAgMDAwMDAwMCAgMDAwICAgMDAwICAwMDAwMDAwMCAgIDAwMDAwMDAwICAgMDAwMDAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMDAwXG4jIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAgICAgMDAwMCAgMDAwICAgICAwMDBcbiMgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgICAwMDAwMDAwICAgIDAwMDAwMDAgICAwMDAgMCAwMDAgICAgIDAwMFxuIyAwMDAgICAgICAgMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgICAgIDAwMCAgMDAwMCAgICAgMDAwXG4jICAwMDAwMDAwICAgMDAwMDAwMCAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAwMDAwMCAgMDAwICAgMDAwICAgICAwMDBcblxuY3VycmVudEFwcCA9IChhcHBOYW1lKSAtPlxuXG4gICAgY3VycmVudE5hbWUgICA9ICdrYXBwbycgaWYgZW1wdHkgY3VycmVudE5hbWVcbiAgICBhcHBOYW1lICAgICAgID0gJ2thcHBvJyBpZiBlbXB0eSBhcHBOYW1lXG4gICAgbGFzdE1hdGNoZXMgICA9IGN1cnJlbnROYW1lLnRvTG93ZXJDYXNlKCkgPT0gYXBwTmFtZS50b0xvd2VyQ2FzZSgpXG4gICAgc2NyaXB0TWF0Y2hlcyA9IHNjcmlwdHNbY3VycmVudE5hbWVdPy5mb3JlZ3JvdW5kPyBhbmQgc2xhc2guYmFzZShzY3JpcHRzW2N1cnJlbnROYW1lXS5mb3JlZ3JvdW5kKS50b0xvd2VyQ2FzZSgpID09IGFwcE5hbWUudG9Mb3dlckNhc2UoKVxuICAgICAgICBcbiAgICBpZiAobGFzdE1hdGNoZXMgb3Igc2NyaXB0TWF0Y2hlcykgYW5kIGFwcEhpc3QucHJldmlvdXMoKSBhbmQgcHJlZnMuZ2V0ICdhcHBUb2dnbGUnIHRydWVcbiAgICAgICAgbGlzdEhpc3RvcnkgMVxuICAgICAgICBzZWFyY2ggPSAnJ1xuICAgIGVsc2VcbiAgICAgICAga2xvZyBcImN1cnJlbnRBcHAgI3thcHBOYW1lfSAtPiAje2N1cnJlbnROYW1lfVwiIGxhc3RNYXRjaGVzLCBzY3JpcHRNYXRjaGVzXG4gICAgICAgIG5hbWUgPSBjdXJyZW50TmFtZVxuICAgICAgICBkb1NlYXJjaCAnJ1xuICAgICAgICBzZWxlY3ROYW1lIG5hbWUgaWYgbm90IGVtcHR5IG5hbWVcbiAgICAgICAgc2VhcmNoID0gJydcbiAgICAgICAgJCgnYXBwbmFtZScpLmlubmVySFRNTCA9IG5hbWVcbiAgICAgICAgXG4gICAgJCgnI21haW4nKS5jbGFzc0xpc3QuYWRkICdmYWRlJ1xuXG5wb3N0Lm9uICdjdXJyZW50QXBwJyBjdXJyZW50QXBwXG5cbmN1cnJlbnRJc0FwcCA9ID0+IG5vdCBjdXJyZW50SXNTY3JpcHQoKVxuY3VycmVudElzU2NyaXB0ID0gLT4gcmVzdWx0c1tjdXJyZW50SW5kZXhdPy5zY3JpcHQ/XG5cbiMgMDAwMDAwMDAwICAgMDAwMDAwMCAgICAwMDAwMDAwICAgIDAwMDAwMDAgICAwMDAgICAgICAwMDAwMDAwMCAgXG4jICAgIDAwMCAgICAgMDAwICAgMDAwICAwMDAgICAgICAgIDAwMCAgICAgICAgMDAwICAgICAgMDAwICAgICAgIFxuIyAgICAwMDAgICAgIDAwMCAgIDAwMCAgMDAwICAwMDAwICAwMDAgIDAwMDAgIDAwMCAgICAgIDAwMDAwMDAgICBcbiMgICAgMDAwICAgICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAgICAwMDAgICAgICAgXG4jICAgIDAwMCAgICAgIDAwMDAwMDAgICAgMDAwMDAwMCAgICAwMDAwMDAwICAgMDAwMDAwMCAgMDAwMDAwMDAgIFxuXG50b2dnbGVBcHBUb2dnbGUgPSAtPlxuICAgIFxuICAgIHByZWZzLnNldCAnYXBwVG9nZ2xlJyBub3QgcHJlZnMuZ2V0ICdhcHBUb2dnbGUnIHRydWVcbiAgICBcbnRvZ2dsZURvdWJsZUFjdGl2YXRpb24gPSAtPlxuXG4gICAgcHJlZnMuc2V0ICdoaWRlT25Eb3VibGVBY3RpdmF0aW9uJywgbm90IHByZWZzLmdldCAnaGlkZU9uRG91YmxlQWN0aXZhdGlvbicsIGZhbHNlXG4gICAgXG4jIDAwMCAgIDAwMCAgMDAwICAgMDAwMDAwMCAgMDAwMDAwMDAwICAgMDAwMDAwMCAgIDAwMDAwMDAwICAgMDAwICAgMDAwXG4jIDAwMCAgIDAwMCAgMDAwICAwMDAgICAgICAgICAgMDAwICAgICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgIDAwMCAwMDBcbiMgMDAwMDAwMDAwICAwMDAgIDAwMDAwMDAgICAgICAwMDAgICAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgICAgIDAwMDAwXG4jIDAwMCAgIDAwMCAgMDAwICAgICAgIDAwMCAgICAgMDAwICAgICAwMDAgICAwMDAgIDAwMCAgIDAwMCAgICAgMDAwXG4jIDAwMCAgIDAwMCAgMDAwICAwMDAwMDAwICAgICAgMDAwICAgICAgMDAwMDAwMCAgIDAwMCAgIDAwMCAgICAgMDAwXG5cbmxpc3RIaXN0b3J5ID0gKG9mZnNldD0wKSAtPlxuICAgIGtsb2cgXCJsaXN0SGlzdG9yeSAje29mZnNldH1cIiBhcHBIaXN0Lmxpc3RcbiAgICByZXN1bHRzID0gW11cbiAgICBpZiB2YWxpZCBhcHBIaXN0XG4gICAgICAgIGZvciBoIGluIGFwcEhpc3QubGlzdFxuICAgICAgICAgICAgcmVzdWx0ID0gXy5jbG9uZSBoXG4gICAgICAgICAgICByZXN1bHQuc3RyaW5nID89IHJlc3VsdC5uYW1lXG4gICAgICAgICAgICByZXN1bHRzLnB1c2ggcmVzdWx0XG4gICAgaW5kZXggPSByZXN1bHRzLmxlbmd0aCAtIDEgLSBvZmZzZXRcbiAgICBrbG9nIFwibGlzdEhpc3RvcnkgaW5kZXggI3tpbmRleH1cIiByZXN1bHRzXG4gICAgc2VsZWN0IGluZGV4XG4gICAgc2hvd0RvdHMoKVxuXG5hZGRUb0hpc3RvcnkgPSAtPlxuICAgIFxuICAgIHJldHVybiBpZiBlbXB0eSByZXN1bHRzW2N1cnJlbnRJbmRleF1cbiAgICBcbiAgICByZXN1bHQgPSBfLmNsb25lIHJlc3VsdHNbY3VycmVudEluZGV4XVxuICAgIGRlbGV0ZSByZXN1bHQuc3RyaW5nXG4gICAgYXBwSGlzdC5hZGQgcmVzdWx0XG4gICAgcHJlZnMuc2V0ICdoaXN0b3J5JyBhcHBIaXN0Lmxpc3RcbiAgICBcbm9wZW5JbkZpbmRlciA9ICgpIC0+XG4gICAgXG4gICAgY2hpbGRwLnNwYXduICdvc2FzY3JpcHQnLCBbXG4gICAgICAgICctZScsICd0ZWxsIGFwcGxpY2F0aW9uIFwiRmluZGVyXCInLFxuICAgICAgICAnLWUnLCBcInJldmVhbCBQT1NJWCBmaWxlIFxcXCIje2FwcHNbY3VycmVudE5hbWVdfVxcXCJcIixcbiAgICAgICAgJy1lJywgJ2FjdGl2YXRlJyxcbiAgICAgICAgJy1lJywgJ2VuZCB0ZWxsJ11cblxuIyAgMDAwMDAwMCAgMDAwICAgICAgMDAwMDAwMDAgICAwMDAwMDAwICAgMDAwMDAwMDBcbiMgMDAwICAgICAgIDAwMCAgICAgIDAwMCAgICAgICAwMDAgICAwMDAgIDAwMCAgIDAwMFxuIyAwMDAgICAgICAgMDAwICAgICAgMDAwMDAwMCAgIDAwMDAwMDAwMCAgMDAwMDAwMFxuIyAwMDAgICAgICAgMDAwICAgICAgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwICAgMDAwXG4jICAwMDAwMDAwICAwMDAwMDAwICAwMDAwMDAwMCAgMDAwICAgMDAwICAwMDAgICAwMDBcblxuY2xlYXJTZWFyY2ggPSAtPlxuXG4gICAgaWYgcmVzdWx0cy5sZW5ndGhcbiAgICAgICAgc2VhcmNoID0gJydcbiAgICAgICAgcmVzdWx0cyA9IFtyZXN1bHRzW01hdGgubWluIGN1cnJlbnRJbmRleCwgcmVzdWx0cy5sZW5ndGgtMV1dXG4gICAgICAgIHJlc3VsdHNbMF0uc3RyaW5nID0gY3VycmVudE5hbWVcbiAgICAgICAgJCgnYXBwbmFtZScpLmlubmVySFRNTCA9IGN1cnJlbnROYW1lXG4gICAgICAgIGN1cnJlbnRJbmRleCA9IDBcbiAgICAgICAgc2hvd0RvdHMoKVxuICAgIGVsc2VcbiAgICAgICAgZG9TZWFyY2ggJydcblxucG9zdC5vbiAnY2xlYXJTZWFyY2gnICBjbGVhclNlYXJjaFxuXG4jIDAwMCAgIDAwMDAwMDAgICAwMDAwMDAwICAgMDAwICAgMDAwXG4jIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwMCAgMDAwXG4jIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwIDAgMDAwXG4jIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwICAwMDAwXG4jIDAwMCAgIDAwMDAwMDAgICAwMDAwMDAwICAgMDAwICAgMDAwXG5cbmdldFNjcmlwdEljb24gPSAoc2NyaXB0TmFtZSkgLT4gc2V0SWNvbiBzY3JpcHRzW3NjcmlwdE5hbWVdLmltZ1xuXG5nZXRBcHBJY29uID0gKGFwcE5hbWUpIC0+XG5cbiAgICBpZiBzbGFzaC53aW4oKVxuICAgICAgICBhcHBJY29uID0gcmVxdWlyZSAnLi9leGVpY29uJ1xuICAgIGVsc2VcbiAgICAgICAgYXBwSWNvbiA9IHJlcXVpcmUgJy4vYXBwaWNvbidcblxuICAgIGFwcEljb24uZ2V0XG4gICAgICAgIGFwcFBhdGg6IGFwcHNbYXBwTmFtZV1cbiAgICAgICAgaWNvbkRpcjogaWNvbkRpclxuICAgICAgICBzaXplOiAgICA1MTJcbiAgICAgICAgY2I6ICAgICAgc2V0SWNvblxuXG5zZXRJY29uID0gKGljb25QYXRoKSAtPlxuICAgIFxuICAgICQoJ2FwcGljb24nKS5zdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgPSBcInVybChcXFwiI3tzbGFzaC5maWxlVXJsIGljb25QYXRofVxcXCIpXCJcblxuIyAgMDAwMDAwMCAgMDAwMDAwMDAgIDAwMCAgICAgIDAwMDAwMDAwICAgMDAwMDAwMCAgMDAwMDAwMDAwXG4jIDAwMCAgICAgICAwMDAgICAgICAgMDAwICAgICAgMDAwICAgICAgIDAwMCAgICAgICAgICAwMDBcbiMgMDAwMDAwMCAgIDAwMDAwMDAgICAwMDAgICAgICAwMDAwMDAwICAgMDAwICAgICAgICAgIDAwMFxuIyAgICAgIDAwMCAgMDAwICAgICAgIDAwMCAgICAgIDAwMCAgICAgICAwMDAgICAgICAgICAgMDAwXG4jIDAwMDAwMDAgICAwMDAwMDAwMCAgMDAwMDAwMCAgMDAwMDAwMDAgICAwMDAwMDAwICAgICAwMDBcblxuc2VsZWN0ID0gKGluZGV4KSA9PlxuICAgIGN1cnJlbnRJbmRleCA9IChpbmRleCArIHJlc3VsdHMubGVuZ3RoKSAlIHJlc3VsdHMubGVuZ3RoXG4gICAgaWYgZW1wdHkgcmVzdWx0c1tjdXJyZW50SW5kZXhdXG4gICAgICAgIGxvZyAnZGFmdWs/IGluZGV4OicsIGluZGV4LCAncmVzdWx0czonLCByZXN1bHRzXG4gICAgICAgIHJldHVyblxuICAgIGN1cnJlbnROYW1lID0gcmVzdWx0c1tjdXJyZW50SW5kZXhdLm5hbWVcbiAgICAkKCdhcHBuYW1lJykuaW5uZXJIVE1MID0gcmVzdWx0c1tjdXJyZW50SW5kZXhdLnN0cmluZ1xuICAgICQoJy5jdXJyZW50Jyk/LmNsYXNzTGlzdC5yZW1vdmUgJ2N1cnJlbnQnXG4gICAgJChcImRvdF8je2N1cnJlbnRJbmRleH1cIik/LmNsYXNzTGlzdC5hZGQgJ2N1cnJlbnQnXG4gICAgaWYgY3VycmVudElzQXBwKClcbiAgICAgICAgZ2V0QXBwSWNvbiBjdXJyZW50TmFtZVxuICAgIGVsc2VcbiAgICAgICAgZ2V0U2NyaXB0SWNvbiBjdXJyZW50TmFtZVxuXG5zZWxlY3ROYW1lID0gKG5hbWUpIC0+XG4gICAgXG4gICAgcmV0dXJuIGlmIGVtcHR5IG5hbWVcbiAgICBzZWxlY3QgcmVzdWx0cy5maW5kSW5kZXggKHIpIC0+XG4gICAgICAgIHI/Lm5hbWUudG9Mb3dlckNhc2UoKSA9PSBuYW1lLnRvTG93ZXJDYXNlKClcblxuIyAgIDAwMDAwMDAgICAgIDAwMDAwMDAgICAwMDAwMDAwMDAgICAwMDAwMDAwXG4jICAgMDAwICAgMDAwICAwMDAgICAwMDAgICAgIDAwMCAgICAgMDAwXG4jICAgMDAwICAgMDAwICAwMDAgICAwMDAgICAgIDAwMCAgICAgMDAwMDAwMFxuIyAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAgICAwMDAgICAgICAgICAgMDAwXG4jICAgMDAwMDAwMCAgICAgMDAwMDAwMCAgICAgIDAwMCAgICAgMDAwMDAwMFxuXG5zaG93RG90cyA9IC0+XG5cbiAgICBkb3RzID0kICdhcHBkb3RzJ1xuICAgIGRvdHMuaW5uZXJIVE1MID0gJydcblxuICAgIHdpbldpZHRoID0gc3coKVxuICAgIHNldFN0eWxlICcjYXBwbmFtZScgJ2ZvbnQtc2l6ZScgXCIje3BhcnNlSW50IDEwKzIqKHdpbldpZHRoLTEwMCkvMTAwfXB4XCJcblxuICAgIHJldHVybiBpZiByZXN1bHRzLmxlbmd0aCA8IDJcblxuICAgIGRvdHIgPSBlbGVtIGlkOidhcHBkb3RyJ1xuICAgIGRvdHMuYXBwZW5kQ2hpbGQgZG90clxuXG4gICAgcyA9IHdpbldpZHRoIC8gcmVzdWx0cy5sZW5ndGhcbiAgICBzID0gY2xhbXAgMSwgd2luV2lkdGgvMTAwLCBzXG4gICAgcyA9IHBhcnNlSW50IHNcbiAgICBzZXRTdHlsZSAnLmFwcGRvdCcsICd3aWR0aCcsIFwiI3tzfXB4XCJcbiAgICBzZXRTdHlsZSAnLmFwcGRvdCcsICdoZWlnaHQnLCBcIiN7c31weFwiXG5cbiAgICBmb3IgaSBpbiBbMC4uLnJlc3VsdHMubGVuZ3RoXVxuICAgICAgICBkb3QgPSBlbGVtICdzcGFuJywgY2xhc3M6J2FwcGRvdCcsIGlkOiBcImRvdF8je2l9XCJcbiAgICAgICAgaWYgaSA9PSBjdXJyZW50SW5kZXhcbiAgICAgICAgICAgIGRvdC5jbGFzc0xpc3QuYWRkICdjdXJyZW50J1xuICAgICAgICBkb3RyLmFwcGVuZENoaWxkIGRvdFxuXG4jIDAwMDAwMDAgICAgMDAwICAgICAgIDAwMDAwMDAgICAgMDAwMDAwMCAgMDAwICAgMDAwICAwMDAgICAgICAwMDAgICAwMDAwMDAwICAwMDAwMDAwMDAgIFxuIyAwMDAgICAwMDAgIDAwMCAgICAgIDAwMCAgIDAwMCAgMDAwICAgICAgIDAwMCAgMDAwICAgMDAwICAgICAgMDAwICAwMDAgICAgICAgICAgMDAwICAgICBcbiMgMDAwMDAwMCAgICAwMDAgICAgICAwMDAwMDAwMDAgIDAwMCAgICAgICAwMDAwMDAwICAgIDAwMCAgICAgIDAwMCAgMDAwMDAwMCAgICAgIDAwMCAgICAgXG4jIDAwMCAgIDAwMCAgMDAwICAgICAgMDAwICAgMDAwICAwMDAgICAgICAgMDAwICAwMDAgICAwMDAgICAgICAwMDAgICAgICAgMDAwICAgICAwMDAgICAgIFxuIyAwMDAwMDAwICAgIDAwMDAwMDAgIDAwMCAgIDAwMCAgIDAwMDAwMDAgIDAwMCAgIDAwMCAgMDAwMDAwMCAgMDAwICAwMDAwMDAwICAgICAgMDAwICAgICBcblxuYmxhY2tsaXN0ID0gLT5cblxuICAgIGlnbm9yZSA9IHByZWZzLmdldCAnaWdub3JlJywgW11cbiAgICBcbiAgICBfLnB1bGwgaWdub3JlLCBhcHBzW2N1cnJlbnROYW1lXVxuICAgIF8ucHVsbCBpZ25vcmUsIG51bGxcbiAgICBpZiB2YWxpZCBhcHBzW2N1cnJlbnROYW1lXVxuICAgICAgICBpZ25vcmUucHVzaCBhcHBzW2N1cnJlbnROYW1lXVxuICAgIGVsc2VcbiAgICAgICAgbG9nIFwiY2FuJ3QgaWdub3JlICcje2N1cnJlbnROYW1lfSdcIlxuICAgIFxuICAgIHByZWZzLnNldCAnaWdub3JlJywgaWdub3JlXG4gICAgXG4gICAgZGVsZXRlIGFwcHNbY3VycmVudE5hbWVdXG4gICAgXG4gICAgcmVzdWx0cy5zcGxpY2UgY3VycmVudEluZGV4LCAxXG4gICAgXG4gICAgc2VsZWN0IGN1cnJlbnRJbmRleFxuICAgIFxuIyAgMDAwMDAwMCAgMDAwMDAwMDAgICAwMDAwMDAwICAgMDAwMDAwMDAgICAgMDAwMDAwMCAgMDAwICAgMDAwXG4jIDAwMCAgICAgICAwMDAgICAgICAgMDAwICAgMDAwICAwMDAgICAwMDAgIDAwMCAgICAgICAwMDAgICAwMDBcbiMgMDAwMDAwMCAgIDAwMDAwMDAgICAwMDAwMDAwMDAgIDAwMDAwMDAgICAgMDAwICAgICAgIDAwMDAwMDAwMFxuIyAgICAgIDAwMCAgMDAwICAgICAgIDAwMCAgIDAwMCAgMDAwICAgMDAwICAwMDAgICAgICAgMDAwICAgMDAwXG4jIDAwMDAwMDAgICAwMDAwMDAwMCAgMDAwICAgMDAwICAwMDAgICAwMDAgICAwMDAwMDAwICAwMDAgICAwMDBcblxuZG9TZWFyY2ggPSAocykgLT5cbiAgICBcbiAgICBzZWFyY2ggID0gc1xuICAgIG5hbWVzICAgPSBhbGxLZXlzXG4gICAgZnV6emllZCA9IGZ1enp5LmZpbHRlciBzZWFyY2gsIG5hbWVzLCBwcmU6ICc8Yj4nLCBwb3N0OiAnPC9iPidcbiAgICBmdXp6aWVkID0gXy5zb3J0QnkgZnV6emllZCwgKG8pIC0+IDIgLSBmdXp6YWxkcmluLnNjb3JlIG8ub3JpZ2luYWwsIHNlYXJjaFxuXG4gICAgaWYgc2VhcmNoLmxlbmd0aFxuICAgICAgICBpZiBwcyA9IHByZWZzLmdldCBcInNlYXJjaDoje3NlYXJjaH1cIlxuICAgICAgICAgICAgZnV6emllZCA9IF8uc29ydEJ5IGZ1enppZWQsIChvKSAtPiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiAtIChwc1tvLm9yaWdpbmFsXSA/IDApXG5cbiAgICByZXN1bHRzID0gW11cbiAgICBmb3IgZiBpbiBmdXp6aWVkXG4gICAgICAgIHIgPSBuYW1lOiBmLm9yaWdpbmFsLCBzdHJpbmc6IGYuc3RyaW5nXG4gICAgICAgIHIuc2NyaXB0ID0gc2NyaXB0c1tyLm5hbWVdIGlmIHNjcmlwdHNbci5uYW1lXVxuICAgICAgICByZXN1bHRzLnB1c2ggclxuXG4gICAgaWYgdmFsaWQgcmVzdWx0c1xuICAgICAgICBpZiBzID09ICcnXG4gICAgICAgICAgICBpZiBzbGFzaC53aW4oKVxuICAgICAgICAgICAgICAgIHNlbGVjdE5hbWUgJ3Rlcm1pbmFsJ1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIHNlbGVjdE5hbWUgJ0ZpbmRlcidcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgc2VsZWN0IDBcbiAgICAgICAgc2hvd0RvdHMoKVxuICAgIGVsc2VcbiAgICAgICAgJCgnYXBwZG90cycpLmlubmVySFRNTCA9ICcnXG4gICAgICAgICQoJ2FwcG5hbWUnKS5pbm5lckhUTUwgPSBcIjxiPiN7c2VhcmNofTwvYj5cIlxuXG5jb21wbGV0ZSAgPSAoa2V5KSAtPiBkb1NlYXJjaCBzZWFyY2ggKyBrZXlcbmJhY2tzcGFjZSA9ICAgICAgIC0+IGRvU2VhcmNoIHNlYXJjaC5zdWJzdHIgMCwgc2VhcmNoLmxlbmd0aC0xXG5cbmNhbmNlbFNlYXJjaE9yQ2xvc2UgPSAtPlxuICAgIFxuICAgIGlwYy5zZW5kICdjbG9zZUFib3V0J1xuICAgIFxuICAgIGlmIHNlYXJjaC5sZW5ndGhcbiAgICAgICAgZG9TZWFyY2ggJydcbiAgICBlbHNlXG4gICAgICAgIHBvc3QudG9NYWluICdjYW5jZWwnXG5cbmNsaWNrSUQgPSBkb3duSUQgPSAwXG53aW5kb3cub25tb3VzZWRvd24gID0gKGUpIC0+IGNsaWNrSUQgKz0gMSA7IGRvd25JRCA9IGNsaWNrSURcbndpbmRvdy5vbm1vdXNldXAgICAgPSAoZSkgLT4gb3BlbkN1cnJlbnQoKSBpZiBkb3duSUQgPT0gY2xpY2tJRFxud2luZG93Lm9ubW91c2Vtb3ZlICA9IChlKSAtPiBpZiBlLmJ1dHRvbnMgdGhlbiBkb3duSUQgPSAtMVxud2luZG93Lm9udW5sb2FkID0gLT4gZG9jdW1lbnQub25rZXlkb3duID0gbnVsbFxud2luZG93Lm9uYmx1ciAgID0gLT4gd2luSGlkZSgpXG53aW5kb3cub25yZXNpemUgPSAtPiBzaG93RG90cygpXG5cbndoZWVsQWNjdSA9IDBcbndpbmRvdy5vbndoZWVsICA9IChldmVudCkgLT5cbiAgICB3aGVlbEFjY3UgKz0gKGV2ZW50LmRlbHRhWCArIGV2ZW50LmRlbHRhWSkvNDRcbiAgICBpZiB3aGVlbEFjY3UgPiAxXG4gICAgICAgIHNlbGVjdCBjdXJyZW50SW5kZXgrMSAlIHJlc3VsdHMubGVuZ3RoXG4gICAgICAgIHdoaWxlIHdoZWVsQWNjdSA+IDFcbiAgICAgICAgICAgIHdoZWVsQWNjdSAtPSAxXG4gICAgZWxzZSBpZiB3aGVlbEFjY3UgPCAtMVxuICAgICAgICBzZWxlY3QgY3VycmVudEluZGV4K3Jlc3VsdHMubGVuZ3RoLTEgJSByZXN1bHRzLmxlbmd0aFxuICAgICAgICB3aGlsZSB3aGVlbEFjY3UgPCAtMVxuICAgICAgICAgICAgd2hlZWxBY2N1ICs9IDFcblxuIyAgMDAwMDAwMCAgMDAwICAwMDAwMDAwICAwMDAwMDAwMFxuIyAwMDAgICAgICAgMDAwICAgICAwMDAgICAwMDBcbiMgMDAwMDAwMCAgIDAwMCAgICAwMDAgICAgMDAwMDAwMFxuIyAgICAgIDAwMCAgMDAwICAgMDAwICAgICAwMDBcbiMgMDAwMDAwMCAgIDAwMCAgMDAwMDAwMCAgMDAwMDAwMDBcblxub3BlbkRldlRvb2xzID0gLT4gcG9zdC50b01haW4gJ2RldlRvb2xzJ1xuc2NyZWVuU2l6ZSA9IC0+IHNzID0gZWxlY3Ryb24uaXBjUmVuZGVyZXIuc2VuZFN5bmMgJ2dldFNjcmVlblNpemUnOyBrbG9nICdzY3JlZW5TaXplJyBzczsgc3NcblxuY2xhbXBCb3VuZHMgPSAoYikgLT5cbiAgICBiLndpZHRoID0gY2xhbXAgMjAwLCA2MDAsIGIud2lkdGhcbiAgICBiLmhlaWdodCA9IGNsYW1wIDIwMCwgNjAwLCBiLmhlaWdodFxuICAgIGIueCA9IGNsYW1wIDAsIHNjcmVlblNpemUoKS53aWR0aCAtIGIud2lkdGgsIGIueFxuICAgIGIueSA9IGNsYW1wIDAsIHNjcmVlblNpemUoKS5oZWlnaHQgLSBiLmhlaWdodCwgYi55XG4gICAgYlxuXG5nZXRCb3VuZHMgPSAgICAgLT4gYiA9IGVsZWN0cm9uLmlwY1JlbmRlcmVyLnNlbmRTeW5jICdnZXRXaW5Cb3VuZHMnOyBrbG9nICdnZXRCb3VuZHMnIGI7IGJcbnNldEJvdW5kcyA9IChiKSAtPiBlbGVjdHJvbi5pcGNSZW5kZXJlci5zZW5kICdzZXRXaW5Cb3VuZHMnIGI7IGtsb2cgJ3NldEJvdW5kcycgYlxuICAgIFxuc2l6ZVdpbmRvdyA9IChkKSAtPlxuICAgIGIgPSBnZXRCb3VuZHMoKVxuICAgIGN4ID0gYi54ICsgYi53aWR0aC8yXG4gICAgYi53aWR0aCs9ZFxuICAgIGIuaGVpZ2h0Kz1kXG4gICAgY2xhbXBCb3VuZHMgYlxuICAgIGIueCA9IGN4IC0gYi53aWR0aC8yXG4gICAgc2V0Qm91bmRzIGNsYW1wQm91bmRzIGJcblxubW92ZVdpbmRvdyA9IChkeCxkeSkgLT5cbiAgICBiID0gZ2V0Qm91bmRzKClcbiAgICBiLngrPWR4XG4gICAgYi55Kz1keVxuICAgIHNldEJvdW5kcyBjbGFtcEJvdW5kcyBiXG5cbmJpZ2dlcldpbmRvdyAgICAgPSAtPiBzaXplV2luZG93IDUwXG5zbWFsbGVyV2luZG93ICAgID0gLT4gc2l6ZVdpbmRvdyAtNTBcbm1pbmltaXplV2luZG93ICAgPSAtPiBzZXRCb3VuZHMgeDpzY3JlZW5TaXplKCkud2lkdGgvMi0xMDAsIHk6MCwgd2lkdGg6MjAwLCBoZWlnaHQ6MjAwXG5tYXhpbWl6ZVdpbmRvdyAgID0gLT4gc2V0Qm91bmRzIHg6c2NyZWVuU2l6ZSgpLndpZHRoLzItMzAwLCB5OjAsIHdpZHRoOjYwMCwgaGVpZ2h0OjYwMFxudG9nZ2xlV2luZG93U2l6ZSA9IC0+IGlmIGdldEJvdW5kcygpLndpZHRoID4gMjAwIHRoZW4gbWluaW1pemVXaW5kb3coKSBlbHNlIG1heGltaXplV2luZG93KClcblxucHJldmVudEtleVJlcGVhdCA9IC0+IGxvZyAna2V5UmVwZWF0IGFoZWFkISdcblxuIyAwMDAgICAwMDAgIDAwMDAwMDAwICAwMDAgICAwMDBcbiMgMDAwICAwMDAgICAwMDAgICAgICAgIDAwMCAwMDBcbiMgMDAwMDAwMCAgICAwMDAwMDAwICAgICAwMDAwMFxuIyAwMDAgIDAwMCAgIDAwMCAgICAgICAgICAwMDBcbiMgMDAwICAgMDAwICAwMDAwMDAwMCAgICAgMDAwXG5cbmRvY3VtZW50Lm9ua2V5ZG93biA9IChldmVudCkgLT5cblxuICAgIHsgbW9kLCBrZXksIGNvbWJvLCBjaGFyIH0gPSBrZXlpbmZvLmZvckV2ZW50IGV2ZW50XG5cbiAgICBrbG9nIGNvbWJvICNpZiBhcmdzLnZlcmJvc2VcbiAgICBcbiAgICBpZiBjaGFyPyBhbmQgY29tYm8ubGVuZ3RoID09IDFcbiAgICAgICAgY29tcGxldGUga2V5XG4gICAgICAgIHJldHVyblxuXG4gICAgc3dpdGNoIGNvbWJvXG4gICAgICAgIHdoZW4gJ2YxJyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVuIHByZXZlbnRLZXlSZXBlYXQoKVxuICAgICAgICB3aGVuICdkZWxldGUnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbiBibGFja2xpc3QoKVxuICAgICAgICB3aGVuICdiYWNrc3BhY2UnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbiBiYWNrc3BhY2UoKVxuICAgICAgICB3aGVuICdjb21tYW5kK2JhY2tzcGFjZScsICAgICAgICdjdHJsK2JhY2tzcGFjZScgICAgdGhlbiBkb1NlYXJjaCAnJ1xuICAgICAgICB3aGVuICdjb21tYW5kK2knLCAnY3RybCtpJyAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbiBzY2hlbWUudG9nZ2xlKClcbiAgICAgICAgd2hlbiAnZXNjJyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW4gY2FuY2VsU2VhcmNoT3JDbG9zZSgpXG4gICAgICAgIHdoZW4gJ2Rvd24nLCAncmlnaHQnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVuIHNlbGVjdCBjdXJyZW50SW5kZXgrMVxuICAgICAgICB3aGVuICd1cCcgICwgJ2xlZnQnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbiBzZWxlY3QgY3VycmVudEluZGV4LTFcbiAgICAgICAgd2hlbiAnZW50ZXInICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW4gb3BlbkN1cnJlbnQoKVxuICAgICAgICB3aGVuICdjb21tYW5kK2FsdCtpJywgICAgICAgICAgICdjdHJsK2FsdCtpJyAgICAgICAgdGhlbiBvcGVuRGV2VG9vbHMoKVxuICAgICAgICB3aGVuICdjb21tYW5kKz0nLCAgICAgICAgICAgICAgICdjdHJsKz0nICAgICAgICAgICAgdGhlbiBiaWdnZXJXaW5kb3coKVxuICAgICAgICB3aGVuICdjb21tYW5kKy0nLCAgICAgICAgICAgICAgICdjdHJsKy0nICAgICAgICAgICAgdGhlbiBzbWFsbGVyV2luZG93KClcbiAgICAgICAgd2hlbiAnY29tbWFuZCtyJywgICAgICAgICAgICAgICAnY3RybCtyJyAgICAgICAgICAgIHRoZW4gcG9zdC50b01haW4gJ2ZpbmRBcHBzJ1xuICAgICAgICB3aGVuICdjb21tYW5kK2gnLCAgICAgICAgICAgICAgICdhbHQraCcgICAgICAgICAgICAgdGhlbiBsaXN0SGlzdG9yeSgpXG4gICAgICAgIHdoZW4gJ2NvbW1hbmQrZicsICAgICAgICAgICAgICAgJ2N0cmwrZicgICAgICAgICAgICB0aGVuIG9wZW5JbkZpbmRlcigpXG4gICAgICAgIHdoZW4gJ2NvbW1hbmQrdCcsICAgICAgICAgICAgICAgJ2N0cmwrdCcgICAgICAgICAgICB0aGVuIHRvZ2dsZUFwcFRvZ2dsZSgpXG4gICAgICAgIHdoZW4gJ2NvbW1hbmQrZCcsICAgICAgICAgICAgICAgJ2N0cmwrZCcgICAgICAgICAgICB0aGVuIHRvZ2dsZURvdWJsZUFjdGl2YXRpb24oKVxuICAgICAgICB3aGVuICdhbHQrY29tbWFuZCsvJywgICAgICAgICAgICdhbHQrY3RybCsvJyAgICAgICAgdGhlbiBwb3N0LnRvTWFpbiAnYWJvdXQnXG4gICAgICAgIHdoZW4gJ2NvbW1hbmQrLCcsICAgICAgICAgICAgICAgJ2N0cmwrLCcgICAgICAgICAgICB0aGVuIG9wZW4gcHJlZnMuc3RvcmUuZmlsZVxuICAgICAgICB3aGVuICdjb21tYW5kK3VwJywgICAgICAgICAgICAgICdjdHJsK3VwJyAgICAgICAgICAgdGhlbiBtb3ZlV2luZG93IDAsLTIwXG4gICAgICAgIHdoZW4gJ2NvbW1hbmQrZG93bicsICAgICAgICAgICAgJ2N0cmwrZG93bicgICAgICAgICB0aGVuIG1vdmVXaW5kb3cgMCwgMjBcbiAgICAgICAgd2hlbiAnY29tbWFuZCtsZWZ0JywgICAgICAgICAgICAnY3RybCtsZWZ0JyAgICAgICAgIHRoZW4gbW92ZVdpbmRvdyAtMjAsIDBcbiAgICAgICAgd2hlbiAnY29tbWFuZCtyaWdodCcsICAgICAgICAgICAnY3RybCtyaWdodCcgICAgICAgIHRoZW4gbW92ZVdpbmRvdyAgMjAsIDBcbiAgICAgICAgd2hlbiAnY29tbWFuZCswJywnY29tbWFuZCtvJywgICAnY3RybCswJywnY3RybCtvJyAgIHRoZW4gdG9nZ2xlV2luZG93U2l6ZSgpXG5cbndpbk1haW4oKVxuIl19 635 | //# sourceURL=../coffee/kappo.coffee --------------------------------------------------------------------------------