Handle 'until' and 'recur' simiar to handling of 'gc' (#3753)

This centralizes updates to recurrence and 'until' in Command, instead
of doing so in each individual command implementation.

This is preparatory to opening the TaskChampion replica in read-only
mode.
This commit is contained in:
Dustin J. Mitchell 2025-01-18 02:20:41 -05:00 committed by GitHub
parent 1c9dddcae7
commit aeeec16984
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 87 additions and 39 deletions

View file

@ -852,7 +852,7 @@ int Context::dispatch(std::string& out) {
Command* c = commands[command];
assert(c);
// The command know whether they need a GC.
// The command know whether they need a GC or recurrence update.
if (c->needs_gc()) {
tdb2.gc();
}
@ -869,6 +869,11 @@ int Context::dispatch(std::string& out) {
if (config.getBoolean("debug") && config.getInteger("debug.parser") == 1)
debug(cli2.dump("Parse Tree (before command-specifіc processing)"));
if (c->needs_recur_update()) {
handleUntil();
handleRecurrence();
}
return c->execute(out);
}

View file

@ -40,6 +40,7 @@ CmdAdd::CmdAdd() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = false;
_accepts_modifications = true;

View file

@ -39,6 +39,7 @@ CmdCompletionAliases::CmdCompletionAliases() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -44,6 +44,7 @@ CmdAnnotate::CmdAnnotate() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -44,6 +44,7 @@ CmdAppend::CmdAppend() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -42,6 +42,7 @@ CmdZshAttributes::CmdZshAttributes() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -767,6 +767,7 @@ CmdBurndownMonthly::CmdBurndownMonthly() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -779,8 +780,6 @@ int CmdBurndownMonthly::execute(std::string& output) {
int rc = 0;
// Scan the pending tasks, applying any filter.
handleUntil();
handleRecurrence();
Filter filter;
std::vector<Task> filtered;
filter.subset(filtered);
@ -801,6 +800,7 @@ CmdBurndownWeekly::CmdBurndownWeekly() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -813,8 +813,6 @@ int CmdBurndownWeekly::execute(std::string& output) {
int rc = 0;
// Scan the pending tasks, applying any filter.
handleUntil();
handleRecurrence();
Filter filter;
std::vector<Task> filtered;
filter.subset(filtered);
@ -835,6 +833,7 @@ CmdBurndownDaily::CmdBurndownDaily() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -847,8 +846,6 @@ int CmdBurndownDaily::execute(std::string& output) {
int rc = 0;
// Scan the pending tasks, applying any filter.
handleUntil();
handleRecurrence();
Filter filter;
std::vector<Task> filtered;
filter.subset(filtered);

View file

@ -37,6 +37,7 @@ CmdCalc::CmdCalc() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -49,6 +49,7 @@ CmdCalendar::CmdCalendar() {
_read_only = true;
_displays_id = true;
_needs_gc = true;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
@ -80,8 +81,6 @@ int CmdCalendar::execute(std::string& output) {
monthsPerLine = preferredMonthsPerLine;
// Load the pending tasks.
handleUntil();
handleRecurrence();
auto tasks = Context::getContext().tdb2.pending_tasks();
Datetime today;

View file

@ -45,6 +45,7 @@ CmdColor::CmdColor() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -45,6 +45,7 @@ CmdColumns::CmdColumns() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
@ -119,6 +120,7 @@ CmdCompletionColumns::CmdCompletionColumns() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -45,6 +45,7 @@ CmdCommands::CmdCommands() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
@ -61,6 +62,7 @@ int CmdCommands::execute(std::string& output) {
view.add("R/W", false);
view.add("ID", false);
view.add("GC", false);
view.add("Recur", false);
view.add("Context", false);
view.add("Filter", false);
view.add("Mods", false);
@ -85,15 +87,17 @@ int CmdCommands::execute(std::string& output) {
if (command.second->needs_gc()) view.set(row, 4, "GC");
if (command.second->uses_context()) view.set(row, 5, "Ctxt");
if (command.second->needs_recur_update()) view.set(row, 5, "Recur");
if (command.second->accepts_filter()) view.set(row, 6, "Filt");
if (command.second->uses_context()) view.set(row, 6, "Ctxt");
if (command.second->accepts_modifications()) view.set(row, 7, "Mods");
if (command.second->accepts_filter()) view.set(row, 7, "Filt");
if (command.second->accepts_miscellaneous()) view.set(row, 8, "Misc");
if (command.second->accepts_modifications()) view.set(row, 8, "Mods");
view.set(row, 9, command.second->description());
if (command.second->accepts_miscellaneous()) view.set(row, 9, "Misc");
view.set(row, 10, command.second->description());
}
output = optionalBlankLine() + view.render() + optionalBlankLine() + '\n';

View file

@ -44,6 +44,7 @@ CmdConfig::CmdConfig() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
@ -217,6 +218,7 @@ CmdCompletionConfig::CmdCompletionConfig() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -49,6 +49,7 @@ CmdContext::CmdContext() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
@ -414,6 +415,7 @@ CmdCompletionContext::CmdCompletionContext() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -40,6 +40,7 @@ CmdCount::CmdCount() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -50,8 +51,6 @@ CmdCount::CmdCount() {
////////////////////////////////////////////////////////////////////////////////
int CmdCount::execute(std::string& output) {
// Apply filter.
handleUntil();
handleRecurrence();
Filter filter;
std::vector<Task> filtered;
filter.subset(filtered);

View file

@ -55,6 +55,7 @@ CmdCustom::CmdCustom(const std::string& keyword, const std::string& usage,
_read_only = true;
_displays_id = true;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -100,10 +101,6 @@ int CmdCustom::execute(std::string& output) {
// Add the report filter to any existing filter.
if (reportFilter != "") Context::getContext().cli2.addFilter(reportFilter);
// Make sure reccurent tasks are generated.
handleUntil();
handleRecurrence();
// Apply filter.
Filter filter;
std::vector<Task> filtered;

View file

@ -49,6 +49,7 @@ CmdDelete::CmdDelete() {
_displays_id = false;
_needs_confirm = true;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -49,6 +49,7 @@ CmdDenotate::CmdDenotate() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -50,6 +50,7 @@ CmdDiagnostics::CmdDiagnostics() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -44,6 +44,7 @@ CmdDone::CmdDone() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -44,6 +44,7 @@ CmdDuplicate::CmdDuplicate() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -64,6 +64,7 @@ CmdEdit::CmdEdit() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -40,6 +40,7 @@ CmdExec::CmdExec() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -42,6 +42,7 @@ CmdExport::CmdExport() {
_read_only = true;
_displays_id = true;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -82,10 +83,6 @@ int CmdExport::execute(std::string& output) {
// Add the report filter to any existing filter.
if (reportFilter != "") Context::getContext().cli2.addFilter(reportFilter);
// Make sure reccurent tasks are generated.
handleUntil();
handleRecurrence();
// Apply filter.
Filter filter;
std::vector<Task> filtered;

View file

@ -43,6 +43,7 @@ CmdGet::CmdGet() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -44,6 +44,7 @@ CmdHelp::CmdHelp() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -55,6 +55,7 @@ CmdHistoryBase<HistoryStrategy>::CmdHistoryBase() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -46,6 +46,7 @@ CmdIDs::CmdIDs() {
_read_only = true;
_displays_id = true;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -56,8 +57,6 @@ CmdIDs::CmdIDs() {
////////////////////////////////////////////////////////////////////////////////
int CmdIDs::execute(std::string& output) {
// Apply filter.
handleUntil();
handleRecurrence();
Filter filter;
std::vector<Task> filtered;
filter.subset(filtered);
@ -127,6 +126,7 @@ CmdCompletionIds::CmdCompletionIds() {
_read_only = true;
_displays_id = true;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -163,6 +163,7 @@ CmdZshCompletionIds::CmdZshCompletionIds() {
_read_only = true;
_displays_id = true;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -199,6 +200,7 @@ CmdUUIDs::CmdUUIDs() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -234,6 +236,7 @@ CmdCompletionUuids::CmdCompletionUuids() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -269,6 +272,7 @@ CmdZshCompletionUuids::CmdZshCompletionUuids() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -45,6 +45,7 @@ CmdImport::CmdImport() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -46,6 +46,7 @@ CmdImportV2::CmdImportV2() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -59,6 +59,7 @@ CmdInfo::CmdInfo() {
// Once the test suite is completely modified, this can be corrected.
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -40,6 +40,7 @@ CmdLog::CmdLog() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = false;
_accepts_modifications = true;

View file

@ -39,6 +39,7 @@ CmdLogo::CmdLogo() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -48,6 +48,7 @@ CmdModify::CmdModify() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -57,6 +57,7 @@ CmdNews::CmdNews() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -44,6 +44,7 @@ CmdPrepend::CmdPrepend() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -47,6 +47,7 @@ CmdProjects::CmdProjects() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -59,8 +60,6 @@ int CmdProjects::execute(std::string& output) {
int rc = 0;
// Get all the tasks.
handleUntil();
handleRecurrence();
auto tasks = Context::getContext().tdb2.pending_tasks();
if (Context::getContext().config.getBoolean("list.all.projects"))
@ -141,6 +140,7 @@ CmdCompletionProjects::CmdCompletionProjects() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -151,8 +151,6 @@ CmdCompletionProjects::CmdCompletionProjects() {
////////////////////////////////////////////////////////////////////////////////
int CmdCompletionProjects::execute(std::string& output) {
// Get all the tasks.
handleUntil();
handleRecurrence();
auto tasks = Context::getContext().tdb2.pending_tasks();
if (Context::getContext().config.getBoolean("list.all.projects"))

View file

@ -43,6 +43,7 @@ CmdPurge::CmdPurge() {
_displays_id = false;
_needs_confirm = true;
_needs_gc = true;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -43,6 +43,7 @@ CmdReports::CmdReports() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -53,6 +53,7 @@ CmdShow::CmdShow() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -44,6 +44,7 @@ CmdStart::CmdStart() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -49,6 +49,7 @@ CmdStats::CmdStats() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -43,6 +43,7 @@ CmdStop::CmdStop() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = true;

View file

@ -49,6 +49,7 @@ CmdSummary::CmdSummary() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -65,8 +66,6 @@ int CmdSummary::execute(std::string& output) {
bool showAllProjects = Context::getContext().config.getBoolean("summary.all.projects");
// Apply filter.
handleUntil();
handleRecurrence();
Filter filter;
std::vector<Task> filtered;
filter.subset(filtered);

View file

@ -49,6 +49,7 @@ CmdSync::CmdSync() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -46,6 +46,7 @@ CmdTags::CmdTags() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = false;
_uses_context = true;
_accepts_filter = true;
_accepts_modifications = false;
@ -136,6 +137,7 @@ CmdCompletionTags::CmdCompletionTags() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -48,6 +48,7 @@ CmdTimesheet::CmdTimesheet() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = true;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;
@ -90,8 +91,6 @@ int CmdTimesheet::execute(std::string& output) {
}
// Apply filter to get a set of tasks.
handleUntil();
handleRecurrence();
Filter filter;
std::vector<Task> filtered;
filter.subset(filtered);

View file

@ -48,6 +48,7 @@ CmdUDAs::CmdUDAs() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
@ -156,6 +157,7 @@ CmdCompletionUDAs::CmdCompletionUDAs() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -45,6 +45,7 @@ CmdUndo::CmdUndo() {
_read_only = false;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -43,6 +43,7 @@ CmdUnique::CmdUnique() {
_read_only = true;
_displays_id = true;
_needs_gc = true;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -45,6 +45,7 @@ CmdUrgency::CmdUrgency() {
_read_only = true;
_displays_id = false;
_needs_gc = true;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = true;
_accepts_modifications = false;

View file

@ -48,6 +48,7 @@ CmdVersion::CmdVersion() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;
@ -101,6 +102,7 @@ CmdCompletionVersion::CmdCompletionVersion() {
_read_only = true;
_displays_id = false;
_needs_gc = false;
_needs_recur_update = false;
_uses_context = false;
_accepts_filter = false;
_accepts_modifications = false;

View file

@ -295,6 +295,7 @@ Command::Command()
_displays_id(true),
_needs_confirm(false),
_needs_gc(true),
_needs_recur_update(false),
_uses_context(false),
_accepts_filter(false),
_accepts_modifications(false),
@ -322,6 +323,9 @@ bool Command::displays_id() const { return _displays_id; }
////////////////////////////////////////////////////////////////////////////////
bool Command::needs_gc() const { return _needs_gc; }
////////////////////////////////////////////////////////////////////////////////
bool Command::needs_recur_update() const { return _needs_recur_update; }
////////////////////////////////////////////////////////////////////////////////
bool Command::uses_context() const { return _uses_context; }

View file

@ -62,6 +62,7 @@ class Command {
bool read_only() const;
bool displays_id() const;
bool needs_gc() const;
bool needs_recur_update() const;
virtual bool uses_context() const;
bool accepts_filter() const;
bool accepts_modifications() const;
@ -81,6 +82,7 @@ class Command {
bool _displays_id;
bool _needs_confirm;
bool _needs_gc;
bool _needs_recur_update;
bool _uses_context;
bool _accepts_filter;
bool _accepts_modifications;

View file

@ -47,9 +47,6 @@ std::optional<Datetime> getNextRecurrence(Datetime&, std::string&);
bool generateDueDates(Task&, std::vector<Datetime>&);
void updateRecurrenceMask(Task&);
// recur2.cpp
void handleRecurrence2();
// nag.cpp
void nag(std::vector<Task>&);

View file

@ -44,7 +44,7 @@ class TestCommands(TestCase):
code, out, err = self.t("commands")
self.assertRegex(out, r"add\s+operation\s+RW\s+Ctxt\s+Mods\s+Adds a new task")
self.assertRegex(
out, r"list\s+report\s+RO\s+ID\s+GC\s+Ctxt\s+Filt\s+Most details of"
out, r"list\s+report\s+RO\s+ID\s+GC\s+Recur\s+Ctxt\s+Filt\s+Most details of"
)
self.assertRegex(out, r"modify\s+operation\s+RW\s+Filt\s+Mods\s+Modifies the")
@ -53,7 +53,7 @@ class TestCommands(TestCase):
code, out, err = self.t("commands rc._forcecolor:on")
self.assertRegex(out, r"add\s+operation\s+RW\s+Ctxt\s+Mods\s+Adds a new task")
self.assertRegex(
out, r"list\s+report\s+RO\s+ID\s+GC\s+Ctxt\s+Filt\s+Most details of"
out, r"list\s+report\s+RO\s+ID\s+GC\s+Recur\s+Ctxt\s+Filt\s+Most details of"
)
self.assertRegex(out, r"modify\s+operation\s+RW\s+Filt\s+Mods\s+Modifies the")