Embeddable text editing and rendering plugins for Bevy. Drop them into any app and they coexist with your existing ECS world.
Scope: this is a component library, not a standalone IDE. It gives you a capable code-editing widget you can embed inside a Bevy application — window management, project trees, debugger UIs, and similar IDE-level concerns are outside its scope.
| Crate | What it does | |
|---|---|---|
bevy_instanced_text (separate repo) |
GPU-instanced text rendering: glyph atlas, soft-wrap layout, overlays. | |
bevy_instanced_text_interaction (separate repo) |
Shared UI primitives: clipboard, selection, caret rendering, picking observers. No ropey dep. | |
bevy_instanced_text_editor |
Rope-backed editable text: edit history, undo/redo, typed-char insertion, anchors. | |
bevy_tree_sitter |
Tree-sitter incremental syntax highlighting. | |
bevy_lsp |
Async LSP transport. Responses arrive as Bevy messages. | |
bevscode |
Code editor: multi-cursor, folding, brackets, line numbers, LSP UI. | |
bevsterm |
PTY-backed terminal widget. | (not published — wezterm deps not on crates.io) |
| bevscode | Bevy |
|---|---|
| 0.1 | 0.18 |
use bevy::prelude::*;
use bevscode::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(CodeEditorPlugins)
.add_systems(Startup, |mut commands: Commands| {
commands.spawn(Camera2d);
// AutoResizeViewport keeps the editor's Node sized to the window.
commands.spawn((CodeEditor, AutoResizeViewport));
})
.run();
}For a fixed-size pane (e.g. split layout), omit AutoResizeViewport and set an explicit Node:
commands.spawn((
CodeEditor,
Node { width: Val::Px(800.0), height: Val::Px(600.0), ..default() },
));Pick the plugin set that matches your use case:
// Just GPU text rendering (labels, HUDs)
.add_plugins(InstancedTextPlugins)
// Rendering + selection / clipboard / scroll-wheel
.add_plugins((
InstancedTextPlugins,
InstancedTextInteractionPlugin::<TextSpan>::default(),
))
// Full code editor (cursor, edits, syntax, folding, LSP UI)
.add_plugins(CodeEditorPlugins)State is plain ECS — query it from any system:
use bevy_instanced_text_editor::RopeBuffer;
fn status_bar(
editors: Query<(&TextBuffer<RopeBuffer>, &CursorState), With<CodeEditor>>,
) {
for (buffer, cursor) in &editors { /* … */ }
}To handle a built-in editor action (save, open, completion request, …), add a handler system with EditorAppExt:
use bevscode::prelude::*;
App::new()
.add_plugins(CodeEditorPlugins)
.add_editor_action_handler(my_save_handler)
.run();
fn my_save_handler(mut events: MessageReader<SaveRequested>) {
for ev in events.read() { /* … */ }
}MIT OR Apache-2.0
