diff --git a/src/formatter.cr b/src/formatter.cr index 3c3d572..6aadd2e 100644 --- a/src/formatter.cr +++ b/src/formatter.cr @@ -1,6 +1,7 @@ require "./constants.cr" require "./styles.cr" require "./tartrazine.cr" +require "colorize" module Tartrazine # This is the base class for all formatters. @@ -11,6 +12,63 @@ module Tartrazine raise Exception.new("Not implemented") end + def get_style_defs(theme : Theme) : String + raise Exception.new("Not implemented") + end + end + + class Ansi < Formatter + def format(text : String, lexer : Lexer, theme : Theme) : String + output = String.build do |outp| + lexer.tokenize(text).each do |token| + outp << self.colorize(token[:value], token[:type], theme) + end + end + output + end + + def colorize(text : String, token : String, theme : Theme) : String + style = theme.styles.fetch(token, nil) + return text if style.nil? + if theme.styles.has_key?(token) + s = theme.styles[token] + else + # Themes don't contain information for each specific + # token type. However, they may contain information + # for a parent style. Worst case, we go to the root + # (Background) style. + s = theme.styles[theme.style_parents(token).reverse.find { |parent| + theme.styles.has_key?(parent) + }] + end + text.colorize(*rgb(s.color)).back(*rgb(s.background)).to_s + end + + def rgb(c : String?) + return {0_u8, 0_u8, 0_u8} unless c + r = c[0..1].to_u8(16) + g = c[2..3].to_u8(16) + b = c[4..5].to_u8(16) + {r, g, b} + end + end + + class Html < Formatter + def format(text : String, lexer : Lexer, theme : Theme) : String + output = String.build do |outp| + outp << "
" + outp << ""
+ lexer.tokenize(text).each do |token|
+ fragment = "#{token[:value]}"
+ outp << fragment
+ end
+ outp << "
"
+ end
+ output
+ end
+
# ameba:disable Metrics/CyclomaticComplexity
def get_style_defs(theme : Theme) : String
output = String.build do |outp|
@@ -35,23 +93,6 @@ module Tartrazine
end
output
end
- end
-
- class Html < Formatter
- def format(text : String, lexer : Lexer, theme : Theme) : String
- output = String.build do |outp|
- outp << ""
- outp << ""
- lexer.tokenize(text).each do |token|
- fragment = "#{token[:value]}"
- outp << fragment
- end
- outp << "
"
- end
- output
- end
# Given a token type, return the CSS class to use.
def get_css_class(token, theme)
diff --git a/src/main.cr b/src/main.cr
index 99cf49e..a47ec1a 100644
--- a/src/main.cr
+++ b/src/main.cr
@@ -2,4 +2,4 @@ require "./**"
lexer = Tartrazine.lexer("crystal")
theme = Tartrazine.theme(ARGV[1])
-puts Tartrazine::Html.new.format(File.read(ARGV[0]), lexer, theme)
+puts Tartrazine::Ansi.new.format(File.read(ARGV[0]), lexer, theme)