Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG? hs.application.find("window title") returns window object in results #2394

Open
asmagill opened this issue Jun 11, 2020 · 3 comments
Open

Comments

@asmagill
Copy link
Member

Reading the documentation for hs.application.find, it sounds like hs.application.find should only return application objects or nil/nothing

When I invoke it with a partial window title, I get the window object as the first return value and the application as the second.

Even if it is supposed to return the window object (in which case, update the documentation), the application object should be the first value(s) as this is what one expects from hs.application.find. If I wanted the window object (first), I'd be using hs.window.find.

@latenitefilms
Copy link
Contributor

I’d say this is definitely a bug.

@Rhys-T
Copy link

Rhys-T commented Sep 19, 2023

I think I see what's going on. It has to do with this code:

r=tpack(hs.window.find(hint))
local rs={} for _,w in ipairs(r) do rs[w:application()]=true end -- :toSet
for a in pairs(rs) do r[#r+1]=a end -- and back, no dupes
if #r>0 then return tunpack(r) end

From what I can tell, this is what that code is doing:
169. r is set to a list of matching windows.
170. Each window's application is set as a key in rs, to reduce it to a set of unique applications.
171. Each key (app) from rs is appended to r, to convert that set back into a list… except that r still has the windows from line 169!
172. The combined list of windows and apps is unpacked and returned.

Assuming I'm understanding correctly, r needs to be set back to {} between lines 170 and 171. Patching a copy of application.lua this way and doing hs.application.find('Hammerspoon Console') seems to correctly return just the Hammerspoon application, at least on my machine.

@Rhys-T
Copy link

Rhys-T commented Dec 11, 2023

Also, the 'convert to a set of unique applications' logic doesn't actually do the 'unique' part: Each call to w:application() returns a new hs.application instance/userdata, even if it's referring to the same process - see #2720. For instance, if I create two empty Firefox windows and do hs.application.find('Firefox'), I get two hs.windows and two hs.applications. The two applications are == to each other, and show the same PID, but they have different addresses and aren't rawequal to each other, and count as separate table keys.

This version of the code seems to fix both issues:

  r=tpack(hs.window.find(hint))
  local rs={} for _,w in ipairs(r) do local a=w:application() rs[a:pid()]=a end -- :toSet
  r={} for _,a in pairs(rs) do r[#r+1]=a end -- and back, no dupes
  if #r>0 then return tunpack(r) end
Less minified, more readable version
  local rs = {}
  for _, w in ipairs(r) do
    local a = w:application()
    -- Use the PID as the key, so that it uniques properly, and store the `hs.application` as the value:
    rs[a:pid()] = a
  end -- :toSet
  
  -- Reset `r` to an empty list, getting rid of the `hs.window`s
  r = {}
  -- Look for `hs.application`s as the _values_, not the keys
  for _, a in pairs(rs) do
    r[#r+1] = a
  end -- and back, no dupes
  
  if #r>0 then
    return tunpack(r)
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants