Skip to content

baguette v0.1.78

Latest

Choose a tag to compare

@github-actions github-actions released this 09 Jul 03:44
90b2510

Added

  • Paste & clipboard — real pasteboard support for the simulator. Paste arbitrary unicode into the focused field (emoji, accents, non-Latin scripts — the path around type's US-ASCII keystroke limit) by setting the sim's pasteboard and pressing Cmd+V, in one verb. Four entry points share one path: baguette paste --udid <UDID> --text "…" [--no-press], baguette clipboard get (print the sim's pasteboard raw) / baguette clipboard sync (host → sim full-fidelity, images included — the media answer), wire JSON {"type":"paste","text":"…","press":true?} on both baguette serve's stream WS and baguette input's stdin, and browser Cmd+V/Ctrl+V while the device screen has focus. Previously the browser forwarded Cmd+V as a raw HID chord and iOS pasted its own empty pasteboard — a silent no-op, since nothing in the stream pipeline syncs the host clipboard the way Simulator.app does; the web UI now carves the paste chord out of keydown forwarding so the native paste event fires, reads clipboardData (no permission prompt, works over plain LAN http), and ships the text as a paste envelope, acked WS-side with a typed paste_result frame. paste is deliberately not a Gesture: the pasteboard set is an async host call out of reach of the sync, Input-only Gesture.execute, so both entry points intercept it ahead of the gesture pipeline (the describe_ui shape) via one shared PasteDispatch. Like the status bar this is a simctl path — pbcopy | pbpaste | pbsync host through the existing Subprocess collaborator, fully unit-covered via MockSubprocess — with one collaborator gotcha worth preserving: pbcopy reads its payload from stdin, so Subprocess grew a second, stdin-carrying run requirement (additive — the six existing adapters and their test suites are untouched); the no-stdin variant keeps standardInput = nullDevice for the Ctrl-C/SIGINT detachment baguette logs depends on, while the stdin variant writes a pipe off-thread so a >64 KB payload can't deadlock against a full pipe buffer. Known limits: the wire verb is text-only (for images, copy on the host and clipboard sync), and there's no sim→host reverse sync yet. See docs/features/paste.md.
  • Drag-and-drop a folder-form .app bundle onto the device. The focus page's drop target now takes all three app shapes: an .ipa (unchanged), a pre-zipped .app, and — new — the bare .app directory straight from Finder or a build products folder. A browser can't upload a directory as one file, so sim-file-drop.js walks the dropped bundle via webkitGetAsEntry and packs it into a stored (uncompressed) zip built in-page (local headers + CRC-32 + central directory, ~90 lines, no library), posting it as <Name>.app.zip to the same POST /simulators/:udid/files route. The Swift side gains the matching domain value: AppArchive (a .zip carrying one app) with pure classification, ditto argv projection, and an installableApp(amongExtracted:) locator (exactly one top-level .app; __MACOSX / dotfiles ignored; two apps refused as ambiguous), plus apps().install(archive:) on the Apps collection — extract, locate, then reuse the normal AppBundle install; both spawns run through the existing Subprocess collaborator, fully unit-covered via MockSubprocess. Two gotchas worth preserving: extraction uses ditto -x -k (not unzip) because it restores unix modes from the zip's external attributes, and the browser packer stamps every entry 0755 since the file-system entry API can't read permission bits — otherwise the installed app's binary comes out non-executable and won't launch. A zip that isn't a packed app fails as the upload's fault (415 with the reason: "corrupt zip?" / "zip bomb?" when the contents blow past a 4 GiB decompression cap — refused up front from the central directory's declared sizes, with the extracted bytes re-measured as the backstop against forged headers / "no single .app bundle at the top level"), never a misleading simctl 500. Known limits: the .app must sit at the zip's top level, and symlinks / empty dirs don't survive the browser packer (iOS-style shallow bundles carry neither). See docs/features/file-upload.md.
  • Numpad forwarding. The browser keyboard capture now recognises the Mac's physical numeric keypad — Numpad0Numpad9, NumpadDecimal, NumpadAdd / NumpadSubtract / NumpadMultiply / NumpadDivide, keypad NumpadEnter, and NumpadEqual — and forwards each keystroke into the focused simulator with its own HID keypad usage (page 7, 0x540x63 plus 0x67), distinct from the top-row digits. No wire or CLI change: numpad keys ride the existing key envelope ({ "type": "key", "code": "Numpad5" }) down the same IndigoHIDMessageForHIDArbitrary(target, page:7, usage, op) path already used for letters and digits, so baguette key --code Numpad5 works from the CLI too. Numpad0 takes 0x62 (last in the keypad block, the same last-place quirk as the top-row Digit0). NumLock/Clear is deliberately left out — iOS has no num-lock concept, so forwarding it would be a device no-op that needlessly swallowed the host key. See docs/features/keyboard.md.