Skip to content
Draft
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
2 changes: 1 addition & 1 deletion base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ function run_std_repl(REPL::Module, quiet::Bool, banner::Symbol, history_file::B
repl = REPL.BasicREPL(term)
quiet || @warn "Terminal not fully functional"
else
repl = REPL.LineEditREPL(term, get(stdout, :color, false), true)
repl = REPL.LineEditREPL(term, get(stdout, :color, false))
repl.history_file = history_file
end
# Make sure any displays pushed in .julia/config/startup.jl ends up above the
Expand Down
10 changes: 0 additions & 10 deletions doc/src/manual/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,16 +443,6 @@ should have at the terminal.
The formatting `Base.info_color()` (default: cyan, `"\033[36m"`) that info
should have at the terminal.

### [`JULIA_INPUT_COLOR`](@id JULIA_INPUT_COLOR)

The formatting `Base.input_color()` (default: normal, `"\033[0m"`) that input
should have at the terminal.

### [`JULIA_ANSWER_COLOR`](@id JULIA_ANSWER_COLOR)

The formatting `Base.answer_color()` (default: normal, `"\033[0m"`) that output
should have at the terminal.

### [`NO_COLOR`](@id NO_COLOR)

When this variable is present and not an empty string (regardless of its value) then colored
Expand Down
57 changes: 32 additions & 25 deletions stdlib/REPL/docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -710,43 +710,51 @@ inherit = "julia_rainbow_curly_2"

For a complete list of customizable faces, see the [JuliaSyntaxHighlighting package documentation](https://julialang.github.io/JuliaSyntaxHighlighting.jl/dev/).

## Customizing Colors
## Customizing prompts

The text and colors of the REPL prompts can be customized by setting the `prompt` and `output_prefix`
fields on the `repl` object within an [`atreplinit`](@ref) hook in your `~/.julia/config/startup.jl` file.

The colors used by Julia and the REPL can be customized, as well. To change the
color of the Julia prompt you can add something like the following to your
`~/.julia/config/startup.jl` file, which is to be placed inside your home directory:
Use styled strings to customize the prompt text and colors:

```julia
function customize_colors(repl)
repl.prompt_color = Base.text_colors[:cyan]
end
using StyledStrings

atreplinit(customize_colors)
atreplinit() do repl
repl.prompt = styled"{cyan:myprompt>} "
repl.output_prefix = styled"{red:=>} "
end
```

The available color keys can be seen by typing `Base.text_colors` in the help mode of the REPL.
In addition, the integers 0 to 255 can be used as color keys for terminals
with 256 color support.
The prompt can also be a plain string or a function for dynamic prompts.
Dynamic prompts can be combined with styling:

You can also change the colors for the help and shell prompts and
input and answer text by setting the appropriate field of `repl` in the `customize_colors` function
above (respectively, `help_color`, `shell_color`, `input_color`, and `answer_color`). For the
latter two, be sure that the `envcolors` field is also set to false.
```julia
using StyledStrings
using Dates

It is also possible to apply boldface formatting by using
`Base.text_colors[:bold]` as a color. For instance, to print answers in
boldface font, one can use the following as a `~/.julia/config/startup.jl`:
atreplinit() do repl
# Dynamic prompt with time
repl.output_prefix = () -> string(Dates.format(Dates.now(), "HH:MM:SS"), "> ")

```julia
function customize_colors(repl)
repl.envcolors = false
repl.answer_color = Base.text_colors[:bold]
# Dynamic prompt with Julia version and styling
repl.prompt = () -> styled"{bold,magenta:julia v$(VERSION)>} "
end
```

To customize other REPL modes (shell, help, pkg), set the corresponding prompt fields:

atreplinit(customize_colors)
```julia
using StyledStrings
atreplinit() do repl
repl.shell_prompt = styled"{green:shell>} "
repl.help_prompt = styled"{magenta:help?} "
end
```

You can also customize the color used to render warning and informational messages by
## Customizing Colors

You can customize the color used to render warning and informational messages by
setting the appropriate environment variables. For instance, to render error, warning, and informational
messages respectively in magenta, yellow, and cyan you can add the following to your
`~/.julia/config/startup.jl` file:
Expand All @@ -757,7 +765,6 @@ ENV["JULIA_WARN_COLOR"] = :yellow
ENV["JULIA_INFO_COLOR"] = :cyan
```


## Changing the contextual module which is active at the REPL

When entering expressions at the REPL, they are by default evaluated in the `Main` module;
Expand Down
71 changes: 35 additions & 36 deletions stdlib/REPL/src/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,9 @@ end

mutable struct Prompt <: TextInterface
# A string or function to be printed as the prompt.
prompt::Union{String,Function}
# A string or function to be printed before the prompt. May not change the length of the prompt.
# This may be used for changing the color, issuing other terminal escape codes, etc.
prompt_prefix::Union{String,Function}
# Same as prefix except after the prompt
prompt_suffix::Union{String,Function}
output_prefix::Union{String,Function}
output_prefix_prefix::Union{String,Function}
output_prefix_suffix::Union{String,Function}
prompt::Union{AbstractString,Function}
# A string or function to be printed before a returned result.
output_prefix::Union{AbstractString,Function}
keymap_dict::Dict{Char,Any}
repl::Union{AbstractREPL,Nothing}
complete::CompletionProvider
Expand Down Expand Up @@ -220,17 +214,32 @@ function beep(s::PromptState, duration::Real=options(s).beep_duration,
errormonitor(@async begin
trylock(s.refresh_lock) || return
try
orig_prefix = s.p.prompt_prefix
use_current && push!(colors, prompt_string(orig_prefix))
orig_prompt = s.p.prompt
orig_prompt_str = prompt_string(orig_prompt)
# Extract plain text to wrap in face during beep flash
plain_prompt_str = if orig_prompt_str isa StyledStrings.AnnotatedString
String(orig_prompt_str)
elseif orig_prompt_str isa AbstractString
orig_prompt_str
else
string(orig_prompt_str)
end
use_current && push!(colors, :default)
i = 0
while s.beeping > 0.0
prefix = colors[mod1(i+=1, end)]
s.p.prompt_prefix = prefix
face = colors[mod1(i+=1, end)]
# Temporarily change prompt for visual bell effect
if face === :default
s.p.prompt = orig_prompt
else
beep_prompt_str = StyledStrings.styled"{$face:$plain_prompt_str}"
s.p.prompt = () -> beep_prompt_str
end
refresh_multi_line(s, beeping=true)
sleep(blink)
s.beeping -= blink
end
s.p.prompt_prefix = orig_prefix
s.p.prompt = orig_prompt
refresh_multi_line(s, beeping=true)
s.beeping = 0.0
finally
Expand Down Expand Up @@ -1039,7 +1048,7 @@ function edit_insert(s::PromptState, c::StringLike)
termbuf = terminal(s)
w = width(termbuf)
offset = s.ias.curs_row == 1 || s.indent < 0 ?
sizeof(prompt_string(s.p.prompt)::String) : s.indent
textwidth(prompt_string(s.p.prompt)) : s.indent
offset += position(buf) - beginofline(buf) # size of current line
spinner = '\0'
delayup = !eof(buf) || old_wait
Expand Down Expand Up @@ -1707,24 +1716,12 @@ default_enter_cb(_) = true

write_prompt(terminal::AbstractTerminal, s::PromptState, color::Bool) = write_prompt(terminal, s.p, color)
function write_prompt(terminal::AbstractTerminal, p::Prompt, color::Bool)
prefix = prompt_string(p.prompt_prefix)
suffix = prompt_string(p.prompt_suffix)
write(terminal, prefix)
color && write(terminal, Base.text_colors[:bold])
width = write_prompt(terminal, p.prompt, color)
color && write(terminal, Base.text_colors[:normal])
write(terminal, suffix)
return width
end

function write_output_prefix(io::IO, p::Prompt, color::Bool)
prefix = prompt_string(p.output_prefix_prefix)
suffix = prompt_string(p.output_prefix_suffix)
print(io, prefix)
color && write(io, Base.text_colors[:bold])
width = write_prompt(io, p.output_prefix, color)
color && write(io, Base.text_colors[:normal])
print(io, suffix)
return width
end

Expand Down Expand Up @@ -1766,8 +1763,8 @@ end

# returns the width of the written prompt
function write_prompt(terminal::Union{IO, AbstractTerminal}, s::Union{AbstractString,Function}, color::Bool)
promptstr = prompt_string(s)::String
write(terminal, promptstr)
promptstr = prompt_string(s)
write(IOContext(terminal, :color => color), promptstr)
return textwidth(promptstr)
end

Expand Down Expand Up @@ -2863,21 +2860,23 @@ const default_keymap_dict = keymap([default_keymap, escape_defaults])

function Prompt(prompt
;
prompt_prefix = "",
prompt_suffix = "",
output_prefix = "",
output_prefix_prefix = "",
output_prefix_suffix = "",
keymap_dict = default_keymap_dict,
repl = nothing,
complete = EmptyCompletionProvider(),
on_enter = default_enter_cb,
on_done = ()->nothing,
hist = EmptyHistoryProvider(),
sticky = false,
styling_passes = StylingPass[])

return Prompt(prompt, prompt_prefix, prompt_suffix, output_prefix, output_prefix_prefix, output_prefix_suffix,
styling_passes = StylingPass[],
# Deprecated keyword arguments - accepted for backwards compatibility but ignored
# Use AnnotatedString with face annotations for colored prompts instead
prompt_prefix = nothing,
prompt_suffix = nothing,
output_prefix_prefix = nothing,
output_prefix_suffix = nothing)

return Prompt(prompt, output_prefix,
keymap_dict, repl, complete, on_enter, on_done, hist, sticky, styling_passes)
end

Expand Down
Loading