Skip to content

Commit a72cfb7

Browse files
authored
fix some issues with color configuration (#36689)
- `--color=no` did not remove all color in the REPL - color was not fully disabled by default when stdout was a pipe - `--color=yes` did not enable color when stdout was a pipe (fixes #30703)
1 parent 4a43b03 commit a72cfb7

File tree

6 files changed

+33
-17
lines changed

6 files changed

+33
-17
lines changed

base/client.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,13 +371,12 @@ function run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_fil
371371
invokelatest(REPL_MODULE_REF[]) do REPL
372372
term_env = get(ENV, "TERM", @static Sys.iswindows() ? "" : "dumb")
373373
term = REPL.Terminals.TTYTerminal(term_env, stdin, stdout, stderr)
374-
color_set || (global have_color = REPL.Terminals.hascolor(term))
375374
banner && Base.banner(term)
376375
if term.term_type == "dumb"
377376
active_repl = REPL.BasicREPL(term)
378377
quiet || @warn "Terminal not fully functional"
379378
else
380-
active_repl = REPL.LineEditREPL(term, have_color, true)
379+
active_repl = REPL.LineEditREPL(term, get(stdout, :color, false), true)
381380
active_repl.history_file = history_file
382381
end
383382
# Make sure any displays pushed in .julia/config/startup.jl ends up above the
@@ -487,7 +486,7 @@ function _start()
487486
invokelatest(display_error, catch_stack())
488487
exit(1)
489488
end
490-
if is_interactive && have_color === true
489+
if is_interactive && get(stdout, :color, false)
491490
print(color_normal)
492491
end
493492
end

base/libuv.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ function reinit_stdio()
115115
global stdin = init_stdio(ccall(:jl_stdin_stream, Ptr{Cvoid}, ()))
116116
global stdout = init_stdio(ccall(:jl_stdout_stream, Ptr{Cvoid}, ()))
117117
global stderr = init_stdio(ccall(:jl_stderr_stream, Ptr{Cvoid}, ()))
118+
opts = JLOptions()
119+
if opts.color != 0
120+
have_color = (opts.color == 1)
121+
if !isa(stdout, TTY)
122+
global stdout = IOContext(stdout, :color => have_color)
123+
end
124+
if !isa(stderr, TTY)
125+
global stderr = IOContext(stderr, :color => have_color)
126+
end
127+
end
118128
nothing
119129
end
120130

stdlib/REPL/src/LineEdit.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf
395395
regstart, regstop = region(buf)
396396
written = 0
397397
# Write out the prompt string
398-
lindent = write_prompt(termbuf, prompt)
398+
lindent = write_prompt(termbuf, prompt, hascolor(terminal))
399399
# Count the '\n' at the end of the line if the terminal emulator does (specific to DOS cmd prompt)
400400
miscountnl = @static Sys.iswindows() ? (isa(Terminals.pipe_reader(terminal), Base.TTY) && !Base.ispty(Terminals.pipe_reader(terminal))) : false
401401

@@ -1259,15 +1259,15 @@ refresh_line(s, termbuf) = refresh_multi_line(termbuf, s)
12591259
default_completion_cb(::IOBuffer) = []
12601260
default_enter_cb(_) = true
12611261

1262-
write_prompt(terminal, s::PromptState) = write_prompt(terminal, s.p)
1262+
write_prompt(terminal, s::PromptState, color::Bool) = write_prompt(terminal, s.p, color)
12631263

1264-
function write_prompt(terminal, p::Prompt)
1264+
function write_prompt(terminal, p::Prompt, color::Bool)
12651265
prefix = prompt_string(p.prompt_prefix)
12661266
suffix = prompt_string(p.prompt_suffix)
12671267
write(terminal, prefix)
1268-
write(terminal, Base.text_colors[:bold])
1269-
width = write_prompt(terminal, p.prompt)
1270-
write(terminal, Base.text_colors[:normal])
1268+
color && write(terminal, Base.text_colors[:bold])
1269+
width = write_prompt(terminal, p.prompt, color)
1270+
color && write(terminal, Base.text_colors[:normal])
12711271
write(terminal, suffix)
12721272
return width
12731273
end
@@ -1303,7 +1303,7 @@ end
13031303
end
13041304

13051305
# returns the width of the written prompt
1306-
function write_prompt(terminal, s::Union{AbstractString,Function})
1306+
function write_prompt(terminal, s::Union{AbstractString,Function}, color::Bool)
13071307
@static Sys.iswindows() && _reset_console_mode()
13081308
promptstr = prompt_string(s)
13091309
write(terminal, promptstr)
@@ -1740,7 +1740,7 @@ end
17401740

17411741
input_string(s::PrefixSearchState) = String(take!(copy(s.response_buffer)))
17421742

1743-
write_prompt(terminal, s::PrefixSearchState) = write_prompt(terminal, s.histprompt.parent_prompt)
1743+
write_prompt(terminal, s::PrefixSearchState, color::Bool) = write_prompt(terminal, s.histprompt.parent_prompt, color)
17441744
prompt_string(s::PrefixSearchState) = prompt_string(s.histprompt.parent_prompt.prompt)
17451745

17461746
terminal(s::PrefixSearchState) = s.terminal

stdlib/REPL/src/REPL.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,15 @@ mutable struct LineEditREPL <: AbstractREPL
436436
last_shown_line_infos::Vector{Tuple{String,Int}}
437437
interface::ModalInterface
438438
backendref::REPLBackendRef
439-
LineEditREPL(t,hascolor,prompt_color,input_color,answer_color,shell_color,help_color,history_file,in_shell,in_help,envcolors) =
439+
function LineEditREPL(t,hascolor,prompt_color,input_color,answer_color,shell_color,help_color,history_file,in_shell,in_help,envcolors)
440+
opts = Options()
441+
opts.hascolor = hascolor
442+
if !hascolor
443+
opts.beep_colors = [""]
444+
end
440445
new(t,hascolor,prompt_color,input_color,answer_color,shell_color,help_color,history_file,in_shell,
441-
in_help,envcolors,false,nothing, Options(), nothing, Tuple{String,Int}[])
446+
in_help,envcolors,false,nothing, opts, nothing, Tuple{String,Int}[])
447+
end
442448
end
443449
outstream(r::LineEditREPL) = r.t
444450
specialdisplay(r::LineEditREPL) = r.specialdisplay
@@ -849,7 +855,8 @@ end
849855

850856
function reset(repl::LineEditREPL)
851857
raw!(repl.t, false)
852-
print(repl.t, Base.text_colors[:normal])
858+
hascolor(repl) && print(repl.t, Base.text_colors[:normal])
859+
nothing
853860
end
854861

855862
function prepare_next(repl::LineEditREPL)

stdlib/REPL/src/Terminals.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ beep(t::UnixTerminal) = write(t.err_stream,"\x7")
152152

153153
Base.displaysize(t::UnixTerminal) = displaysize(t.out_stream)
154154

155-
hascolor(t::TTYTerminal) = Base.ttyhascolor(t.term_type)
155+
hascolor(t::TTYTerminal) = get(t.out_stream, :color, false)::Bool
156156

157157
# use cached value of have_color
158158
Base.in(key_value::Pair, t::TTYTerminal) = in(key_value, pipe_writer(t))

stdlib/REPL/test/repl.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ end
9090
# in the mix. If verification needs to be done, keep it to the bare minimum. Basically
9191
# this should make sure nothing crashes without depending on how exactly the control
9292
# characters are being used.
93-
fake_repl(options = REPL.Options(confirm_exit=false,hascolor=false)) do stdin_write, stdout_read, repl
93+
fake_repl(options = REPL.Options(confirm_exit=false,hascolor=true)) do stdin_write, stdout_read, repl
9494
repl.specialdisplay = REPL.REPLDisplay(repl)
9595
repl.history_file = false
9696

@@ -1279,7 +1279,7 @@ end
12791279
repl.backendref = REPL.REPLBackendRef(Channel(1), Channel(1))
12801280
put!(repl.backendref.response_channel, (bt, true))
12811281

1282-
REPL.print_response(repl, (err, true), true, false)
1282+
REPL.print_response(repl, (bt, true), true, false)
12831283
seekstart(out_stream)
12841284
@test count(
12851285
contains(

0 commit comments

Comments
 (0)