lux-hammer 0.2.4 → 0.2.5
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 +294 -0
- data/bin/hammer +7 -6
- data/lib/lux-hammer.rb +23 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb668fabef5892decb2ee58add685f52dad7fe742ae0cd8597ba62da576c3d13
|
|
4
|
+
data.tar.gz: f74beef4ccb0af5aaa546c7c4a2dec29bc08fffdb929edfa5f3dcdf261627b69
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fddfa7b7f657cb1baa30793e46fe331cd3f65704ac31ce582bcfc851b154a15eb72e5610e0a0b8af29ed99a763823f7c7bbdd1ef7ad33f40b95fcd803a6216f
|
|
7
|
+
data.tar.gz: 6b176bb61def54c305a28f0c9b9419074ed16c14c1b8412ccc084cd2ed5f1a0bfa93d947aac9fcce704cde00c2307bb897e0255e200f1bf1bb077f2795f40330
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.2.
|
|
1
|
+
0.2.5
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# AGENTS.md - lux-hammer
|
|
2
|
+
|
|
3
|
+
Conventions and constraints for AI agents working on this gem.
|
|
4
|
+
|
|
5
|
+
## What this gem is
|
|
6
|
+
|
|
7
|
+
A tiny CLI builder stitched together from three influences:
|
|
8
|
+
namespaces and prereqs from Rake, typed option parsing from Thor, and
|
|
9
|
+
the `task :name do ... end` block DSL from Joshua. Users drop a
|
|
10
|
+
`Hammerfile` in their project, run `hammer`, get a structured CLI. Also
|
|
11
|
+
usable as a library (`require 'lux-hammer'`, subclass `Hammer`, call
|
|
12
|
+
`.start(ARGV)`).
|
|
13
|
+
|
|
14
|
+
## Hard constraints
|
|
15
|
+
|
|
16
|
+
* **One root constant**: `Hammer`. Never pollute `Object` or introduce
|
|
17
|
+
another top-level constant. Sub-types live as `Hammer::Shell`,
|
|
18
|
+
`Hammer::Option`, `Hammer::Parser`, `Hammer::Command`,
|
|
19
|
+
`Hammer::Loader`, `Hammer::Builder`, `Hammer::CommandBuilder`. The one
|
|
20
|
+
exception is `String#color(:name)` (defined in `lib/hammer/shell.rb`)
|
|
21
|
+
- a tiny convenience for `"hi".color(:cyan)`. Do not add more
|
|
22
|
+
monkey-patches.
|
|
23
|
+
* **Zero runtime dependencies**. The gem must work with stdlib only. New
|
|
24
|
+
dependencies require explicit user approval.
|
|
25
|
+
* **Ruby >= 2.7**. Do not use language features introduced after 2.7
|
|
26
|
+
without flagging.
|
|
27
|
+
* **`desc` is single-arg, multi-line allowed**. The argument is one
|
|
28
|
+
string; it may contain newlines. The first line is the brief shown in
|
|
29
|
+
command listings, the full string renders (indented) in per-command
|
|
30
|
+
help. Trailing whitespace is stripped so heredocs work cleanly. `desc`
|
|
31
|
+
is never multi-arg - that form was tried and reverted.
|
|
32
|
+
* **The `proc` is the trailing expression of a `task` block.** Do not
|
|
33
|
+
introduce `run do ... end` or similar - the user explicitly chose this.
|
|
34
|
+
|
|
35
|
+
## File layout
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
bin/hammer # CLI entry point
|
|
39
|
+
lib/lux-hammer.rb # Entry - defines class Hammer and its DSL
|
|
40
|
+
lib/hammer/shell.rb # ANSI/IO helpers
|
|
41
|
+
lib/hammer/option.rb # One option definition
|
|
42
|
+
lib/hammer/parser.rb # ARGV -> [positional, opts_hash]
|
|
43
|
+
lib/hammer/command.rb # One registered command (name, opts, alts, handler)
|
|
44
|
+
lib/hammer/loader.rb # `*_hammer.rb` fragment loader (auto/glob/file)
|
|
45
|
+
lib/hammer/builder.rb # Block-DSL context (Hammerfile / Hammer.run)
|
|
46
|
+
lib/hammer/command_builder.rb # `task :name do ... end` context
|
|
47
|
+
test/dsl_test.rb # DSL surface, dispatch, help formatting
|
|
48
|
+
test/load_test.rb # `load` / `*_hammer.rb` fragment loader
|
|
49
|
+
test/parser_test.rb # ARGV parsing edge cases
|
|
50
|
+
test/option_test.rb # Option declaration / casting
|
|
51
|
+
test/command_test.rb # Command data type
|
|
52
|
+
test/shell_test.rb # ANSI / IO helpers
|
|
53
|
+
test/cli_test.rb # `hammer` binary end-to-end
|
|
54
|
+
examples/Hammerfile # Reference Hammerfile
|
|
55
|
+
examples/class_dsl.rb # Reference class DSL usage
|
|
56
|
+
examples/block_dsl.rb # Reference block DSL usage
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## DSL surface (do not break compatibility silently)
|
|
60
|
+
|
|
61
|
+
Inside a `task :name do ... end` block (CommandBuilder context):
|
|
62
|
+
|
|
63
|
+
* `desc 'short description'` (string may contain `\n`; first line is
|
|
64
|
+
the brief shown in listings, full text renders in per-command help)
|
|
65
|
+
* `example 'invocation example'` (callable many times)
|
|
66
|
+
* `opt :name, type:, default:, alias:, desc:, req:` - any other kwarg
|
|
67
|
+
raises `Hammer::Error` ("unknown opt parameter(s)")
|
|
68
|
+
* `alt :other_name` (callable many times)
|
|
69
|
+
* `needs :other_cmd, 'ns:cmd'` - prereqs run before the handler;
|
|
70
|
+
resolved against root (same lookup as `hammer`), deduped per
|
|
71
|
+
top-level `start` so each prereq fires at most once. Dedupe also
|
|
72
|
+
spans `+`-chained segments. Unknown prereq raises `Hammer::Error`.
|
|
73
|
+
* `proc do |opts| ... end` - **the last expression**, becomes handler
|
|
74
|
+
|
|
75
|
+
At class scope (for `def`-style commands):
|
|
76
|
+
|
|
77
|
+
* `desc`, `example`, `opt`, `alt`, `needs` set pending state
|
|
78
|
+
* The next `def` consumes the pending state IF `desc` was set; otherwise
|
|
79
|
+
the method is treated as a plain helper
|
|
80
|
+
* Methods with arity 0 are called without opts; methods that take an arg
|
|
81
|
+
receive the opts hash
|
|
82
|
+
|
|
83
|
+
At class or `Hammerfile` scope:
|
|
84
|
+
|
|
85
|
+
* `task :name do ... end`
|
|
86
|
+
* `namespace :name do ... end`
|
|
87
|
+
* `load` / `load auto: true` / `load 'path/file.rb'` / `load 'glob/*.rb'` /
|
|
88
|
+
`load 'some/dir'` - pull in Hammerfile fragments from `*_hammer.rb`
|
|
89
|
+
files. Paths resolve relative to the caller's file. A directory
|
|
90
|
+
argument triggers the same recursive scan as `load auto: true` but
|
|
91
|
+
anchored at the given dir (empty result is OK, no error - apps with
|
|
92
|
+
no fragments are normal). Globs and explicit file paths still raise
|
|
93
|
+
on zero matches as a typo guard. Fragments are de-duplicated per
|
|
94
|
+
target class, so re-entrant `load` is safe. Skipped dirs:
|
|
95
|
+
`.git`, `.bundle`, `node_modules`, `tmp`, `vendor`, `dist`, `build`,
|
|
96
|
+
`coverage`, plus any hidden dir. Fragment shape is the block DSL
|
|
97
|
+
(`task`, `namespace`); class-DSL fragments belong in plain `.rb`
|
|
98
|
+
files loaded with `require_relative`.
|
|
99
|
+
|
|
100
|
+
Runtime cross-invocation:
|
|
101
|
+
|
|
102
|
+
* `hammer(name, *args, **opts)` - `name` is a symbol for a top-level
|
|
103
|
+
command (`hammer :build`) or a colon-path string for namespaced ones
|
|
104
|
+
(`hammer 'db:users:list'`). Trailing positionals become positional
|
|
105
|
+
ARGV. Kwargs become flags: underscores in keys map to dashes,
|
|
106
|
+
`true` -> `--flag`, `false` -> skipped (use `no_x: true` to negate),
|
|
107
|
+
any other value -> `--key=value`. Available both on a class
|
|
108
|
+
(`MyCli.hammer ...`) and inside a handler proc.
|
|
109
|
+
|
|
110
|
+
## Entry points
|
|
111
|
+
|
|
112
|
+
* `Hammer.run(argv = ARGV) { ... }` - inline block DSL, builds an
|
|
113
|
+
anonymous subclass, dispatches `argv` against it.
|
|
114
|
+
* `Hammer.run(argv = ARGV)` - **without a block**: load `./Hammerfile`
|
|
115
|
+
if present, otherwise auto-discover `*_hammer.rb` under `Dir.pwd`,
|
|
116
|
+
then dispatch. No walk-up, no chdir. The "do the obvious thing"
|
|
117
|
+
entry point for a fixed bin script; users who need
|
|
118
|
+
walk-up + chdir + missing-Hammerfile error use `Hammer.cli`
|
|
119
|
+
(`bin/hammer`).
|
|
120
|
+
* `Hammer.cli(argv = ARGV)` - internal entry for `bin/hammer` only:
|
|
121
|
+
walks up from `Dir.pwd` for a `Hammerfile`, chdirs into its dir,
|
|
122
|
+
errors if none found anywhere up the tree. Not part of the
|
|
123
|
+
user-facing surface - don't recommend it in examples; `Hammer.run`
|
|
124
|
+
is what library users should reach for.
|
|
125
|
+
* `class MyCli < Hammer; ... end; MyCli.start(ARGV)` - classic class
|
|
126
|
+
DSL. `.start` is the dispatch primitive everything else funnels into.
|
|
127
|
+
|
|
128
|
+
## `opts` hash contract
|
|
129
|
+
|
|
130
|
+
Always a `Hash` with **symbol keys**. Never change this without an
|
|
131
|
+
explicit ADR-level discussion. Keys:
|
|
132
|
+
|
|
133
|
+
* one per declared option
|
|
134
|
+
* `opts[:args]` - leftover positional ARGV (after declaration-order
|
|
135
|
+
fill)
|
|
136
|
+
|
|
137
|
+
## Dispatch model
|
|
138
|
+
|
|
139
|
+
* Commands are addressed by colon path: `db:users:list`.
|
|
140
|
+
* The root `Hammer` subclass holds `@commands` and `@namespaces`.
|
|
141
|
+
* `resolve('a:b:c')` walks `@namespaces['a'].namespaces['b']` and
|
|
142
|
+
finds command `c` in the last class.
|
|
143
|
+
* There is **no per-level dispatch**. A namespace is a container, not a
|
|
144
|
+
CLI of its own. Do not reintroduce `subclass.start(remaining_argv)`.
|
|
145
|
+
* `start(argv)` is a two-step pipeline: `split_chain(argv)` (private)
|
|
146
|
+
splits on bare `+` tokens and unescapes `++` -> `+`, then `dispatch`
|
|
147
|
+
(private) runs each segment. `start` is the only public entry that
|
|
148
|
+
also sets up the per-invocation `needs`/`before` dedupe state, so the
|
|
149
|
+
whole `+` chain shares one dedupe scope. Don't have `dispatch` call
|
|
150
|
+
back into `start` for sub-segments - that re-triggers chain detection
|
|
151
|
+
on already-unescaped `+` tokens (bug we fixed; the test
|
|
152
|
+
`test_chain_escape_double_plus_yields_literal_plus_arg` guards it).
|
|
153
|
+
|
|
154
|
+
## Help formatting
|
|
155
|
+
|
|
156
|
+
* Program name in usage lines is computed automatically (invocation path
|
|
157
|
+
relative to cwd if the bin lives inside cwd, otherwise the basename of
|
|
158
|
+
`$PROGRAM_NAME`). There is no user-facing override; the auto-detection
|
|
159
|
+
is the whole API. `Hammer.cli` warms the cache before chdir-ing into
|
|
160
|
+
the Hammerfile's directory so the resolved name stays relative to the
|
|
161
|
+
cwd the user invoked from.
|
|
162
|
+
* `hammer` (no args), `hammer -h`, and `hammer --help` all print top-level help.
|
|
163
|
+
* `hammer COMMAND -h` / `--help` prints per-command help (reserved on every command).
|
|
164
|
+
* Commands listed flat with colon paths, grouped by top-level namespace.
|
|
165
|
+
* Bare namespace (`hammer db`) prints the same listing scoped to that
|
|
166
|
+
namespace.
|
|
167
|
+
* Per-command help: usage line shows declared opts inline (required
|
|
168
|
+
bare, optional bracketed), then options with `(default: ...)` /
|
|
169
|
+
`(required)` annotations, then examples.
|
|
170
|
+
|
|
171
|
+
## Inline helpers (`Hammer::Shell`)
|
|
172
|
+
|
|
173
|
+
Mixed into every handler. Also callable directly as `Hammer::Shell.<x>`.
|
|
174
|
+
Complete surface:
|
|
175
|
+
|
|
176
|
+
```ruby
|
|
177
|
+
say 'plain' # print
|
|
178
|
+
say.green 'ok' # colored via proxy (preferred form)
|
|
179
|
+
say 'ok', :green # equivalent two-arg form
|
|
180
|
+
say '' # blank line (NOT `say` with no args)
|
|
181
|
+
|
|
182
|
+
'OK'.color(:green) # paint without printing
|
|
183
|
+
Hammer::Shell.paint('x', :red) # the underlying primitive
|
|
184
|
+
|
|
185
|
+
error 'config missing' unless ok # raise Hammer::Error -> dispatcher exits 1
|
|
186
|
+
name = ask 'name' # read line
|
|
187
|
+
env = ask 'env', default: 'dev' # blank input -> default
|
|
188
|
+
exit 0 unless yes? 'continue?' # y/Y prefix -> true, else false
|
|
189
|
+
idx = choose 'Pick env', envs # arrow-key picker, returns Integer or nil
|
|
190
|
+
sh 'bundle install' # echo "$ cmd" gray, raise on non-zero
|
|
191
|
+
|
|
192
|
+
Hammer::Shell.color!(true|false) # force ANSI on/off
|
|
193
|
+
Hammer::Shell.color? # current state
|
|
194
|
+
Hammer::Shell.print_error 'msg' # stderr, no raise - dispatcher-only
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Doc rule: prefer `say.<color> 'x'` over `say 'x', :<color>` in README
|
|
198
|
+
and examples - both work, but the proxy form reads better and is what
|
|
199
|
+
new code in this gem should show.
|
|
200
|
+
|
|
201
|
+
`choose` invariants worth knowing:
|
|
202
|
+
|
|
203
|
+
* Uses `io/console` (stdlib, no new dependency).
|
|
204
|
+
* TTY path renders the list, redraws on each keystroke (`\e[NA\e[J`),
|
|
205
|
+
hides/restores the cursor, and reads bytes via `$stdin.raw { ... }`.
|
|
206
|
+
* Keys: `j`/`k` and arrow keys (ESC `[` `A`/`B`) move; Enter confirms;
|
|
207
|
+
`q`, ESC alone, and Ctrl-C cancel. ESC-vs-arrow is disambiguated with
|
|
208
|
+
a tiny `IO.select` timeout - the arrow's `[A` follows ESC immediately,
|
|
209
|
+
a bare ESC keystroke is alone.
|
|
210
|
+
* Non-TTY path (`!$stdin.tty?` or stdin without `raw`) prints a numbered
|
|
211
|
+
list and reads one line. Both paths return the same: `Integer` index
|
|
212
|
+
or `nil`. Don't break this contract - it's why `choose` is scriptable.
|
|
213
|
+
* On confirm, the rendered list is collapsed to one green line; on
|
|
214
|
+
cancel, the list is cleared. Don't leave the raw-mode list behind.
|
|
215
|
+
* Empty `items` raises `Hammer::Error` ('at least one item') - same
|
|
216
|
+
failure pattern as bad colors.
|
|
217
|
+
|
|
218
|
+
## Colors
|
|
219
|
+
|
|
220
|
+
* Color set: `:black :red :green :yellow :blue :magenta :cyan :white :gray`
|
|
221
|
+
(see `Hammer::Shell::COLORS`). No bold, no bright variants, no
|
|
222
|
+
background colors. Don't add more without an explicit ask.
|
|
223
|
+
* All four entry points (`say x, :c`, `say.c x`, `paint x, :c`,
|
|
224
|
+
`'x'.color(:c)`) flow through `Shell.paint` - it's the only place
|
|
225
|
+
ANSI codes live.
|
|
226
|
+
* Unknown colors must raise `Hammer::Error` with the list of valid
|
|
227
|
+
names. This is enforced in `Shell.paint` and in `SayProxy#method_missing`
|
|
228
|
+
- don't bypass it. Validation runs even when colors are disabled, so
|
|
229
|
+
a typo fails loudly in CI.
|
|
230
|
+
* `say` with no args returns the `SayProxy`; `say ''` is how you print
|
|
231
|
+
a blank line. Don't restore `say` (no args) -> blank-line semantics.
|
|
232
|
+
|
|
233
|
+
## Error handling
|
|
234
|
+
|
|
235
|
+
* `Hammer::Shell.error 'msg'` raises `Hammer::Error`. The dispatcher
|
|
236
|
+
catches it inside `run_command`, prints `[error] msg` in red to
|
|
237
|
+
stderr, and exits 1 - no backtrace, no per-command help.
|
|
238
|
+
* `Hammer::Shell.print_error 'msg'` prints without raising; reserved
|
|
239
|
+
for the dispatcher's own diagnostics (unknown command, missing
|
|
240
|
+
Hammerfile).
|
|
241
|
+
* `Hammer::Parser::Error` is also caught in `run_command` and
|
|
242
|
+
additionally prints per-command help (because the input *was* aimed
|
|
243
|
+
at that command).
|
|
244
|
+
* Inside a handler, just call `error 'msg'` - it resolves via the
|
|
245
|
+
`Shell` mixin.
|
|
246
|
+
|
|
247
|
+
## Coding rules
|
|
248
|
+
|
|
249
|
+
* No trailing spaces on empty lines. End every file with a newline.
|
|
250
|
+
* Use ASCII only - `-`, not unicode dashes; `*` for bullets in docs.
|
|
251
|
+
* Preserve existing style. Minimize diff size.
|
|
252
|
+
* Comments only when the *why* is non-obvious. Don't restate the code.
|
|
253
|
+
* No `// removed` markers - delete cleanly.
|
|
254
|
+
* Constants: prefer `FOO ||=` over `FOO =` (re-load safety).
|
|
255
|
+
* Never commit or push without explicit confirmation.
|
|
256
|
+
|
|
257
|
+
## Testing
|
|
258
|
+
|
|
259
|
+
* Run: `bundle exec rake test`
|
|
260
|
+
* Single file: `bundle exec ruby -Ilib -Itest test/parser_test.rb`
|
|
261
|
+
* Single test by name: `... test/parser_test.rb -n test_boolean_via_short_alias`
|
|
262
|
+
* Helper `CaptureIO` in `test/test_helper.rb` swaps `$stdout`/`$stderr`
|
|
263
|
+
for `StringIO`. Use `capture { ... }` for non-exiting code and
|
|
264
|
+
`capture_exit { ... }` for code that calls `exit`.
|
|
265
|
+
|
|
266
|
+
When you add a feature, add a test in the matching `_test.rb`. When you
|
|
267
|
+
fix a bug, write the failing test first.
|
|
268
|
+
|
|
269
|
+
## What NOT to do
|
|
270
|
+
|
|
271
|
+
* Don't add generators / templates (Thor-style file scaffolding).
|
|
272
|
+
* Don't add shell-completion generation to core - that belongs in a
|
|
273
|
+
separate plugin gem.
|
|
274
|
+
* Don't introduce a class hierarchy for commands. Commands are data
|
|
275
|
+
(`Hammer::Command` instances), not classes.
|
|
276
|
+
* Don't reintroduce a user-facing `program` / `program_name` setter -
|
|
277
|
+
the auto-detected name is the whole API and was deliberately reduced
|
|
278
|
+
to that.
|
|
279
|
+
* Don't propagate `program_name` into namespaces as a longer prefix -
|
|
280
|
+
there is only one program name.
|
|
281
|
+
* Don't make `desc` multi-arg again (it once took `usage, description`
|
|
282
|
+
- that was reverted intentionally).
|
|
283
|
+
* Don't add a `subcommand 'name', SomeClass` form - it was replaced by
|
|
284
|
+
`namespace :name do ... end` intentionally.
|
|
285
|
+
* Don't auto-namespace fragments by filename (e.g. `db_hammer.rb` does
|
|
286
|
+
not implicitly wrap in `namespace :db do ... end`). Be explicit, as
|
|
287
|
+
Rake's `import` is. If a fragment wants a namespace, it writes it.
|
|
288
|
+
|
|
289
|
+
## When in doubt
|
|
290
|
+
|
|
291
|
+
* Read `lib/lux-hammer.rb` top-to-bottom. It's the whole DSL surface.
|
|
292
|
+
* Run the example: `cd examples && ruby -I../lib ../bin/hammer`
|
|
293
|
+
* Check `test/dsl_test.rb` for the canonical behavior of each feature.
|
|
294
|
+
* Check `test/load_test.rb` for `load` / fragment loader behavior.
|
data/bin/hammer
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
# Prefer the adjacent lib/ when this script lives in a repo checkout
|
|
3
|
+
# (lib/lux-hammer.rb sits next to bin/), otherwise fall back to the
|
|
4
|
+
# installed gem. Otherwise an installed older gem shadows local edits.
|
|
5
|
+
local_lib = File.expand_path('../lib/lux-hammer.rb', __dir__)
|
|
6
|
+
if File.file?(local_lib)
|
|
7
|
+
$LOAD_PATH.unshift File.dirname(local_lib)
|
|
8
8
|
end
|
|
9
|
+
require 'lux-hammer'
|
|
9
10
|
Hammer.cli(ARGV)
|
data/lib/lux-hammer.rb
CHANGED
|
@@ -619,10 +619,31 @@ class Hammer
|
|
|
619
619
|
klass.start(argv)
|
|
620
620
|
end
|
|
621
621
|
|
|
622
|
+
# Dump the gem's AGENTS.md to stdout - AI-optimized guide for
|
|
623
|
+
# writing Hammerfiles. Bundled with the gem and resolved relative
|
|
624
|
+
# to this file so it works from any install location.
|
|
625
|
+
def self.print_ai_help
|
|
626
|
+
path = File.expand_path('../AGENTS.md', __dir__)
|
|
627
|
+
if File.file?(path)
|
|
628
|
+
puts File.read(path)
|
|
629
|
+
else
|
|
630
|
+
Shell.print_error "AGENTS.md not found at #{path}"
|
|
631
|
+
exit 1
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
|
|
622
635
|
# Entry point for the `hammer` binary. Walks up from CWD until it
|
|
623
636
|
# finds a Hammerfile, evaluates it as the block DSL, then dispatches
|
|
624
637
|
# ARGV against the resulting CLI.
|
|
638
|
+
#
|
|
639
|
+
# `--ai` is a meta-flag handled here, before Hammerfile lookup,
|
|
640
|
+
# so it works anywhere (no project required).
|
|
625
641
|
def self.cli(argv = ARGV)
|
|
642
|
+
if argv.include?('--ai')
|
|
643
|
+
print_ai_help
|
|
644
|
+
exit 0
|
|
645
|
+
end
|
|
646
|
+
|
|
626
647
|
path = find_hammerfile(Dir.pwd)
|
|
627
648
|
unless path
|
|
628
649
|
Shell.print_error "no Hammerfile found in #{Dir.pwd} or any parent directory"
|
|
@@ -649,6 +670,8 @@ class Hammer
|
|
|
649
670
|
end
|
|
650
671
|
end
|
|
651
672
|
RUBY
|
|
673
|
+
Shell.say ''
|
|
674
|
+
Shell.say "tip: run `#{File.basename($PROGRAM_NAME)} --ai` for AI-friendly Hammerfile authoring docs", :gray
|
|
652
675
|
exit 1
|
|
653
676
|
end
|
|
654
677
|
|
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.
|
|
4
|
+
version: 0.2.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dino Reic
|
|
@@ -32,6 +32,7 @@ extensions: []
|
|
|
32
32
|
extra_rdoc_files: []
|
|
33
33
|
files:
|
|
34
34
|
- "./.version"
|
|
35
|
+
- "./AGENTS.md"
|
|
35
36
|
- "./README.md"
|
|
36
37
|
- "./bin/hammer"
|
|
37
38
|
- "./lib/hammer/builder.rb"
|