lib/spoom/cli/helper.rb in spoom-1.0.8 vs lib/spoom/cli/helper.rb in spoom-1.0.9

- old
+ new

@@ -9,41 +9,57 @@ module Cli module Helper extend T::Sig include Thor::Shell + # Print `message` on `$stdout` + sig { params(message: String).void } + def say(message) + buffer = StringIO.new + buffer << highlight(message) + buffer << "\n" unless message.end_with?("\n") + + $stdout.print(buffer.string) + $stdout.flush + end + # Print `message` on `$stderr` # # The message is prefixed by a status (default: `Error`). - sig { params(message: String, status: String).void } - def say_error(message, status = "Error") - status = set_color(status, :red) - + sig do + params( + message: String, + status: T.nilable(String), + nl: T::Boolean + ).void + end + def say_error(message, status: "Error", nl: true) buffer = StringIO.new - buffer << "#{status}: #{message}" - buffer << "\n" unless message.end_with?("\n") + buffer << "#{red(status)}: " if status + buffer << highlight(message) + buffer << "\n" if nl && !message.end_with?("\n") $stderr.print(buffer.string) $stderr.flush end # Is `spoom` ran inside a project with a `sorbet/config` file? sig { returns(T::Boolean) } def in_sorbet_project? - File.file?(sorbet_config) + File.file?(sorbet_config_file) end # Enforce that `spoom` is ran inside a project with a `sorbet/config` file # # Display an error message and exit otherwise. sig { void } def in_sorbet_project! unless in_sorbet_project? say_error( - "not in a Sorbet project (#{colorize(sorbet_config, :yellow)} not found)\n\n" \ + "not in a Sorbet project (`#{sorbet_config_file}` not found)\n\n" \ "When running spoom from another path than the project's root, " \ - "use #{colorize('--path PATH', :blue)} to specify the path to the root." + "use `--path PATH` to specify the path to the root." ) Kernel.exit(1) end end @@ -52,24 +68,82 @@ def exec_path T.unsafe(self).options[:path] # TODO: requires_ancestor end sig { returns(String) } - def sorbet_config + def sorbet_config_file Pathname.new("#{exec_path}/#{Spoom::Sorbet::CONFIG_PATH}").cleanpath.to_s end + sig { returns(Sorbet::Config) } + def sorbet_config + Sorbet::Config.parse_file(sorbet_config_file) + end + + # Colors + + # Color used to highlight expressions in backticks + HIGHLIGHT_COLOR = :blue + # Is the `--color` option true? sig { returns(T::Boolean) } def color? T.unsafe(self).options[:color] # TODO: requires_ancestor end + sig { params(string: String).returns(String) } + def highlight(string) + return string unless color? + + res = StringIO.new + word = StringIO.new + in_ticks = T.let(false, T::Boolean) + string.chars.each do |c| + if c == '`' && !in_ticks + in_ticks = true + elsif c == '`' && in_ticks + in_ticks = false + res << colorize(word.string, HIGHLIGHT_COLOR) + word = StringIO.new + elsif in_ticks + word << c + else + res << c + end + end + res.string + end + # Colorize a string if `color?` sig { params(string: String, color: Symbol).returns(String) } def colorize(string, color) return string unless color? string.colorize(color) + end + + sig { params(string: String).returns(String) } + def blue(string) + colorize(string, :blue) + end + + sig { params(string: String).returns(String) } + def gray(string) + colorize(string, :light_black) + end + + sig { params(string: String).returns(String) } + def green(string) + colorize(string, :green) + end + + sig { params(string: String).returns(String) } + def red(string) + colorize(string, :red) + end + + sig { params(string: String).returns(String) } + def yellow(string) + colorize(string, :yellow) end end end end