safari-workspaces/trash/system.js

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
}
}