Skip to content

Commit 2bf85fe

Browse files
committed
chore(wails): remove all Wails references and dependencies
- Remove EventEmittingWriter (Wails-specific) from service layer - Replace with simple output buffer for non-API usage - Update README.md to replace Wails with Avalonia GUI - Update CLAUDE.md to remove gui/app_test.go reference - Update main.go help text to reference Avalonia instead of Wails - Remove unused Wails runtime import All Go tests passing (1024 tests)
1 parent 2b668ec commit 2bf85fe

File tree

4 files changed

+29
-32
lines changed

4 files changed

+29
-32
lines changed

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ go clean -testcache && go test ./...
2525
./arm-emulator program.s
2626
```
2727

28-
**Test Organization:** Tests in `./tests/unit/` and `./tests/integration/` (exceptions: `gui/app_test.go`, `debugger/tui_internal_test.go`)
28+
**Test Organization:** Tests in `./tests/unit/` and `./tests/integration/` (exception: `debugger/tui_internal_test.go`)
2929

3030
## Swift GUI (macOS, Primary GUI)
3131

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ This is an example of using vibe coding to re-create my first commercial project
66

77
Here I am attempting to use Claude Code to broadly recreate the emulator as a cross-platform Go project, with a simple TUI debugger. Claude was given a one-paragraph prompt and essentially left to its own devices, with only gentle high level steering.
88

9-
After the TUI interface, I went on to make a cross-platform GUI using Wails. While this works, I was dissatisfied with the webview interface, so **the Wails GUI is now deprecated**. The current GUI is a **native Swift app for macOS** that provides a superior native experience, calling into the Go VM using a REST API. Perhaps later I will write a Windows GUI using the same backend, using WinUI or WPF.
9+
After the TUI interface, I added a REST API backend to support GUI frontends. The project now includes two native GUI applications: a **Swift app for macOS** and an **Avalonia app for Windows/Linux/macOS**, both calling into the Go VM using the REST API.
1010

1111
The project therefore consists of:
1212

1313
- A Go backend implementing the ARM2 emulator, CLI and TUI debugger, and REST API for GUI integration
1414
- A native Swift macOS app providing a GUI frontend using SwiftUI and MVVM architecture
15-
- (Deprecated) A Wails cross-platform GUI using web technologies
15+
- An Avalonia cross-platform GUI using .NET and ReactiveUI (Windows/Linux/macOS)
1616

1717
## Security
1818

@@ -200,9 +200,15 @@ open ARMEmulator.xcodeproj
200200
- [docs/HTTP_API.md](docs/HTTP_API.md) - REST API and WebSocket reference
201201
- [openapi.yaml](openapi.yaml) - OpenAPI 3.0 specification
202202

203-
#### Wails Cross-Platform GUI (Deprecated)
203+
#### Avalonia Cross-Platform GUI
204204

205-
Web-based GUI available for reference. See [Wails.md](Wails.md) and [docs/GUI.md](docs/GUI.md).
205+
.NET-based GUI for Windows, Linux, and macOS. Built with Avalonia UI and ReactiveUI using MVVM architecture.
206+
207+
**Requirements:** .NET SDK 10.0+
208+
209+
**Documentation:**
210+
- [docs/AVALONIA_IMPLEMENTATION_PLAN.md](docs/AVALONIA_IMPLEMENTATION_PLAN.md) - Implementation details
211+
- [docs/HTTP_API.md](docs/HTTP_API.md) - REST API and WebSocket reference
206212

207213
### Symbol Table Dump
208214

@@ -341,8 +347,8 @@ Download pre-built binaries with SHA256 checksums from [Releases](https://github
341347
├── tools/ # Development tools (lint, format, xref)
342348
├── api/ # HTTP REST API backend for GUIs
343349
├── service/ # Service layer for API/GUI integration
344-
├── swift-gui/ # Swift native macOS app (SwiftUI + MVVM) - Primary GUI
345-
├── gui/ # Wails cross-platform GUI (DEPRECATED)
350+
├── swift-gui/ # Swift native macOS app (SwiftUI + MVVM)
351+
├── avalonia-gui/ # Avalonia cross-platform GUI (.NET + ReactiveUI)
346352
├── tests/ # Test files (1,024 tests, 100% passing, 75% coverage)
347353
├── examples/ # Example ARM assembly programs (49 programs)
348354
└── docs/ # User and developer documentation

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ Diagnostic Modes:
752752
-register-trace-format Register trace format: text, json (default: text)
753753

754754
Examples:
755-
# Start API server for GUI frontends (Swift app, Wails app)
755+
# Start API server for GUI frontends (Swift app, Avalonia app)
756756
arm-emulator -api-server
757757
arm-emulator -api-server -port 3000
758758

service/debugger_service.go

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package service
22

33
import (
44
"bytes"
5-
"context"
65
"fmt"
76
"io"
87
"log"
@@ -48,7 +47,7 @@ func init() {
4847
}
4948

5049
// DebuggerService provides a thread-safe interface to debugger functionality
51-
// This service is shared by TUI, GUI, and CLI interfaces
50+
// This service is shared by TUI, API/GUI frontends, and CLI interfaces
5251
//
5352
// Lock Ordering:
5453
// The service uses its own sync.RWMutex (s.mu) to protect all field access,
@@ -59,7 +58,7 @@ func init() {
5958
// This is safe because:
6059
// - The TUI uses the Debugger's internal mutex directly (no service mutex)
6160
// - The service always acquires s.mu before any Debugger method that uses d.mu
62-
// - The GUI only accesses debugger state through the service
61+
// - The API/GUI frontends only access debugger state through the service
6362
//
6463
// Do NOT acquire locks in the reverse order (debugger.mu -> s.mu) as this
6564
// would create a deadlock risk.
@@ -72,9 +71,8 @@ type DebuggerService struct {
7271
sourceMapByAddr map[uint32]string // Quick lookup by address (for debugger)
7372
program *parser.Program
7473
entryPoint uint32
75-
outputWriter *EventEmittingWriter
76-
ctx context.Context
77-
stateChangedCallback func() // Callback for GUI state updates
74+
outputBuffer *bytes.Buffer // Output buffer for VM output (when not using API)
75+
stateChangedCallback func() // Callback for GUI state updates
7876

7977
// stdin redirection for guest programs (GUI)
8078
stdinPipeReader *io.PipeReader
@@ -106,13 +104,6 @@ func (s *DebuggerService) GetVM() *vm.VM {
106104
return s.vm
107105
}
108106

109-
// SetContext sets the Wails context for event emission
110-
func (s *DebuggerService) SetContext(ctx context.Context) {
111-
s.mu.Lock()
112-
defer s.mu.Unlock()
113-
s.ctx = ctx
114-
}
115-
116107
// SetStateChangedCallback sets a callback for GUI state updates during execution
117108
func (s *DebuggerService) SetStateChangedCallback(callback func()) {
118109
s.mu.Lock()
@@ -157,17 +148,13 @@ func (s *DebuggerService) LoadProgram(program *parser.Program, entryPoint uint32
157148
}
158149
}
159150

160-
// Create output buffer with event emission
161-
// IMPORTANT: Only set OutputWriter if it hasn't been configured already.
162-
// The API server sets up EventWriter for WebSocket broadcasting before calling LoadProgram.
163-
// The GUI (Wails) doesn't pre-configure OutputWriter, so we set up EventEmittingWriter for it.
151+
// Note: OutputWriter should be configured by the API layer before calling LoadProgram.
152+
// The API server sets up EventWriter for WebSocket broadcasting.
153+
// If OutputWriter is still os.Stdout, set up a buffer to capture output for GetOutput().
164154
if s.vm.OutputWriter == os.Stdout {
165-
// OutputWriter is still the default (os.Stdout), so set up event emission
166-
outputBuffer := &bytes.Buffer{}
167-
s.outputWriter = NewEventEmittingWriter(outputBuffer, s.ctx)
168-
s.vm.OutputWriter = s.outputWriter
155+
s.outputBuffer = &bytes.Buffer{}
156+
s.vm.OutputWriter = s.outputBuffer
169157
}
170-
// else: OutputWriter was already configured (e.g., by API layer), leave it alone
171158

172159
// Load into debugger
173160
s.debugger.LoadSymbols(s.symbols)
@@ -590,15 +577,19 @@ func (s *DebuggerService) GetExitCode() int32 {
590577
}
591578

592579
// GetOutput returns captured program output (clears buffer)
580+
// Note: With the API server, output is broadcast via WebSocket events.
581+
// This method is primarily used by tests and direct service usage (not via API).
593582
func (s *DebuggerService) GetOutput() string {
594583
s.mu.Lock()
595584
defer s.mu.Unlock()
596585

597-
if s.outputWriter == nil {
586+
if s.outputBuffer == nil {
598587
return ""
599588
}
600589

601-
return s.outputWriter.GetBufferAndClear()
590+
output := s.outputBuffer.String()
591+
s.outputBuffer.Reset()
592+
return output
602593
}
603594

604595
// GetDisassembly returns disassembled instructions starting at address.

0 commit comments

Comments
 (0)