@zgeoff/format-codemod 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,4 +8,4 @@ export interface CLIArgs {
8
8
  readonly ignore: readonly string[];
9
9
  readonly inputs: readonly string[];
10
10
  }
11
- export declare function parseCLIArgs(argv: readonly string[]): CLIArgs | string;
11
+ export declare function parseCLIArgs(argv: readonly string[]): Promise<CLIArgs | string>;
package/dist/cli.js CHANGED
@@ -62,35 +62,43 @@ function loadFormatIgnore(dir) {
62
62
  }
63
63
 
64
64
  // src/cli/parse-cli-args.ts
65
- import { parseArgs } from "node:util";
66
- function parseCLIArgs(argv) {
65
+ import { cli } from "gunshi/bone";
66
+ import { define } from "gunshi/definition";
67
+ var CLI_ARGS = {
68
+ check: { type: "boolean", default: false },
69
+ dry: { type: "boolean", default: false },
70
+ bench: { type: "boolean", default: false },
71
+ quiet: { type: "boolean", default: false },
72
+ version: { type: "boolean", default: false },
73
+ help: { type: "boolean", default: false },
74
+ ignore: { type: "string", multiple: true }
75
+ };
76
+ async function parseCLIArgs(argv) {
77
+ let parsed = null;
78
+ const command = define({
79
+ name: "format-codemod",
80
+ args: CLI_ARGS,
81
+ run: (ctx) => {
82
+ if (ctx.validationError !== undefined) {
83
+ throw ctx.validationError;
84
+ }
85
+ parsed = {
86
+ mode: pickMode(ctx.values.check, ctx.values.dry),
87
+ quiet: ctx.values.quiet,
88
+ bench: ctx.values.bench,
89
+ help: ctx.values.help,
90
+ version: ctx.values.version,
91
+ ignore: ctx.values.ignore ?? [],
92
+ inputs: [...ctx.positionals, ...ctx.rest]
93
+ };
94
+ }
95
+ });
67
96
  try {
68
- const parsed = parseArgs({
69
- args: [...argv],
70
- options: {
71
- check: { type: "boolean", default: false },
72
- dry: { type: "boolean", default: false },
73
- bench: { type: "boolean", default: false },
74
- quiet: { type: "boolean", default: false },
75
- version: { type: "boolean", default: false },
76
- help: { type: "boolean", default: false },
77
- ignore: { type: "string", multiple: true, default: [] }
78
- },
79
- allowPositionals: true,
80
- strict: true
81
- });
82
- return {
83
- mode: pickMode(parsed.values.check, parsed.values.dry),
84
- quiet: parsed.values.quiet,
85
- bench: parsed.values.bench,
86
- help: parsed.values.help,
87
- version: parsed.values.version,
88
- ignore: parsed.values.ignore,
89
- inputs: parsed.positionals
90
- };
97
+ await cli([...argv], command, { strict: true });
91
98
  } catch (error) {
92
- return error instanceof Error ? error.message : String(error);
99
+ return formatParseError(error);
93
100
  }
101
+ return parsed ?? "the command line could not be parsed";
94
102
  }
95
103
  function pickMode(check, dry) {
96
104
  if (check) {
@@ -98,6 +106,13 @@ function pickMode(check, dry) {
98
106
  }
99
107
  return dry ? "dry" : "write";
100
108
  }
109
+ function formatParseError(error) {
110
+ if (error instanceof AggregateError) {
111
+ return error.errors.map((reason) => formatParseError(reason)).join(`
112
+ `);
113
+ }
114
+ return error instanceof Error ? error.message : String(error);
115
+ }
101
116
 
102
117
  // src/cli/print-help.ts
103
118
  function printHelp() {
@@ -531,8 +546,8 @@ import fs4 from "node:fs";
531
546
 
532
547
  // src/cli/build-unified-diff.ts
533
548
  function buildUnifiedDiff(before, after, label) {
534
- const ops = new MyersDiff(splitLines(before), splitLines(after)).buildOps();
535
- const hunks = buildHunks(ops);
549
+ const operations = buildDiffOps({ before: splitLines(before), after: splitLines(after) });
550
+ const hunks = buildHunks(operations);
536
551
  if (hunks.length === 0) {
537
552
  return "";
538
553
  }
@@ -548,88 +563,82 @@ function splitLines(s) {
548
563
  }
549
564
  return lines;
550
565
  }
551
-
552
- class MyersDiff {
553
- a;
554
- b;
555
- v = new Map([[1, 0]]);
556
- trace = [];
557
- constructor(a, b) {
558
- this.a = a;
559
- this.b = b;
560
- }
561
- buildOps() {
562
- this.updateTrace();
563
- return this.backtrack();
564
- }
565
- updateTrace() {
566
- for (let d = 0;d <= this.a.length + this.b.length; d++) {
567
- this.trace.push(new Map(this.v));
568
- if (this.stepRound(d)) {
569
- return;
570
- }
571
- }
572
- }
573
- stepRound(d) {
574
- for (let k = -d;k <= d; k += 2) {
575
- const x = this.slideDiagonal(this.pickX(k, d), k);
576
- this.v.set(k, x);
577
- if (x >= this.a.length && x - k >= this.b.length) {
578
- return true;
579
- }
566
+ function buildDiffOps(lines) {
567
+ return backtrack(lines, buildTrace(lines));
568
+ }
569
+ function buildTrace(lines) {
570
+ const furthestX = new Map([[1, 0]]);
571
+ const trace = [];
572
+ for (let depth = 0;depth <= lines.before.length + lines.after.length; depth++) {
573
+ trace.push(new Map(furthestX));
574
+ if (stepRound(lines, furthestX, depth)) {
575
+ break;
580
576
  }
581
- return false;
582
- }
583
- pickX(k, d) {
584
- const moveDown = k === -d || k !== d && (this.v.get(k - 1) ?? 0) < (this.v.get(k + 1) ?? 0);
585
- return moveDown ? this.v.get(k + 1) ?? 0 : (this.v.get(k - 1) ?? 0) + 1;
586
577
  }
587
- slideDiagonal(x, k) {
588
- let nx = x;
589
- while (nx < this.a.length && nx - k < this.b.length && this.a[nx] === this.b[nx - k]) {
590
- nx++;
591
- }
592
- return nx;
593
- }
594
- backtrack() {
595
- const ops = [];
596
- let pos = { x: this.a.length, y: this.b.length };
597
- for (let d = this.trace.length - 1;d >= 0; d--) {
598
- const round = this.unwindRound(pos, d);
599
- ops.push(...round.ops);
600
- pos = round.pos;
601
- }
602
- return ops.toReversed();
603
- }
604
- unwindRound(pos, d) {
605
- const previous = this.findPrevious(pos, d);
606
- const prev = previous.prev;
607
- const ops = this.buildEqualOps(pos, prev);
608
- if (d > 0) {
609
- const changeOp = previous.moveDown ? { kind: "+", text: this.b[prev.y] ?? "" } : { kind: "-", text: this.a[prev.x] ?? "" };
610
- ops.push(changeOp);
611
- }
612
- return { ops, pos: prev };
613
- }
614
- findPrevious(pos, d) {
615
- const v = this.trace[d] ?? new Map;
616
- const k = pos.x - pos.y;
617
- const moveDown = k === -d || k !== d && (v.get(k - 1) ?? 0) < (v.get(k + 1) ?? 0);
618
- const prevK = moveDown ? k + 1 : k - 1;
619
- const prevX = v.get(prevK) ?? 0;
620
- return { prev: { x: prevX, y: prevX - prevK }, moveDown };
621
- }
622
- buildEqualOps(pos, prev) {
623
- const ops = [];
624
- let x = pos.x;
625
- let y = pos.y;
626
- while (x > prev.x && y > prev.y) {
627
- ops.push({ kind: " ", text: this.a[x - 1] ?? "" });
628
- x--;
629
- y--;
578
+ return trace;
579
+ }
580
+ function stepRound(lines, furthestX, depth) {
581
+ for (let diagonal = -depth;diagonal <= depth; diagonal += 2) {
582
+ const x = slideDiagonal(lines, pickX(furthestX, diagonal, depth), diagonal);
583
+ furthestX.set(diagonal, x);
584
+ if (x >= lines.before.length && x - diagonal >= lines.after.length) {
585
+ return true;
630
586
  }
631
- return ops;
632
587
  }
588
+ return false;
589
+ }
590
+ function pickX(furthestX, diagonal, depth) {
591
+ const below = furthestX.get(diagonal - 1) ?? 0;
592
+ const above = furthestX.get(diagonal + 1) ?? 0;
593
+ const moveDown = diagonal === -depth || diagonal !== depth && below < above;
594
+ return moveDown ? above : below + 1;
595
+ }
596
+ function slideDiagonal(lines, x, diagonal) {
597
+ let endX = x;
598
+ while (endX < lines.before.length && endX - diagonal < lines.after.length && lines.before[endX] === lines.after[endX - diagonal]) {
599
+ endX++;
600
+ }
601
+ return endX;
602
+ }
603
+ function backtrack(lines, trace) {
604
+ const operations = [];
605
+ let position = { x: lines.before.length, y: lines.after.length };
606
+ for (let depth = trace.length - 1;depth >= 0; depth--) {
607
+ const round = unwindRound(lines, trace, position, depth);
608
+ operations.push(...round.operations);
609
+ position = round.position;
610
+ }
611
+ return operations.toReversed();
612
+ }
613
+ function unwindRound(lines, trace, position, depth) {
614
+ const step = findPreviousStep(trace, position, depth);
615
+ const operations = buildEqualOps(lines, position, step.position);
616
+ if (depth > 0) {
617
+ const changeOp = step.moveDown ? { kind: "+", text: lines.after[step.position.y] ?? "" } : { kind: "-", text: lines.before[step.position.x] ?? "" };
618
+ operations.push(changeOp);
619
+ }
620
+ return { operations, position: step.position };
621
+ }
622
+ function findPreviousStep(trace, position, depth) {
623
+ const furthestX = trace[depth] ?? new Map;
624
+ const diagonal = position.x - position.y;
625
+ const below = furthestX.get(diagonal - 1) ?? 0;
626
+ const above = furthestX.get(diagonal + 1) ?? 0;
627
+ const moveDown = diagonal === -depth || diagonal !== depth && below < above;
628
+ const previousDiagonal = moveDown ? diagonal + 1 : diagonal - 1;
629
+ const previousX = furthestX.get(previousDiagonal) ?? 0;
630
+ return { position: { x: previousX, y: previousX - previousDiagonal }, moveDown };
631
+ }
632
+ function buildEqualOps(lines, position, previous) {
633
+ const operations = [];
634
+ let x = position.x;
635
+ let y = position.y;
636
+ while (x > previous.x && y > previous.y) {
637
+ operations.push({ kind: " ", text: lines.before[x - 1] ?? "" });
638
+ x--;
639
+ y--;
640
+ }
641
+ return operations;
633
642
  }
634
643
  function buildHunks(ops) {
635
644
  return buildWindows(ops).map((w) => buildHunk(ops, w));
@@ -729,7 +738,7 @@ function tryCheckFile(file, mode) {
729
738
  }
730
739
 
731
740
  // src/cli.ts
732
- var parsedArgs = parseCLIArgs(process.argv.slice(2));
741
+ var parsedArgs = await parseCLIArgs(process.argv.slice(2));
733
742
  if (typeof parsedArgs === "string") {
734
743
  console.error(parsedArgs);
735
744
  process.exit(2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zgeoff/format-codemod",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Enforce blank-line padding conventions in TypeScript via a fast text-splice codemod",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,11 +30,12 @@
30
30
  "typecheck": "tsc"
31
31
  },
32
32
  "dependencies": {
33
- "oxc-parser": "0.137.0"
33
+ "gunshi": "1.0.0-rc.1",
34
+ "oxc-parser": "0.153.0"
34
35
  },
35
36
  "devDependencies": {
36
- "@types/bun": "1.3.14",
37
- "typescript": "7.0.1-rc"
37
+ "@types/bun": "1.4.2",
38
+ "typescript": "7.0.2"
38
39
  },
39
40
  "engines": {
40
41
  "bun": ">=1.3",