Table of Contents
-
Go
-
tview (2.0 without validation, i1.0, u1.5)
Note that the edit modal does not apply a darkened background.
-
gocui (possibly 1.0, UI was made before the specification solidified)
Supports adding and toggling
-
(planned) bubbletea
-
vaxis (1.1 without buttons, i1.1, u1.1) edit modal does not apply a darkened background
-
-
Rust
-
ratatui (1.2, i1.1, u1.0)
fully featured except mouse support and a "proper" modal UI for editing. Note, editing is supported by borrowing the newtodo input widget.
-
(maybe?) cursive, requires ncurses
-
(STALLED) zi (-, -, u1.5)
interestingly, there's a "todos" example in the Zi repository where the code explicitly declares a "TodoMvc" component. However, it does not fully implement what this specification requires, nor looks like the actual TodoMVC, it does however provide many extra features than these implementations.
-
(planned) tui-realm
-
-
Zig
- libvaxis (1.0, i1.1, i1.0)
-
Lua (but written with Fennel, probably)
- (planned) ltui
- (planned) a C lib with bindings
-
Nim
-
illwill (1.0, i1.1, u1.0)
Similar in terms of functionality (& limitations) as the V-lang implementation. One difference being that modal dialog for editing is not implemented.
-
(planned) nimwave
-
-
C
- (planned) ncurses, possibly
-
Python
-
Textual (2.0 without buttons, i1.0, u1.5)
Does not have buttons for "mark all as completed" etc because I can't figure out how to have single-row buttons in textual, and using keybindings to do these operations instead is boring and trivial.
-
(probably NOT) urwid, curses
-
(WIP) blessed
-
(planned) pytermgui
-
-
(planned) Some lisps, hopefully.
-
JS/TS
- (planned) react-ink, probably.
- (planned) solid-ink
- (no) deno-tui does not seem customizable enough just yet to suit my needs (event handling)
-
(planned) shell - bash or maybe even nushell.
-
haskell- as much as I'd love to add it to the list, the tooling is extremely involved to setup (on my machine) right now. -
OCaml
-
(WIP) minttea
-
(WIP) lwd + nottui
-
-
V
-
term.ui
(1.1, i1.1, u1.1)fully-featured with modal dialog (with darkened background) for editing, no mouse support.
-
-
(planned) C++
-
(WIP) Odin (using only
core:encoding/ansi
), also note some of these resources might be useful as an ad-hoc solution: https://github.com/odin-lang/Odin/discussions?discussions_q=terminal -
(planned) Odin -- Waiting for the core
terminal
package to be implemented: odin-lang/Odin#978
- finish V version
- frame for nim illwill
- continue with nim
- attempt at frame for go vaxis
- finalize UI and formalize it into spec
- attempt at rust Zi
- update older impl to new UI spec
- finish go vaxis
- finish rust Zi
- attempt at Zig libvaxis
- finish Zig libvaxis
(loosely formatted)
Implementations marked with [x]
are deemed "complete". They should satisfy
at least version 1.0 as described below.
The "version" numbering next to bullet points gives a sense of the priority of a given feature for implementations. Ideally, an implementation that targets a version number of X should implement ALL features tagged with version X and lower.
- All code should be in a single file unless required otherwise by the
toolchain, in which case, stick to as little code splitting as possible for ease
of comparison. The single file should be named
main.<ext>
unless required otherwise by the toolchain. - Documentation on functions may be added
- A binary, if produced, or a project name if required, should be named "todomvc-tui". Use "todomvc_tui" if dashes are not allowed.
- Directories are named
<language>-<framework>
where language is the full language name, followed by the framework/library used that does the primary heavy-lifting for the terminal.
- Tests may be added, but they should not be in the
main.<ext>
file. For instance, therust-ratatui
implementation saves the actual code of the TUI insrc/main.rs
, and tests insrc/test.rs
, which is not needed for compiling the binary. - Linting is not necessary, but recommended. (E.g.
cargo clippy
,go vet
) - An official style guide or formatting tool should be used if available. (E.g.
zig fmt
,go fmt
)
0.1
- Show N incomplete under the todolist, right-aligned. It should be hidden where there are no items in the todolist. A custom text (such as "All done!") when there are items, but all have been completed, and a "N items left"/"1 item left" otherwise.
- Keys to navigate the list --
up/down/j/k
- Input field should support arrow keys, backspace/delete, and basic emacs keys
Ctrl-A/Home
,Ctrl-E/End
- Space key to toggle completion state of the currently selected todo item
1.0
- Scrollable list view -- todo items should not be drawn to "overflow" the list container
1.1
e
key to edit the name of the currently selected todo item, using a pop up modal. It should support both saving the new name, or cancelling the operation
1.2
- Button to mark all as completed
- Button to clear all completed items. (See how current selection is retained in the Rust Ratatui implementation, where the current selection is kept if it is not cleared; if it is cleared, a previous item is selected.)
The row of buttons should be below the input and above the todolist. (See Go Tview for an example.)
2.0
- Input validation -- new todo item name must be a non-empty string (with leading/trailing whitespace trimmed), see Python Textual implementation.
- Backspace key to delete items. The previous item should be selected afterwards.
- Mouse to switch focus between input and todolist.
- Mouse support for input field (see Go Tview and Python Textual) for example behaviour
u0.1
- Hero section with a center-aligned
T O D O M V C
- New todo input field: height (including borders) 3
- List items in the todo list should have total height of 3 rows each. The middle row is used to display the completion status followed by the todo name.
- Use
(X)
/( )
to show completion status, unless a native "checkbox" widget is built-in, such as in Python Textual.
u1.0
- Solid borders for input and todolist.
- Different style/color of borders determines focus, unless the framework supports this natively using another distinction (such as solid vs double borders like in Go Tview).
- Centered main section (hero, input, todolist, itemsleft) with equal margins on either sides.
- itemsleft right aligned under the todolist
u1.1
- Edit modal applies a background overlay on top of other contents outside modal. (See how it can be implemented by-hand in the Vlang implementation.)
u1.2
- A footer with the list of keys and their descriptions (see screenshot at the top showing Rust Ratatui). Keys should be bold. The entire line should be centered.
u1.5
-
Widgets dynamically sized rather than hardcoded -- for wide screens, keep the width within a maximum, and for narrow screens, remove side paddings entirely and fill widgets to the full width. Side padding (number of columns and the sides) may be hardcoded for "medium"-width screens.
The exact cutoffs are currently undecided. See Python Textual, Go Tview implementations for examples.
i1.0
- structs for Todo, and method (if supported by language) for
toggle()
i1.1
- structs and methods for both Todo and Todolist (if supported by language)
i1.5
- refactor input, list, and itemsleft as separate widgets with their own lifecycle/update methods (as applicable to the framework used)
i2.1
- incremental re-renders (rather than re-drawing the entire screen on each update), or an alternative method of performance optimization of renders
A package definition file, e.g. Cargo.toml
, go.mod
is not strictly necessary
unless the toolchain requires these files to be present to compile.
- Some toolchains require package definition files to include a "version"
number. The spec compatibility version number as specified
above may be used. If SemVer is required, kindly keep the
patch portion 0. For instance,
1.2
->1.2.0
. If the the version key is used, use only the version number for functionality, and omit ones for UI, internals, or other prefixed versions. - The author of the implementation should be the one listed in the author field, if required.
- The repository field should be set to https://github.com/hedyhli/todomvc-tui, if required.
- If the documentation field should be set to be the same as repository field, if required.
- The implementation "project" should only specify an executable. A provided
library should NOT be defined (for example, see
build.zig
of Zig Vaxis). - The package itself should NOT be published.
Kindly take these at face value and analyze at will in conjunction with the spec feature versions as listed at the top.
The command snippets, which are in Nu, are provided as a rough overview of the commands run in the stats script with the formatting code removed to get the idea across.
( scc --by-file -f csv --sort code --uloc
rust-ratatui/src/main.rs go-tview/main.go # ...
| from csv | select Filename Code Comments Complexity ULOC | to md )
Kindly read in conjunction with the implementation spec compatibility version numbers, and keep in mind this is not a code-golfing competition!
File | Code | ULOC | Comments | Complexity |
---|---|---|---|---|
rust-ratatui (src/main.rs) | 407 | 345 | 31 | 63 |
v-term-ui (main.v) | 348 | 287 | 38 | 86 |
go-vaxis (main.go) | 338 | 290 | 36 | 44 |
zig-libvaxis (src/main.zig) | 326 | 308 | 48 | 78 |
nim-illwill (main.nim) | 247 | 270 | 47 | 25 |
go-tview (main.go) | 181 | 162 | 3 | 21 |
python-textual (main.py) | 180 | 146 | 5 | 9 |
Each implementation here is compiled using a command as listed below, then the
binary is moved to ../bin/<name-of-dir-as-exe-name>
.
Toolchain specs
Rust
stable-aarch64-apple-darwin (default)
rustc 1.77.2 (25ef9e3d8 2024-04-09)
cargo build --release
Go
go version go1.19.5 darwin/arm64
go build
Zig
- version 0.13.0
zig build --release=<annotated>
Nim
Nim Compiler Version 2.0.0 [MacOSX: arm64]
Compiled at 2023-08-01
nim c main.nim
V
V 0.4.6 6b2d527
v main.v
ls bin | sort-by -r size | select name size | to md
Name | Size |
---|---|
go-tview | 3.8 MiB |
go-vaxis | 2.9 MiB |
rust-ratatui | 711.3 KiB |
v-term-ui | 630.6 KiB |
zig-libvaxis (safe) | 389.4 KiB |
zig-libvaxis (fast) | 324.5 KiB |
nim-illwill | 289.8 KiB |
zig-libvaxis (small) | 153.9 KiB |
It might be interesting to use PyInstaller for python-*
implementations here
to compare binary sizes with AOT-compiled languages, but I am not yet interested
in installing PyInstaller just for this single purpose. This can be done once I
set up CI that will automate generating these tables.
The spec isn't yet finalized, but I'm happy to review PRs/patches that introduce new implementations with the same features and UI as any of the existing ones, either in another language, or another framework of an existing language. Such as... more lisps!