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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c947550570c131a847f744a29edc640efd04f969648bfc79926092f125a88559
4
- data.tar.gz: 672a2a5fbf302fae7853ca72dc0fb7bca4e42a0723201c45fba57845b8c0b541
3
+ metadata.gz: f0f8f5abc50111342c80fbfc411408159e625d00e52a31dc8f8956ac658c21f0
4
+ data.tar.gz: d05eb3f51a19efa9d1a9328229a4dbb5b680eb91c1b36c9cb8f5e973cfc6f17d
5
5
  SHA512:
6
- metadata.gz: 85e701c6c4ce14be709878d1ba055c5dc53d02f6d5ea41bdc1afe50f36444ce0964852c158ff315e7a085c3adebfcca7b336782b7feb6c7999f19d3e2f0aa52d
7
- data.tar.gz: 20e83b75b2578870ceb1c06cb7f917601f524d236943eb906abc59340fe531c5f654897ff5d4b829f3cc176269f7dfe10791551e5bdff4a4726b0e1459fb90d7
6
+ metadata.gz: 5bf720911c5338c70a41f29af05ee2fad030ec54faad56727d9843bdae46355dbf22ef17e722c9196edf2aba7cdc9458f50dade6ca518f4d2709eeb2888ed43c
7
+ data.tar.gz: 005cc75962461f3e7c6e11ae04e31b99cec50b5cc1401b27ba968a28a64bf648599097d133fe8bd306896e99c5b76e020546b6cae4b867af85b015d19da5a2e3
data/.version CHANGED
@@ -1 +1 @@
1
- 0.2.9
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), `hammer -h`, and `hammer --help` all print top-level help.
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
- puts(i == selected ? paint("> #{item}", highlight) : " #{item}")
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
- puts paint("> #{items[selected]}", :green)
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
- def print_help(target = nil, full: false)
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
- print_global_flags
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
- print_global_flags
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 (AI-friendly Hammerfile authoring docs)'
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lux-hammer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dino Reic