Working with Colors in BCUtils
The BCUtils.ColorFuncs module provides a comprehensive set of functions for working with terminal colors and text effects using ANSI escape codes. This guide covers all the capabilities and features of the module.
Table of Contents
- Overview
 - Basic Usage
 - Color Palette
 - Text Effects
 - Advanced Functions
 - True Color Support
 - Auto-Generated Combinations
 - Practical Examples
 - Best Practices
 - Color Reference
 
Overview
The BCUtils.ColorFuncs module offers:
- 73 named colors from basic ANSI to extended 256-color palette
 - 9 text effects (bold, italic, underline, etc.)
 - True color support (24-bit RGB)
 - Hex color support for web-style colors
 - Auto-generated color combinations for all foreground/background pairs
 - Utility functions for easy color manipulation
 
Basic Usage
Simple Foreground Colors
# Basic usage
ColorFuncs.fg(:red) <> "Red text" <> ColorFuncs.reset()
# With effects
ColorFuncs.fg(:blue, [:bold]) <> "Bold blue text" <> ColorFuncs.reset()
# Multiple effects
ColorFuncs.fg(:green, [:bold, :underline]) <> "Bold underlined green" <> ColorFuncs.reset()Background Colors
# Simple background
ColorFuncs.bg(:yellow) <> "Text on yellow background" <> ColorFuncs.reset()
# Foreground + background
ColorFuncs.fg(:white) <> ColorFuncs.bg(:black) <> "White on black" <> ColorFuncs.reset()Convenience Functions
# Wrap text with automatic reset
ColorFuncs.wrap("Hello World", :purple, [:bold])
# Apply effects only
ColorFuncs.effect(:italic) <> "Italic text" <> ColorFuncs.reset()Color Palette
The module includes 73 carefully selected colors organized into categories:
Standard ANSI Colors (16)
- Basic: 
black,red,green,yellow,blue,magenta,cyan,white - Bright: 
bright_black,bright_red,bright_green,bright_yellow,bright_blue,bright_magenta,bright_cyan,bright_white 
Extended Colors (20)
Popular colors for enhanced aesthetics:
orange,purple,pink,lime,navy,maroon,olive,tealsilver,gold,coral,salmon,khaki,violet,indigo,crimsonforest,sky,rose,mint
Vibrant Colors (20)
Rich, saturated colors:
turquoise,aqua,brown,tan,beige,ivorylavender,plum,orchid,peach,apricot,lemonchartreuse,emerald,jade,sapphire,ruby,amber,bronze,copper
Nature-Inspired Colors (10)
Earth and nature tones:
grass,leaf,ocean,sand,stone,clay,earth,bark,moss,fern
Modern/Tech Colors (10)
Cyberpunk and tech aesthetics:
neon_green,neon_blue,neon_pink,electric,plasmalaser,matrix,cyber,terminal,hacker
Grayscale (12)
Fine-grained grayscale options:
gray1throughgray12(from darkest to lightest)
Text Effects
The module supports 9 text effects that can be combined:
effects = [
  :bold,           # Bold/bright text
  :dim,            # Dimmed text
  :italic,         # Italic text (not universally supported)
  :underline,      # Underlined text
  :blink,          # Slow blink
  :rapid_blink,    # Rapid blink
  :reverse,        # Reverse video (swap fg/bg colors)
  :hidden,         # Hidden text
  :strikethrough   # Strikethrough text
]
# Single effect
ColorFuncs.fg(:red, [:bold])
# Multiple effects
ColorFuncs.fg(:blue, [:bold, :underline, :italic])
# Effect only (no color change)
ColorFuncs.effect(:bold)Advanced Functions
The tui Function
The main function for creating complex color combinations:
# Basic syntax: tui(foreground, background, effects)
ColorFuncs.tui(:white, :blue, [:bold])
ColorFuncs.tui(:yellow, :red, [:bold, :underline])
ColorFuncs.tui(:green, :black, [])Utility Functions
# List all available colors
ColorFuncs.available_colors()
# List all available effects  
ColorFuncs.available_effects()
# Reset all formatting
ColorFuncs.reset()True Color Support
RGB Colors
Use any RGB color combination:
# RGB foreground (values 0-255)
ColorFuncs.rgb_fg(255, 128, 0)    # Orange
ColorFuncs.rgb_fg(64, 224, 208)   # Turquoise
ColorFuncs.rgb_fg(255, 20, 147)   # Deep pink
# RGB background
ColorFuncs.rgb_bg(25, 25, 112)    # Midnight blue
ColorFuncs.rgb_bg(0, 0, 0)        # True black
# Combined usage
text = ColorFuncs.rgb_fg(255, 255, 255) <> 
       ColorFuncs.rgb_bg(0, 0, 0) <> 
       "White on true black" <> 
       ColorFuncs.reset()Hex Colors
Use web-style hex colors:
# Hex foreground
ColorFuncs.hex_fg("#FF8000")      # Orange
ColorFuncs.hex_fg("#7aa2f7")      # Nice blue
ColorFuncs.hex_fg("#9ece6a")      # Green
# Hex background  
ColorFuncs.hex_bg("#1a1b26")      # Dark background
ColorFuncs.hex_bg("#ff0000")      # Red background
# Both formats supported
ColorFuncs.hex_fg("FF8000")       # Without #
ColorFuncs.hex_fg("#FF8000")      # With #Auto-Generated Combinations
The module automatically generates functions for all foreground/background color combinations:
# Pattern: {foreground}_on_{background}
ColorFuncs.red_on_white()
ColorFuncs.blue_on_yellow()
ColorFuncs.white_on_black()
ColorFuncs.green_on_gray5()
ColorFuncs.neon_green_on_black()
ColorFuncs.purple_on_bright_white()
# Usage example
header = ColorFuncs.white_on_blue() <> " HEADER " <> ColorFuncs.reset()
error = ColorFuncs.white_on_red() <> " ERROR " <> ColorFuncs.reset()
success = ColorFuncs.black_on_green() <> " SUCCESS " <> ColorFuncs.reset()This generates 5,329 functions (73 × 73) for instant access to any color combination!
Practical Examples
Creating a Status Bar
defmodule StatusBar do
  alias BCUtils.ColorFuncs, as: CF
  def render(status, message) do
    case status do
      :success -> 
        CF.wrap(" ✓ ", :black, [], :bright_green) <> 
        CF.wrap(" #{message} ", :bright_green)
        
      :error -> 
        CF.wrap(" ✗ ", :white, [], :red) <> 
        CF.wrap(" #{message} ", :red)
        
      :warning -> 
        CF.wrap(" ⚠ ", :black, [], :yellow) <> 
        CF.wrap(" #{message} ", :yellow)
        
      :info -> 
        CF.wrap(" ℹ ", :white, [], :blue) <> 
        CF.wrap(" #{message} ", :blue)
    end
  end
end
# Usage
IO.puts(StatusBar.render(:success, "Database connected"))
IO.puts(StatusBar.render(:error, "Connection failed"))Syntax Highlighting
defmodule SyntaxHighlight do
  alias BCUtils.ColorFuncs, as: CF
  def keyword(text), do: CF.wrap(text, :purple, [:bold])
  def string(text), do: CF.wrap(text, :green)
  def number(text), do: CF.wrap(text, :cyan)
  def comment(text), do: CF.wrap(text, :gray7, [:italic])
  def function_name(text), do: CF.wrap(text, :blue, [:bold])
  def highlight_elixir(code) do
    code
    |> String.replace(~r/\bdef\b/, keyword("def"))
    |> String.replace(~r/"[^"]*"/, &string/1)
    |> String.replace(~r/\d+/, &number/1)
    |> String.replace(~r/#.*$/, &comment/1)
  end
endProgress Indicators
defmodule Progress do
  alias BCUtils.ColorFuncs, as: CF
  def bar(percentage, width \\ 50) do
    filled = round(percentage * width / 100)
    empty = width - filled
    
    filled_bar = CF.wrap(String.duplicate("█", filled), :bright_green)
    empty_bar = CF.wrap(String.duplicate("░", empty), :gray3)
    percentage_text = CF.wrap(" #{percentage}% ", :bright_white, [:bold])
    
    "[#{filled_bar}#{empty_bar}]#{percentage_text}"
  end
  
  def spinner(frame) do
    frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
    current = Enum.at(frames, rem(frame, length(frames)))
    CF.wrap(current, :cyan) <> " Loading..."
  end
end
# Usage
IO.puts(Progress.bar(75))
IO.puts(Progress.spinner(3))Log Level Formatting
defmodule LogFormatter do
  alias BCUtils.ColorFuncs, as: CF
  def format_level(:debug), do: CF.wrap("DEBUG", :gray8)
  def format_level(:info),  do: CF.wrap("INFO ", :bright_cyan)
  def format_level(:warn),  do: CF.wrap("WARN ", :yellow, [:bold])
  def format_level(:error), do: CF.wrap("ERROR", :red, [:bold])
  def format_level(:fatal), do: CF.wrap("FATAL", :white, [:bold], :red)
  def format_log(level, module, message) do
    timestamp = CF.wrap(DateTime.utc_now() |> to_string(), :gray6)
    level_text = format_level(level)
    module_text = CF.wrap("[#{module}]", :blue)
    
    "#{timestamp} #{level_text} #{module_text} #{message}"
  end
endTerminal UI Components
defmodule TerminalUI do
  alias BCUtils.ColorFuncs, as: CF
  def header(title) do
    width = 60
    padding = div(width - String.length(title) - 2, 2)
    
    top = CF.wrap(String.duplicate("═", width), :bright_blue)
    middle = CF.wrap("║", :bright_blue) <> 
             String.duplicate(" ", padding) <>
             CF.wrap(title, :bright_white, [:bold]) <>
             String.duplicate(" ", padding) <>
             CF.wrap("║", :bright_blue)
    bottom = CF.wrap(String.duplicate("═", width), :bright_blue)
    
    [top, middle, bottom] |> Enum.join("\n")
  end
  def menu_item(text, selected \\ false) do
    if selected do
      CF.wrap(" ▶ #{text} ", :black, [:bold], :bright_cyan)
    else
      CF.wrap("   #{text} ", :bright_white)
    end
  end
  def table_row(cells, colors \\ []) do
    cells
    |> Enum.with_index()
    |> Enum.map(fn {cell, idx} ->
      color = Enum.at(colors, idx, :white)
      CF.wrap(String.pad_trailing(cell, 15), color)
    end)
    |> Enum.join(" │ ")
  end
endBest Practices
1. Always Reset
Always use ColorFuncs.reset() or the wrap/3 function to avoid color bleeding:
# Good
text = ColorFuncs.fg(:red) <> "Error message" <> ColorFuncs.reset()
# Better
text = ColorFuncs.wrap("Error message", :red)2. Check Terminal Capabilities
Not all terminals support all features:
# Some terminals don't support italic
text = if terminal_supports_italic?() do
  ColorFuncs.wrap("Italic text", :blue, [:italic])
else
  ColorFuncs.wrap("Bold text", :blue, [:bold])
end3. Use Semantic Color Functions
Create semantic wrappers for better maintainability:
defmodule Colors do
  alias BCUtils.ColorFuncs, as: CF
  
  def error(text), do: CF.wrap(text, :red, [:bold])
  def success(text), do: CF.wrap(text, :green, [:bold])
  def warning(text), do: CF.wrap(text, :yellow, [:bold])
  def info(text), do: CF.wrap(text, :blue)
  def debug(text), do: CF.wrap(text, :gray8)
end4. Consider Accessibility
Choose colors that work well together and are accessible:
# Good contrast
ColorFuncs.wrap("Important", :bright_white, [:bold], :red)
# Poor contrast (avoid)
ColorFuncs.wrap("Hard to read", :yellow, [], :white)5. Use Soft Colors for Large Text Blocks
For readability, prefer softer colors over bright ones:
# Better for large text
ColorFuncs.wrap(long_text, :teal)
# Too harsh for large text
ColorFuncs.wrap(long_text, :bright_cyan)6. Consistent Color Schemes
Define a consistent color scheme for your application:
defmodule AppTheme do
  alias BCUtils.ColorFuncs, as: CF
  
  # Primary colors
  def primary(text), do: CF.wrap(text, :blue, [:bold])
  def secondary(text), do: CF.wrap(text, :teal)
  
  # Status colors
  def success(text), do: CF.wrap(text, :emerald, [:bold])
  def danger(text), do: CF.wrap(text, :crimson, [:bold])
  def warning(text), do: CF.wrap(text, :amber, [:bold])
  
  # Text hierarchy
  def heading(text), do: CF.wrap(text, :bright_white, [:bold])
  def subheading(text), do: CF.wrap(text, :bright_white)
  def body(text), do: CF.wrap(text, :white)
  def muted(text), do: CF.wrap(text, :gray8)
endColor Reference
Quick Reference Table
| Category | Colors | 
|---|---|
| Basic | black, red, green, yellow, blue, magenta, cyan, white | 
| Bright | bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white | 
| Extended | orange, purple, pink, lime, navy, maroon, olive, teal, silver, gold, coral, salmon, khaki, violet, indigo, crimson, forest, sky, rose, mint | 
| Vibrant | turquoise, aqua, brown, tan, beige, ivory, lavender, plum, orchid, peach, apricot, lemon, chartreuse, emerald, jade, sapphire, ruby, amber, bronze, copper | 
| Nature | grass, leaf, ocean, sand, stone, clay, earth, bark, moss, fern | 
| Tech | neon_green, neon_blue, neon_pink, electric, plasma, laser, matrix, cyber, terminal, hacker | 
| Grayscale | gray1, gray2, gray3, gray4, gray5, gray6, gray7, gray8, gray9, gray10, gray11, gray12 | 
Effects Reference
| Effect | Description | Support | 
|---|---|---|
:bold | Bold/bright text | Universal | 
:dim | Dimmed text | Most terminals | 
:italic | Italic text | Limited | 
:underline | Underlined text | Most terminals | 
:blink | Slow blink | Limited | 
:rapid_blink | Rapid blink | Very limited | 
:reverse | Reverse video | Most terminals | 
:hidden | Hidden text | Most terminals | 
:strikethrough | Strikethrough | Modern terminals | 
Function Reference
| Function | Description | Example | 
|---|---|---|
fg(color, effects) | Foreground color with effects | fg(:red, [:bold]) | 
bg(color) | Background color | bg(:blue) | 
tui(fg, bg, effects) | Complete formatting | tui(:white, :red, [:bold]) | 
wrap(text, color, effects) | Wrap with auto-reset | wrap("Hello", :green) | 
rgb_fg(r, g, b) | RGB foreground | rgb_fg(255, 128, 0) | 
rgb_bg(r, g, b) | RGB background | rgb_bg(0, 0, 255) | 
hex_fg(hex) | Hex foreground | hex_fg("#FF8000") | 
hex_bg(hex) | Hex background | hex_bg("#0080FF") | 
effect(name) | Apply effect only | effect(:bold) | 
reset() | Reset all formatting | reset() | 
available_colors() | List all colors | available_colors() | 
available_effects() | List all effects | available_effects() | 
This guide covers the complete functionality of the BCUtils.ColorFuncs module. For more examples and updates, check the module documentation and tests.