From 8efbaa2db615727b4e9c253e562f6a53003e89a1 Mon Sep 17 00:00:00 2001 From: Thomas Lauf Date: Sun, 7 Dec 2025 21:31:59 +0100 Subject: [PATCH 1/2] Update libshared to 3da15345b1bdd2bc69de7231e578bd5d530fc92c Signed-off-by: Thomas Lauf --- src/libshared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libshared b/src/libshared index 15cb6f90..3da15345 160000 --- a/src/libshared +++ b/src/libshared @@ -1 +1 @@ -Subproject commit 15cb6f90f25758612d79f788095a4c3a9c090b89 +Subproject commit 3da15345b1bdd2bc69de7231e578bd5d530fc92c From d13d8d7a1745dbdbad2138aba88078f7022b3d7d Mon Sep 17 00:00:00 2001 From: Thomas Lauf Date: Tue, 25 Nov 2025 12:27:27 +0100 Subject: [PATCH 2/2] Pass color settings to the tables The builders of the tags and summary table did not pass the value of the color setting. Also, the 'Table' component had an internal TTY check which could interfere with the color setting of the main application. Add test for color hint Reapply command line hints after loading config files Closes #727 Signed-off-by: Thomas Lauf --- AUTHORS | 2 + ChangeLog | 3 ++ src/SummaryTable.cpp | 9 ++++ src/SummaryTable.h | 3 ++ src/TagsTable.cpp | 9 ++++ src/TagsTable.h | 2 + src/commands/CmdSummary.cpp | 1 + src/commands/CmdTags.cpp | 1 + src/init.cpp | 12 +++++ test/color_hint.t | 102 ++++++++++++++++++++++++++++++++++++ 10 files changed, 144 insertions(+) create mode 100755 test/color_hint.t diff --git a/AUTHORS b/AUTHORS index a1b07d53..555eefbb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -131,3 +131,5 @@ Thanks to the following, who submitted detailed bug reports and excellent sugges Sebastian Carlos ftambara Tobias Predel + Alex Rogers + diff --git a/ChangeLog b/ChangeLog index e87225b4..556c4197 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +- #727 :color hint does not work with the summary report + (thanks to Alex Rogers) + ------ current release --------------------------- 1.9.1 (2025-08-27) - 8c14b6d44adc75b7031eb0c25237db842aba37f9 diff --git a/src/SummaryTable.cpp b/src/SummaryTable.cpp index c0310bc5..6ce4fa05 100644 --- a/src/SummaryTable.cpp +++ b/src/SummaryTable.cpp @@ -110,6 +110,13 @@ SummaryTable::Builder & SummaryTable::Builder::withIntervals (const std::vector return *this; } +//////////////////////////////////////////////////////////////////////////////// +SummaryTable::Builder& SummaryTable::Builder::withColor (bool withColor) +{ + _with_color = withColor; + return *this; +} + //////////////////////////////////////////////////////////////////////////////// Table SummaryTable::Builder::build () { @@ -164,6 +171,8 @@ Table SummaryTable::Builder::build () table.add ("Annotation"); } + table.withColor(_with_color); + table.add ("Start", false); table.add ("End", false); table.add ("Time", false); diff --git a/src/SummaryTable.h b/src/SummaryTable.h index 3c58b21a..9ba98a1d 100644 --- a/src/SummaryTable.h +++ b/src/SummaryTable.h @@ -51,6 +51,8 @@ class SummaryTable Builder& withRange (const Range&); Builder& withIntervals (const std::vector &); + Builder& withColor (bool); + Table build (); private: @@ -63,6 +65,7 @@ class SummaryTable bool _show_tags; bool _show_weekdays; bool _show_weeks; + bool _with_color; Range _range; std::vector _tracked; diff --git a/src/TagsTable.cpp b/src/TagsTable.cpp index 53b62f58..15f931b4 100644 --- a/src/TagsTable.cpp +++ b/src/TagsTable.cpp @@ -40,6 +40,13 @@ TagsTable::Builder& TagsTable::Builder::withTagDescriptions (std::vector &); + Builder& withColor (bool); Table build (); private: std::vector _tagDescriptions {}; + bool _with_color {false}; }; public: diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index dcbf6b50..3edac0c1 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -154,6 +154,7 @@ int CmdSummary ( .withAnnotations (show_annotations) .withRange (range) .withIntervals (tracked) + .withColor (rules.getBoolean ("color")) .build (); std::cout << '\n' diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index 1f7272ea..d80e71db 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -80,6 +80,7 @@ int CmdTags ( auto table = TagsTable::builder() .withTagDescriptions (tagDescriptions) + .withColor (rules.getBoolean ("color")) .build (); std::cout << '\n' diff --git a/src/init.cpp b/src/init.cpp index 2bdfe4de..ae2d0943 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -158,6 +158,18 @@ void initializeDataJournalAndRules ( enableDebugMode (rules.getBoolean ("debug")); paths::initializeDirs (rules); + for (auto& arg : cli._args) + { + if (arg.hasTag ("HINT")) + { + if (arg.attribute ("canonical") == ":debug") rules.set ("debug", "on"); + if (arg.attribute ("canonical") == ":quiet") rules.set ("verbose", "off"); + if (arg.attribute ("canonical") == ":color") rules.set ("color", "on"); + if (arg.attribute ("canonical") == ":nocolor") rules.set ("color", "off"); + if (arg.attribute ("canonical") == ":yes") rules.set ("confirmation", "off"); + } + } + if (rules.has ("debug.indicator")) setDebugIndicator (rules.get ("debug.indicator")); diff --git a/test/color_hint.t b/test/color_hint.t new file mode 100755 index 00000000..19cbb3d6 --- /dev/null +++ b/test/color_hint.t @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +############################################################################### +# +# Copyright 2025, Gothenburg Bit Factory. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# https://opensource.org/license/mit +# +############################################################################### + +import os +import sys +import unittest + +# Ensure python finds the local simpletap module +sys.path.append(os.path.dirname(os.path.abspath(__file__))) + +from basetest import Timew, TestCase + + +class TestColorHint(TestCase): + def setUp(self): + """Executed before each test in the class""" + self.t = Timew() + + def test_color_hint_overrides_config_and_works_when_piped(self): + """:color hint should override color=off config and work with piped output""" + # Set color to off in config file + try: + self.t.config("color", "off") + except: + pass + + # Track some time + self.t("start 1h ago foo") + self.t("stop") + + # Test with day command - output is naturally piped in test framework + code, out, err = self.t(":color day") + self.assertIn("\033[", out, "Expected colors with :color hint for day command") + + # Test with summary command + code, out, err = self.t(":color summary") + self.assertIn("\033[", out, "Expected colors with :color hint for summary command") + + # Test with tags command + code, out, err = self.t(":color tags") + self.assertIn("\033[", out, "Expected colors with :color hint for tags command") + + def test_nocolor_hint_disables_color(self): + """:nocolor hint should disable color output""" + # Set color to on in config file + self.t.config("color", "on") + + # Track some time + self.t("start 1h ago bar") + self.t("stop") + + # Use :nocolor hint + code, out, err = self.t(":nocolor day") + + # Check that there are no ANSI color codes + self.assertNotIn("\033[", out, "Expected no ANSI color codes when using :nocolor hint") + + def test_no_color_by_default_when_piped(self): + """By default, no color should be used when output is piped""" + # Don't set any color config (should default to off for pipes) + + # Track some time + self.t("start 2h ago qux") + self.t("stop 1h ago") + + # Without :color hint, output should not have colors when piped + # (test framework pipes output by default) + code, out, err = self.t("day") + self.assertNotIn("\033[", out, "Expected no colors by default when piped") + + code, out, err = self.t("summary") + self.assertNotIn("\033[", out, "Expected no colors in summary by default when piped") + + +if __name__ == "__main__": + from simpletap import TAPTestRunner + unittest.main(testRunner=TAPTestRunner())