The Problem
Developers need a fast, featureârich plainâtext editor for iOS that can handle code (syntax highlighting, line numbers, invisibleâcharacter rendering, etc.) without pulling in heavyweight UI frameworks. Existing options are either heavy, lack Treeâsitterâbased incremental parsing, or are tied to macOS only.
What This Does
Runestone delivers a Swiftânative editor component built on Treeâsitter for incremental parsing. The core UI lives in Sources/Runestone/TextView/Core/, e.g. TextView.swift (the primary UIView subclass) and TextInputView.swift (handles input, cursor, and selection). Syntaxâhighlighting rules are defined in language packages under Example/Languages/Sources/, such as RunestoneJavaScriptLanguage/TreeSitterLanguage.swift. Themes are pureâSwift assets in Example/Themes/Sources/, e.g. RunestoneOneDarkTheme/OneDarkTheme.swift. The sample iOS app (Example/Example.xcodeproj) wires the editor in Example/Example/Application/SceneDelegate.swift and demonstrates usage of helpers like TextView+Helpers.swift.
How It Is Wired
Entry point â the iOS launch sequence starts in Example/Example/Application/SceneDelegate.swift, which creates a UIWindow and sets MainViewController as root. MainViewController imports Runestone and instantiates Runestone.TextView (implemented in Sources/Runestone/TextView/Core/TextView.swift).
Parsing â TextView holds a TreeSitterLanguage instance (see Example/Languages/Sources/RunestoneJavaScriptLanguage/TreeSitterLanguage.swift). On text changes, TextEditHelper.swift (in Sources/Runestone/Library/) batches edits and forwards them to the languageâs tree_sitter parser (C source Example/Languages/Sources/TreeSitterJavaScript/src/parser.c). The parser returns a syntax tree that drives the RedBlackTreeâbased line model (Sources/Runestone/RedBlackTree/RedBlackTree.swift).
Rendering â TextView walks the syntax tree, applying HighlightName definitions from theme files (RunestoneThemeCommon/HighlightName.swift) to generate NSAttributedString fragments. The view also consults TextView+Helpers.swift for invisibleâcharacter rendering and lineânumber drawing.
Effect scope â The editor component does not perform I/O itself; all side effects (file saving, network sync) are expected to be handled by the host app. The widest blast radius within the repo is TextView.swift (â1,500 LOC) and TextInputView.swift, because they own the view hierarchy, edit batching, and interaction with the parser.
No circular import edges were detected; the internal module graph is flat, simplifying future refactoring.
How To Use It
# clone the repo
git clone https://github.com/moses-y/Runestone
cd Runestone
# build the example app (SwiftPM)
swift build -c release
# open the Xcode project to run on a simulator/device
open Example/Example.xcodeproj
Add the package to another project by pointing Xcode to Package.swift. Import Runestone and create a Runestone.TextView in a view controller. Configure a language by adding a TreeSitterLanguage subclass (see RunestoneJavaScriptLanguage/TreeSitterLanguage.swift) and a theme by conforming to EditorTheme (see OneDarkTheme.swift).
RealâWorld Use
A noteâtaking app can embed Runestone.TextView to provide codeâaware editing. The host app registers TreeSitterLanguage for each supported language, then persists the editorâs text property to iCloud. Because parsing is incremental, scrolling through a 10âŻkâline source file remains smooth on iPhoneâŻ12.
Code Health & Issues
Static analysis findings (48 total, 20âŻhigh / 28âŻmedium):
- Deep nesting â up to 8 levels in
Example/Languages/Sources/RunestoneJavaScriptLanguage/TreeSitterLanguage.swift,Example/Languages/Sources/TreeSitterJavaScript/src/scanner.c,Sources/Runestone/Library/TextEditHelper.swift. - Duplicated code blocks â 528âline fragments repeated across 77 files (e.g.,
SceneDelegate.swiftin both Example and UITests). - Oversized files â
Sources/Runestone/TextView/Core/TextView.swift,Sources/Runestone/TextView/Core/TextInputView.swift,Sources/TestTreeSitterLanguages/html/parser.ceach exceed 1,400 lines. - High branching density â 38 branches in 85 lines in
Sources/Runestone/RedBlackTree/RedBlackTree.swiftand similar files.
CI/CD hygiene (5 audit findings):
- HIGH â Pin thirdâparty actions to commit SHAs in
.github/workflows/*. - HIGH â Remove
continue-on-errorfrom correctness steps inbuild_and_test.yml. - MEDIUM â Declare leastâprivilege
permissionsforGITHUB_TOKEN. - MEDIUM â Move large binary
Design/Tutorials.sketch(28âŻMB) to GitâŻLFS. - LOW â Add
timeout-minutesto workflow jobs.
All tests (89 files) and documentation (9 doc files) are present, and a license is included.
The Bottom Line
Runestone provides a solid, Treeâsitterâbacked iOS text editor with rich codeâediting features, but the core UI files are large and contain deep nesting, making future maintenance nonâtrivial. It is wellâsuited for teams that need a performant inâapp code editor and are comfortable refactoring the identified hotspots.