Skip to content

Commit 0f4d783

Browse files
committed
Make the REPL banner resize to avoid wrapping
We also spritz it up a bit using the new StyledStrings library, namely: - colouring the Help and Pkg key prompts - making the docs link a terminal link, and Pkg a link to the Pkg docs - using box drawing characters for the dividing line - making branch status more colourful - making the official version text more subdued With these change the four banners (from smallest to largest) are: 1. A one-liner, for extreme circumstances (new) 2. The short banner 3. The large banner, with the description stacked vertically (new) 4. The large banner, with the description stacked horizontally
1 parent df3fe22 commit 0f4d783

File tree

5 files changed

+120
-81
lines changed

5 files changed

+120
-81
lines changed

base/client.jl

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ function run_main_repl(interactive::Bool, quiet::Bool, banner::Symbol, history_f
431431
invokelatest(REPL_MODULE_REF[]) do REPL
432432
term_env = get(ENV, "TERM", @static Sys.iswindows() ? "" : "dumb")
433433
term = REPL.Terminals.TTYTerminal(term_env, stdin, stdout, stderr)
434-
banner == :no || REPL.banner(term, short=banner==:short)
434+
banner == :no || REPL.banner(term, banner)
435435
if term.term_type == "dumb"
436436
repl = REPL.BasicREPL(term)
437437
quiet || @warn "Terminal not fully functional"
@@ -556,12 +556,26 @@ end
556556
function repl_main(_)
557557
opts = Base.JLOptions()
558558
interactiveinput = isa(stdin, Base.TTY)
559-
b = opts.banner
560-
auto = b == -1
561-
banner = b == 0 || (auto && !interactiveinput) ? :no :
562-
b == 1 || (auto && interactiveinput) ? :yes :
563-
:short # b == 2
564-
559+
bval = if opts.banner == -1 # Auto
560+
Int(interactiveinput)
561+
else
562+
opts.banner
563+
end
564+
# All the options produced by `jloptions.c`'s `case opt_banner`.
565+
# 0=off, 1=largest, ..., N=smallest
566+
banner = if bval == 0
567+
:no
568+
elseif bval == 1
569+
:full
570+
elseif bval == 2
571+
:narrow
572+
elseif bval == 3
573+
:short
574+
elseif bval == 4
575+
:tiny
576+
else # For type stability of `banner`
577+
:unreachable
578+
end
565579
quiet = (opts.quiet != 0)
566580
history_file = (opts.historyfile != 0)
567581
return run_main_repl(interactiveinput, quiet, banner, history_file)

src/jloptions.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ static const char opts[] =
171171
" -i, --interactive Interactive mode; REPL runs and\n"
172172
" `isinteractive()` is true.\n"
173173
" -q, --quiet Quiet startup: no banner, suppress REPL warnings\n"
174-
" --banner={yes|no|short|auto*} Enable or disable startup banner\n"
174+
" --banner={yes|no|auto*|<size>} Enable or disable startup banner, or specify a\n"
175+
" preferred <size> (tiny, short, narrow, or full).\n"
175176
" --color={yes|no|auto*} Enable or disable color text\n"
176177
" --history-file={yes*|no} Load or save history\n\n"
177178

@@ -495,16 +496,22 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
495496
jl_options.banner = 0;
496497
break;
497498
case opt_banner: // banner
498-
if (!strcmp(optarg, "yes"))
499-
jl_options.banner = 1;
499+
if (!strcmp(optarg, "auto"))
500+
jl_options.banner = -1;
500501
else if (!strcmp(optarg, "no"))
501502
jl_options.banner = 0;
502-
else if (!strcmp(optarg, "auto"))
503-
jl_options.banner = -1;
504-
else if (!strcmp(optarg, "short"))
503+
else if (!strcmp(optarg, "yes"))
504+
jl_options.banner = 1;
505+
else if (!strcmp(optarg, "full"))
506+
jl_options.banner = 1; // Same as "yes".
507+
else if (!strcmp(optarg, "narrow"))
505508
jl_options.banner = 2;
509+
else if (!strcmp(optarg, "short"))
510+
jl_options.banner = 3;
511+
else if (!strcmp(optarg, "tiny"))
512+
jl_options.banner = 4;
506513
else
507-
jl_errorf("julia: invalid argument to --banner={yes|no|auto|short} (%s)", optarg);
514+
jl_errorf("julia: invalid argument to --banner={yes|no|auto|full|narrow|short|tiny} (%s)", optarg);
508515
break;
509516
case opt_sysimage_native_code:
510517
if (!strcmp(optarg,"yes"))

stdlib/REPL/src/REPL.jl

Lines changed: 68 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,11 +1688,21 @@ ends_with_semicolon(code::AbstractString) = ends_with_semicolon(String(code))
16881688
ends_with_semicolon(code::Union{String,SubString{String}}) =
16891689
contains(_rm_strings_and_comments(code), r";\s*$")
16901690

1691-
function banner(io::IO = stdout; short = false)
1692-
if Base.GIT_VERSION_INFO.tagged_commit
1693-
commit_string = Base.TAGGED_RELEASE_BANNER
1691+
"""
1692+
banner(io::IO = stdout, preferred::Symbol = :full)
1693+
1694+
Print the "Julia" informative banner to `io`, using the `preferred` variant
1695+
if reasonable and known.
1696+
1697+
!!! warning
1698+
The particular banner selected by `preferred` is liable to being changed
1699+
without warning. The current variants are: `:tiny`, `:short`, `:narrow`, and `:full`.
1700+
"""
1701+
function banner(io::IO = stdout, preferred::Symbol = :full)
1702+
commit_string = if Base.GIT_VERSION_INFO.tagged_commit
1703+
Base.AnnotatedString(TAGGED_RELEASE_BANNER, :face => :shadow)
16941704
elseif isempty(Base.GIT_VERSION_INFO.commit)
1695-
commit_string = ""
1705+
styled""
16961706
else
16971707
days = Int(floor((ccall(:jl_clock_now, Float64, ()) - Base.GIT_VERSION_INFO.fork_master_timestamp) / (60 * 60 * 24)))
16981708
days = max(0, days)
@@ -1701,60 +1711,65 @@ function banner(io::IO = stdout; short = false)
17011711
commit = Base.GIT_VERSION_INFO.commit_short
17021712

17031713
if distance == 0
1704-
commit_string = "Commit $(commit) ($(days) $(unit) old master)"
1714+
styled"""Commit {grey:$commit} \
1715+
({warning:⌛ {italic:$days $unit}} old master)"""
17051716
else
17061717
branch = Base.GIT_VERSION_INFO.branch
1707-
commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))"
1718+
styled"""{emphasis:$branch}/{grey:$commit} \
1719+
({italic:{success:{bold,(slant=normal):↑} $distance commits}, \
1720+
{warning:{(slant=normal):⌛} $days $unit}})"""
17081721
end
17091722
end
17101723

1711-
commit_date = isempty(Base.GIT_VERSION_INFO.date_string) ? "" : " ($(split(Base.GIT_VERSION_INFO.date_string)[1]))"
1712-
1713-
if get(io, :color, false)::Bool
1714-
c = Base.text_colors
1715-
tx = c[:normal] # text
1716-
jl = c[:normal] # julia
1717-
d1 = c[:bold] * c[:blue] # first dot
1718-
d2 = c[:bold] * c[:red] # second dot
1719-
d3 = c[:bold] * c[:green] # third dot
1720-
d4 = c[:bold] * c[:magenta] # fourth dot
1721-
1722-
if short
1723-
print(io,"""
1724-
$(d3)o$(tx) | Version $(VERSION)$(commit_date)
1725-
$(d2)o$(tx) $(d4)o$(tx) | $(commit_string)
1726-
""")
1727-
else
1728-
print(io,""" $(d3)_$(tx)
1729-
$(d1)_$(tx) $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | Documentation: https://docs.julialang.org
1730-
$(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) |
1731-
$(jl)_ _ _| |_ __ _$(tx) | Type \"?\" for help, \"]?\" for Pkg help.
1732-
$(jl)| | | | | | |/ _` |$(tx) |
1733-
$(jl)| | |_| | | | (_| |$(tx) | Version $(VERSION)$(commit_date)
1734-
$(jl)_/ |\\__'_|_|_|\\__'_|$(tx) | $(commit_string)
1735-
$(jl)|__/$(tx) |
1736-
1737-
""")
1738-
end
1739-
else
1740-
if short
1741-
print(io,"""
1742-
o | Version $(VERSION)$(commit_date)
1743-
o o | $(commit_string)
1744-
""")
1745-
else
1746-
print(io,"""
1747-
_
1748-
_ _ _(_)_ | Documentation: https://docs.julialang.org
1749-
(_) | (_) (_) |
1750-
_ _ _| |_ __ _ | Type \"?\" for help, \"]?\" for Pkg help.
1751-
| | | | | | |/ _` | |
1752-
| | |_| | | | (_| | | Version $(VERSION)$(commit_date)
1753-
_/ |\\__'_|_|_|\\__'_| | $(commit_string)
1754-
|__/ |
1755-
1756-
""")
1757-
end
1724+
commit_date = isempty(Base.GIT_VERSION_INFO.date_string) ? "" : styled" {light:($(split(Base.GIT_VERSION_INFO.date_string)[1]))}"
1725+
doclink = styled"{bold:Documentation:} {(underline=grey),link={https://docs.julialang.org}:https://docs.julialang.org}"
1726+
help = styled"Type {repl_prompt_help:?} for help, {repl_prompt_pkg:]?} for {(underline=grey),link={https://pkgdocs.julialang.org/}:Pkg} help."
1727+
1728+
sizenames = (:tiny, :short, :narrow, :full)
1729+
maxsize = something(findfirst(==(preferred), sizenames), length(sizenames))
1730+
size = min(if all(displaysize(io) .>= (8, 70)); 4 # Full size
1731+
elseif all(displaysize(io) .>= (8, 45)); 3 # Narrower
1732+
elseif all(displaysize(io) .>= (3, 50)); 2 # Tiny
1733+
else 1 end,
1734+
max(0, maxsize))
1735+
1736+
if size == 4 # Full size
1737+
print(io, styled"""
1738+
{bold,green:_}
1739+
{bold,blue:_} _ {bold:{red:_}{green:(_)}{magenta:_}} {shadow:│} $doclink
1740+
{bold,blue:(_)} | {bold:{red:(_)} {magenta:(_)}} {shadow:│}
1741+
_ _ _| |_ __ _ {shadow:│} $help
1742+
| | | | | | |/ _` | {shadow:│}
1743+
| | |_| | | | (_| | {shadow:│} Version {bold:$VERSION}$commit_date
1744+
_/ |\\__'_|_|_|\\__'_| {shadow:│} $commit_string
1745+
|__/ {shadow:│}
1746+
\n""")
1747+
elseif size == 3 # Rotated
1748+
print(io, styled"""
1749+
{bold,green:_}
1750+
{bold,blue:_} _ {bold:{red:_}{green:(_)}{magenta:_}}
1751+
{bold,blue:(_)} | {bold:{red:(_)} {magenta:(_)}}
1752+
_ _ _| |_ __ _
1753+
| | | | | | |/ _` |
1754+
| | |_| | | | (_| |
1755+
_/ |\\__'_|_|_|\\__'_|
1756+
|__/
1757+
1758+
$doclink
1759+
$help
1760+
1761+
Version {bold:$VERSION}$commit_date
1762+
$commit_string
1763+
\n""")
1764+
elseif size == 2 # Tiny
1765+
print(io, styled"""
1766+
{bold,green:o} {shadow:│} Version {bold:$VERSION}$commit_date
1767+
{bold:{red:o} {magenta:o}} {shadow:│} $commit_string
1768+
""", ifelse(displaysize(io) > (12, 0), "\n", ""))
1769+
elseif size == 1 && Base.GIT_VERSION_INFO.tagged_commit # Text only
1770+
print(io, styled"""{bold:{blue:∴} {magenta:Julia} $VERSION}$commit_date\n""")
1771+
elseif size == 1 # Text only
1772+
print(io, styled"""{bold:{blue:∴} {magenta:Julia} $VERSION}$commit_date $commit_string\n""")
17581773
end
17591774
end
17601775

stdlib/REPL/test/repl.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,9 +1952,9 @@ let io = IOBuffer()
19521952
seek(io, 0)
19531953
@test countlines(io) == 9
19541954
take!(io)
1955-
@test REPL.banner(io; short=true) === nothing
1955+
@test REPL.banner(io, :tiny) === nothing
19561956
seek(io, 0)
1957-
@test countlines(io) == 2
1957+
@test countlines(io) == 1
19581958
end
19591959

19601960
@testset "Docstrings" begin

test/cmdlineargs.jl

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -263,18 +263,21 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no`
263263

264264
# --quiet, --banner
265265
let p = "print((Base.JLOptions().quiet, Base.JLOptions().banner))"
266-
@test read(`$exename -e $p`, String) == "(0, -1)"
267-
@test read(`$exename -q -e $p`, String) == "(1, 0)"
268-
@test read(`$exename --quiet -e $p`, String) == "(1, 0)"
269-
@test read(`$exename --banner=no -e $p`, String) == "(0, 0)"
270-
@test read(`$exename --banner=yes -e $p`, String) == "(0, 1)"
271-
@test read(`$exename --banner=short -e $p`, String) == "(0, 2)"
272-
@test read(`$exename -q --banner=no -e $p`, String) == "(1, 0)"
273-
@test read(`$exename -q --banner=yes -e $p`, String) == "(1, 1)"
274-
@test read(`$exename -q --banner=short -e $p`, String) == "(1, 2)"
275-
@test read(`$exename --banner=no -q -e $p`, String) == "(1, 0)"
276-
@test read(`$exename --banner=yes -q -e $p`, String) == "(1, 1)"
277-
@test read(`$exename --banner=short -q -e $p`, String) == "(1, 2)"
266+
@test read(`$exename -e $p`, String) == "(0, -1)"
267+
@test read(`$exename -q -e $p`, String) == "(1, 0)"
268+
@test read(`$exename --quiet -e $p`, String) == "(1, 0)"
269+
@test read(`$exename --banner=auto -e $p`, String) == "(0, -1)"
270+
@test read(`$exename --banner=no -e $p`, String) == "(0, 0)"
271+
@test read(`$exename --banner=yes -e $p`, String) == "(0, 1)"
272+
@test read(`$exename --banner=full -e $p`, String) == "(0, 1)"
273+
@test read(`$exename -q --banner=no -e $p`, String) == "(1, 0)"
274+
@test read(`$exename -q --banner=yes -e $p`, String) == "(1, 1)"
275+
@test read(`$exename -q --banner=tiny -e $p`, String) == "(1, 4)"
276+
@test read(`$exename --banner=no -q -e $p`, String) == "(1, 0)"
277+
@test read(`$exename --banner=yes -q -e $p`, String) == "(1, 1)"
278+
@test read(`$exename --banner=narrow -q -e $p`, String) == "(1, 2)"
279+
@test read(`$exename --banner=short -q -e $p`, String) == "(1, 3)"
280+
@test read(`$exename --banner=tiny -q -e $p`, String) == "(1, 4)"
278281
end
279282

280283
# --home

0 commit comments

Comments
 (0)