-
-
Save chetan/3151545b8d7a078bc531c53d7e3f8c64 to your computer and use it in GitHub Desktop.
Quickly search for homebrew formula or casks and display info via fzf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# bi | |
# Quickly fetch and display info for the given homebrew formula or cask | |
# | |
# perf: | |
# brew info nginx -> 0m1.742s | |
# bi nginx -> 0m0.166s | |
# | |
# Works well with fzf (via brew.fzf) | |
# rubocop:disable Metrics, Style/Documentation, Style/CaseLikeIf | |
HOMEBREW_PREFIX = '/usr/local' | |
def cask(name, &block) | |
classname = name.capitalize | |
eval <<~EOF | |
class #{classname} < Formula | |
def self._caskify(&block) | |
instance_exec(&block) | |
end | |
def self.version(str=nil) | |
return @version if @version | |
@version = Cask::DSL::Version.new(str) | |
end | |
def self.name(str=nil) | |
return @name if @name | |
@name = str | |
end | |
def cask? | |
true | |
end | |
end | |
EOF | |
clazz = Module.const_get(classname.to_sym) | |
clazz._caskify(&block) | |
obj = clazz.new(name) | |
end | |
class String | |
def /(other) | |
if end_with?('/') | |
self + other | |
else | |
self + '/' + other | |
end | |
end | |
def exist? | |
File.exist?(self) | |
end | |
def read | |
IO.read(self) if exist? | |
end | |
end | |
require 'cgi' | |
require 'forwardable' | |
require 'pathname' | |
$LOAD_PATH << '/usr/local/Homebrew/Library/Homebrew' | |
require 'vendor/bundle/ruby/2.6.0/gems/sorbet-runtime-stub-0.2.0/lib/sorbet-runtime-stub' | |
require 'vendor/bundle/ruby/2.6.0/gems/activesupport-6.1.4.1/lib/active_support/core_ext/object/blank' | |
# require 'extend/pathname' | |
require 'version' | |
require 'utils/shell' | |
require 'cask/dsl/version' | |
class Pathname | |
def stem | |
File.basename(self, extname) | |
end | |
end | |
module Language | |
module Python | |
module Virtualenv | |
end | |
end | |
end | |
class Array | |
def second | |
self[1] | |
end | |
end | |
class Formula | |
include Utils::Shell | |
class << self | |
attr_reader :deprecated, :name | |
def [](key) | |
Formula.new(key) | |
end | |
def descendants | |
ObjectSpace.each_object(Class).select { |klass| klass < self } | |
end | |
def method_missing(symbol, *args) | |
var = ('@' + symbol.id2name).to_sym | |
if block_given? | |
pass | |
elsif args.empty? | |
instance_variable_get(var) | |
elsif args.length == 1 | |
instance_variable_set(var, args[0]) | |
else | |
instance_variable_set(var, args) | |
end | |
end | |
def respond_to_missing?(_name, _include_private = false) | |
true | |
end | |
def depends_on(pkg = nil) | |
unless pkg.nil? | |
@depends_on ||= [] | |
@depends_on << pkg | |
end | |
@depends_on | |
end | |
def deprecate!(*args) | |
@deprecated = true if args.length > 0 | |
end | |
def test(); end | |
end | |
def initialize(name) | |
@name = name | |
end | |
def caveats; end | |
def deps | |
return @deps if @deps | |
deps = self.class.depends_on | |
return '' if !deps || deps.empty? | |
@deps = deps.map do |d| | |
if d.is_a?(String) | |
d | |
elsif d.is_a?(Symbol) | |
nil | |
else | |
r = [] | |
d.each do |k, v| | |
r << k if v != :build | |
end | |
r.join(' ') | |
end | |
end.reject { |s| s.nil? || s.empty? }.join(' ') | |
end | |
def version | |
return @version if @version | |
@version = if self.class.version | |
Version.parse(self.class.version) | |
else | |
Version.parse(self.class.url) | |
end | |
end | |
def cask? | |
false | |
end | |
def any_version_installed? | |
false | |
end | |
attr_reader :name | |
def etc | |
HOMEBREW_PREFIX / 'etc' | |
end | |
def var | |
HOMEBREW_PREFIX / 'var' | |
end | |
def opt_prefix | |
HOMEBREW_PREFIX / 'opt' / name | |
end | |
def opt_bin | |
opt_prefix / 'bin' | |
end | |
def opt_include | |
opt_prefix / 'include' | |
end | |
def opt_lib | |
opt_prefix / 'lib' | |
end | |
def opt_libexec | |
opt_prefix / 'libexec' | |
end | |
def opt_sbin | |
opt_prefix / 'sbin' | |
end | |
def opt_share | |
opt_prefix / 'share' | |
end | |
def opt_pkgshare | |
opt_prefix / 'share' / name | |
end | |
def opt_elisp | |
opt_prefix / 'share/emacs/site-lisp' / name | |
end | |
def opt_frameworks | |
opt_prefix / 'Frameworks' | |
end | |
def shell_profile | |
Utils::Shell.profile | |
end | |
end | |
def main | |
tap = nil | |
formula = ARGV[0] | |
# Find the correct formula/cask path | |
if formula.include? '/' | |
fs = formula.split('/') | |
tap = fs.first | |
formula = fs.last | |
paths = `fd ^#{formula}.rb /usr/local/Homebrew/Library/Taps/#{tap}`.strip.split(/\n/) | |
else | |
paths = `fd ^#{formula}.rb /usr/local/Homebrew/Library/Taps`.strip.split(/\n/) | |
end | |
if paths.empty? | |
puts "error: formula '#{formula}' not found" | |
exit 1 | |
end | |
if paths.length == 1 | |
path = paths[0] | |
else | |
path = paths.find { |s| s.include? 'homebrew/homebrew-core' } | |
path = paths[0] if path.nil? | |
end | |
# Load it | |
require path | |
# Create an instance | |
clazz = Formula.descendants.first | |
f = clazz.new(formula) | |
ver = if f.cask? | |
clazz.version | |
else | |
f.version.to_s.gsub(/\.tar$/, '') | |
end | |
# Print info | |
puts "#{formula}: #{ver}" | |
puts clazz.desc unless clazz.desc.blank? | |
puts clazz.homepage unless clazz.homepage.blank? | |
puts "tap: #{tap}" if tap | |
puts 'cask' if f.cask? | |
puts 'Deprecated' if clazz.deprecated | |
puts "deps: #{f.deps}" unless f.deps.blank? | |
unless f.caveats.nil? || f.caveats.empty? | |
puts 'caveats:' | |
puts f.caveats | |
end | |
end | |
main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# brew.fzf | |
# Quickly search for homebrew formula or casks and display info via fzf | |
function brew.fzf { | |
! type fzf &>/dev/null && | |
echo "fzf required. Install with 'brew install fzf'." && | |
return 1 | |
local str="" | |
declare -a FLAGS=(--formula) | |
while [ ! $# -eq 0 ]; do | |
case "$1" in | |
-c | --casks | --cask) | |
FLAGS+=("--casks") | |
;; | |
-h | --help) | |
_brew.fzf.usage | |
exit 0 | |
;; | |
*) | |
str="$str $1" | |
;; | |
esac | |
shift | |
done | |
str=$(echo "$str" | tr -d ' ') | |
if [ -z "$str" ]; then | |
_brew.fzf.usage | |
exit 0 | |
fi | |
brew search ${FLAGS[@]} $str | grep -v '==' | grep -v '^$' | fzf -m +s --header "searching homebrew for '$str'" --preview 'bi {}' | |
} | |
function _brew.fzf.usage { | |
cat << EOF | |
usage: $PROGRAM [--casks] <search term> | |
Search for homebrew formulas and/or casks with the help of fzf | |
OPTIONS: | |
-c|--casks Include casks in the search (default: false) | |
-h|--help Show this message | |
EOF | |
} | |
PROGRAM=$(basename $0) | |
brew.fzf $@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment