Hammerspoon / hammerspoon

Staggeringly powerful macOS desktop automation with Lua

Home Page:http://www.hammerspoon.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`hs.application.open` always returns `nil`

andmis opened this issue · comments

(Using 0.9.97.)

If I call local app = hs.application.open('/Applications/Spotify.app') or any other path in /Applications, the call succeeds (the app gets opened/focused) but app is nil.

I'm not totally sure whether this is a problem with hs.application.open in general or has something specific to do with passing in an app bundle.

I am invoking the command from the HS console.


Update: changed title to reflect the conversation below.

By default hs.application.open() will return as quickly as it can, which generally means the app hasn't launched yet. There's a second argument wait which lets you specify a number of seconds it will wait for the app to launch, so it can return the app object. There's also a third argument waitForFirstWindow which will also wait until the app has opened a window.

See http://www.hammerspoon.org/docs/hs.application.html#open but in general if you're writing a Hammerspoon config that's going to be opening apps, it may well be worth taking the time to create an hs.application.watcher and separating the "open the app" logic from the "get the app's object and do stuff to it" logic.

Thanks for the quick reply.

I've tested more and I am not able to make hs.application.open return non-nil at all. Here are some things I've tried, some of these commands are being run with the relevant app already open, some are being run after closing the relevant app. In all cases the app opens, HS hangs for the given number of seconds, and then returns nil.

> hs.application.open('/Applications/Hyper.app', 5)
nil

> hs.application.open('/Applications/Hyper.app', 5)
nil

> hs.application.open('/Applications/iTerm.app', 5)
nil

> hs.application.open('/Applications/iTerm.app', 5, true)
nil

> hs.application.open('/Applications/Spotify.app', 5)
nil

> hs.application.open('/Applications/Spotify.app', 5)
nil

> hs.application.open('/Applications/Spotify.app', 20)
nil

@cmsj can we reopen this? Or should I make a new issue? Or am I missing something?

I believe this is failing because application.get requires that the application name used exactly matches the name of the running application. A fix would be changing the second argument of find to false, i.e. return tpack(application.find(hint,false),nil)[1]

return tpack(application.find(hint,true),nil)[1] -- just to be sure, discard extra results

You can try this snippet:

app = 'iTerm'
wait = 0
waitForWindow = nil
if type(app)~='string' then error('app must be a string',2) end
if wait and type(wait)~='number' then error('wait must be a number',2) end
local r=application.launchOrFocus(app) or application.launchOrFocusByBundleID(app)
if not r then print("r is nil") return end
r=nil
wait=(wait or 0)*1000000
local CHECK_INTERVAL=100000
repeat
    r=r or table.pack(application.find(app, false), nil)[1]
    print("get is", r)
    if r and (not waitForWindow or r:mainWindow()) then return r end
    timer.usleep(math.min(wait,CHECK_INTERVAL)) wait=wait-CHECK_INTERVAL
until wait<=0
return r