Skip to content

[feat]: compile'!pattern' — support late compilation (after atclone/atpull) with pattern in a single ice #776

Description

@HaleTom

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:

  1. 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.
  2. Intent is split across two ices (nocompile'!' for timing, compile'pattern' for selection) when it should be expressible as one.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions