# frozen_string_literal: true module Wayfarer class 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 puts format_route_output(route) true end private def format_route_output(route) [segments(route), route_description(route)].join[3..] end def segments(route) [parents(route).map { |parent| parent_segment(parent) }, segment(route)].join end def parent_segment(parent) trailer?(parent) ? INDENT : REGULAR_SEGMENT end def segment(route) trailer?(route) ? CORNER_SEGMENT : JUNCTION_SEGMENT end def route_description(route) attrs = [route_arg(route), routing_result(route), route_action(route), route_params(route)].compact text = attrs.any? ? "#{matcher_name(route)}(#{attrs.join(', ')})" : matcher_name(route) set_color(text, *route_colors(route)) end def matcher_name(route) case route when Wayfarer::Routing::TargetRoute "Target" when Wayfarer::Routing::RootRoute Wayfarer::Routing::PathFinder.result(route, url).class.name.demodulize else route.matcher.class.name.demodulize end end def routing_result(route) return if route.is_a?(Wayfarer::Routing::RootRoute) "match: #{route.matcher.match(url)}" end def route_action(route) return unless route.is_a?(Wayfarer::Routing::RootRoute) result = Wayfarer::Routing::PathFinder.result(route, url) result.action.inspect if result.is_a?(Wayfarer::Routing::Result::Match) end def route_arg(route) return if route.is_a?(Wayfarer::Routing::RootRoute) || route.is_a?(Wayfarer::Routing::TargetRoute) matcher = route.matcher matcher_opts = case 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.to_s when Wayfarer::Routing::Matchers::Scheme then matcher.scheme when Wayfarer::Routing::Matchers::Suffix then matcher.suffix end matcher_opts.inspect end def route_params(route) params = if route.is_a?(Wayfarer::Routing::RootRoute) result = Wayfarer::Routing::PathFinder.result(route, url) result.params if result.is_a?(Wayfarer::Routing::Result::Match) else route.matcher.params(url) end "params: #{params.symbolize_keys}" if params&.any? end def parents(route, current = []) return current unless route.parent parents(route.parent, [route.parent, *current]) end def trailer?(route) !route.parent || route.parent.children.last == route end def route_colors(route) if path_finder.path.include?(route) %i[green bold] elsif route.matcher.match(url) %i[green] else %i[red] end end def set_color(string, *colors) return string if ENV.key?("NO_COLOR") super(string, *colors) end end end end