commit:     eb36c3077fd69b7cbc5ef64c68d42baff50b3d43
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Wed Feb 15 07:02:48 2023 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Wed Feb 15 07:32:45 2023 +0000
URL:        
https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=eb36c307

Implement proper TTY detection, once and for all

Following a litany of ill-considered bodges and hacks over the years, it
is high time that the matter of tty detection was conclusively dealt
with. This commit aims to accomplish exactly that, in a fashion that can
be described twofold.

Firstly, the recently introduced _eprint() function will now test
whether STDOUT is a tty at the time of invocation. If found to be a tty,
ECMA-48 SGR sequences shall be incorporated into the message. Otherwise,
they shall not be. This positively affects the following functions.

  - ebegin
  - einfo
  - einfon
  - eerror
  - eerrorn
  - ewarnn
  - ewarn
  - vebegin
  - veinfo
  - veinfon
  - veerror
  - veerrorn
  - vewarnn
  - vewarn

Note that the *eerror* and *ewarn* functions duplicate file descriptor 2
(STDERR) to file descriptor 1 (STDOUT), meaning that the -t 1 test will
always be in the context of the appropriate file descriptor.

Secondly, the _eend() function will now test whether STDOUT is a tty at
the time of invocation. Just as with _eprint(), ECMA-48 SGR sequences
will be omitted in the case that STDOUT is found not to be a tty
However, the fact that _eend() prints a so-called end column must also
be taken into account. The end column string is not defined by this
function, but may or may not incorporate ECMA-48 CSI sequences that are
intended to move the cursor up - and to the end of - the previous line.
Previously, _eend() would always use the end column if was found to be
non-empty, despite containing such sequences. Now, it will refrain from
printing the end column where STDOUT is not a tty. Instead, it will fall
back to the method of printing the success/failure indicator on the
current line. Furthemore, if the fallback method is used under these
exact circumstances, the number of available columns will be assumed as
being 80 for the scope of the function call. After all, the width of the
controlling terminal is wholly immaterial unless printing to it. This
positively affects the following functions.

  - eend
  - ewend
  - veend
  - vewend

Consequently, all eighteen of the aformentioned functions will act
properly, in accordance with the state of both STDOUT and STDERR, at the
time that they are called. As such, the truly repulsive hack that was to
permanently disable colour if _either_ were found not to be a tty at the
time of sourcing functions.sh has been jettisoned. Good riddance.

Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Bug: https://bugs.gentoo.org/631870
Signed-off-by: Sam James <sam <AT> gentoo.org>

 functions.sh | 47 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/functions.sh b/functions.sh
index 151775f..a0422b6 100644
--- a/functions.sh
+++ b/functions.sh
@@ -16,7 +16,11 @@ _eprint() {
        if [ -z "${genfun_endcol}" ] && [ "${genfun_lastcall}" = "ebegin" ]; 
then
                printf '\n'
        fi
-       printf ' %s*%s %s%b' "${color}" "${NORMAL}" "${genfun_indent}" "$*"
+       if [ -t 1 ]; then
+               printf ' %s*%s %s%b' "${color}" "${NORMAL}" "${genfun_indent}" 
"$*"
+       else
+               printf ' * %s%b' "${genfun_indent}" "$*"
+       fi
 }
 
 #
@@ -202,7 +206,7 @@ ebegin()
 #
 _eend()
 {
-       local efunc msg retval
+       local cols efunc is_tty msg retval
 
        efunc=$1
        shift
@@ -217,22 +221,44 @@ _eend()
                shift
        fi
 
+       if [ -t 1 ]; then
+               is_tty=1
+               cols=${genfun_cols}
+       else
+               # STDOUT is not currently a TTY. Therefore, the width of the
+               # controlling terminal, if any, is irrelevant. For this call,
+               # consider the number of columns as being 80.
+               is_tty=0
+               cols=80
+       fi
+
        if [ "${retval}" -ne 0 ]; then
+               # If a message was given, print it with the specified function.
                if _is_visible "$*"; then
                        "${efunc}" "$*"
                fi
-               msg="${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}"
+               # Generate an indicator for ebegin's unsuccessful conclusion.
+               if [ "${is_tty}" -eq 0 ]; then
+                       msg="[ !! ]"
+               else
+                       msg="${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}"
+               fi
        elif yesno "${EINFO_QUIET}"; then
                return "${retval}"
        else
-               msg="${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}"
+               # Generate an indicator for ebegin's successful conclusion.
+               if [ "${is_tty}" -eq 0 ]; then
+                       msg="[ ok ]"
+               else
+                       msg="${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}"
+               fi
        fi
 
-       if [ -n "${genfun_endcol}" ]; then
+       if [ "${is_tty}" -eq 1 ] && [ -n "${genfun_endcol}" ]; then
                printf '%s  %s\n' "${genfun_endcol}" "${msg}"
        else
                [ "${genfun_lastcall}" = ebegin ] || genfun_lastbegun_strlen=0
-               printf "%$(( genfun_cols - genfun_lastbegun_strlen - 6 ))s%s\n" 
'' "${msg}"
+               printf "%$(( cols - genfun_lastbegun_strlen - 6 ))s%s\n" '' 
"${msg}"
        fi
 
        return "${retval}"
@@ -452,15 +478,6 @@ unset -v genfun_endcol
 # Set the initial value for e-message indentation.
 genfun_indent=
 
-# If either STDOUT or STDERR is not a tty, disable coloured output. A useful
-# improvement for  the future would be to have the individual logging functions
-# act as they should. For example, ewarn prints to STDOUT whereas eerror prints
-# to STDERR. For now, this is a reasonable compromise.
-if [ ! -t 1 ] || [ ! -t 2 ]; then
-       RC_NOCOLOR="yes"
-       genfun_endcol=
-fi
-
 for arg in "$@" ; do
        case "${arg}" in
                # Lastly check if the user disabled it with --nocolor argument

Reply via email to