About.jl/src/utils.jl

138 lines
4.9 KiB
Julia

const FACE_CYCLE = [:bright_blue, :bright_green, :bright_yellow, :bright_magenta]
function humansize(bytes::Integer)
units = ("B", "kB", "MB", "GB")
magnitude = floor(Int, log(1024, 1 + bytes))
if 10 < bytes < 10*1024^magnitude
round(bytes / 1024^magnitude, digits=1)
else
round(Int, bytes / 1024^magnitude)
end, units[1+magnitude]
end
function hassizeof(type::Type)
!isconcretetype(type) && return false
type <: GenericMemory && return false
type in (Symbol, String, Core.SimpleVector) && return false
true
end
function cpad(s, n::Integer, pad::Union{AbstractString, AbstractChar}=' ', r::RoundingMode = RoundToZero)
rpad(lpad(s, div(n+textwidth(s), 2, r), pad), n, pad)
end
splural(n::Int) = ifelse(n == 1, "", "s")
splural(c::Vector) = splural(length(c))
function struncate(str::AbstractString, maxwidth::Int, joiner::AbstractString = "", mode::Symbol = :center)
textwidth(str) <= maxwidth && return str
left, right = firstindex(str) - 1, lastindex(str) + 1
width = textwidth(joiner)
while width < maxwidth
if mode (:right, :center)
left = nextind(str, left)
width += textwidth(str[left])
end
if mode (:left, :center) && width < maxwidth
right = prevind(str, right)
width += textwidth(str[right])
end
end
str[begin:left] * joiner * str[right:end]
end
function columnlist(io::IO, entries::Vector{<:AbstractString};
maxcols::Int=8, maxwidth::Int=last(displaysize(io)),
prefix::AbstractString = S"{emphasis:•} ", spacing::Int=2)
isempty(entries) && return
thecolumns = Vector{eltype(entries)}[]
thecolwidths = Int[]
for ncols in 1:maxcols
columns = Vector{eltype(entries)}[]
for col in Iterators.partition(entries, div(length(entries), ncols, RoundUp))
push!(columns, collect(col))
end
widths = map.(textwidth, columns)
colwidths = map(maximum, widths)
layoutwidth = sum(colwidths) + ncols * textwidth(prefix) + (ncols - 1) * spacing
if layoutwidth > maxwidth
break
else
thecolumns, thecolwidths = columns, colwidths
end
end
for rnum in 1:length(first(thecolumns))
for cnum in 1:length(thecolumns)
rnum > length(thecolumns[cnum]) && continue
cnum > 1 && print(io, ' '^spacing)
print(io, prefix, rpad(thecolumns[cnum][rnum], thecolwidths[cnum]))
end
println(io)
end
end
function multirow_wrap(io::IO, cells::Matrix{<:AbstractString};
indent::AbstractString = " ", maxwidth::Int=last(displaysize(io)))
widths = map(textwidth, cells)
colwidths = maximum(widths, dims=1)
thiscol = textwidth(indent)
segments = UnitRange{Int}[1:0]
for (i, (col, width)) in enumerate(zip(eachcol(cells), colwidths))
if thiscol + width > maxwidth
push!(segments, last(last(segments))+1:i-1)
thiscol = textwidth(indent) + width
else
thiscol += width
end
end
push!(segments, last(last(segments))+1:size(cells, 2))
filter!(!isempty, segments)
for segment in segments
for row in eachrow(cells[:, segment])
println(io, indent, join(row))
end
end
end
"""
wraplines(content::AnnotatedString, width::Integer = 80, column::Integer = 0)
Wrap `content` into a vector of lines of at most `width` (according to
`textwidth`), with the first line starting at `column`.
"""
function wraplines(content::Union{Annot, SubString{<:Annot}}, width::Integer = 80, column::Integer = 0) where { Annot <: AnnotatedString}
s, lines = String(content), SubString{Annot}[]
i, lastwrap, slen = firstindex(s), 0, ncodeunits(s)
most_recent_break_opportunity = 1
while i < slen
if isspace(s[i]) && s[i] != '\n'
most_recent_break_opportunity = i
elseif s[i] == '\n'
push!(lines, content[nextind(s, lastwrap):prevind(s, i)])
lastwrap = i
column = 0
elseif column >= width && most_recent_break_opportunity > 1
if lastwrap == most_recent_break_opportunity
nextbreak = findfirst(isspace, @view s[nextind(s, lastwrap):end])
if isnothing(nextbreak)
break
else
most_recent_break_opportunity = lastwrap + nextbreak
end
i = most_recent_break_opportunity
else
i = nextind(s, most_recent_break_opportunity)
end
push!(lines, content[nextind(s, lastwrap):prevind(s, most_recent_break_opportunity)])
lastwrap = most_recent_break_opportunity
column = 0
end
column += textwidth(s[i])
i = nextind(s, i)
end
if lastwrap < slen
push!(lines, content[nextind(s, lastwrap):end])
end
lines
end