#!/usr/bin/env ruby require 'tins' include Tins::GO require 'term/ansicolor' include Term::ANSIColor class String include Term::ANSIColor end require 'hackmac' include Hackmac require 'amatch' require 'search_ui' include SearchUI $opts = go 'c:m:n:jlh', defaults: { ?s => true, ?n => 5 } def usage puts <<~end Usage: #{File.basename($0)} [OPTIONS] OPTIONS are -h this help -l output GPU performance data as list -j output GPU performance data as json -n SECONDS measure every SECONDS -m METRIC output graph for performance METRIC -c COLOR output graph in this terminal COLOR (between 0 - 255) end 0 end def ps `ioreg -l`.lines.find { |l| if l =~ /"PerformanceStatistics" = {([^}]+)}/ break Hash[ $1.split(?,).map { |a| a = a.split(?=) [ a[0][1..-2], (Integer(a[1]) rescue a[1]) ] }.sort_by { |name, _| name.downcase } ] end } end def list(ps) max = ps.keys.max_by(&:size)&.size&.to_i include Hackmac::Graph::Formatters puts ps.map { |n, v| ("%-#{max}s" % n) + " " + ("%s" % send(derive_formatter(n), v)).bold } end def choose_metric(ps) case metric = $opts[?m] when nil ps_names = ps.keys metric = Search.new( match: -> answer { matcher = Amatch::PairDistance.new(answer.downcase) matches = ps_names.map { |n| [ n, -matcher.similar(n.downcase) ] }. select { |_, s| s < 0 }.sort_by(&:last).map(&:first) matches.empty? and matches = ps_names matches.first(Tins::Terminal.lines - 1) }, query: -> _answer, matches, selector { matches.each_with_index. map { |m, i| i == selector ? m.on_blue : m } * ?\n }, found: -> _answer, matches, selector { matches[selector] }, output: STDOUT ).start and return metric else ps.key?(metric) and return metric end fail "Metric #{metric} not known" end def derive_formatter(metric) case metric when /bytes/i :as_bytes when /Hz/ :as_hertz when /\(C\)/ :as_celsius when /\(%\)/ :as_percent else :as_default end end def display_graph if metric = choose_metric(ps) sleep_duration = [ 1, ($opts[?n] || 10).to_i ].max format_value = derive_formatter(metric) graph = Hackmac::Graph.new( title: metric, sleep: sleep_duration, value: -> _ { ps[metric] }, color: $opts[?c], format_value: ) graph.start end ensure graph&.stop end case when $opts[?h] exit usage when $opts[?l] list ps when $opts[?j] jj ps else display_graph end