class Rigor::ModuleGraph::CLI::StatsCmd
stats reports the fan-out / fan-in / internal / nodes numbers per namespace. Same filter flags as the renderers so a focused subgraph can be summarised without regenerating the JSONL.
Constants
- FORMATS
- HEADERS
Public Class Methods
Source
# File lib/rigor/module_graph/cli.rb, line 956 def initialize(stdout:, stderr:, stdin:) @stdout = stdout @stderr = stderr @stdin = stdin @state = { kinds: nil, confidences: nil, from: nil, depth: nil, direction: :both, edge_scope: :cluster, grouping_depth: 1, format: "text", limit: nil } end
Public Instance Methods
Source
# File lib/rigor/module_graph/cli.rb, line 1049 def format_row(row, widths) row.each_with_index.map do |cell, idx| idx.zero? ? cell.ljust(widths[idx]) : cell.rjust(widths[idx]) end.join(" ") end
Source
# File lib/rigor/module_graph/cli.rb, line 1031 def format_table(metrics) if metrics.empty? return "(no edges)\n" end rows = metrics.map do |m| [m.namespace, m.nodes.to_s, m.fan_out.to_s, m.fan_in.to_s, m.internal.to_s, m.total.to_s] end widths = HEADERS.zip(*rows).map { |col| col.map(&:length).max } out = +"" out << format_row(HEADERS, widths) << "\n" out << ("-" * widths.sum { |w| w + 2 }) << "\n" rows.each { |row| out << format_row(row, widths) << "\n" } out end
A space-padded text table sized to the widest cell per column. Numeric columns are right-aligned so a quick eye-scan finds the hotspots.
Source
# File lib/rigor/module_graph/cli.rb, line 995 def parse_options!(argv) parser = OptionParser.new do |opts| opts.banner = "Usage: rigor-module-graph stats [options] [FILE]" opts.on("--grouping-depth N", Integer, "How many leading namespace segments to group by (default: 1)") do |n| @state[:grouping_depth] = n end opts.on("--limit N", Integer, "Show only the top N namespaces by fan-out") do |n| @state[:limit] = n end opts.on("--format FORMAT", FORMATS, "Output format (#{FORMATS.join("/")}; default: text)") do |fmt| @state[:format] = fmt end add_filter_options(opts, @state) opts.on("-h", "--help") do @stdout.puts opts exit 0 end end parser.parse!(argv) end
Source
# File lib/rigor/module_graph/cli.rb, line 1019 def render(metrics) case @state[:format] when "json" @stdout.puts(JSON.pretty_generate(metrics.map(&:to_h))) when "text" @stdout.print(format_table(metrics)) end end
Source
# File lib/rigor/module_graph/cli.rb, line 967 def run(argv) argv = argv.dup parse_options!(argv) path, = argv io = path ? File.open(path, "r") : @stdin begin edges = EdgeIO.read(io) ensure io.close if path && !io.closed? end edges = apply_filters( edges, kinds: @state[:kinds], confidences: @state[:confidences], from: @state[:from], depth: @state[:depth], direction: @state[:direction], edge_scope: @state[:edge_scope] ) metrics = Stats.compute(edges, depth: @state[:grouping_depth]) metrics = metrics.first(@state[:limit]) if @state[:limit] render(metrics) 0 rescue OptionParser::ParseError => e @stderr.puts "rigor-module-graph stats: #{e.message}" 2 end