Skip to content

Commit 82d8e9b

Browse files
committed
feat: Integrate c64u machine into c64u tree explorer
1 parent e830ff4 commit 82d8e9b

File tree

6 files changed

+149
-23
lines changed

6 files changed

+149
-23
lines changed

CHANGELOG.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,32 @@
22

33
All notable changes to the "c64-vscode" extension will be documented in this file.
44

5-
## [Unreleased]
5+
## [0.5.3] - 2026-02-18
6+
7+
### Added
8+
9+
- **Machine Control in Tree View** — Machine section as a root node in the C64 Ultimate Tree View with directly clickable actions: Reset, Reboot, Pause, Resume, Power Off — no QuickPick menu required.
10+
- **Compile & Run button in Tree View title bar**`$(cloud-upload)` button for Assemble, Upload and Run directly from the C64 Ultimate panel.
11+
- **Unmount Disk Image** — Renamed from "Unmount Drive" for clarity.
12+
- **Updated kickass_ls** — Bundles the latest version of the kickass_ls language server.
13+
14+
### Changed
15+
16+
- C64 Ultimate Tree View now has two root sections: **Machine** (with control actions) and **File System** (existing file browser).
17+
18+
## [0.5.2] - 2026-02-18
619

720
### Added
821

922
- **Language Server Settings UI** — All kickass_ls diagnostics and formatting options are now configurable via VS Code settings (search for "kickass_ls"). Changes take effect immediately without reload.
1023
- **GitHub Actions Release Workflow** — Automatically builds platform-specific VSIX files when a version tag is pushed.
24+
- **C64U toggle** — All C64 Ultimate commands, keybindings, Tree View and Activity Bar icon are now toggleable via the `c64u.enabled` setting (default: false).
25+
- **`.kasm` file extension** — Kick Assembler-specific extension to avoid conflicts with other assembler extensions (e.g. HLASM).
26+
27+
### Fixed
28+
29+
- **Extension activation** — Fixed VSIX packaging issue where `vscode-languageclient` dependency was excluded, causing the extension to silently fail to activate.
30+
- **Language Server activation** — Added pattern-based document selectors (`**/*.asm`, `**/*.kasm`) to ensure the language server activates even when another extension claims the `.asm` file association.
1131

1232
## [0.3.0] - 2026-02-07
1333

README.md

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,16 @@ All syntax highlighting and code analysis comes from the **kickass_ls** language
3131

3232
Full integration with C64 Ultimate hardware via the `c64u` CLI tool:
3333

34-
- **Tree View File Explorer** in the Activity Bar with drag-and-drop support
34+
- **Tree View** in the Activity Bar with two sections:
35+
- **Machine** — directly clickable Reset, Reboot, Pause, Resume, Power Off actions
36+
- **File System** — full file browser with drag-and-drop support
3537
- Open text files (`.asm`, `.bas`, `.seq`, `.txt`, `.cfg`, `.inc`, `.sym`, `.dbg`) directly in the editor — changes are automatically uploaded back to the C64 Ultimate on save
3638
- Open binary files (`.prg`, `.crt`, `.bin`, `.tap`, `.t64`, `.rel`, `.ko`) in the Hex Editor
3739
- Browse and navigate the C64 Ultimate filesystem
3840
- Upload, download, rename, copy, and delete files
3941
- Create directories and disk images (d64, d71, d81, g64, dnp)
4042
- Mount/unmount disk images on IEC drives
4143
- Run `.prg` files directly on hardware
42-
- Machine control (reset, reboot, pause, resume)
4344
- Interactive QuickPick-based file browser
4445

4546
## Prerequisites
@@ -195,13 +196,14 @@ If another extension claims the `.asm` file association, the language server sti
195196

196197
### C64 Ultimate Workflow
197198

198-
1. Enable C64 Ultimate in settings and configure host/port
199-
2. Use `Ctrl+Shift+U` to assemble, upload, and run on real hardware
200-
3. Use the Tree View in the Activity Bar to browse files on the C64 Ultimate
201-
4. Click text files to edit them — changes are automatically uploaded on save
202-
5. Click binary files to view them in the Hex Editor
203-
6. Right-click for context actions (rename, copy, delete, mount, run)
204-
7. Drag and drop files to move them between directories
199+
1. Enable C64 Ultimate in settings (`c64u.enabled`) and configure host/port
200+
2. Use `Ctrl+Shift+U` or the `$(cloud-upload)` button in the Tree View title bar to assemble, upload, and run on real hardware
201+
3. Use the **Machine** section in the Tree View to reset, reboot, pause or power off the C64 directly
202+
4. Use the **File System** section to browse files on the C64 Ultimate
203+
5. Click text files to edit them — changes are automatically uploaded on save
204+
6. Click binary files to view them in the Hex Editor
205+
7. Right-click for context actions (rename, copy, delete, mount, run)
206+
8. Drag and drop files to move them between directories
205207

206208
## Commands
207209

@@ -230,11 +232,21 @@ Access via Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`):
230232

231233
- **Open in Editor** — Open text/binary files in appropriate editor
232234
- **Run Program** — Run `.prg` files on C64 Ultimate
233-
- **Mount/Unmount** — Mount disk images on IEC drives
235+
- **Mount / Unmount Disk Image** — Mount disk images on IEC drives
234236
- **Download/Upload** — Transfer files to/from local machine
235237
- **Rename/Copy/Delete** — File management
236238
- **New Directory / Create Disk Image** — Create new items
237239

240+
### Tree View Machine Section
241+
242+
Click directly to execute without confirmation dialog:
243+
244+
- **Reset** — Soft reset the C64
245+
- **Reboot** — Full reboot
246+
- **Pause** — Pause the machine
247+
- **Resume** — Resume from pause
248+
- **Power Off** — Power off the C64 Ultimate
249+
238250
## Building with Bundled Binaries
239251

240252
To build the extension with bundled Go binaries:

package.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "c64-vscode",
33
"displayName": "C64 Assembler Development",
44
"description": "Complete C64 development environment with Kick Assembler, LSP support, VICE emulator, and C64 Ultimate integration",
5-
"version": "0.5.2",
5+
"version": "0.5.3",
66
"publisher": "cybersorcerer",
77
"license": "Apache-2.0",
88
"repository": {
@@ -201,7 +201,7 @@
201201
},
202202
{
203203
"command": "c64u.treeview.unmount",
204-
"title": "Unmount Drive",
204+
"title": "Unmount Disk Image",
205205
"icon": "$(debug-disconnect)"
206206
},
207207
{
@@ -219,6 +219,11 @@
219219
"title": "Run Program",
220220
"icon": "$(play)"
221221
},
222+
{
223+
"command": "c64u.treeview.machine",
224+
"title": "Machine Control",
225+
"icon": "$(vm)"
226+
},
222227
{
223228
"command": "c64u.treeview.openFile",
224229
"title": "Open in Editor",
@@ -555,6 +560,10 @@
555560
{
556561
"command": "c64u.treeview.openFile",
557562
"when": "false"
563+
},
564+
{
565+
"command": "c64u.treeview.machine",
566+
"when": "false"
558567
}
559568
],
560569
"view/title": [
@@ -563,6 +572,11 @@
563572
"when": "view == c64u.fileExplorer",
564573
"group": "navigation"
565574
},
575+
{
576+
"command": "c64u.uploadAndRun",
577+
"when": "view == c64u.fileExplorer",
578+
"group": "navigation"
579+
},
566580
{
567581
"command": "c64u.treeview.upload",
568582
"when": "view == c64u.fileExplorer",

src/c64u/service.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ export class C64UService {
4141
await this.fileBrowserProvider.show();
4242
}
4343

44+
async executeMachineAction(action: string): Promise<void> {
45+
const result = await executeC64U(['machine', action]);
46+
if (result.success) {
47+
vscode.window.showInformationMessage(`Machine ${action} executed`);
48+
} else {
49+
vscode.window.showErrorMessage(`Machine control failed: ${result.error}`);
50+
}
51+
}
52+
4453
async showMachineControl(): Promise<void> {
4554
const actions = [
4655
{ label: '$(debug-restart) Reset', value: 'reset' },

src/c64u/treeview.ts

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ import * as path from 'path';
33
import { C64UClient } from './client';
44
import { C64UFileOpenManager } from './file-open-manager';
55

6+
// Machine control actions shown as direct tree items
7+
const MACHINE_ACTIONS: { label: string; action: string; icon: string; description: string }[] = [
8+
{ label: 'Reset', action: 'reset', icon: 'debug-restart', description: 'Soft reset' },
9+
{ label: 'Reboot', action: 'reboot', icon: 'refresh', description: 'Full reboot' },
10+
{ label: 'Pause', action: 'pause', icon: 'debug-pause', description: 'Pause machine' },
11+
{ label: 'Resume', action: 'resume', icon: 'debug-continue', description: 'Resume machine' },
12+
{ label: 'Power Off', action: 'poweroff', icon: 'circle-slash', description: 'Power off' },
13+
];
14+
615
export class C64UFileSystemProvider implements vscode.TreeDataProvider<C64UTreeItem>, vscode.TreeDragAndDropController<C64UTreeItem> {
716
private _onDidChangeTreeData: vscode.EventEmitter<C64UTreeItem | undefined | null | void> = new vscode.EventEmitter<C64UTreeItem | undefined | null | void>();
817
readonly onDidChangeTreeData: vscode.Event<C64UTreeItem | undefined | null | void> = this._onDidChangeTreeData.event;
@@ -41,14 +50,36 @@ export class C64UFileSystemProvider implements vscode.TreeDataProvider<C64UTreeI
4150
)];
4251
}
4352

53+
// Root level: show Machine section and File System section
54+
if (!element) {
55+
return [
56+
new C64UTreeItem('Machine', vscode.TreeItemCollapsibleState.Expanded, 'machine-root', '__machine__'),
57+
new C64UTreeItem('File System', vscode.TreeItemCollapsibleState.Expanded, 'filesystem-root', '/'),
58+
];
59+
}
60+
61+
// Machine section children: individual machine actions
62+
if (element.itemType === 'machine-root') {
63+
return MACHINE_ACTIONS.map(a => new C64UTreeItem(
64+
a.label,
65+
vscode.TreeItemCollapsibleState.None,
66+
'machine-action',
67+
`__machine__/${a.action}`,
68+
undefined,
69+
a.icon,
70+
a.description
71+
));
72+
}
73+
74+
// File System section children: existing file browsing logic
4475
try {
45-
const targetPath = element ? element.resourcePath : '/';
76+
const targetPath = element.itemType === 'filesystem-root' ? '/' : element.resourcePath;
4677
console.log(`[C64U TreeView] Loading children for: ${targetPath}`);
4778
const files = await this.client.listFiles(targetPath);
4879

4980
// Add parent directory entry if not at root
5081
const items: C64UTreeItem[] = [];
51-
if (targetPath !== '/' && !element) {
82+
if (targetPath !== '/') {
5283
const parentPath = targetPath.substring(0, targetPath.lastIndexOf('/')) || '/';
5384
items.push(new C64UTreeItem(
5485
'..',
@@ -90,7 +121,7 @@ export class C64UFileSystemProvider implements vscode.TreeDataProvider<C64UTreeI
90121
}
91122

92123
// If directory is empty, show a friendly message
93-
if (items.length === 0 && targetPath !== '/') {
124+
if (items.length === 0) {
94125
console.log(`[C64U TreeView] Directory ${targetPath} is empty`);
95126
return [new C64UTreeItem(
96127
'Empty directory',
@@ -196,7 +227,8 @@ export class C64UFileSystemProvider implements vscode.TreeDataProvider<C64UTreeI
196227
// Move each dragged item
197228
for (const item of draggedItems) {
198229
// Skip special items
199-
if (item.itemType === 'parent' || item.itemType === 'message' || item.itemType === 'error') {
230+
if (item.itemType === 'parent' || item.itemType === 'message' || item.itemType === 'error' ||
231+
item.itemType === 'machine-root' || item.itemType === 'machine-action' || item.itemType === 'filesystem-root') {
200232
continue;
201233
}
202234

@@ -293,22 +325,34 @@ export class C64UFileSystemProvider implements vscode.TreeDataProvider<C64UTreeI
293325
}
294326
}
295327

296-
type C64UItemType = 'directory' | 'diskimage' | 'diskimage-gcr' | 'program' | 'sid' | 'cartridge' | 'textfile' | 'binaryfile' | 'file' | 'parent' | 'message' | 'error';
328+
type C64UItemType = 'directory' | 'diskimage' | 'diskimage-gcr' | 'program' | 'sid' | 'cartridge' | 'textfile' | 'binaryfile' | 'file' | 'parent' | 'message' | 'error' | 'machine-root' | 'machine-action' | 'filesystem-root';
297329

298330
export class C64UTreeItem extends vscode.TreeItem {
299331
constructor(
300332
public readonly label: string,
301333
public readonly collapsibleState: vscode.TreeItemCollapsibleState,
302334
public readonly itemType: C64UItemType,
303335
public readonly resourcePath: string,
304-
public readonly fileSize?: number
336+
public readonly fileSize?: number,
337+
customIcon?: string,
338+
description?: string
305339
) {
306340
super(label, collapsibleState);
307341

308342
this.contextValue = itemType;
309343
this.tooltip = this.buildTooltip();
310-
this.iconPath = this.getIcon();
311-
this.description = this.getDescription();
344+
this.iconPath = customIcon ? new vscode.ThemeIcon(customIcon) : this.getIcon();
345+
this.description = description ?? this.getDescription();
346+
347+
// Machine actions execute on click
348+
if (itemType === 'machine-action') {
349+
const action = resourcePath.replace('__machine__/', '');
350+
this.command = {
351+
command: 'c64u.treeview.machine',
352+
title: label,
353+
arguments: [action]
354+
};
355+
}
312356

313357
// Make clickable items that navigate
314358
if (itemType === 'directory' || itemType === 'parent') {
@@ -317,7 +361,10 @@ export class C64UTreeItem extends vscode.TreeItem {
317361
title: 'Navigate',
318362
arguments: [this]
319363
};
320-
} else if (C64UFileOpenManager.isOpenableFile(label)) {
364+
} else if (itemType === 'filesystem-root') {
365+
// File System root navigates to /
366+
this.command = undefined;
367+
} else if (C64UFileOpenManager.isOpenableFile(label) && itemType !== 'machine-action') {
321368
this.command = {
322369
command: 'c64u.treeview.openFile',
323370
title: 'Open File',
@@ -330,6 +377,15 @@ export class C64UTreeItem extends vscode.TreeItem {
330377
if (this.itemType === 'message' || this.itemType === 'error') {
331378
return this.label;
332379
}
380+
if (this.itemType === 'machine-root') {
381+
return 'C64 Ultimate Machine Control';
382+
}
383+
if (this.itemType === 'machine-action') {
384+
return `Execute: ${this.label}`;
385+
}
386+
if (this.itemType === 'filesystem-root') {
387+
return 'C64 Ultimate File System';
388+
}
333389

334390
let tooltip = `Path: ${this.resourcePath}`;
335391
if (this.fileSize !== undefined) {
@@ -341,6 +397,12 @@ export class C64UTreeItem extends vscode.TreeItem {
341397

342398
private getIcon(): vscode.ThemeIcon {
343399
switch (this.itemType) {
400+
case 'machine-root':
401+
return new vscode.ThemeIcon('vm');
402+
case 'machine-action':
403+
return new vscode.ThemeIcon('gear');
404+
case 'filesystem-root':
405+
return new vscode.ThemeIcon('server');
344406
case 'directory':
345407
return new vscode.ThemeIcon('folder');
346408
case 'parent':

src/extension.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ export function activate(context: vscode.ExtensionContext) {
136136
})
137137
);
138138

139+
context.subscriptions.push(
140+
vscode.commands.registerCommand('c64u.treeview.machine', async (action: string) => {
141+
await c64uService!.executeMachineAction(action);
142+
})
143+
);
144+
139145
// Start Language Server first
140146
startLanguageServer(context);
141147

@@ -313,7 +319,10 @@ function startLanguageServer(context: vscode.ExtensionContext) {
313319
},
314320
initializationOptions: {
315321
settings: { kickass_ls: getKickassLsSettings() }
316-
}
322+
},
323+
outputChannelName: 'Kick Assembler Language Server',
324+
revealOutputChannelOn: 1, // RevealOutputChannelOn.Info
325+
traceOutputChannel: vscode.window.createOutputChannel('Kick Assembler Language Server (Trace)')
317326
};
318327

319328
// Create and start the language client

0 commit comments

Comments
 (0)