commit 4044c23905e1253267ebb43c5eb4e4371dd6d01a Author: p3ls Date: Sat Oct 24 21:37:49 2020 +0200 init diff --git a/README.md b/README.md new file mode 100644 index 0000000..50c3957 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ + +# Tastenkürzel + +Neuer Workspace + + ctrl + shift + N + +Neues Fenster + + ctrl + shift + W + +Fenster hinzufügen + + ctrl + shift + A + +Workspace Öffnen + + ctrl + shift + O + +Workspace Schliessen + + ctrl + shift + Q + +Workspace Speichern + + ctrl + shift + S + diff --git a/Services b/Services new file mode 120000 index 0000000..474b61f --- /dev/null +++ b/Services @@ -0,0 +1 @@ +/Users/stef/Library/Services \ No newline at end of file diff --git a/add-window.js b/add-window.js new file mode 100644 index 0000000..3128fec --- /dev/null +++ b/add-window.js @@ -0,0 +1,32 @@ +var workspace = Library("workspace") + +var name = workspace.chooseFromList("Add Window") + +if(name){ + + + var title = workspace.chooseFromSafariWindows() + console.log(title) + var id = workspace.safariWindowWithTitle(title) + console.log(id) + workspace.addWindowToWorkspace(id, name) + +} + +// var docs = Application('Safari').documents + +// for (var i = 0; i < docs.length; i++) { +// Things[i] +// } +// Application('Safari').documents[1].name() +// var app = Application('Safari') +// var windows = app.windows() + +// for (var k = 0; k < windows.length; k++) { + +// var url = app.windows.at(k).currentTab.url() +// var name = app.windows.at(k).currentTab.name() +// var id = app.windows.at(k).id() +// console.log(url, name) +// } + diff --git a/add.js b/add.js new file mode 100644 index 0000000..264d6c7 --- /dev/null +++ b/add.js @@ -0,0 +1,8 @@ +var workspace = Library("workspace") + +var name = workspace.chooseFromList("Add New Window") + +if(name){ + workspace.addNewWindowTo(name) +} + diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..528c27a --- /dev/null +++ b/build.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# cli.sh + +# workspace open Elm + +# workspace print Elm +# workspace save Elm + +# bash_completions + + + +osacompile -l JavaScript -o "$HOME/Library/Script Libraries/os.scpt" os.js +osacompile -l JavaScript -o "$HOME/Library/Script Libraries/workspace.scpt" workspace.js +# echo "Libraries copied $HOME/Library/Script Libraries" + +if [ "$1" = "" ]; then + echo "usage: build.sh open|close|add|new|workflow" && exit 0 +fi + + +if [ "$1" = "workflow" ]; then + cp -r "workflows/New Workspace.workflow" "$HOME/Library/Services" + cp -r "workflows/New Window in Workspace.workflow" "$HOME/Library/Services" + cp -r "workflows/Open Workspace.workflow" "$HOME/Library/Services" + cp -r "workflows/Close Workspace.workflow" "$HOME/Library/Services" + cp -r "workflows/Save Workspace.workflow" "$HOME/Library/Services" + exit 0 +fi + + + +if [ -f "$1.js" ]; then + osascript -l JavaScript "$1.js" +else + echo "error: $1.js not found" && exit 1 +fi diff --git a/close.js b/close.js new file mode 100644 index 0000000..077e08e --- /dev/null +++ b/close.js @@ -0,0 +1,7 @@ +var workspace = Library("workspace") + +var name = workspace.chooseFromList("Close Workspace") +if(name){ + workspace.closeWindows(name) +} + diff --git a/new.js b/new.js new file mode 100644 index 0000000..0b8adf1 --- /dev/null +++ b/new.js @@ -0,0 +1,31 @@ +var workspace = Library("workspace") +var app = Application.currentApplication() +app.includeStandardAdditions = true + +var response = app.displayDialog("Enter New Workspace Name", { + defaultAnswer: "", + withIcon: "note", + buttons: ["Cancel", "Continue"], + defaultButton: "Continue" +}) + +var selectedWorkspaceName = response.textReturned + +var allWorkspaceNames = workspace.getNames() + +for (var i = 0; i < allWorkspaceNames.length; i++) { + if(allWorkspaceNames[i] == selectedWorkspaceName){ + var response = app.displayDialog(" Workspace name already used. Please choose another", { + defaultAnswer: "", + withIcon: "note" + }) + } +} + +var selectedWorkspaceProps = { Safari: [] } +workspace.saveProperties(selectedWorkspaceName, selectedWorkspaceProps) + +workspace.addNewWindowTo(selectedWorkspaceName) + +// Result: {"buttonReturned":"Continue", "textReturned":"Jen"} +// app.displayDialog("Hello, " + (response.textReturned) + ".") \ No newline at end of file diff --git a/open.js b/open.js new file mode 100644 index 0000000..a22111c --- /dev/null +++ b/open.js @@ -0,0 +1,7 @@ +var workspace = Library("workspace") + +var name = workspace.chooseFromList("Open workspace") +if(name){ + workspace.openWindows(name) +} + diff --git a/os.js b/os.js new file mode 100644 index 0000000..f086795 --- /dev/null +++ b/os.js @@ -0,0 +1,78 @@ +ObjC.import('Foundation') +ObjC.import('AppKit') + +/** +* +* 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 +} + +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 writeFile(pPathStr, pOutputStr) { + + var nsStr = $.NSString.alloc.initWithUTF8String(pOutputStr) + var nsPath = $(pPathStr).stringByStandardizingPath + 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] +} \ No newline at end of file diff --git a/safari-workspaces b/safari-workspaces new file mode 120000 index 0000000..7695708 --- /dev/null +++ b/safari-workspaces @@ -0,0 +1 @@ +/Users/stef/.safari-workspaces \ No newline at end of file diff --git a/save.js b/save.js new file mode 100644 index 0000000..69a10d1 --- /dev/null +++ b/save.js @@ -0,0 +1,9 @@ +var workspace = Library("workspace") + +var name = workspace.chooseFromList("Save Workspace") +if(name){ + workspace.saveWindows(name, workspace.readProperties(name)) +} + + +// workspace.saveWindows("CouchDB", workspace.readProperties("CouchDB")) diff --git a/trash/Folder and Rename.js b/trash/Folder and Rename.js new file mode 100644 index 0000000..1b8413c --- /dev/null +++ b/trash/Folder and Rename.js @@ -0,0 +1,54 @@ + +var currentApp = Application.currentApplication(); +currentApp.includeStandardAdditions = true; +var finder = Application("Finder"); +var systemEvents = Application("System Events"); + +// Ask a folder to process + +var sourcePath = currentApp.chooseFolder ({ + withPrompt: "Choose the source folder" +}).toString(); +var sourceFolder = systemEvents.aliases.byName(sourcePath); + +// Create the destination folder + +var container = sourceFolder.container(); +var containerPath = container.path(); +var destinationFolder = finder.make({ + new: "folder", at: containerPath, + withProperties: { name: sourceFolder.name() + " - Edited" } +}); + +// Create an array of items to be processed + +var items = systemEvents.aliases.byName(sourcePath).diskItems; +var selectedItems = []; + +for (var i = 0; i < items.length; i++) { + var item = items[i]; + if (item.class() != "folder" && item.visible()) { + selectedItems.push(item.name()); + } +} + +// Process every item + +var createdFolders = []; +selectedItems.forEach(function(itemName) { + var item = systemEvents.aliases.byName(sourcePath + "/" + itemName); + var name = item.name().match(/(.*) - (.*)/); + try { + var folderName = name[1]; + if (!createdFolders.includes(folderName)) { + var newFolder = finder.make({ + new: "folder", at: destinationFolder, withProperties: { name: folderName } + }); + createdFolders.push(folderName); + } + item = finder.move(item.path(), { to: destinationFolder.folders[folderName] }); + item.name = name[2]; + } catch (error) { + console.log("Error (item: " + item.name() + "): " + error); + } +}); diff --git a/trash/add.js b/trash/add.js new file mode 100644 index 0000000..bb74418 --- /dev/null +++ b/trash/add.js @@ -0,0 +1,178 @@ +var systemEvents = Application("System Events"); + +var workspacesDir = "/Users/stef/dbox/src/safari-workspace/workspaces" + +function getWorkspaceNames() { + + var items = systemEvents.aliases.byName(path).diskItems; + var selectedItems = []; + + for (var i = 0; i < items.length; i++) { + var item = items[i]; + if (item.class() != "folder" && item.visible()) { + selectedItems.push(item.name().substring(0, item.name().length - 5)); + } + } + return selectedItems; +} + +function chooseWorkspaceFromList() { + + var app = Application.currentApplication() + app.includeStandardAdditions = true + + var choices = getWorkspaceNames() + var choice = app.chooseFromList(choices, { + withPrompt: "Workspace wählen:", + defaultItems: [0] + }) + + return choice + +} + + +function allWindows(){ + var app = Application("Safari") + var windows = [] + for(var i = 0; i < app.windows().length; i++){ + windows.push(app.windows.at(i).id()) + } + return windows + // return windows.sort(function(a, b){return a-b}) +} + +function newWindow(){ + var app = Application("Safari") + app.activate() + app.Document().make() + delay(1) + + return newWindowID(-1) +} + +function newWindowID(index){ + var app = Application("Safari") + var windows = allWindows() + if(index < 0){ + index = windows.length + index + } + return app.windows.byId(windows[index]).id() +} + +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 writeFile(pPathStr, pOutputStr) { + + var nsStr = $.NSString.alloc.initWithUTF8String(pOutputStr) + var nsPath = $(pPathStr).stringByStandardizingPath + 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 setWorkspaceProperties(workspaceName, workspaceProps) { + var path = workspacesDir + "/" + workspaceName + ".json" + var result = writeJson(path, selectedWorkspaceProps) + var success = result[0] + return success +} + +function getWorkspaceProperties(workspaceName) { + var result = readJson(workspacesDir + "/" + workspaceName + ".json") + if(result[0]){ + return result[1] + } + return {error: "workspace not found"} +} + +function newWorkspaceWindow(workspaceProps) { + + var winID = newWindow() + var win = {id: winID, tabs: []} + workspaceProps["Safari"].push(win) + + // add tab + // selectedWorkspaceProps["Safari"][0]["tabs"].push("http://example.com") +} + +function saveWorkspaceWindows() { + var app = Application("Safari") + // var windows = [] + for(var i = 0; i < app.windows().length; i++){ + + for (var j = 0; j < selectedWorkspaceProps["Safari"].length; j++) { + var workspaceWinID = selectedWorkspaceProps["Safari"][j].id + console.log(workspaceWinID, app.windows.at(i).id()) + // if(workspaceWinID == app.windows.at(i).id()){ + + // } + } + + + // windows.push(app.windows.at(i).id()) + + + } + } + +// var selectedWorkspaceName = chooseWorkspaceFromList() +var selectedWorkspaceName = "needle" +var selectedWorkspaceProps = getWorkspaceProperties(selectedWorkspaceName) +newWorkspaceWindow(selectedWorkspaceProps) +setWorkspaceProperties(selectedWorkspaceName, selectedWorkspaceProps) + + +saveWorkspaceWindows() +// console.log(JSON.stringify(selectedWorkspaceProps, null, 2)) + + +// console.log() + diff --git a/trash/choose.js b/trash/choose.js new file mode 100644 index 0000000..b93c6f7 --- /dev/null +++ b/trash/choose.js @@ -0,0 +1,38 @@ +var systemEvents = Application("System Events"); + + + +function getWorkspaceNames() { + var path = "/Users/stef/dbox/src/safari-workspace/workspaces" + var items = systemEvents.aliases.byName(path).diskItems; + var selectedItems = []; + + for (var i = 0; i < items.length; i++) { + var item = items[i]; + if (item.class() != "folder" && item.visible()) { + selectedItems.push(item.name().substring(0, item.name().length - 5)); + } + } + return selectedItems; +} + +function chooseWorkspaceFromList() { + + var app = Application.currentApplication() + app.includeStandardAdditions = true + + var choices = getWorkspaceNames() + var choice = app.chooseFromList(choices, { + withPrompt: "Workspace wählen:", + defaultItems: [0] + }) + + return choice + +} + + + + +console.log(chooseWorkspaceFromList()) + diff --git a/trash/folder.js b/trash/folder.js new file mode 100644 index 0000000..f2b9383 --- /dev/null +++ b/trash/folder.js @@ -0,0 +1,10 @@ +var app = Application.currentApplication() +app.includeStandardAdditions = true + +function readFile(file) { + // Convert the file to a string + var fileString = file.toString() + + // Read the file and return its contents + return app.read(Path(fileString)) +} \ No newline at end of file diff --git a/trash/run.js b/trash/run.js new file mode 100644 index 0000000..9b2403b --- /dev/null +++ b/trash/run.js @@ -0,0 +1,75 @@ +var app = Application("Safari") + +function newWorkspaceWindow(){ + app.activate() + app.Document().make() + // delay(1) + + // return window id + return newWindowID() +} + +function newWindowID(){ + + var windows = getAllWindows() + if(index < 0){ + index = windows.length + index + } + return app.windows.byId(windows[index]).id() +} + +/** + + @returns {Array} List of objects in the form {title: title, url:url} + +*/ +function tabsInWindowWithId(id){ + var urls = [] + if(!sys.windowExistWithId("Safari", id)){ + return urls + } + var win = app.windows.byId(id) + + for (var i = 0; i < win.tabs.length; i++) { + var url = win.tabs.at(i).url() + var name = win.tabs.at(i).name() + urls.push({name:name, url:url}) + } + return urls +} + + +function getAllWindows(){ + var windows = [] + for(var i = 0; i < app.windows().length; i++){ + windows.push(app.windows.at(i).id()) + } + return windows + // return windows.sort(function(a, b){return a-b}) +} + +function tabsInWindowAtIndex(index) { + var win + for(var i = 0; i < app.windows().length; i++){ + if(i == index){ + win = app.windows.at(i) + } + } + + var tabs = [] + for (var i = 0; i < win.tabs.length; i++) { + var url = win.tabs.at(i).url() + var title = win.tabs.at(i).name() + tabs.push({title: title, url: url}) + } + return tabs +} + +var tabs = tabsInWindowAtIndex(0) +for (var i = 0; i < tabs.length; i++) { + console.log(tabs[i].title, tabs[i].url) +} + +// console.log(getAllWindows()) +// console.log(newWorkspaceWindow()) + diff --git a/trash/safari.js b/trash/safari.js new file mode 100644 index 0000000..0566faa --- /dev/null +++ b/trash/safari.js @@ -0,0 +1,224 @@ +#!/usr/bin/env osascript -l JavaScript + +var sys = Library("system") +var app = Application('Safari') +var workspace + +function setWorkspace(w){ + workspace = w + sys.setWorkspace(w) +} + +function create(url){ + app.Document().make().url = url + delay(1) + return sys.windowID("Safari", -1) +} + +/** + + @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() { + var result = sys.retrieve("Safari") + var success = result[0] + var wlist = result[1] + if(!success){ + return [] + } + return wlist +} + +// var url = "https://news.ycombinator.com/" +// var name = "HN" +// var id = safari.create(url) +// console.log("id", id) +// if(id != -1){ +// var workspaceWindow = {id:id, url:url, name:name } +// wlist.push(workspaceWindow) +// if(store(appName, wlist)[0]){ +// return true +// } +// } + +function addWorkspaceWindow(){ + var wlist = workspaceWindows() + var name = "HN" + var url = "https://news.ycombinator.com/" + var id = create(url) + + if(id != -1){ + var workspaceWindow = {id:id, tabs:[{url:url, name:name}] } + wlist.push(workspaceWindow) + if(sys.store("Safari", wlist)[0]){ + return true + } + } + return false +} + +function deleteWorkspaceWindow() { + list() + var index = parseInt(sys.prompt("The window at which index would you delete?", -1)) + if (index < 0){ + return false + } + + var wlist = workspaceWindows() + console.log("list", wlist.length, "index", index) + if(wlist.length > index){ + var win = wlist[index] + var id = win["id"] + console.log("win", JSON.stringify(win)) + if(sys.windowExistWithId("Safari", id)){ + app.close(app.windows.byId(id)) + } + wlist.splice(index, 1) + sys.store("Safari", wlist) + }else{ + console.log("out of range") + } + +} + + + +/** + + @desc Print list of all open Terminal windows. + +**/ + +function list() { + var wlist = workspaceWindows() + for (var i = 0; i < wlist.length; i++) { + var id = wlist[i]["id"] + var running = sys.windowExistWithId("Safari", id) + var winName = "" + var tabCount = wlist[i]["tabs"].length + var win = null + if(running){ + win = app.windows.byId(id) + winName = win.name() + tabCount = win.tabs.length + 1 + } + console.log(i, id, "tabs", tabCount, "running", running , winName) + } +} + +function addTab(id, url){ + var tab = app.Tab() + tab.url = url + var win = app.windows.byId(id) + win.tabs.push(tab) +} + +function open(){ + + var wlist = workspaceWindows() + var changed = false + // define new window if none are there + if(wlist.length == 0){ + var win + var url = arguments[0] + if(arguments.length > 0){ + win = {id:0, tabs:[{name:"", url:url}]} + }else{ + win = {id:0, tabs:[{name:"HN", url:"http://news.ycombinator.com"}]} + } + wlist.push(win) + changed = true + } + + + // create windows + for (var i = 0; i < wlist.length; i++) { + var win = wlist[i] + var id = win.id + if(!sys.windowExistWithId("Safari", id)){ + + var tabs = wlist[i]["tabs"] + var windowID = create(tabs[0]["url"]) + wlist[i]["id"] = windowID // update window id in file + changed = true + for (var j = 1; j < tabs.length; j++) { + if(tabs[j]["url"] != null){ + addTab(windowID, tabs[j]["url"]) + } + } + } + } + + if(changed){ + sys.store("Safari", wlist) + } + + return true +} + + + +function save(wlist){ + + if(wlist.length == 0) return false + + for (var i = 0; i < wlist.length; i++) { + var win = wlist[i] + var id = win.id + if(sys.windowExistWithId("Safari", id)){ + var tabs = tabsInWindowWithId(id) + if(tabs.length > 0){ + wlist[i]["tabs"] = tabs + } + } + } + return sys.store("Safari", wlist)[0] +} + +function close(){ + + var wlist = workspaceWindows() + + if(wlist.length == 0) return false + + if(!save(wlist)){ + console.log("safari window save error") + } + + for (var i = 0; i < wlist.length; i++) { + + try{ + // var win = wlist[i] + // var id = win.id + // console.log("close", JSON.stringify(wlist[i])) + app.close(app.windows.byId(wlist[i]["id"])) + }catch(err){} + } + return true +} + +/** + + @returns {Array} List of objects in the form {url:url, name:name} + +*/ +function tabsInWindowWithId(id){ + var urls = [] + if(!sys.windowExistWithId("Safari", id)){ + return urls + } + var win = app.windows.byId(id) + + for (var i = 0; i < win.tabs.length; i++) { + var url = win.tabs.at(i).url() + var name = win.tabs.at(i).name() + urls.push({name:name, url:url}) + } + return urls +} diff --git a/trash/save.js b/trash/save.js new file mode 100644 index 0000000..9a3bad8 --- /dev/null +++ b/trash/save.js @@ -0,0 +1,320 @@ +var systemEvents = Application("System Events"); +var workspace = Library("workspace") + + +// return +var workspacesDir = "/Users/stef/dbox/src/safari-workspace/workspaces" +var app = Application("Safari") +// var selectedWorkspaceName = "needle" +// var selectedWorkspaceName = chooseWorkspaceFromList() +// var selectedWorkspaceProps = getWorkspaceProperties(selectedWorkspaceName) +// console.log(JSON.stringify(selectedWorkspaceProps, null, 2)) + +// New Workspace... +// New Workspace Window... +// Open Workspace... +// Close Workspace... +// Save Workspace... + +// workspace.js +// system.js + +// close.js +// save.js +// open.js +// new.js +// window.js + + +function getWorkspaceNames() { + + var items = systemEvents.aliases.byName(path).diskItems; + var selectedItems = []; + + for (var i = 0; i < items.length; i++) { + var item = items[i]; + if (item.class() != "folder" && item.visible()) { + selectedItems.push(item.name().substring(0, item.name().length - 5)); + } + } + return selectedItems; +} + +function chooseWorkspaceFromList() { + + var app = Application.currentApplication() + app.includeStandardAdditions = true + + var choices = getWorkspaceNames() + var choice = app.chooseFromList(choices, { + withPrompt: "Workspace wählen:", + defaultItems: [0] + }) + + return choice + +} + + +function allWindows(){ + var app = Application("Safari") + var windows = [] + for(var i = 0; i < app.windows().length; i++){ + windows.push(app.windows.at(i).id()) + } + // return windows + return windows.sort(function(a, b){return a-b}) +} + +function newWindow(){ + var app = Application("Safari") + app.activate() + app.Document().make() + console.log(app.windows().length) + // delay(1) + // console.log(app.windows().length) + + var windows = allWindows() + return windows[windows.length - 1] + +} + +function newWindowID(index){ + var app = Application("Safari") + var windows = allWindows() + if(index < 0){ + index = windows.length + index + } + return app.windows.byId(windows[index]).id() +} + +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 writeFile(pPathStr, pOutputStr) { + + var nsStr = $.NSString.alloc.initWithUTF8String(pOutputStr) + var nsPath = $(pPathStr).stringByStandardizingPath + 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 saveWorkspaceProperties(workspaceName, workspaceProps) { + var path = workspacesDir + "/" + workspaceName + ".json" + var result = writeJson(path, selectedWorkspaceProps) + var success = result[0] + return success +} + +function getWorkspaceProperties(workspaceName) { + var result = readJson(workspacesDir + "/" + workspaceName + ".json") + if(result[0]){ + return result[1] + } + return {error: "workspace not found"} +} + +function newWorkspaceWindow(workspaceProps) { + + var winID = newWindow() + var win = {id: winID, tabs: []} + workspaceProps["Safari"].push(win) + +} + +function tabsInWindowWithId(id){ + var urls = [] + if(!sys.windowExistWithId("Safari", id)){ + return urls + } + var win = app.windows.byId(id) + + for (var i = 0; i < win.tabs.length; i++) { + var url = win.tabs.at(i).url() + var name = win.tabs.at(i).name() + urls.push({name:name, url:url}) + } + return urls +} + +function saveWorkspaceWindows() { + var app = Application("Safari") + + for(var i = 0; i < app.windows().length; i++){ + + var openWindow = app.windows.at(i) + // console.log("Safari window", openWindow.id()) + for (var j = 0; j < selectedWorkspaceProps["Safari"].length; j++) { + + var workspaceWindow = selectedWorkspaceProps["Safari"][j] + // console.log("workspaceWindow.id", workspaceWindow.id) + + if(openWindow.id() == workspaceWindow.id){ + + workspaceWindow.tabs = [] + for (var k = 0; k < app.windows.at(i).tabs.length; k++) { + var url = openWindow.tabs.at(k).url() + if(url){ + workspaceWindow.tabs.push(url) + } + } + } + } + } + saveWorkspaceProperties(selectedWorkspaceName, selectedWorkspaceProps) +} + + + +function closeWorkspaceWindows() { + + saveWorkspaceWindows() + + var app = Application("Safari") + for (var i = 0; i < selectedWorkspaceProps["Safari"].length; i++) { + + var workspaceWindow = selectedWorkspaceProps["Safari"][i] + for(var j = 0; j < app.windows().length; j++){ + var openWindow = app.windows.at(j) + + if(openWindow.id() == workspaceWindow.id){ + app.close(app.windows.byId(openWindow.id())) + } + } + + } + + + + + + + + + // for(var i = 0; i < app.windows().length; i++){ + + // var openWindow = app.windows.at(i) + // console.log("Safari window", openWindow.id()) + // for (var j = 0; j < selectedWorkspaceProps["Safari"].length; j++) { + + // var workspaceWindow = selectedWorkspaceProps["Safari"][j] + // console.log("workspaceWindow.id", workspaceWindow.id) + + // if(openWindow.id() == workspaceWindow.id){ + // app.close(app.windows.byId(openWindow.id())) + // } + // } + // } +} + +function addTab(id, url){ + var app = Application("Safari") + var tab = app.Tab() + tab.url = url + var win = app.windows.byId(id) + win.tabs.push(tab) +} + +function openWorkspaceWindows() { + + var app = Application("Safari") + for (var i = 0; i < selectedWorkspaceProps["Safari"].length; i++) { + + var workspaceWindow = selectedWorkspaceProps["Safari"][i] + var windowExists = false + for(var j = 0; j < app.windows().length; j++){ + var openWindow = app.windows.at(j) + if(openWindow.id() == workspaceWindow.id){ + windowExists = true + } + } + + if(!windowExists){ + + var newWindowID = newWindow() + // console.log("new window created", newWindowID) + workspaceWindow.id = newWindowID + for (var k = 0; k < workspaceWindow.tabs.length; k++) { + // console.log(workspaceWindow.tabs[k]) + addTab(newWindowID, workspaceWindow.tabs[k]) + } + }else{ + console.log("window exists", workspaceWindow.id) + + } + + saveWorkspaceProperties(selectedWorkspaceName, selectedWorkspaceProps) + } +} + +// console.log(allWindows()) +// newWorkspaceWindow(selectedWorkspaceProps) +// setWorkspaceProperties(selectedWorkspaceName, selectedWorkspaceProps) +// console.log(allWindows()) + +// openWorkspaceWindows() + +// closeWorkspaceWindows() + +// console.log(app.windows().length) + + +// saveWorkspaceWindows() + + +var selectedWorkspaceName = workspace.chooseFromList() + + + + +// workspace.openWindows(selectedWorkspaceName) +workspace.closeWindows(selectedWorkspaceName) + +// console.log(JSON.stringify(selectedWorkspaceProps, null, 2)) diff --git a/trash/system.js b/trash/system.js new file mode 100644 index 0000000..ff9e49c --- /dev/null +++ b/trash/system.js @@ -0,0 +1,495 @@ +#!/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 + } +} diff --git a/workflows/Add Window.workflow/Contents/Info.plist b/workflows/Add Window.workflow/Contents/Info.plist new file mode 100644 index 0000000..666a4a9 --- /dev/null +++ b/workflows/Add Window.workflow/Contents/Info.plist @@ -0,0 +1,23 @@ + + + + + NSServices + + + NSMenuItem + + default + Add Window To Workspace + + NSMessage + runWorkflowAsService + NSRequiredContext + + NSApplicationIdentifier + com.apple.Safari + + + + + diff --git a/workflows/Add Window.workflow/Contents/QuickLook/Thumbnail.png b/workflows/Add Window.workflow/Contents/QuickLook/Thumbnail.png new file mode 100644 index 0000000..6c44b52 Binary files /dev/null and b/workflows/Add Window.workflow/Contents/QuickLook/Thumbnail.png differ diff --git a/workflows/Add Window.workflow/Contents/document.wflow b/workflows/Add Window.workflow/Contents/document.wflow new file mode 100644 index 0000000..faa5215 --- /dev/null +++ b/workflows/Add Window.workflow/Contents/document.wflow @@ -0,0 +1,151 @@ + + + + + AMApplicationBuild + 419 + AMApplicationVersion + 2.6 + AMDocumentVersion + 2 + actions + + + action + + AMAccepts + + Container + List + Optional + + Types + + com.apple.applescript.object + + + AMActionVersion + 1.0 + AMApplication + + Automator + + AMParameterProperties + + source + + + AMProvides + + Container + List + Types + + com.apple.applescript.object + + + ActionBundlePath + /System/Library/Automator/Run JavaScript.action + ActionName + Run JavaScript + ActionParameters + + source + var workspace = Library("workspace") + +var name = workspace.chooseFromList("Add Window") + +if(name){ + + + var title = workspace.chooseFromSafariWindows() + console.log(title) + var id = workspace.safariWindowWithTitle(title) + console.log(id) + workspace.addWindowToWorkspace(id, name) + +} + + + BundleIdentifier + com.apple.Automator.RunJavaScript + CFBundleVersion + 1.0 + CanShowSelectedItemsWhenRun + + CanShowWhenRun + + Category + + AMCategoryUtilities + + Class Name + RunJavaScriptAction + InputUUID + 37B74330-193E-4E8D-B449-ED2F571F6AE5 + Keywords + + Run + JavaScript + + OutputUUID + 7B06B951-BB15-4304-B518-A1341F0FFE23 + UUID + FF274825-2F9A-47B9-9400-46CEA70220FA + UnlocalizedApplications + + Automator + + arguments + + 0 + + default value + function run(input, parameters) { + + // Your script goes here + + return input; +} + name + source + required + 0 + type + 0 + uuid + 0 + + + conversionLabel + 0 + isViewVisible + + location + 309.000000:316.000000 + nibPath + /System/Library/Automator/Run JavaScript.action/Contents/Resources/Base.lproj/main.nib + + isViewVisible + + + + connectors + + workflowMetaData + + serviceApplicationBundleID + com.apple.Safari + serviceApplicationPath + /Applications/Safari.app + serviceInputTypeIdentifier + com.apple.Automator.nothing + serviceOutputTypeIdentifier + com.apple.Automator.nothing + serviceProcessesInput + 0 + workflowTypeIdentifier + com.apple.Automator.servicesMenu + + + diff --git a/workflows/Close Workspace.workflow/Contents/Info.plist b/workflows/Close Workspace.workflow/Contents/Info.plist new file mode 100644 index 0000000..2974e4d --- /dev/null +++ b/workflows/Close Workspace.workflow/Contents/Info.plist @@ -0,0 +1,23 @@ + + + + + NSServices + + + NSMenuItem + + default + Close Workspace + + NSMessage + runWorkflowAsService + NSRequiredContext + + NSApplicationIdentifier + com.apple.Safari + + + + + diff --git a/workflows/Close Workspace.workflow/Contents/QuickLook/Thumbnail.png b/workflows/Close Workspace.workflow/Contents/QuickLook/Thumbnail.png new file mode 100644 index 0000000..e203785 Binary files /dev/null and b/workflows/Close Workspace.workflow/Contents/QuickLook/Thumbnail.png differ diff --git a/workflows/Close Workspace.workflow/Contents/document.wflow b/workflows/Close Workspace.workflow/Contents/document.wflow new file mode 100644 index 0000000..906b632 --- /dev/null +++ b/workflows/Close Workspace.workflow/Contents/document.wflow @@ -0,0 +1,135 @@ + + + + + AMApplicationBuild + 419 + AMApplicationVersion + 2.6 + AMDocumentVersion + 2 + actions + + + action + + AMAccepts + + Container + List + Optional + + Types + + com.apple.applescript.object + + + AMActionVersion + 1.0 + AMApplication + + Automator + + AMParameterProperties + + source + + + AMProvides + + Container + List + Types + + com.apple.applescript.object + + + ActionBundlePath + /System/Library/Automator/Run JavaScript.action + ActionName + Run JavaScript + ActionParameters + + source + var workspace = Library("workspace") var name = workspace.chooseFromList("Close Workspace") if(name){ workspace.closeWindows(name) } + + BundleIdentifier + com.apple.Automator.RunJavaScript + CFBundleVersion + 1.0 + CanShowSelectedItemsWhenRun + + CanShowWhenRun + + Category + + AMCategoryUtilities + + Class Name + RunJavaScriptAction + InputUUID + 7F9F1DE1-A7A7-49ED-A176-8CDD7720140D + Keywords + + Run + JavaScript + + OutputUUID + 16DCD07D-E279-4864-8A3C-5DC99A710768 + UUID + D470416C-8650-4D12-BAC5-BB0A833E5B38 + UnlocalizedApplications + + Automator + + arguments + + 0 + + default value + function run(input, parameters) { + + // Your script goes here + + return input; +} + name + source + required + 0 + type + 0 + uuid + 0 + + + isViewVisible + + location + 309.000000:316.000000 + nibPath + /System/Library/Automator/Run JavaScript.action/Contents/Resources/Base.lproj/main.nib + + isViewVisible + + + + connectors + + workflowMetaData + + serviceApplicationBundleID + com.apple.Safari + serviceApplicationPath + /Applications/Safari.app + serviceInputTypeIdentifier + com.apple.Automator.nothing + serviceOutputTypeIdentifier + com.apple.Automator.nothing + serviceProcessesInput + 0 + workflowTypeIdentifier + com.apple.Automator.servicesMenu + + + diff --git a/workflows/New Window.workflow/Contents/Info.plist b/workflows/New Window.workflow/Contents/Info.plist new file mode 100644 index 0000000..c6febd8 --- /dev/null +++ b/workflows/New Window.workflow/Contents/Info.plist @@ -0,0 +1,18 @@ + + + + + NSServices + + + NSMenuItem + + default + New Window in Workspace + + NSMessage + runWorkflowAsService + + + + diff --git a/workflows/New Window.workflow/Contents/QuickLook/Thumbnail.png b/workflows/New Window.workflow/Contents/QuickLook/Thumbnail.png new file mode 100644 index 0000000..a359727 Binary files /dev/null and b/workflows/New Window.workflow/Contents/QuickLook/Thumbnail.png differ diff --git a/workflows/New Window.workflow/Contents/document.wflow b/workflows/New Window.workflow/Contents/document.wflow new file mode 100644 index 0000000..3684d67 --- /dev/null +++ b/workflows/New Window.workflow/Contents/document.wflow @@ -0,0 +1,131 @@ + + + + + AMApplicationBuild + 419 + AMApplicationVersion + 2.6 + AMDocumentVersion + 2 + actions + + + action + + AMAccepts + + Container + List + Optional + + Types + + com.apple.applescript.object + + + AMActionVersion + 1.0 + AMApplication + + Automator + + AMParameterProperties + + source + + + AMProvides + + Container + List + Types + + com.apple.applescript.object + + + ActionBundlePath + /System/Library/Automator/Run JavaScript.action + ActionName + Run JavaScript + ActionParameters + + source + var workspace = Library("workspace") var name = workspace.chooseFromList("New Window") if(name){ workspace.addNewWindowTo(name) } + + BundleIdentifier + com.apple.Automator.RunJavaScript + CFBundleVersion + 1.0 + CanShowSelectedItemsWhenRun + + CanShowWhenRun + + Category + + AMCategoryUtilities + + Class Name + RunJavaScriptAction + InputUUID + 190315AD-4027-4B5C-84D3-69AB00B3AFC9 + Keywords + + Run + JavaScript + + OutputUUID + CD7CCA8B-A359-4B72-AB5D-BE73FB396D47 + UUID + 28E27097-50F3-41CE-92CF-4CE61B499309 + UnlocalizedApplications + + Automator + + arguments + + 0 + + default value + function run(input, parameters) { + + // Your script goes here + + return input; +} + name + source + required + 0 + type + 0 + uuid + 0 + + + isViewVisible + + location + 309.000000:316.000000 + nibPath + /System/Library/Automator/Run JavaScript.action/Contents/Resources/Base.lproj/main.nib + + isViewVisible + + + + connectors + + workflowMetaData + + serviceInputTypeIdentifier + com.apple.Automator.nothing + serviceOutputTypeIdentifier + com.apple.Automator.nothing + serviceProcessesInput + 0 + workflowTypeIdentifier + com.apple.Automator.servicesMenu + + + diff --git a/workflows/New Workspace.workflow/Contents/Info.plist b/workflows/New Workspace.workflow/Contents/Info.plist new file mode 100644 index 0000000..6c0c7f7 --- /dev/null +++ b/workflows/New Workspace.workflow/Contents/Info.plist @@ -0,0 +1,23 @@ + + + + + NSServices + + + NSMenuItem + + default + New Workspace + + NSMessage + runWorkflowAsService + NSRequiredContext + + NSApplicationIdentifier + com.apple.Safari + + + + + diff --git a/workflows/New Workspace.workflow/Contents/QuickLook/Thumbnail.png b/workflows/New Workspace.workflow/Contents/QuickLook/Thumbnail.png new file mode 100644 index 0000000..3f294ab Binary files /dev/null and b/workflows/New Workspace.workflow/Contents/QuickLook/Thumbnail.png differ diff --git a/workflows/New Workspace.workflow/Contents/document.wflow b/workflows/New Workspace.workflow/Contents/document.wflow new file mode 100644 index 0000000..4d9b138 --- /dev/null +++ b/workflows/New Workspace.workflow/Contents/document.wflow @@ -0,0 +1,135 @@ + + + + + AMApplicationBuild + 419 + AMApplicationVersion + 2.6 + AMDocumentVersion + 2 + actions + + + action + + AMAccepts + + Container + List + Optional + + Types + + com.apple.applescript.object + + + AMActionVersion + 1.0 + AMApplication + + Automator + + AMParameterProperties + + source + + + AMProvides + + Container + List + Types + + com.apple.applescript.object + + + ActionBundlePath + /System/Library/Automator/Run JavaScript.action + ActionName + Run JavaScript + ActionParameters + + source + var workspace = Library("workspace") var app = Application.currentApplication() app.includeStandardAdditions = true var response = app.displayDialog("Enter Name for New Workspace", { defaultAnswer: "", withIcon: "note", buttons: ["Cancel", "Continue"], defaultButton: "Continue" }) var selectedWorkspaceName = response.textReturned var allWorkspaceNames = workspace.getNames() for (var i = 0; i < allWorkspaceNames.length; i++) { if(allWorkspaceNames[i] == selectedWorkspaceName){ var response = app.displayDialog(" Workspace name already used. Please choose another", { defaultAnswer: "", withIcon: "note" }) } } var selectedWorkspaceProps = { Safari: [] } workspace.saveProperties(selectedWorkspaceName, selectedWorkspaceProps) workspace.addNewWindowTo(selectedWorkspaceName) // Result: {"buttonReturned":"Continue", "textReturned":"Jen"} // app.displayDialog("Hello, " + (response.textReturned) + ".") + + BundleIdentifier + com.apple.Automator.RunJavaScript + CFBundleVersion + 1.0 + CanShowSelectedItemsWhenRun + + CanShowWhenRun + + Category + + AMCategoryUtilities + + Class Name + RunJavaScriptAction + InputUUID + FBE6C993-52EE-41D0-BD21-930E380F6DDF + Keywords + + Run + JavaScript + + OutputUUID + B523AC97-AB88-4C3B-9AD9-7A312D268481 + UUID + 209EE2EE-6708-4074-A81D-C22F65CAC830 + UnlocalizedApplications + + Automator + + arguments + + 0 + + default value + function run(input, parameters) { + + // Your script goes here + + return input; +} + name + source + required + 0 + type + 0 + uuid + 0 + + + isViewVisible + + location + 309.000000:316.000000 + nibPath + /System/Library/Automator/Run JavaScript.action/Contents/Resources/Base.lproj/main.nib + + isViewVisible + + + + connectors + + workflowMetaData + + serviceApplicationBundleID + com.apple.Safari + serviceApplicationPath + /Applications/Safari.app + serviceInputTypeIdentifier + com.apple.Automator.nothing + serviceOutputTypeIdentifier + com.apple.Automator.nothing + serviceProcessesInput + 0 + workflowTypeIdentifier + com.apple.Automator.servicesMenu + + + diff --git a/workflows/Open Workspace.workflow/Contents/Info.plist b/workflows/Open Workspace.workflow/Contents/Info.plist new file mode 100644 index 0000000..44f13a9 --- /dev/null +++ b/workflows/Open Workspace.workflow/Contents/Info.plist @@ -0,0 +1,23 @@ + + + + + NSServices + + + NSMenuItem + + default + Open Workspace + + NSMessage + runWorkflowAsService + NSRequiredContext + + NSApplicationIdentifier + com.apple.Safari + + + + + diff --git a/workflows/Open Workspace.workflow/Contents/QuickLook/Thumbnail.png b/workflows/Open Workspace.workflow/Contents/QuickLook/Thumbnail.png new file mode 100644 index 0000000..c437ff6 Binary files /dev/null and b/workflows/Open Workspace.workflow/Contents/QuickLook/Thumbnail.png differ diff --git a/workflows/Open Workspace.workflow/Contents/document.wflow b/workflows/Open Workspace.workflow/Contents/document.wflow new file mode 100644 index 0000000..9024936 --- /dev/null +++ b/workflows/Open Workspace.workflow/Contents/document.wflow @@ -0,0 +1,135 @@ + + + + + AMApplicationBuild + 419 + AMApplicationVersion + 2.6 + AMDocumentVersion + 2 + actions + + + action + + AMAccepts + + Container + List + Optional + + Types + + com.apple.applescript.object + + + AMActionVersion + 1.0 + AMApplication + + Automator + + AMParameterProperties + + source + + + AMProvides + + Container + List + Types + + com.apple.applescript.object + + + ActionBundlePath + /System/Library/Automator/Run JavaScript.action + ActionName + Run JavaScript + ActionParameters + + source + var workspace = Library("workspace") var name = workspace.chooseFromList("Open Workspace") if(name){ workspace.openWindows(name) } + + BundleIdentifier + com.apple.Automator.RunJavaScript + CFBundleVersion + 1.0 + CanShowSelectedItemsWhenRun + + CanShowWhenRun + + Category + + AMCategoryUtilities + + Class Name + RunJavaScriptAction + InputUUID + 9200F188-26ED-423E-8D71-61A932B6BE4C + Keywords + + Run + JavaScript + + OutputUUID + 2F558129-08B8-481D-9E70-569BCD136E2F + UUID + E99A67F6-D636-437E-BDF8-E5DD1DD9A644 + UnlocalizedApplications + + Automator + + arguments + + 0 + + default value + function run(input, parameters) { + + // Your script goes here + + return input; +} + name + source + required + 0 + type + 0 + uuid + 0 + + + isViewVisible + + location + 309.000000:316.000000 + nibPath + /System/Library/Automator/Run JavaScript.action/Contents/Resources/Base.lproj/main.nib + + isViewVisible + + + + connectors + + workflowMetaData + + serviceApplicationBundleID + com.apple.Safari + serviceApplicationPath + /Applications/Safari.app + serviceInputTypeIdentifier + com.apple.Automator.nothing + serviceOutputTypeIdentifier + com.apple.Automator.nothing + serviceProcessesInput + 0 + workflowTypeIdentifier + com.apple.Automator.servicesMenu + + + diff --git a/workflows/Save Workspace.workflow/Contents/Info.plist b/workflows/Save Workspace.workflow/Contents/Info.plist new file mode 100644 index 0000000..e2e3d5a --- /dev/null +++ b/workflows/Save Workspace.workflow/Contents/Info.plist @@ -0,0 +1,23 @@ + + + + + NSServices + + + NSMenuItem + + default + Save Workspace + + NSMessage + runWorkflowAsService + NSRequiredContext + + NSApplicationIdentifier + com.apple.Safari + + + + + diff --git a/workflows/Save Workspace.workflow/Contents/QuickLook/Thumbnail.png b/workflows/Save Workspace.workflow/Contents/QuickLook/Thumbnail.png new file mode 100644 index 0000000..1803556 Binary files /dev/null and b/workflows/Save Workspace.workflow/Contents/QuickLook/Thumbnail.png differ diff --git a/workflows/Save Workspace.workflow/Contents/document.wflow b/workflows/Save Workspace.workflow/Contents/document.wflow new file mode 100644 index 0000000..818e582 --- /dev/null +++ b/workflows/Save Workspace.workflow/Contents/document.wflow @@ -0,0 +1,135 @@ + + + + + AMApplicationBuild + 419 + AMApplicationVersion + 2.6 + AMDocumentVersion + 2 + actions + + + action + + AMAccepts + + Container + List + Optional + + Types + + com.apple.applescript.object + + + AMActionVersion + 1.0 + AMApplication + + Automator + + AMParameterProperties + + source + + + AMProvides + + Container + List + Types + + com.apple.applescript.object + + + ActionBundlePath + /System/Library/Automator/Run JavaScript.action + ActionName + Run JavaScript + ActionParameters + + source + var workspace = Library("workspace") var name = workspace.chooseFromList("Save Workspace") if(name){ workspace.saveWindows(name, workspace.readProperties(name)) } + + BundleIdentifier + com.apple.Automator.RunJavaScript + CFBundleVersion + 1.0 + CanShowSelectedItemsWhenRun + + CanShowWhenRun + + Category + + AMCategoryUtilities + + Class Name + RunJavaScriptAction + InputUUID + DD014771-EE7F-4EDD-9B50-AF9B03DA109A + Keywords + + Run + JavaScript + + OutputUUID + B727F99B-F58C-4CD5-80D5-DB5FAEA23AC8 + UUID + 6429699E-98F2-402B-ABE3-B57AFA0D5485 + UnlocalizedApplications + + Automator + + arguments + + 0 + + default value + function run(input, parameters) { + + // Your script goes here + + return input; +} + name + source + required + 0 + type + 0 + uuid + 0 + + + isViewVisible + + location + 309.000000:316.000000 + nibPath + /System/Library/Automator/Run JavaScript.action/Contents/Resources/Base.lproj/main.nib + + isViewVisible + + + + connectors + + workflowMetaData + + serviceApplicationBundleID + com.apple.Safari + serviceApplicationPath + /Applications/Safari.app + serviceInputTypeIdentifier + com.apple.Automator.nothing + serviceOutputTypeIdentifier + com.apple.Automator.nothing + serviceProcessesInput + 0 + workflowTypeIdentifier + com.apple.Automator.servicesMenu + + + diff --git a/workspace.js b/workspace.js new file mode 100644 index 0000000..e287485 --- /dev/null +++ b/workspace.js @@ -0,0 +1,289 @@ +var systemEvents = Application("System Events") +var os = Library("os") + +var workspacesDir = os.env("HOME") + "/.safari-workspaces" + +function getNames() { + + var items = systemEvents.aliases.byName(workspacesDir).diskItems; + var selectedItems = []; + + for (var i = 0; i < items.length; i++) { + var item = items[i]; + if (item.class() != "folder" && item.visible()) { + selectedItems.push(item.name().substring(0, item.name().length - 5)); + } + } + return selectedItems; +} + +function chooseFromList(title) { + + if(!title){ + title = "Choose Workspace" + } + + var app = Application.currentApplication() + app.includeStandardAdditions = true + app.activate() + + var choices = getNames() + var choice = app.chooseFromList(choices, { + withPrompt: title, + defaultItems: choices[0], + buttons: ["Cancel", "OK"], + defaultButton: "OK" + }) + + // if(!choice){ + // choice = "" + // } + + return choice +} + +function getSafariWindowTitles() { + + var app = Application('Safari') + var titles = [] + var windows = app.windows() + for (var k = 0; k < windows.length; k++) { + + var url = app.windows.at(k).currentTab.url() + var name = app.windows.at(k).currentTab.name() + var id = app.windows.at(k).id() + titles.push(name) + } + return titles +} + +function safariWindowWithTitle(title) { + var app = Application('Safari') + var windows = app.windows() + for (var k = 0; k < windows.length; k++) { + + var name = app.windows.at(k).currentTab.name() + if(name == title){ + var id = app.windows.at(k).id() + return id + } + } + return -1 +} + +function chooseFromSafariWindows() { + + var app = Application.currentApplication() + app.includeStandardAdditions = true + app.activate() + + var choices = getSafariWindowTitles() + var choice = app.chooseFromList(choices, { + withPrompt: "Choose Window:", + defaultItems: choices[0] + }) + + return choice +} + +function saveProperties(workspaceName, workspaceProps) { + var path = workspacesDir + "/" + workspaceName + ".json" + var result = os.writeJson(path, workspaceProps) + var success = result[0] + return success +} + +function readProperties(workspaceName) { + var result = os.readJson(workspacesDir + "/" + workspaceName + ".json") + if(result[0]){ + return result[1] + } + return {error: "workspace not found"} +} + +function addTab(id, url){ + var app = Application("Safari") + var tab = app.Tab() + tab.url = url + var win = app.windows.byId(id) + win.tabs.push(tab) +} + +function allWindows(){ + var app = Application("Safari") + var windows = [] + for(var i = 0; i < app.windows().length; i++){ + windows.push(app.windows.at(i).id()) + } + return windows.sort(function(a, b){return a-b}) +} + +function newWindow(url){ + + var app = Application("Safari") + app.activate() + + if(url){ + app.Document({url: url}).make() + }else{ + app.Document().make() + } + + var windows = allWindows() + return windows[windows.length - 1] +} + +function addNewWindowTo(workspaceName) { + + var workspaceProps = readProperties(workspaceName) + var winID = newWindow() + var workspaceWindow = {id: winID, tabs: []} + workspaceProps["Safari"].push(workspaceWindow) + saveProperties(workspaceName, workspaceProps) +} + +function shouldIgnoreUrl(url) { + var urls = [ + "https://gl.intermodi.cc", + "https://news.ycombinator.com", + "https://git.iris-cloud.de", + "https://web.threema.ch", + "https://kdw.intermodi.cc", + "http://euangoddard.github.io/clipboard2markdown/", + "safari-resource:/ErrorPage.html" + ] + + for (var i = 0; i < urls.length; i++) { + if(url.startsWith(urls[i])){ + return true + } + } + return false +} +function openWindows(workspaceName) { + + var workspaceProps = readProperties(workspaceName) + + var app = Application("Safari") + + for (var i = 0; i < workspaceProps["Safari"].length; i++) { + + var workspaceWindow = workspaceProps["Safari"][i] + var windowExists = false + for(var j = 0; j < app.windows().length; j++){ + var openWindow = app.windows.at(j) + if(openWindow.id() == workspaceWindow.id){ + windowExists = true + } + } + + if(!windowExists){ + + var firstTab = workspaceWindow.tabs[0] + var newWindowID = newWindow(firstTab) + // console.log("new window created", newWindowID) + workspaceWindow.id = newWindowID + for (var k = 1; k < workspaceWindow.tabs.length; k++) { + // console.log(workspaceWindow.tabs[k]) + var url = workspaceWindow.tabs[k] + if(!shouldIgnoreUrl(url)){ + addTab(newWindowID, workspaceWindow.tabs[k]) + } + } + }else{ + console.log("window exists", workspaceWindow.id) + } + saveProperties(workspaceName, workspaceProps) + } +} + +function saveWindows(workspaceName, workspaceProps) { + + var app = Application("Safari") + + for(var i = 0; i < app.windows().length; i++){ + + var openWindow = app.windows.at(i) + // console.log("Safari window", openWindow.id()) + for (var j = 0; j < workspaceProps["Safari"].length; j++) { + + var workspaceWindow = workspaceProps["Safari"][j] + if(openWindow.id() == workspaceWindow.id){ + + workspaceWindow.tabs = [] + for (var k = 0; k < app.windows.at(i).tabs.length; k++) { + + var url = openWindow.tabs.at(k).url() + if(url){ + if(!shouldIgnoreUrl(url)){ + workspaceWindow.tabs.push(url) + } + } + } + } + } + } + log(workspaceProps) + saveProperties(workspaceName, workspaceProps) +} + +function log(obj) { + console.log(JSON.stringify(obj, null, 2)) +} + +function addWindowToWorkspace(id, workspaceName) { + var app = Application("Safari") + var openWindow = app.windows.byId(id) + var workspaceProps = readProperties(workspaceName) + var workspaceWindow = {id: id, tabs: []} + for (var k = 0; k < openWindow.tabs.length; k++) { + + var url = openWindow.tabs.at(k).url() + if(url){ + if(!shouldIgnoreUrl(url)){ + workspaceWindow.tabs.push(url) + } + } + } + workspaceProps["Safari"].push(workspaceWindow) + saveWindows(workspaceName, workspaceProps) +} + +// todo: choose from list for window to remove from workspace +function closeWindows(workspaceName) { + + var app = Application("Safari") + var workspaceProps = readProperties(workspaceName) + saveWindows(workspaceName, workspaceProps) + var windowsToRemove = [] + + for (var i = 0; i < workspaceProps["Safari"].length; i++) { + + var workspaceWindow = workspaceProps["Safari"][i] + + try{ + app.close(app.windows.byId(workspaceWindow.id)) + }catch(err){ + // fenster die vorher manuell geschlossen wurden + // werden aus der liste an fenstern entfernt + // windowsToRemove.push(workspaceProps["Safari"][i].id) + + } + } + + // for (var i = 0; i < workspaceProps["Safari"].length; i++) { + + // var workspaceWindow = workspaceProps["Safari"][i] + + // for (var j = 0; j < windowsToRemove.length; j++) { + // if(workspaceWindow.id == windowsToRemove[j]){ + // try{ + // workspaceProps["Safari"].splice([i], 1) + // }catch(err){ + // } + // } + // } + // } + + +} \ No newline at end of file