Skip to content

Commit

Permalink
Apply code review suggestions
Browse files Browse the repository at this point in the history
- Changed the API to `stylize("string").bold.blue.on_white`
- Moved magic numbers to constants
  • Loading branch information
gustavothecoder committed Dec 8, 2024
1 parent 11cb3fa commit 113ed0e
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 150 deletions.
295 changes: 173 additions & 122 deletions lib/dry/cli/styles.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,134 +2,185 @@

module Dry
class CLI
# Collection of functions to style text.
# Collection of functions to style text
#
# @since 1.3.0
module Styles
# since 1.3.0
def bold(text)
ensure_clean_sequence("\e[1m#{text}")
end

# since 1.3.0
def dim(text)
ensure_clean_sequence("\e[2m#{text}")
end

# since 1.3.0
def italic(text)
ensure_clean_sequence("\e[3m#{text}")
end

# since 1.3.0
def underline(text)
ensure_clean_sequence("\e[4m#{text}")
end

# since 1.3.0
def blink(text)
ensure_clean_sequence("\e[5m#{text}")
end

# since 1.3.0
def reverse(text)
ensure_clean_sequence("\e[7m#{text}")
end

# since 1.3.0
def invisible(text)
ensure_clean_sequence("\e[8m#{text}")
end

# since 1.3.0
def black(text)
ensure_clean_sequence("\e[30m#{text}")
end

# since 1.3.0
def red(text)
ensure_clean_sequence("\e[31m#{text}")
end

# since 1.3.0
def green(text)
ensure_clean_sequence("\e[32m#{text}")
end

# since 1.3.0
def yellow(text)
ensure_clean_sequence("\e[33m#{text}")
end

# since 1.3.0
def blue(text)
ensure_clean_sequence("\e[34m#{text}")
end

# since 1.3.0
def magenta(text)
ensure_clean_sequence("\e[35m#{text}")
end

# since 1.3.0
def cyan(text)
ensure_clean_sequence("\e[36m#{text}")
end

# since 1.3.0
def white(text)
ensure_clean_sequence("\e[37m#{text}")
end

# since 1.3.0
def on_black(text)
ensure_clean_sequence("\e[40m#{text}")
end

# since 1.3.0
def on_red(text)
ensure_clean_sequence("\e[41m#{text}")
end

# since 1.3.0
def on_green(text)
ensure_clean_sequence("\e[42m#{text}")
end

# since 1.3.0
def on_yellow(text)
ensure_clean_sequence("\e[43m#{text}")
end

# since 1.3.0
def on_blue(text)
ensure_clean_sequence("\e[44m#{text}")
end

# since 1.3.0
def on_magenta(text)
ensure_clean_sequence("\e[45m#{text}")
end

# since 1.3.0
def on_cyan(text)
ensure_clean_sequence("\e[46m#{text}")
end

# since 1.3.0
def on_white(text)
ensure_clean_sequence("\e[47m#{text}")
RESET = 0
BOLD = 1
DIM = 2
ITALIC = 3
UNDERLINE = 4
BLINK = 5
REVERSE = 7
INVISIBLE = 8
BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
ON_BLACK = 40
ON_RED = 41
ON_GREEN = 42
ON_YELLOW = 43
ON_BLUE = 44
ON_MAGENTA = 45
ON_CYAN = 46
ON_WHITE = 47

# Returns a text that can be styled
#
# @param text [String] text to be styled
#
# @since 1.3.0
def stylize(text)
StyledText.new(text)
end

private

# Styled text
#
# @since 1.3.0
# @api private
def ensure_clean_sequence(text)
clen_text = text
clear = "\e[0m"
clen_text += clear unless text.end_with?(clear)
clen_text
class StyledText
def initialize(text)
@text = text
end

# Makes `StyledText` printable
#
# @since 1.3.0
def to_s
@text
end

# since 1.3.0
def bold
chainable_update!("\e[#{BOLD}m#{@text}")
end

# since 1.3.0
def dim
chainable_update!("\e[#{DIM}m#{@text}")
end

# since 1.3.0
def italic
chainable_update!("\e[#{ITALIC}m#{@text}")
end

# since 1.3.0
def underline
chainable_update!("\e[#{UNDERLINE}m#{@text}")
end

# since 1.3.0
def blink
chainable_update!("\e[#{BLINK}m#{@text}")
end

# since 1.3.0
def reverse
chainable_update!("\e[#{REVERSE}m#{@text}")
end

# since 1.3.0
def invisible
chainable_update!("\e[#{INVISIBLE}m#{@text}")
end

# since 1.3.0
def black
chainable_update!("\e[#{BLACK}m#{@text}")
end

# since 1.3.0
def red
chainable_update!("\e[#{RED}m#{@text}")
end

# since 1.3.0
def green
chainable_update!("\e[#{GREEN}m#{@text}")
end

# since 1.3.0
def yellow
chainable_update!("\e[#{YELLOW}m#{@text}")
end

# since 1.3.0
def blue
chainable_update!("\e[#{BLUE}m#{@text}")
end

# since 1.3.0
def magenta
chainable_update!("\e[#{MAGENTA}m#{@text}")
end

# since 1.3.0
def cyan
chainable_update!("\e[#{CYAN}m#{@text}")
end

# since 1.3.0
def white
chainable_update!("\e[#{WHITE}m#{@text}")
end

# since 1.3.0
def on_black
chainable_update!("\e[#{ON_BLACK}m#{@text}")
end

# since 1.3.0
def on_red
chainable_update!("\e[#{ON_RED}m#{@text}")
end

# since 1.3.0
def on_green
chainable_update!("\e[#{ON_GREEN}m#{@text}")
end

# since 1.3.0
def on_yellow
chainable_update!("\e[#{ON_YELLOW}m#{@text}")
end

# since 1.3.0
def on_blue
chainable_update!("\e[#{ON_BLUE}m#{@text}")
end

# since 1.3.0
def on_magenta
chainable_update!("\e[#{ON_MAGENTA}m#{@text}")
end

# since 1.3.0
def on_cyan
chainable_update!("\e[#{ON_CYAN}m#{@text}")
end

# since 1.3.0
def on_white
chainable_update!("\e[#{ON_WHITE}m#{@text}")
end

private

# @since 1.3.0
# @api private
def chainable_update!(new_text)
clen_text = new_text
clear = "\e[#{RESET}m"
clen_text += clear unless clen_text.end_with?(clear)
@text = clen_text
self
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/support/fixtures/foo
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module Foo
]

def call(engine: nil, **)
puts blue(bold("console - engine: ")), magenta(engine.to_s)
puts stylize("console - engine: ").blue.bold, stylize(engine.to_s).magenta
end
end

Expand Down
52 changes: 26 additions & 26 deletions spec/support/fixtures/styles
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,32 @@ module StylesDemo
# rubocop:disable Metrics/AbcSize
def call
demo = <<~DEMO
`bold` #{bold("This is bold")}
`dim` #{dim("This is dim")}
`italic` #{italic("This is italic")}
`underline` #{underline("This is underline")}
`blink` #{blink("This blinks")}
`reverse` #{reverse("This was reversed")}
`invisible` #{invisible("This is invisible")} (you can't see it, right?)
`black` #{black("This is black")}
`red` #{red("This is red")}
`green` #{green("This is green")}
`yellow` #{yellow("This is yellow")}
`blue` #{blue("This is blue")}
`magenta` #{magenta("This is magenta")}
`cyan` #{cyan("This is cyan")}
`white` #{white("This is white")}
`on_black` #{on_black("This is black")}
`on_red` #{on_red("This is red")}
`on_green` #{on_green("This is green")}
`on_yellow` #{on_yellow("This is yellow")}
`on_blue` #{on_blue("This is blue")}
`on_magenta` #{on_magenta("This is magenta")}
`on_cyan` #{on_cyan("This is cyan")}
`on_white` #{on_white("This is white")}
`bold`+`red`: #{bold(red("This is bold red"))}
`bold`+`on_green`: #{bold(on_green("This is bold on green"))}
`bold`+`red`+`on_green`: #{bold(red(on_green("This is bold red on green")))}
`stylize("This is bold").bold` #=> #{stylize("This is bold").bold}
`stylize("This is dim").dim` #=> #{stylize("This is dim").dim}
`stylize("This is italic").italic` #=> #{stylize("This is italic").italic}
`stylize("This is underline").underline` #=> #{stylize("This is underline").underline}
`stylize("This blinks").blink` #=> #{stylize("This blinks").blink}
`stylize("This was reversed").reverse` #=> #{stylize("This was reversed").reverse}
`stylize("This is invisible").invisible` #=> #{stylize("This is invisible").invisible} (you can't see it, right?)
`stylize("This is black").black` #=> #{stylize("This is black").black}
`stylize("This is red").red` #=> #{stylize("This is red").red}
`stylize("This is green").green` #=> #{stylize("This is green").green}
`stylize("This is yellow").yellow` #=> #{stylize("This is yellow").yellow}
`stylize("This is blue").blue` #=> #{stylize("This is blue").blue}
`stylize("This is magenta").magenta` #=> #{stylize("This is magenta").magenta}
`stylize("This is cyan").cyan` #=> #{stylize("This is cyan").cyan}
`stylize("This is white").white` #=> #{stylize("This is white").white}
`stylize("This is black").on_black` #=> #{stylize("This is black").on_black}
`stylize("This is red").on_red` #=> #{stylize("This is red").on_red}
`stylize("This is green").on_green` #=> #{stylize("This is green").on_green}
`stylize("This is yellow").on_yellow` #=> #{stylize("This is yellow").on_yellow}
`stylize("This is blue").on_blue` #=> #{stylize("This is blue").on_blue}
`stylize("This is magenta").on_magenta` #=> #{stylize("This is magenta").on_magenta}
`stylize("This is cyan").on_cyan` #=> #{stylize("This is cyan").on_cyan}
`stylize("This is white").on_white` #=> #{stylize("This is white").on_white}
`stylize("This is bold red").bold.red #=> #{stylize("This is bold red").bold.red}
`stylize("This is bold on green").bold.on_green` #=> #{stylize("This is bold on green").bold.on_green}
`stylize("This is bold red on green").bold.red.on_green` #=> #{stylize("This is bold red on green").bold.red.on_green}
DEMO
puts demo
end
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/dry/cli/styles_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Dummy
include Dry::CLI::Styles

def bold_and_black
black(bold("two"))
stylize("two").black.bold.to_s
end
end

Expand Down

0 comments on commit 113ed0e

Please sign in to comment.