String

Colorize your outputs

Since we mostly work with the command-line, we need our output to be more elegant. Here are the main colors you may need to do so. You can always add to this set.

  1. class String
  2. def red; colorize(self, "\e[1m\e[31m"); end
  3. def green; colorize(self, "\e[1m\e[32m"); end
  4. def dark_green; colorize(self, "\e[32m"); end
  5. def yellow; colorize(self, "\e[1m\e[33m"); end
  6. def blue; colorize(self, "\e[1m\e[34m"); end
  7. def dark_blue; colorize(self, "\e[34m"); end
  8. def purple; colorize(self, "\e[35m"); end
  9. def dark_purple; colorize(self, "\e[1;35m"); end
  10. def cyan; colorize(self, "\e[1;36m"); end
  11. def dark_cyan; colorize(self, "\e[36m"); end
  12. def pure; colorize(self, "\e[0m\e[28m"); end
  13. def bold; colorize(self, "\e[1m"); end
  14. def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
  15. end

All you need is to call the color when you puts it

  1. puts "RubyFu".red
  2. puts "RubyFu".green
  3. puts "RubyFu".yellow.bold

To understand this code, let’s explain it with a diagram

  1. \033 [0; 31m
  2. ^ ^ ^
  3. | | |
  4. | | |--------------------------------------- [The color number]
  5. | |-------------------- [The modifier] (ends with "m")
  6. |-- [Escaped character] | 0 - normal
  7. (you can use "\e") | 1 - bold
  8. | 2 - normal again
  9. | 3 - background color
  10. | 4 - underline
  11. | 5 - blinking

Or you can use an external gem called [colorized] for fancier options

  1. gem install colorize

Then just require it in your script

  1. require 'colorize'

Overwriting Console Output

It’s awesome to have more flexibility in your terminal, and sometimes we need to do more with our scripts.

Overwriting console output makes our applications elegant and less noisy for repeated outputs like counting and loading progress bars.

I’ve read a how-to about bash Prompt cursor movement and I found it is convenient to have in our scripts. Here’s what I’ve found so far

  1. - Position the Cursor:
  2. \033[<L>;<C>H
  3. Or
  4. \033[<L>;<C>f
  5. puts the cursor at line L and column C.
  6. - Move the cursor up N lines:
  7. \033[<N>A
  8. - Move the cursor down N lines:
  9. \033[<N>B
  10. - Move the cursor forward N columns:
  11. \033[<N>C
  12. - Move the cursor backward N columns:
  13. \033[<N>D
  14. - Clear the screen, move to (0,0):
  15. \033[2J
  16. - Erase to end of line:
  17. \033[K
  18. - Save cursor position:
  19. \033[s
  20. - Restore cursor position:
  21. \033[u

So to test these I created the following PoC

  1. #!/usr/bin/env ruby
  2. # KING SABRI | @KINGSABRI
  3. (1..3).map do |num|
  4. print "\rNumber: #{num}"
  5. sleep 0.5
  6. print ("\033[1B") # Move cursor down 1 line
  7. ('a'..'c').map do |char|
  8. print "\rCharacter: #{char}"
  9. print ("\e[K")
  10. sleep 0.5
  11. print ("\033[1B") # Move cursor down 1 lines
  12. ('A'..'C').map do |char1|
  13. print "\rCapital letters: #{char1}"
  14. print ("\e[K")
  15. sleep 0.3
  16. end
  17. print ("\033[1A") # Move curse up 1 line
  18. end
  19. print ("\033[1A") # Move curse up 1 line
  20. end
  21. print ("\033[2B") # Move cursor down 2 lines
  22. puts ""

So far so good, but why don’t we make these as Ruby methods for more elegant usage? So I came up with the following

  1. # KING SABRI | @KINGSABRI
  2. class String
  3. def mv_up(n=1)
  4. cursor(self, "\033[#{n}A")
  5. end
  6. def mv_down(n=1)
  7. cursor(self, "\033[#{n}B")
  8. end
  9. def mv_fw(n=1)
  10. cursor(self, "\033[#{n}C")
  11. end
  12. def mv_bw(n=1)
  13. cursor(self, "\033[#{n}D")
  14. end
  15. def cls_upline
  16. cursor(self, "\e[K")
  17. end
  18. def cls
  19. # cursor(self, "\033[2J")
  20. cursor(self, "\e[H\e[2J")
  21. end
  22. def save_position
  23. cursor(self, "\033[s")
  24. end
  25. def restore_position
  26. cursor(self, "\033[u")
  27. end
  28. def cursor(text, position)
  29. "\r#{position}#{text}"
  30. end
  31. end

Then as a PoC, I’ve used the same previous PoC code (after updating String class on-the-fly in the same script)

  1. #!/usr/bin/env ruby
  2. # KING SABRI | @KINGSABRI
  3. # Level 1
  4. (1..3).map do |num|
  5. print "\rNumber: #{num}"
  6. sleep 0.7
  7. # Level 2
  8. ('a'..'c').map do |char|
  9. print "Characters: #{char}".mv_down
  10. sleep 0.5
  11. # Level 3
  12. ('A'..'C').map do |char1|
  13. print "Capital: #{char1}".mv_down
  14. sleep 0.2
  15. print "".mv_up
  16. end
  17. print "".mv_up
  18. end
  19. sleep 0.7
  20. end
  21. print "".mv_down 3

It’s much more elegant, isn’t it? Say yes plz

Some application…

Create Progress Percent

  1. (1..10).each do |percent|
  2. print "#{percent*10}% complete\r"
  3. sleep(0.5)
  4. print ("\e[K") # Delete current line
  5. end
  6. puts "Done!"

Another example

  1. (1..5).to_a.reverse.each do |c|
  2. print "\rI'll exit after #{c} second(s)"
  3. print "\e[K"
  4. sleep 1
  5. end

Using our elegant way (after updating String class on-the-fly)

  1. (1..5).to_a.reverse.each do |c|
  2. print "I'll exit after #{c} second".cls_upline
  3. sleep 1
  4. end
  5. puts