diff --git a/lib/functions/compilation/kernel-make.sh b/lib/functions/compilation/kernel-make.sh index ffa8b23f2..5080a974f 100644 --- a/lib/functions/compilation/kernel-make.sh +++ b/lib/functions/compilation/kernel-make.sh @@ -24,6 +24,8 @@ function run_kernel_make_internal() { "DPKG_COLORS=always" # Use colors for dpkg @TODO no dpkg is done anymore, remove? "XZ_OPT='--threads=0'" # Use parallel XZ compression "TERM='${TERM}'" # Pass the terminal type, so that 'make menuconfig' can work. + "COLUMNS='${COLUMNS:-160}'" + "COLORFGBG='${COLORFGBG}'" ) # If CCACHE_DIR is set, pass it to the kernel build; Pass the ccache dir explicitly, since we'll run under "env -i" diff --git a/lib/functions/compilation/kernel-patching.sh b/lib/functions/compilation/kernel-patching.sh index a78903c74..9d1e1086c 100644 --- a/lib/functions/compilation/kernel-patching.sh +++ b/lib/functions/compilation/kernel-patching.sh @@ -32,6 +32,7 @@ function kernel_main_patching_python() { #"TARGET=" # TARGET is need for u-boot's SPI/SATA etc selection logic. empty for kernel # For table generation to fit into the screen, or being large when in GHA. "COLUMNS=${COLUMNS}" + "COLORFGBG=${COLORFGBG}" "GITHUB_ACTIONS=${GITHUB_ACTIONS}" # Needed so git can find the global .gitconfig, and Python can parse the PATH to determine which git to use. "PATH=${PATH}" diff --git a/lib/functions/compilation/uboot-patching.sh b/lib/functions/compilation/uboot-patching.sh index 8325098e5..d039510c2 100644 --- a/lib/functions/compilation/uboot-patching.sh +++ b/lib/functions/compilation/uboot-patching.sh @@ -27,6 +27,7 @@ function uboot_main_patching_python() { "USERPATCHES_PATH=${USERPATCHES_PATH}" # Needed to find the userpatches. # For table generation to fit into the screen, or being large when in GHA. "COLUMNS=${COLUMNS}" + "COLORFGBG=${COLORFGBG}" "GITHUB_ACTIONS=${GITHUB_ACTIONS}" # Needed so git can find the global .gitconfig, and Python can parse the PATH to determine which git to use. "PATH=${PATH}" diff --git a/lib/functions/configuration/aggregation.sh b/lib/functions/configuration/aggregation.sh index 8e93c357b..dbf148c83 100644 --- a/lib/functions/configuration/aggregation.sh +++ b/lib/functions/configuration/aggregation.sh @@ -57,6 +57,11 @@ function aggregate_all_packages_python() { "OUTPUT=${temp_file_for_aggregation}" "ASSET_LOG_BASE=$(print_current_asset_log_base_file)" # base file name for the asset log; to write .md summaries. + # Terminal variables + "TERM=${TERM}" + "COLORFGBG=${COLORFGBG}" + "COLUMNS=${COLUMNS:-160}" + # For the main packages, and others; main packages are not mixed with BOARD or DESKTOP packages. # Results: # - AGGREGATED_DEBOOTSTRAP_COMPONENTS diff --git a/lib/functions/general/bat-cat.sh b/lib/functions/general/bat-cat.sh index df713d055..47debea97 100644 --- a/lib/functions/general/bat-cat.sh +++ b/lib/functions/general/bat-cat.sh @@ -96,8 +96,12 @@ function run_tool_batcat() { if [[ "${bat_cat_columns}" -lt 60 ]]; then # but lever less than 60 bat_cat_columns=60 fi + case "${background_dark_or_light}" in + dark) declare bat_cat_theme="Dracula" ;; + *) declare bat_cat_theme="ansi" ;; + esac display_alert "Calling batcat" "COLUMNS: ${bat_cat_columns} | $*" "debug" - BAT_CONFIG_DIR="${DIR_BATCAT}/config" BAT_CACHE_PATH="${DIR_BATCAT}/cache" "${BATCAT_BIN}" --theme "Dracula" --paging=never --force-colorization --wrap auto --terminal-width "${bat_cat_columns}" "$@" + BAT_CONFIG_DIR="${DIR_BATCAT}/config" BAT_CACHE_PATH="${DIR_BATCAT}/cache" "${BATCAT_BIN}" --theme "${bat_cat_theme}" --paging=never --force-colorization --wrap auto --terminal-width "${bat_cat_columns}" "$@" wait_for_disk_sync "after running batcat" } diff --git a/lib/functions/host/docker.sh b/lib/functions/host/docker.sh index 24d17d2e4..b521ef465 100644 --- a/lib/functions/host/docker.sh +++ b/lib/functions/host/docker.sh @@ -377,8 +377,9 @@ function docker_cli_prepare_launch() { # Change the ccache directory to the named volume or bind created. @TODO: this needs more love. it works for Docker, but not sudo "--env" "CCACHE_DIR=${DOCKER_ARMBIAN_TARGET_PATH}/cache/ccache" - # Pass down the TERM and the COLUMNS + # Pass down the TERM, COLORFGBG, and the COLUMNS "--env" "TERM=${TERM}" + "--env" "COLORFGBG=${COLORFGBG-}" "--env" "COLUMNS=${COLUMNS:-"160"}" # Pass down the CI env var (GitHub Actions, Jenkins, etc) diff --git a/lib/functions/logging/display-alert.sh b/lib/functions/logging/display-alert.sh index 120b12cba..d5ce75869 100644 --- a/lib/functions/logging/display-alert.sh +++ b/lib/functions/logging/display-alert.sh @@ -30,7 +30,10 @@ function display_alert() { skip_screen=1 fi level_indicator="🐛" - inline_logs_color="\e[1;33m" + case "${background_dark_or_light}" in + light) inline_logs_color="\e[1;2;33m" ;; + *) inline_logs_color="\e[1;33m" ;; + esac skip_logfile=1 ;; @@ -44,7 +47,10 @@ function display_alert() { info) level_indicator="🌱" - inline_logs_color="\e[0;32m" + case "${background_dark_or_light}" in + light) inline_logs_color="\e[1;2;32m" ;; + *) inline_logs_color="\e[1;32m" ;; + esac ;; cleanup | trap) @@ -52,7 +58,10 @@ function display_alert() { skip_screen=1 fi level_indicator="🧽" - inline_logs_color="\e[1;33m" + case "${background_dark_or_light}" in + light) inline_logs_color="\e[1;2;33m" ;; + *) inline_logs_color="\e[1;33m" ;; + esac skip_logfile=1 ;; @@ -141,7 +150,10 @@ function display_alert() { ext) level_indicator="✨" - inline_logs_color="\e[1;32m" + case "${background_dark_or_light}" in + light) inline_logs_color="\e[1;2;32m" ;; + *) inline_logs_color="\e[1;32m" ;; + esac ;; change-tracking) @@ -152,7 +164,10 @@ function display_alert() { *) level="${level:-info}" # for file logging. level_indicator="🌿" - inline_logs_color="\e[1;37m" + case "${background_dark_or_light}" in + dark) inline_logs_color="\e[1;37m" ;; + *) inline_logs_color="\e[1;39m" ;; + esac ;; esac diff --git a/lib/functions/logging/logging.sh b/lib/functions/logging/logging.sh index 9e738b526..8f2cb7c67 100644 --- a/lib/functions/logging/logging.sh +++ b/lib/functions/logging/logging.sh @@ -19,13 +19,37 @@ function logging_init() { declare -g SHOW_DEBUG="${SHOW_DEBUG:-"yes"}" fi + # detect terminal background color + case "${COLORFGBG+${COLORFGBG#*;}}" in + [0-6]|8) + declare -g background_dark_or_light=dark + ;; + 7|9|1[0-5]) + declare -g background_dark_or_light=light + ;; + *) + declare -g background_dark_or_light= + ;; + esac + # globals declare -g padding="" left_marker="[" right_marker="]" declare -g normal_color="\x1B[0m" gray_color="\e[1;30m" # "bright black", which is grey declare -g bright_red_color="\e[1;31m" red_color="\e[0;31m" declare -g bright_blue_color="\e[1;34m" blue_color="\e[0;34m" declare -g bright_magenta_color="\e[1;35m" magenta_color="\e[0;35m" - declare -g bright_yellow_color="\e[1;33m" yellow_color="\e[0;33m" + case "${background_dark_or_light}" in + light) + # bold dim yellow, to ensure readability + declare -g bright_yellow_color="\e[1;2;33m" + declare -g yellow_color="\e[0;33m" + ;; + *) + declare -g bright_yellow_color="\e[1;33m" + declare -g yellow_color="\e[0;33m" + ;; + esac + declare -g ansi_reset_color="\e[0m" declare -g -i logging_section_counter=0 # -i: integer declare -g tool_color="${normal_color}" # default to normal color. diff --git a/lib/tools/common/armbian_utils.py b/lib/tools/common/armbian_utils.py index fe37b3a01..b639f75a0 100755 --- a/lib/tools/common/armbian_utils.py +++ b/lib/tools/common/armbian_utils.py @@ -20,6 +20,8 @@ from pathlib import Path import sys +from common.term_colors import background_dark_or_light + REGEX_WHITESPACE_LINEBREAK_COMMA_SEMICOLON = r"[\s,;\n]+" ARMBIAN_BOARD_CONFIG_REGEX_GENERIC = r"^(?!\s)(?:[export |declare \-g]?)+([A-Z0-9_]+)=(?:'|\")(.*)(?:'|\")" @@ -80,14 +82,24 @@ def setup_logging(): if is_debug(): level = "DEBUG" format = "%(message)s" - styles = { - 'trace': {'color': 'white', 'bold': False}, - 'debug': {'color': 'white', 'bold': False}, - 'info': {'color': 'green', 'bold': True}, - 'warning': {'color': 'yellow', 'bold': True}, - 'error': {'color': 'red'}, - 'critical': {'bold': True, 'color': 'red'} - } + if background_dark_or_light() == 'light': + styles = { + 'trace': {'color': 'black', 'bright': True}, + 'debug': {'color': 'black', 'bright': True}, + 'info': {'color': 'green', 'bold': True, 'faint': True}, + 'warning': {'color': 'yellow', 'bold': True, 'faint': True}, + 'error': {'color': 'red'}, + 'critical': {'bold': True, 'color': 'red'} + } + else: + styles = { + 'trace': {'color': 'white', 'bold': False}, + 'debug': {'color': 'white', 'bold': False}, + 'info': {'color': 'green', 'bold': True}, + 'warning': {'color': 'yellow', 'bold': True}, + 'error': {'color': 'red'}, + 'critical': {'bold': True, 'color': 'red'} + } coloredlogs.install(level=level, stream=sys.stderr, isatty=True, fmt=format, level_styles=styles) except ImportError: level = logging.INFO diff --git a/lib/tools/common/patching_utils.py b/lib/tools/common/patching_utils.py index 0ee4b2aab..69daea7c4 100755 --- a/lib/tools/common/patching_utils.py +++ b/lib/tools/common/patching_utils.py @@ -20,6 +20,7 @@ from unidecode import unidecode from unidiff import PatchSet from common.patching_config import PatchingConfig +from common.term_colors import background_dark_or_light MAGIC_MBOX_MARKER_STANDARD = "Mon Sep 17 00:00:00 2001" MAGIC_MBOX_MARKER_B4 = "git@z Thu Jan 1 00:00:00 1970" @@ -703,11 +704,12 @@ class PatchInPatchFile: color = "yellow" else: color = "red" + bold = 'bold dim' if background_dark_or_light() == 'light' else 'bold' # @TODO: once our ansi-haste supports it, use [link url=file://blaaa] if self.parent.multiple_patches_in_file: - return f"[bold][{color}]{self.markdown_name(skip_markdown=True)}[/bold](:{self.counter})" + return f"[{bold}][{color}]{self.markdown_name(skip_markdown=True)}[/{bold}](:{self.counter})" else: - return f"[bold {color}]{self.markdown_name(skip_markdown=True)}" + return f"[{bold} {color}]{self.markdown_name(skip_markdown=True)}" def rich_patch_output(self): ret = self.patch_output @@ -716,10 +718,11 @@ class PatchInPatchFile: 'yellow': ['with fuzz', 'offset ', ' hunks ignored', ' hunk ignored'], 'red': ['hunk FAILED', 'hunks FAILED'] } + bold = 'bold dim' if background_dark_or_light() == 'light' else 'bold' # use Rich's syntax highlighting to highlight with color for color in color_tags: for tag in color_tags[color]: - ret = ret.replace(tag, f"[bold {color}]{tag}[/bold {color}]") + ret = ret.replace(tag, f"[{bold} {color}]{tag}[/{bold} {color}]") return ret def apply_patch_date_to_files(self, working_dir, options): diff --git a/lib/tools/common/term_colors.py b/lib/tools/common/term_colors.py new file mode 100644 index 000000000..6d2281bce --- /dev/null +++ b/lib/tools/common/term_colors.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2024 Darsey Litzenberger, dlitz@dlitz.net +# +# This file is a part of the Armbian Build Framework +# https://github.com/armbian/build/ +# + +import os + + +def background_dark_or_light(): + """ + Returns: + 'dark' if the terminal background is dark, + 'light' if the terminal background is light, or + '' if the terminal background color is unknown. + """ + colorfgbg = os.environ.get("COLORFGBG", "") + try: + _, bg = colorfgbg.split(';') + bg = int(bg) + except ValueError: + return "" + if 0 <= bg <= 6 or bg == 8: + return "dark" + elif bg == 7 or 9 <= bg <= 15: + return "light" + return ""