This repository was archived by the owner on Feb 21, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathtodo.cpp
More file actions
254 lines (231 loc) · 6.03 KB
/
Copy pathtodo.cpp
File metadata and controls
254 lines (231 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
//Loosely inspired by https://github.com/2coolerino/cli_todo_list
#include <iostream>
#include <string>
#include <fstream>
#include <map>
using namespace std;
//The file storing the list items.
const string FILE_NAME = "todo_data.txt";
//The help menu, called with the '--help' command.
const string HELP_TEXT =
"Available Commands:"
"\n(no arguments) Display the todo list."
"\n--help Show a list of available commands."
"\nadd <item> Add <item> to the todo list."
"\ndelete <item> Remove <item> from the todo list."
"\ndelete -i <item_number> Remove the item at the provided index."
"\ntick <item> Tick <item> on the todo list."
"\ntick -i <item_number> Tick the item at the provided index."
"\nuntick <item> Untick <item> on the todo list."
"\nuntick -i <item_number> Untick the item at the provided index."
"\nclean Remove all ticked items from the todo list."
;
//Reads the list from file.
map<string, bool> read(){
//First char of each line is 0 or 1 - bit value of checked
map<string, bool> list;
fstream dataFile;
dataFile.open(FILE_NAME, ios::in);
if(dataFile.is_open()){
string line;
while(getline(dataFile, line)){
if(line.length() > 1){
char tick_char = line[0];
bool tick = tick_char == '1';
string item = line.substr(1);
list[item] = tick;
}
}
}
return list;
}
//Writes the list to file
void write(map<string, bool> &list){
fstream dataFile;
dataFile.open(FILE_NAME, ios::out);
if(dataFile.is_open()){
for(auto &item: list){
//Format 1foo\n0bar etc. for items foo (ticked) and bar (unticked)
dataFile << item.second << item.first << "\n";
}
}
}
//prints the provided list to the console,
//adding in the number of each item for reference
//with '-i' modifier
void printList(map<string, bool> &list){
if(list.size() == 0){
cout << "Nothing on your todo list." << endl;
return;
}
int i = 1;
for(auto &item: list){
cout << i << ". ";
if(item.second){
cout << "\u2713" << " ";
}
cout << item.first << endl;
i++;
}
}
//Gets the list item at the provided index
string getItem(map<string, bool> &list, int index){
auto it = list.begin();
advance(it, index);
return it->first;
}
//Gets the list item at the provided index,
//where a string has been provided.
//(rather than parsing the input string into an int,
//only to find that said int is out of range.)
string getItem(map<string, bool> &list, string indexAsString){
for(int i = 1; i <= list.size(); i++){
if(indexAsString == to_string(i)){
return getItem(list, i - 1);
}
}
cout << "No item exists of that number." << endl;
return "";
}
//Outputs the help menu
void help(){
cout << HELP_TEXT << endl;
}
//Adds an item to the provided list,
//given that it doesn't already exist.
bool addItem(map<string, bool> &list, string item){
if(list.find(item) == list.end()){
list[item] = 0;
return true;
} else {
cout << "Item already exists." << endl;
return false;
}
}
//Removes an item from the provided list.
bool deleteItem(map<string, bool> &list, string item){
if(list.find(item) != list.end()){
list.erase(item);
return true;
} else {
cout << "Item doesn't exist." << endl;
return false;
}
}
//Ticks the provided list item.
bool tickItem(map<string, bool> &list, string item){
if(list.find(item) != list.end()){
if(list[item] == 0){
list[item] = 1;
return true;
} else {
cout << "Item already ticked." << endl;
}
} else {
cout << "Item doesn't exist." << endl;
}
return false;
}
//Unticks the provided list item.
bool untickItem(map<string, bool> &list, string item){
if(list.find(item) != list.end()){
if(list[item] == 1){
list[item] = 0;
return true;
} else {
cout << "Item not ticked yet." << endl;
}
} else {
cout << "Item doesn't exist." << endl;
}
return false;
}
//Cleans the list,
//removing any ticked items.
bool cleanList(map<string, bool> &list){
int itemsRemoved = 0;
for(auto &item : list){
if(item.second == 1){
list.erase(item.first);
itemsRemoved++;
}
}
cout << to_string(itemsRemoved) << " item(s) removed." << endl;
return itemsRemoved != 0;
}
int main(int argc, char* argv[]){
//No command, so just display the current list
if(argc < 2){
map<string, bool> list = read();
printList(list);
exit(0);
}
string command = argv[1];
//Check for commands which don't need file access first
if(command == "--help"){
help();
exit(0);
}
//File-using commands
map<string, bool> list = read();
bool needsWritten = false;
if(command == "add" && argc == 3){
//Add next argument to the list
string item = argv[2];
needsWritten = addItem(list, item);
} else if(command == "delete" && argc == 3){
//Delete next argument from the list
string item = argv[2];
needsWritten = deleteItem(list, item);
} else if(command == "delete" && argc == 4){
string mod = argv[2];
if(mod == "-i"){
//Delete item from list at index specified by next argument
string index = argv[3];
string item = getItem(list, index);
if(item != ""){
needsWritten = deleteItem(list, item);
}
}
} else if(command == "tick" && argc == 3){
//Tick the next argument
string item = argv[2];
needsWritten = tickItem(list, item);
} else if(command == "tick" && argc == 4){
string mod = argv[2];
if(mod == "-i"){
string index = argv[3];
string item = getItem(list, index);
if(item != ""){
needsWritten = tickItem(list, item);
}
}
} else if(command == "untick" && argc == 3){
//Untick the next argument
string item = argv[2];
needsWritten = untickItem(list, item);
} else if(command == "untick" && argc == 4){
string mod = argv[2];
if(mod == "-i"){
string index = argv[3];
string item = getItem(list, index);
if(item != ""){
needsWritten = untickItem(list, item);
}
}
} else if(command == "clean" && argc == 2){
//Remove all ticked items from the list
needsWritten = cleanList(list);
} else {
//Something went wrong
cout << "todo: command not recognised." << endl
<< "Try 'todo --help' for more information." << endl;
exit(1);
}
if(needsWritten){
//Update file
write(list);
printList(list);
}
return 0;
}