diff --git a/changelog/index.html b/changelog/index.html
index 4637f46..414aaaa 100644
--- a/changelog/index.html
+++ b/changelog/index.html
@@ -1,5 +1,5 @@
-
+
@@ -362,6 +362,7 @@
- Vastly improved name handling in Chrome. (Missing in Firefox)
+ - Support
[a:z]
character batches
Version 4.1 September 21, 2019
diff --git a/lib/batches.ts b/lib/batches.ts
index 85c99e2..ddd9726 100644
--- a/lib/batches.ts
+++ b/lib/batches.ts
@@ -93,6 +93,60 @@ class Numeral implements Generator {
}
}
+class Character implements Generator {
+ public readonly start: number;
+
+ public readonly stop: number;
+
+ public readonly step: number;
+
+ public readonly length: number;
+
+ public readonly preview: string;
+
+ constructor(str: string) {
+ const rawpieces = str.split(":").map(e => e.trim());
+ const pieces = rawpieces.map((e, i) => {
+ if (i === 2) {
+ return reallyParseInt(e);
+ }
+ if (e.length > 1) {
+ throw new Error("Malformed Character sequence");
+ }
+ return e.charCodeAt(0);
+ });
+ if (pieces.length < 2) {
+ throw new Error("Invalid input");
+ }
+ const [start, stop, step] = pieces;
+ if (step === 0) {
+ throw new Error("Invalid step");
+ }
+ this.step = !step ? 1 : step;
+ const dir = this.step > 0;
+ if (dir && start > stop) {
+ throw new Error("Invalid sequence");
+ }
+ else if (!dir && start < stop) {
+ throw new Error("Invalid sequence");
+ }
+ this.start = start;
+ this.stop = stop;
+ this.length = Math.floor(
+ (this.stop - this.start + (dir ? 1 : -1)) / this.step);
+ this.preview = this[Symbol.iterator]().next().value as string;
+ Object.freeze(this);
+ }
+
+ *[Symbol.iterator]() {
+ const {start, stop, step} = this;
+ const dir = step > 0;
+ for (let i = start; (dir ? i <= stop : i >= stop); i += step) {
+ yield String.fromCharCode(i);
+ }
+ }
+}
+
export class BatchGenerator implements Generator {
private readonly gens: Generator[];
@@ -120,9 +174,14 @@ export class BatchGenerator implements Generator {
try {
this.gens.push(new Numeral(tok));
}
- catch (ex) {
- this.gens.push(new Literal(`[${tok}]`));
- this.hasInvalid = true;
+ catch {
+ try {
+ this.gens.push(new Character(tok));
+ }
+ catch {
+ this.gens.push(new Literal(`[${tok}]`));
+ this.hasInvalid = true;
+ }
}
}
if (str) {
diff --git a/tests/test_batches.js b/tests/test_batches.js
index 92a6e9a..769c8ce 100644
--- a/tests/test_batches.js
+++ b/tests/test_batches.js
@@ -113,4 +113,29 @@ describe("BatchGenerator", function() {
expect(items[0]).to.equal(gen.preview);
expect(gen.hasInvalid).to.be.true;
});
+
+ it("characters", function() {
+ const gen = new BatchGenerator("abc[a:c].lol[1].b");
+ const items = Array.from(gen);
+ expect(items).to.deep.equal([
+ "abca.lol[1].b",
+ "abcb.lol[1].b",
+ "abcc.lol[1].b",
+ ]);
+ expect(items.length).to.equal(gen.length);
+ expect(items[0]).to.equal(gen.preview);
+ });
+
+ it("characters two", function() {
+ const gen = new BatchGenerator("abc[D:G].lol[1].b");
+ const items = Array.from(gen);
+ expect(items).to.deep.equal([
+ "abcD.lol[1].b",
+ "abcE.lol[1].b",
+ "abcF.lol[1].b",
+ "abcG.lol[1].b",
+ ]);
+ expect(items.length).to.equal(gen.length);
+ expect(items[0]).to.equal(gen.preview);
+ });
});