Module: Dkit::ShellHook

Defined in:
lib/dkit/shell_hook.rb

Class Method Summary collapse

Class Method Details

.generateObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/dkit/shell_hook.rb', line 5

def generate
  <<~'ZSH'
    # Generated by: dkit hook
    # Add to ~/.zshrc: eval "$(dkit hook)"

    _DKIT_ROOT=""
    _DKIT_ACTIVE_CMDS=()
    _DKIT_GLOB_PATTERNS=()
    _DKIT_GLOB_CMDS=()

    _dkit_reset() {
      local cmd
      for cmd in "${_DKIT_ACTIVE_CMDS[@]}"; do
        unfunction "$cmd" 2>/dev/null
      done
      _DKIT_ACTIVE_CMDS=()
      _DKIT_GLOB_PATTERNS=()
      _DKIT_GLOB_CMDS=()
    }

    _dkit_verbose_fallback() {
      [[ "${DKIT_VERBOSE}" == "0" || -z "${_DKIT_ROOT}" ]] && return
      local _ic="${_DKIT_ROOT}/.devcontainer/dkit-intercept"
      grep -qxF 'verbose: false' "$_ic" 2>/dev/null && return
      printf '\033[31m[dkit] %s → host (fallback)\033[0m\n' "$1" >&2
    }

    _dkit_expand_glob() {
      local root="$1" pattern="$2"
      local full_pattern="$root/$pattern"
      local matches=( ${~full_pattern}(N*) )
      local m rel
      for m in "${matches[@]}"; do
        rel="${m#$root/}"
        (( ${_DKIT_ACTIVE_CMDS[(Ie)$rel]} )) && continue
        eval "function ${rel}() {
          if dkit status --quiet 2>/dev/null; then
            dkit run ${rel} \"\$@\"
          else
            _dkit_verbose_fallback \"${rel}\"
            command ${rel} \"\$@\"
          fi
        }"
        _DKIT_ACTIVE_CMDS+=("${rel}")
        _DKIT_GLOB_CMDS+=("${rel}")
      done
    }

    _dkit_refresh_globs() {
      [[ -z "$_DKIT_ROOT" || ${#_DKIT_GLOB_PATTERNS[@]} -eq 0 ]] && return
      local cmd
      for cmd in "${_DKIT_GLOB_CMDS[@]}"; do
        if [[ ! -e "$_DKIT_ROOT/$cmd" ]]; then
          unfunction "$cmd" 2>/dev/null
          _DKIT_ACTIVE_CMDS=("${(@)_DKIT_ACTIVE_CMDS:#$cmd}")
        fi
      done
      _DKIT_GLOB_CMDS=()
      local pat
      for pat in "${_DKIT_GLOB_PATTERNS[@]}"; do
        _dkit_expand_glob "$_DKIT_ROOT" "$pat"
      done
    }

    _dkit_load() {
      local root="$1"
      local intercept="$root/.devcontainer/dkit-intercept"
      [[ -f "$intercept" ]] || return
      local cmd
      while IFS= read -r cmd; do
        [[ -z "$cmd" || "${cmd[1]}" == "#" ]] && continue
        # Trim whitespace
        cmd="${cmd## }"
        cmd="${cmd%% }"
        [[ -z "$cmd" ]] && continue
        # Glob pattern: expand matching executables
        if [[ "$cmd" == *[\*\?\[]* ]]; then
          _DKIT_GLOB_PATTERNS+=("${cmd}")
          _dkit_expand_glob "$root" "$cmd"
          continue
        fi
        eval "function ${cmd}() {
          if dkit status --quiet 2>/dev/null; then
            dkit run ${cmd} \"\$@\"
          else
            _dkit_verbose_fallback \"${cmd}\"
            command ${cmd} \"\$@\"
          fi
        }"
        _DKIT_ACTIVE_CMDS+=("${cmd}")
      done < "$intercept"
    }

    _dkit_chpwd() {
      # Fast path: still inside the same project root
      if [[ -n "$_DKIT_ROOT" && "$PWD" == "$_DKIT_ROOT"* ]]; then
        return
      fi
      local new_root
      new_root="$(dkit root 2>/dev/null || echo '')"
      [[ "$new_root" == "$_DKIT_ROOT" ]] && return
      _dkit_reset
      _DKIT_ROOT="$new_root"
      [[ -n "$new_root" ]] && _dkit_load "$new_root"
    }

    # Special commands — always available, always route to devcontainer
    code() {
      if dkit status --quiet 2>/dev/null; then
        dkit code "$@"
      else
        _dkit_verbose_fallback "code"
        command code "$@"
      fi
    }

    claude() {
      if dkit status --quiet 2>/dev/null; then
        dkit claude "$@"
      else
        _dkit_verbose_fallback "claude"
        command claude "$@"
      fi
    }

    autoload -U add-zsh-hook
    add-zsh-hook chpwd _dkit_chpwd
    add-zsh-hook precmd _dkit_refresh_globs
    _dkit_chpwd
  ZSH
end