feat(macos): support native title exclusion flags#128
Conversation
Greptile SummaryThis PR wires macOS title-exclusion settings from the Python layer into the Swift watcher subprocess, introducing a new
Confidence Score: 5/5Safe to merge; the Python↔Swift command-building contract is correct and well-tested, and the one flaw found is a pattern-array accumulation on accessibility-permission retries that does not affect correctness. All changed code paths are straightforward: the Python side builds a shell command list and the Swift side parses it. The only issue found is that parseOptionalArguments appends to the global excludeTitlePatterns on every start() retry, causing duplicate entries after repeated accessibility-permission checks — but duplicated patterns still produce the correct exclusion result. aw_watcher_window/macos.swift — specifically the interaction between parseOptionalArguments and the start() retry loop Important Files Changed
Sequence DiagramsequenceDiagram
participant PY as main.py (Python)
participant CLI as macos_cli.py
participant SW as macos.swift (Swift)
PY->>CLI: build_swift_command(binpath, addr, bucket, host, client, exclude_title, exclude_titles)
CLI-->>PY: [binpath, addr, bucket, host, client, --exclude-title?, --exclude-titles pat1, ...]
PY->>SW: subprocess.Popen(command)
SW->>SW: start() — parse positional args
SW->>SW: parseOptionalArguments(args[5:])
Note over SW: compiles each pattern to NSRegularExpression
loop Every window focus / poll
SW->>SW: getWindowData()
SW->>SW: "excludeTitle || titleShouldBeExcluded(title)?"
alt excluded
SW->>SW: "data.title = excluded"
end
SW->>SW: sendHeartbeat(heartbeat)
end
Reviews (2): Last reviewed commit: "fix(macos/swift): rename catch binding t..." | Re-trigger Greptile |
| func compileExcludeTitlePattern(_ pattern: String) -> NSRegularExpression { | ||
| do { | ||
| return try NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) | ||
| } catch { | ||
| error("Invalid regex pattern: \(pattern)") | ||
| exit(1) | ||
| } | ||
| } |
There was a problem hiding this comment.
Swift's implicit
catch binding shadows the error() logging function. In a bare catch { } clause Swift automatically binds the caught value to an implicit constant also named error. Inside this block error is of type Error (not callable), so error("Invalid regex pattern: …") is a compile-time type error and the Swift binary will fail to build. Give the caught value an explicit name to avoid the shadowing.
| func compileExcludeTitlePattern(_ pattern: String) -> NSRegularExpression { | |
| do { | |
| return try NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) | |
| } catch { | |
| error("Invalid regex pattern: \(pattern)") | |
| exit(1) | |
| } | |
| } | |
| func compileExcludeTitlePattern(_ pattern: String) -> NSRegularExpression { | |
| do { | |
| return try NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) | |
| } catch let regexError { | |
| error("Invalid regex pattern: \(pattern) – \(regexError.localizedDescription)") | |
| exit(1) | |
| } | |
| } |
| def main(): | ||
| from .main import main as _main | ||
|
|
||
| return _main() |
There was a problem hiding this comment.
Lazy import may surprise entry-point callers
The wrapper function is needed to avoid pulling in aw_client/aw_core when the package is imported (e.g. during test collection), but it changes the identity of the exported symbol: aw_watcher_window.main.__module__ is now aw_watcher_window instead of aw_watcher_window.main, and attributes like __doc__ from the real main are no longer visible. A comment explaining why the deferred import exists would help future readers understand the intent.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Swift's implicit 'error' variable in catch blocks shadows the custom error() function defined in the same file, causing the compiler error: 'cannot call value of non-function type any Error'.
Summary
Testing
Closes #121