diff --git a/NEWS.md b/NEWS.md index 32b2b7ab892db..bc0a7e72ed4b9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -233,6 +233,8 @@ Library improvements * The functions `strip`, `lstrip` and `rstrip` now return `SubString` ([#22496]). + * The functions `strwidth` and `charwidth` have been merged into `textwidth`([#20816]). + * The functions `base` and `digits` digits now accept a negative base (like `ndigits` did) ([#21692]). diff --git a/base/deprecated.jl b/base/deprecated.jl index bd758c9518491..17578096c5fbd 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1651,7 +1651,7 @@ end end # PR #23187 -@deprecate cpad(s, n::Integer, p=" ") rpad(lpad(s, div(n+strwidth(s), 2), p), n, p) false +@deprecate cpad(s, n::Integer, p=" ") rpad(lpad(s, div(n+textwidth(s), 2), p), n, p) false # PR #22088 function hex2num(s::AbstractString) @@ -1877,6 +1877,10 @@ end nothing end +# issue #20816 +@deprecate strwidth textwidth +@deprecate charwidth textwidth + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/dict.jl b/base/dict.jl index 24aaa18c9dbae..f4b0642759eca 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license function _truncate_at_width_or_chars(str, width, chars="", truncmark="…") - truncwidth = strwidth(truncmark) + truncwidth = textwidth(truncmark) (width <= 0 || width < truncwidth) && return "" wid = truncidx = lastidx = 0 @@ -9,7 +9,7 @@ function _truncate_at_width_or_chars(str, width, chars="", truncmark="…") while !done(str, idx) lastidx = idx c, idx = next(str, idx) - wid += charwidth(c) + wid += textwidth(c) wid >= width - truncwidth && truncidx == 0 && (truncidx = lastidx) (wid >= width || c in chars) && break end diff --git a/base/exports.jl b/base/exports.jl index 5d80d9feddfd6..57e0a174cd491 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -730,7 +730,6 @@ export bin, bits, bytes2hex, - charwidth, chomp, chop, chr2ind, @@ -800,8 +799,8 @@ export sprint, string, strip, - strwidth, summary, + textwidth, titlecase, transcode, ucfirst, diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 1167a7a7e9da4..ad160ae956b9a 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -570,7 +570,7 @@ end function warnbanner(msg...; label="[ WARNING ]", prefix="") cols = Base.displaysize(STDERR)[2] - str = rpad(lpad(label, div(cols+strwidth(label), 2), "="), cols, "=") + str = rpad(lpad(label, div(cols+textwidth(label), 2), "="), cols, "=") warn(prefix="", str) println(STDERR) warn(prefix=prefix, msg...) diff --git a/base/printf.jl b/base/printf.jl index dff3d28412df7..2f8347f6f8a95 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -617,11 +617,11 @@ function gen_c(flags::String, width::Int, precision::Int, c::Char) blk = Expr(:block, :($x = Char($x))) if width > 1 && !('-' in flags) p = '0' in flags ? '0' : ' ' - push!(blk.args, pad(width-1, :($width-charwidth($x)), p)) + push!(blk.args, pad(width-1, :($width-textwidth($x)), p)) end push!(blk.args, :(write(out, $x))) if width > 1 && '-' in flags - push!(blk.args, pad(width-1, :($width-charwidth($x)), ' ')) + push!(blk.args, pad(width-1, :($width-textwidth($x)), ' ')) end :(($x)::Integer), blk end @@ -652,11 +652,11 @@ function gen_s(flags::String, width::Int, precision::Int, c::Char) push!(blk.args, :($x = _limit($x, $precision))) end if !('-' in flags) - push!(blk.args, pad(width, :($width-strwidth($x)), ' ')) + push!(blk.args, pad(width, :($width-textwidth($x)), ' ')) end push!(blk.args, :(write(out, $x))) if '-' in flags - push!(blk.args, pad(width, :($width-strwidth($x)), ' ')) + push!(blk.args, pad(width, :($width-textwidth($x)), ' ')) end else if precision!=-1 diff --git a/base/repl/LineEdit.jl b/base/repl/LineEdit.jl index 7c330774fef99..36c8ffb726f19 100644 --- a/base/repl/LineEdit.jl +++ b/base/repl/LineEdit.jl @@ -307,8 +307,8 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf while moreinput l = readline(buf, chomp=false) moreinput = endswith(l, "\n") - # We need to deal with on-screen characters, so use strwidth to compute occupied columns - llength = strwidth(l) + # We need to deal with on-screen characters, so use textwidth to compute occupied columns + llength = textwidth(l) slength = sizeof(l) cur_row += 1 cmove_col(termbuf, lindent + 1) @@ -319,7 +319,7 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf # in this case, we haven't yet written the cursor position line_pos -= slength # '\n' gets an extra pos if line_pos < 0 || !moreinput - num_chars = (line_pos >= 0 ? llength : strwidth(l[1:prevind(l, line_pos + slength + 1)])) + num_chars = (line_pos >= 0 ? llength : textwidth(l[1:prevind(l, line_pos + slength + 1)])) curs_row, curs_pos = divrem(lindent + num_chars - 1, cols) curs_row += cur_row curs_pos += 1 @@ -408,7 +408,7 @@ function edit_move_left(buf::IOBuffer) #move to the next base UTF8 character to the left while true c = char_move_left(buf) - if charwidth(c) != 0 || c == '\n' || position(buf) == 0 + if textwidth(c) != 0 || c == '\n' || position(buf) == 0 break end end @@ -466,7 +466,7 @@ function edit_move_right(buf::IOBuffer) pos = position(buf) nextc = read(buf,Char) seek(buf,pos) - (charwidth(nextc) != 0 || nextc == '\n') && break + (textwidth(nextc) != 0 || nextc == '\n') && break end return true end @@ -637,7 +637,7 @@ function edit_backspace(buf::IOBuffer, align::Bool=false, adjust::Bool=false) newpos = position(buf) if align && c == ' ' # maybe delete multiple spaces beg = beginofline(buf, newpos) - align = strwidth(String(buf.data[1+beg:newpos])) % 4 + align = textwidth(String(buf.data[1+beg:newpos])) % 4 nonspace = findprev(_notspace, buf.data, newpos) if newpos - align >= nonspace newpos -= align @@ -950,7 +950,7 @@ end function write_prompt(terminal, s::Union{AbstractString,Function}) promptstr = prompt_string(s) write(terminal, promptstr) - strwidth(promptstr) + textwidth(promptstr) end ### Keymap Support @@ -1697,7 +1697,7 @@ function edit_insert_tab(buf::IOBuffer, jump_spaces=false, delete_trailing=jump_ end end # align to multiples of 4: - align = 4 - strwidth(String(buf.data[1+beginofline(buf, i):i])) % 4 + align = 4 - textwidth(String(buf.data[1+beginofline(buf, i):i])) % 4 edit_insert(buf, ' '^align) return true end diff --git a/base/show.jl b/base/show.jl index 3f6aad653eab7..1ad119d814e83 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1682,7 +1682,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat, screenwidth -= length(pre) + length(post) presp = repeat(" ", length(pre)) # indent each row to match pre string postsp = "" - @assert strwidth(hdots) == strwidth(ddots) + @assert textwidth(hdots) == textwidth(ddots) sepsize = length(sep) rowsA, colsA = indices(X,1), indices(X,2) m, n = length(rowsA), length(colsA) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 71edd09db674a..29b639e5b42b3 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -389,21 +389,6 @@ next(e::EachStringIndex, state) = (state, nextind(e.s, state)) done(e::EachStringIndex, state) = done(e.s, state) eltype(::Type{EachStringIndex}) = Int -## character column width function ## - -""" - strwidth(s::AbstractString) - -Give the number of columns needed to print a string. - -# Examples -```jldoctest -julia> strwidth("March") -5 -``` -""" -strwidth(s::AbstractString) = (w=0; for c in s; w += charwidth(c); end; w) - """ isascii(c::Union{Char,AbstractString}) -> Bool diff --git a/base/strings/utf8proc.jl b/base/strings/utf8proc.jl index 3c82902a1c01b..70e406097303a 100644 --- a/base/strings/utf8proc.jl +++ b/base/strings/utf8proc.jl @@ -8,7 +8,7 @@ import Base: show, ==, hash, string, Symbol, isless, length, eltype, start, next export isgraphemebreak, category_code, category_abbrev, category_string # also exported by Base: -export normalize_string, graphemes, is_assigned_char, charwidth, isvalid, +export normalize_string, graphemes, is_assigned_char, textwidth, isvalid, islower, isupper, isalpha, isdigit, isnumber, isalnum, iscntrl, ispunct, isspace, isprint, isgraph @@ -208,21 +208,35 @@ end ############################################################################ +## character column width function ## """ - charwidth(c) + textwidth(c) -Gives the number of columns needed to print a character. +Give the number of columns needed to print a character. # Examples ```jldoctest -julia> charwidth('α') +julia> textwidth('α') 1 -julia> charwidth('❤') +julia> textwidth('❤') 2 ``` """ -charwidth(c::Char) = Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), c)) +textwidth(c::Char) = Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), c)) + +""" + textwidth(s::AbstractString) + +Give the number of columns needed to print a string. + +# Examples +```jldoctest +julia> textwidth("March") +5 +``` +""" +textwidth(s::AbstractString) = mapreduce(textwidth, +, 0, s) lowercase(c::Char) = isascii(c) ? ('A' <= c <= 'Z' ? c + 0x20 : c) : Char(ccall(:utf8proc_tolower, UInt32, (UInt32,), c)) uppercase(c::Char) = isascii(c) ? ('a' <= c <= 'z' ? c - 0x20 : c) : Char(ccall(:utf8proc_toupper, UInt32, (UInt32,), c)) diff --git a/base/strings/util.jl b/base/strings/util.jl index 665fae4c6398d..2d3e646109055 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -204,9 +204,9 @@ strip(s::AbstractString, chars::Chars) = lstrip(rstrip(s, chars), chars) ## string padding functions ## function lpad(s::AbstractString, n::Integer, p::AbstractString=" ") - m = n - strwidth(s) + m = n - textwidth(s) (m <= 0) && (return s) - l = strwidth(p) + l = textwidth(p) if l==1 return string(p^m, s) end @@ -217,9 +217,9 @@ function lpad(s::AbstractString, n::Integer, p::AbstractString=" ") end function rpad(s::AbstractString, n::Integer, p::AbstractString=" ") - m = n - strwidth(s) + m = n - textwidth(s) (m <= 0) && (return s) - l = strwidth(p) + l = textwidth(p) if l==1 return string(s, p^m) end diff --git a/doc/src/stdlib/strings.md b/doc/src/stdlib/strings.md index 9be348f2ec9f8..003b9b1b92b6d 100644 --- a/doc/src/stdlib/strings.md +++ b/doc/src/stdlib/strings.md @@ -59,8 +59,7 @@ Base.chr2ind Base.nextind Base.prevind Base.Random.randstring -Base.UTF8proc.charwidth -Base.strwidth +Base.UTF8proc.textwidth Base.UTF8proc.isalnum Base.UTF8proc.isalpha Base.isascii diff --git a/test/dict.jl b/test/dict.jl index 45245f457185b..8c0f22e383592 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -274,7 +274,7 @@ end Base.show(io, MIME("text/plain"), d) out = split(String(take!(s)),'\n') for line in out[2:end] - @test strwidth(line) <= cols + @test textwidth(line) <= cols end @test length(out) <= rows @@ -284,7 +284,7 @@ end Base.show(io, MIME("text/plain"), f(d)) out = split(String(take!(s)),'\n') for line in out[2:end] - @test strwidth(line) <= cols + @test textwidth(line) <= cols end @test length(out) <= rows end diff --git a/test/unicode/utf8proc.jl b/test/unicode/utf8proc.jl index 2c70ed21291f8..ef05772064913 100644 --- a/test/unicode/utf8proc.jl +++ b/test/unicode/utf8proc.jl @@ -266,16 +266,17 @@ end end @testset "#3721, #6939 up-to-date character widths" begin - @test charwidth('\U1f355') == 2 - @test strwidth("\U1f355") == 2 - @test strwidth(GenericString("\U1f355")) == 2 - @test strwidth("\U1f355\u0302") == 2 - @test strwidth(GenericString("\U1f355\u0302")) == 2 + @test textwidth("") == 0 + @test textwidth('\U1f355') == 2 + @test textwidth("\U1f355") == 2 + @test textwidth(GenericString("\U1f355")) == 2 + @test textwidth("\U1f355\u0302") == 2 + @test textwidth(GenericString("\U1f355\u0302")) == 2 end @testset "#10958 handling of embedded NUL chars" begin @test length("\0w") == length("\0α") == 2 - @test strwidth("\0w") == strwidth("\0α") == 1 + @test textwidth("\0w") == textwidth("\0α") == 1 @test normalize_string("\0W", casefold=true) == "\0w" end