Skip to content

Commit

Permalink
Multisplit and token support for typing chunked text from file.
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanbeattie committed Mar 23, 2024
1 parent 63f1490 commit c77dd9f
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 45 deletions.
40 changes: 10 additions & 30 deletions src/instruction-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
getDelay,
readFileAsync,
getRandomness,
readChunks
} from './utils';
import { setAwaiter } from './wait-for-input';

Expand Down Expand Up @@ -56,39 +57,18 @@ export const typeChunksFromFile = async (
const workspaceFolder = workspace.workspaceFolders[0].uri.fsPath;
const path = join(workspaceFolder, '.presentation-buddy', instruction.path);
const text = await readFileAsync(path);
const waitInsteadOf = instruction.waitInsteadOf || ["/*WAIT*/"];
const waitAfter = instruction.waitAfter || ["\n" ]
const skipChunksContaining = instruction.skipChunksContaining || ["/*SKIP*/"];
var chunks = [ text ];
for(var token of waitAfter) {
chunks = chunks
.map(chunk => chunk.split(token).map(chunk => chunk ? chunk : token))
.flat();
}
for(var token of waitInsteadOf) {
chunks = chunks
.map(chunk => chunk.split(token))
.flat();
}

function keep(chunk: string): boolean { return !skipChunksContaining.some(t => chunk.includes(t)) };

chunks = chunks.filter(chunk => keep(chunk));

const consumeTokens = instruction.waitInsteadOf || ["/*WAIT*/"];
const preserveTokens = instruction.waitAfter || ["\n"];
const skipTokens = instruction.skipLinesContaining || ["/*SKIP*/"];
var chunks = readChunks(text, consumeTokens, preserveTokens, skipTokens);
for (const chunk of chunks) {
await typeTextIntoActiveTextEditor(Array.from(chunk), instruction.delay);
if (chunk.endsWith('\n')) await command({
type: "command",
command: "cursorHome",
args: [],
repeat: 1
});
await wait({
delay: "manual",
type: 'wait'
});
if (chunk.endsWith('\n')) {
await command({ type: "command", command: "cursorHome", args: [], repeat: 1 });
}
await wait({ delay: "manual", type: 'wait' });
}
}
};

export const typeText = async (instruction: TypeText): Promise<void> => {
const data = Array.from(instruction.text.join('\n'));
Expand Down
2 changes: 1 addition & 1 deletion src/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export type TypeChunksFromFile = {
delay?: number;
waitInsteadOf: string[];
waitAfter: string[];
skipChunksContaining: string[];
skipLinesContaining: string[];
};

export type OpenFile = { type: "openFile"; path: string };
Expand Down
88 changes: 83 additions & 5 deletions src/test/extension.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,93 @@
import * as assert from 'assert';
import { splat, readChunks } from '../utils';

// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
// import * as myExtension from '../../extension';

suite('Extension Test Suite', () => {
vscode.window.showInformationMessage('Start all tests.');
vscode.window.showInformationMessage('Start all tests.');

test('Sample test', () => {
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
});
test('Sample test', () => {
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
});
});

const empty = {
text: "",
consumeTokens: [],
preserveTokens: [],
skipTokens: [],
expected: []
};
let inputs = [
{ ...empty },
{ ...empty, text: "baba", expected: ["baba"] },
{ ...empty, text: "baba", consumeTokens: ["a"], expected: ["b", "b"] },
{ ...empty, text: "banana", consumeTokens: ["b", "n"], expected: ["a", "a", "a"] },
{ ...empty, text: "banana", preserveTokens: ["a"], expected: ["ba", "na", "na"] },
{
...empty,
text: "var x = sqrt(5);",
preserveTokens: [" = ", "("],
expected: ["var x = ", "sqrt(", "5);"]
},
{
...empty,
text: "var x = sqrt(5);\r\nvar y = Console.ReadLine();\r\nConsole.WriteLine(x + y);",
preserveTokens: ["\n", " = ", "("],
expected: [
"var x = ",
"sqrt(",
"5);\n",
"var y = ",
"Console.ReadLine(", ");\n",
"Console.WriteLine(", "x + y);"
]
},
{
...empty,
text: `a,b
c
SKIPd,e,f
SKIPg
h,i,j
`,
preserveTokens: [ "\n" ],
consumeTokens: [","],
skipTokens: ["SKIP"],
expected: ["a", "b\n", "c\n", "h", "i", "j\n", "\n"]
},
{
...empty,
text: `using System.Mail; /*SKIP*/
/*SKIP*/
var x = sqrt(5); /*SKIP*/
var y = Console.ReadLine();
Console.WriteLine(x + y);
var z = 25;
`,
preserveTokens: ["\n", " = ", "("],
skipTokens: [ "/*SKIP*/" ],
expected: [
"var y = ",
"Console.ReadLine(", ");\n",
"Console.WriteLine(", "x + y);\n",
"var z = ",
"25;\n",
"\n"
]
},
];
suite('Chunk parsing tests', () => {
inputs.forEach((input) => {
test(`${input.text} / ${input.consumeTokens} / ${input.preserveTokens} / ${input.skipTokens}`, () => {
let chunks = readChunks(input.text, input.consumeTokens, input.preserveTokens, input.skipTokens);
assert.deepEqual(chunks, input.expected);
});
});
});
42 changes: 33 additions & 9 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,40 @@ const mkdirAsync = async (path: string): Promise<void> => {
console.log(err);
}
};

export function multiSplit(text: string, tokens: string[]): string[] {
if (tokens.length) {
tokens.sort((a, b) => b.length - a.length);
let token = tokens[0];
for (var i = 1; i < tokens.length; i++) {
text = text.split(tokens[i]).join(token);
export function* splat(text: string, token: string) {
let i = 0;
let candidate = "";
while (i++ < text.length) {
candidate = text.substring(0, i);
if (candidate.endsWith(token)) {
yield candidate;
candidate = "";
text = text.substring(i);
i = 0;
}
return text.split(token);
}
return [text];
if (candidate) { yield candidate };
}
export function readChunks(
text: string,
consumeTokens: string[] = [],
preserveTokens: string[] = [],
skipTokens: string[] = []
): string[] {

let result = [ text
.split(/\r?\n/)
.filter(line => !skipTokens.some(skip => line.includes(skip)))
.join('\n') ];

for (var token of consumeTokens) {
result = result.map(r => r.split(token)).flat();
}
for (var token of preserveTokens) {
result = result.map(r => [...splat(r, token)]).flat();
}
let keep = (s: string) => (s !== "" && (!skipTokens.some(t => s.includes(t))));
return result.filter(t => keep(t));
}

export async function mkdirIfNotExists(dir: string) {
Expand Down Expand Up @@ -99,3 +122,4 @@ export function getRandomness() {

return pause || 0;
}

0 comments on commit c77dd9f

Please sign in to comment.