• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GothenburgBitFactory / taskwarrior / 10152339701

29 Jul 2024 09:45PM UTC coverage: 84.437% (+0.07%) from 84.372%
10152339701

push

github

web-flow
Merge pull request #3566 from felixschurk/add-clang-format

Add clang-format to enforce style guide

12359 of 13760 new or added lines in 147 files covered. (89.82%)

123 existing lines in 42 files now uncovered.

19070 of 22585 relevant lines covered (84.44%)

19724.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.44
/src/commands/CmdProjects.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright 2006 - 2021, Tomas Babej, Paul Beckingham, Federico Hernandez.
4
//
5
// Permission is hereby granted, free of charge, to any person obtaining a copy
6
// of this software and associated documentation files (the "Software"), to deal
7
// in the Software without restriction, including without limitation the rights
8
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the Software is
10
// furnished to do so, subject to the following conditions:
11
//
12
// The above copyright notice and this permission notice shall be included
13
// in all copies or substantial portions of the Software.
14
//
15
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
// SOFTWARE.
22
//
23
// https://www.opensource.org/licenses/mit-license.php
24
//
25
////////////////////////////////////////////////////////////////////////////////
26

27
#include <cmake.h>
28
// cmake.h include header must come first
29

30
#include <CmdProjects.h>
31
#include <Context.h>
32
#include <Filter.h>
33
#include <Table.h>
34
#include <format.h>
35
#include <main.h>
36
#include <util.h>
37

38
#include <algorithm>
39
#include <list>
40
#include <sstream>
41

42
////////////////////////////////////////////////////////////////////////////////
43
CmdProjects::CmdProjects() {
4,389✔
44
  _keyword = "projects";
4,389✔
45
  _usage = "task <filter> projects";
4,389✔
46
  _description = "Shows all project names used";
4,389✔
47
  _read_only = true;
4,389✔
48
  _displays_id = false;
4,389✔
49
  _needs_gc = true;
4,389✔
50
  _uses_context = true;
4,389✔
51
  _accepts_filter = true;
4,389✔
52
  _accepts_modifications = false;
4,389✔
53
  _accepts_miscellaneous = false;
4,389✔
54
  _category = Command::Category::metadata;
4,389✔
55
}
4,389✔
56

57
////////////////////////////////////////////////////////////////////////////////
58
int CmdProjects::execute(std::string& output) {
10✔
59
  int rc = 0;
10✔
60

61
  // Get all the tasks.
62
  handleUntil();
10✔
63
  handleRecurrence();
10✔
64
  auto tasks = Context::getContext().tdb2.pending_tasks();
10✔
65

66
  if (Context::getContext().config.getBoolean("list.all.projects"))
10✔
67
    for (auto& task : Context::getContext().tdb2.completed_tasks()) tasks.push_back(task);
2✔
68

69
  // Apply the filter.
70
  Filter filter;
10✔
71
  std::vector<Task> filtered;
10✔
72
  filter.subset(tasks, filtered);
10✔
73
  int quantity = filtered.size();
10✔
74

75
  std::stringstream out;
10✔
76

77
  // Scan all the tasks for their project name, building a map using project
78
  // names as keys.
79
  std::map<std::string, int> unique;
10✔
80
  bool no_project = false;
10✔
81
  std::string project;
10✔
82
  for (auto& task : filtered) {
27✔
83
    if (task.getStatus() == Task::deleted) {
17✔
84
      --quantity;
×
85
      continue;
×
86
    }
87

88
    // Increase the count for the project the task belongs to and all
89
    // its super-projects
90
    project = task.get("project");
17✔
91

92
    std::vector<std::string> projects = extractParents(project);
17✔
93
    projects.push_back(project);
17✔
94

95
    for (auto& parent : projects) unique[parent] += 1;
37✔
96

97
    if (project == "") no_project = true;
17✔
98
  }
17✔
99

100
  if (unique.size()) {
10✔
101
    // Render a list of project names from the map.
102
    Table view;
10✔
103
    view.width(Context::getContext().getWidth());
10✔
104
    view.add("Project");
10✔
105
    view.add("Tasks", false);
10✔
106
    setHeaderUnderline(view);
10✔
107

108
    // create sorted list of table entries
109
    std::list<std::pair<std::string, int>> sorted_view;
10✔
110
    sort_projects(sorted_view, unique);
10✔
111

112
    // construct view from sorted list
113
    for (auto& item : sorted_view) {
29✔
114
      int row = view.addRow();
19✔
115
      view.set(row, 0, (item.first == "" ? "(none)" : indentProject(item.first, "  ", '.')));
19✔
116
      view.set(row, 1, item.second);
19✔
117
    }
118

119
    int number_projects = unique.size();
10✔
120
    if (no_project) --number_projects;
10✔
121

NEW
122
    out << optionalBlankLine() << view.render() << optionalBlankLine()
×
123
        << (number_projects == 1 ? format("{1} project", number_projects)
20✔
124
                                 : format("{1} projects", number_projects))
125
        << ' ' << (quantity == 1 ? format("({1} task)", quantity) : format("({1} tasks)", quantity))
20✔
126
        << '\n';
30✔
127
  } else {
10✔
UNCOV
128
    out << "No projects.\n";
×
129
    rc = 1;
×
130
  }
131

132
  output = out.str();
10✔
133
  return rc;
10✔
134
}
10✔
135

136
////////////////////////////////////////////////////////////////////////////////
137
CmdCompletionProjects::CmdCompletionProjects() {
4,389✔
138
  _keyword = "_projects";
4,389✔
139
  _usage = "task <filter> _projects";
4,389✔
140
  _description = "Shows only a list of all project names used";
4,389✔
141
  _read_only = true;
4,389✔
142
  _displays_id = false;
4,389✔
143
  _needs_gc = true;
4,389✔
144
  _uses_context = false;
4,389✔
145
  _accepts_filter = true;
4,389✔
146
  _accepts_modifications = false;
4,389✔
147
  _accepts_miscellaneous = false;
4,389✔
148
  _category = Command::Category::internal;
4,389✔
149
}
4,389✔
150

151
////////////////////////////////////////////////////////////////////////////////
152
int CmdCompletionProjects::execute(std::string& output) {
10✔
153
  // Get all the tasks.
154
  handleUntil();
10✔
155
  handleRecurrence();
10✔
156
  auto tasks = Context::getContext().tdb2.pending_tasks();
10✔
157

158
  if (Context::getContext().config.getBoolean("list.all.projects"))
10✔
159
    for (auto& task : Context::getContext().tdb2.completed_tasks()) tasks.push_back(task);
3✔
160

161
  // Apply the filter.
162
  Filter filter;
10✔
163
  std::vector<Task> filtered;
10✔
164
  filter.subset(tasks, filtered);
10✔
165

166
  // Scan all the tasks for their project name, building a map using project
167
  // names as keys.
168
  std::map<std::string, int> unique;
10✔
169
  for (auto& task : filtered) unique[task.get("project")] = 0;
23✔
170

171
  for (auto& project : unique)
23✔
172
    if (project.first.length()) output += project.first + '\n';
13✔
173

174
  return 0;
10✔
175
}
10✔
176

177
////////////////////////////////////////////////////////////////////////////////
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc