Skip to content

TextMate 2.2.0-undead

Choose a tag to compare

@github-actions github-actions released this 27 Aug 03:56
Immutable release. Only release title and notes can be modified.
bb8b704

2026-08-26 (v2.2.0-undead)

The rave build system is replaced by CMake, two crashes are fixed, and a fork-wide sweep gets bundle Ruby running on the system interpreter — 50 bundle pull requests across 40 repositories. See all changes since v2.1.5-undead.

Build

  • rave is gone; the tree builds with CMake and Ninja. bin/rave (1,686 lines of Ruby), configure and the 60 default.rave files are removed, along with two scripts only rave called — bin/gen_build and bin/notarize_await, the latter obsolete since notarytool replaced altool. The test suites run under CTest, and CI and the release workflow configure and build through CMake. ⌘B still builds and relaunches TextMate: bin/relaunch_app reproduces rave's TextMate/run target behind a run target. (#42, d4f6338f, 65d907b6, 94bd8270)
  • The CMake build came from @tectiv3. tectiv3/textmate migrated TextMate to CMake first, and this fork adopted their work rather than repeating it: the root CMakeLists.txt, cmake/TextMateHelpers.cmake, CMakePresets.json and 54 of the module CMakeLists.txt files are theirs. Three more — SoftwareUpdate, network and CrashReporter — were written here because tectiv3 had dropped those modules, and version derivation, Markdown rendering and a few include scopes were adapted to this tree. Thanks for doing it first.
  • boost, google-sparsehash and ragel are no longer build dependencies. google::dense_hash_map gives way to std::unordered_map, ascii.rl to a hand-written ASCII plist parser, boost::variant to std::variant, and boost::crc_32_type to zlib's crc32(). Ported from tectiv3/textmate 36acd469, 34e166b9 and 2c49eead. multimarkdown is deliberately retained — it drives the twelve in-app Help pages as well as the About window, and is build-time only. (#42, 0bbeb579)
  • Deployment target raised from 10.12 to 14.0, which the dependency removals require (std::variant needs a modern libc++). LSMinimumSystemVersion follows it, so the app now declares macOS 14 as its floor. (#42, d8867a71)
  • Globbed sources are re-scanned on every build. CMake's file(GLOB) runs once at configure time, so a newly added file was silently ignored until someone re-ran cmake by hand — and for tests that failure is invisible: the file is not compiled into the runner and the suite passes without it. CONFIGURE_DEPENDS makes ninja recheck each glob. (#43, 37bc59a9)
  • Contributions.md aggregates by person instead of by commit. One entry per commit rendered 739 rows and 1.1 MB of HTML that changed on every push; it is now one row per contributor — avatar, name, handle, commit count, years active — 107 contributors and 39 KB. Identity keys on the GitHub login, so someone who committed under several addresses appears once. (#42, 8e01ffc8)

Stability

  • Fixed a crash on launch while restoring a session. An uncaught std::bad_variant_access escaped NSApplicationMain and main()'s handler called abort(). Moving plist::any_t off boost::variant had renamed the lenient plist::get<T> to plist::convert<T> and given the old name to the strict accessor, so call sites that relied on coercion silently became strict — and grammars and themes in the wild do carry a numeric name or a string disabled. The lenient read is restored at the schema field handlers, the theme colour and font reads, and the disabled check in parse::convert_plist. (#43, bc899cb4)
  • Fixed a crash on ⌘G and ⇧⌘G in the HTML output window. -findNext: and -findPrevious: passed completionHandler:nil to -[WKWebView findString:withConfiguration:completionHandler:], whose handler parameter is implicitly nonnull; WebKit invokes it without a null check, faulting at 0x10 on the async IPC reply. The find dialog was never affected — only the two keyboard shortcuts. (#44, 8473c153)

Editor

  • Tab titles and close buttons are centred again. Both were pinned a few points above the bottom of the tab, which only centres them in a 22pt tab — the height OakTabBarView asks for. As a titlebar accessory it is fixed at 36pt whatever it requests, so tabs are 35pt and both subviews sat well below the middle. They are constrained to the tab's centre instead. (#46, a48d539e)

Commands

  • Commands run in a UTF-8 locale. Launched from Finder the app inherits no LANG or LC_*, and neither is in the environment whitelist, so everything it spawned landed in the C locale. For Ruby that means Encoding.default_external is US-ASCII and ENV strings come back tagged ASCII-8BIT, so interpolating a TM_FILEPATH containing an accent raised Encoding::CompatibilityError. bash_init.sh had exported LC_CTYPE since forever, but fix_shebang only prepends that preamble to commands with no shebang of their own — every #!/usr/bin/env ruby command went without. It is now set in setup_basic_environment(), covering all of them. (#48, 5cab4eef)
  • No more env: ruby18: No such file or directory. macOS has no ruby18, so every command carrying that shebang died at exec. Fixed in Avian.tmbundle, which ships inside the app and has no upstream repo of its own, and in the Bundle Editor command templates, which were minting a ruby18 shebang into every newly created command. The 1.8-era -KU flag — which Ruby 2.6 warns about on every run — is replaced by -Eutf-8. (#45, #47, f8803570, 525ac364)

Bundles

The embedded bundles are pinned by SHA and ship with the app; everything in the catalogue auto-updates from main and arrives on the next poll.

  • Word Count works again. Text.tmbundle required jcode, removed in Ruby 1.9, and called the String#jcount it added, so the command died at the require on a fresh install. Pin 34ab5891f3fd9fc9. (#51, text.tmbundle#1, thanks @capac)
  • Every command that used shelltokenize was broken. lib/shelltokenize.rb failed to parse at all under the system Ruby — invalid multibyte escape: /[^\w_\-\+=\/\x7F-\xFF]/ — whatever shebang the caller carried. Bundle Support and Source pins bumped to pick that up, along with File.exists?/ERB.new modernization (thanks @mattneub) and the Source shebang fix. (#49, 4a9664fb)
  • ruby18 shebangs replaced across 15 bundles — cvs, lua, bundle-development, cron, groovy, html, java, markdown, perl, php, python, ruby, source, xcode and yaml — and ruby20 in html and rust.
  • The 1.8-era -K flag replaced with -Eutf-8 in 18 bundles — ant, applescript, arduino, cmake, git, golang, haskell, Julia, nim, ninja, pdb, processing, r, rust, scala, swift, tads3 and vagrant. Dropping it outright is not enough: with no locale set Encoding.default_external falls back to US-ASCII, which is what -KU was there to prevent.
  • Hash#to_plist resolves again in 6 bundles — ant, apache, git, objective-c, ocaml and html — which used it without requiring private/plist.
  • Markdown list commands work under modern Ruby. List.parse called String#to_a, removed in Ruby 1.9. (markdown.tmbundle#2, thanks @tbates)
  • GitHub Markdown preview works under Ruby 4.0. Rouge 3.x calls CGI.parse in Lexer.lookup_fancy, and Ruby 4.0 ships only cgi/escape, so any code block with no language tag — including every indented one — raised NoMethodError when TM_RUBY pointed at a modern interpreter. The cgi gem is now a declared dependency. (GitHub-Markdown.tmbundle#3, reported by @capac)
  • Hyperlink Helper matches non-ASCII URLs. URL detection covered ASCII only, so an IRI stopped at the first accented character; matching also no longer runs through Unicode whitespace. (hyperlink-helper.tmbundle#1, #2, thanks @tectiv3)
  • AppleScript URL escaping uses URI::DEFAULT_PARSER.escape instead of URI.encode, removed in Ruby 3.0. (applescript.tmbundle#2)
  • iPhone dropped from the catalogue, 108 entries → 107. Its Completion: Inside Brackets command requires a symlink into the flat TextMate 1 bundle layout, which cannot resolve under one-repo-per-bundle; Objective-C grammar and completion come from objective-c.tmbundle. It was never a default bundle, so nothing installed it. (#50, bundle-support.tmbundle#9)

What's Changed

Full Changelog: v2.1.5-undead...v2.2.0-undead