Skip to content

Add folder workspaces: hideable sidebar + native tabs + macdown .#493

Open
fluxa wants to merge 1 commit into
schuyler:mainfrom
fluxa:folder-workspaces
Open

Add folder workspaces: hideable sidebar + native tabs + macdown .#493
fluxa wants to merge 1 commit into
schuyler:mainfrom
fluxa:folder-workspaces

Conversation

@fluxa

@fluxa fluxa commented Jun 30, 2026

Copy link
Copy Markdown

Summary

Adds folder workspaces to MacDown 3000: browse a folder of Markdown files in a hideable sidebar and open them as native macOS window tabs, instead of only opening individual files. Reachable from a new File → Open Folder… command and from the command line with macdown ..

This is an additive feature — the editor/preview pipeline and existing single-file behaviour are untouched, and there are no new dependencies.

What you get

  • Folder sidebar (an NSOutlineView source list) showing subfolders and Markdown files (.md / .markdown), dotfiles excluded.
  • Open files as native tabs — double-click (or Enter) opens a file in the same window as an OS tab; each file is its own document with its own undo/dirty state. Re-opening an already-open file just focuses its tab.
  • macdown . — the CLI learns to accept a directory and opens it as a workspace (files still open as before; macdown file.md is unchanged).
  • Hide/show with ⌘\, Reveal in Finder / Copy Path context menu, and live refresh when the folder changes on disk.
  • Seamless tab switching — sidebar width, visibility, and expanded folders stay in sync across a workspace's tabs (editor/preview split and per-file selection stay per-tab).

How it works

MacDown is a standard NSDocument app (one document per window). Rather than refactor that, this leans into native window tabbing (addTabbedWindow:): each file stays its own MPDocument, and the OS merges their windows into one tabbed window. The sidebar is added per-window by nesting the existing editor/preview split inside an outer NSSplitView.

New components (all under MacDown/Code/Sidebar/):

  • MPFileNode — filesystem-tree model (filtering + folders-first sort).
  • MPFolderWatcher — recursive FSEvents watcher (respects the existing remote-volume guard).
  • MPFolderSidebarViewController — the source list + open/activation + context menu.
  • MPSidebarSyncCoordinator — shares sidebar state across tabs.

Wiring:

  • MPDocument gains workspaceRootURL, sidebar install/toggle, and the open-as-tab flow.
  • MPMainController gains Open Folder… and inserts its menu items by member selector (so they install in non-English locales too).
  • macdown-cmd routes directory arguments to a new shared-defaults key.

Testing

  • New XCTest coverage for the model, watcher, sync coordinator, directory routing, menu installation, tab-reuse lookup, and workspace-root propagation. The full suite passes (the pre-existing HGMarkdownHighlighterTests theme failures are unrelated to this change).
  • Window tabbing and the view nesting can't be exercised headlessly; those were verified manually in the running app: Open Folder… / macdown ., double-click-to-tab + tab reuse, ⌘\ toggle, live refresh, Reveal/Copy Path, and cross-tab sync.

Notes / design decisions

  • Per-tab sidebar, kept in sync. Native tabs are separate windows, so each carries its own sidebar; the coordinator keeps width/visibility/expansion consistent (no-op updates are ignored to avoid feedback loops, and width only syncs on a real divider drag).
  • No persistence across launches (start fresh), other than the sidebar's default width.
  • Happy to split this into smaller commits, adjust scope, or iterate on anything.

Closes/relates to: (feel free to link a folder-browsing feature request if one exists)

Browse a folder of Markdown files in a hideable sidebar and open them as
native macOS window tabs (one NSDocument per file). Reachable via a new
File > Open Folder... command and a 'macdown .' CLI directory argument.

- MPFileNode: filesystem-tree model (folders + Markdown files, sorted;
  dotfiles excluded).
- MPFolderWatcher: recursive FSEvents watcher for live refresh (respects the
  remote-volume guard).
- MPFolderSidebarViewController: NSOutlineView source list; double-click /
  Enter opens a file as a tab (reusing an already-open tab); Reveal in
  Finder / Copy Path context menu.
- MPSidebarSyncCoordinator: keeps sidebar width / visibility / folder
  expansion in sync across a workspace's tabs so switching tabs is seamless.
- MPDocument gains workspaceRootURL + sidebar install/toggle (Cmd-\) +
  open-as-tab; MPMainController gains Open Folder... and programmatic menu
  items located by selector (locale-proof); macdown-cmd routes directory
  arguments through shared defaults.

No new dependencies. The editor/preview pipeline and existing single-file
behaviour are unchanged. Covered by XCTest.
@schuyler

Copy link
Copy Markdown
Owner

@fluxa pretty exciting, thank you for submitting. this is a feature that several folks have asked for. I'll have a review done and send notes back. we can try to target the 3000.0.8 release for this feature.

@fluxa

fluxa commented Jun 30, 2026

Copy link
Copy Markdown
Author

Thanks, sounds great, ready for your notes whenever.

@schuyler schuyler added this to the v3000.0.8 milestone Jul 1, 2026
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.

2 participants