Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make banner size depend on terminal size #51811

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ function run_main_repl(interactive::Bool, quiet::Bool, banner::Symbol, history_f
invokelatest(REPL_MODULE_REF[]) do REPL
term_env = get(ENV, "TERM", @static Sys.iswindows() ? "" : "dumb")
term = REPL.Terminals.TTYTerminal(term_env, stdin, stdout, stderr)
banner == :no || REPL.banner(term, short=banner==:short)
banner == :no || REPL.banner(term, banner)
if term.term_type == "dumb"
repl = REPL.BasicREPL(term)
quiet || @warn "Terminal not fully functional"
Expand Down Expand Up @@ -556,12 +556,26 @@ end
function repl_main(_)
opts = Base.JLOptions()
interactiveinput = isa(stdin, Base.TTY)
b = opts.banner
auto = b == -1
banner = b == 0 || (auto && !interactiveinput) ? :no :
b == 1 || (auto && interactiveinput) ? :yes :
:short # b == 2

bval = if opts.banner == -1 # Auto
Int(interactiveinput)
else
opts.banner
end
# All the options produced by `jloptions.c`'s `case opt_banner`.
# 0=off, 1=largest, ..., N=smallest
banner = if bval == 0
:no
elseif bval == 1
:full
elseif bval == 2
:narrow
elseif bval == 3
:short
elseif bval == 4
:tiny
else # For type stability of `banner`
:unreachable
end
quiet = (opts.quiet != 0)
history_file = (opts.historyfile != 0)
return run_main_repl(interactiveinput, quiet, banner, history_file)
Expand Down
21 changes: 14 additions & 7 deletions src/jloptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ static const char opts[] =
" -i, --interactive Interactive mode; REPL runs and\n"
" `isinteractive()` is true.\n"
" -q, --quiet Quiet startup: no banner, suppress REPL warnings\n"
" --banner={yes|no|short|auto*} Enable or disable startup banner\n"
" --banner={yes|no|auto*|<size>} Enable or disable startup banner, or specify a\n"
" preferred <size> (tiny, short, narrow, or full).\n"
" --color={yes|no|auto*} Enable or disable color text\n"
" --history-file={yes*|no} Load or save history\n\n"

Expand Down Expand Up @@ -495,16 +496,22 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
jl_options.banner = 0;
break;
case opt_banner: // banner
if (!strcmp(optarg, "yes"))
jl_options.banner = 1;
if (!strcmp(optarg, "auto"))
jl_options.banner = -1;
else if (!strcmp(optarg, "no"))
jl_options.banner = 0;
else if (!strcmp(optarg, "auto"))
jl_options.banner = -1;
else if (!strcmp(optarg, "short"))
else if (!strcmp(optarg, "yes"))
jl_options.banner = 1;
else if (!strcmp(optarg, "full"))
jl_options.banner = 1; // Same as "yes".
else if (!strcmp(optarg, "narrow"))
jl_options.banner = 2;
else if (!strcmp(optarg, "short"))
jl_options.banner = 3;
else if (!strcmp(optarg, "tiny"))
jl_options.banner = 4;
else
jl_errorf("julia: invalid argument to --banner={yes|no|auto|short} (%s)", optarg);
jl_errorf("julia: invalid argument to --banner={yes|no|auto|full|narrow|short|tiny} (%s)", optarg);
break;
case opt_sysimage_native_code:
if (!strcmp(optarg,"yes"))
Expand Down
121 changes: 68 additions & 53 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1688,11 +1688,21 @@ ends_with_semicolon(code::AbstractString) = ends_with_semicolon(String(code))
ends_with_semicolon(code::Union{String,SubString{String}}) =
contains(_rm_strings_and_comments(code), r";\s*$")

function banner(io::IO = stdout; short = false)
if Base.GIT_VERSION_INFO.tagged_commit
commit_string = Base.TAGGED_RELEASE_BANNER
"""
banner(io::IO = stdout, preferred::Symbol = :full)

Print the "Julia" informative banner to `io`, using the `preferred` variant
if reasonable and known.

!!! warning
The particular banner selected by `preferred` is liable to being changed
without warning. The current variants are: `:tiny`, `:short`, `:narrow`, and `:full`.
"""
function banner(io::IO = stdout, preferred::Symbol = :full)
commit_string = if Base.GIT_VERSION_INFO.tagged_commit
Base.AnnotatedString(TAGGED_RELEASE_BANNER, :face => :shadow)
elseif isempty(Base.GIT_VERSION_INFO.commit)
commit_string = ""
styled""
else
days = Int(floor((ccall(:jl_clock_now, Float64, ()) - Base.GIT_VERSION_INFO.fork_master_timestamp) / (60 * 60 * 24)))
days = max(0, days)
Expand All @@ -1701,60 +1711,65 @@ function banner(io::IO = stdout; short = false)
commit = Base.GIT_VERSION_INFO.commit_short

if distance == 0
commit_string = "Commit $(commit) ($(days) $(unit) old master)"
styled"""Commit {grey:$commit} \
({warning:⌛ {italic:$days $unit}} old master)"""
else
branch = Base.GIT_VERSION_INFO.branch
commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))"
styled"""{emphasis:$branch}/{grey:$commit} \
({italic:{success:{bold,(slant=normal):↑} $distance commits}, \
{warning:{(slant=normal):⌛} $days $unit}})"""
end
end

commit_date = isempty(Base.GIT_VERSION_INFO.date_string) ? "" : " ($(split(Base.GIT_VERSION_INFO.date_string)[1]))"

if get(io, :color, false)::Bool
c = Base.text_colors
tx = c[:normal] # text
jl = c[:normal] # julia
d1 = c[:bold] * c[:blue] # first dot
d2 = c[:bold] * c[:red] # second dot
d3 = c[:bold] * c[:green] # third dot
d4 = c[:bold] * c[:magenta] # fourth dot

if short
print(io,"""
$(d3)o$(tx) | Version $(VERSION)$(commit_date)
$(d2)o$(tx) $(d4)o$(tx) | $(commit_string)
""")
else
print(io,""" $(d3)_$(tx)
$(d1)_$(tx) $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | Documentation: https://docs.julialang.org
$(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) |
$(jl)_ _ _| |_ __ _$(tx) | Type \"?\" for help, \"]?\" for Pkg help.
$(jl)| | | | | | |/ _` |$(tx) |
$(jl)| | |_| | | | (_| |$(tx) | Version $(VERSION)$(commit_date)
$(jl)_/ |\\__'_|_|_|\\__'_|$(tx) | $(commit_string)
$(jl)|__/$(tx) |

""")
end
else
if short
print(io,"""
o | Version $(VERSION)$(commit_date)
o o | $(commit_string)
""")
else
print(io,"""
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type \"?\" for help, \"]?\" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version $(VERSION)$(commit_date)
_/ |\\__'_|_|_|\\__'_| | $(commit_string)
|__/ |

""")
end
commit_date = isempty(Base.GIT_VERSION_INFO.date_string) ? "" : styled" {light:($(split(Base.GIT_VERSION_INFO.date_string)[1]))}"
doclink = styled"{bold:Documentation:} {(underline=grey),link={https://docs.julialang.org}:https://docs.julialang.org}"
help = styled"Type {repl_prompt_help:?} for help, {repl_prompt_pkg:]?} for {(underline=grey),link={https://pkgdocs.julialang.org/}:Pkg} help."

sizenames = (:tiny, :short, :narrow, :full)
maxsize = something(findfirst(==(preferred), sizenames), length(sizenames))
size = min(if all(displaysize(io) .>= (8, 70)); 4 # Full size
elseif all(displaysize(io) .>= (8, 45)); 3 # Narrower
elseif all(displaysize(io) .>= (3, 50)); 2 # Tiny
else 1 end,
max(0, maxsize))

if size == 4 # Full size
print(io, styled"""
{bold,green:_}
{bold,blue:_} _ {bold:{red:_}{green:(_)}{magenta:_}} {shadow:│} $doclink
{bold,blue:(_)} | {bold:{red:(_)} {magenta:(_)}} {shadow:│}
_ _ _| |_ __ _ {shadow:│} $help
| | | | | | |/ _` | {shadow:│}
| | |_| | | | (_| | {shadow:│} Version {bold:$VERSION}$commit_date
_/ |\\__'_|_|_|\\__'_| {shadow:│} $commit_string
|__/ {shadow:│}
\n""")
elseif size == 3 # Rotated
print(io, styled"""
{bold,green:_}
{bold,blue:_} _ {bold:{red:_}{green:(_)}{magenta:_}}
{bold,blue:(_)} | {bold:{red:(_)} {magenta:(_)}}
_ _ _| |_ __ _
| | | | | | |/ _` |
| | |_| | | | (_| |
_/ |\\__'_|_|_|\\__'_|
|__/

$doclink
$help

Version {bold:$VERSION}$commit_date
$commit_string
\n""")
elseif size == 2 # Tiny
print(io, styled"""
{bold,green:o} {shadow:│} Version {bold:$VERSION}$commit_date
{bold:{red:o} {magenta:o}} {shadow:│} $commit_string
""", ifelse(displaysize(io) > (12, 0), "\n", ""))
elseif size == 1 && Base.GIT_VERSION_INFO.tagged_commit # Text only
print(io, styled"""{bold:{blue:∴} {magenta:Julia} $VERSION}$commit_date\n""")
elseif size == 1 # Text only
print(io, styled"""{bold:{blue:∴} {magenta:Julia} $VERSION}$commit_date $commit_string\n""")
end
end

Expand Down
4 changes: 2 additions & 2 deletions stdlib/REPL/test/repl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1952,9 +1952,9 @@ let io = IOBuffer()
seek(io, 0)
@test countlines(io) == 9
take!(io)
@test REPL.banner(io; short=true) === nothing
@test REPL.banner(io, :tiny) === nothing
seek(io, 0)
@test countlines(io) == 2
@test countlines(io) == 1
end

@testset "Docstrings" begin
Expand Down
27 changes: 15 additions & 12 deletions test/cmdlineargs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -263,18 +263,21 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no`

# --quiet, --banner
let p = "print((Base.JLOptions().quiet, Base.JLOptions().banner))"
@test read(`$exename -e $p`, String) == "(0, -1)"
@test read(`$exename -q -e $p`, String) == "(1, 0)"
@test read(`$exename --quiet -e $p`, String) == "(1, 0)"
@test read(`$exename --banner=no -e $p`, String) == "(0, 0)"
@test read(`$exename --banner=yes -e $p`, String) == "(0, 1)"
@test read(`$exename --banner=short -e $p`, String) == "(0, 2)"
@test read(`$exename -q --banner=no -e $p`, String) == "(1, 0)"
@test read(`$exename -q --banner=yes -e $p`, String) == "(1, 1)"
@test read(`$exename -q --banner=short -e $p`, String) == "(1, 2)"
@test read(`$exename --banner=no -q -e $p`, String) == "(1, 0)"
@test read(`$exename --banner=yes -q -e $p`, String) == "(1, 1)"
@test read(`$exename --banner=short -q -e $p`, String) == "(1, 2)"
@test read(`$exename -e $p`, String) == "(0, -1)"
@test read(`$exename -q -e $p`, String) == "(1, 0)"
@test read(`$exename --quiet -e $p`, String) == "(1, 0)"
@test read(`$exename --banner=auto -e $p`, String) == "(0, -1)"
@test read(`$exename --banner=no -e $p`, String) == "(0, 0)"
@test read(`$exename --banner=yes -e $p`, String) == "(0, 1)"
@test read(`$exename --banner=full -e $p`, String) == "(0, 1)"
@test read(`$exename -q --banner=no -e $p`, String) == "(1, 0)"
@test read(`$exename -q --banner=yes -e $p`, String) == "(1, 1)"
@test read(`$exename -q --banner=tiny -e $p`, String) == "(1, 4)"
@test read(`$exename --banner=no -q -e $p`, String) == "(1, 0)"
@test read(`$exename --banner=yes -q -e $p`, String) == "(1, 1)"
@test read(`$exename --banner=narrow -q -e $p`, String) == "(1, 2)"
@test read(`$exename --banner=short -q -e $p`, String) == "(1, 3)"
@test read(`$exename --banner=tiny -q -e $p`, String) == "(1, 4)"
end

# --home
Expand Down