{%- set output_width = terminal_width | default(80) -%}
{%- macro render_row(icon, pack_name, file_name, status_tag, status_label, note_ref) -%}
{%- set right_col = "[" ~ status_tag ~ "]" ~ status_label ~ "[/" ~ status_tag ~ "]" -%}
{%- if note_ref %}{% set right_col = right_col ~ " [dim][" ~ note_ref ~ "][/dim]" %}{% endif -%}
{%- set status_width = right_col | display_width -%}
{%- set file_tbl = tabular([{"width": 1, "style": "dim"}, {"width": 20}, {"width": "fill", "truncate": "middle", "style": "dim"}, {"width": status_width, "align": "right", "anchor": "right"}], separator=" ", width=output_width) -%}
{{ file_tbl.row([
icon,
pack_name,
file_name,
right_col
]) }}
{%- endmacro -%}
{%- macro render_pack(pack, view_mode, notes) -%}
{%- if view_mode == "short" -%}
{{ pack.name | col(32) }} ({{ pack.summary_count }}) [{{ pack.summary_status }}]{{ pack.summary_status }}[/{{ pack.summary_status }}]
{% else -%}
{% for file in pack.files %}{{ render_row(file.symbol, pack.name, file.name, file.status, file.status_label, file.note_ref) }}
{% endfor %}
{%- endif -%}
{%- endmacro -%}
{%- macro render_ignored_pack(pack) -%}
{{ render_row("∅", pack.display_name, pack.ignore_file, "ignored-pack", "ignored", none) }}
{%- endmacro -%}
{%- macro render_note(note, index) -%}
[{{ index }}] {% if note.timeline %}{% for ok in note.timeline %}{% if ok %}[deployed]✓[/deployed] {% else %}[error]✗[/error] {% endif %}{% endfor %}{% endif %}[{{ note.kind }}]{{ note.body }}{% if note.command %}, see [/{{ note.kind }}][diagnostic-command]{{ note.command }}[/diagnostic-command][{{ note.kind }}] for more.{% endif %}[/{{ note.kind }}]
{% if note.hint %} [{{ note.kind }}]hint: {{ note.hint }}[/{{ note.kind }}]
{% endif %}{%- endmacro -%}
{% if conflicts %}[conflict-banner] ✗ Cross-pack conflicts detected — see details below [/conflict-banner]
{% endif %}{% if message %}[message]{{ message }}[/message]
{% endif %}{% if dry_run %}[dry-run] (dry run — no changes made)[/dry-run]
{% endif %}{% if group_mode == "status" %}{% set deployed_group = packs | selectattr("summary_status", "equalto", "deployed") | list %}{% if deployed_group %}[group-banner-deployed]Deployed Packs[/group-banner-deployed]
{% for pack in deployed_group %}{{ render_pack(pack, view_mode, notes) }}{% endfor %}
{% endif %}{% set pending_group = packs | selectattr("summary_status", "equalto", "pending") | list %}{% if pending_group %}[group-banner-pending]Pending Packs[/group-banner-pending]
{% for pack in pending_group %}{{ render_pack(pack, view_mode, notes) }}{% endfor %}
{% endif %}{% set error_group = packs | selectattr("summary_status", "equalto", "error") | list %}{% if error_group %}[group-banner-error]Error Packs[/group-banner-error]
{% for pack in error_group %}{{ render_pack(pack, view_mode, notes) }}{% endfor %}
{% endif %}{% if ignored_packs %}{% if packs %}
{% endif %}{% for pack in ignored_packs %}{{ render_ignored_pack(pack) }}{% endfor %}
{% endif %}{% if inactive_packs %}[group-banner-ignored]Inactive on this OS[/group-banner-ignored]
{% for name in inactive_packs %} [ignored-pack]{{ name }}[/ignored-pack]
{% endfor %}
{% endif %}{% else %}{% for pack in packs %}{{ render_pack(pack, view_mode, notes) }}{% endfor %}{% if ignored_packs %}{% if packs %}
{% endif %}{% for pack in ignored_packs %}{{ render_ignored_pack(pack) }}{% endfor %}
{% endif %}{% if inactive_packs %}[pack-name]Inactive on this OS[/pack-name]
{% for name in inactive_packs %} [ignored-pack]{{ name }}[/ignored-pack]
{% endfor %}{% endif %}{% endif %}{% if notes %}{% set error_notes = notes | selectattr("kind", "equalto", "error") | list %}{% set warning_notes = notes | selectattr("kind", "equalto", "warning") | list %}{% if error_notes %}
[error]Errors:[/error]
{% for note in notes %}{% if note.kind == "error" %}{{ render_note(note, loop.index) }}{% endif %}{% endfor %}{% endif %}{% if warning_notes %}
[warning]Warnings:[/warning]
{% for note in notes %}{% if note.kind == "warning" %}{{ render_note(note, loop.index) }}{% endif %}{% endfor %}{% endif %}{% endif %}{% if conflicts %}
[conflict-header] Cross-pack conflicts [/conflict-header]
{% for c in conflicts %}
{% if c.kind == "symlink" %}The target path [conflict-target]{{ c.target }}[/conflict-target] would be used by multiple packs:
{% else %}The executable [conflict-target]{{ c.target }}[/conflict-target] would be shadowed across multiple packs in $PATH:
{% endif %}{% for cl in c.claimants %} - [conflict-pack]{{ cl.source }}[/conflict-pack]
{% endfor %}{% endfor %}
[conflict-hint]Common fixes: give them unique names, override the destination in the pack's config,[/conflict-hint]
[conflict-hint]or ignore the pack entirely. See `dodot config --help` for the last option.[/conflict-hint]
[conflict-hint]`dodot up` won't run while conflicts exist.[/conflict-hint]
{% endif %}{% if diffs %}
[header]Diffs (run-once files with edits since last run):[/header]
{% for d in diffs %}
[pack-name]{{ d.pack }} / {{ d.file }}[/pack-name]
{{ d.body }}{% endfor %}{% endif %}