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)