# frozen_string_literal: true module Wayfarer module CLI class RoutePrinter < Thor::Shell::Color attr_reader :url, :path_finder, :output INDENT = " " REGULAR_SEGMENT = "│ " JUNCTION_SEGMENT = "├──" CORNER_SEGMENT = "└──" def self.print(route, url) route.accept(new(url)) end def initialize(url) @url = url @path_finder = Wayfarer::Routing::PathFinder.new(url) super() end def visit(route) route.accept(path_finder) unless route.parent return true if route.is_a?(Wayfarer::Routing::RootRoute) puts [segments(route), label(route)].join("")[3..] true end def segments(route) current = segment(route) parents = parents(route).map { |parent| parent_segment(parent) } [parents, current].join end def parent_segment(parent) if trailer?(parent) INDENT else REGULAR_SEGMENT end end def segment(route) if trailer?(route) CORNER_SEGMENT else JUNCTION_SEGMENT end end def label(route) [highlight_matcher(route, matcher_label(route)), highlight_options(route, options(route)), highlight_options(route, params(route))].compact.join(" ") end def highlight_matcher(route, string) if path_finder.path.include?(route) set_color(string, :green, :bold) elsif route.matcher.match(url) set_color(string, :green) else set_color(string, :red) end end def highlight_options(route, string) return string unless path_finder.path.include?(route) set_color(string, :green, :bold) end def matcher_label(route) return "Target" if route.is_a?(Wayfarer::Routing::TargetRoute) route.matcher.class.name.demodulize end def options(route) return "" if route.is_a?(Wayfarer::Routing::RootRoute) case (matcher = route.matcher) when Wayfarer::Routing::Matchers::Host then matcher.host when Wayfarer::Routing::Matchers::Path then matcher.path when Wayfarer::Routing::Matchers::Query then matcher.fields when Wayfarer::Routing::Matchers::Custom then "##{route.action}" when Wayfarer::Routing::Matchers::Scheme then matcher.scheme when Wayfarer::Routing::Matchers::Suffix then matcher.suffix end end def params(route) params = route.matcher.params(url) "=> #{params.symbolize_keys}" if params.any? end private def parents(route, current = []) return current unless route.parent parents(route.parent, [route.parent, *current]) end def trailer?(route) return true unless route.parent route.parent.children.last == route end end end end