diff --git a/xbar/brew-cask-updates.1h.rb b/xbar/brew-cask-updates.1h.rb deleted file mode 100755 index 887f546..0000000 --- a/xbar/brew-cask-updates.1h.rb +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -# Brew Cask Updates -# v2.0.0 -# Jim Myhrberg -# jimeh -# Show outdated Homebrew casks -# https://i.imgur.com/aAD0pqO.png -# ruby -# -# string(VAR_BREW_PATH="/usr/local/bin/brew"): Path to "brew" executable. - -# rubocop:disable Style/IfUnlessModifier - -require 'open3' -require 'json' - -module Xbar - class Printer - attr_reader :nested_level - - SUB_STR = '--' - SEP_STR = '---' - PARAM_SEP = '|' - - def initialize(nested_level = 0) - @nested_level = nested_level - end - - def item(label = nil, **props) - print_item(label, **props) if !label.nil? && !label.empty? - - yield(sub_printer) if block_given? - end - - def separator - print_item(SEP_STR) - end - alias sep separator - - private - - def print_item(text, **props) - output = [text] - unless props.empty? - output << PARAM_SEP - output += props.map { |k, v| "#{k}=\"#{v}\"" } - end - - $stdout.print(SUB_STR * nested_level, output.join(' ')) - $stdout.puts - end - - def sub_printer - @sub_printer || self.class.new(nested_level + 1) - end - end -end - -module Brew - class CommandError < StandardError; end - - class Common - def self.prefix(value = nil) - return @prefix if value.nil? || value == '' - - @prefix = value - end - - private - - def prefix - self.class.prefix - end - - def default_printer - @default_printer ||= ::Xbar::Printer.new - end - - def cmd(*args) - out, err, s = Open3.capture3(*args) - raise CommandError, "#{args.join(' ')}: #{err}" if s.exitstatus != 0 - - out - end - - def brew_path - @brew_path ||= ENV.fetch('VAR_BREW_PATH', '/usr/local/bin/brew') - end - - def brew_check(printer = nil) - printer ||= default_printer - return if File.exist?(brew_path) - - printer.item("#{prefix}↑:warning:", dropdown: false) - printer.sep - printer.item('Homebrew not found', color: 'red') - printer.item("Executable \"#{brew_path}\" does not exist.") - printer.sep - printer.item( - 'Visit https://brew.sh/ for installation instructions', - href: 'https://brew.sh' - ) - - exit 0 - end - - def brew_update - cmd(brew_path, 'update') - rescue CommandError => e - # Continue as if nothing happened when brew update fails, as it likely - # to be due to another update process is already running. - end - end - - class Cask - attr_reader :name, :installed_version, :latest_version - - def initialize(attributes = {}) - @name = attributes['name'] - @installed_version = attributes['installed_versions'] - @latest_version = attributes['current_version'] - end - - alias current_version installed_version - end - - class CaskUpdates < Common - prefix ':tropical_drink:' - - def run - printer = default_printer - - brew_check(printer) - brew_update - - printer.item("#{prefix}↑#{casks.size}", dropdown: false) - printer.sep - printer.item('Brew Cask Updates') - printer.item("#{casks.size} outdated") do |printer| - printer.sep - printer.item(':hourglass: Refresh', refresh: true) - end - - print_casks(printer) - printer.sep - printer.item('Refresh', refresh: true) - end - - private - - def print_casks(printer) - return unless casks.size.positive? - - printer.item( - 'Upgrade all casks', - terminal: true, refresh: true, - shell: brew_path, param1: 'upgrade' - ) - printer.sep - printer.item('Upgrade:') - casks.each do |cask| - printer.item(cask.name) do |printer| - printer.item( - 'Upgrade', - terminal: true, refresh: true, shell: brew_path, - param1: 'upgrade', param2: '--cask', param3: cask.name - ) - printer.item( - "Upgrade (#{cask.current_version} → #{cask.latest_version})", - alternate: true, terminal: true, refresh: true, - shell: brew_path, param1: 'upgrade', param2: '--cask', - param3: cask.name - ) - printer.sep - printer.item("Installed: #{cask.installed_version}") - printer.item("Latest: #{cask.latest_version}") - printer.sep - printer.item('Uninstall') do |printer| - printer.item('Are you sure?') - printer.sep - printer.item( - 'Yes', - terminal: true, refresh: true, - shell: brew_path, param1: 'uninstall', - param2: '--cask', param3: cask.name - ) - end - end - end - end - - def casks - @casks ||= JSON.parse( - cmd(brew_path, 'outdated', '--cask', '--json') - )['casks'].map { |line| Cask.new(line) } - end - end -end - -begin - Brew::CaskUpdates.new.run -rescue StandardError => e - puts "ERROR: #{e.message}:\n\t#{e.backtrace.join("\n\t")}" - exit 1 -end - -# rubocop:enable Style/IfUnlessModifier diff --git a/xbar/brew-formula-updates.1h.rb b/xbar/brew-updates.1h.rb similarity index 67% rename from xbar/brew-formula-updates.1h.rb rename to xbar/brew-updates.1h.rb index efb609f..fd5cd5d 100755 --- a/xbar/brew-formula-updates.1h.rb +++ b/xbar/brew-updates.1h.rb @@ -1,12 +1,12 @@ #!/usr/bin/env ruby # frozen_string_literal: true -# Brew Formula Updates +# Brew Updates # v2.0.0 # Jim Myhrberg # jimeh -# Show outdated Homebrew formulas -# https://i.imgur.com/6PC6OPg.png +# List and manage outdated Homebrew formulas and casks +# https://i.imgur.com/gHrTZpd.png # ruby # # string(VAR_BREW_PATH="/usr/local/bin/brew"): Path to "brew" executable. @@ -131,8 +131,20 @@ module Brew end end + class Cask + attr_reader :name, :installed_version, :latest_version + + def initialize(attributes = {}) + @name = attributes['name'] + @installed_version = attributes['installed_versions'] + @latest_version = attributes['current_version'] + end + + alias current_version installed_version + end + class FormulaUpdates < Common - prefix ':beer:' + prefix ':beers:' def run printer = default_printer @@ -140,21 +152,28 @@ module Brew brew_check(printer) brew_update - printer.item("#{prefix}↑#{formulas.size}", dropdown: false) + printer.item("#{prefix}↑#{formulas.size + casks.size}", dropdown: false) printer.sep - printer.item('Brew Formula Updates') + printer.item('Brew Updates') pinned_msg = " / #{pinned.size} pinned" if pinned.size.positive? printer.item( - "#{formulas.size} outdated#{pinned_msg}" + "#{formulas.size} formulas / #{casks.size} casks#{pinned_msg}" ) do |printer| printer.sep printer.item(':hourglass: Refresh', refresh: true) end + printer.item('Upgrade All') do |printer| + printer.item('Are you sure?') + printer.item( + 'Yes', + terminal: true, refresh: true, shell: brew_path, param1: 'upgrade' + ) + end print_formulas(printer) + print_casks(printer) print_pinned(printer) printer.sep - printer.item('Refresh', refresh: true) end private @@ -162,12 +181,16 @@ module Brew def print_formulas(printer) return unless formulas.size.positive? - printer.item( - 'Upgrade all formula', - terminal: true, refresh: true, shell: brew_path, param1: 'upgrade' - ) printer.sep - printer.item('Upgrade:') + printer.item('Formulas:') + printer.item('Upgrade All') do |printer| + printer.item('Are you sure?') + printer.item( + 'Yes', + terminal: true, refresh: true, shell: brew_path, param1: 'upgrade', + param2: '--formula' + ) + end formulas.each do |formula| printer.item(formula.name) do |printer| printer.item( @@ -196,7 +219,6 @@ module Brew ) printer.item('Uninstall') do |printer| printer.item('Are you sure?') - printer.sep printer.item( 'Yes', terminal: true, refresh: true, @@ -207,11 +229,55 @@ module Brew end end + def print_casks(printer) + return unless casks.size.positive? + + printer.sep + printer.item('Casks:') + printer.item('Upgrade All') do |printer| + printer.item('Are you sure?') + printer.item( + 'Yes', + terminal: true, refresh: true, + shell: brew_path, param1: 'upgrade', param2: '--cask' + ) + end + casks.each do |cask| + printer.item(cask.name) do |printer| + printer.item( + 'Upgrade', + terminal: true, refresh: true, shell: brew_path, + param1: 'upgrade', param2: '--cask', param3: cask.name + ) + printer.item( + "Upgrade (#{cask.current_version} → #{cask.latest_version})", + alternate: true, terminal: true, refresh: true, + shell: brew_path, param1: 'upgrade', param2: '--cask', + param3: cask.name + ) + printer.sep + printer.item("Installed: #{cask.installed_version}") + printer.item("Latest: #{cask.latest_version}") + printer.sep + printer.item('Uninstall') do |printer| + printer.item('Are you sure?') + printer.sep + printer.item( + 'Yes', + terminal: true, refresh: true, + shell: brew_path, param1: 'uninstall', + param2: '--cask', param3: cask.name + ) + end + end + end + end + def print_pinned(printer) return unless pinned.size.positive? printer.sep - printer.item('Pinned:') + printer.item('Pinned Formulas:') pinned.each do |formula| printer.item(formula.name) do |printer| printer.item('Upgrade') @@ -233,7 +299,6 @@ module Brew ) printer.item('Uninstall') do |printer| printer.item('Are you sure?') - printer.sep printer.item( 'Yes', terminal: true, refresh: true, @@ -245,17 +310,23 @@ module Brew end def formulas - @formulas ||= outdated.reject(&:pinned) + @formulas ||= all_formulas.reject(&:pinned) end def pinned - @pinned ||= outdated.select(&:pinned) + @pinned ||= all_formulas.select(&:pinned) + end + + def all_formulas + @all_formulas ||= outdated['formulae'].map { |line| Formula.new(line) } + end + + def casks + @casks ||= outdated['casks'].map { |line| Cask.new(line) } end def outdated - @outdated ||= JSON.parse( - cmd(brew_path, 'outdated', '--formula', '--json') - )['formulae'].map { |line| Formula.new(line) } + @outdated ||= JSON.parse(cmd(brew_path, 'outdated', '--json')) end end end