Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: colorizing printfs



I know I'm late, but I do like a colorful terminal...

Kannan - I think you may be overcomplicating it - the StackExchange
post certainly does! I personally find overly complex parameter
expansion somewhat distasteful. Keep It Simple.

The first part of the top answer is actually preferred, but it was
answered in the context of the original question, rather than "how can
I print colors in ZSH?"

Specifically, line 13 is what you're looking for:
    print -P "%F{$color}$ip%f\n"

print -P is what you probably want - unless you're trying to do
something portable (a.k.a. bash), in which case you can't use autoload
colors or zsh prompt expansion anyways, and should just stick to the
more portable style of ANSI escape codes with 8 or 256 colors or
truecolor modes.

This is the "old fashioned" (portable) way of printing colors:

    printf "\e[32m%s\e[0m\n" "this is green"
    printf "\e[92m%s\e[0m\n" "this is bright green"
    printf "\e[38;5;120m%s\e[0m\n" "this is probably green"
    printf "\e[38;2;0;255;0m%s\e[0m\n" "as green as it gets"

But in ZSH we can just use 'print -P' (see also: print in
zshbuiltins(1)). Note: this doesn't require "autoload colors''

    text="What color is grass?"
    print -P "%F{green}$text%f"

Using "autoload colors":

    autoload -Uz colors && colors
    text="grass is green"
    echo "Did you know, ${fg[green]}${text}${fg[default]} but the sky is not"

Under the hood, all we're doing is emitting "Select Graphic Rendition
(SGR)" terminal control sequences - e.g. "ESC [ ATTR m" where ESC is
one of: \e or \033 or \x1b followed by a literal "[", then an SGR
attribute number and maybe optional parameters separated by a
semi-colon ";", finally ending in the letter "m".

printf-style SGR examples with "autoload colors" associative array and
PROMPT_PERCENT/print -P equivalents:

1. \e[31m = \033[31m = \x1b[31m = red foreground using the terminal's
16 color palette = $fg[red] = $color[red] = %F{red} = %F{1}
2. \e[91m = "bright" red foreground = $fg_bold[red] = %B%F{red} = %F{9}
3. \033[41m = red background = $bg[red] = %K{red} = %K{1}
4. \x1b[38;2;255;0;0m = red foreground using 24-bit (truecolor) RGB
5. \x1b[48;2;255;0;0m = red background using 24-bit (truecolor) RGB
6. \x1b[38;5;196m = red foreground using the terminal's 256 color
palette = %F{196}
7. \e[0m = reset all
foreground/background/bold/italic/underline/blinking = $colors[none]
8. \e[39m = reset foreground color to default = $fg[default] = %f
9. \e[49m = reset background color to default = $bg[default] = %k

A rainbow of resources are available for the color curious:

- README_FIRST.txt: https://en.wikipedia.org/wiki/ANSI_escape_code
- zshcontrib(1) "Other Functions" -
https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#Other-Functions
- zshmisc(1) "Expansion of Prompt Sequences: Visual Effects" -
https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html#Visual-effects
- zshzle(1) "Character Highlighting" -
https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
- zshmodules(1) "zsh/nearcolor module" -
https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-zsh_002fnearcolor-Module
- https://github.com/termstandard/colors
- https://terminalguide.namepad.de/

Rick

Thanks,

Rick


On Sat, May 11, 2024 at 5:19 PM Kannan Varadhan <kvaradhan3@xxxxxxxxx> wrote:
>
>
> On 5/11/24 07:37, Roman Perepelitsa wrote:
>
> On Sat, May 11, 2024 at 4:27 PM Mikael Magnusson <mikachu@xxxxxxxxx> wrote:
>
> On Sat, May 11, 2024 at 2:54 AM Kannan Varadhan <kvaradhan3@xxxxxxxxx> wrote:
>
> ~⦒printf '%s.%s.%s\n' "${(%):-%F{blue}%B}" "test" "${(%):-%b}${(%):-%f}"
> %B}.test.
>
> You probably have a badly made / cargo culted precmd() function
> active.
>
> I am sorry, I did not follow this.
>
> That output is actually expected. The right curly must be escaped.
>
>     printf '%s.%s.%s\n' "${(%):-%F{blue\}%B}" "test" "${(%):-%b}${(%):-%f}"
>
> Yes, this works,
>
> Is this something that I missed in the documentation?
>
> Many useful, useable variants, thank you for these.
>
> However, it's easier to use `print -P`:
>
>     print -P '%F{blue}%Btest%b%f'
>
> Or, when printing $var:
>
>     print -rP '%F{blue}%B'${var//\%/%%}'%b%f'
>
> Alternatively:
>
>     print -Pn '%F{blue}%B'
>     print -rn -- $var
>     print -P '%b%f'
>
> Another alternative:
>
>     print -r -- ${(%):-'%F{blue}%B'${var//\%/%%}'%b%f'}
>
>
> Kannan




Messages sorted by: Reverse Date, Date, Thread, Author