Module: Hammer::Recipe
- Defined in:
- lib/hammer/recipe.rb
Overview
Discovery + helpers for “recipes” - standalone Hammerfile-style scripts shipped under ‘<gem>/recipes/` (and optionally the user’s ‘~/.config/hammer/recipes/`) that are exposed as their own bin scripts in PATH via a tiny Ruby wrapper.
Class Method Summary collapse
-
.all ⇒ Object
{ “name” => “/abs/path/name.rb” }.
-
.desc(path) ⇒ Object
First ‘# desc: …` line at the top of the file, or empty string.
-
.dirs ⇒ Object
Recipe lookup directories, in priority order.
-
.grouped ⇒ Object
Group recipes by their source directory for the listing view.
-
.installed_path(name) ⇒ Object
If a stub for ‘name` is on PATH, return its absolute path.
-
.path(name) ⇒ Object
Path to the recipe file for ‘name`, or nil if unknown.
-
.stub(name) ⇒ Object
Ruby wrapper text printed by ‘hammer self:recipe install`.
Class Method Details
.all ⇒ Object
{ “name” => “/abs/path/name.rb” }. User-dir entries win over gem entries because they come first in ‘dirs`.
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/hammer/recipe.rb', line 23 def all out = {} dirs.each do |dir| next unless File.directory?(dir) Dir.glob(File.join(dir, '*.rb')).sort.each do |path| name = File.basename(path, '.rb') out[name] ||= path end end out end |
.desc(path) ⇒ Object
First ‘# desc: …` line at the top of the file, or empty string. Cheap - reads only the first ~20 lines, no eval.
42 43 44 45 46 47 48 49 50 |
# File 'lib/hammer/recipe.rb', line 42 def desc(path) return '' unless path && File.file?(path) File.foreach(path).first(20).each do |line| if (m = line.match(/\A#\s*desc:\s*(.+)$/i)) return m[1].strip end end '' end |
.dirs ⇒ Object
Recipe lookup directories, in priority order. User dir is only included when it exists. Honors HAMMER_RECIPES_DIR for overrides (mostly for tests).
14 15 16 17 18 19 |
# File 'lib/hammer/recipe.rb', line 14 def dirs out = [GEM_DIR] user = ENV['HAMMER_RECIPES_DIR'] || File.('~/.config/hammer/recipes') out.unshift(user) if File.directory?(user) out end |
.grouped ⇒ Object
Group recipes by their source directory for the listing view. Returns [[source_label, { name => path }], …].
82 83 84 85 86 87 88 89 90 |
# File 'lib/hammer/recipe.rb', line 82 def grouped user_dir = ENV['HAMMER_RECIPES_DIR'] || File.('~/.config/hammer/recipes') groups = { 'gem' => {}, 'user' => {} } all.each do |name, path| bucket = path.start_with?(user_dir) ? 'user' : 'gem' groups[bucket][name] = path end groups.reject { |_, v| v.empty? }.to_a end |
.installed_path(name) ⇒ Object
If a stub for ‘name` is on PATH, return its absolute path. Detects by reading the file and looking for the literal `Hammer.recipe(’<name>‘` token - cheap and near-zero false positive.
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/hammer/recipe.rb', line 68 def installed_path(name) token = "Hammer.recipe('#{name}'" ENV.fetch('PATH', '').split(File::PATH_SEPARATOR).each do |dir| candidate = File.join(dir, name.to_s) next unless File.file?(candidate) && File.executable?(candidate) return candidate if File.read(candidate, 512).include?(token) rescue StandardError next end nil end |
.path(name) ⇒ Object
Path to the recipe file for ‘name`, or nil if unknown.
36 37 38 |
# File 'lib/hammer/recipe.rb', line 36 def path(name) all[name.to_s] end |
.stub(name) ⇒ Object
Ruby wrapper text printed by ‘hammer self:recipe install`. User redirects it to a file in PATH and chmods +x. The leading comment documents the canonical install command. Name is passed as a string literal so hyphenated names (`git-helper`) work too.
56 57 58 59 60 61 62 63 |
# File 'lib/hammer/recipe.rb', line 56 def stub(name) <<~RUBY #!/usr/bin/env ruby # install: hammer self:recipe install #{name} > ~/bin/#{name} && chmod +x $_ require 'lux-hammer' Hammer.recipe('#{name}', ARGV) RUBY end |