Skip to content

Commit c958451

Browse files
Enhance sequence command with leading zeros preservation and max-length padding
- Add leading zeros preservation logic similar to increment/decrement commands - Implement max-length consistent padding across all numbers in selection - Add comprehensive test coverage for various zero padding scenarios - Fixes issue #72: sequence command now maintains leading zero formatting 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 575a8bb commit c958451

File tree

3 files changed

+180
-2
lines changed

3 files changed

+180
-2
lines changed

content.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,6 @@ prefix007 suffix008 middle009
6262
0009 0010 0001
6363
0001 0099 0000
6464
0007 0008 0009
65+
test01 value100 prefix007 99
66+
02 100 4
67+
010 100 123

src/commands/sequence.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,40 @@ export const sequence: CommandFunction = (
44
str: string,
55
multiselectData: MultiSelectData = {}
66
) => {
7+
// First pass: find all numbers and determine the maximum length for zero padding
8+
const numbers = Array.from(str.matchAll(/-?\d+/g));
9+
const maxLength = Math.max(...numbers.map(match => {
10+
const num = match[0];
11+
// Only consider numbers with leading zeros for max length calculation
12+
if (num.length > 1 && num.charAt(num.charAt(0) === '-' ? 1 : 0) === '0') {
13+
return num.length;
14+
}
15+
return 0;
16+
}));
17+
718
return str.replace(/-?\d+/g, (n) => {
819
const isFirst = typeof multiselectData.offset !== "number";
920
multiselectData.offset = isFirst
1021
? Number(n)
1122
: (multiselectData.offset || 0) + 1;
12-
return String(multiselectData.offset);
23+
24+
const sequenceValue = multiselectData.offset;
25+
26+
// Use max length for consistent padding if any number in the string has leading zeros
27+
if (maxLength > 0) {
28+
const isNegative = sequenceValue < 0;
29+
const sequenceStr = String(sequenceValue);
30+
31+
if (isNegative) {
32+
// For negative numbers, pad after the minus sign
33+
const absStr = sequenceStr.substring(1);
34+
return '-' + absStr.padStart(maxLength - 1, '0');
35+
} else {
36+
// For positive numbers, pad the entire string
37+
return sequenceStr.padStart(maxLength, '0');
38+
}
39+
}
40+
41+
return String(sequenceValue);
1342
});
1443
};

src/test/extension.test.ts

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,152 @@ suite("Extension Test Suite", () => {
746746
);
747747
});
748748

749+
test("sequence preserves leading zeros", async () => {
750+
const [output1, output2, output3] = await getTextForSelectionsByCommand(
751+
"string-manipulation.sequence",
752+
[
753+
{
754+
start: { line: 55, character: 0 },
755+
end: { line: 55, character: 21 },
756+
},
757+
{
758+
start: { line: 56, character: 0 },
759+
end: { line: 56, character: 26 },
760+
},
761+
{
762+
start: { line: 57, character: 0 },
763+
end: { line: 57, character: 30 },
764+
},
765+
]
766+
);
767+
768+
assert.strictEqual(
769+
output1 /* abc009 def010 ghi001 */,
770+
"abc009 def010 ghi011"
771+
);
772+
assert.strictEqual(
773+
output2 /* test001 value99 number000 */,
774+
"test012 value013 number014"
775+
);
776+
assert.strictEqual(
777+
output3 /* prefix007 suffix008 middle009 */,
778+
"prefix015 suffix016 middle017"
779+
);
780+
});
781+
782+
test("sequence preserves leading zeros without prefixes", async () => {
783+
const [output1, output2, output3] = await getTextForSelectionsByCommand(
784+
"string-manipulation.sequence",
785+
[
786+
{
787+
start: { line: 58, character: 0 },
788+
end: { line: 58, character: 11 },
789+
},
790+
{
791+
start: { line: 59, character: 0 },
792+
end: { line: 59, character: 10 },
793+
},
794+
{
795+
start: { line: 60, character: 0 },
796+
end: { line: 60, character: 11 },
797+
},
798+
]
799+
);
800+
801+
assert.strictEqual(
802+
output1 /* 009 010 001 */,
803+
"009 010 011"
804+
);
805+
assert.strictEqual(
806+
output2 /* 001 99 000 */,
807+
"012 013 014"
808+
);
809+
assert.strictEqual(
810+
output3 /* 007 008 009 */,
811+
"015 016 017"
812+
);
813+
});
814+
815+
test("sequence preserves 3 leading zeros", async () => {
816+
const [output1, output2, output3] = await getTextForSelectionsByCommand(
817+
"string-manipulation.sequence",
818+
[
819+
{
820+
start: { line: 61, character: 0 },
821+
end: { line: 61, character: 14 },
822+
},
823+
{
824+
start: { line: 62, character: 0 },
825+
end: { line: 62, character: 14 },
826+
},
827+
{
828+
start: { line: 63, character: 0 },
829+
end: { line: 63, character: 14 },
830+
},
831+
]
832+
);
833+
834+
assert.strictEqual(
835+
output1 /* 0009 0010 0001 */,
836+
"0009 0010 0011"
837+
);
838+
assert.strictEqual(
839+
output2 /* 0001 0099 0000 */,
840+
"0012 0013 0014"
841+
);
842+
assert.strictEqual(
843+
output3 /* 0007 0008 0009 */,
844+
"0015 0016 0017"
845+
);
846+
});
847+
848+
test("sequence preserves leading zeros with mixed number formats", async () => {
849+
const [output] = await getTextForSelectionsByCommand(
850+
"string-manipulation.sequence",
851+
[
852+
{
853+
start: { line: 64, character: 0 },
854+
end: { line: 64, character: 28 },
855+
},
856+
]
857+
);
858+
859+
// Test with a mix of zero-padded and regular numbers
860+
// Line 64 contains: "test01 value100 prefix007 99"
861+
// Max length is 3 from "prefix007", so all numbers should be padded to 3 digits
862+
assert.strictEqual(
863+
output /* test01 value100 prefix007 99 */,
864+
"test001 value002 prefix003 004"
865+
);
866+
});
867+
868+
test("sequence uses max length for consistent zero padding", async () => {
869+
const [output1, output2] = await getTextForSelectionsByCommand(
870+
"string-manipulation.sequence",
871+
[
872+
{
873+
start: { line: 65, character: 0 },
874+
end: { line: 65, character: 8 },
875+
},
876+
{
877+
start: { line: 66, character: 0 },
878+
end: { line: 66, character: 11 },
879+
},
880+
]
881+
);
882+
883+
// Line 65: "02 100 4" - max length is 2 from "02", so all should be padded to 2 digits
884+
assert.strictEqual(
885+
output1 /* 02 100 4 */,
886+
"02 03 04"
887+
);
888+
// Line 66: "010 100 123" - max length is 3 from "010", so all should be padded to 3 digits
889+
assert.strictEqual(
890+
output2 /* 010 100 123 */,
891+
"005 006 007"
892+
);
893+
});
894+
749895
test("utf8ToChar converts Unicode escapes to characters", async () => {
750896
const [output] = await getTextForSelectionsByCommand(
751897
"string-manipulation.utf8ToChar",
@@ -784,7 +930,7 @@ suite("Extension Test Suite", () => {
784930
const input = "Hello, World!";
785931

786932
test("maintains string length and lowercased content", async () => {
787-
const [output] = await getTextForSelectionsByCommand(
933+
await getTextForSelectionsByCommand(
788934
"string-manipulation.randomCase",
789935
[
790936
{

0 commit comments

Comments
 (0)