diff --git a/xbar/brew-updates.1h.rb b/xbar/brew-updates.1h.rb
index d2d8c5a..7adf4a3 100755
--- a/xbar/brew-updates.1h.rb
+++ b/xbar/brew-updates.1h.rb
@@ -4,18 +4,23 @@
# rubocop:disable Layout/LineLength
# Brew Updates
-# v2.5.2
+# v2.6.0
# Jim Myhrberg
# jimeh
# List and manage outdated Homebrew formulas and casks
-# https://i.imgur.com/7gJDWmu.png
+# https://i.imgur.com/HbSHhaa.png
# ruby
# https://github.com/jimeh/dotfiles/tree/main/xbar
#
# string(VAR_BREW_PATH=""): Path to "brew" executable.
-# string(VAR_GREEDY=""): Comma separted list of greedy types for brew outdated command ("latest", "auto-updates").
+# boolean(VAR_GREEDY_LATEST=false): Run "brew outdated" with --greedy-latest flag..
+# boolean(VAR_GREEDY_AUTO_UPDATES=false): Run "brew outdated" with --greedy-auto-updates flag.
+# boolean(VAR_POST_RUN_CLEANUP=false): Run "brew cleanup" after package changes.
+# boolean(VAR_POST_RUN_DOCTOR=false): Run "brew cleanup" after package changes.
+# string(VAR_UPGRADE_ALL_EXCLUDE=""): Comma-separated list formulas/casks to exclude from upgrade all operations.
# rubocop:enable Layout/LineLength
+
# rubocop:disable Lint/ShadowingOuterLocalVariable
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/BlockLength
@@ -31,6 +36,7 @@ require 'set'
module Xbar
class CommandError < StandardError; end
+ class RPCError < StandardError; end
module Service
private
@@ -65,7 +71,9 @@ module Xbar
def run(argv = [])
return service.run if argv.empty?
- return unless service.respond_to?(argv[0])
+ unless service.respond_to?(argv[0])
+ raise RPCError, "Unknown RPC method: #{argv[0]}"
+ end
service.public_send(*argv)
end
@@ -232,7 +240,7 @@ module Brew
printer ||= default_printer
return if File.exist?(brew_path)
- printer.item("#{prefix}β:warning:", dropdown: false)
+ printer.item("#{prefix}ββ οΈ", dropdown: false)
printer.sep
printer.item('Homebrew not found', color: 'red')
printer.item("Executable \"#{brew_path}\" does not exist.")
@@ -276,7 +284,7 @@ module Brew
end
class FormulaUpdates < Common
- prefix ':beers:'
+ prefix 'π»'
def run
brew_check(printer)
@@ -285,68 +293,54 @@ module Brew
printer.item("#{prefix}β#{formulas.size + casks.size}", dropdown: false)
printer.sep
printer.item('Brew UpdatesοΈ') do |printer|
- printer.item('Settings')
- printer.sep
-
- if greedy_latest?
- printer.item(
- ':white_check_mark: Greedy: Latest',
- rpc: %w[remove_greedy latest],
- refresh: true
- )
- else
- printer.item(
- ':ballot_box_with_check: Greedy: Latest',
- rpc: %w[add_greedy latest],
- refresh: true
- )
- end
-
- if greedy_auto_updates?
- printer.item(
- ':white_check_mark: Greedy: Auto Updates',
- rpc: %w[remove_greedy auto_updates],
- refresh: true
- )
- else
- printer.item(
- ':ballot_box_with_check: Greedy: Auto Updates',
- rpc: %w[add_greedy auto_updates],
- refresh: true
- )
- end
+ print_settings(printer)
end
printer.item(status_label) do |printer|
- printer.item(
- ':hourglass: Refresh',
- alt: ':hourglass: Refresh (βR)',
- refresh: true
- )
+ printer.item('β³ Refresh', alt: 'β³ Refresh (βR)', refresh: true)
printer.sep
- if formulas.size.positive? && casks.size.positive?
+ all_formulas = formulas.reject { |f| upgrade_all_exclude?(f.name) }
+ all_casks = casks.reject { |c| upgrade_all_exclude?(c.name) }
+ excluded = ((formulas - all_formulas) + (casks - all_casks))
+
+ if all_formulas.size.positive? && all_casks.size.positive?
+ names = all_formulas.map(&:name) + all_casks.map(&:name)
printer.item(
- "Upgrade All (#{formulas.size + casks.size})",
+ "β¬οΈ Upgrade All (#{all_formulas.size + all_casks.size})",
terminal: true, refresh: true,
- shell: [brew_path, 'upgrade'] +
- formulas.map(&:name) + casks.map(&:name)
+ shell: [
+ brew_path, 'upgrade'
+ ] + names + post_commands(names)
)
end
- if formulas.size.positive?
+ if all_formulas.size.positive?
+ names = all_formulas.map(&:name)
printer.item(
- "Upgrade All Formulas (#{formulas.size})",
+ "β¬οΈ Upgrade All Formulas (#{all_formulas.size})",
terminal: true, refresh: true,
- shell: [brew_path, 'upgrade', '--formula'] + formulas.map(&:name)
+ shell: [
+ brew_path, 'upgrade', '--formula'
+ ] + names + post_commands(names)
)
end
- if casks.size.positive?
+ if all_casks.size.positive?
+ names = all_casks.map(&:name)
printer.item(
- "Upgrade All Casks (#{casks.size})",
+ "β¬οΈ Upgrade All Casks (#{all_casks.size})",
terminal: true, refresh: true,
- shell: [brew_path, 'upgrade', '--cask'] + casks.map(&:name)
+ shell: [
+ brew_path, 'upgrade', '--cask'
+ ] + names + post_commands(names)
)
end
+ if excluded.size.positive?
+ printer.sep
+ printer.item("Excluded (#{excluded.size}):")
+ excluded.sort_by(&:name).each do |item|
+ printer.item(item.name)
+ end
+ end
end
print_formulas(printer)
@@ -355,24 +349,72 @@ module Brew
printer.sep
end
- def add_greedy(*args)
- vals = greedy_types.clone
- vals += args.map(&:strip).reject(&:empty?)
-
- config['VAR_GREEDY'] = vals.sort.join(',')
+ def greedy_latest(*args)
+ config['VAR_GREEDY_LATEST'] = truthy?(args.first)
config.save
end
- def remove_greedy(*args)
- vals = greedy_types.clone
- vals -= args.map(&:strip).reject(&:empty?)
+ def greedy_auto_updates(*args)
+ config['VAR_GREEDY_AUTO_UPDATES'] = truthy?(args.first)
+ config.save
+ end
- config['VAR_GREEDY'] = vals.sort.join(',')
+ def post_run_cleanup(*args)
+ config['VAR_POST_RUN_CLEANUP'] = truthy?(args.first)
+ config.save
+ end
+
+ def post_run_doctor(*args)
+ config['VAR_POST_RUN_DOCTOR'] = truthy?(args.first)
+ config.save
+ end
+
+ def exclude_upgrade_all(*args)
+ exclude = upgrade_all_exclude.clone
+ exclude += args.map(&:strip).reject(&:empty?)
+
+ config['VAR_UPGRADE_ALL_EXCLUDE'] = exclude.sort.join(',')
+ config.save
+ end
+
+ def include_upgrade_all(*args)
+ exclude = upgrade_all_exclude.clone
+ exclude -= args.map(&:strip).reject(&:empty?)
+
+ config['VAR_UPGRADE_ALL_EXCLUDE'] = exclude.sort.join(',')
config.save
end
private
+ def greedy_latest?
+ @greedy_latest ||= truthy?(config['VAR_GREEDY_LATEST'])
+ end
+
+ def greedy_auto_updates?
+ @greedy_auto_updates ||= truthy?(config['VAR_GREEDY_AUTO_UPDATES'])
+ end
+
+ def post_run_cleanup?
+ @post_run_cleanup ||= truthy?(config['VAR_POST_RUN_CLEANUP'])
+ end
+
+ def post_run_doctor?
+ @post_run_doctor ||= truthy?(config['VAR_POST_RUN_DOCTOR'])
+ end
+
+ def upgrade_all_exclude?(name)
+ upgrade_all_exclude.include?(name)
+ end
+
+ def upgrade_all_exclude
+ @upgrade_all_exclude ||= config.as_set('VAR_UPGRADE_ALL_EXCLUDE')
+ end
+
+ def truthy?(value)
+ %w[true yes 1 on y t].include?(value.to_s.downcase)
+ end
+
def brew_update
cmd(brew_path, 'update')
rescue Xbar::CommandError
@@ -390,36 +432,89 @@ module Brew
label.join(', ')
end
+ def print_settings(printer)
+ printer.item('Settings')
+ printer.sep
+
+ print_rpc_toggle(
+ printer, 'Greedy: Latest', 'greedy_latest', greedy_latest?
+ )
+
+ print_rpc_toggle(
+ printer, 'Greedy: Auto Updates', 'greedy_auto_updates',
+ greedy_auto_updates?
+ )
+
+ print_rpc_toggle(
+ printer, 'Post Run: Cleanup', 'post_run_cleanup', post_run_cleanup?
+ )
+
+ print_rpc_toggle(
+ printer, 'Post-Run: Doctor', 'post_run_doctor', post_run_doctor?
+ )
+ end
+
+ def print_rpc_toggle(printer, name, rpc, current_value)
+ if current_value
+ icon = 'β
'
+ value = 'false'
+ else
+ icon = 'βοΈ'
+ value = 'true'
+ end
+
+ printer.item("#{icon} #{name}", rpc: [rpc, value], refresh: true)
+ end
+
def print_formulas(printer)
return unless formulas.size.positive?
printer.sep
printer.item("Formulas (#{formulas.size}):")
formulas.each do |formula|
- printer.item(formula.name) do |printer|
+ name = formula.name
+ name += ' ‫' if upgrade_all_exclude?(name)
+ printer.item(name) do |printer|
printer.item(
- 'Upgrade',
- alt: 'Upgrade ' \
+ 'β¬οΈ Upgrade',
+ alt: 'β¬οΈ Upgrade ' \
"(#{formula.current_version} β #{formula.latest_version})",
terminal: true, refresh: true,
- shell: [brew_path, 'upgrade', formula.name]
+ shell: [
+ brew_path, 'upgrade', formula.name
+ ] + post_commands([formula.name])
)
printer.sep
- printer.item("Installed: #{formula.installed_versions.join(', ')}")
- printer.item("Latest: #{formula.latest_version}")
+ printer.item("β Installed: #{formula.installed_versions.join(', ')}")
+ printer.item("β Latest: #{formula.latest_version}")
printer.sep
printer.item(
- 'Pin',
+ 'π Pin',
alt: "Pin (to #{formula.current_version})",
terminal: false, refresh: true,
shell: [brew_path, 'pin', formula.name]
)
- printer.item('Uninstall') do |printer|
+ if upgrade_all_exclude?(formula.name)
+ printer.item(
+ 'β
Upgrade All: Exclude',
+ terminal: false, refresh: true,
+ rpc: ['include_upgrade_all', formula.name]
+ )
+ else
+ printer.item(
+ 'βοΈ Upgrade All: Exclude ',
+ terminal: false, refresh: true,
+ rpc: ['exclude_upgrade_all', formula.name]
+ )
+ end
+ printer.item('π« Uninstall') do |printer|
printer.item('Are you sure?')
printer.item(
'Yes',
terminal: true, refresh: true,
- shell: [brew_path, 'uninstall', formula.name]
+ shell: [
+ brew_path, 'uninstall', formula.name
+ ] + post_commands([formula.name])
)
end
end
@@ -432,25 +527,44 @@ module Brew
printer.sep
printer.item("Casks (#{casks.size}):")
casks.each do |cask|
- printer.item(cask.name) do |printer|
+ name = cask.name
+ name += ' ‫' if upgrade_all_exclude?(name)
+ printer.item(name) do |printer|
printer.item(
- 'Upgrade',
- alt: 'Upgrade '\
+ 'β¬οΈ Upgrade',
+ alt: 'β¬οΈ Upgrade '\
"(#{cask.current_version} β #{cask.latest_version})",
terminal: true, refresh: true,
- shell: [brew_path, 'upgrade', '--cask', cask.name]
+ shell: [
+ brew_path, 'upgrade', '--cask', cask.name
+ ] + post_commands([cask.name])
)
printer.sep
- printer.item("Installed: #{cask.installed_version}")
- printer.item("Latest: #{cask.latest_version}")
+ printer.item("β Installed: #{cask.installed_version}")
+ printer.item("β Latest: #{cask.latest_version}")
printer.sep
- printer.item('Uninstall') do |printer|
+ if upgrade_all_exclude?(cask.name)
+ printer.item(
+ 'β
Upgrade All: Exclude',
+ terminal: false, refresh: true,
+ rpc: ['include_upgrade_all', cask.name]
+ )
+ else
+ printer.item(
+ 'βοΈ Upgrade All: Exclude',
+ terminal: false, refresh: true,
+ rpc: ['exclude_upgrade_all', cask.name]
+ )
+ end
+ printer.item('π« Uninstall') do |printer|
printer.item('Are you sure?')
printer.sep
printer.item(
'Yes',
terminal: true, refresh: true,
- shell: [brew_path, 'uninstall', '--cask', cask.name]
+ shell: [
+ brew_path, 'uninstall', '--cask', cask.name
+ ] + post_commands([cask.name])
)
end
end
@@ -465,34 +579,44 @@ module Brew
pinned.each do |formula|
printer.item(formula.name) do |printer|
printer.item(
- 'Upgrade',
- alt: 'Upgrade ' \
+ 'β¬ Upgrade',
+ alt: 'β¬ Upgrade ' \
"(#{formula.current_version} β #{formula.latest_version})"
)
printer.sep
- printer.item("Pinned: #{formula.pinned_version}")
+ printer.item("β Pinned: #{formula.pinned_version}")
if formula.installed_versions.size > 1
- printer.item("Installed: #{formula.installed_versions.join(', ')}")
+ printer.item("β Installed: #{formula.installed_versions.join(', ')}")
end
- printer.item("Latest: #{formula.latest_version}")
+ printer.item("β Latest: #{formula.latest_version}")
printer.sep
printer.item(
- 'Unpin',
+ 'π Unpin',
terminal: false, refresh: true,
shell: [brew_path, 'unpin', formula.name]
)
- printer.item('Uninstall') do |printer|
+ printer.item('π« Uninstall') do |printer|
printer.item('Are you sure?')
printer.item(
'Yes',
terminal: true, refresh: true,
- shell: [brew_path, 'uninstall', formula.name]
+ shell: [
+ brew_path, 'uninstall', formula.name
+ ] + post_commands([formula.name])
)
end
end
end
end
+ def post_commands(cleanup_names = [])
+ cmds = []
+ cmds += ['&&', brew_path, 'cleanup'] + cleanup_names if post_run_cleanup?
+ cmds += ['&&', brew_path, 'doctor'] if post_run_doctor?
+
+ cmds
+ end
+
def formulas
@formulas ||= all_formulas.reject(&:pinned)
end
@@ -509,18 +633,6 @@ module Brew
@casks ||= outdated['casks'].map { |line| Cask.new(line) }
end
- def greedy_types
- @greedy_types ||= config.as_set('VAR_GREEDY')
- end
-
- def greedy_latest?
- @greedy_latest ||= greedy_types.include?('latest')
- end
-
- def greedy_auto_updates?
- @greedy_auto_updates ||= greedy_types.include?('auto_updates')
- end
-
def greedy_args
args = []
args << '--greedy-latest' if greedy_latest?