Skip to content

Commit f7b804c

Browse files
committed
✨ add workspace mode
1 parent d99c529 commit f7b804c

File tree

7 files changed

+234
-37
lines changed

7 files changed

+234
-37
lines changed
File renamed without changes.
File renamed without changes.

src/ASM/main.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as Diag from '../diagnose/main';
88
import * as conf from '../utils/configuration';
99
import { messageCollector } from '../diagnose/messageCollector';
1010
import { logger } from '../utils/logger';
11+
import { getFiles } from './util';
1112

1213
const fs = vscode.workspace.fs;
1314

@@ -279,7 +280,7 @@ export async function activate(context: vscode.ExtensionContext) {
279280
}
280281
logger.channel(
281282
logger.localize('diag.msg', diagnose.error.toString(), diagnose.warn.toString()),
282-
"\n\t" + result.replace(/\r/g, "").replace(/[\n]*/g, "\n\t")
283+
"\n\t" + result.replace(/\r/g, "").replace(/[\n]+/g, "\n\t")
283284
);
284285
}
285286

@@ -325,15 +326,16 @@ export async function activate(context: vscode.ExtensionContext) {
325326
if (workspaceFolder === undefined) {
326327
throw new Error("can't get current workspace of file:" + _uri.fsPath);
327328
}
328-
const rel = path.relative(workspaceFolder.uri.fsPath, _uri.fsPath);
329-
const fileInfo = path.parse(rel);
329+
const fileRel = path.relative(workspaceFolder.uri.fsPath, _uri.fsPath);
330+
const fileInfo = path.parse(fileRel);
330331
const folder = vscode.Uri.joinPath(_uri, "..");
331332

332333
if (conf.extConf.emulator === conf.DosEmulatorType.dosbox || conf.extConf.emulator === conf.DosEmulatorType.dosboxX) {
333334
const autoexec = [
334335
`mount c "${assemblyToolsFolder.fsPath}""`,
335336
`mount d "${workspaceFolder.uri.fsPath}""`,
336337
'd:',
338+
`cd ${fileInfo.dir}`,
337339
...action.before
338340
];
339341
const logUri = vscode.Uri.joinPath(assemblyToolsFolder, logFilename);
@@ -342,8 +344,8 @@ export async function activate(context: vscode.ExtensionContext) {
342344
}
343345
function cb(val: string) {
344346
const r = val
345-
.replace("${file}", path.resolve(fileInfo.dir, fileInfo.base))
346-
.replace("${filename}", path.resolve(fileInfo.dir, fileInfo.name));
347+
.replace("${file}", fileInfo.base)
348+
.replace("${filename}", fileInfo.name);
347349
if (val.startsWith('>')) {
348350
return r.replace(">", "");
349351
}
@@ -423,11 +425,18 @@ export async function activate(context: vscode.ExtensionContext) {
423425

424426
if (conf.extConf.emulator === conf.DosEmulatorType.jsdos) {
425427
await api.jsdos.jszip.loadAsync(bundle);
426-
api.jsdos.jszip.file('code/' + fileInfo.base, doc.getText());
428+
for await (const f of getFiles(workspaceFolder.uri.fsPath)) {
429+
const rel = path.relative(workspaceFolder.uri.fsPath, f);
430+
const dst = path.posix.join('code/', rel);
431+
const _data = await fs.readFile(vscode.Uri.file(f));
432+
const fileContent = new TextDecoder().decode(_data);
433+
api.jsdos.jszip.file(dst, fileContent);
434+
}
427435
const autoexec = [
428436
`mount c .`,
429437
`mount d ./code`,
430438
'd:',
439+
`cd ${fileInfo.dir}`,
431440
...action.before
432441
];
433442
function cb(val: string) {
@@ -518,7 +527,7 @@ export async function activate(context: vscode.ExtensionContext) {
518527
}
519528
logger.channel(
520529
logger.localize('diag.msg', diagnose.error.toString(), diagnose.warn.toString()),
521-
"\n\t" + result.replace(/\r/g, "").replace(/[\n]*/g, "\n\t")
530+
"\n\t" + result.replace(/\r/g, "").replace(/[\n]+/g, "\n\t")
522531
);
523532
}
524533

@@ -542,8 +551,6 @@ export async function activate(context: vscode.ExtensionContext) {
542551
break;
543552
}
544553

545-
546-
547554
context.subscriptions.push(
548555
vscode.commands.registerCommand('masm-tasm.openEmulator', (uri: vscode.Uri) => workingMode(conf.actionType.open, uri)),
549556
vscode.commands.registerCommand('masm-tasm.runASM', (uri: vscode.Uri) => workingMode(conf.actionType.run, uri)),

src/ASM/util.ts

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,14 @@
1-
import { FileType } from 'vscode';
1+
import * as nodefs from 'fs';
2+
import * as path from 'path';
23

3-
/**check whether the entry is in directory or not
4-
* @param dirinfo the entris of one directory
5-
* @param entry the entry to find
6-
* @param ignoreCase ignore Case or not,default is true in win32 and false for other
7-
*/
8-
export function inDirectory(dirinfo: [string, FileType][], entry: [string, FileType], ignoreCase: boolean = process.platform === "win32"): [string, FileType] | undefined {
9-
for (const d of dirinfo) {
10-
const filecheck = ignoreCase ? d[0].toLowerCase() === entry[0].toLowerCase() : d[0] === entry[0];
11-
if (filecheck && d[1] === entry[1]) {
12-
return d;
4+
export async function* getFiles(dir: string): AsyncGenerator<string> {
5+
const dirents = await nodefs.promises.readdir(dir, { withFileTypes: true });
6+
for (const dirent of dirents) {
7+
const res = path.resolve(dir, dirent.name);
8+
if (dirent.isDirectory()) {
9+
yield* getFiles(res);
10+
} else {
11+
yield res;
1312
}
1413
}
15-
return;
16-
}
17-
18-
/**
19-
* make sure value in the list
20-
*/
21-
export function validfy<T>(value: T | undefined, list: T[]): T {
22-
for (const val of list) {
23-
if (value === val) {
24-
return value;
25-
}
26-
}
27-
return list[0];
2814
}

src/test/suite/ASM.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { DosEmulatorType, Assembler } from '../../utils/configuration';
1212

1313
const samplesUri = vscode.Uri.joinPath(vscode.Uri.file(__dirname), '../../../samples/');
1414

15-
suite('Extension Test Suite', function () {
15+
suite('single file mode Test Suite', function () {
1616
vscode.window.showInformationMessage('Start all tests.');
1717
const MASMorTASM = [
1818
Assembler['MASM-v5.00'],
@@ -62,6 +62,7 @@ function testAsmCode(file: string, shouldErr: number, emu: DosEmulatorType, asm:
6262

6363
//update settings
6464
await vscode.workspace.getConfiguration('masmtasm').update("dosbox.run", "exit");
65+
await vscode.workspace.getConfiguration('masmtasm').update("ASM.mode", "single file");
6566
await vscode.workspace.getConfiguration('masmtasm').update("ASM.emulator", emu);
6667
await vscode.workspace.getConfiguration('masmtasm').update("ASM.assembler", asm);
6768

src/test/suite/workspace.test.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
2+
import * as assert from 'assert';
3+
4+
// You can import and use all API from the 'vscode' module
5+
// as well as import your extension to test it
6+
import * as vscode from 'vscode';
7+
import { AsmResult } from '../../ASM/main';
8+
import { DIAGCODE } from '../../diagnose/main';
9+
import { DosEmulatorType, Assembler } from '../../utils/configuration';
10+
11+
// import * as myExtension from '../../extension';
12+
13+
const samplesUri = vscode.Uri.joinPath(vscode.Uri.file(__dirname), '../../../samples/');
14+
15+
suite('workspace mode Test Suite', function () {
16+
vscode.window.showInformationMessage('Start all tests.');
17+
const MASMorTASM = [
18+
Assembler['MASM-v5.00'],
19+
Assembler['MASM-v6.11'],
20+
Assembler.TASM,
21+
];
22+
const emulator: DosEmulatorType[] = [
23+
DosEmulatorType.dosbox,
24+
DosEmulatorType.dosboxX,
25+
DosEmulatorType.jsdos,
26+
];
27+
28+
const filelist: [string, number][] = [
29+
['1.asm', 0],
30+
// ['3中文路径hasError.asm', 1],
31+
['multi/2.asm', 0],
32+
];
33+
34+
const args: [string, DIAGCODE, DosEmulatorType, Assembler][] = [];
35+
for (const file of filelist) {
36+
for (const emu of emulator) {
37+
for (const asm of MASMorTASM) {
38+
args.push([file[0], file[1], emu, asm]);
39+
}
40+
}
41+
}
42+
43+
this.beforeEach(async function () {
44+
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
45+
});
46+
47+
shuffle(args).forEach((val) => { testAsmCode(...val); });
48+
});
49+
50+
function testAsmCode(file: string, shouldErr: number, emu: DosEmulatorType, asm: Assembler): void {
51+
test(`test file ${file} in ${emu} use ${asm} want should ${shouldErr} error`,
52+
async function () {
53+
this.timeout('60s');
54+
this.slow('20s');
55+
//skip azure pipeline test for this condition
56+
if (file === '3中文路径hasError.asm' && emu === DosEmulatorType.msdos && asm === Assembler.MASM && !process.env.LANG?.includes('zh_CN')) {
57+
this.skip();
58+
}
59+
60+
//open test file. NOTE: the extension will be activated when open .asm file
61+
const samplefile = vscode.Uri.joinPath(samplesUri, file);
62+
63+
//update settings
64+
await vscode.workspace.getConfiguration('masmtasm').update("dosbox.run", "exit");
65+
await vscode.workspace.getConfiguration('masmtasm').update("ASM.mode", "workspace");
66+
await vscode.workspace.getConfiguration('masmtasm').update("ASM.emulator", emu);
67+
await vscode.workspace.getConfiguration('masmtasm').update("ASM.assembler", asm);
68+
69+
//assert the extension activated and command contributed
70+
const vscodecmds = await vscode.commands.getCommands(true);
71+
const cmd = 'masm-tasm.runASM';
72+
if (!vscodecmds.includes(cmd)) {
73+
await vscode.extensions.getExtension('xsro.masm-tasm')?.activate();
74+
}
75+
const vscodecmds2 = await vscode.commands.getCommands(true);
76+
assert.ok(vscodecmds2.includes(cmd));
77+
78+
//assert message processed
79+
const _result = await vscode.commands.executeCommand(cmd, samplefile);
80+
const { message, error } = _result as AsmResult;
81+
assert.strictEqual(error, shouldErr, message);
82+
});
83+
}
84+
85+
function shuffle<T>(arr: T[]): T[] {
86+
for (let i = 1; i < arr.length; i++) {
87+
const random = Math.floor(Math.random() * (i + 1));
88+
[arr[i], arr[random]] = [arr[random], arr[i]];
89+
}
90+
return arr;
91+
}

src/web/ASM.ts

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as Diag from '../diagnose/main';
77
import * as conf from '../utils/configuration';
88
import { messageCollector } from '../diagnose/messageCollector';
99
import { logger } from '../utils/logger';
10+
import { getFiles } from '../ASM/util';
1011

1112
const fs = vscode.workspace.fs;
1213

@@ -117,9 +118,120 @@ export async function activate(context: vscode.ExtensionContext) {
117118
};
118119
}
119120

121+
async function workspaceMode(act: conf.actionType, _uri: vscode.Uri): Promise<AsmResult> {
122+
logger.channel(actionMessage(act, _uri.fsPath));
123+
124+
const extConfig = vscode.workspace.getConfiguration('masmtasm');
125+
126+
const actions: ACTIONS | undefined = extConfig.get('ASM.actions');
127+
if (actions === undefined) {
128+
throw new Error("configurate `masmtasm.ASM.actions` first");
129+
}
130+
const action = actions[conf.extConf.asmType];
131+
132+
const doc = await vscode.workspace.openTextDocument(_uri);
133+
if (doc.isDirty && extConfig.get('ASM.savefirst')) {
134+
await doc.save();
135+
}
136+
137+
const bundlePath = vscode.Uri.joinPath(
138+
context.extensionUri,
139+
action["baseBundle"].replace('<built-in>/', "resources/")
140+
);
141+
const bundle = await fs.readFile(bundlePath);
142+
143+
let result = "<should-not-return>";
144+
const workspaceFolder = vscode.workspace.workspaceFolders?.find(val => {
145+
const r = path.relative(val.uri.fsPath, _uri.fsPath);
146+
return !r.startsWith("..");
147+
});
148+
if (workspaceFolder === undefined) {
149+
throw new Error("can't get current workspace of file:" + _uri.fsPath);
150+
}
151+
const fileRel = path.relative(workspaceFolder.uri.fsPath, _uri.fsPath);
152+
const fileInfo = path.parse(fileRel);
153+
154+
if (conf.extConf.emulator === conf.DosEmulatorType.jsdos) {
155+
await api.jsdos.jszip.loadAsync(bundle);
156+
for await (const f of getFiles(workspaceFolder.uri.fsPath)) {
157+
const rel = path.relative(workspaceFolder.uri.fsPath, f);
158+
const dst = path.posix.join('code/', rel);
159+
const _data = await fs.readFile(vscode.Uri.file(f));
160+
const fileContent = new TextDecoder().decode(_data);
161+
api.jsdos.jszip.file(dst, fileContent);
162+
}
163+
const autoexec = [
164+
`mount c .`,
165+
`mount d ./code`,
166+
'd:',
167+
`cd ${fileInfo.dir}`,
168+
...action.before
169+
];
170+
function cb(val: string) {
171+
const r = val
172+
.replace("${file}", fileInfo.base)
173+
.replace("${filename}", fileInfo.name);
174+
if (val.startsWith('>')) {
175+
return r.replace(">", "");
176+
}
177+
return r;
178+
}
179+
if (act === conf.actionType.run) {
180+
autoexec.push(...action.run.map(cb));
181+
}
182+
if (act === conf.actionType.debug) {
183+
autoexec.push(...action.debug.map(cb));
184+
}
185+
api.jsdos.updateAutoexec(autoexec);
186+
const webview = await api.jsdos.runInWebview();
187+
if (act !== conf.actionType.open) {
188+
const [hook, promise] = messageCollector();
189+
webview.onDidReceiveMessage(e => {
190+
switch (e.command) {
191+
case 'stdout':
192+
hook(e.value);
193+
break;
194+
}
195+
});
196+
result = await promise;
197+
}
198+
}
199+
200+
const diagnose = diag.process(result, doc, conf.extConf.asmType);
201+
if (diagnose) {
202+
if (diagnose?.error > 0) {
203+
vscode.window.showErrorMessage(logger.localize("ASM.error"));
204+
logger.outputChannel.show();
205+
}
206+
logger.channel(
207+
logger.localize('diag.msg', diagnose.error.toString(), diagnose.warn.toString()),
208+
"\n\t" + result.replace(/\r/g, "").replace(/[\n]+/g, "\n\t")
209+
);
210+
}
211+
212+
return {
213+
message: result,
214+
error: diagnose?.error,
215+
warn: diagnose?.warn
216+
};
217+
}
218+
219+
const mode = vscode.workspace.getConfiguration('masmtasm').get('ASM.mode');
220+
let workingMode = singleFileMode;
221+
switch (mode) {
222+
case "workspace":
223+
workingMode = workspaceMode;
224+
break;
225+
case "single file":
226+
workingMode = singleFileMode;
227+
const msg = logger.localize("ASM.singleFileMode", "no folder in web extension");
228+
logger.channel(msg);
229+
break;
230+
}
231+
120232
context.subscriptions.push(
121-
vscode.commands.registerCommand('masm-tasm.openEmulator', (uri: vscode.Uri) => singleFileMode(actionType.open, uri)),
122-
vscode.commands.registerCommand('masm-tasm.runASM', (uri: vscode.Uri) => singleFileMode(actionType.run, uri)),
123-
vscode.commands.registerCommand('masm-tasm.debugASM', (uri: vscode.Uri) => singleFileMode(actionType.debug, uri))
233+
vscode.commands.registerCommand('masm-tasm.openEmulator', (uri: vscode.Uri) => workingMode(actionType.open, uri)),
234+
vscode.commands.registerCommand('masm-tasm.runASM', (uri: vscode.Uri) => workingMode(actionType.run, uri)),
235+
vscode.commands.registerCommand('masm-tasm.debugASM', (uri: vscode.Uri) => workingMode(actionType.debug, uri))
124236
);
125237
}

0 commit comments

Comments
 (0)