From 708729bef81e73636e5cf68423a1e9136ec4ba96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Madrid-Menc=C3=ADa?= Date: Mon, 7 Jun 2021 23:34:22 +0200 Subject: [PATCH] Define lpad/rpad in terms of textwidth (#39044) Fix #38256, per triage consensus there --- NEWS.md | 1 + base/strings/util.jl | 16 ++++++++++------ test/strings/util.jl | 5 +++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index c6a41f44e00c9..cc488312bbc70 100644 --- a/NEWS.md +++ b/NEWS.md @@ -100,6 +100,7 @@ Standard library changes * `keys(::RegexMatch)` is now defined to return the capture's keys, by name if named, or by index if not ([#37299]). * `keys(::Generator)` is now defined to return the iterator's keys ([#34678]) * `RegexMatch` now iterate to give their captures. ([#34355]). +* `lpad/rpad` are now defined in terms of `textwidth` ([#39044]) * `Test.@test` now accepts `broken` and `skip` boolean keyword arguments, which mimic `Test.@test_broken` and `Test.@test_skip` behavior, but allows skipping tests failing only under certain conditions. For example diff --git a/base/strings/util.jl b/base/strings/util.jl index 9bc043513deed..411961d8221e7 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -327,7 +327,7 @@ strip(f, s::AbstractString) = lstrip(f, rstrip(f, s)) lpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') -> String Stringify `s` and pad the resulting string on the left with `p` to make it `n` -characters (code points) long. If `s` is already `n` characters long, an equal +characters (in [`textwidth`](@ref)) long. If `s` is already `n` characters long, an equal string is returned. Pad with spaces by default. # Examples @@ -335,6 +335,8 @@ string is returned. Pad with spaces by default. julia> lpad("March", 10) " March" ``` +!!! compat "Julia 1.7" + In Julia 1.7, this function was changed to use `textwidth` rather than a raw character (codepoint) count. """ lpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') = lpad(string(s)::AbstractString, n, string(p)) @@ -344,9 +346,9 @@ function lpad( p::Union{AbstractChar,AbstractString}=' ', ) :: String n = Int(n)::Int - m = signed(n) - Int(length(s))::Int + m = signed(n) - Int(textwidth(s))::Int m ≤ 0 && return string(s) - l = length(p) + l = textwidth(p) q, r = divrem(m, l) r == 0 ? string(p^q, s) : string(p^q, first(p, r), s) end @@ -355,7 +357,7 @@ end rpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') -> String Stringify `s` and pad the resulting string on the right with `p` to make it `n` -characters (code points) long. If `s` is already `n` characters long, an equal +characters (in [`textwidth`](@ref)) long. If `s` is already `n` characters long, an equal string is returned. Pad with spaces by default. # Examples @@ -363,6 +365,8 @@ string is returned. Pad with spaces by default. julia> rpad("March", 20) "March " ``` +!!! compat "Julia 1.7" + In Julia 1.7, this function was changed to use `textwidth` rather than a raw character (codepoint) count. """ rpad(s, n::Integer, p::Union{AbstractChar,AbstractString}=' ') = rpad(string(s)::AbstractString, n, string(p)) @@ -372,9 +376,9 @@ function rpad( p::Union{AbstractChar,AbstractString}=' ', ) :: String n = Int(n)::Int - m = signed(n) - Int(length(s))::Int + m = signed(n) - Int(textwidth(s))::Int m ≤ 0 && return string(s) - l = length(p) + l = textwidth(p) q, r = divrem(m, l) r == 0 ? string(s, p^q) : string(s, p^q, first(p, r)) end diff --git a/test/strings/util.jl b/test/strings/util.jl index e8ea3b643fcda..b0b5a0c36b8ef 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -44,6 +44,11 @@ # Issue #32160 (unsigned underflow in lpad/rpad) @test lpad("xx", UInt(1), " ") == "xx" @test rpad("xx", UInt(1), " ") == "xx" + # Issue #38256 (lpad/rpad defined in terms of textwidth) + @test lpad("⟨k|H₁|k̃⟩", 12) |> textwidth == 12 + @test rpad("⟨k|H₁|k̃⟩", 12) |> textwidth == 12 + @test lpad("⟨k|H₁|k⟩", 12) |> textwidth == 12 + @test rpad("⟨k|H₁|k⟩", 12) |> textwidth == 12 end # string manipulation