diff --git a/base/strings/util.jl b/base/strings/util.jl index fcccb9babadfd..1b73fbbbab5cf 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -476,7 +476,12 @@ function lpad( n = Int(n)::Int m = signed(n) - Int(textwidth(s))::Int m ≤ 0 && return stringfn(s) - l = textwidth(p) + l = Int(textwidth(p))::Int + if l == 0 + throw(ArgumentError("$(repr(p)) has zero textwidth" * (ncodeunits(p) != 1 ? "" : + "; maybe you want pad^max(0, npad - ncodeunits(str)) * str to pad by codeunits" * + (s isa AbstractString && codeunit(s) != UInt8 ? "?" : " (bytes)?")))) + end q, r = divrem(m, l) r == 0 ? stringfn(p^q, s) : stringfn(p^q, first(p, r), s) end @@ -508,7 +513,12 @@ function rpad( n = Int(n)::Int m = signed(n) - Int(textwidth(s))::Int m ≤ 0 && return stringfn(s) - l = textwidth(p) + l = Int(textwidth(p))::Int + if l == 0 + throw(ArgumentError("$(repr(p)) has zero textwidth" * (ncodeunits(p) != 1 ? "" : + "; maybe you want str * pad^max(0, npad - ncodeunits(str)) to pad by codeunits" * + (s isa AbstractString && codeunit(s) != UInt8 ? "?" : " (bytes)?")))) + end q, r = divrem(m, l) r == 0 ? stringfn(s, p^q) : stringfn(s, p^q, first(p, r)) end diff --git a/test/strings/util.jl b/test/strings/util.jl index ae16e24f4ea8b..bb87881bbaa1d 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -65,6 +65,13 @@ end @test rpad("⟨k|H₁|k̃⟩", 12) |> textwidth == 12 @test lpad("⟨k|H₁|k⟩", 12) |> textwidth == 12 @test rpad("⟨k|H₁|k⟩", 12) |> textwidth == 12 + for pad in (rpad, lpad), p in ('\0', "\0", "\0\0", "\u302") + if ncodeunits(p) == 1 + @test_throws r".*has zero textwidth.*maybe you want.*bytes.*" pad("foo", 10, p) + else + @test_throws r".*has zero textwidth$" pad("foo", 10, p) + end + end end @testset "string truncation (ltruncate, rtruncate, ctruncate)" begin