diff --git a/.gitignore b/.gitignore index e070556..40f20d9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /.shards/ *.dwarf logo-full.svg +/blahaj diff --git a/README.md b/README.md index 00b1480..88243d2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@
Code Of Conduct BSD-2-Clause - ci action status + ci action status

# @@ -32,13 +32,20 @@ They are built & published by our lovely [actions](https://github.com/GeopJr/BLA #### Dependencies -- `crystal` - `1.4.1` +- `crystal` - `1.6.2` #### Makefile - `$ make` (or `$ make static` on Alpine Linux for a static build) - `# make install` +##### Multithreading + +Releases are already in mt mode. It makes BLÅHAJ a *lot* faster: + +- `$ make build_mt` (or `$ make static_mt` on Alpine Linux for a static build) +- `# make install` + # ## FAQ @@ -73,7 +80,7 @@ Great! Follow the [Contributing section](#contributing) and modify [data/colors. ``` $ blahaj -h -BLÅHAJ v1.0.0 +BLÅHAJ v2.0.0 Usage: blahaj [arguments] @@ -85,12 +92,12 @@ Examples: blahaj -s -b neofetch | blahaj -c gay blahaj -f -c lesbian -m 4 - blahaj -- -w /etc/os-release + blahaj -w /etc/os-release Arguments: -b, --background Color the background - -f, --flag Return a flag -s, --shark Shork + -f, --flag Return a flag -i, --individual Color individual characters -w, --words Color individual words -m MULTIPLIER, --multiplier=MULTIPLIER diff --git a/data/ascii.txt b/data/ascii.txt index ab23193..6396049 100644 --- a/data/ascii.txt +++ b/data/ascii.txt @@ -14,4 +14,4 @@ .. ....,..........,..*#%#######/( .. .............,*%%%%#%((((/ **,,,****//*(##((###(#((( - &#(#/#((((((((# \ No newline at end of file + &#(#/#((((((((# diff --git a/data/colors.json b/data/colors.json deleted file mode 100644 index 40eb2a6..0000000 --- a/data/colors.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "trans": [ - "5BCEFA", - "F5A9B8", - "FFFFFF", - "F5A9B8", - "5BCEFA" - ], - "agender": [ - "000000", - "B9B9B9", - "FFFFFF", - "B8F483", - "FFFFFF", - "B9B9B9", - "000000" - ], - "gay": [ - "118C70", - "2DCDA9", - "97E7C0", - "EFEFFF", - "7AACE1", - "504BCB", - "3F2077" - ], - "ace": [ - "000000", - "A3A3A3", - "FFFFFF", - "800080" - ], - "aro": [ - "3DA542", - "A7D379", - "FFFFFF", - "A9A9A9", - "000000" - ], - "bi": [ - "D60270", - "9B4F96", - "0038A8" - ], - "genderfluid": [ - "FF75A2", - "FFFFFF", - "BE18D6", - "000000", - "333EBD" - ], - "genderqueer": [ - "b57EDC", - "FFFFFF", - "4A8123" - ], - "nb": [ - "FFF430", - "FFFFFF", - "9C59D1", - "000000" - ], - "pan": [ - "FF218C", - "FFD800", - "21B1FF" - ], - "pride": [ - "E40303", - "FF8C00", - "FFED00", - "008026", - "004DFF", - "750787" - ], - "philadelphia": [ - "000000", - "784F17", - "E40303", - "FF8C00", - "FFED00", - "008026", - "004DFF", - "750787" - ], - "progress": [ - "FFFFFF", - "F5A9B8", - "5BCEFA", - "784F17", - "000000", - "E40303", - "FF8C00", - "FFED00", - "008026", - "004DFF", - "750787" - ], - "lesbian": [ - "D52D00", - "EF7627", - "FF9A56", - "FFFFFF", - "D162A4", - "B55690", - "A30262" - ], - "demiboy": [ - "7F7F7F", - "C3C3C3", - "9AD9EA", - "FFFFFF", - "9AD9EA", - "C3C3C3", - "7F7F7F" - ], - "demigirl": [ - "7F7F7F", - "C3C3C3", - "FEAEC9", - "FFFFFF", - "FEAEC9", - "C3C3C3", - "7F7F7F" - ], - "abrosexual": [ - "75CA92", - "B4E4C9", - "FFFFFF", - "E795B6", - "D9446E" - ], - "bear": [ - "623804", - "D56300", - "FEDD63", - "FEE6B8", - "FFFFFF", - "555555" - ], - "transgender": "trans", - "nwlnw": "gay", - "asexual": "ace", - "aromantic": "aro", - "bisexual": "bi", - "nonbinary": "nb", - "enby": "nb", - "lgbt": "pride", - "lgbtq": "pride", - "pansexual": "pan", - "philly": "philadelphia", - "nmlnm": "lesbian", - "abro": "abrosexual", - "bears": "bear", - "bearpride": "bear" -} \ No newline at end of file diff --git a/data/colors.yaml b/data/colors.yaml new file mode 100644 index 0000000..2d943b8 --- /dev/null +++ b/data/colors.yaml @@ -0,0 +1,162 @@ +trans: + color: + - 5BCEFA + - F5A9B8 + - FFFFFF + - F5A9B8 + - 5BCEFA + alias: + - transgender +agender: + color: + - "000000" + - B9B9B9 + - FFFFFF + - B8F483 + - FFFFFF + - B9B9B9 + - "000000" +gay: + color: + - 118C70 + - 2DCDA9 + - 97E7C0 + - EFEFFF + - 7AACE1 + - 504BCB + - 3F2077 +ace: + color: + - "000000" + - A3A3A3 + - FFFFFF + - "800080" + alias: + - asexual +aro: + color: + - 3DA542 + - A7D379 + - FFFFFF + - A9A9A9 + - "000000" + alias: + - aromantic +bi: + color: + - D60270 + - 9B4F96 + - 0038A8 + alias: + - bisexual +genderfluid: + color: + - FF75A2 + - FFFFFF + - BE18D6 + - "000000" + - 333EBD +genderqueer: + color: + - b57EDC + - FFFFFF + - 4A8123 +nb: + color: + - FFF430 + - FFFFFF + - 9C59D1 + - "000000" + alias: + - nonbinary + - enby +pan: + color: + - FF218C + - FFD800 + - 21B1FF + alias: + - pansexual +pride: + color: + - E40303 + - FF8C00 + - FFED00 + - "008026" + - 004DFF + - "750787" + alias: + - lgbt + - lgbtq +philadelphia: + color: + - "000000" + - 784F17 + - E40303 + - FF8C00 + - FFED00 + - "008026" + - 004DFF + - "750787" + alias: + - philly +progress: + color: + - FFFFFF + - F5A9B8 + - 5BCEFA + - 784F17 + - "000000" + - E40303 + - FF8C00 + - FFED00 + - "008026" + - 004DFF + - "750787" +lesbian: + color: + - D52D00 + - EF7627 + - FF9A56 + - FFFFFF + - D162A4 + - B55690 + - A30262 +demiboy: + color: + - 7F7F7F + - C3C3C3 + - 9AD9EA + - FFFFFF + - 9AD9EA + - C3C3C3 + - 7F7F7F +demigirl: + color: + - 7F7F7F + - C3C3C3 + - FEAEC9 + - FFFFFF + - FEAEC9 + - C3C3C3 + - 7F7F7F +abrosexual: + color: + - 75CA92 + - B4E4C9 + - FFFFFF + - E795B6 + - D9446E + alias: + - abro +bear: + color: + - "623804" + - D56300 + - FEDD63 + - FEE6B8 + - FFFFFF + - "555555" + alias: + - bears + - bearpride diff --git a/shard.lock b/shard.lock new file mode 100644 index 0000000..4f3e149 --- /dev/null +++ b/shard.lock @@ -0,0 +1,2 @@ +version: 2.0 +shards: {} diff --git a/shard.yml b/shard.yml index 6ed6225..e28e2ed 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: blahaj -version: 1.0.1 +version: 2.0.0 authors: - Evangelos "GeopJr" Paterakis @@ -8,6 +8,6 @@ targets: blahaj: main: src/blahaj.cr -crystal: 1.4.1 +crystal: 1.6.2 license: BSD-2-Clauses diff --git a/spec/blahaj_spec.cr b/spec/blahaj_spec.cr deleted file mode 100644 index f38f961..0000000 --- a/spec/blahaj_spec.cr +++ /dev/null @@ -1,52 +0,0 @@ -require "./spec_helper" - -describe Blahaj do - it "outputs a trans flag" do - output = {{ run("#{__DIR__}/../src/blahaj", "-f").stringify }} - result = {{ read_file("#{__DIR__}/results/flag.txt") }} - - output.should eq result - end - - it "outputs a trans flag with 3x multiplier" do - output = {{ run("#{__DIR__}/../src/blahaj", "-f", "-m", "3").stringify }} - result = {{ read_file("#{__DIR__}/results/flag_3x.txt") }} - - output.should eq result - end - - it "outputs an agender shark" do - output = {{ run("#{__DIR__}/../src/blahaj", "-s", "-c", "agender").stringify }} - result = {{ read_file("#{__DIR__}/results/shark.txt") }} - - output.should eq result - end - - it "reads from ARGF and outputs a lesbian cowsay" do - output = {{ run("#{__DIR__}/../src/blahaj", "-c", "lesbian", "#{__DIR__}/results/cowsay.txt").stringify }} - result = {{ read_file("#{__DIR__}/results/cowsay_colored.txt") }} - - output.should eq result - end - - it "outputs an ace shark with each character colorized individually" do - output = {{ run("#{__DIR__}/../src/blahaj", "-s", "-c", "ace", "-i").stringify }} - result = {{ read_file("#{__DIR__}/results/shark_individual.txt") }} - - output.should eq result - end - - it "outputs an aro shark with each word colorized individually" do - output = {{ run("#{__DIR__}/../src/blahaj", "-s", "-c", "aro", "-w").stringify }} - result = {{ read_file("#{__DIR__}/results/shark_words.txt") }} - - output.should eq result - end - - it "outputs a gay shark with its background colorized" do - output = {{ run("#{__DIR__}/../src/blahaj", "-s", "-c", "nwlnw", "-b").stringify }} - result = {{ read_file("#{__DIR__}/results/shark_background.txt") }} - - output.should eq result - end -end diff --git a/spec/cli_spec.cr b/spec/cli_spec.cr new file mode 100644 index 0000000..456761a --- /dev/null +++ b/spec/cli_spec.cr @@ -0,0 +1,66 @@ +require "./spec_helper" + +def to_cli_args(arr) + arr.map do |k, v| + next if v == false + + prefix = "-" + joiner = "" + if k.to_s.size > 1 + prefix += prefix + joiner = "=" + end + + flag = "#{prefix}#{k}" + + if v.is_a?(Bool) + flag + else + "#{flag}#{joiner}#{v}" + end + end.compact +end + +describe Blahaj::CLI do + r = Random.new + + it "sets the config" do + args = { + b: r.next_bool, + s: r.next_bool, + f: r.next_bool, + i: r.next_bool, + w: r.next_bool, + m: r.rand(100) + 1, + c: Blahaj::COLORS.keys.sample, + } + + cli = Blahaj::CLI.new(to_cli_args(args)) + cli.config.background.should eq args[:b] + cli.config.shark.should eq args[:s] + cli.config.flag.should eq args[:f] + cli.config.individual.should eq args[:i] + cli.config.words.should eq args[:w] + cli.config.multiplier.should eq args[:m] + cli.config.color.should eq args[:c] + end + + it "gets the flag from alias" do + original_flag = Blahaj::COLORS.reject { |k, v| v.aliases.size == 0 }.sample + args = { + c: original_flag[1].aliases.sample, + } + + cli = Blahaj::CLI.new(to_cli_args(args)) + cli.config.color.should eq original_flag[0] + end + + it "handles multiplier limits" do + args = { + m: 0, + } + + cli = Blahaj::CLI.new(to_cli_args(args)) + cli.config.multiplier.should_not eq args[:m] + end +end diff --git a/spec/colorizer_spec.cr b/spec/colorizer_spec.cr new file mode 100644 index 0000000..af956c4 --- /dev/null +++ b/spec/colorizer_spec.cr @@ -0,0 +1,83 @@ +require "./spec_helper" + +describe Blahaj::Colorizer do + it "outputs a trans flag" do + config = Blahaj::Config.new + config.flag = true + + io = IO::Memory.new + colorizer = Blahaj::Colorizer.new(config, io) + + io.to_s.should eq {{ read_file("#{__DIR__}/results/flag.txt") }} + end + + it "outputs a trans flag with 3x multiplier" do + config = Blahaj::Config.new + config.flag = true + config.multiplier = 3 + + io = IO::Memory.new + colorizer = Blahaj::Colorizer.new(config, io) + + io.to_s.should eq {{ read_file("#{__DIR__}/results/flag_3x.txt") }} + end + + it "outputs an agender shark" do + config = Blahaj::Config.new + config.shark = true + config.color = "agender" + + io = IO::Memory.new + colorizer = Blahaj::Colorizer.new(config, io) + + io.to_s.should eq {{ read_file("#{__DIR__}/results/shark.txt") }} + end + + it "reads from ARGF and outputs a lesbian cowsay" do + ARGV << "#{__DIR__}/results/cowsay.txt" + + config = Blahaj::Config.new + config.color = "lesbian" + + io = IO::Memory.new + colorizer = Blahaj::Colorizer.new(config, io) + + io.to_s.should eq {{ read_file("#{__DIR__}/results/cowsay_colored.txt") }} + end + + it "outputs an ace shark with each character colorized individually" do + config = Blahaj::Config.new + config.shark = true + config.individual = true + config.color = "ace" + + io = IO::Memory.new + colorizer = Blahaj::Colorizer.new(config, io) + + io.to_s.should eq {{ read_file("#{__DIR__}/results/shark_individual.txt") }} + end + + it "outputs an aro shark with each word colorized individually" do + config = Blahaj::Config.new + config.shark = true + config.words = true + config.color = "aro" + + io = IO::Memory.new + colorizer = Blahaj::Colorizer.new(config, io) + + io.to_s.should eq {{ read_file("#{__DIR__}/results/shark_words.txt") }} + end + + it "outputs a gay shark with its background colorized" do + config = Blahaj::Config.new + config.shark = true + config.background = true + config.color = "gay" + + io = IO::Memory.new + colorizer = Blahaj::Colorizer.new(config, io) + + io.to_s.should eq {{ read_file("#{__DIR__}/results/shark_background.txt") }} + end +end diff --git a/spec/results/shark_words.txt b/spec/results/shark_words.txt index 7224349..b6e772e 100644 --- a/spec/results/shark_words.txt +++ b/spec/results/shark_words.txt @@ -1,17 +1,17 @@ -                                          ,(((/                                  -                                        /(((((                                   -                                       ((((#((                              (//  -                                      (((((((.                           *(((/   -                                    /(######/                          *((((/    -                                 *//%#####((/                         ((#((/     -               ,*/********/////////////////(//*           (%*      ,((##((       -      ,*/((///(//////////((/(///////(/////(////*,(*#((/(/((//////###(###(/(      -   /(((((((//((///((////((((((/(((((((((((((((((/(((##((#%(##(/((///*(&#(##/     -  /#((%(#(((((//#((((((((((((((((((((((((#(((((((((((/##(((((//((//*    ####(/   -   (((###(###(#(#####(###############((#((((((((/((//(((#/(/////            ,,   -     ,(###%####%&%#############(#(#(####(((((((/(((/////*//,                     -         . .....*#(#######(((###(#(##(##(((/(/(/////,                            -          .. ....,..........,..*#%#######/(                                      -               ..  .............,*%%%%#%((((/                                    -                       **,,,****//*(##((###(#(((                                 -                                        &#(#/#((((((((#                          + ,(((/ + /((((( + ((((#(( (// + (((((((. *(((/ + /(######/ *((((/ + *//%#####((/ ((#((/ + ,*/********/////////////////(//* (%* ,((##(( + ,*/((///(//////////((/(///////(/////(////*,(*#((/(/((//////###(###(/( + /(((((((//((///((////((((((/(((((((((((((((((/(((##((#%(##(/((///*(&#(##/ + /#((%(#(((((//#((((((((((((((((((((((((#(((((((((((/##(((((//((//* ####(/ + (((###(###(#(#####(###############((#((((((((/((//(((#/(///// ,, + ,(###%####%&%#############(#(#(####(((((((/(((/////*//, + . .....*#(#######(((###(#(##(##(((/(/(/////, + .. ....,..........,..*#%#######/( + .. .............,*%%%%#%((((/ + **,,,****//*(##((###(#((( + &#(#/#((((((((# diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 5c72058..7e11751 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -1,15 +1,3 @@ require "spec" require "file_utils" require "../src/blahaj" - -module Blahaj - CLI = { - "background" => false, - "color" => "trans", - "flag" => false, - "shark" => false, - "individual" => false, - "multiplier" => 1, - "words" => false, - } -end diff --git a/src/blahaj.cr b/src/blahaj.cr index 2311d1e..83a2db6 100644 --- a/src/blahaj.cr +++ b/src/blahaj.cr @@ -1,117 +1,24 @@ -require "json" +require "yaml" +require "./blahaj/data_parser.cr" module Blahaj + # Shork + ASCII = {{read_file("#{__DIR__}/../data/ascii.txt")}} + # Hash of all colors from data/colors.json - COLORS = Hash(String, String | Array(Blahaj::Color)).from_json({{read_file("#{__DIR__}/../data/colors.json")}}) + COLORS = Flags.new({{read_file("#{__DIR__}/../data/colors.yaml")}}).flags + # Chars that are to be ignored during -i or -w - NO_COLOR = {'\n', '\t', ' '} + NO_COLOR = {'\n', '\t', '\r', ' '} end # Need to be required after the above have been declared require "./blahaj/*" +# [MACRO] Skip on spec +{% skip_file if @top_level.has_constant? "Spec" %} + module Blahaj - # Shork - ascii = {{read_file("#{__DIR__}/../data/ascii.txt")}} - - # Selected color - scheme = COLORS[Blahaj::CLI["color"]].as(Array(Blahaj::Color)) - multiplied_cols = 4 * scheme.size * Blahaj::CLI["multiplier"].as(Int32) - i = 0 - - # [MACRO]: Instead of checking the CLI options and colorizing accordingly, pre-generate all available - # colorizers(?) using macros - macro handle_input(background, flag, ascii, individual, words) - {% - input = if flag - "scheme.each".id - elsif ascii - "ascii.each_line".id - else - "ARGF.each_line".id - end - %} - - {{input}} do |x| - current_color = scheme[i % scheme.size] - - {% if flag %} # When -f is present - tmp_i = 0 - # Attempt to scale the flag based on the multiplied (-m) - while tmp_i < Blahaj::CLI["multiplier"].as(Int32) - STDOUT.puts (" " * multiplied_cols).colorize.back(current_color.color) - tmp_i += 1 - end - {% elsif individual || words %} # When -w or -i are present - # individual: x.chars.map - # words: x.split(' ').map - - {% - word_char_splitting = "x." - word_char_joiner = "" - if words - word_char_splitting += "split(' ')" - word_char_joiner = " " - else - word_char_splitting += "chars" - end - word_char_splitting = word_char_splitting.id - %} - - STDOUT.puts {{word_char_splitting}}.map { |y| - next y if NO_COLOR.includes?(y) - tmp_color = current_color - i += 1 - current_color = scheme[i % scheme.size] - - {% if background %} - y.colorize.back(tmp_color.color).fore(tmp_color.foreground) - {% else %} - y.colorize(tmp_color.color) - {% end %} - - }.join({{word_char_joiner}}) - i -= 1 - {% elsif background %} # When -b is present - STDOUT.puts x.colorize.back(current_color.color).fore(current_color.foreground) - {% else %} - STDOUT.puts x.colorize(current_color.color) - {% end %} - i += 1 - end - exit - end - - # [MACRO]: Skip some repetitive if statements. - macro i_w_none(background = false, flag = false, ascii = false) - if Blahaj::CLI["individual"] - handle_input(background: {{background}}, flag: {{flag}}, ascii: {{ascii}}, individual: true, words: false) - elsif Blahaj::CLI["words"] - handle_input(background: {{background}}, flag: {{flag}}, ascii: {{ascii}}, individual: false, words: true) - else - handle_input(background: {{background}}, flag: {{flag}}, ascii: {{ascii}}, individual: false, words: false) - end - end - - # [MACRO]: Skip on spec - {% unless @top_level.has_constant? "Spec" %} - # This is repetitive but they are macros. It saves runtime checks. - if Blahaj::CLI["shark"] - if Blahaj::CLI["background"] - i_w_none(background: true, flag: false, ascii: true) - else - i_w_none(background: false, flag: false, ascii: true) - end - elsif Blahaj::CLI["flag"] - handle_input(background: false, flag: true, ascii: false, individual: false, words: false) - elsif Blahaj::CLI["background"] - i_w_none(background: true, flag: false, ascii: false) - elsif Blahaj::CLI["individual"] - handle_input(background: false, flag: false, ascii: false, individual: true, words: false) - elsif Blahaj::CLI["words"] - handle_input(background: false, flag: false, ascii: false, individual: false, words: true) - else - handle_input(background: false, flag: false, ascii: false, individual: false, words: false) - end - {% end %} + Blahaj::CLI.new(ARGV) + Blahaj::Colorizer.new end diff --git a/src/blahaj/color.cr b/src/blahaj/color.cr index 6fc80d7..e92ffdb 100644 --- a/src/blahaj/color.cr +++ b/src/blahaj/color.cr @@ -7,11 +7,12 @@ def clean_hex(hex : String) : String clean_hex = hex.lstrip('#') if clean_hex.size == 3 - tmp_hex = "" - clean_hex.each_char do |char| - tmp_hex += "#{char}#{char}" + clean_hex = String.build do |str| + clean_hex.each_char do |char| + str << char + str << char + end end - clean_hex = tmp_hex end clean_hex.upcase @@ -24,9 +25,8 @@ end # Converts hex to rgb. def hex2rgb(hex : String) : NamedTuple(r: UInt8, g: UInt8, b: UInt8) - clean_hex = clean_hex(hex) + chars = clean_hex(hex).chars.each - chars = clean_hex.chars.each { r: "#{chars.next}#{chars.next}".to_u8(16), g: "#{chars.next}#{chars.next}".to_u8(16), @@ -36,6 +36,9 @@ end module Blahaj class Color + getter r, g, b : UInt8 + getter color : Colorize::ColorRGB + # Initialize `Blahaj::Color` using UInt8 RGB values def initialize(r : UInt8, g : UInt8, b : UInt8) @r = r @@ -69,19 +72,13 @@ module Blahaj initialize(json.read_string) end - # Red value - def r : UInt8 - @r - end + # :nodoc: + def initialize(ctx : YAML::ParseContext, node : YAML::Nodes::Node) + unless node.is_a?(YAML::Nodes::Scalar) + node.raise "Expected scalar, not #{node.kind}" + end - # Green value - def g : UInt8 - @g - end - - # Blue value - def b : UInt8 - @b + initialize(node.value) end # Hex string @@ -89,11 +86,6 @@ module Blahaj @hex.upcase end - # Color as `Colorize::ColorRGB` - def color : Colorize::ColorRGB - @color - end - # Returns the foreground color based on whether the color is dark or light def foreground : Colorize::ColorRGB ((0.299 * @r + 0.587 * @g + 0.114 * @b)/255) > 0.5 ? Colorize::ColorRGB.new(0, 0, 0) : Colorize::ColorRGB.new(255, 255, 255) diff --git a/src/blahaj/colorizer.cr b/src/blahaj/colorizer.cr new file mode 100644 index 0000000..36edf0d --- /dev/null +++ b/src/blahaj/colorizer.cr @@ -0,0 +1,100 @@ +module Blahaj + class Colorizer + @io : IO + @config : Blahaj::Config + @scheme : Array(Blahaj::Color) + @multiplied_cols : Int32 = 1 + @iter : IO::ARGF | String + @proc : Proc(String | Char, Blahaj::Color, Colorize::Object(Char) | Colorize::Object(String)) + + def initialize(config : Blahaj::Config = Blahaj.config, io : IO = STDOUT) + @io = io + @config = config + @scheme = COLORS[config.color].color + + if config.flag + @multiplied_cols = 4 * @scheme.size * config.multiplier + + return print_flag + end + + @proc = proc_bg_fw + @iter = config.shark ? ASCII : ARGF + if config.individual + print_individual + elsif config.words + print_words + elsif config.background + print_background + else + print_color + end + end + + private def print_flag + row = " " * @multiplied_cols + @scheme.each do |x| + @config.multiplier.times do + @io.puts row.colorize.back(x.color) + end + end + end + + private def print_background + @iter.each_line.with_index do |x, i| + @io.puts @proc.call(x, current_color(i)) + end + end + + private def print_individual + i = 0 + + @iter.each_char do |x| + next @io.print x if NO_COLOR.includes?(x) + c_color = current_color(i) + i = i.succ + + @io.print @proc.call(x, c_color) + end + end + + private def print_words + c_color = current_color(0) + dont_change = false + i = 0 + + @iter.each_char do |x| + if NO_COLOR.includes?(x) + unless dont_change + c_color = current_color(i) + i = i.succ + end + dont_change = true + + next @io.print x + end + dont_change = false + + @io.print @proc.call(x, c_color) + end + end + + private def print_color + @iter.each_line.with_index do |x, i| + @io.puts @proc.call(x, current_color(i)) + end + end + + private def proc_bg_fw(flag : Bool = false) : Proc(String | Char, Blahaj::Color, Colorize::Object(Char) | Colorize::Object(String)) + if @config.background + ->(x : String | Char, c_color : Blahaj::Color) { x.colorize.back(c_color.color).fore(c_color.foreground) } + else + ->(x : String | Char, c_color : Blahaj::Color) { x.colorize(c_color.color) } + end + end + + private def current_color(index : Int32) : Blahaj::Color + @scheme[index % @scheme.size] + end + end +end diff --git a/src/blahaj/config.cr b/src/blahaj/config.cr new file mode 100644 index 0000000..1a050d3 --- /dev/null +++ b/src/blahaj/config.cr @@ -0,0 +1,24 @@ +module Blahaj + class Config + INSTANCE = Config.new + + property background : Bool = false + property flag : Bool = false + property shark : Bool = false + property individual : Bool = false + property words : Bool = false + property multiplier : Int32 = 1 + property color : String = "trans" + + def initialize + end + end + + def self.config + yield Config::INSTANCE + end + + def self.config + Config::INSTANCE + end +end diff --git a/src/blahaj/data_parser.cr b/src/blahaj/data_parser.cr new file mode 100644 index 0000000..6962148 --- /dev/null +++ b/src/blahaj/data_parser.cr @@ -0,0 +1,18 @@ +module Blahaj + class Flags + getter flags : Hash(String, Flag) + + class Flag + include YAML::Serializable + + property color : Array(Blahaj::Color) + + @[YAML::Field(key: "alias")] # alias is reserved + property aliases : Array(String) = [] of String + end + + def initialize(yaml_data : String) + @flags = Hash(String, Flag).from_yaml(yaml_data) + end + end +end diff --git a/src/blahaj/option_parser.cr b/src/blahaj/option_parser.cr index 4fab006..0653c67 100644 --- a/src/blahaj/option_parser.cr +++ b/src/blahaj/option_parser.cr @@ -1,76 +1,91 @@ -# [MACRO] Skip on spec -{% skip_file if @top_level.has_constant? "Spec" %} - require "option_parser" module Blahaj Version = {{read_file("#{__DIR__}/../../shard.yml").split("version: ")[1].split("\n")[0]}} # [MACRO] Get blahaj version - # CLI options / defaults - CLI = { - "background" => false, - "color" => "trans", - "flag" => false, - "shark" => false, - "individual" => false, - "multiplier" => 1, - "words" => false, - } + class CLI + # [MACRO] Only expose in spec. + {% if @top_level.has_constant? "Spec" %} + getter config : Blahaj::Config + {% end %} - OptionParser.parse do |parser| - parser.banner = <<-BANNER - #{"BLÅHAJ".colorize(:blue).bold} v#{Version} + def initialize(args : Array(String)?) + @config = Blahaj.config - #{"Usage:".colorize(:light_blue)} - blahaj [arguments] - blahaj [arguments] file - command | blahaj [arguments] - - #{"Examples:".colorize(:light_blue)} - blahaj -c trans ~/.bashrc - blahaj -s -b - neofetch | blahaj -c gay - blahaj -f -c lesbian -m 4 - blahaj -w /etc/os-release - - #{"Arguments:".colorize(:light_blue)} - BANNER - - parser.on("-b", "--background", "Color the background") { CLI["background"] = true } - parser.on("-s", "--shark", "Shork") { CLI["shark"] = true } - parser.on("-f", "--flag", "Return a flag") { CLI["flag"] = true } - parser.on("-i", "--individual", "Color individual characters") { CLI["individual"] = true } - parser.on("-w", "--words", "Color individual words") { CLI["words"] = true } - parser.on("-m MULTIPLIER", "--multiplier=MULTIPLIER", "Multiplier for the flag size (-f)") do |multiplier| - int = multiplier.to_i? - CLI["multiplier"] = int unless int.nil? || int <= 0 + parse args unless args.nil? end - parser.on("-c FLAG", "--colors=FLAG", "Color scheme to use (Default: trans)") do |flag| - down_flag = flag.downcase - unless COLORS.has_key?(down_flag) - puts "Unknown flag/color \"#{down_flag}\".\nPlease pass \"--flags\" for a list of all available flags/colors.".colorize(:red) - exit(1) + + private def parse(args : Array(String)) + OptionParser.parse args do |parser| + parser.banner = <<-BANNER + #{"BLÅHAJ".colorize(:blue).bold} v#{Version} + + #{"Usage:".colorize(:light_blue)} + blahaj [arguments] + blahaj [arguments] file + command | blahaj [arguments] + + #{"Examples:".colorize(:light_blue)} + blahaj -c trans ~/.bashrc + blahaj -s -b + neofetch | blahaj -c gay + blahaj -f -c lesbian -m 4 + blahaj -w /etc/os-release + + #{"Arguments:".colorize(:light_blue)} + BANNER + + parser.on("-b", "--background", "Color the background") { @config.background = true } + parser.on("-s", "--shark", "Shork") { @config.shark = true } + parser.on("-f", "--flag", "Return a flag") { @config.flag = true } + parser.on("-i", "--individual", "Color individual characters") { @config.individual = true } + parser.on("-w", "--words", "Color individual words") { @config.words = true } + parser.on("-m MULTIPLIER", "--multiplier=MULTIPLIER", "Multiplier for the flag size (-f)") do |multiplier| + int = multiplier.to_i? + + @config.multiplier = int unless int.nil? || int <= 0 + end + parser.on("-c FLAG", "--colors=FLAG", "Color scheme to use (Default: trans)") do |flag| + down_flag = flag.downcase + + unless COLORS.has_key?(down_flag) + down_flag = COLORS.find { |k, v| v.aliases.includes?(down_flag) }.try &.[0] + end + + unless !down_flag.nil? && COLORS.has_key?(down_flag) + puts "Unknown flag/color \"#{down_flag}\".\nPlease pass \"--flags\" for a list of all available flags/colors.".colorize(:red) + exit(1) + end + + @config.color = down_flag + end + + parser.on("--flags", "List all available flags") do + puts "Available flags/colors:\n".colorize(:light_blue) + puts COLORS.keys.sort.map { |x| + colors = COLORS[x].color.map { |y| " ".colorize.back(y.color) }.join + "#{x.capitalize} #{colors}" + }.join("\n") + exit + end + + parser.on("-h", "--help", "Show this help") do + puts parser + exit + end + parser.invalid_option do |flag| + STDERR.puts "ERROR: #{flag} is not a valid option." + STDERR.puts parser + exit(1) + end end - down_flag = COLORS[down_flag].as(String).downcase if COLORS[down_flag].is_a?(String) - CLI["color"] = down_flag - end - parser.on("--flags", "List all available flags") do - puts "Available flags/colors:\n".colorize(:light_blue) - # Skip symlink flags (eg. transgender => trans) - puts COLORS.reject { |_, v| v.is_a?(String) }.keys.sort.map { |x| - colors = COLORS[x].as(Array(Blahaj::Color)).map { |y| " ".colorize.back(y.color) }.join - "#{x.capitalize} #{colors}" - }.join("\n") - exit - end - parser.on("-h", "--help", "Show this help") do - puts parser - exit - end - parser.invalid_option do |flag| - STDERR.puts "ERROR: #{flag} is not a valid option." - STDERR.puts parser - exit(1) end + + # [MACRO] Only expose in spec. + {% if @top_level.has_constant? "Spec" %} + def parse(args : Array(String)) + previous_def + end + {% end %} end end