Support js/wasm build - #138
Conversation
Exclude the tty/ioctl based getTermWindowSize from js builds and add a js implementation that asks the tcell screen for its size, so gocui applications can be compiled with GOOS=js GOARCH=wasm and run in a browser via tcell's WebAssembly backend. Claude-Session: https://claude.ai/code/session_01NP7bUvSDzvc2XwHE5YhX4o
- Switch gocui to the ngs/gocui fork with js/wasm support (upstream PR: awesome-gocui/gocui#138) and upgrade tcell to v2.13 - Abstract persistence behind storage.go / storage_js.go; the js build saves settings and game progress to localStorage - Add web/ static assets: index.html (fullscreen terminal sized to the window via terminalCells/tcellSetSize, GitHub link overlay) and patched tcell.js webfiles (clear stale cell next to wide chars, force wide glyphs to 2ch, compute mouse cell coordinates per event) - Add make wasm / make serve-wasm (Go dev server with port fallback) - Add pages.yml workflow deploying dist/ to GitHub Pages (koikoi.ngs.io) Claude-Session: https://claude.ai/code/session_01NP7bUvSDzvc2XwHE5YhX4o
If the page defines terminalCells() returning [cols, rows], the js/wasm terminal is sized to it at startup instead of tcell's default 80x24, and the page can call tcellSetSize(cols, rows) from a resize listener to resize the running terminal. tcell's SetSize posts an EventResize, so gocui relayouts as usual. The page is treated as an untrusted boundary: exceptions thrown by terminalCells() and malformed return values are ignored. Screen.SetSize is looked up via an interface assertion because the tcell version pinned here (v2.4) predates it; applications that build with a newer tcell get the behavior automatically. Claude-Session: https://claude.ai/code/session_01NP7bUvSDzvc2XwHE5YhX4o
|
It might be worth to just update No need for the Then in your wasm app, you could just use the |
Follow up on the review of awesome-gocui#138: instead of teaching gocui about the browser through a set of JS globals, get the terminal size from tcell on every platform and expose tcell's Screen.SetSize as a gocui API. - Bump tcell to v2.9.0. Screen.SetSize landed in v2.6.0, but v2.9.0 is the first release whose wScreen implements the full screenImpl interface, so it is the oldest version that builds for GOOS=js GOARCH=wasm. - NewGui now always takes the size from screen.Size(), which makes the platform specific getTermWindowSize implementations redundant: gui_others.go (tty ioctl), gui_windows.go (GetConsoleScreenBufferInfo) and gui_js.go (the JS globals added by this branch) are all removed. - Add Gui.SetSize, so an application can ask the terminal to resize. On js/wasm this lets the hosting page decide how many cells fit into the browser window, without gocui reaching into JS itself. Note that tcell v2.9.0 requires Go 1.23, so the go directive of both modules moves from 1.13 to 1.23.0.
Purely mechanical: gofmt reindents the Go 1.19 style doc comment code blocks. The CI formatting job runs gofmt -s from the matrix Go version, so this is needed before that matrix can move off Go 1.16. No code changes.
The matrix was pinned to Go 1.13/1.15/1.16, which can no longer resolve the module now that the go directive is 1.23.0. Also build the js/wasm target and run the tests, neither of which the workflow covered.
|
Thanks @dankox, that is a much better shape than what I had. I reworked the branch along your suggestion. What changed
Two things worth your call
Verified
For context on the tcell side: the wasm backend fixes I have been leaning on (gdamore/tcell#1150, gdamore/tcell#1151) are ones I sent upstream and gdamore merged earlier this month, so the browser path is in reasonable shape now. |
Summary
This PR makes gocui compile for
GOOS=js GOARCH=wasm, so gocui applications can run in a browser using tcell's WebAssembly backend (webfiles/).Currently a js/wasm build fails because
gui_others.gorelies on tty ioctls and signals that do not exist on js:Changes
Commit 1 — build support
gui_others.gofrom js builds (//go:build !windows && !js)gui_js.gowith agetTermWindowSizeimplementation that asks the tcell screen for its size, which is how the WebAssembly backend reports the emulated terminal dimensionsCommit 2 — let the hosting page control the terminal size (optional but makes browser apps practical)
terminalCells()returning[cols, rows], the terminal is sized to it at startup instead of tcell's default 80x24tcellSetSize(cols, rows)is registered so the page can resize the running terminal from aresizelistener; tcell posts anEventResizeand gocui relayouts as usualScreen.SetSizeis looked up via an interface assertion because the tcell version pinned in go.mod (v2.4) predates it, so this PR requires no dependency bump; applications building with a newer tcell get the behavior automaticallyTesting
go build ./...andgo test ./...pass on darwinGOOS=js GOARCH=wasm go build ./...now succeedswebfiles, including dynamic window resizing: https://koikoi.ngs.io (source: https://github.com/ngs/go-koikoi)