Module: Colsole

Defined in:
lib/colsole.rb,
lib/colsole/version.rb

Overview

Utility functions for colorful console applications.

Constant Summary collapse

ANSI_COLORS =
{
  'n' => '',       # no color
  'k' => "\e[30m", # black
  'r' => "\e[31m", # red
  'g' => "\e[32m", # green
  'y' => "\e[33m", # yellow
  'b' => "\e[34m", # blue
  'm' => "\e[35m", # magenta
  'c' => "\e[36m", # cyan
  'w' => "\e[37m", # white
}
ANSI_STYLES =
{
  'b' => "\e[1m", # bold
  'u' => "\e[4m", # underlined
  'i' => "\e[7m", # inverted
  'z' => "\e[0m", # terminate
}
VERSION =
'1.0.0'

Class Method Summary collapse

Class Method Details

.colorize(string) ⇒ Object

Convert color markers to ansi colors.



106
107
108
109
110
# File 'lib/colsole.rb', line 106

def colorize(string)
  process_color_markers string do |color, styles, text|
    "#{styles}#{color}#{text}#{ANSI_STYLES['z']}"
  end
end

.command_exist?(command) ⇒ Boolean

Returns true if the command exists in the path

Returns:

  • (Boolean)


50
51
52
53
54
# File 'lib/colsole.rb', line 50

def command_exist?(command)
  ENV['PATH'].split(File::PATH_SEPARATOR).any? do |dir|
    File.exist?(File.join dir, command) or File.exist?(File.join dir, "#{command}.exe")
  end
end

.internal_say(text, stream, replace: false) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/colsole.rb', line 126

def internal_say(text, stream, replace: false)
  text = "\033[2K\r#{text}" if replace && terminal?
  last = text[-1, 1]
  handler = use_colors?(stream) ? :colorize : :strip_colors

  if terminal? && ((last == ' ') || (last == '\t'))
    stream.print send(handler, text)
  else
    stream.print send(handler, "#{text}\n")
  end
end

.process_color_markers(string) ⇒ Object



117
118
119
120
121
122
123
124
# File 'lib/colsole.rb', line 117

def process_color_markers(string)
  string.gsub(/([rgybmcn])([ubi]{0,3})`([^`]*)`/) do
    color = ANSI_COLORS[$1]
    styles = $2.chars.map { |a| ANSI_STYLES[a] }.join
    text = $3
    yield color, styles, text
  end
end

.safe_get_tty_size(default = [80, 30]) ⇒ Object



138
139
140
141
142
143
144
145
146
# File 'lib/colsole.rb', line 138

def safe_get_tty_size(default = [80, 30])
  return default unless IO.console

  begin
    IO.console.winsize.reverse
  rescue Errno::ENOTTY
    default
  end
end

.say(text, replace: false) ⇒ Object

Output a string with optional color markers to stdout. If text is ended with a white space, you can call again with replace: true to replace that line



29
30
31
# File 'lib/colsole.rb', line 29

def say(text, replace: false)
  internal_say text, $stdout, replace: replace
end

.say!(text, replace: false) ⇒ Object

Output a string with optional color markers to stderr. Behaves similarly to ‘#say`.



35
36
37
# File 'lib/colsole.rb', line 35

def say!(text, replace: false)
  internal_say text, $stderr, replace: replace
end

.strip_colors(string) ⇒ Object

Remove color markers.



113
114
115
# File 'lib/colsole.rb', line 113

def strip_colors(string)
  process_color_markers(string) { |_color, _styles, text| text }
end

.terminal?(stream = $stdout) ⇒ Boolean

Returns true if stdout/stderr are a terminal

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
# File 'lib/colsole.rb', line 40

def terminal?(stream = $stdout)
  case ENV['TTY']
  when 'on'  then true
  when 'off' then false
  else
    stream.tty?
  end
end

.terminal_heightObject

Returns the rows part of the ‘#terminal_size`



83
84
85
# File 'lib/colsole.rb', line 83

def terminal_height
  terminal_size[1]
end

.terminal_size(default = [80, 30]) ⇒ Object

Returns the terminal size as [columns, rows]. Environment variables can be used to cheat.



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/colsole.rb', line 63

def terminal_size(default = [80, 30])
  result = if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
    [ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
  else
    safe_get_tty_size default
  end

  unless result[0].is_a?(Integer) && result[1].is_a?(Integer) && result[0].positive? && result[1].positive?
    result = default
  end

  result
end

.terminal_widthObject

Returns the columns part of the ‘#terminal_size`



78
79
80
# File 'lib/colsole.rb', line 78

def terminal_width
  terminal_size[0]
end

.use_colors?(stream = $stdout) ⇒ Boolean

Returns true if we can and should use colors in this stream

Returns:

  • (Boolean)


57
58
59
# File 'lib/colsole.rb', line 57

def use_colors?(stream = $stdout)
  ENV['FORCE_COLOR'] || (!ENV['NO_COLOR'] && terminal?(stream))
end

.word_wrap(text, length = nil) ⇒ Object

Converts a long string to be wrapped keeping words in tact. If the string starts with one or more spaces, they will be preserved in all subsequent lines (i.e., remain indented).



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/colsole.rb', line 90

def word_wrap(text, length = nil)
  length ||= terminal_width
  lead = text[/^\s*/]
  text.strip!
  length -= lead.length
  text.split("\n").collect! do |line|
    if line.length > length
      line.gsub!(/([^\s]{#{length}})([^\s$])/, '\\1 \\2')
      line.gsub(/(.{1,#{length}})(\s+|$)/, "#{lead}\\1\n").rstrip
    else
      "#{lead}#{line}"
    end
  end * "\n"
end