All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Robert Estelle via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Robert Estelle <robert.estelle@gmail.com>,
	Robert Estelle <robertestelle@gmail.com>
Subject: [PATCH] color: allow colors to be prefixed with "reset"
Date: Tue, 26 Oct 2021 01:03:47 +0000	[thread overview]
Message-ID: <pull.1117.git.git.1635210227532.gitgitgadget@gmail.com> (raw)

From: Robert Estelle <robertestelle@gmail.com>

"reset" was previously treated as a standalone special color name
representing `\e[m`. Now, it can apply to other color properties,
allowing exact specifications without implicit attribute inheritance.

For example, "reset green" now renders `\e[;32m`, which is interpreted
as "reset everything; then set foreground to green". This means the
background and other attributes are also reset to their defaults.

Previously, this was impossible to represent in a single color:
"reset" could be specified alone, or a color with attributes, but some
thing like clearing a background color were impossible.

There is a separate change that introduces the "default" color name to
assist with that, but even then, the above could only to be represented
by explicitly disabling each of the attributes:
  green default no-bold no-dim no-italic no-ul no-blink no-reverse no-strike

Signed-off-by: Robert Estelle <robertestelle@gmail.com>
---
    color: allow color specs to be prefixed by "reset"
    
    The pseudo-attribute "reset", which was previously treated as a
    standalone special color name, can now be combined with other color
    properties.
    
    This allows specification of an "entire" text style without implicitly
    inheriting existing properties (colors, bold/italic/etc) nor requiring a
    comprehensive clearing of each of them.
    
    For example, "reset green" now renders \e[;32m, which is interpreted as
    "default properties; then set foreground to green".
    
    Previously, it was not possible to represent this in a single color due
    to inability to clear the foreground or background (at best, they could
    be overridden to a some explicit value). There is a complementary
    proposed change (color: support "default" to restore fg/bg color,
    https://lore.kernel.org/git/pull.1116.git.git.1635201156.gitgitgadget@gmail.com/,
    https://github.com/git/git/pull/1116) which introduces the "default"
    color name to facilitate that, but even then, the above would still
    require disabling each of the attributes explicitly: green default
    no-bold no-dim no-italic no-ul no-blink no-reverse no-strike
    
    This is useful in scenarios that the "reset" word or any of the "no-"
    attribute modifiers might have been used before, e.g.
    colors.diff-highlight.newReset.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1117%2Frwe%2Freset-color-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1117/rwe/reset-color-v1
Pull-Request: https://github.com/git/git/pull/1117

 Documentation/config.txt |  5 +++++
 color.c                  | 18 +++++++++++-------
 color.h                  |  1 +
 t/t4026-color.sh         |  4 ++++
 4 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index bf82766a6a2..b1423b6ce8b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -280,6 +280,11 @@ The position of any attributes with respect to the colors
 be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`,
 `no-ul`, etc).
 +
+The pseudo-attribute `reset` resets all colors and attributes before
+applying the specified coloring. For example, `reset green` will result
+in a green foreground and default background without any active
+attributes.
++
 An empty color string produces no color effect at all. This can be used
 to avoid coloring specific elements without disabling color entirely.
 +
diff --git a/color.c b/color.c
index 64f52a4f93a..29ac83b2d6e 100644
--- a/color.c
+++ b/color.c
@@ -234,6 +234,7 @@ int color_parse_mem(const char *value, int value_len, char *dst)
 	const char *ptr = value;
 	int len = value_len;
 	char *end = dst + COLOR_MAXLEN;
+	unsigned int has_reset = 0;
 	unsigned int attr = 0;
 	struct color fg = { COLOR_UNSPECIFIED };
 	struct color bg = { COLOR_UNSPECIFIED };
@@ -248,12 +249,7 @@ int color_parse_mem(const char *value, int value_len, char *dst)
 		return 0;
 	}
 
-	if (!strncasecmp(ptr, "reset", len)) {
-		xsnprintf(dst, end - dst, GIT_COLOR_RESET);
-		return 0;
-	}
-
-	/* [fg [bg]] [attr]... */
+	/* [reset] [fg [bg]] [attr]... */
 	while (len > 0) {
 		const char *word = ptr;
 		struct color c = { COLOR_UNSPECIFIED };
@@ -270,6 +266,11 @@ int color_parse_mem(const char *value, int value_len, char *dst)
 			len--;
 		}
 
+		if (match_word(word, wordlen, "reset")) {
+			has_reset = 1;
+			continue;
+		}
+
 		if (!parse_color(&c, word, wordlen)) {
 			if (fg.type == COLOR_UNSPECIFIED) {
 				fg = c;
@@ -295,13 +296,16 @@ int color_parse_mem(const char *value, int value_len, char *dst)
 	*dst++ = (x); \
 } while(0)
 
-	if (attr || !color_empty(&fg) || !color_empty(&bg)) {
+	if (has_reset || attr || !color_empty(&fg) || !color_empty(&bg)) {
 		int sep = 0;
 		int i;
 
 		OUT('\033');
 		OUT('[');
 
+		if (has_reset)
+			sep++;
+
 		for (i = 0; attr; i++) {
 			unsigned bit = (1 << i);
 			if (!(attr & bit))
diff --git a/color.h b/color.h
index 98894d6a175..684dbd3bceb 100644
--- a/color.h
+++ b/color.h
@@ -6,6 +6,7 @@ struct strbuf;
 /*
  * The maximum length of ANSI color sequence we would generate:
  * - leading ESC '['            2
+ * - reset ';' .................1
  * - attr + ';'                 2 * num_attr (e.g. "1;")
  * - no-attr + ';'              3 * num_attr (e.g. "22;")
  * - fg color + ';'             17 (e.g. "38;2;255;255;255;")
diff --git a/t/t4026-color.sh b/t/t4026-color.sh
index c0b642c1ab0..5ef2ff28c48 100755
--- a/t/t4026-color.sh
+++ b/t/t4026-color.sh
@@ -58,6 +58,10 @@ test_expect_success 'fg bg attr...' '
 	color "blue bold dim ul blink reverse" "[1;2;4;5;7;34m"
 '
 
+test_expect_success 'reset fg bg attr...' '
+	color "reset blue bold dim ul blink reverse" "[;1;2;4;5;7;34m"
+'
+
 # note that nobold and nodim are the same code (22)
 test_expect_success 'attr negation' '
 	color "nobold nodim noul noblink noreverse" "[22;24;25;27m"

base-commit: 225bc32a989d7a22fa6addafd4ce7dcd04675dbf
-- 
gitgitgadget

             reply	other threads:[~2021-10-26  1:03 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-26  1:03 Robert Estelle via GitGitGadget [this message]
2021-10-26 21:42 ` [PATCH] color: allow colors to be prefixed with "reset" Junio C Hamano
2021-10-27  4:28   ` Robert Estelle

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=pull.1117.git.git.1635210227532.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=robert.estelle@gmail.com \
    --cc=robertestelle@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.