From 0a85d265cbeca682703bdb12e4ad5544e4a854d0 Mon Sep 17 00:00:00 2001 From: fatalerrors Date: Thu, 28 May 2026 12:04:30 +0200 Subject: [PATCH] made configuration saving generic --- profile.d/conf.sh | 152 ++++++++++++++++++++++++++++++++++++++++++++ profile.d/help.sh | 1 + profile.d/prompt.sh | 104 +----------------------------- 3 files changed, 155 insertions(+), 102 deletions(-) create mode 100755 profile.d/conf.sh diff --git a/profile.d/conf.sh b/profile.d/conf.sh new file mode 100755 index 0000000..4188924 --- /dev/null +++ b/profile.d/conf.sh @@ -0,0 +1,152 @@ +#!/usr/bin/env bash +# ------------------------------------------------------------------------------ +# Copyright (c) 2013-2026 Geoffray Levasseur +# Protected by the BSD3 license. Please read bellow for details. +# +# * Redistribution and use in source and binary forms, +# * with or without modification, are permitted provided +# * that the following conditions are met: +# * +# * Redistributions of source code must retain the above +# * copyright notice, this list of conditions and the +# * following disclaimer. +# * +# * Redistributions in binary form must reproduce the above +# * copyright notice, this list of conditions and the following +# * disclaimer in the documentation and/or other materials +# * provided with the distribution. +# * +# * Neither the name of the copyright holder nor the names +# * of any other contributors may be used to endorse or +# * promote products derived from this software without +# * specific prior written permission. +# * +# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# * OF SUCH DAMAGE. +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +# Save or update a key=value pair in a section of the profile configuration file. +# The user configuration ($HOME/.profile.conf) is updated when it exists, +# otherwise the installation configuration ($PROFILE_CONF or $MYPATH/profile.conf) +# is used. The section header is created automatically when absent. +# +# Usage: conf_save
+# section : INI section name without brackets, e.g. "prompt" for [prompt] +# key : variable name to set (alphanumeric and underscore only) +# value : value to assign (may be empty) +conf_save() +{ + if [[ $# -ne 3 ]]; then + disp E "Usage: conf_save
" + return 1 + fi + + local section="$1" key="$2" value="$3" + + if ! [[ "$section" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then + disp E "conf_save: invalid section name '${section}' (alphanumeric and underscore only)." + return 1 + fi + if ! [[ "$key" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then + disp E "conf_save: invalid key name '${key}' (alphanumeric and underscore only)." + return 1 + fi + + local conf_file + if [[ -f "$HOME/.profile.conf" ]]; then + conf_file="$HOME/.profile.conf" + else + conf_file="${PROFILE_CONF:-${MYPATH}/profile.conf}" + fi + + local conf_dir="${conf_file%/*}" + [[ -d "$conf_dir" ]] || mkdir -p "$conf_dir" || { + disp E "conf_save: unable to create configuration directory: ${conf_dir}" + return 1 + } + + if [[ ! -e "$conf_file" ]]; then + { + printf "[%s]\n" "$section" + printf "%s=%s\n" "$key" "$value" + } > "$conf_file" || { + disp E "conf_save: unable to write configuration file: ${conf_file}" + return 1 + } + return 0 + fi + + local tmp_file="${conf_file}.tmp.$$" + awk -v sec="$section" -v key="$key" -v val="$value" ' + BEGIN { + in_sec = 0 + saw_sec = 0 + wrote = 0 + } + + { + if ($0 ~ /^\[[^]]+\][[:space:]]*$/) { + if (in_sec && !wrote) { + print key "=" val + wrote = 1 + } + + if ($0 ~ ("^\\[" sec "\\][[:space:]]*$")) { + in_sec = 1 + saw_sec = 1 + } else { + in_sec = 0 + } + + print + next + } + + if (in_sec && $0 ~ ("^[[:space:]]*" key "[[:space:]]*=")) { + if (!wrote) { + print key "=" val + wrote = 1 + } + next + } + + print + } + + END { + if (in_sec && !wrote) { + print key "=" val + } + if (!saw_sec) { + print "" + print "[" sec "]" + print key "=" val + } + } + ' "$conf_file" > "$tmp_file" || { + rm -f "$tmp_file" + disp E "conf_save: unable to update configuration file: ${conf_file}" + return 1 + } + + mv "$tmp_file" "$conf_file" || { + rm -f "$tmp_file" + disp E "conf_save: unable to replace configuration file: ${conf_file}" + return 1 + } +} +export -f conf_save +# ------------------------------------------------------------------------------ + + +# EOF diff --git a/profile.d/help.sh b/profile.d/help.sh index d0457a2..af7f605 100644 --- a/profile.d/help.sh +++ b/profile.d/help.sh @@ -57,6 +57,7 @@ help() printf "busy\t\tMonitor /dev/urandom for a hex pattern — look busy\n" printf "check_updates\tCheck for new versions of profile\n" printf "clean\t\tErase backup files in given directories, optionally recursive\n" + printf "conf_save\tSave or update a key=value pair in a profile configuration section\n" printf "disp\t\tDisplay formatted info/warning/error/debug messages\n" printf "dwl\t\tDownload a URL using curl, wget, or fetch transparently\n" printf "expandlist\tExpand glob expressions into a quoted, separated list\n" diff --git a/profile.d/prompt.sh b/profile.d/prompt.sh index 17ab096..2ec7b7a 100644 --- a/profile.d/prompt.sh +++ b/profile.d/prompt.sh @@ -169,106 +169,6 @@ load_theme() # ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# Persist PROMPT_THEME in profile configuration ([prompt] section). -# Preference order: ~/.profile.conf when present, else PROFILE_CONF. -_set_theme_save_prompt_theme() -{ - local theme_name="$1" - [[ -z "$theme_name" ]] && { - disp E "Cannot save an empty theme name." - return 1 - } - - local conf_file - if [[ -f "$HOME/.profile.conf" ]]; then - conf_file="$HOME/.profile.conf" - else - conf_file="${PROFILE_CONF:-${MYPATH}/profile.conf}" - fi - - local conf_dir - conf_dir="${conf_file%/*}" - [[ -d "$conf_dir" ]] || mkdir -p "$conf_dir" || { - disp E "Unable to create configuration directory: $conf_dir" - return 1 - } - - local tmp_file="${conf_file}.tmp.$$" - if [[ ! -e "$conf_file" ]]; then - { - printf "[prompt]\n" - printf "PROMPT_THEME=%s\n" "$theme_name" - } > "$conf_file" || { - disp E "Unable to write configuration file: $conf_file" - return 1 - } - return 0 - fi - - awk -v theme="$theme_name" ' - BEGIN { - in_prompt = 0 - saw_prompt = 0 - wrote_key = 0 - } - - { - if ($0 ~ /^\[[^]]+\][[:space:]]*$/) { - if (in_prompt && !wrote_key) { - print "PROMPT_THEME=" theme - wrote_key = 1 - } - - if ($0 == "[prompt]") { - in_prompt = 1 - saw_prompt = 1 - } else { - in_prompt = 0 - } - - print - next - } - - if (in_prompt && $0 ~ /^[[:space:]]*PROMPT_THEME[[:space:]]*=/) { - if (!wrote_key) { - print "PROMPT_THEME=" theme - wrote_key = 1 - } - next - } - - print - } - - END { - if (in_prompt && !wrote_key) { - print "PROMPT_THEME=" theme - wrote_key = 1 - } - - if (!saw_prompt) { - print "" - print "[prompt]" - print "PROMPT_THEME=" theme - } - } - ' "$conf_file" > "$tmp_file" || { - rm -f "$tmp_file" - disp E "Unable to update configuration file: $conf_file" - return 1 - } - - mv "$tmp_file" "$conf_file" || { - rm -f "$tmp_file" - disp E "Unable to replace configuration file: $conf_file" - return 1 - } -} -# Not exported, it remains private -# ------------------------------------------------------------------------------ - # ------------------------------------------------------------------------------ # Dynamically switch the prompt theme for the current shell session. @@ -352,7 +252,7 @@ set_theme() if (( list_only )) || [[ -z "$theme_name" && $preview -eq 0 ]]; then if (( save )); then if [[ -n "${PROMPT_THEME:-}" ]]; then - _set_theme_save_prompt_theme "$PROMPT_THEME" || return 1 + conf_save "prompt" "PROMPT_THEME" "$PROMPT_THEME" || return 1 disp I "Saved current prompt theme '$PROMPT_THEME' to configuration." return 0 fi @@ -441,7 +341,7 @@ set_theme() export PROMPT_THEME="$theme_name" if (( save )); then - _set_theme_save_prompt_theme "$theme_name" || return 1 + conf_save "prompt" "PROMPT_THEME" "$theme_name" || return 1 disp I "Prompt theme set to $theme_name and saved to configuration." return 0 fi