From 58ee0fabc9028fcdf86faab3bb9c1db2b27e3644 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 19 Apr 2024 15:57:23 +0200 Subject: Add APT::Configuration::color helper to colorize things --- apt-pkg/aptconfiguration.cc | 35 +++++++++++++++++++++++++++++++++++ apt-pkg/aptconfiguration.h | 2 ++ test/libapt/configuration_test.cc | 30 ++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 982e68bb1..f462b6eda 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -563,4 +563,39 @@ bool Configuration::checkUsrMerged() return true; } /*}}}*/ +// isUsrMerged - whether usr is merged t /*{{{*/ +// --------------------------------------------------------------------- +/* */ +std::string Configuration::color(std::string const &colorName, std::string const &content) +{ + if (not _config->FindB("APT::Color")) + return content; + + auto colors = ::Configuration(_config->Tree("APT::Color")); + auto color = colors.Find(colorName); + + // Resolve the color recursively. A color string has the following format + // := \x1B ; fully resolved color + // | \\x1B ; color escaped. + // | ; a simple color name + // | ; a sequence of colors + if (color.find(" ") != color.npos) + { + std::string res; + for (auto &&colorPart : VectorizeString(color, ' ')) + res += Configuration::color(colorPart); + color = res; + } + else if (not color.empty() && color[0] != '\x1B') + { + if (APT::String::Startswith(color, "\\x1B")) + color = "\x1B" + color.substr(4); + else + color = Configuration::color(color); + } + if (content.empty()) + return color; + return color + content + Configuration::color("Neutral"); +} + /*}}}*/ } diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index 3e2636edc..58c925b7f 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -130,7 +130,9 @@ namespace Configuration { /*{{{*/ APT_PUBLIC bool isChroot(); /** \return Check usr is merged or produce error. */ APT_PUBLIC bool checkUsrMerged(); + APT_PUBLIC std::string color(std::string const &colorName, std::string const &content = ""); #endif + /*}}}*/ } /*}}}*/ diff --git a/test/libapt/configuration_test.cc b/test/libapt/configuration_test.cc index 4d297a9f2..61c7348a2 100644 --- a/test/libapt/configuration_test.cc +++ b/test/libapt/configuration_test.cc @@ -230,3 +230,33 @@ List::Option2 { "Multi"; EXPECT_TRUE(Cnf.FindB("Trailing")); EXPECT_FALSE(Cnf.Exists("Commented::Out")); } + +TEST(ConfigurationTest, Color) +{ + _config->Clear(); + _config->Set("APT::Color::Neutral", "\x1B[N"); + _config->Set("APT::Color::Green", "\x1B[G"); + // This is escaped for extra fun + _config->Set("APT::Color::Bold", "\\x1B[B"); + _config->Set("APT::Color::BoldGreen", "bold green"); + _config->Set("APT::Color::BoldGreenRef", "boldgreen"); + _config->Set("APT::Color::BoldGreenNeutral", "boldgreen neutral"); + _config->Set("APT::Color::BoldGreenRefNeutral", "boldgreenref neutral"); + + EXPECT_EQ("", APT::Configuration::color("bold")); + EXPECT_EQ("", APT::Configuration::color("green")); + EXPECT_EQ("content", APT::Configuration::color("green", "content")); + EXPECT_EQ("", APT::Configuration::color("boldgreen")); + EXPECT_EQ("", APT::Configuration::color("boldgreenref")); + EXPECT_EQ("", APT::Configuration::color("boldgreenneutral")); + EXPECT_EQ("", APT::Configuration::color("boldgreenrefneutral")); + + _config->Set("APT::Color", "true"); + EXPECT_EQ("\x1B[B", APT::Configuration::color("bold")); + EXPECT_EQ("\x1B[G", APT::Configuration::color("green")); + EXPECT_EQ("\x1B[Gcontent\x1B[N", APT::Configuration::color("green", "content")); + EXPECT_EQ("\x1B[B\x1B[G", APT::Configuration::color("boldgreen")); + EXPECT_EQ("\x1B[B\x1B[G", APT::Configuration::color("boldgreenref")); + EXPECT_EQ("\x1B[B\x1B[G\x1B[N", APT::Configuration::color("boldgreenneutral")); + EXPECT_EQ("\x1B[B\x1B[G\x1B[N", APT::Configuration::color("boldgreenrefneutral")); +} -- cgit v1.2.3-70-g09d2 From e07450beb5a474ec3c099ff3eb329892b040d04c Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 19 Apr 2024 16:05:08 +0200 Subject: Use APT::Configuration::color to apply color to output --- apt-private/acqprogress.cc | 5 +++-- apt-private/private-install.cc | 2 +- apt-private/private-output.cc | 18 ++++++++++-------- apt-private/private-output.h | 8 ++++---- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc index 1f5acdd97..b4b16e6a9 100644 --- a/apt-private/acqprogress.cc +++ b/apt-private/acqprogress.cc @@ -9,6 +9,7 @@ // Include files /*{{{*/ #include +#include #include #include #include @@ -281,14 +282,14 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner) // Draw the current status if (_config->FindB("Apt::Color", false) == true) - out << _config->Find("APT::Color::Yellow"); + out << APT::Configuration::color("Yellow"); if (LastLineLength > Line.length()) clearLastLine(); else out << '\r'; out << Line << std::flush; if (_config->FindB("Apt::Color", false) == true) - out << _config->Find("APT::Color::Neutral") << std::flush; + out << APT::Configuration::color("Neutral") << std::flush; LastLineLength = Line.length(); Update = false; diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index ecbd703d8..87793d973 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -1104,7 +1104,7 @@ bool DoInstall(CommandLine &CmdL) if (_config->FindI("APT::Output-Version") < 30 && Cache->InstCount() != verset[MOD_INSTALL].size()) ShowList(c1out, _("The following additional packages will be installed:"), Universe, PkgIsExtraInstalled(&Cache, &verset[MOD_INSTALL]), - &PrettyFullName, CandidateVersion(&Cache), "APT::Color::Green"); + &PrettyFullName, CandidateVersion(&Cache), "green"); /* Print out a list of suggested and recommended packages */ if (_config->FindI("APT::Output-Version") < 30) diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 522fba4c6..380558964 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -1,6 +1,7 @@ // Include files /*{{{*/ #include +#include #include #include #include @@ -30,6 +31,7 @@ /*}}}*/ using namespace std; +using APT::Configuration::color; std::ostream c0out(0); std::ostream c1out(0); @@ -302,8 +304,8 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles) StatusStr = _("[residual-config]"); output = SubstVar(output, "${apt:Status}", StatusStr); - output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", "")); - output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", "")); + output = SubstVar(output, "${color:highlight}", color("Highlight")); + output = SubstVar(output, "${color:neutral}", color("Neutral")); output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P)); if (output.find("${LongDescription}") != string::npos) output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P)); @@ -555,7 +557,7 @@ void ShowNew(ostream &out,CacheFile &Cache) [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); }, &PrettyFullName, CandidateVersion(&Cache), - "APT::Color::Green"); + "green"); return; } @@ -563,12 +565,12 @@ void ShowNew(ostream &out,CacheFile &Cache) [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall() && (Cache[Pkg].Flags & pkgCache::Flag::Auto) == 0; }, &PrettyFullName, CandidateVersion(&Cache), - "APT::Color::Green"); + "green"); ShowList(out,_("Installing dependencies:"), Universe, [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall() && Cache[Pkg].Flags & pkgCache::Flag::Auto;}, &PrettyFullName, CandidateVersion(&Cache), - "APT::Color::Green"); + "green"); } /*}}}*/ // ShowDel - Show packages to delete /*{{{*/ @@ -586,7 +588,7 @@ void ShowDel(ostream &out,CacheFile &Cache) return str; }, CandidateVersion(&Cache), - "APT::Color::Red"); + "red"); } /*}}}*/ // ShowPhasing - Show packages kept due to phasing /*{{{*/ @@ -625,7 +627,7 @@ void ShowUpgraded(ostream &out,CacheFile &Cache) }, &PrettyFullName, CurrentToCandidateVersion(&Cache), - "APT::Color::Green"); + "green"); } /*}}}*/ // ShowDowngraded - Show downgraded packages /*{{{*/ @@ -642,7 +644,7 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache) }, &PrettyFullName, CurrentToCandidateVersion(&Cache), - "APT::Color::Yellow"); + "yellow"); } /*}}}*/ // ShowHold - Show held but changed packages /*{{{*/ diff --git a/apt-private/private-output.h b/apt-private/private-output.h index 4cc7c01b4..330801bb0 100644 --- a/apt-private/private-output.h +++ b/apt-private/private-output.h @@ -1,6 +1,7 @@ #ifndef APT_PRIVATE_OUTPUT_H #define APT_PRIVATE_OUTPUT_H +#include #include #include #include @@ -18,7 +19,6 @@ class CacheFile; class pkgDepCache; class pkgRecords; - APT_PUBLIC extern std::ostream c0out; APT_PUBLIC extern std::ostream c1out; APT_PUBLIC extern std::ostream c2out; @@ -43,7 +43,7 @@ template bool PredicateC Predicate, DisplayP PkgDisplay, DisplayV VerboseDisplay, - std::string colorName = "APT::Color::Neutral") + std::string colorName = "") { size_t const ScreenWidth = (::ScreenWidth > 3) ? ::ScreenWidth - 3 : 0; int ScreenUsed = 0; @@ -52,8 +52,8 @@ template bool bool printedTitle = false; std::vector PackageList; - auto setColor = _config->FindI("APT::Output-Version") >= 30 ? _config->Find(colorName) : ""; - auto resetColor = _config->FindI("APT::Output-Version") >= 30 ? _config->Find("APT::Color::Neutral") : ""; + auto setColor = _config->FindI("APT::Output-Version") >= 30 ? APT::Configuration::color(colorName) : ""; + auto resetColor = _config->FindI("APT::Output-Version") >= 30 && not setColor.empty() ? APT::Configuration::color("neutral") : ""; for (auto const &Pkg: cont) { -- cgit v1.2.3-70-g09d2 From dc779ff0a33d9da8bc55390ee55ad73d31739e46 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 19 Apr 2024 16:12:42 +0200 Subject: Configure individual action colors using APT::Color::Action --- apt-private/private-install.cc | 2 +- apt-private/private-output.cc | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 87793d973..774c03d0a 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -1104,7 +1104,7 @@ bool DoInstall(CommandLine &CmdL) if (_config->FindI("APT::Output-Version") < 30 && Cache->InstCount() != verset[MOD_INSTALL].size()) ShowList(c1out, _("The following additional packages will be installed:"), Universe, PkgIsExtraInstalled(&Cache, &verset[MOD_INSTALL]), - &PrettyFullName, CandidateVersion(&Cache), "green"); + &PrettyFullName, CandidateVersion(&Cache), "action::install-dependencies"); /* Print out a list of suggested and recommended packages */ if (_config->FindI("APT::Output-Version") < 30) diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 380558964..c2e936d2c 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -105,6 +105,12 @@ bool InitOutput(std::basic_streambuf * const out) /*{{{*/ _config->CndSet("APT::Color::Magenta", "\x1B[35m"); _config->CndSet("APT::Color::Cyan", "\x1B[36m"); _config->CndSet("APT::Color::White", "\x1B[37m"); + + _config->CndSet("APT::Color::Action::Upgrade", "green"); + _config->CndSet("APT::Color::Action::Install", "green"); + _config->CndSet("APT::Color::Action::Install-Dependencies", "green"); + _config->CndSet("APT::Color::Action::Downgrade", "yellow"); + _config->CndSet("APT::Color::Action::Remove", "red"); } return true; @@ -557,7 +563,7 @@ void ShowNew(ostream &out,CacheFile &Cache) [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); }, &PrettyFullName, CandidateVersion(&Cache), - "green"); + "action::install"); return; } @@ -565,12 +571,12 @@ void ShowNew(ostream &out,CacheFile &Cache) [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall() && (Cache[Pkg].Flags & pkgCache::Flag::Auto) == 0; }, &PrettyFullName, CandidateVersion(&Cache), - "green"); + "action::install"); ShowList(out,_("Installing dependencies:"), Universe, [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall() && Cache[Pkg].Flags & pkgCache::Flag::Auto;}, &PrettyFullName, CandidateVersion(&Cache), - "green"); + "action::install-dependencies"); } /*}}}*/ // ShowDel - Show packages to delete /*{{{*/ @@ -588,7 +594,7 @@ void ShowDel(ostream &out,CacheFile &Cache) return str; }, CandidateVersion(&Cache), - "red"); + "action::remove"); } /*}}}*/ // ShowPhasing - Show packages kept due to phasing /*{{{*/ @@ -627,7 +633,7 @@ void ShowUpgraded(ostream &out,CacheFile &Cache) }, &PrettyFullName, CurrentToCandidateVersion(&Cache), - "green"); + "action::upgrade"); } /*}}}*/ // ShowDowngraded - Show downgraded packages /*{{{*/ @@ -644,7 +650,7 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache) }, &PrettyFullName, CurrentToCandidateVersion(&Cache), - "yellow"); + "action::downgrade"); } /*}}}*/ // ShowHold - Show held but changed packages /*{{{*/ -- cgit v1.2.3-70-g09d2 From be5289525a2a037881eaac48fbab26f864f72cd5 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 19 Apr 2024 16:18:57 +0200 Subject: Add a --color, --no-color option Wrap empty else in {} to avoid readability issues --- apt-private/private-cmndline.cc | 7 +++---- apt-private/private-moo.cc | 2 +- doc/apt.ent | 10 ++++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 9b84f2dd5..e0e00c917 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -246,10 +246,8 @@ static bool addArgumentsAPTGet(std::vector &Args, char const } else if (CmdMatches("clean", "autoclean", "auto-clean", "distclean", "dist-clean", "check", "download", "changelog") || CmdMatches("markauto", "unmarkauto")) // deprecated commands - ; - else if (CmdMatches("moo")) - addArg(0, "color", "APT::Moo::Color", 0); - + { + } if (CmdMatches("install", "reinstall", "remove", "purge", "upgrade", "dist-upgrade", "dselect-upgrade", "autoremove", "auto-remove", "autopurge", "check", "clean", "autoclean", "auto-clean", "distclean", "dist-clean", @@ -409,6 +407,7 @@ std::vector getCommandArgs(APT_CMD const Program, char const addArg('h', "help", "help", 0); addArg('v', "version", "version", 0); // general options + addArg(0, "color", "APT::Color", 0); addArg('q', "quiet", "quiet", CommandLine::IntLevel); addArg('q', "silent", "quiet", CommandLine::IntLevel); addArg('c', "config-file", 0, CommandLine::ConfigFile); diff --git a/apt-private/private-moo.cc b/apt-private/private-moo.cc index 2a9ed9391..5eb6db56a 100644 --- a/apt-private/private-moo.cc +++ b/apt-private/private-moo.cc @@ -96,7 +96,7 @@ static bool DoMoo2(time_t const timenow) /*{{{*/ return printMooLine(timenow); std::string const moo = getMooLine(timenow); size_t const depth = moo.length()/4; - if (_config->FindB("APT::Moo::Color", false) == false) + if (_config->FindB("APT::Color", false) == false) c1out << OutputInDepth(depth, " ") << " (__) \n" << OutputInDepth(depth, " ") << " _______~(..)~ \n" << diff --git a/doc/apt.ent b/doc/apt.ent index a6abb0e0a..386abd493 100644 --- a/doc/apt.ent +++ b/doc/apt.ent @@ -70,6 +70,16 @@ + + + + +Turn colors on or off. Colors are on by default on supported terminals for &apt; and +can also be disabled using the NO_COLOR or APT_NO_COLOR environment variables, +or further configured by the configuration option and scope, see &apt-conf; for information on that. + + + ">