Plug-In: New Tab Set Window
This macOS plug-in restores the stored tab set to a new window.
To store the tab set of the current window, launch this plug-in while holding down the Option key.

To set content display preferences of the tab windows, launch this plug-in while holding down the Control key.

Multiple Tab Sets
Want more than one tab set — like, one for personal and one for work?
Here's how to make that a reality. It will require the use of Text Editor application. Simply follow these steps:
- Make copies of the plug-in, one for each tab set. For example, one for “Personal” management, and one for “Work” management.
- Change the names of the plug-in files to match the two categories, like this: of-window-tab-set-personal.omnifocusjs and of-window-tab-set-work.omnifocusjs
- Edit the plug-ins in the Text Editor application, and alter the value of the plug-in's identifier metadata tag so that each identifier value is unique — maybe add a word to the ID. Like: com.omni-automation.of.archive-restores-tab-set-personal and com.omni-automation.of.archive-restores-tab-set-work etc.
- Change the value of the label metadata tag to something like: "New Tab Set Personal" and "New Tab Set Work" etc.
- Place both copies of the plug-ins in the OmniFocus plug-ins folder, either the local one or the one on iCloud Drive > OmniFocus > Plug-Ins
That’s it! You now have two tab sets with their own preferences.
Return to: OmniFocus Plug-In Collection
New Tab Set Window (macOS)
/*{
"type": "action",
"targets": ["omnifocus"],
"author": "Otto Automator",
"identifier": "com.omni-automation.of.archive-restores-tab-set",
"version": "1.1",
"description": "This macOS plug-in restores the stored tab set to a new window. To store the tab set of the current window, launch this plug-in while holding down the Option key. To set content display preferences of the tab windows, launch this plug-in while holding down the Control key.",
"label": "New Tab Set Window",
"shortLabel": "Tab Set",
"paletteLabel": "Tab Set",
"image": "uiwindow.split.2x1"
}*/
(() => {
var preferences = new Preferences() // NO ID = PLUG-IN ID
const action = new PlugIn.Action(async function(selection, sender){
try {
if(app.optionKeyDown){
// PROMPT USER
alertTitle = "Store Tab Set"
alertMsg = "Store the tab (perspective) set of the frontmost window?"
alert = new Alert(alertTitle, alertMsg)
alert.addOption("Store Tab Set")
alert.addOption("Cancel")
buttonIndex = await alert.show()
if (buttonIndex === 0){
tabs = document.windows[0].tabGroupWindows
tabNames = tabs.map(tab => tab.perspective.name)
prefValue = JSON.stringify(tabNames)
preferences.write("tabNames", prefValue)
}
} else if (app.controlKeyDown){
sidebarVisibility = preferences.readBoolean("sidebarVisibility")
if(!sidebarVisibility instanceof Boolean){
console.log("sidebarVisibility missing")
preferences.write("sidebarVisibility", false)
}
console.log("Pref-R: sidebarVisibility", sidebarVisibility)
sidebarVisibilityCheckbox = new Form.Field.Checkbox(
"sidebarVisibility",
"Show the Sidebar",
sidebarVisibility
)
inspectorVisibility = preferences.readBoolean("inspectorVisibility")
if(!inspectorVisibility instanceof Boolean){
console.log("inspectorVisibility missing")
preferences.write("inspectorVisibility", false)
}
console.log("Pref-R: inspectorVisibility", inspectorVisibility)
inspectorVisibilityCheckbox = new Form.Field.Checkbox(
"inspectorVisibility",
"Show the Inspector",
inspectorVisibility
)
itemsAreExpanded = preferences.readBoolean("itemsAreExpanded")
if(!itemsAreExpanded instanceof Boolean){
console.log("itemsAreExpanded missing")
preferences.write("itemsAreExpanded", false)
}
console.log("Pref-R: itemsAreExpanded", itemsAreExpanded)
itemsAreExpandedCheckbox = new Form.Field.Checkbox(
"itemsAreExpanded",
"Items are expanded",
itemsAreExpanded
)
notesAreExpanded = preferences.readBoolean("notesAreExpanded")
if(!notesAreExpanded instanceof Boolean){
console.log("notesAreExpanded missing")
preferences.write("notesAreExpanded", false)
}
console.log("Pref-R: notesAreExpanded", notesAreExpanded)
notesAreExpandedCheckbox = new Form.Field.Checkbox(
"notesAreExpanded",
"Notes are displayed",
notesAreExpanded
)
inputForm = new Form()
inputForm.addField(sidebarVisibilityCheckbox)
inputForm.addField(inspectorVisibilityCheckbox)
inputForm.addField(itemsAreExpandedCheckbox)
inputForm.addField(notesAreExpandedCheckbox)
formPrompt = "Content display options:"
buttonTitle = "Continue"
formObject = await inputForm.show(formPrompt,buttonTitle)
sidebarVisibility = formObject.values["sidebarVisibility"]
console.log("Pref-W: sidebarVisibility", sidebarVisibility)
inspectorVisibility = formObject.values["inspectorVisibility"]
console.log("Pref-W: inspectorVisibility", inspectorVisibility)
itemsAreExpanded = formObject.values["itemsAreExpanded"]
console.log("Pref-W: itemsAreExpanded", itemsAreExpanded)
notesAreExpanded = formObject.values["notesAreExpanded"]
console.log("Pref-W: notesAreExpanded", notesAreExpanded)
preferences.write("sidebarVisibility", sidebarVisibility)
preferences.write("inspectorVisibility", inspectorVisibility)
preferences.write("itemsAreExpanded", itemsAreExpanded)
preferences.write("notesAreExpanded", notesAreExpanded)
} else {
// RETRIEVE STORED PREFERENCE VALUES
tabNames = preferences.readString("tabNames")
if(!tabNames){tabNames = []}
if(tabNames.length === 0){
throw {
name: "Missing Names",
message: "There are no stored tab names (perspectives).\n\nLaunch this plug-in while holding down the Option key to have it store the tab set of the current OmniFocus window."
}
}
sidebarVisibility = preferences.readBoolean("sidebarVisibility")
if(!sidebarVisibility){sidebarVisibility = false}
console.log("sidebarVisibility", sidebarVisibility)
inspectorVisibility =
inspectorVisibility = preferences.readBoolean("inspectorVisibility")
if(!inspectorVisibility){inspectorVisibility = false}
console.log("inspectorVisibility", inspectorVisibility)
itemStatesIndex = preferences.readNumber("itemStatesIndex")
if(!itemStatesIndex){itemStatesIndex = 0}
console.log("Pref-R: itemStatesIndex", itemStatesIndex)
noteStatesIndex = preferences.readNumber("noteStatesIndex")
if(!noteStatesIndex){noteStatesIndex = 0}
console.log("Pref-R: noteStatesIndex", noteStatesIndex)
tabNames = JSON.parse(tabNames)
console.log("Pref-R: tabNames", tabNames)
// CREATE ARRAY OF PERSPECTIVE REFERENCES
var pArray = new Array()
for (tabName of tabNames){
console.log("tabName", tabName)
switch (tabName) {
case "Inbox":
var tp = Perspective.BuiltIn.Inbox
break;
case "Projects":
var tp = Perspective.BuiltIn.Projects
break;
case "Tags":
var tp = Perspective.BuiltIn.Tags
break;
case "Forecast":
var tp = Perspective.BuiltIn.Forecast
break;
case "Flagged":
var tp = Perspective.BuiltIn.Flagged
break;
case "Nearby":
var tp = Perspective.BuiltIn.Nearby
break;
case "Review":
var tp = Perspective.BuiltIn.Review
break;
case "Search":
var tp = Perspective.BuiltIn.Search
break;
default:
try {
var tp = Perspective.Custom.byName(tabName)
} catch (err){
throw {
name: "Missing Perspective",
message: `The stored perspective “${tabName}” does not exist.`
}
}
}
pArray.push(tp)
}
console.log("pArray", pArray)
// CREATE NEW WINDOW
var newWin = await document.newWindow()
console.log("newWin", newWin)
// ADD NUMBER OF TABS TO NEW WINDOW
for ([idx, tabName] of tabNames.entries()){
if(idx !== 0){
await document.newTabOnWindow(newWin)
}
}
// ASSIGN PERSPECTIVES TO TABS
var newTabs = newWin.tabGroupWindows
for ([idx, pSpect] of pArray.entries()){
console.log("idx", idx)
console.log("pSpect", pSpect)
newTabs[idx].perspective = pSpect
}
// TAB SETUP
tabs = document.windows[0].tabGroupWindows
for(tab of tabs){
// SHOW|HIDE PANELS
tab.sidebarVisible = sidebarVisibility
tab.inspectorVisible = inspectorVisibility
// SET VIEW PARAMETERS
tree = tab.content
// EXPAND|COLLAPSE NODES
if(itemsAreExpanded === true){
tree.rootNode.children.forEach(node => node.expand(true))
} else {
tree.rootNode.children.forEach(node => node.collapse(true))
}
// EXPAND|COLLAPSE NOTES
if(notesAreExpanded === true){
tree.rootNode.children.forEach(node => node.expandNote(true))
} else {
tree.rootNode.children.forEach(node => node.collapseNote(true))
}
}
}
}
catch(err){
if(!err.causedByUserCancelling){
console.error(err.name, err.message)
new Alert(err.name, err.message).show()
}
}
});
action.validate = function(selection, sender){
// AVAILABLE ON masOS ONLY
return (Device.current.type === DeviceType.mac)
};
return action;
})();