Skip to content

Commit

Permalink
Merge branch 'release/v1.6.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
andweeb committed Sep 17, 2019
2 parents c4295ce + e659d32 commit d53a353
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 81 deletions.
33 changes: 33 additions & 0 deletions docs/html/Application.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ <h3>API Overview</h3>
<li>Methods - API calls which can only be made on an object returned by a constructor</li>
<ul>
<li><a href="#createMenuItemEvent">createMenuItemEvent</a></li>
<li><a href="#createMenuItemSelectionEvent">createMenuItemSelectionEvent</a></li>
<li><a href="#focus">focus</a></li>
<li><a href="#getApplication">getApplication</a></li>
<li><a href="#getMenuItemList">getMenuItemList</a></li>
Expand Down Expand Up @@ -87,6 +88,38 @@ <h5><a href="#createMenuItemEvent">createMenuItemEvent</a></h5>
<ul>
<li>None</li>
</ul>
</td>
</tr>
</table>
</section>
<section id="createMenuItemSelectionEvent">
<a name="//apple_ref/cpp/Method/createMenuItemSelectionEvent" class="dashAnchor"></a>
<h5><a href="#createMenuItemSelectionEvent">createMenuItemSelectionEvent</a></h5>
<table>
<tr>
<th>Signature</th>
<td><code>Application.createMenuItemSelectionEvent(menuItem[, shouldFocusAfter, shouldFocusBefore])</code></td>
</tr>
<tr>
<th>Type</th>
<td>Method</td>
</tr>
<tr>
<th>Description</th>
<td><p>Convenience method to create an event handler that presents a selection modal containing menu items that are nested/expandable underneath at the provided <code>menuItem</code> path, with optionally specified behavior on how the menu item selection occurs</p>
<p>Parameters:</p>
<ul>
<li><code>menuItem</code> - a table list of strings that represent a path to a menu item that expands to menu item list, i.e., <code>{ "File", "Open Recent" }</code></li>
<li><code>options</code> - a optional table containing some or all of the following fields to define the behavior for the menu item selection event:<ul>
<li><code>focusBefore</code> - an optional boolean denoting whether to focus the application before the menu item is selected</li>
<li><code>focusAfter</code> - an optional boolean denoting whether to focus the application after the menu item is selected</li>
</ul>
</li>
</ul>
<p>Returns:</p>
<ul>
<li>None</li>
</ul>
</td>
</tr>
</table>
Expand Down
9 changes: 9 additions & 0 deletions docs/markdown/Application.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Application class that subclasses [Entity](Entity.html) to represent some automa
* [behaviors](#behaviors)
* Methods - API calls which can only be made on an object returned by a constructor
* [createMenuItemEvent](#createMenuItemEvent)
* [createMenuItemSelectionEvent](#createMenuItemSelectionEvent)
* [focus](#focus)
* [getApplication](#getApplication)
* [getMenuItemList](#getMenuItemList)
Expand Down Expand Up @@ -36,6 +37,14 @@ Application class that subclasses [Entity](Entity.html) to represent some automa
| **Parameters** | <ul><li>`menuItem` - the menu item to select, specified as either a string or a table</li><li>`options` - a optional table containing some or all of the following fields to define the behavior for the menu item selection event:</li><li> `isRegex` - a boolean denoting whether there is a regular expression within the menu item name(s)</li><li> `isToggleable` - a boolean denoting whether the menu item parameter is passed in as a list of two items to toggle between, i.e., `{ "Play", "Pause" }`</li><li> `focusBefore` - an optional boolean denoting whether to focus the application before the menu item is selected</li><li> `focusAfter` - an optional boolean denoting whether to focus the application after the menu item is selected</li></ul> |
| **Returns** | <ul><li>None</li></ul> |

| [createMenuItemSelectionEvent](#createMenuItemSelectionEvent) | |
| --------------------------------------------|-------------------------------------------------------------------------------------|
| **Signature** | `Application.createMenuItemSelectionEvent(menuItem[, shouldFocusAfter, shouldFocusBefore])` |
| **Type** | Method |
| **Description** | Convenience method to create an event handler that presents a selection modal containing menu items that are nested/expandable underneath at the provided `menuItem` path, with optionally specified behavior on how the menu item selection occurs |
| **Parameters** | <ul><li>`menuItem` - a table list of strings that represent a path to a menu item that expands to menu item list, i.e., `{ "File", "Open Recent" }`</li><li>`options` - a optional table containing some or all of the following fields to define the behavior for the menu item selection event:</li><li> `focusBefore` - an optional boolean denoting whether to focus the application before the menu item is selected</li><li> `focusAfter` - an optional boolean denoting whether to focus the application after the menu item is selected</li></ul> |
| **Returns** | <ul><li>None</li></ul> |

| [focus](#focus) | |
| --------------------------------------------|-------------------------------------------------------------------------------------|
| **Signature** | `Application:focus(app[, choice])` |
Expand Down
3 changes: 3 additions & 0 deletions spec/application.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ local function getSelectionItemsTests()
text = "Test Window",
subText = "Window 1 ",
windowId = 1,
windowIndex = 1,
},
},
},
Expand All @@ -69,6 +70,7 @@ local function getSelectionItemsTests()
text = "Test Window",
subText = "Window 1 (full screen)",
windowId = 1,
windowIndex = 1,
},
},
},
Expand All @@ -87,6 +89,7 @@ local function getSelectionItemsTests()
text = "Test Window",
subText = "Window 1 (minimized)",
windowId = 1,
windowIndex = 1,
},
},
},
Expand Down
4 changes: 4 additions & 0 deletions spec/entity.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,14 @@ local function triggerAfterConfirmationTests()
local mockDialog = {
blockAlert = function() return test.answer end,
}
local mockTimer = {
doAfter = function(_, callback) callback() end
}

_G.hs = mock(mockHs({
dialog = mockDialog,
focus = focusSpy,
timer = mockTimer,
}))

entity.triggerAfterConfirmation(table.unpack(test.args))
Expand Down
52 changes: 50 additions & 2 deletions src/application.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ if not _G.requirePackage then
end
-- luacov: enable

local Entity = _G.requirePackage("Entity", true)
local Util = _G.requirePackage("util", true)
local Entity = _G.requirePackage("entity", true)
local Application = Entity:subclass("Application")
local ApplicationBehaviors = {}

Expand Down Expand Up @@ -118,6 +119,7 @@ function Application:getSelectionItems()
text = window:title(),
subText = "Window "..index.." "..state,
windowId = window:id(),
windowIndex = index,
})
end

Expand Down Expand Up @@ -159,6 +161,53 @@ function Application.createMenuItemEvent(menuItem, options)
end
end

--- Application.createMenuItemSelectionEvent(menuItem[, shouldFocusAfter, shouldFocusBefore])
--- Method
--- Convenience method to create an event handler that presents a selection modal containing menu items that are nested/expandable underneath at the provided `menuItem` path, with optionally specified behavior on how the menu item selection occurs
---
--- Parameters:
--- * `menuItem` - a table list of strings that represent a path to a menu item that expands to menu item list, i.e., `{ "File", "Open Recent" }`
--- * `options` - a optional table containing some or all of the following fields to define the behavior for the menu item selection event:
--- * `focusBefore` - an optional boolean denoting whether to focus the application before the menu item is selected
--- * `focusAfter` - an optional boolean denoting whether to focus the application after the menu item is selected
---
--- Returns:
--- * None
function Application.createMenuItemSelectionEvent(menuItem, options)
options = options or {}

return function(app, windowChoice)
local menuItemList = Application.getMenuItemList(app, menuItem)
local choices = {}

for _, item in pairs(menuItemList) do
if item.AXTitle and #item.AXTitle > 0 then
table.insert(choices, {
text = item.AXTitle,
})
end
end

Application.showSelectionModal(choices, function(menuItemChoice)
if menuItemChoice then
if (options.focusBefore) then
Application.focus(app, windowChoice)
end

local targetMenuItem = Util:clone(menuItem)

table.insert(targetMenuItem, menuItemChoice.text)

app:selectMenuItem(targetMenuItem)

if (options.focusAfter) then
Application.focus(app, windowChoice)
end
end
end)
end
end

--- Application.getMenuItemList(app, menuItemPath) -> table or nil
--- Method
--- Gets a list of menu items from a hierarchical menu item path
Expand All @@ -177,7 +226,6 @@ function Application.getMenuItemList(app, menuItemPath)
for _, menuItem in pairs(menuItems) do
if menuItem.AXTitle == menuItemName then
menuItems = menuItem.AXChildren[1]

if menuItemName ~= menuItemPath[#menuItemPath] then
isFound = true
end
Expand Down
37 changes: 25 additions & 12 deletions src/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ function Defaults.createEntityEvents()
{ nil, "m", entities.Messages, { "Select Events", "Select a Messages conversation" } },
{ nil, "n", entities.Notes, { "Select Events", "Select a Note" } },
{ nil, "p", entities.Preview, { "Select Events", "Select a Preview window" } },
{ nil, "q", entities.QuickTimePlayer, { "Select Events", "QuickTime Player" } },
{ nil, "s", entities.Safari, { "Select Events", "Select a Safari tab or window" } },
{ nil, "t", entities.Terminal, { "Select Events", "Select a Terminal window" } },
{ nil, ",", entities.SystemPreferences, { "Entities", "Select a System Preferences pane" } },
Expand Down Expand Up @@ -365,11 +366,15 @@ function Defaults.createNormalEvents(Ki)
function actions.logout()
Ki.state:exitMode()

local answer = hs.dialog.blockAlert("Log out from your computer?", "", "Log out", "Cancel")
hs.timer.doAfter(0, function()
hs.focus()

if answer == "Log out" then
hs.osascript.applescript([[ tell application "System Events" to log out ]])
end
local answer = hs.dialog.blockAlert("Log out from your computer?", "", "Log out", "Cancel")

if answer == "Log out" then
hs.osascript.applescript([[ tell application "System Events" to log out ]])
end
end)
end

function actions.startScreenSaver()
Expand All @@ -388,21 +393,29 @@ function Defaults.createNormalEvents(Ki)
function actions.restart()
Ki.state:exitMode()

local answer = hs.dialog.blockAlert("Restart your computer?", "", "Restart", "Cancel")
hs.timer.doAfter(0, function()
hs.focus()

if answer == "Restart" then
hs.osascript.applescript([[ tell application "Finder" to restart ]])
end
local answer = hs.dialog.blockAlert("Restart your computer?", "", "Restart", "Cancel")

if answer == "Restart" then
hs.osascript.applescript([[ tell application "Finder" to restart ]])
end
end)
end

function actions.shutdown()
Ki.state:exitMode()

local answer = hs.dialog.blockAlert("Shut down your computer?", "", "Shut Down", "Cancel")
hs.timer.doAfter(0, function()
hs.focus()

if answer == "Shut Down" then
hs.osascript.applescript([[ tell application "System Events" to shut down ]])
end
local answer = hs.dialog.blockAlert("Shut down your computer?", "", "Shut Down", "Cancel")

if answer == "Shut Down" then
hs.osascript.applescript([[ tell application "System Events" to shut down ]])
end
end)
end

local normalEvents = {
Expand Down
27 changes: 4 additions & 23 deletions src/entities/preview.lua
Original file line number Diff line number Diff line change
@@ -1,32 +1,13 @@
local Application = dofile(_G.spoonPath.."/application.lua")
local actions = {
close = Application.createMenuItemEvent("Close Window", { focusBefore = true }),
find = Application.createMenuItemEvent({ "Find", "Find..." }, { focusAfter = true }),
open = Application.createMenuItemEvent("Open...", { focusAfter = true }),
close = Application.createMenuItemEvent("Close Window", { focusBefore = true }),
openRecent = Application.createMenuItemSelectionEvent({ "File", "Open Recent" }, {
focusAfter = true,
}),
}

function actions.openRecent(app)
local menuItem = { "File", "Open Recent" }
local menuItemList = Application.getMenuItemList(app, menuItem)
local recentFileChoices = {}

for _, item in pairs(menuItemList) do
if item.AXTitle and #item.AXTitle > 0 then
table.insert(recentFileChoices, {
text = item.AXTitle,
})
end
end

local function selectMenuItemAndFocus(choice)
table.insert(menuItem, choice.text)
app:selectMenuItem(menuItem)
Application.focus(app)
end

Application.showSelectionModal(recentFileChoices, selectMenuItemAndFocus)
end

local shortcuts = {
{ nil, "o", actions.open, { "File", "Open..." } },
{ nil, "w", actions.close, { "File", "Close Window" } },
Expand Down
58 changes: 41 additions & 17 deletions src/entities/quicktime-player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,59 @@ local actions = {
newAudioRecording = Application.createMenuItemEvent("New Audio Recording"),
newMovieRecording = Application.createMenuItemEvent("New Movie Recording"),
openFile = Application.createMenuItemEvent("Open File...", { focusAfter = true }),
openRecent = Application.createMenuItemSelectionEvent({ "File", "Open Recent" }, {
focusAfter = true,
}),
newScreenRecording = Application.createMenuItemEvent("New Screen Recording"),
trim = Application.createMenuItemEvent("Trim...", { focusBefore = true }),
exportAs = Application.createMenuItemSelectionEvent({ "File", "Export As" }, {
focusBefore = true,
}),
}

function actions.openRecent(app)
local menuItem = { "File", "Open Recent" }
local menuItemList = Application.getMenuItemList(app, menuItem)
local recentFileChoices = {}

for _, item in pairs(menuItemList) do
if item.AXTitle and #item.AXTitle > 0 then
table.insert(recentFileChoices, {
text = item.AXTitle,
})
end
function actions.togglePlay(_, choice)
local target = choice
and "document "..choice.windowIndex
or "the first document"
local script = Application.renderScriptTemplate("quicktime-player", {
option = "toggle-play",
target = target,
})
local isOk, _, rawTable = hs.osascript.applescript(script)

if not isOk then
Application.notifyError("Error toggling play", rawTable.NSLocalizedFailureReason)
end
end

function actions.toggleFileLoop(_, choice)
local target = choice
and "document "..choice.windowIndex
or "the first document"
local script = Application.renderScriptTemplate("quicktime-player", {
option = "toggle-looping",
target = target,
})
local isOk, isLooping, rawTable = hs.osascript.applescript(script)

if not isOk then
Application.notifyError("Error toggling file loop option", rawTable.NSLocalizedFailureReason)
end

Application.showSelectionModal(recentFileChoices, function(choice)
if choice then
table.insert(menuItem, choice.text)
app:selectMenuItem(menuItem)
end
end)
local toggleText = isLooping and "ON" or "OFF"

hs.notify.show("Ki", "QuickTime Player", "Turned File Loop option"..toggleText)
end

local shortcuts = {
{ nil, "a", actions.newAudioRecording, { "File", "New Audio Recording" } },
{ nil, "e", actions.exportAs, { "File", "Export As" } },
{ nil, "l", actions.toggleFileLoop, { "File", "Toggle File Loop Option" } },
{ nil, "m", actions.newMovieRecording, { "File", "New Movie Recording" } },
{ nil, "o", actions.openFile, { "File", "Open File..." } },
{ nil, "s", actions.newScreenRecording, { "File", "New Screen Recording" } },
{ nil, "t", actions.trim, { "File", "Trim..." } },
{ nil, "space", actions.togglePlay, { "Playback", "Toggle Play" } },
{ { "shift" }, "o", actions.openRecent, { "File", "Open Recent" } },
}

Expand Down
Loading

0 comments on commit d53a353

Please sign in to comment.