From c82c00a5af11b343c84878154457ee2cbfc5ec8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Galisteo?= Date: Fri, 15 Mar 2024 00:01:42 +0100 Subject: [PATCH] Refactor with renderer --- lib/flatito.rb | 2 + lib/flatito/finder.rb | 101 +++++----------------- lib/flatito/flatten_yaml.rb | 6 +- lib/flatito/regex_from_search.rb | 9 ++ lib/flatito/renderer.rb | 144 +++++++++++++++++++++++++++++++ lib/flatito/tree_iterator.rb | 4 +- 6 files changed, 178 insertions(+), 88 deletions(-) create mode 100644 lib/flatito/regex_from_search.rb create mode 100644 lib/flatito/renderer.rb diff --git a/lib/flatito.rb b/lib/flatito.rb index 58a2849..a618b2c 100644 --- a/lib/flatito.rb +++ b/lib/flatito.rb @@ -7,6 +7,8 @@ require_relative "flatito/flatten_yaml" require_relative "flatito/finder" require_relative "flatito/yaml_with_line_number" +require_relative "flatito/renderer" +require_relative "flatito/regex_from_search" module Flatito def self.search(paths, options) diff --git a/lib/flatito/finder.rb b/lib/flatito/finder.rb index cf71b28..c14b0f1 100644 --- a/lib/flatito/finder.rb +++ b/lib/flatito/finder.rb @@ -1,58 +1,49 @@ # frozen_string_literal: true -require "io/console" +require_relative "regex_from_search" + module Flatito class Finder + include RegexFromSearch + DEFAULT_EXTENSIONS = %w[json yml yaml].freeze - attr_reader :paths, :search, :extensions + attr_reader :paths, :search, :extensions, :options, :renderer def initialize(paths, options = {}) @paths = paths @search = options[:search] @extensions = prepare_extensions(options[:extensions] || DEFAULT_EXTENSIONS) - @no_color = options[:no_color] || false - @skip_hidden = options[:skip_hidden] || true + @options = options + @renderer = Renderer.build(options) end def call - listen_for_stdout_width_change + renderer.prepare paths.each do |path| - TreeIterator.new(path, skip_hidden: @skip_hidden).each do |pathname| - print "\r #{truncate(pathname.to_s, stdout_width - 4)}#{erase_line}" if tty? + TreeIterator.new(path, options).each do |pathname| + renderer.print_file_progress(pathname) if extensions.include?(pathname.extname) - items = FlattenYaml.new(pathname).flatten - items = filter_by_search(items) if search - - next unless items.any? - - line_number_padding = items.map(&:line).max.to_s.length - - print erase_line if tty? - puts colorize(pathname.to_s, :light_blue) - - # TODO: allow sorting by line number or key - # items.sort_by(&:line).each do |item| - items.each do |item| - print_item(item, line_number_padding) - end - puts + flat_and_filter(pathname) end - - $stdout.flush end end - print erase_line if tty? - puts + renderer.ending end private - def no_color? - ENV["TERM"] == "dumb" || ENV["NO_COLOR"] == "true" || @no_color == true + def flat_and_filter(pathname) + items = FlattenYaml.new(pathname).items + items = filter_by_search(items) if search + + return unless items.any? + + renderer.print_pathname(pathname) + renderer.print_items(items) end def prepare_extensions(extensions) @@ -61,62 +52,10 @@ def prepare_extensions(extensions) end end - def truncate(string, max = 50) - string.length > max ? "#{string[0...max]}..." : string - end - - def tty? - $stdout.tty? - end - - def stdout_width - @stdout_width ||= $stdout.winsize[1] - rescue StandardError - 80 - end - - def listen_for_stdout_width_change - Signal.trap(:WINCH) do - @stdout_width = $stdout.winsize[1] - end - end - - def erase_line - "\e[K\e[0G" - end - - def print_item(item, line_number_padding) - line_number = colorize("#{item.line.to_s.rjust(line_number_padding)}: ", :light_yellow) - value = if item.value.length.positive? - colorize("=> #{item.value}", :gray) - else - "" - end - - puts "#{line_number} #{matched_string(item.key)} #{value}\n" - end - def filter_by_search(items) items.select do |item| regex.match?(item.key) end end - - def colorize(string, color) - no_color? ? string : string.colorize(color) - end - - def matched_string(string) - return string if search.nil? || no_color? - - regex.match(string).to_a&.each do |match| - string = string.gsub(/#{match}/, match.colorize(:light_red)) - end - string - end - - def regex - @regex ||= Regexp.new(search) - end end end diff --git a/lib/flatito/flatten_yaml.rb b/lib/flatito/flatten_yaml.rb index be27451..69ee3f8 100644 --- a/lib/flatito/flatten_yaml.rb +++ b/lib/flatito/flatten_yaml.rb @@ -7,11 +7,7 @@ def initialize(pathname) @pathname = pathname end - def entries - flatten - end - - def flatten + def items with_line_numbers.compact.flat_map do |line| flatten_hash(line) if line.is_a?(Hash) end.compact diff --git a/lib/flatito/regex_from_search.rb b/lib/flatito/regex_from_search.rb new file mode 100644 index 0000000..edf4cf4 --- /dev/null +++ b/lib/flatito/regex_from_search.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Flatito + module RegexFromSearch + def regex + @regex ||= Regexp.new(search) + end + end +end diff --git a/lib/flatito/renderer.rb b/lib/flatito/renderer.rb new file mode 100644 index 0000000..bb5758b --- /dev/null +++ b/lib/flatito/renderer.rb @@ -0,0 +1,144 @@ +# frozen_string_literal: true + +require "io/console" +require_relative "regex_from_search" + +module Flatito + class Renderer + include RegexFromSearch + + def self.build(options) + if tty? + Renderer::TTY.new(options) + else + Renderer::Plain.new(options) + end + end + + def self.tty? + $stdout.tty? + end + end + + class Base + attr_reader :search, :no_color + + def initialize(options) + @no_color = options[:no_color] || false + @search = options[:search] + end + + def prepare; end + def print_file_progress(pathname); end + def ending; end + + def print_pathname(pathname) + puts colorize(pathname.to_s, :light_blue) + end + + def print_items(items) + line_number_padding = items.map(&:line).max.to_s.length + + items.each do |item| + print_item(item, line_number_padding) + end + puts + flush + end + + def print_item(item, line_number_padding) + line_number = colorize("#{item.line.to_s.rjust(line_number_padding)}: ", :light_yellow) + value = if item.value.length.positive? + colorize("=> #{item.value}", :gray) + else + "" + end + + puts "#{line_number} #{matched_string(item.key)} #{value}\n" + end + + private + + def flush + stdout.flush + end + + def regex + @regex ||= Regexp.new(search) + end + + def matched_string(string) + return string if search.nil? || no_color? + + regex.match(string).to_a&.each do |match| + string = string.gsub(/#{match}/, match.colorize(:light_red)) + end + string + end + + def no_color? + ENV["TERM"] == "dumb" || ENV["NO_COLOR"] == "true" || no_color == true + end + + def truncate(string, max = 50) + string.length > max ? "#{string[0...max]}..." : string + end + + def stdout + $stdout + end + + def colorize(string, color) + no_color? ? string : string.colorize(color) + end + end + + class Renderer::Plain < Base + def ending + puts + end + end + + class Renderer::TTY < Base + def initialize(options) + super + require "io/console" + end + + def prepare + listen_for_stdout_width_change + end + + def print_file_progress(pathname) + print "\r #{truncate(pathname.to_s, stdout_width - 4)}#{erase_line}" + end + + def print_pathname(pathname) + print erase_line + super + end + + def ending + print erase_line + puts + end + + private + + def erase_line + "\e[K\e[0G" + end + + def stdout_width + @stdout_width ||= stdout.winsize[1] + rescue StandardError + 80 + end + + def listen_for_stdout_width_change + Signal.trap(:WINCH) do + @stdout_width = stdout.winsize[1] + end + end + end +end diff --git a/lib/flatito/tree_iterator.rb b/lib/flatito/tree_iterator.rb index 663cbf4..202940a 100644 --- a/lib/flatito/tree_iterator.rb +++ b/lib/flatito/tree_iterator.rb @@ -6,9 +6,9 @@ class TreeIterator attr_reader :base_path, :skip_hidden - def initialize(base_path, skip_hidden: true) + def initialize(base_path, options = {}) @base_path = base_path - @skip_hidden = skip_hidden + @skip_hidden = options[:skip_hidden] || true end def each(&block)