Problem
To compile files that are generated by atclone/atpull (e.g. scripts produced by a build step), zinit currently requires two separate ices working together:
zinit ice nocompile'!' compile'init.zsh' ...
This is unintuitive and inconsistent for several reasons:
nocompile'!' is a negative ice being used as a positive trigger. The ! value on nocompile secretly means "do compile, but later" — the opposite of what the ice name implies.
- Intent is split across two ices (
nocompile'!' for timing, compile'pattern' for selection) when it should be expressible as one.
- Inconsistency with every other timed ice. In zinit,
! as a prefix on the value consistently means "run this earlier or later in the hook sequence": make'!', atpull'!', configure'!', etc. The natural expectation is that compile'!pattern' means "compile this pattern, but after atclone/atpull".
Concrete example where this bites users
# atclone generates init.zsh and _atuin — but compile runs BEFORE atclone,
# so there is nothing to compile yet. The workaround is ugly:
zinit ice \
atclone"atuin init zsh > init.zsh && atuin gen-completions --shell zsh > _atuin" \
atpull"%atclone" run-atpull \
nocompile'!' compile'init.zsh' \ # two ices to express one intent
pick"init.zsh"
zinit light zdharma-continuum/null
Describe the proposed feature.
Proposed solution
Support compile'!pattern' — where a ! prefix on the value means "compile after atclone/atpull", matching files by the remainder of the value as a glob pattern. This directly mirrors the existing !-prefix timing convention.
# Clean, single-ice expression of the same intent:
zinit ice \
atclone"atuin init zsh > init.zsh && atuin gen-completions --shell zsh > _atuin" \
atpull"%atclone" run-atpull \
compile'!init.zsh' \
pick"init.zsh"
zinit light zdharma-continuum/null
Behaviour spec
| Ice value |
Timing |
Files compiled |
compile'*.zsh' |
Before atclone/atpull (current default) |
Files matching *.zsh |
compile'!*.zsh' |
After atclone/atpull (new) |
Files matching *.zsh |
nocompile'!' |
No-op (bare ! with no pattern) |
Nothing — preserves any edge-case compatibility. Do NOT add `nocompile'!pattern' |
Backwards compatibility
- No existing behaviour changes.
compile'pattern' (no !) continues to work exactly as today.
nocompile'!' continues to work as today (no deprecation required unless maintainers choose to).
- The only code path added is: if
ICE[compile] starts with ! and has content after the !, treat it as a late-compile with that suffix as the pattern.
Describe alternatives you've considered
Work-around already described (duplicate ices, not intuitive)
Additional context
Implementation hint
In ∞zinit-compile-plugin-hook (zinit-install.zsh), the relevant condition is:
if ! [[ ( $hook = *\!at(clone|pull)* && ${+ICE[nocompile]} -eq 0 ) || \
( $hook = at(clone|pull)* && $ICE[nocompile] = '!' ) ]]; then
return 0
fi
A compile'!pattern' implementation would add a third branch: trigger late compilation when $hook = at(clone|pull)* and ${ICE[compile]} starts with ! (and has a non-empty pattern suffix), using ${ICE[compile]#!} as the glob.
Related Issues
No response
Problem
To compile files that are generated by
atclone/atpull(e.g. scripts produced by a build step), zinit currently requires two separate ices working together:This is unintuitive and inconsistent for several reasons:
nocompile'!'is a negative ice being used as a positive trigger. The!value onnocompilesecretly means "do compile, but later" — the opposite of what the ice name implies.nocompile'!'for timing,compile'pattern'for selection) when it should be expressible as one.!as a prefix on the value consistently means "run this earlier or later in the hook sequence":make'!',atpull'!',configure'!', etc. The natural expectation is thatcompile'!pattern'means "compile this pattern, but afteratclone/atpull".Concrete example where this bites users
Describe the proposed feature.
Proposed solution
Support
compile'!pattern'— where a!prefix on the value means "compile afteratclone/atpull", matching files by the remainder of the value as a glob pattern. This directly mirrors the existing!-prefix timing convention.Behaviour spec
compile'*.zsh'atclone/atpull(current default)*.zshcompile'!*.zsh'atclone/atpull(new)*.zshnocompile'!'!with no pattern)Backwards compatibility
compile'pattern'(no!) continues to work exactly as today.nocompile'!'continues to work as today (no deprecation required unless maintainers choose to).ICE[compile]starts with!and has content after the!, treat it as a late-compile with that suffix as the pattern.Describe alternatives you've considered
Work-around already described (duplicate ices, not intuitive)
Additional context
Implementation hint
In
∞zinit-compile-plugin-hook(zinit-install.zsh), the relevant condition is:A
compile'!pattern'implementation would add a third branch: trigger late compilation when$hook = at(clone|pull)*and${ICE[compile]}starts with!(and has a non-empty pattern suffix), using${ICE[compile]#!}as the glob.Related Issues
No response