Skip to content

Commit be5961b

Browse files
Fix #2336: Parameretized padding
1 parent 8cc8cea commit be5961b

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

src/fable-library/String.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { toString as dateToString } from "./Date.js";
22
import { compare as numericCompare, isNumeric, multiply, Numeric, toExponential, toFixed, toHex, toPrecision } from "./Numeric.js";
33
import { escape } from "./RegExp.js";
4-
import { toString } from "./Types.js";
4+
import { FSharpRef, toString } from "./Types.js";
55

6-
const fsFormatRegExp = /(^|[^%])%([0+\- ]*)(\d+)?(?:\.(\d+))?(\w)/;
6+
const fsFormatRegExp = /(^|[^%])%([0+\- ]*)(\*|\d+)?(?:\.(\d+))?(\w)/;
77
const interpolateRegExp = /(?:(^|[^%])%([0+\- ]*)(\d+)?(?:\.(\d+))?(\w))?%P\(\)/g;
88
const formatRegExp = /\{(\d+)(,-?\d+)?(?:\:([a-zA-Z])(\d{0,2})|\:(.+?))?\}/g;
99

@@ -184,7 +184,7 @@ function formatReplacement(rep: any, prefix: any, flags: any, padLength: any, pr
184184
} else {
185185
rep = toString(rep);
186186
}
187-
padLength = parseInt(padLength, 10);
187+
padLength = typeof padLength === "number" ? padLength : parseInt(padLength, 10);
188188
if (!isNaN(padLength)) {
189189
const zeroFlag = flags.indexOf("0") >= 0; // Use '0' for left padding
190190
const minusFlag = flags.indexOf("-") >= 0; // Right padding
@@ -201,22 +201,33 @@ function formatReplacement(rep: any, prefix: any, flags: any, padLength: any, pr
201201
return prefix ? prefix + rep : rep;
202202
}
203203

204-
function formatOnce(str2: string, rep: any) {
205-
return str2.replace(fsFormatRegExp, (_, prefix, flags, padLength, precision, format) => {
204+
function formatOnce(str2: string, rep: any, padRef: FSharpRef<number|null>) {
205+
return str2.replace(fsFormatRegExp, (match, prefix, flags, padLength, precision, format) => {
206+
if (padRef.contents != null) {
207+
padLength = padRef.contents;
208+
padRef.contents = null;
209+
}
210+
else if (padLength === "*") {
211+
if (rep < 0) {
212+
throw new Error("Non-negative number required");
213+
}
214+
padRef.contents = rep;
215+
return match;
216+
}
206217
const once = formatReplacement(rep, prefix, flags, padLength, precision, format);
207218
return once.replace(/%/g, "%%");
208219
});
209220
}
210221

211-
function createPrinter(str: string, cont: (...args: any[]) => any) {
222+
function createPrinter(str: string, cont: (...args: any[]) => any, padRef = new FSharpRef<number|null>(null)) {
212223
return (...args: any[]) => {
213224
// Make a copy as the function may be used several times
214225
let strCopy = str;
215226
for (const arg of args) {
216-
strCopy = formatOnce(strCopy, arg);
227+
strCopy = formatOnce(strCopy, arg, padRef);
217228
}
218229
return fsFormatRegExp.test(strCopy)
219-
? createPrinter(strCopy, cont)
230+
? createPrinter(strCopy, cont, padRef)
220231
: cont(strCopy.replace(/%%/g, "%"));
221232
};
222233
}

tests/Main/StringTests.fs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,10 @@ let tests =
279279
sprintf "%5d" -5L |> equal " -5"
280280
sprintf "%- 4i" 5 |> equal " 5 "
281281

282+
testCase "parameterized padding works" <| fun () -> // See #2336
283+
sprintf "[%*s][%*s]" 6 "Hello" 5 "Foo"
284+
|> equal "[ Hello][ Foo]"
285+
282286
testCase "String.Format combining padding and zeroes pattern works" <| fun () ->
283287
String.Format("{0:++0.00++}", -5000.5657) |> equal "-++5000.57++"
284288
String.Format("{0:000.00}foo", 5) |> equal "005.00foo"

0 commit comments

Comments
 (0)