496 lines
11 KiB
JavaScript
496 lines
11 KiB
JavaScript
#!/usr/bin/env osascript -l JavaScript
|
|
|
|
/**
|
|
* @fileOverview Various system functions.
|
|
*/
|
|
|
|
ObjC.import('Foundation')
|
|
ObjC.import('AppKit')
|
|
|
|
var sys_events = Application("System Events")
|
|
var workspace
|
|
|
|
function setWorkspace(w){
|
|
workspace = w
|
|
}
|
|
|
|
function workspaceHome(){
|
|
return env("WORKSPACES_HOME") + "/" + workspace
|
|
}
|
|
|
|
function workspacesHome(){
|
|
return env("WORKSPACES_HOME")
|
|
}
|
|
|
|
|
|
function test(){
|
|
console.log("workspace name", workspace["name"])
|
|
}
|
|
|
|
function sh(cmd) {
|
|
var me = Application.currentApplication()
|
|
me.includeStandardAdditions = true
|
|
me.doShellScript(cmd)
|
|
}
|
|
|
|
// More keycodes can be added. Keycode reference:
|
|
// http://www.codemacs.com/coding/applescript/applescript-key-codes-reference.8288271.htm
|
|
var key_codes = {
|
|
"→": 124,
|
|
"←": 123,
|
|
"↑": 126,
|
|
"↓": 125,
|
|
"⏎": 36
|
|
}
|
|
|
|
var modifiers = {
|
|
"⌘": "command down",
|
|
"^": "control down",
|
|
"⌥": "option down",
|
|
"⇧": "shift down"
|
|
}
|
|
|
|
function running() {
|
|
var apps = $.NSWorkspace.sharedWorkspace.runningApplications // Note these never take () unless they have arguments
|
|
apps = ObjC.unwrap(apps) // Unwrap the NSArray instance to a normal JS array
|
|
var app
|
|
for (var i = 0, j = apps.length; i < j; i++) {
|
|
app = apps[i]
|
|
console.log(ObjC.unwrap(app.bundleIdentifier))
|
|
// Another option for comparison is to unwrap app.bundleIdentifier
|
|
// ObjC.unwrap(app.bundleIdentifier) === 'org.whatever.Name'
|
|
|
|
// Some applications do not have a bundleIdentifier as an NSString
|
|
// if (typeof app.bundleIdentifier.isEqualToString === 'undefined') {
|
|
// continue;
|
|
// }
|
|
|
|
// if (app.bundleIdentifier.isEqualToString('com.apple.iTunes')) {
|
|
// isRunning = true;
|
|
// break;
|
|
// }
|
|
}
|
|
}
|
|
|
|
function press(hotkey) {
|
|
var using = [];
|
|
|
|
while (hotkey.length > 1) {
|
|
if (modifiers[hotkey[0]] == undefined) {
|
|
throw new Error(hotkey[0] + " is not a recognized modifier key");
|
|
}
|
|
|
|
using.push(modifiers[hotkey[0]]);
|
|
hotkey = hotkey.slice(1);
|
|
}
|
|
|
|
if (key_codes[hotkey] != undefined) {
|
|
sys_events.keyCode(key_codes[hotkey], {using: using});
|
|
}
|
|
else {
|
|
sys_events.keystroke(hotkey.toLowerCase(), {using: using});
|
|
}
|
|
}
|
|
|
|
function type(text) {
|
|
for (var i=0; i < text.length; i++) {
|
|
sys_events.keystroke(text[i]);
|
|
}
|
|
}
|
|
|
|
function menu_item() {
|
|
if (!arguments.length) return;
|
|
|
|
var process = sys_events.processes.whose({"frontmost": true})[0];
|
|
var menu_bar = process.menuBars[0].menuBarItems[arguments[0]];
|
|
|
|
var menu_item = menu_bar;
|
|
for (var i=1; i < arguments.length; i++) {
|
|
menu_item = menu_item.menus[0].menuItems[arguments[i]];
|
|
}
|
|
menu_item.click();
|
|
}
|
|
|
|
function quit(name) {
|
|
try{
|
|
Application(name).quit()
|
|
}catch(err){}
|
|
}
|
|
|
|
|
|
function closeWindows(name){
|
|
var app = Application(name);
|
|
for(var i = 0; i < app.windows().length; i++){
|
|
var win = app.windows.at(i);
|
|
if(!win.selectedTab.busy()){
|
|
app.close(win, {saving:"no"})
|
|
}
|
|
}
|
|
}
|
|
|
|
// function safariWindows(){
|
|
// windowIDs = []
|
|
// var app = Application("Safari")
|
|
// for(var i = 0; i < app.windows().length; i++){
|
|
// var win = app.windows.at(i)
|
|
// windowIDs.push(win.id())
|
|
// }
|
|
// return windowIDs
|
|
// }
|
|
|
|
function title(app, win){
|
|
return Application(app).windows.byId(win).name()
|
|
}
|
|
|
|
// function needWindows(app, count, path){
|
|
// windowIDs = []
|
|
// var app = Application(app)
|
|
// if(app.windows().length < count){
|
|
// needed = count - app.windows().length
|
|
// console.log(needed)
|
|
// for(var i = 0; i < needed; i++ ){
|
|
// app.open(path)
|
|
// }
|
|
// }
|
|
// delay(1)
|
|
// for(var i = 0; i < app.windows().length; i++){
|
|
// var win = app.windows.at(i)
|
|
// windowIDs.push(win.id())
|
|
// }
|
|
// return windowIDs
|
|
// }
|
|
|
|
function writeFile(pPathStr, pOutputStr) {
|
|
//--- CONVERT TO NS STRING ---
|
|
var nsStr = $.NSString.alloc.initWithUTF8String(pOutputStr)
|
|
|
|
//--- EXPAND TILDE AND CONVERT TO NS PATH ---
|
|
var nsPath = $(pPathStr).stringByStandardizingPath
|
|
|
|
//--- WRITE TO FILE ---
|
|
var successBool = nsStr.writeToFileAtomicallyEncodingError(nsPath, false, $.NSUTF8StringEncoding, null)
|
|
|
|
if (!successBool) {
|
|
throw new Error("function writeFile ERROR:\nWrite to File FAILED for:\n" + pPathStr)
|
|
}
|
|
|
|
return successBool
|
|
|
|
}
|
|
|
|
function writeJson(path, obj) {
|
|
try{
|
|
var str = JSON.stringify(obj, null, 2)
|
|
}catch(err){ return [false, "JSON error"]}
|
|
|
|
try{
|
|
writeFile(path, str)
|
|
}catch(err){ return [false, "file error"] }
|
|
return [true, obj]
|
|
}
|
|
|
|
|
|
function store(k, v) {
|
|
var path = workspacePropertiesFile()
|
|
var result = readJson(path)
|
|
var obj = {}
|
|
if(result[0]){
|
|
obj = result[1]
|
|
}
|
|
obj[k] = v
|
|
|
|
var result = writeJson(path, obj)
|
|
var success = result[0]
|
|
if(!success){
|
|
console.log("could not write JSON")
|
|
return result
|
|
}
|
|
return [true, v]
|
|
}
|
|
|
|
function workspacePropertiesFile(){
|
|
return workspaceHome() + "/" + "properties.json"
|
|
}
|
|
|
|
/**
|
|
@desc Reads objects from JSON file
|
|
@param {String} key The key to get values from
|
|
@returns {Array}
|
|
|
|
*/
|
|
|
|
function retrieve(k) {
|
|
|
|
var path = workspacePropertiesFile()
|
|
var result = readJson(path)
|
|
var success = result[0]
|
|
|
|
if(!success){
|
|
return result
|
|
}
|
|
|
|
var obj = result[1]
|
|
var v = obj[k]
|
|
|
|
if(v == undefined) return [false, "key error"]
|
|
return [true, v]
|
|
}
|
|
|
|
function retrieve(k) {
|
|
|
|
var path = workspacePropertiesFile()
|
|
var result = readJson(path)
|
|
var success = result[0]
|
|
|
|
if(!success){
|
|
console.log("retrieve", result[1])
|
|
return result
|
|
}
|
|
|
|
var obj = result[1]
|
|
var v = obj[k]
|
|
|
|
if(v == undefined){
|
|
console.log("retrieve key error")
|
|
return [false, "key error"]
|
|
}
|
|
return [true, v]
|
|
}
|
|
|
|
|
|
function readJson(path) {
|
|
var data = readFile(path)
|
|
if(!data[0]){ return [false, "file error"] }
|
|
try{
|
|
var obj = JSON.parse(data[1])
|
|
}catch(err){
|
|
return [false, "JSON error"]
|
|
}
|
|
return [true, obj]
|
|
}
|
|
|
|
function readFile(file) {
|
|
var app = Application.currentApplication()
|
|
app.includeStandardAdditions = true
|
|
|
|
// Convert the file to a string
|
|
var fileString = file.toString()
|
|
|
|
try{
|
|
var p = Path(fileString)
|
|
}catch(err){ return [false, err] }
|
|
|
|
try{
|
|
var str = app.read(p)
|
|
}catch(err){
|
|
return [false, err]
|
|
}
|
|
// Read the file and return its contents
|
|
return [true, str]
|
|
}
|
|
|
|
|
|
function toggleActiveWindowFullScreen(){
|
|
sys_events.keystroke('f', { using: ['control down','command down'] });
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Get environment variable by name
|
|
*
|
|
*/
|
|
|
|
|
|
function env(name){
|
|
var env = $.NSProcessInfo.processInfo.environment // -[[NSProcessInfo processInfo] environment]
|
|
env = ObjC.unwrap(env)
|
|
for (var k in env) {
|
|
if(k == name){
|
|
return ObjC.unwrap(env[k])
|
|
}
|
|
}
|
|
return undefined
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Print available environment variables
|
|
*
|
|
*/
|
|
|
|
function env_list(){
|
|
var env = $.NSProcessInfo.processInfo.environment // -[[NSProcessInfo processInfo] environment]
|
|
env = ObjC.unwrap(env)
|
|
for (var k in env) {
|
|
console.log('"' + k + '": ' + ObjC.unwrap(env[k]))
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
@desc Get list of workspace-related windows from file. If there
|
|
are stored windows that do not exist, they will be removed.
|
|
|
|
@param {String} appName
|
|
@returns {Array} List of objects in the form {id:2445, }
|
|
|
|
*/
|
|
|
|
function existingWorkspaceWindows(appName) {
|
|
|
|
if(appName == undefined){
|
|
console.log("no app name given")
|
|
return []
|
|
}
|
|
// console.log(appName)
|
|
// appName = lowerCase(appName)
|
|
var result = retrieve(appName)
|
|
var success = result[0]
|
|
var wlist = result[1]
|
|
// console.log("window count", wlist.length)
|
|
if(!success){
|
|
return []
|
|
}
|
|
|
|
var changed = false
|
|
for (var i = 0; i < wlist.length; i++) {
|
|
var id = wlist[i]["id"]
|
|
// console.log("window exist", id, windowExistWithId(appName, id))
|
|
if(!windowExistWithId(appName, id)){
|
|
wlist.splice(i, 1)
|
|
changed = true
|
|
}
|
|
}
|
|
|
|
if(changed){
|
|
store(appName, wlist)
|
|
}
|
|
|
|
return wlist
|
|
}
|
|
|
|
/**
|
|
|
|
@desc Get list of workspace-related windows from file. If there
|
|
are stored windows that do not exist, they will be removed.
|
|
|
|
@param {String} appName
|
|
@returns {Array} List of objects in the form {id:2445, }
|
|
|
|
*/
|
|
|
|
function workspaceWindows(appName) {
|
|
|
|
if(appName == undefined){
|
|
console.log("no app name given")
|
|
return []
|
|
}
|
|
// console.log(appName)
|
|
// appName = lowerCase(appName)
|
|
var result = retrieve(appName)
|
|
var success = result[0]
|
|
var wlist = result[1]
|
|
// console.log("window count", wlist.length)
|
|
if(!success){
|
|
return []
|
|
}
|
|
|
|
var changed = false
|
|
for (var i = 0; i < wlist.length; i++) {
|
|
var id = wlist[i]["id"]
|
|
// console.log("window exist", id, windowExistWithId(appName, id))
|
|
if(!windowExistWithId(appName, id)){
|
|
wlist.splice(i, 1)
|
|
changed = true
|
|
}
|
|
}
|
|
|
|
if(changed){
|
|
store(appName, wlist)
|
|
}
|
|
|
|
return wlist
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
@param {String} appName
|
|
@param {Integer} id
|
|
@returns {Boolean}
|
|
|
|
**/
|
|
|
|
function windowExistWithId(appName, id) {
|
|
var wlist = windowIDs(appName)
|
|
for (var i = 0; i < wlist.length; i++) {
|
|
var wID = wlist[i]
|
|
if(id == wID) return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
|
|
@desc Get list of id's of Safari windows.
|
|
@param {String} appName
|
|
@returns {Array} Array of integers
|
|
|
|
**/
|
|
|
|
function windowIDs(appName){
|
|
// console.log(appName)
|
|
var app = Application(appName)
|
|
// console.log(app)
|
|
var wlist = []
|
|
for(var i = 0; i < app.windows().length; i++){
|
|
var win = app.windows.at(i)
|
|
wlist.push(win.id())
|
|
}
|
|
return wlist.sort(function(a, b){return a-b})
|
|
}
|
|
|
|
/**
|
|
|
|
@desc Get window id by index from list of all windows.
|
|
@param {Integer} index may be -2, -1, 0, 1, 2, etc.
|
|
@return {Integer}
|
|
|
|
**/
|
|
|
|
function windowID(appName, index){
|
|
var app = Application(appName)
|
|
var wlist = windowIDs(appName)
|
|
if(index < 0){
|
|
index = wlist.length + index
|
|
}
|
|
return app.windows.byId(wlist[index]).id()
|
|
}
|
|
|
|
// cannot call safari.foo() here, because
|
|
// somehow this library cannot import library safari in here
|
|
function add(appName){
|
|
// var wlist = workspaceWindows2(appName)
|
|
|
|
if(appName == "Safari"){
|
|
console.log("sys.add", appName)
|
|
// safari.addWorkspaceWindow()
|
|
|
|
}
|
|
return false
|
|
}
|
|
|
|
|
|
function prompt(text, defaultAnswer) {
|
|
var t = Application("Terminal")
|
|
t.includeStandardAdditions = true
|
|
var options = { defaultAnswer: defaultAnswer || '' }
|
|
try {
|
|
return t.displayDialog(text, options).textReturned
|
|
} catch (e) {
|
|
return defaultAnswer
|
|
}
|
|
}
|