ANSI escape codes in Ruby
Ruby's double-quoted strings accept `\e` as the ESC literal (no need for `\x1b` or `\033`), and `puts` / `print` / `STDOUT.write` are byte-clean on every platform. Ruby 3.0+ on Windows auto-enables `ENABLE_VIRTUAL_TERMINAL_PROCESSING` on the standard streams, so `\e[31m` lights up Conhost and Windows Terminal without a `colorama`-style shim. For ergonomic styling: `colorize` monkey-patches `String` with chainable colour methods (`"oops".red.bold`), `term-ansicolor` (Florian Frank's classic — powers `pry` and `rspec`) offers both module-call (`Term::ANSIColor.red(...)`) and mixin styles, and `pastel` (from the TTY toolkit) ships isolated SGR helpers that auto-detect `NO_COLOR` and `CLICOLOR_FORCE` without polluting `String`. For full TUIs reach for the rest of the TTY toolkit — `tty-prompt`, `tty-spinner`, `tty-cursor`, `tty-progressbar`.
Recommended libraries
- colorize
Monkey-patches `String` with chainable colour methods — `"oops".red.bold.on_white`. ~30M downloads, the de facto choice for one-off scripts and Rakefile output. Supports 8 named colours + extended palette via `colorize(color: :red, mode: :bold, background: :white)`.
- term-ansicolor
Florian Frank's classic gem (since 2009) — both module-call style (`Term::ANSIColor.red("text")`) and mixin style (`include Term::ANSIColor; red("text")`). Powers `pry`, `rspec`, `cucumber`, and a long tail of Ruby CLI tools. Honours `NO_COLOR` since 1.7.0.
- pastel
Module-scoped SGR helper — `Pastel.new.red.bold("oops")`. No `String` monkey-patching. The TTY toolkit's idiomatic colour layer; `Pastel.new(enabled: nil)` auto-detects via `tty?` + `NO_COLOR` + `CLICOLOR_FORCE`. Supports decorators (`pastel.decorate("text", :red, :bold)`) and 256-colour `on_<color>` chains.
- tty-prompt
Interactive prompts — `select`, `ask`, `multi_select`, `mask` (password), `yes?`/`no?`, with polished styling and keyboard navigation. Pairs with `tty-spinner`, `tty-progressbar`, `tty-cursor` for a full TUI stack. Used by Hanami, Pry, Bundler-style installers, and Foreman.
Idiomatic patterns
puts "\e[1;31merror:\e[0m permission denied"require 'colorize'
puts "error:".red.bold + " permission denied"
puts "ok".green
puts "deprecated".yellow.on_blackrequire 'pastel'
# Pastel.new(enabled: nil) auto-detects:
# STDOUT.tty? AND NO_COLOR not set AND CLICOLOR != '0'
# CLICOLOR_FORCE=1 forces colour even when redirected.
pastel = Pastel.new
puts "#{pastel.red.bold('error:')} permission denied"
puts pastel.decorate('lavender truecolor', :on_blue, :bold)
# Disable globally — e.g. in CI:
plain = Pastel.new(enabled: false)
puts plain.red('this prints as plain text')STDOUT.print "\e[?25l" # hide cursor
at_exit { STDOUT.print "\e[?25h" } # restore on any exit path
100.times do |i|
# \r returns to col 1, \e[K erases to end of line
STDOUT.print "\r\e[K#{i + 1}% complete"
STDOUT.flush
sleep 0.02
end
puts