Skip to content

Commit d13d8d7

Browse files
committed
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 <[email protected]>
1 parent 8efbaa2 commit d13d8d7

File tree

10 files changed

+144
-0
lines changed

10 files changed

+144
-0
lines changed

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,5 @@ Thanks to the following, who submitted detailed bug reports and excellent sugges
131131
Sebastian Carlos
132132
ftambara
133133
Tobias Predel
134+
Alex Rogers
135+

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
- #727 :color hint does not work with the summary report
2+
(thanks to Alex Rogers)
3+
14
------ current release ---------------------------
25

36
1.9.1 (2025-08-27) - 8c14b6d44adc75b7031eb0c25237db842aba37f9

src/SummaryTable.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ SummaryTable::Builder & SummaryTable::Builder::withIntervals (const std::vector
110110
return *this;
111111
}
112112

113+
////////////////////////////////////////////////////////////////////////////////
114+
SummaryTable::Builder& SummaryTable::Builder::withColor (bool withColor)
115+
{
116+
_with_color = withColor;
117+
return *this;
118+
}
119+
113120
////////////////////////////////////////////////////////////////////////////////
114121
Table SummaryTable::Builder::build ()
115122
{
@@ -164,6 +171,8 @@ Table SummaryTable::Builder::build ()
164171
table.add ("Annotation");
165172
}
166173

174+
table.withColor(_with_color);
175+
167176
table.add ("Start", false);
168177
table.add ("End", false);
169178
table.add ("Time", false);

src/SummaryTable.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class SummaryTable
5151
Builder& withRange (const Range&);
5252
Builder& withIntervals (const std::vector <Interval>&);
5353

54+
Builder& withColor (bool);
55+
5456
Table build ();
5557

5658
private:
@@ -63,6 +65,7 @@ class SummaryTable
6365
bool _show_tags;
6466
bool _show_weekdays;
6567
bool _show_weeks;
68+
bool _with_color;
6669

6770
Range _range;
6871
std::vector <Interval> _tracked;

src/TagsTable.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ TagsTable::Builder& TagsTable::Builder::withTagDescriptions (std::vector <TagDes
4040
return *this;
4141
}
4242

43+
////////////////////////////////////////////////////////////////////////////////
44+
TagsTable::Builder& TagsTable::Builder::withColor (bool forceColor)
45+
{
46+
_with_color = forceColor;
47+
return *this;
48+
}
49+
4350
////////////////////////////////////////////////////////////////////////////////
4451
Table TagsTable::Builder::build ()
4552
{
@@ -51,6 +58,8 @@ Table TagsTable::Builder::build ()
5158
table.add ("Tag");
5259
table.add ("Description");
5360

61+
table.withColor (_with_color);
62+
5463
for (const auto& tagDescription : _tagDescriptions)
5564
{
5665
auto row = table.addRow ();

src/TagsTable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ class TagsTable
3737
{
3838
public:
3939
Builder& withTagDescriptions (std::vector <TagDescription>&);
40+
Builder& withColor (bool);
4041

4142
Table build ();
4243

4344
private:
4445
std::vector <TagDescription> _tagDescriptions {};
46+
bool _with_color {false};
4547
};
4648

4749
public:

src/commands/CmdSummary.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ int CmdSummary (
154154
.withAnnotations (show_annotations)
155155
.withRange (range)
156156
.withIntervals (tracked)
157+
.withColor (rules.getBoolean ("color"))
157158
.build ();
158159

159160
std::cout << '\n'

src/commands/CmdTags.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ int CmdTags (
8080

8181
auto table = TagsTable::builder()
8282
.withTagDescriptions (tagDescriptions)
83+
.withColor (rules.getBoolean ("color"))
8384
.build ();
8485

8586
std::cout << '\n'

src/init.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ void initializeDataJournalAndRules (
158158
enableDebugMode (rules.getBoolean ("debug"));
159159
paths::initializeDirs (rules);
160160

161+
for (auto& arg : cli._args)
162+
{
163+
if (arg.hasTag ("HINT"))
164+
{
165+
if (arg.attribute ("canonical") == ":debug") rules.set ("debug", "on");
166+
if (arg.attribute ("canonical") == ":quiet") rules.set ("verbose", "off");
167+
if (arg.attribute ("canonical") == ":color") rules.set ("color", "on");
168+
if (arg.attribute ("canonical") == ":nocolor") rules.set ("color", "off");
169+
if (arg.attribute ("canonical") == ":yes") rules.set ("confirmation", "off");
170+
}
171+
}
172+
161173
if (rules.has ("debug.indicator"))
162174
setDebugIndicator (rules.get ("debug.indicator"));
163175

test/color_hint.t

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python3
2+
3+
###############################################################################
4+
#
5+
# Copyright 2025, Gothenburg Bit Factory.
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included
15+
# in all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20+
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
# SOFTWARE.
24+
#
25+
# https://opensource.org/license/mit
26+
#
27+
###############################################################################
28+
29+
import os
30+
import sys
31+
import unittest
32+
33+
# Ensure python finds the local simpletap module
34+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
35+
36+
from basetest import Timew, TestCase
37+
38+
39+
class TestColorHint(TestCase):
40+
def setUp(self):
41+
"""Executed before each test in the class"""
42+
self.t = Timew()
43+
44+
def test_color_hint_overrides_config_and_works_when_piped(self):
45+
""":color hint should override color=off config and work with piped output"""
46+
# Set color to off in config file
47+
try:
48+
self.t.config("color", "off")
49+
except:
50+
pass
51+
52+
# Track some time
53+
self.t("start 1h ago foo")
54+
self.t("stop")
55+
56+
# Test with day command - output is naturally piped in test framework
57+
code, out, err = self.t(":color day")
58+
self.assertIn("\033[", out, "Expected colors with :color hint for day command")
59+
60+
# Test with summary command
61+
code, out, err = self.t(":color summary")
62+
self.assertIn("\033[", out, "Expected colors with :color hint for summary command")
63+
64+
# Test with tags command
65+
code, out, err = self.t(":color tags")
66+
self.assertIn("\033[", out, "Expected colors with :color hint for tags command")
67+
68+
def test_nocolor_hint_disables_color(self):
69+
""":nocolor hint should disable color output"""
70+
# Set color to on in config file
71+
self.t.config("color", "on")
72+
73+
# Track some time
74+
self.t("start 1h ago bar")
75+
self.t("stop")
76+
77+
# Use :nocolor hint
78+
code, out, err = self.t(":nocolor day")
79+
80+
# Check that there are no ANSI color codes
81+
self.assertNotIn("\033[", out, "Expected no ANSI color codes when using :nocolor hint")
82+
83+
def test_no_color_by_default_when_piped(self):
84+
"""By default, no color should be used when output is piped"""
85+
# Don't set any color config (should default to off for pipes)
86+
87+
# Track some time
88+
self.t("start 2h ago qux")
89+
self.t("stop 1h ago")
90+
91+
# Without :color hint, output should not have colors when piped
92+
# (test framework pipes output by default)
93+
code, out, err = self.t("day")
94+
self.assertNotIn("\033[", out, "Expected no colors by default when piped")
95+
96+
code, out, err = self.t("summary")
97+
self.assertNotIn("\033[", out, "Expected no colors in summary by default when piped")
98+
99+
100+
if __name__ == "__main__":
101+
from simpletap import TAPTestRunner
102+
unittest.main(testRunner=TAPTestRunner())

0 commit comments

Comments
 (0)