Skip to content

Open Markdown files with PlanCake - #11

Merged
Menelion merged 11 commits into
masterfrom
markdown-association
Oct 19, 2026
Merged

Menelion merged 11 commits into
masterfrom
markdown-association

Conversation

@Menelion

@Menelion Menelion commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What and why

PlanCake opens .md and .markdown files, but Windows did not know it: the installer registered nothing, so PlanCake was missing from Explorer's Open with list and from Windows Settings → Default apps, and a double-click on a plan never reached it.

Since Windows 10 no program can make itself the default for a file type, so the change has two halves:

  • The installer always registers PlanCake as a handler for both extensions, with no checkbox: the file type PlanCake.Markdown, PlanCake in each extension's OpenWithProgids, an Applications\plancake.exe entry, and capabilities listed under RegisteredApplications. It never writes the extensions' default value, so the program the user chose keeps opening Markdown files, and the ProgID has no verb but open (File → Open in editor relies on that). ChangesAssociations=yes refreshes Explorer. The uninstaller removes PlanCake's own keys whole and only its values from the shared keys (uninsdeletevalue, uninsdeletekeyifempty).
  • Settings → Advanced gets a button, "Choose PlanCake for Markdown files in Windows Settings...", with a wrapping label above it. It opens ms-settings:defaultapps?registeredAppMachine=PlanCake, PlanCake's own page in Default apps (the general Default apps page on older Windows). The button and label show only when the registration is there and PlanCake is not portable.

The plan is docs/plans/completed/002-markdown-association.md. This ships in 1.1, which waits for it.

Tasks completed

  • Add the Default apps link and the button's visibility rule (Utils/DefaultApps.cs)
  • Register PlanCake for .md and .markdown in the installer, with MarkdownFileType in all six .isl files
  • Add the Default apps button to Settings → Advanced
  • Translate the new interface strings and add the Windows terms (Default apps, Windows Settings, Open with, Choose another app, and the Windows 10 Set defaults by app and Manage) to the glossaries
  • Update the six manuals: Installing, Opening a file, Uninstalling, Settings → Advanced
  • Update CHANGELOG, README and CLAUDE.md

Review

  • Round 1, a full sweep through seven lenses (quality, implementation, testing, simplification, documentation, conventions, accessibility): 17 findings, 12 confirmed and fixed in one commit, 5 refuted.
    • Fixed: the button was renamed so a screen reader hears where it goes (the label above it is not read when tabbing to the button); two installer tests that could pass vacuously or checked too little; the registry read failure now logs at Warning; the manuals give the Windows 10 steps; the Hebrew label and manual now agree; the installer builds its registry paths from its company and app defines; small test cleanups.
    • Refuted: more tests for IsRegistered and the dialog wiring (the plan asks for exactly the no-throw test, and the visibility rule is a tested pure function); a {cm:} cross-check (ISCC already fails on an unknown name); the visibility helper as over-engineering (the plan asks for it); a README "Open a file" gap (Installing covers it).
  • Round 2, a critical re-check (quality, implementation): no findings. Every lens reported.
  • Checked and found fine across the lenses: the registry lines, quoting and uninstall order; the 64-bit view the installer writes and the app reads; single-instance activation on a double-click; Open in editor falling back to Notepad when PlanCake is the default; exception handling and disposal in DefaultApps; mnemonics in all six languages; TableLayoutPanel, WrappingLabel and tab order; the manuals' ids and links.
  • Codex review (gpt-6-astra, read-only, over master...HEAD): no actionable issues found.

Validation

All passed on the final commit:

  • ./src/PlanCake/locale/scripts/Compile-Translations.ps1 -Strict (no fuzzy entries)
  • dotnet build
  • dotnet test (1286 tests)
  • dotnet format --verify-no-changes
  • ./installer/Build-Installer.ps1 -AllowDirty (the installer compiles; it was not run)

FileWatcherTests.Polling_ReadsTheFileOnlyWhenItsSizeOrTimeChanged and Polling_LooksAtTheFileEverySecond_AndReportsAChange failed now and then and passed on a rerun. They come from the WSL polling change, not this one, but they are flaky enough to need their own fix.

To check by hand

  • Installer, on a machine where another program already opens .md:

    • install, and check the default did not change;
    • check that PlanCake is in Open with for both extensions and in Default apps with its icon;
    • set it as the default there, double-click a plan whose path has spaces, and double-click it again while it is open (its window comes forward);
    • uninstall, and check that the PlanCake keys and the RegisteredApplications value are gone, that OpenWithProgids lost only PlanCake's value, and that the other program still opens .md.

    Repeat on Windows 10 if one is at hand.

  • JAWS, in Settings → Advanced:

    • the label and the button read well;
    • the button opens PlanCake's page in Default apps, which works from the keyboard;
    • the button is absent in the portable build.

    Check the Hebrew interface too.

  • Windows 10 terms: the Ukrainian and Hebrew names for "Set defaults by app" and "Manage" in the manuals and glossaries were not checked against a localized Windows 10.

Read installer files through CallerFilePath, move the registration parity test next to the .iss it checks, give the exact [Registry] lines with uninsdeletekeyifempty and doubled quotes, check every BOM, add the Windows terms to the glossaries, note the German mnemonic clash until translation, and cover Opening a file in the manuals.
DefaultApps holds the registered application name, the ms-settings link
to PlanCake's page in Default apps, a registry check for the installer's
registration, and the pure rule that shows the Settings button only when
PlanCake is installed and registered. Tests cover the link, all four
visibility cases and a registry read that never throws.
The installer now registers a PlanCake.Markdown file type, adds it to
each extension's OpenWithProgids, writes an Applications entry and
Default apps capabilities under RegisteredApplications, and sets
ChangesAssociations. The extensions' default value is never written.
MarkdownFileType is added to all six custom message files.
InstallerTests checks the message keys, the BOMs and the registration.
The Advanced tab gets a wrapping label and the button "Open &Markdown
files with PlanCake...", which opens PlanCake's page in Windows
Settings → Default apps. Both are shown only when the installer's
registration is there and PlanCake is not portable. The button saves
nothing and reports a failure to open Settings in a message box.

Tests check the button's place and the label's type, and that the
button fits its tab in every language. MnemonicTests fails for German
until the button is translated (Task 4): the English &Markdown collides
with &Mausklick there.
…glossaries

Translate the Settings → Advanced label, the Default apps button and the
error when Windows Settings does not open in all five catalogs, with a
mnemonic the Settings dialog does not already use in each language (the
German button no longer takes M). Add Default apps, Windows Settings,
Open with and Choose another app to the glossaries, as Windows names them
in each language.
Describe the installer's Markdown registration in Installing (installer,
portable, uninstalling), the double-click in Opening a file, and the
Default apps button in Settings, Advanced, in all six languages with the
catalogs' labels and the glossary terms. Align the Russian, Ukrainian and
French names of Windows Settings with the glossaries.
Add the CHANGELOG entry under Unreleased, a README sentence on the Markdown registration, and a CLAUDE.md paragraph on what the installer registers, what it never writes and what InstallerTests checks.
- Name the Default apps button after where it goes, "Choose PlanCake
  for Markdown files in Windows Settings...", since a screen reader
  reads only the button's own text on Tab; the label now says "This
  button opens", as the translations did. Translated in all five
  catalogs with the same mnemonics, and the six manuals follow.
- Hebrew: the label says כפתור and עמוד, as the manual does, and the
  glossary pins "button".
- Manuals: on Windows 10 the button opens the general Default apps
  page, so say to choose Set defaults by app, then PlanCake, then
  Manage; both terms are in the five glossaries.
- Log a failed read of the registered applications at Warning, so a
  hidden button can be traced in a Release log.
- Installer: build the Oire and PlanCake registry keys from the
  company and folder defines, so the parent keys and the capabilities
  key cannot drift apart.
- InstallerTests: the guard on the extensions' default value matches
  .md and .markdown keys under any root and in any case, and fails if
  it finds none; the RegisteredApplications line must be under HKLM;
  one helper for the script path; no dead BOM trim.
- SettingsDialogTests: drop an assertion that could not fail and name
  the fit theory after the button it now checks too.
@Menelion Menelion self-assigned this Oct 19, 2026
The polling tests drive FileWatcher through a fake timer, but Start also watches the folder for real. The event about the test's own write arrived on a pool thread at any moment and replaced the pending poll with a check, so a test sometimes saw an extra read. The polling tests now pass a synchronizing object that drops those events.
@Menelion
Menelion merged commit 9a4683d into master Oct 19, 2026
1 check passed
@Menelion
Menelion deleted the markdown-association branch October 19, 2026 13:42
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.

1 participant