mirror of
https://github.com/jimeh/dotfiles.git
synced 2026-02-19 08:26:42 +00:00
feat(xbar/brew-updates): add support for SwiftBar in addition to Xbar
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
# rubocop:disable Layout/LineLength
|
# rubocop:disable Layout/LineLength
|
||||||
|
|
||||||
# <xbar.title>Brew Updates</xbar.title>
|
# <xbar.title>Brew Updates</xbar.title>
|
||||||
# <xbar.version>v2.6.3</xbar.version>
|
# <xbar.version>v2.7.0</xbar.version>
|
||||||
# <xbar.author>Jim Myhrberg</xbar.author>
|
# <xbar.author>Jim Myhrberg</xbar.author>
|
||||||
# <xbar.author.github>jimeh</xbar.author.github>
|
# <xbar.author.github>jimeh</xbar.author.github>
|
||||||
# <xbar.desc>List and manage outdated Homebrew formulas and casks</xbar.desc>
|
# <xbar.desc>List and manage outdated Homebrew formulas and casks</xbar.desc>
|
||||||
@@ -30,15 +30,60 @@
|
|||||||
# rubocop:disable Metrics/PerceivedComplexity
|
# rubocop:disable Metrics/PerceivedComplexity
|
||||||
# rubocop:disable Style/IfUnlessModifier
|
# rubocop:disable Style/IfUnlessModifier
|
||||||
|
|
||||||
|
require 'fileutils'
|
||||||
require 'open3'
|
require 'open3'
|
||||||
require 'json'
|
require 'json'
|
||||||
require 'set'
|
require 'set'
|
||||||
|
|
||||||
|
# Xbar is a tiny helper library for creating Xbar and SwiftBar plugins in Ruby.
|
||||||
module Xbar
|
module Xbar
|
||||||
class CommandError < StandardError; end
|
class CommandError < StandardError; end
|
||||||
class RPCError < StandardError; end
|
class RPCError < StandardError; end
|
||||||
|
|
||||||
|
module Helpers
|
||||||
|
def plugin_data_path
|
||||||
|
@plugin_data_path ||= (swiftbar_data_path || File.dirname(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
|
def plugin_file_path
|
||||||
|
@plugin_file_path ||= (swiftbar_plugin_path || __FILE__)
|
||||||
|
end
|
||||||
|
|
||||||
|
def plugin_filename
|
||||||
|
@plugin_filename ||= File.basename(plugin_file_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def plugin_name
|
||||||
|
@plugin_name ||= begin
|
||||||
|
parts = plugin_filename.split('.')
|
||||||
|
if parts.size < 3
|
||||||
|
raise "Invalid plugin name: #{plugin_filename}"
|
||||||
|
end
|
||||||
|
|
||||||
|
parts[0..-3].join('.')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def swiftbar?
|
||||||
|
ENV['SWIFTBAR'] == '1'
|
||||||
|
end
|
||||||
|
|
||||||
|
def swiftbar_cache_path
|
||||||
|
@swiftbar_cache_path ||= ENV['SWIFTBAR_PLUGIN_CACHE_PATH'] if swiftbar?
|
||||||
|
end
|
||||||
|
|
||||||
|
def swiftbar_data_path
|
||||||
|
@swiftbar_data_path ||= ENV['SWIFTBAR_PLUGIN_DATA_PATH'] if swiftbar?
|
||||||
|
end
|
||||||
|
|
||||||
|
def swiftbar_plugin_path
|
||||||
|
@swiftbar_plugin_path ||= ENV['SWIFTBAR_PLUGIN_PATH'] if swiftbar?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module Service
|
module Service
|
||||||
|
include Helpers
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def config
|
def config
|
||||||
@@ -49,8 +94,11 @@ module Xbar
|
|||||||
@printer ||= ::Xbar::Printer.new
|
@printer ||= ::Xbar::Printer.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def cmd(*args)
|
def cmd(*args, dir: nil)
|
||||||
out, err, s = Open3.capture3(*args)
|
opts = {}
|
||||||
|
opts[:chdir] = File.expand_path(dir) if dir
|
||||||
|
|
||||||
|
out, err, s = Open3.capture3(*args, opts)
|
||||||
if s.exitstatus != 0
|
if s.exitstatus != 0
|
||||||
msg = "Command failed: #{args.join(' ')}"
|
msg = "Command failed: #{args.join(' ')}"
|
||||||
msg += ": #{err}" unless err.empty?
|
msg += ": #{err}" unless err.empty?
|
||||||
@@ -79,7 +127,16 @@ module Xbar
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Config is a simple wrapper around a JSON file that contains the plugin's
|
||||||
|
# configuration. It is compatible with Xbar's behavior of loading environment
|
||||||
|
# variables from it. We don't rely on that however and directly read the file
|
||||||
|
# ourselves.
|
||||||
|
#
|
||||||
|
# In SwiftBar, we use `SWIFTBAR_PLUGIN_DATA_PATH` to determine where to store
|
||||||
|
# the configuration in a `config.json` file.
|
||||||
class Config < Hash
|
class Config < Hash
|
||||||
|
include Helpers
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
|
|
||||||
@@ -95,15 +152,25 @@ module Xbar
|
|||||||
end
|
end
|
||||||
|
|
||||||
def filename
|
def filename
|
||||||
@filename ||= "#{__FILE__}.vars.json"
|
@filename ||= File.join(
|
||||||
|
plugin_data_path,
|
||||||
|
swiftbar? ? 'config.json' : "#{plugin_filename}.vars.json"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def dirname
|
||||||
|
@dirname ||= File.dirname(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
|
FileUtils.mkdir_p(dirname)
|
||||||
File.write(filename, JSON.pretty_generate(self))
|
File.write(filename, JSON.pretty_generate(self))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Printer
|
class Printer
|
||||||
|
include Helpers
|
||||||
|
|
||||||
attr_reader :nested_level
|
attr_reader :nested_level
|
||||||
|
|
||||||
SUB_STR = '--'
|
SUB_STR = '--'
|
||||||
@@ -147,13 +214,25 @@ module Xbar
|
|||||||
end
|
end
|
||||||
|
|
||||||
def plugin_refresh_uri
|
def plugin_refresh_uri
|
||||||
@plugin_refresh_uri ||= 'xbar://app.xbarapp.com/refreshPlugin' \
|
return @plugin_refresh_uri if @plugin_refresh_uri
|
||||||
"?path=#{File.basename(__FILE__)}"
|
|
||||||
|
if swiftbar?
|
||||||
|
@plugin_refresh_uri = "swiftbar://refreshplugin?name=#{plugin_name}"
|
||||||
|
else
|
||||||
|
@plugin_refresh_uri = 'xbar://app.xbarapp.com/refreshPlugin' \
|
||||||
|
"?path=#{plugin_filename}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_props(props = {})
|
def normalize_props(props = {})
|
||||||
props = props.dup
|
props = props.dup
|
||||||
|
|
||||||
|
# Explicitly set terminal to false for SwiftBar, as it seems to default
|
||||||
|
# to true when not specified. At least with SwiftBar 2.0.1.
|
||||||
|
if swiftbar? && !props.key?(:terminal)
|
||||||
|
props[:terminal] = false
|
||||||
|
end
|
||||||
|
|
||||||
if props[:rpc] && props[:shell].nil?
|
if props[:rpc] && props[:shell].nil?
|
||||||
props[:shell] = [__FILE__] + props[:rpc]
|
props[:shell] = [__FILE__] + props[:rpc]
|
||||||
props.delete(:rpc)
|
props.delete(:rpc)
|
||||||
@@ -167,8 +246,12 @@ module Xbar
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Refresh Xbar after shell command has run in terminal
|
# Always refresh SwiftBar via refresh plugin URI so as to temporarily
|
||||||
if props[:terminal] && props[:refresh] && props[:shell]
|
# disable the menu bar icon while refresh is running.
|
||||||
|
#
|
||||||
|
# For Xbar this does not work when terminal is false, so we only trigger
|
||||||
|
# refresh via the plugin refresh URI when terminal is true.
|
||||||
|
if props[:refresh] && props[:shell] && (swiftbar? || props[:terminal])
|
||||||
props[:refresh] = false
|
props[:refresh] = false
|
||||||
i = 1
|
i = 1
|
||||||
i += 1 while props.key?("param#{i}".to_sym)
|
i += 1 while props.key?("param#{i}".to_sym)
|
||||||
@@ -491,7 +574,7 @@ module Brew
|
|||||||
printer.sep
|
printer.sep
|
||||||
printer.item(
|
printer.item(
|
||||||
'📌 Pin',
|
'📌 Pin',
|
||||||
alt: "Pin (to #{formula.current_version})",
|
alt: "📌 Pin (to #{formula.current_version})",
|
||||||
terminal: false, refresh: true,
|
terminal: false, refresh: true,
|
||||||
shell: [brew_path, 'pin', formula.name]
|
shell: [brew_path, 'pin', formula.name]
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user