Skip to content

Add an .osType return type, for scripts that answer with a constant - #9

Merged
fredsimard merged 3 commits into
mainfrom
ostype-return-type
Oct 16, 2026
Merged

fredsimard merged 3 commits into
mainfrom
ostype-return-type

Conversation

@fredsimard

Copy link
Copy Markdown
Owner

Closes #7.

What

Adds an .osType return type for the properties that are documented as enumerations and cannot answer with anything else — a disk's format in the Finder, a range's format in Numbers. .wildCard already reached those as AppleScriptValue.constant, but the caller had to switch on a type they already knew to get at the code. .osType declares it up front and the raw FourCharCode comes back directly:

let code = try AppleScriptBridge.executeAppleScript(diskFormat, with: ["diskName": "Macintosh HD"]) as? FourCharCode

if code == "dfap".appleScriptFourCharCode { … }

The open question in #7

Settled on the raw FourCharCode, not a mapping to dictionary terms. The terminology lives in each application's sdef, which the package has no access to at the point where a result is decoded, so a mapping would mean shipping per-application tables or asking the caller to supply one — and a caller who can supply the table can already compare against the codes in it. String.appleScriptFourCharCode and String(appleScriptFourCharCode:) cover the ergonomics, and the result stays the same shape as .wildCard's .constant, so moving between the two return types is a cast, not a rewrite.

Behaviour

What the script answered What comes back
A constant ('enum', 'type', 'prop', 'keyw') Its FourCharCode, raw.
missing value The code 'msng', comparable against FourCharCode(cMissingValue). Not singled out as it is in AppleScriptValue.
Text of exactly four characters, or a boolean The code it coerces to — a boolean is 'true' or 'fals' underneath.
Anything else — a number, a date, a list, longer text nil, rather than a code read out of unrelated bytes, which is what enumCodeValue hands over on its own.

Like .wildCard, .osType needs the Apple event descriptor, so executeAppleScriptViaCommandLine(_:with:) throws .unsupportedReturnType before launching the process: osascript prints the term its dictionary defines, APFS format, with the code nowhere in it.

Upgrade note

AppleScriptReturnType gained a case, so code that switches over it exhaustively without a default stops compiling until .osType is handled. Nothing else changes.

Tests

Ten new tests in OSTypeTests.swift: the four constant-carrying descriptor types, missing value, the coercible descriptors, the non-constant ones, two execution suites running self-contained scripts through NSAppleScript (no Automation permission needed), and the command-line refusal. swift build, swift test (53 tests) and the CI-style example build pass locally; SwiftLint is not installed on this machine, so the lint job is unverified here.

Docs updated: README, Documentation/API.md, Examples/AppleScripts.swift (an .osType script and its call site next to the .wildCard ones), and a 1.3.0 CHANGELOG entry.

🤖 Generated with Claude Code

fredsimard and others added 2 commits October 16, 2026 17:27
Some application properties are documented as enumerations and cannot answer with anything else: a
disk's format in the Finder, a range's format in Numbers. .wildCard already reached those, as
AppleScriptValue.constant, but the caller had to switch on a type it already knew to get at the code.

.osType declares it instead, and the raw FourCharCode comes back directly. The code stays raw, as
.constant's is — 'dfap', not the APFS format Script Editor shows — because the terminology lives in
each application's sdef, which the package cannot read at the point where a result is decoded. There
is no honest mapping to hand the caller, so they compare against the codes their target documents.

A result that is not a constant yields nil rather than a code read out of unrelated bytes, which is
what enumCodeValue answers on its own for an integer. missing value arrives as 'msng' rather than
being singled out as it is in AppleScriptValue, and the two things AppleScript treats as constants in
disguise — text of exactly four characters, and a boolean — are coerced. Like .wildCard, .osType
needs the Apple event descriptor, so executeAppleScriptViaCommandLine throws .unsupportedReturnType
before launching the process.

Closes #7.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first version offered a non-constant descriptor to coerce(toDescriptorType:), which accepts text
of exactly four characters and a boolean. It does so only where the process has the Apple event
coercion handlers for it: "dfap" yields 'dfap' in a user session and nothing on a headless CI runner,
which is how the test caught it.

A result that changes with the environment is worse than no result, so the descriptor's own type now
decides and nothing is coerced. Text that looks like a code yields nil, as any other non-constant
does. The tests say so in both places, so the behaviour cannot drift back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fredsimard fredsimard self-assigned this Oct 16, 2026
missing value is a constant like any other, so .osType hands it over as 'msng' rather than as nil.
The example compared that against 'dfap' and answered false, reporting a disk the Finder cannot
describe as "some other format" — while the .wildCard example a few lines up treats the same answer
as "no format reported". It is ruled out before the comparison now, and both doc comments say that
the code can arrive.

The two claims predate .osType and the second commit made them wrong: API.md called .wildCard the
only case that does not coerce, and the README said every return type in its table coerces, each a
few lines from the new section saying .osType coerces nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fredsimard
fredsimard merged commit 5bc18ad into main Oct 16, 2026
3 checks passed
@fredsimard
fredsimard deleted the ostype-return-type branch October 16, 2026 22:40
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

Successfully merging this pull request may close these issues.

Add an .osType return type, for scripts whose result is known to be a constant

1 participant