Skip to content

Commit e60020a

Browse files
committed
Deduplication flags function with tests
1 parent 87bd15a commit e60020a

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { describe, it, expect } from "vitest";
2+
import { dedupFlags } from "./flags.js";
3+
4+
describe("dedupFlags", () => {
5+
it("should keep single flags unchanged", () => {
6+
expect(dedupFlags("--verbose")).toBe("--verbose");
7+
expect(dedupFlags("-v")).toBe("-v");
8+
expect(dedupFlags("--debug=true")).toBe("--debug=true");
9+
});
10+
11+
it("should preserve multiple different flags", () => {
12+
expect(dedupFlags("--quiet --verbose")).toBe("--quiet --verbose");
13+
expect(dedupFlags("-v -q --log=debug")).toBe("-v -q --log=debug");
14+
});
15+
16+
it("should use last value when flags are duplicated", () => {
17+
expect(dedupFlags("--debug=false --debug=true")).toBe("--debug=true");
18+
expect(dedupFlags("--log=info --log=warn --log=error")).toBe("--log=error");
19+
});
20+
21+
it("should handle mix of flags with and without values", () => {
22+
expect(dedupFlags("--debug=false -v --debug=true")).toBe("-v --debug=true");
23+
expect(dedupFlags("-v --quiet -v")).toBe("--quiet -v");
24+
});
25+
26+
// Edge cases
27+
it("should handle empty string", () => {
28+
expect(dedupFlags("")).toBe("");
29+
});
30+
31+
it("should handle multiple spaces between flags", () => {
32+
expect(dedupFlags("--debug=false --verbose --debug=true")).toBe("--verbose --debug=true");
33+
});
34+
35+
it("should handle flags with empty values", () => {
36+
expect(dedupFlags("--path= --path=foo")).toBe("--path=foo");
37+
expect(dedupFlags("--path=foo --path=")).toBe("--path=");
38+
});
39+
40+
it("should preserve values containing equals signs", () => {
41+
expect(dedupFlags("--url=http://example.com?foo=bar")).toBe("--url=http://example.com?foo=bar");
42+
});
43+
44+
it("should handle flags with special characters", () => {
45+
expect(dedupFlags("--path=/usr/local --path=/home/user")).toBe("--path=/home/user");
46+
expect(dedupFlags('--name="John Doe" --name="Jane Doe"')).toBe('--name="Jane Doe"');
47+
});
48+
49+
it("should handle multiple flag variants", () => {
50+
const input = "--env=dev -v --env=prod --quiet -v --env=staging";
51+
expect(dedupFlags(input)).toBe("--quiet -v --env=staging");
52+
});
53+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Deduplicates command line flags by keeping only the last occurrence of each flag.
3+
* Preserves the order of the last occurrence of each flag.
4+
*
5+
* @param flags - A space-separated string of command line flags
6+
* @returns A space-separated string of deduplicated flags
7+
*
8+
* @example
9+
* // Single flags are preserved
10+
* dedupFlags("--quiet --verbose") // returns "--quiet --verbose"
11+
*
12+
* @example
13+
* // For duplicate flags, the last value wins and maintains its position
14+
* dedupFlags("--debug=false --log=info --debug=true") // returns "--log=info --debug=true"
15+
*
16+
* @example
17+
* // Mixing flags with and without values
18+
* dedupFlags("-v --log=debug -v") // returns "--log=debug -v"
19+
*/
20+
export function dedupFlags(flags: string): string {
21+
const seen = new Set<string>();
22+
const result: [string, string | boolean][] = [];
23+
24+
const pairs = flags
25+
.split(" ")
26+
.filter(Boolean) // Remove empty strings from multiple spaces
27+
.map((flag): [string, string | boolean] => {
28+
const equalIndex = flag.indexOf("=");
29+
if (equalIndex !== -1) {
30+
const key = flag.slice(0, equalIndex);
31+
const value = flag.slice(equalIndex + 1);
32+
return [key, value];
33+
} else {
34+
return [flag, true];
35+
}
36+
});
37+
38+
// Process in reverse to keep last occurrence
39+
for (const [key, value] of pairs.reverse()) {
40+
if (!seen.has(key)) {
41+
seen.add(key);
42+
result.unshift([key, value]);
43+
}
44+
}
45+
46+
return result.map(([key, value]) => (value === true ? key : `${key}=${value}`)).join(" ");
47+
}

0 commit comments

Comments
 (0)