{ pkgs }: pkgs.writeGawkBin "nixos-format-error" '' # usage: nixos-rebuild ... 2>&1 | nixos-format-error function out() { print next } BEGIN { IDLE = 0 ACTIVE = 1 PASSIVE = 2 ERROR = 3 start_state = IDLE state = start_state } END { if (trace_count) for (i = trace_count - 1; i >= 0; i--) print trace[i] } state == PASSIVE { out() } state == IDLE { if ($0 ~ /^building the system configuration\.\.\. ?$/) { state = ACTIVE } out() } state == ACTIVE { if ($1 ~ /(\[[0-9;]+m)?error:(\[[0-9;]m)?/) { state = ERROR sub(/^/,"\x1b[31;1m"); sub(/$/,"\x1b[m") trace[trace_count++] = $0 "stty -F /dev/tty size" |& getline COLUMNS = gensub(/.* ([0-9]+)$/, "\\1", "1") next } if ($0 ~ /^these [0-9]+ derivations will be built:/) { state = PASSIVE } if ($0 == "activating the configuration...") { state = PASSIVE } out() } state == ERROR { sub(/ $/, "") gsub(/\[[0-9;]*m/, "") if ($0 ~ /^\s*at /) { location = gensub(/^\s*at (.*):$/,"\\1","1") content = "" lnumcol = gensub(/^.*:([0-9]+:[0-9]+)$/,"\\1","1",location) lnum = gensub(/:.*/,"","1",lnumcol) col = gensub(/.*:/,"","1",lnumcol) next } if ($1 == lnum "|") { content = gensub(/^\s*[0-9]+\|(.*)/,"\\1","1") location = sprintf("%50s", location) preview_size = COLUMNS - length(location " ") prefix = gensub(/^\s*/,"","1",substr(content, 1, col)) infix = gensub(/^([0-9a-zA-Z]+|.).*$/, "\\1", "1", substr(content, col + 1)) suffix = substr(content, col + length(infix) + 1) if (length(prefix infix suffix) > preview_size) { n = (preview_size - length(infix)) / 2 - length(" ") prefix = substr(prefix, length(prefix) - n + 1) if (prefix != "") { prefix = "…" prefix } suffix = substr(suffix, 1, n) if (suffix != "") { suffix = suffix "…" } } preview = \ "\x1b[38;5;244m" prefix "\x1b[m" \ "\x1b[38;5;230m" infix "\x1b[m" \ "\x1b[38;5;244m" suffix "\x1b[m" trace[trace_count++] = location " " preview next } if ($0 == "") next if ($0 ~ /^\s*… (from|while)/) next if ($0 ~ /^\s*([0-9]*)\|/) next trace[trace_count++] = $0 next } ''