lux-hammer 0.2.9 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/AGENTS.md +4 -1
- data/lib/hammer/shell.rb +10 -6
- data/lib/lux-hammer.rb +63 -18
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0f8f5abc50111342c80fbfc411408159e625d00e52a31dc8f8956ac658c21f0
|
|
4
|
+
data.tar.gz: d05eb3f51a19efa9d1a9328229a4dbb5b680eb91c1b36c9cb8f5e973cfc6f17d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5bf720911c5338c70a41f29af05ee2fad030ec54faad56727d9843bdae46355dbf22ef17e722c9196edf2aba7cdc9458f50dade6ca518f4d2709eeb2888ed43c
|
|
7
|
+
data.tar.gz: 005cc75962461f3e7c6e11ae04e31b99cec50b5cc1401b27ba968a28a64bf648599097d133fe8bd306896e99c5b76e020546b6cae4b867af85b015d19da5a2e3
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.3.1
|
data/AGENTS.md
CHANGED
|
@@ -182,7 +182,10 @@ explicit ADR-level discussion. Keys:
|
|
|
182
182
|
is the whole API. `Hammer.cli` warms the cache before chdir-ing into
|
|
183
183
|
the Hammerfile's directory so the resolved name stays relative to the
|
|
184
184
|
cwd the user invoked from.
|
|
185
|
-
* `hammer` (no args)
|
|
185
|
+
* `hammer` (no args) prints just the command listing (with a top gray
|
|
186
|
+
`lux-hammer VERSION - <homepage>` banner for the hammer binary).
|
|
187
|
+
* `hammer -h` / `hammer --help` adds global flags, a small Hammerfile
|
|
188
|
+
example, and the footer link on top of the same listing.
|
|
186
189
|
* `hammer COMMAND -h` / `--help` prints per-command help (reserved on every command).
|
|
187
190
|
* Commands listed flat with colon paths, grouped by top-level namespace.
|
|
188
191
|
* Bare namespace (`hammer db`) prints the same listing scoped to that
|
data/lib/hammer/shell.rb
CHANGED
|
@@ -94,9 +94,13 @@ class Hammer
|
|
|
94
94
|
return choose_numbered(items) unless $stdin.tty? && $stdin.respond_to?(:raw)
|
|
95
95
|
|
|
96
96
|
selected = 0
|
|
97
|
+
# In raw mode \n is not translated to \r\n, so the picker uses \r\n
|
|
98
|
+
# explicitly. The initial draw happens in cooked mode but \r\n is
|
|
99
|
+
# harmless there.
|
|
97
100
|
redraw = lambda do |highlight = :cyan|
|
|
98
101
|
items.each_with_index do |item, i|
|
|
99
|
-
|
|
102
|
+
line = i == selected ? paint("> #{item}", highlight) : " #{item}"
|
|
103
|
+
$stdout.print "#{line}\r\n"
|
|
100
104
|
end
|
|
101
105
|
end
|
|
102
106
|
redraw.call
|
|
@@ -109,11 +113,11 @@ class Hammer
|
|
|
109
113
|
case ch
|
|
110
114
|
when "\r", "\n"
|
|
111
115
|
# Collapse the list to the chosen line, in green.
|
|
112
|
-
$stdout.print "\e[#{items.size}A\e[J"
|
|
113
|
-
|
|
116
|
+
$stdout.print "\e[#{items.size}A\r\e[J"
|
|
117
|
+
$stdout.print "#{paint("> #{items[selected]}", :green)}\r\n"
|
|
114
118
|
return selected
|
|
115
119
|
when "\x03", 'q' # Ctrl-C, q
|
|
116
|
-
$stdout.print "\e[#{items.size}A\e[J"
|
|
120
|
+
$stdout.print "\e[#{items.size}A\r\e[J"
|
|
117
121
|
return nil
|
|
118
122
|
when "\e"
|
|
119
123
|
# ESC may stand alone or start an arrow sequence \e[A / \e[B.
|
|
@@ -123,13 +127,13 @@ class Hammer
|
|
|
123
127
|
when 'B' then selected = (selected + 1) % items.size
|
|
124
128
|
end
|
|
125
129
|
else
|
|
126
|
-
$stdout.print "\e[#{items.size}A\e[J"
|
|
130
|
+
$stdout.print "\e[#{items.size}A\r\e[J"
|
|
127
131
|
return nil
|
|
128
132
|
end
|
|
129
133
|
when 'k' then selected = (selected - 1) % items.size
|
|
130
134
|
when 'j' then selected = (selected + 1) % items.size
|
|
131
135
|
end
|
|
132
|
-
$stdout.print "\e[#{items.size}A\e[J"
|
|
136
|
+
$stdout.print "\e[#{items.size}A\r\e[J"
|
|
133
137
|
redraw.call
|
|
134
138
|
end
|
|
135
139
|
end
|
data/lib/lux-hammer.rb
CHANGED
|
@@ -325,20 +325,12 @@ class Hammer
|
|
|
325
325
|
name = argv.shift
|
|
326
326
|
|
|
327
327
|
if name.nil?
|
|
328
|
-
# Bare invocation of the `hammer` binary: print a gem banner
|
|
329
|
-
# above the help so users can see which lux-hammer they have.
|
|
330
|
-
# Skipped for `-h` / `help` (those stay terse) and for user-
|
|
331
|
-
# built CLIs (their own program name, not lux-hammer).
|
|
332
|
-
if root.instance_variable_get(:@hammer_binary)
|
|
333
|
-
Shell.say "lux-hammer #{VERSION}"
|
|
334
|
-
Shell.say ''
|
|
335
|
-
end
|
|
336
328
|
return print_help
|
|
337
329
|
end
|
|
338
330
|
|
|
339
331
|
if name == 'help' || name == '-h' || name == '--help'
|
|
340
332
|
target = argv.shift
|
|
341
|
-
return print_help(target)
|
|
333
|
+
return print_help(target, extended: true)
|
|
342
334
|
end
|
|
343
335
|
|
|
344
336
|
# Trailing colon ("db:") -> namespace listing. Bare ":" lists root.
|
|
@@ -564,24 +556,29 @@ class Hammer
|
|
|
564
556
|
scan.include?('-h') || scan.include?('--help')
|
|
565
557
|
end
|
|
566
558
|
|
|
567
|
-
|
|
559
|
+
# `extended: true` is the verbose `help` / `-h` / `--help` form -
|
|
560
|
+
# appends global flags, the GitHub footer, and (for the hammer binary)
|
|
561
|
+
# a Hammerfile example. Bare invocation passes `extended: false` so
|
|
562
|
+
# the no-args output stays a clean command listing.
|
|
563
|
+
def print_help(target = nil, full: false, extended: false)
|
|
568
564
|
if target
|
|
569
565
|
# `help ns:` is equivalent to `ns:` - namespace listing.
|
|
570
566
|
if target.end_with?(':') && target != ':'
|
|
571
567
|
bare = target.chomp(':')
|
|
572
568
|
ns, canonical = resolve_namespace(bare)
|
|
573
|
-
return print_namespace_help(canonical, ns) if ns
|
|
569
|
+
return print_namespace_help(canonical, ns, extended: extended) if ns
|
|
574
570
|
Shell.print_error("unknown: #{target}")
|
|
575
571
|
return
|
|
576
572
|
end
|
|
577
573
|
cmd, _, canonical = resolve(target)
|
|
578
574
|
return print_command_help(cmd, canonical) if cmd
|
|
579
575
|
ns, canonical = resolve_namespace(target)
|
|
580
|
-
return print_namespace_help(canonical, ns, full: full) if ns
|
|
576
|
+
return print_namespace_help(canonical, ns, full: full, extended: extended) if ns
|
|
581
577
|
Shell.print_error("unknown: #{target}")
|
|
582
578
|
return
|
|
583
579
|
end
|
|
584
580
|
|
|
581
|
+
print_top_banner
|
|
585
582
|
Shell.say "Usage: #{program_name} COMMAND [ARGS]", :cyan
|
|
586
583
|
if full
|
|
587
584
|
each_command { |path, c| print_full_block(path, c) unless c.desc.empty? }
|
|
@@ -589,11 +586,10 @@ class Hammer
|
|
|
589
586
|
Shell.say ''
|
|
590
587
|
print_command_list(self)
|
|
591
588
|
end
|
|
592
|
-
|
|
593
|
-
print_footer
|
|
589
|
+
print_extras if extended
|
|
594
590
|
end
|
|
595
591
|
|
|
596
|
-
def print_namespace_help(prefix, ns, full: false)
|
|
592
|
+
def print_namespace_help(prefix, ns, full: false, extended: false)
|
|
597
593
|
Shell.say "Usage: #{program_name} #{prefix}:COMMAND [ARGS]", :cyan
|
|
598
594
|
rows = []
|
|
599
595
|
sibling = find_namespace_sibling(prefix)
|
|
@@ -605,8 +601,7 @@ class Hammer
|
|
|
605
601
|
width = rows.map { |path, _| path.length }.max
|
|
606
602
|
emit_rows(rows.sort_by { |path, _| [path.count(':'), path] }, width)
|
|
607
603
|
end
|
|
608
|
-
|
|
609
|
-
print_footer
|
|
604
|
+
print_extras if extended
|
|
610
605
|
end
|
|
611
606
|
|
|
612
607
|
# One "task block" for the expanded listing: blank line separator
|
|
@@ -618,6 +613,27 @@ class Hammer
|
|
|
618
613
|
|
|
619
614
|
HOMEPAGE ||= 'https://github.com/dux/hammer'.freeze
|
|
620
615
|
|
|
616
|
+
# Gray "lux-hammer X.Y.Z - <homepage>" line shown above top-level help
|
|
617
|
+
# in both bare-invocation and `--help` modes, so the link is always
|
|
618
|
+
# one glance away. User CLIs skip it (the lux-hammer name/link is
|
|
619
|
+
# irrelevant outside the `hammer` binary).
|
|
620
|
+
def print_top_banner
|
|
621
|
+
return unless root.instance_variable_get(:@hammer_binary)
|
|
622
|
+
Shell.say "lux-hammer #{VERSION} - #{HOMEPAGE}", :gray
|
|
623
|
+
Shell.say ''
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
# Extras shown only in the extended (`help` / `-h` / `--help`) view:
|
|
627
|
+
# global flags, GitHub footer, and a Hammerfile example for the
|
|
628
|
+
# `hammer` binary. The footer is skipped for the hammer binary
|
|
629
|
+
# because `print_top_banner` already surfaces the same link.
|
|
630
|
+
def print_extras
|
|
631
|
+
hammer_bin = root.instance_variable_get(:@hammer_binary)
|
|
632
|
+
print_global_flags
|
|
633
|
+
print_hammerfile_example if hammer_bin
|
|
634
|
+
print_footer unless hammer_bin
|
|
635
|
+
end
|
|
636
|
+
|
|
621
637
|
# Global flags only exist when invoked via the `hammer` binary
|
|
622
638
|
# (see `Hammer.cli`), not for user-built CLIs that call `start`
|
|
623
639
|
# on their own subclass.
|
|
@@ -625,7 +641,7 @@ class Hammer
|
|
|
625
641
|
return unless root.instance_variable_get(:@hammer_binary)
|
|
626
642
|
Shell.say ''
|
|
627
643
|
Shell.say 'Global:', :yellow
|
|
628
|
-
Shell.say ' --ai # Print AGENTS.md
|
|
644
|
+
Shell.say ' --ai # Print AGENTS.md - AI-friendly Hammerfile authoring docs'
|
|
629
645
|
end
|
|
630
646
|
|
|
631
647
|
def print_footer
|
|
@@ -633,6 +649,35 @@ class Hammer
|
|
|
633
649
|
Shell.say "powered by hammer - #{HOMEPAGE}", :gray
|
|
634
650
|
end
|
|
635
651
|
|
|
652
|
+
# Small Hammerfile cheat-sheet shown under `hammer --help`. Touches
|
|
653
|
+
# the main surface area (task/desc/example/opt, namespace, before,
|
|
654
|
+
# needs, sh, say) without trying to be exhaustive - that's --ai's job.
|
|
655
|
+
def print_hammerfile_example
|
|
656
|
+
Shell.say ''
|
|
657
|
+
Shell.say 'Hammerfile example:', :yellow
|
|
658
|
+
Shell.say <<~RUBY
|
|
659
|
+
task :hello do
|
|
660
|
+
desc 'Greet someone'
|
|
661
|
+
example 'hello world --loud'
|
|
662
|
+
opt :loud, type: :boolean, alias: :l
|
|
663
|
+
proc do |opts|
|
|
664
|
+
msg = "hello \#{opts[:args].first || 'world'}"
|
|
665
|
+
say(opts[:loud] ? msg.upcase : msg, :cyan)
|
|
666
|
+
end
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
namespace :db do
|
|
670
|
+
before { hammer :env }
|
|
671
|
+
|
|
672
|
+
task :migrate do
|
|
673
|
+
desc 'Run migrations'
|
|
674
|
+
needs 'db:check'
|
|
675
|
+
proc { sh 'bin/rails db:migrate' }
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
RUBY
|
|
679
|
+
end
|
|
680
|
+
|
|
636
681
|
def print_command_list(klass, prefix = nil)
|
|
637
682
|
rows = []
|
|
638
683
|
# Commands without a `desc` are hidden from listings but still
|