3
14
Fork
You've already forked dvui-editor
1
A simple vscode style text editor written in Zig with DVUI.
  • Zig 90.5%
  • C 4.5%
  • Objective-C 2.8%
  • Ink 2.2%
2026年06月16日 21:15:13 +02:00
core_widgets (chore) made contributing widgets much simpler. 2026年06月14日 21:53:30 +02:00
file_widgets (fix) preloading images for smooth animation, now have a large hang. 2026年06月16日 21:15:13 +02:00
src (chore) made contributing widgets much simpler. 2026年06月14日 21:53:30 +02:00
test_data (add) more integration tests for different file types. 2026年06月14日 12:02:06 +02:00
tests (chore) a little more beautiful markdown tables. 2026年06月15日 22:12:17 +02:00
ztray (chore) ztray readme. 2026年05月13日 21:17:42 +02:00
.gitignore (chore) some cleanup. 2026年05月13日 09:22:12 +02:00
build.zig (add) CodeEditor Tests and some renaming. 2026年06月14日 13:06:17 +02:00
build.zig.zon (chore) refactored into new file_widgets module. 2026年05月27日 18:07:12 +02:00
dvui-editor-csv.png (add) working CsvWidget with sorting. 2026年05月27日 21:27:10 +02:00
dvui-editor-ink.png (add) image with ink support 2026年05月15日 01:02:06 +02:00
dvui-editor-md.png (add) image with ink support 2026年05月15日 01:02:06 +02:00
LICENSE (add) license. 2026年05月12日 07:57:14 +02:00
README.md (chore) made contributing widgets much simpler. 2026年06月14日 21:53:30 +02:00

DVUI Editor

A simple vscode style text editor written in Zig with DVUI.

DVUI Editor Markdown DVUI Editor Ink DVUI Editor CSV

Contributing

Adding support for a new file type

file_widgets/ is the home for file-format-specific widgets. Each format typically needs two files:

Steps to wire up a new format:

  1. Create your widget files in file_widgets/src/. The widget module must export:

    pubconstwidget_id="my_format";// unique snake_case idpubconstwidget_name="My Format Editor";// shown in the infobarpubfnfileTypePriority(kind:FileType.Kind)?u8{...}pubfninit(...)MyFormatWidget{...}pubfndeinit(self:MyFormatWidget)void{...}pubfnprocessEvents(self:*MyFormatWidget)void{...}

    If the widget needs persistent state (parsed AST, scroll position, etc.), also export:

    pubconstState=MyFormatPreviewWidget.State;
  2. Register it in file_widgets/src/root.zig — two lines only:

    pubconstMyFormatWidget=@import("MyFormatWidget.zig");// top of file// ...constwidget_table=.{// ... existing widgets ...MyFormatWidget,// ← add here};

    WidgetKind, WidgetState, and all dispatch are generated automatically from the table.

  3. Register the file extension in core_widgets/src/FileType.zig.

  4. Declare any new C libraries in file_widgets/build.zig.

Widget priority

Each widget declares pub fn fileTypePriority(kind: FileType.Kind) ?u8. Return null if the widget doesn't support a given kind; return an integer otherwise — lower wins (the widget is shown by default). Established values:

Priority Widgets
50 Format-specific editors (Markdown, Ink, JSON, CSV)
100 CodeEditorWidget (source files)
200 TextEditWidget (all editable files)
255 TextEditWidget for unknown (no-extension) files

The infobar automatically shows a dropdown when more than one widget supports the open file, letting the user override the default.

Testing a new file type widget

Add a file tests/<format>_test.zig following the pattern of the existing widget tests (e.g. tests/json_test.zig):

  1. Set up a FileRef with a small inline fixture and the correct path extension so FileType.fromPath routes correctly.
  2. Create the preview state (e.g. FooPreviewWidget.State = .{}), call settle(), and defer state.deinit(allocator).
  3. Assert parsed content — check state fields that the widget populates during rendering (parsed AST, table, transcript, etc.) and verify that specific fixture values appear in them.
  4. Assert dvui visibility — add a .tag to a key rendered widget (e.g. the success-path container) and call dvui.testing.expectVisible("my-tag") after settle.
  5. Wire it up in build.zig — the loop at the bottom of build() that calls addTest for each tests/*.zig file picks up new files automatically.

Advanced note: CsvPreviewWidget uses GridWidget which requires multiple frames to measure cell heights. Use a for (0..20) |_| { _ = try dvui.testing.step(frame.f); } loop instead of settle().

Credits