Packages
io_ansi_table
0.4.2
1.0.40
1.0.39
1.0.38
1.0.37
1.0.36
1.0.34
1.0.33
1.0.32
1.0.31
1.0.30
1.0.29
1.0.28
1.0.27
1.0.26
1.0.25
1.0.24
1.0.23
1.0.22
1.0.21
1.0.20
1.0.19
1.0.18
1.0.17
1.0.16
1.0.15
1.0.14
1.0.13
1.0.12
1.0.11
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.4.32
0.4.31
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.29
0.3.28
0.3.27
0.3.26
0.3.25
0.3.24
0.3.23
0.3.22
0.3.21
0.3.20
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Writes data to "stdio" in a table with borders and colors. Can choose a table style to change the look of the table.
Current section
Files
Jump to
Current section
Files
lib/io/ansi/plus.ex
defmodule IO.ANSI.Plus do
# @moduledoc """
# Functionality to render ANSI escape sequences.
# [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code)
# are characters embedded in text used to control formatting, color, and
# other output options on video text terminals.
# """
@moduledoc false
use PersistConfig
import IO.ANSI.Sequence
@type ansicode :: atom
@type ansilist ::
maybe_improper_list(
char | ansicode | binary | ansilist,
binary | ansicode | []
)
@type ansidata :: ansilist | ansicode | binary
@color_codes Application.get_env(@app, :color_codes)
@doc """
Checks if ANSI coloring is supported and enabled on this machine.
This function simply reads the configuration value for
`:ansi_enabled` in the `:elixir` application. The value is by
default `false` unless Elixir can detect during startup that
both `stdout` and `stderr` are terminals.
"""
@spec enabled? :: boolean
def enabled? do
Application.get_env(:elixir, :ansi_enabled, false)
end
@doc "Sets foreground color."
@spec color(0..255) :: String.t()
def color(code) when code in 0..255, do: "\e[38;5;#{code}m"
@doc ~S"""
Sets the foreground color from individual RGB values.
Valid values for each color are in the range 0 to 5.
"""
@spec color(0..5, 0..5, 0..5) :: String.t()
def color(r, g, b) when r in 0..5 and g in 0..5 and b in 0..5 do
color(16 + 36 * r + 6 * g + b)
end
@doc "Sets background color."
@spec color_background(0..255) :: String.t()
def color_background(code) when code in 0..255, do: "\e[48;5;#{code}m"
@doc ~S"""
Sets the background color from individual RGB values.
Valid values for each color are in the range 0 to 5.
"""
@spec color_background(0..5, 0..5, 0..5) :: String.t()
def color_background(r, g, b) when r in 0..5 and g in 0..5 and b in 0..5 do
color_background(16 + 36 * r + 6 * g + b)
end
@doc "Resets all attributes."
defsequence(:reset, 0)
@doc "Bright (increased intensity) or bold."
defsequence(:bright, 1)
@doc "Faint (decreased intensity). Not widely supported."
defsequence(:faint, 2)
@doc "Italic: on. Not widely supported. Sometimes treated as inverse."
defsequence(:italic, 3)
@doc "Underline: single."
defsequence(:underline, 4)
@doc "Blink: slow. Less than 150 per minute."
defsequence(:blink_slow, 5)
@doc """
Blink: rapid. MS-DOS ANSI.SYS; 150 per minute or more; not widely supported.
"""
defsequence(:blink_rapid, 6)
@doc "Image: negative. Swap foreground and background."
defsequence(:inverse, 7)
@doc "Image: negative. Swap foreground and background."
defsequence(:reverse, 7)
@doc "Conceal. Not widely supported."
defsequence(:conceal, 8)
@doc """
Crossed-out. Characters legible, but marked for deletion.
Not widely supported.
"""
defsequence(:crossed_out, 9)
@doc "Sets primary (default) font."
defsequence(:primary_font, 10)
for font_n <- [1, 2, 3, 4, 5, 6, 7, 8, 9] do
@doc "Sets alternative font #{font_n}."
defsequence(:"font_#{font_n}", font_n + 10)
end
@doc "Normal color or intensity."
defsequence(:normal, 22)
@doc "Not italic."
defsequence(:not_italic, 23)
@doc "Underline: none."
defsequence(:no_underline, 24)
@doc "Blink: off."
defsequence(:blink_off, 25)
@doc "Image: positive. Normal foreground and background."
defsequence(:inverse_off, 27)
@doc "Image: positive. Normal foreground and background."
defsequence(:reverse_off, 27)
colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]
for {color, code} <- Enum.with_index(colors) do
@doc "Sets foreground color to #{color}."
defsequence(color, code + 30)
@doc "Sets foreground color to light #{color}."
defsequence(:"light_#{color}", code + 90)
@doc "Sets background color to #{color}."
defsequence(:"#{color}_background", code + 40)
@doc "Sets background color to light #{color}."
defsequence(:"light_#{color}_background", code + 100)
end
## Beginning of enhancements
for code <- 0..255 do
# def color0(), do: "\e[38;5;0m"
# defp format_sequence(:color0), do: color0()
defsequence(:"color#{code}", "38;5;#{code}")
# def color0_background(), do: "\e[48;5;0m"
# defp format_sequence(:color0_background), do: color0_background()
defsequence(:"color#{code}_background", "48;5;#{code}")
end
for {color, code} <- @color_codes do
# def chartreuse(), do: "\e[38;5;118m"
# defp format_sequence(:chartreuse), do: chartreuse()
defsequence(color, "38;5;#{code}")
# def chartreuse_background(), do: "\e[48;5;118m"
# defp format_sequence(:chartreuse_background), do: chartreuse_background()
defsequence(:"#{color}_background", "48;5;#{code}")
end
## End of enhancements
@doc "Default text color."
defsequence(:default_color, 39)
@doc "Default background color."
defsequence(:default_background, 49)
@doc "Framed."
defsequence(:framed, 51)
@doc "Encircled."
defsequence(:encircled, 52)
@doc "Overlined."
defsequence(:overlined, 53)
@doc "Not framed or encircled."
defsequence(:not_framed_encircled, 54)
@doc "Not overlined."
defsequence(:not_overlined, 55)
@doc "Sends cursor home."
defsequence(:home, "", "H")
@doc "Clears screen."
defsequence(:clear, "2", "J")
@doc "Clears line."
defsequence(:clear_line, "2", "K")
defp format_sequence(other) do
raise ArgumentError,
"invalid ANSI sequence specification: #{inspect(other)}"
end
@doc ~S"""
Formats a chardata-like argument by converting named ANSI sequences into
actual ANSI codes.
The named sequences are represented by atoms.
It will also append an `IO.ANSI.reset/0` to the chardata when a conversion is
performed. If you don't want this behaviour, use `format_fragment/2`.
An optional boolean parameter can be passed to enable or disable
emitting actual ANSI codes. When `false`, no ANSI codes will emitted.
By default checks if ANSI is enabled using the `enabled?/0` function.
## Examples
iex> IO.ANSI.Plus.format(["Hello, ", :red, :bright, "world!"], true)
[[[[[[], "Hello, "] | "\e[31m"] | "\e[1m"], "world!"] | "\e[0m"]
"""
def format(chardata, emit? \\ enabled?()) when is_boolean(emit?) do
do_format(chardata, [], [], emit?, :maybe)
end
@doc ~S"""
Formats a chardata-like argument by converting named ANSI sequences into
actual ANSI codes.
The named sequences are represented by atoms.
An optional boolean parameter can be passed to enable or disable
emitting actual ANSI codes. When `false`, no ANSI codes will emitted.
By default checks if ANSI is enabled using the `enabled?/0` function.
## Examples
iex> IO.ANSI.Plus.format_fragment([:bright, 'Word'], true)
[[[[[[] | "\e[1m"], 87], 111], 114], 100]
"""
def format_fragment(chardata, emit? \\ enabled?()) when is_boolean(emit?) do
do_format(chardata, [], [], emit?, false)
end
defp do_format([term | rest], rem, acc, emit?, append_reset) do
do_format(term, [rest | rem], acc, emit?, append_reset)
end
defp do_format(term, rem, acc, true, append_reset) when is_atom(term) do
do_format([], rem, [acc | format_sequence(term)], true, !!append_reset)
end
defp do_format(term, rem, acc, false, append_reset) when is_atom(term) do
do_format([], rem, acc, false, append_reset)
end
defp do_format(term, rem, acc, emit?, append_reset) when not is_list(term) do
do_format([], rem, [acc, term], emit?, append_reset)
end
defp do_format([], [next | rest], acc, emit?, append_reset) do
do_format(next, rest, acc, emit?, append_reset)
end
defp do_format([], [], acc, true, true) do
[acc | IO.ANSI.reset()]
end
defp do_format([], [], acc, _emit?, _append_reset) do
acc
end
end