diff --git a/profile.d/conf.sh b/profile.d/conf.sh index f6c628f..5b77da7 100755 --- a/profile.d/conf.sh +++ b/profile.d/conf.sh @@ -156,13 +156,18 @@ export -f conf_save # # Usage: conf_dump [options] [pattern] # -s, --section NAME : Only display the given section +# -a, --all : Also show commented-out keys (default values, in white) # pattern : Only display keys whose name contains this substring +# +# Output colours: +# green — key is explicitly set (uncommented) in the config file +# white — key is present but commented out (shows the default value) conf_dump() { - local section="" key_pattern="" + local section="" key_pattern="" show_all=0 local PARSED - PARSED=$(getopt -o hs: --long help,section: -n 'conf_dump' -- "$@") + PARSED=$(getopt -o hs:a --long help,section:,all -n 'conf_dump' -- "$@") # shellcheck disable=SC2181 if [[ $? -ne 0 ]]; then disp E "Invalid options, use \"conf_dump --help\" to display usage." @@ -177,15 +182,23 @@ conf_dump() printf "Usage: conf_dump [options] [pattern]\n\n" printf "Options:\n" printf "\t-h, --help\t\tDisplay this help screen\n" - printf "\t-s, --section NAME\tOnly display the given section\n\n" + printf "\t-s, --section NAME\tOnly display the given section\n" + printf "\t-a, --all\t\tAlso show commented-out keys (default values)\n\n" printf "Arguments:\n" - printf "\tpattern\tOnly display keys whose name contains this substring\n" + printf "\tpattern\tOnly display keys whose name contains this substring\n\n" + printf "Output colours:\n" + printf "\t\033[1;32mgreen\033[0m — key is explicitly set (active)\n" + printf "\t\033[1;97mwhite\033[0m — key is commented out (default value)\n" return 0 ;; -s|--section) section="$2" shift 2 ;; + -a|--all) + show_all=1 + shift + ;; --) shift break @@ -209,51 +222,77 @@ conf_dump() # Colours are passed via ENVIRON to avoid awk -v escape interpretation. _CONF_DUMP_SEC="${Blue:-}" \ - _CONF_DUMP_KEY="${BIWhite:-}" \ + _CONF_DUMP_KEY_ACTIVE="${BGreen:-}" \ + _CONF_DUMP_KEY_DEFAULT="${BIWhite:-}" \ _CONF_DUMP_RST="${RESETCOL:-}" \ - awk -v sec_filter="$section" -v key_filter="$key_pattern" ' + awk -v sec_filter="$section" -v key_filter="$key_pattern" -v show_all="$show_all" ' BEGIN { - c_sec = ENVIRON["_CONF_DUMP_SEC"] - c_key = ENVIRON["_CONF_DUMP_KEY"] - c_rst = ENVIRON["_CONF_DUMP_RST"] + c_sec = ENVIRON["_CONF_DUMP_SEC"] + c_active = ENVIRON["_CONF_DUMP_KEY_ACTIVE"] + c_default = ENVIRON["_CONF_DUMP_KEY_DEFAULT"] + c_rst = ENVIRON["_CONF_DUMP_RST"] # Shell colour vars contain literal \e[…m strings; convert to # the actual ESC byte so awk print emits real ANSI sequences. gsub(/\\e/, "\033", c_sec) - gsub(/\\e/, "\033", c_key) + gsub(/\\e/, "\033", c_active) + gsub(/\\e/, "\033", c_default) gsub(/\\e/, "\033", c_rst) - in_target = 0 + in_target = 0 current_sec = "" hdr_printed = 0 found = 0 + # seen[sec:key] — tracks every key already printed to deduplicate + # commented entries and avoid re-showing an active key in white. } { sub(/\r$/, "") + # Section header if ($0 ~ /^\[[^]]+\][[:space:]]*$/) { current_sec = $0 - sub(/^\[/, "", current_sec) - sub(/\][[:space:]]*$/, "", current_sec) + sub(/^\[/, "", current_sec) + sub(/\][[:space:]]*$/, "", current_sec) in_target = (sec_filter == "" || current_sec == sec_filter) hdr_printed = 0 next } if (!in_target) next - if ($0 !~ /^[[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*=/) next - key = $0; sub(/[[:space:]]*=.*$/, "", key); sub(/^[[:space:]]*/, "", key) - val = $0; sub(/^[^=]*=/, "", val) - - if (key_filter != "" && index(key, key_filter) == 0) next - - if (!hdr_printed) { - if (found) print "" - print c_sec "[" current_sec "]" c_rst - hdr_printed = 1 - found = 1 + # Active (uncommented) key=value — always shown + if ($0 ~ /^[[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*=/) { + key = $0; sub(/[[:space:]]*=.*$/, "", key); sub(/^[[:space:]]*/, "", key) + val = $0; sub(/^[^=]*=/, "", val) + if (key_filter != "" && index(key, key_filter) == 0) next + if (!hdr_printed) { + if (found) print "" + print c_sec "[" current_sec "]" c_rst + hdr_printed = 1; found = 1 + } + seen[current_sec ":" key] = 1 + print " " c_active key c_rst "=" val + next + } + + # Commented-out key=value — shown only with show_all. + # The value displayed is the live environment value (what load_conf + # actually exported), not the commented-out text which may be an + # example or stale documentation. Each key is shown at most once. + if (show_all && $0 ~ /^[[:space:]]*#[[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*=/) { + line = $0; sub(/^[[:space:]]*#[[:space:]]*/, "", line) + key = line; sub(/[[:space:]]*=.*$/, "", key); sub(/^[[:space:]]*/, "", key) + if (seen[current_sec ":" key]) next + seen[current_sec ":" key] = 1 + if (key_filter != "" && index(key, key_filter) == 0) next + val = ENVIRON[key] + if (!hdr_printed) { + if (found) print "" + print c_sec "[" current_sec "]" c_rst + hdr_printed = 1; found = 1 + } + print " " c_default key c_rst "=" val } - print " " c_key key c_rst "=" val } ' "$conf_file" }