Architecture
SweetEditor is built around a strict split between a native editor kernel and a Kotlin/Compose wrapper.
High-level Structure
editor-core: native editor kerneleditor-compose: Kotlin Multiplatform wrapper and Compose UI integrationexample: reference applicationplatform-demo: platform-specific demos and experiments
Core Principle
The project is not a BasicTextField enhancement. It is a dedicated editor architecture:
- native kernel owns editing semantics
- Kotlin layer owns state wrapping, protocol decoding, and Compose integration
- Compose layer consumes render models instead of re-deriving editor state
Layer Responsibilities
Native Core
The native core is responsible for:
- document model
- editing algorithms
- cursor and selection semantics
- render model generation
- fold state, bracket matching, highlighting, diagnostics payloads
- C API surface exported to Kotlin
The core used by this repository is based on:
Kotlin Wrapper
The Kotlin Multiplatform layer is responsible for:
- safe native bridge calls
- binary protocol parsing
- lifecycle management of native-backed documents
- public APIs such as controllers, providers, and events
- platform source set isolation
Typical types in this layer include:
SweetEditorControllerEditorDocumentDecorationProviderCompletionProviderInlineSuggestionController
Compose UI Layer
The Compose layer is responsible for:
- rendering the editor surface
- pointer, keyboard, and IME integration
- popup UI such as completion and inline suggestion action bars
- text measurement and theme application
Render Flow
The typical rendering pipeline is:
- editor input is sent through the Kotlin wrapper
- native core updates document and render state
- core emits render payload / model data
- Kotlin decodes payload into Compose-consumable models
- Compose draws the editor surface from that render model
Decoration Flow
The decoration pipeline is intentionally layered:
- Compose/Kotlin provider reads
DecorationProviderContext - provider returns
DecorationUpdate - manager merges or replaces provider-owned data
- wrapper encodes the aggregated result
- native core consumes the decoration payload
- render model reflects the final result
Important Boundaries
- Do not re-implement native editing algorithms in Kotlin
- Keep common abstractions in
commonMain - Keep platform-specific hooks in their own source sets
- Treat the render model as the single source of truth for drawing