diff --git a/spec/application.spec.lua b/spec/application.spec.lua index 352085b..8a2c0e1 100644 --- a/spec/application.spec.lua +++ b/spec/application.spec.lua @@ -592,6 +592,43 @@ local function selectBehaviorTests() end end +local function entityBehaviorTests() + local behaviorTests = { + { + name = "returns assigned auto-exit value if application has name", + applicationName = "", + autoExitMode = false, + args = { spy.new(function() end), nil, nil, {} }, + eventHandlerCallCount = 0, + expectedResult = false, + }, + } + + -- Run `entity` mode behavior method tests + for _, test in pairs(behaviorTests) do + it(test.name, function() + local eventHandlerSpy = test.args[1] + local application = require("application") + + application.name = test.applicationName + application.autoExitMode = test.autoExitMode + application.getSelectionItems = function() + return test.selectionItems + end + application.getApplication = function() + return #test.applicationName > 0 and {} or nil + end + + assert.are.same(type(application.behaviors.entity), "function") + + local result = application.behaviors.entity(application, table.unpack(test.args)) + + assert.are.same(test.expectedResult, result) + assert.spy(eventHandlerSpy).was.called(test.eventHandlerCallCount) + end) + end +end + describe("application.lua (#application)", function() local printFunc = _G.print @@ -624,4 +661,5 @@ describe("application.lua (#application)", function() describe("`toggleFullScreen` method", toggleFullScreenTests) describe("`default` behavior function", defaultBehaviorTests) describe("`select` behavior function", selectBehaviorTests) + describe("`entity` behavior function", entityBehaviorTests) end) diff --git a/src/application.lua b/src/application.lua index c697023..a799a4e 100644 --- a/src/application.lua +++ b/src/application.lua @@ -23,48 +23,77 @@ end local Entity = _G.requirePackage("Entity", true) local Application = Entity:subclass("Application") +local ApplicationBehaviors = {} ---- Application.behaviors ---- Variable ---- Application [behaviors](Entity.html#behaviors) defined to invoke event handlers with `hs.application`. -Application.behaviors = Entity.behaviors + { - default = function(self, eventHandler) - local app = self.name and self:getApplication() or nil +-- Default application behavior function +function ApplicationBehaviors.default(self, eventHandler) + local app = self.name and self:getApplication() or nil - if not app then - return self.autoExitMode - end + if not app then + return self.autoExitMode + end - local autoFocus, autoExit = eventHandler(app) + local autoFocus, autoExit = eventHandler(app) - if app and autoFocus == true then - self.focus(app) - end + if app and autoFocus == true then + self.focus(app) + end - return autoExit == nil and self.autoExitMode or autoExit - end, - select = function(self, eventHandler) - local app = self.name and self:getApplication() or nil + return autoExit == nil and self.autoExitMode or autoExit +end - if not app then - return self.autoExitMode - end +-- Application behavior function for select mode +function ApplicationBehaviors.select(self, eventHandler) + local app = self.name and self:getApplication() or nil - local choices = self:getSelectionItems() + if not app then + return self.autoExitMode + end - if choices and #choices > 0 then - local function onSelection(choice) - if choice then - eventHandler(app, choice) - end + local choices = self:getSelectionItems() + + if choices and #choices > 0 then + local function onSelection(choice) + if choice then + eventHandler(app, choice) end + end + + self.showSelectionModal(choices, onSelection) + end - self.showSelectionModal(choices, onSelection) + return true +end + +-- Application behavior function for entity mode +function ApplicationBehaviors.entity(self, eventHandler, _, _, workflow) + local shouldSelect = false + local app = self.name and self:getApplication() or nil + + if not app then + return self.autoExitMode + end + + for _, event in pairs(workflow) do + if event.mode == "select" then + shouldSelect = true + break end + end - return true - end, -} + if shouldSelect then + return ApplicationBehaviors.select(self, eventHandler, _, _, workflow) + end + + local _, autoExit = eventHandler(app, shouldSelect) + + return autoExit == nil and self.autoExitMode or autoExit +end + +--- Application.behaviors +--- Variable +--- Application [behaviors](Entity.html#behaviors) defined to invoke event handlers with `hs.application`. +Application.behaviors = Entity.behaviors + ApplicationBehaviors --- Application:getSelectionItems() --- Method diff --git a/src/init.lua b/src/init.lua index a5463ed..7397e77 100644 --- a/src/init.lua +++ b/src/init.lua @@ -334,6 +334,11 @@ Ki.defaultTransitionEvents = { function() Ki.state:exitMode() end, { "Select Mode", "Exit to Normal Mode" }, }, + { + {"cmd"}, "e", + function() Ki.state:enterEntityMode() end, + { "Select Mode", "Transition to Entity Mode" }, + }, { {"cmd"}, "f", function() Ki.state:enterFileMode() end, @@ -378,6 +383,7 @@ Ki._defaultStateEvents = { { name = "enterNormalMode", from = "desktop", to = "normal" }, { name = "enterEntityMode", from = "normal", to = "entity" }, { name = "enterEntityMode", from = "action", to = "entity" }, + { name = "enterEntityMode", from = "select", to = "entity" }, { name = "enterActionMode", from = "normal", to = "action" }, { name = "enterSelectMode", from = "entity", to = "select" }, { name = "enterSelectMode", from = "normal", to = "select" },