dkit 0.3.1 → 0.4.0

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/bin/dkit +64 -21
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff6fc0e53b34c039584e579f8b866d5097ee8ef9ff3b5951e3fa6a905ef6320e
4
- data.tar.gz: cc0cf53bb9df918be82d7e38542175ef10421b522f06b746380f7c2a4fc74bea
3
+ metadata.gz: 50d35a0b2d2d8d179be81ce6360eccc29cacd941125ce01dc7202954a7499ab1
4
+ data.tar.gz: 727ca198989f81815d6aa2fecb8a2096ababe1402de1f2e73e0cdc07938753dc
5
5
  SHA512:
6
- metadata.gz: 153b4417073e89d4b28da38ee174049e16439406e1915bc631e41b81d7986bf91dcd8effa28db55b861f0f563378ea63417562889e737b9b8435a4835a781d5e
7
- data.tar.gz: 9e8b738739abfd0c65b1815d7d30f948bdbe3bf26e5af42a8582f60712e71be02639f739ac30293de22e1b6d0fa27fab8836c0e802e73fe9844d616591e4c28f
6
+ metadata.gz: 24a65808288983e07fe1897600f467d763518c09954480c6b0dd753e2f310a055c8928e1cd7cf3933c46945ac6a6f2b87eecdb66d754f083e24c20d82153e595
7
+ data.tar.gz: 6e604b67d3bafed4b1c90794fd5bf9309a807dbdcd5a0d72f7641f0b5faeb20b7da3a9db2206e983461c43d94204195269c4abfd24ed9b660ec4a603ab5e2e9b
data/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.0] - 2026-04-13
9
+
10
+ ### Added
11
+ - Glob/wildcard patterns in intercept file: `bin/*` intercepts all executables under `bin/` (e.g. `bin/rails`, `bin/rspec`)
12
+ - New zsh helpers `_dkit_expand_glob` and `_dkit_refresh_globs` for dynamic function creation from glob patterns
13
+ - `precmd` hook automatically picks up new executables and cleans up deleted ones between prompts
14
+ - Help text documents glob usage with quoting example
15
+
16
+ ### Notes
17
+ - Glob patterns must be quoted to prevent shell expansion: `dkit intercept add 'bin/*'`
18
+ - Only executable files are matched (non-executable files like READMEs are skipped)
19
+ - Requires `exec zsh` after gem update to reload the shell hook
20
+
21
+ ## [0.3.3] - 2026-04-13
22
+
23
+ ### Changed
24
+ - Verbose fallback messages are now printed in red and include a `(fallback)` label: `[dkit] bundle → host (fallback)`
25
+
8
26
  ## [0.3.1] - 2026-04-13
9
27
 
10
28
  ### Added
data/bin/dkit CHANGED
@@ -16,7 +16,7 @@ require 'pathname'
16
16
  require 'shellwords'
17
17
  require 'fileutils'
18
18
 
19
- VERSION = "0.3.1"
19
+ VERSION = "0.4.0"
20
20
  DC_CONFIG = ".devcontainer/devcontainer.json"
21
21
  DC_INTERCEPT = ".devcontainer/dkit-intercept"
22
22
 
@@ -228,6 +228,8 @@ def cmd_hook
228
228
 
229
229
  _DKIT_ROOT=""
230
230
  _DKIT_ACTIVE_CMDS=()
231
+ _DKIT_GLOB_PATTERNS=()
232
+ _DKIT_GLOB_CMDS=()
231
233
 
232
234
  _dkit_reset() {
233
235
  local cmd
@@ -235,6 +237,52 @@ def cmd_hook
235
237
  unfunction "$cmd" 2>/dev/null
236
238
  done
237
239
  _DKIT_ACTIVE_CMDS=()
240
+ _DKIT_GLOB_PATTERNS=()
241
+ _DKIT_GLOB_CMDS=()
242
+ }
243
+
244
+ _dkit_verbose_fallback() {
245
+ [[ "${DKIT_VERBOSE}" == "0" || -z "${_DKIT_ROOT}" ]] && return
246
+ local _ic="${_DKIT_ROOT}/.devcontainer/dkit-intercept"
247
+ grep -qxF 'verbose: false' "$_ic" 2>/dev/null && return
248
+ printf '\033[31m[dkit] %s → host (fallback)\033[0m\n' "$1" >&2
249
+ }
250
+
251
+ _dkit_expand_glob() {
252
+ local root="$1" pattern="$2"
253
+ local full_pattern="$root/$pattern"
254
+ local matches=( ${~full_pattern}(N*) )
255
+ local m rel
256
+ for m in "${matches[@]}"; do
257
+ rel="${m#$root/}"
258
+ (( ${_DKIT_ACTIVE_CMDS[(Ie)$rel]} )) && continue
259
+ eval "function ${rel}() {
260
+ if dkit status --quiet 2>/dev/null; then
261
+ dkit run ${rel} \"\$@\"
262
+ else
263
+ _dkit_verbose_fallback \"${rel}\"
264
+ command ${rel} \"\$@\"
265
+ fi
266
+ }"
267
+ _DKIT_ACTIVE_CMDS+=("${rel}")
268
+ _DKIT_GLOB_CMDS+=("${rel}")
269
+ done
270
+ }
271
+
272
+ _dkit_refresh_globs() {
273
+ [[ -z "$_DKIT_ROOT" || ${#_DKIT_GLOB_PATTERNS[@]} -eq 0 ]] && return
274
+ local cmd
275
+ for cmd in "${_DKIT_GLOB_CMDS[@]}"; do
276
+ if [[ ! -e "$_DKIT_ROOT/$cmd" ]]; then
277
+ unfunction "$cmd" 2>/dev/null
278
+ _DKIT_ACTIVE_CMDS=("${(@)_DKIT_ACTIVE_CMDS:#$cmd}")
279
+ fi
280
+ done
281
+ _DKIT_GLOB_CMDS=()
282
+ local pat
283
+ for pat in "${_DKIT_GLOB_PATTERNS[@]}"; do
284
+ _dkit_expand_glob "$_DKIT_ROOT" "$pat"
285
+ done
238
286
  }
239
287
 
240
288
  _dkit_load() {
@@ -248,16 +296,17 @@ def cmd_hook
248
296
  cmd="${cmd## }"
249
297
  cmd="${cmd%% }"
250
298
  [[ -z "$cmd" ]] && continue
299
+ # Glob pattern: expand matching executables
300
+ if [[ "$cmd" == *[\*\?\[]* ]]; then
301
+ _DKIT_GLOB_PATTERNS+=("${cmd}")
302
+ _dkit_expand_glob "$root" "$cmd"
303
+ continue
304
+ fi
251
305
  eval "function ${cmd}() {
252
306
  if dkit status --quiet 2>/dev/null; then
253
307
  dkit run ${cmd} \"\$@\"
254
308
  else
255
- if [[ \"\${DKIT_VERBOSE}\" != \"0\" && -n \"\${_DKIT_ROOT}\" ]]; then
256
- local _ic=\"\${_DKIT_ROOT}/.devcontainer/dkit-intercept\"
257
- if ! grep -qxF 'verbose: false' \"\$_ic\" 2>/dev/null; then
258
- print -u2 \"[dkit] ${cmd} → host\"
259
- fi
260
- fi
309
+ _dkit_verbose_fallback \"${cmd}\"
261
310
  command ${cmd} \"\$@\"
262
311
  fi
263
312
  }"
@@ -283,12 +332,7 @@ def cmd_hook
283
332
  if dkit status --quiet 2>/dev/null; then
284
333
  dkit code "$@"
285
334
  else
286
- if [[ "${DKIT_VERBOSE}" != "0" && -n "${_DKIT_ROOT}" ]]; then
287
- local _ic="${_DKIT_ROOT}/.devcontainer/dkit-intercept"
288
- if ! grep -qxF 'verbose: false' "$_ic" 2>/dev/null; then
289
- print -u2 "[dkit] code → host"
290
- fi
291
- fi
335
+ _dkit_verbose_fallback "code"
292
336
  command code "$@"
293
337
  fi
294
338
  }
@@ -297,32 +341,28 @@ def cmd_hook
297
341
  if dkit status --quiet 2>/dev/null; then
298
342
  dkit claude "$@"
299
343
  else
300
- if [[ "${DKIT_VERBOSE}" != "0" && -n "${_DKIT_ROOT}" ]]; then
301
- local _ic="${_DKIT_ROOT}/.devcontainer/dkit-intercept"
302
- if ! grep -qxF 'verbose: false' "$_ic" 2>/dev/null; then
303
- print -u2 "[dkit] claude → host"
304
- fi
305
- fi
344
+ _dkit_verbose_fallback "claude"
306
345
  command claude "$@"
307
346
  fi
308
347
  }
309
348
 
310
349
  autoload -U add-zsh-hook
311
350
  add-zsh-hook chpwd _dkit_chpwd
351
+ add-zsh-hook precmd _dkit_refresh_globs
312
352
  _dkit_chpwd
313
353
  ZSH
314
354
  end
315
355
 
316
356
  def cmd_exec(ctx, args)
317
357
  abort_err("exec: no command given") if args.empty?
318
- warn "[dkit] #{args.join(" ")} → #{ctx.container}" if verbose_enabled?(ctx.project_root)
358
+ warn "\e[32m[dkit] #{args.join(" ")} → #{ctx.container}\e[0m" if verbose_enabled?(ctx.project_root)
319
359
  system("docker", "exec", "--user", ctx.user, "--workdir", ctx.cwd, ctx.container, *args)
320
360
  exit $?.exitstatus
321
361
  end
322
362
 
323
363
  def cmd_run(ctx, args)
324
364
  abort_err("run: no command given") if args.empty?
325
- warn "[dkit] #{args.join(" ")} → #{ctx.container}" if verbose_enabled?(ctx.project_root)
365
+ warn "\e[32m[dkit] #{args.join(" ")} → #{ctx.container}\e[0m" if verbose_enabled?(ctx.project_root)
326
366
  exec("docker", "exec", "-it", "--user", ctx.user, "--workdir", ctx.cwd, ctx.container, *args)
327
367
  end
328
368
 
@@ -331,10 +371,12 @@ def cmd_shell(ctx)
331
371
  end
332
372
 
333
373
  def cmd_claude(ctx, args)
374
+ warn "\e[32m[dkit] claude → #{ctx.container}\e[0m" if verbose_enabled?(ctx.project_root)
334
375
  exec("docker", "exec", "-it", "--user", ctx.user, "--workdir", ctx.cwd, ctx.container, "claude", *args)
335
376
  end
336
377
 
337
378
  def cmd_code(ctx, path_arg)
379
+ warn "\e[32m[dkit] code → #{ctx.container}\e[0m" if verbose_enabled?(ctx.project_root)
338
380
  host_path = path_arg ? File.expand_path(path_arg) : ctx.project_root
339
381
  rel = begin
340
382
  Pathname(host_path).relative_path_from(Pathname(ctx.project_root)).to_s
@@ -399,6 +441,7 @@ def cmd_help
399
441
  dkit init Create .devcontainer/dkit-intercept with auto-detected defaults
400
442
  dkit intercept list List intercepted commands for current project
401
443
  dkit intercept add <cmd> Add command to current project's intercept list
444
+ dkit intercept add 'bin/*' Add glob pattern (quote to prevent shell expansion)
402
445
  dkit intercept remove <cmd> Remove command from current project's intercept list
403
446
 
404
447
  Verbose routing messages (on by default):
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Augusto Stroligo