xaizek / dit (License: GPLv3) (since 2018-12-07)
Command-line task keeper that remembers all old values and is meant to combine several orthogonal features to be rather flexible in managing items.
Commit cedec35134a1861f070fa2cfb05bd917df0dc77a

More sorting of keys on completion
Author: xaizek
Author date (UTC): 2016-06-06 18:29
Committer name: xaizek
Committer date (UTC): 2016-06-06 18:29
Parent(s): 1fdbcbba2f3351b17887fed2ae5f9546359192ec
Signing key: 99DC5E4DB05F6BE2
Tree: 8ea031693fed1e44fe5e4dca21e031edb1d7fa9c
File Lines added Lines deleted
src/completion.cpp 2 2
tests/cmds/AddCmd.cpp 7 12
tests/cmds/ConfigCmd.cpp 3 6
tests/cmds/ExportCmd.cpp 5 8
tests/cmds/RenameCmd.cpp 2 4
tests/cmds/SetCmd.cpp 9 16
tests/cmds/ShowCmd.cpp 3 6
File src/completion.cpp changed (mode: 100644) (index 447532c..6e5fad6)
... ... completeKeys(Item &item, std::ostream &os, const std::vector<std::string> &args)
77 77 int int
78 78 completeKeys(Storage &storage, std::ostream &os) completeKeys(Storage &storage, std::ostream &os)
79 79 { {
80 std::unordered_set<std::string> keys;
80 std::set<std::string> keys;
81 81
82 82 for (Item &item : storage.list()) { for (Item &item : storage.list()) {
83 83 const std::set<std::string> &itemKeys = item.listRecordNames(); const std::set<std::string> &itemKeys = item.listRecordNames();
 
... ... int
95 95 completeKeys(Storage &storage, std::ostream &os, completeKeys(Storage &storage, std::ostream &os,
96 96 const std::vector<std::string> &args) const std::vector<std::string> &args)
97 97 { {
98 std::unordered_set<std::string> keys;
98 std::set<std::string> keys;
99 99
100 100 for (Item &item : storage.list()) { for (Item &item : storage.list()) {
101 101 const std::set<std::string> &itemKeys = item.listRecordNames(); const std::set<std::string> &itemKeys = item.listRecordNames();
File tests/cmds/AddCmd.cpp changed (mode: 100644) (index a862451..0f9e0db)
... ... TEST_CASE("Add fails on wrong invocation", "[cmds][add][invocation]")
37 37 std::unique_ptr<Project> prj = Tests::makeProject(); std::unique_ptr<Project> prj = Tests::makeProject();
38 38 Command *const cmd = Commands::get("add"); Command *const cmd = Commands::get("add");
39 39
40 std::ostringstream out;
41 std::ostringstream err;
40 std::ostringstream out, err;
42 41 Tests::setStreams(out, err); Tests::setStreams(out, err);
43 42
44 43 boost::optional<int> exitCode; boost::optional<int> exitCode;
 
... ... TEST_CASE("Addition on new item", "[cmds][add]")
81 80 cfg.set("!ids.total", "64"); cfg.set("!ids.total", "64");
82 81 cfg.set("!ids.next", "fYP"); cfg.set("!ids.next", "fYP");
83 82
84 std::ostringstream out;
85 std::ostringstream err;
83 std::ostringstream out, err;
86 84 Tests::setStreams(out, err); Tests::setStreams(out, err);
87 85
88 86 SECTION("Item is added") SECTION("Item is added")
 
... ... TEST_CASE("Completion of first key name on addition", "[cmds][add][completion]")
124 122
125 123 Command *const cmd = Commands::get("add"); Command *const cmd = Commands::get("add");
126 124
127 std::ostringstream out;
128 std::ostringstream err;
125 std::ostringstream out, err;
129 126 Tests::setStreams(out, err); Tests::setStreams(out, err);
130 127
131 128 boost::optional<int> exitCode = cmd->complete(*prj, { "ti" }); boost::optional<int> exitCode = cmd->complete(*prj, { "ti" });
 
... ... TEST_CASE("Completion of first key name on addition", "[cmds][add][completion]")
133 130 REQUIRE(*exitCode == EXIT_SUCCESS); REQUIRE(*exitCode == EXIT_SUCCESS);
134 131
135 132 const std::string expectedOut = const std::string expectedOut =
136 "title:\n"
137 "bug_number:\n";
133 "bug_number:\n"
134 "title:\n";
138 135 REQUIRE(out.str() == expectedOut); REQUIRE(out.str() == expectedOut);
139 136 REQUIRE(err.str() == std::string()); REQUIRE(err.str() == std::string());
140 137 } }
 
... ... TEST_CASE("Completion of next key name on addition", "[cmds][add][completion]")
152 149
153 150 Command *const cmd = Commands::get("add"); Command *const cmd = Commands::get("add");
154 151
155 std::ostringstream out;
156 std::ostringstream err;
152 std::ostringstream out, err;
157 153 Tests::setStreams(out, err); Tests::setStreams(out, err);
158 154
159 155 boost::optional<int> exitCode = cmd->complete(*prj, { "title:", "t", "b" }); boost::optional<int> exitCode = cmd->complete(*prj, { "title:", "t", "b" });
 
... ... TEST_CASE("Completion of a value on addition", "[cmds][add][completion]")
178 174
179 175 Command *const cmd = Commands::get("add"); Command *const cmd = Commands::get("add");
180 176
181 std::ostringstream out;
182 std::ostringstream err;
177 std::ostringstream out, err;
183 178 Tests::setStreams(out, err); Tests::setStreams(out, err);
184 179
185 180 boost::optional<int> exitCode = cmd->complete(*prj, { "title=" }); boost::optional<int> exitCode = cmd->complete(*prj, { "title=" });
File tests/cmds/ConfigCmd.cpp changed (mode: 100644) (index d4bca13..9a8e55f)
... ... TEST_CASE("Config value completion on trailing =", "[cmds][config][completion]")
40 40 Config &cfg = prj->getConfig(false); Config &cfg = prj->getConfig(false);
41 41 cfg.set("ui.ls", "ls-value"); cfg.set("ui.ls", "ls-value");
42 42
43 std::ostringstream out;
44 std::ostringstream err;
43 std::ostringstream out, err;
45 44 Tests::setStreams(out, err); Tests::setStreams(out, err);
46 45
47 46 boost::optional<int> exitCode = cmd->complete(*prj, { "ui.ls=" }); boost::optional<int> exitCode = cmd->complete(*prj, { "ui.ls=" });
 
... ... TEST_CASE("Config completes options", "[cmds][config][completion]")
64 63 Config &cfg = prj->getConfig(false); Config &cfg = prj->getConfig(false);
65 64 cfg.set("ui.ls", "ls-value"); cfg.set("ui.ls", "ls-value");
66 65
67 std::ostringstream out;
68 std::ostringstream err;
66 std::ostringstream out, err;
69 67 Tests::setStreams(out, err); Tests::setStreams(out, err);
70 68
71 69 boost::optional<int> exitCode = cmd->complete(*prj, { "-" }); boost::optional<int> exitCode = cmd->complete(*prj, { "-" });
 
... ... TEST_CASE("Config completes global config", "[cmds][config][completion]")
94 92 Config &cfg = prj->getConfig(false); Config &cfg = prj->getConfig(false);
95 93 cfg.set("ui.ls", "ls-value"); cfg.set("ui.ls", "ls-value");
96 94
97 std::ostringstream out;
98 std::ostringstream err;
95 std::ostringstream out, err;
99 96 Tests::setStreams(out, err); Tests::setStreams(out, err);
100 97
101 98 static char xdg_env[] = "XDG_CONFIG_HOME=tests/data"; static char xdg_env[] = "XDG_CONFIG_HOME=tests/data";
File tests/cmds/ExportCmd.cpp changed (mode: 100644) (index 73ced33..79e591d)
... ... TEST_CASE("Export fails on wrong invocation", "[cmds][export][invocation]")
36 36 std::unique_ptr<Project> prj = Tests::makeProject(); std::unique_ptr<Project> prj = Tests::makeProject();
37 37 Command *const cmd = Commands::get("export"); Command *const cmd = Commands::get("export");
38 38
39 std::ostringstream out;
40 std::ostringstream err;
39 std::ostringstream out, err;
41 40 Tests::setStreams(out, err); Tests::setStreams(out, err);
42 41
43 42 boost::optional<int> exitCode; boost::optional<int> exitCode;
 
... ... TEST_CASE("Completion of export", "[cmds][export][completion]")
67 66
68 67 Command *const cmd = Commands::get("export"); Command *const cmd = Commands::get("export");
69 68
70 std::ostringstream out;
71 std::ostringstream err;
69 std::ostringstream out, err;
72 70 Tests::setStreams(out, err); Tests::setStreams(out, err);
73 71
74 72 boost::optional<int> exitCode; boost::optional<int> exitCode;
 
... ... TEST_CASE("Completion of export", "[cmds][export][completion]")
83 81 { {
84 82 exitCode = cmd->complete(*prj, { "cmd", "ti" }); exitCode = cmd->complete(*prj, { "cmd", "ti" });
85 83 expectedOut = expectedOut =
86 "title\n"
87 "bug_number\n";
84 "bug_number\n"
85 "title\n";
88 86 } }
89 87
90 88 REQUIRE(exitCode); REQUIRE(exitCode);
 
... ... TEST_CASE("Item exporting", "[cmds][export]")
107 105
108 106 Command *const cmd = Commands::get("export"); Command *const cmd = Commands::get("export");
109 107
110 std::ostringstream out;
111 std::ostringstream err;
108 std::ostringstream out, err;
112 109 Tests::setStreams(out, err); Tests::setStreams(out, err);
113 110
114 111 SECTION("No operation run") SECTION("No operation run")
File tests/cmds/RenameCmd.cpp changed (mode: 100644) (index 4bee6b4..aec4574)
... ... TEST_CASE("Rename command successful completion", "[cmds][rename][completion]")
140 140
141 141 Dit dit({ "app" }); Dit dit({ "app" });
142 142
143 std::ostringstream out;
144 std::ostringstream err;
143 std::ostringstream out, err;
145 144 Tests::setStreams(out, err); Tests::setStreams(out, err);
146 145
147 146 boost::optional<int> exitCode; boost::optional<int> exitCode;
 
... ... TEST_CASE("Rename failed successful completion", "[cmds][rename][completion]")
185 184
186 185 Dit dit({ "app" }); Dit dit({ "app" });
187 186
188 std::ostringstream out;
189 std::ostringstream err;
187 std::ostringstream out, err;
190 188 Tests::setStreams(out, err); Tests::setStreams(out, err);
191 189
192 190 boost::optional<int> exitCode = cmd->complete(dit, { "a", "b", "c" }); boost::optional<int> exitCode = cmd->complete(dit, { "a", "b", "c" });
File tests/cmds/SetCmd.cpp changed (mode: 100644) (index 23b99f7..1466a62)
... ... TEST_CASE("Set fails on wrong invocation", "[cmds][set][invocation]")
36 36 std::unique_ptr<Project> prj = Tests::makeProject(); std::unique_ptr<Project> prj = Tests::makeProject();
37 37 Command *const cmd = Commands::get("set"); Command *const cmd = Commands::get("set");
38 38
39 std::ostringstream out;
40 std::ostringstream err;
39 std::ostringstream out, err;
41 40 Tests::setStreams(out, err); Tests::setStreams(out, err);
42 41
43 42 boost::optional<int> exitCode; boost::optional<int> exitCode;
 
... ... TEST_CASE("Set allows external editing", "[cmds][set][integration]")
86 85
87 86 Tests::storeItem(storage, std::move(item)); Tests::storeItem(storage, std::move(item));
88 87
89 std::ostringstream out;
90 std::ostringstream err;
88 std::ostringstream out, err;
91 89 Tests::setStreams(out, err); Tests::setStreams(out, err);
92 90
93 91 static char editor_env[] = "EDITOR=echo new-value >>"; static char editor_env[] = "EDITOR=echo new-value >>";
 
... ... TEST_CASE("Item is changed successfully", "[cmds][set]")
119 117
120 118 Command *const cmd = Commands::get("set"); Command *const cmd = Commands::get("set");
121 119
122 std::ostringstream out;
123 std::ostringstream err;
120 std::ostringstream out, err;
124 121 Tests::setStreams(out, err); Tests::setStreams(out, err);
125 122
126 123 boost::optional<int> exitCode; boost::optional<int> exitCode;
 
... ... TEST_CASE("Completion of id for set", "[cmds][set][completion]")
155 152
156 153 Command *const cmd = Commands::get("set"); Command *const cmd = Commands::get("set");
157 154
158 std::ostringstream out;
159 std::ostringstream err;
155 std::ostringstream out, err;
160 156 Tests::setStreams(out, err); Tests::setStreams(out, err);
161 157
162 158 boost::optional<int> exitCode = cmd->complete(*prj, { "i" }); boost::optional<int> exitCode = cmd->complete(*prj, { "i" });
 
... ... TEST_CASE("Completion of first key name on set", "[cmds][set][completion]")
181 177
182 178 Command *const cmd = Commands::get("set"); Command *const cmd = Commands::get("set");
183 179
184 std::ostringstream out;
185 std::ostringstream err;
180 std::ostringstream out, err;
186 181 Tests::setStreams(out, err); Tests::setStreams(out, err);
187 182
188 183 boost::optional<int> exitCode = cmd->complete(*prj, { "id", "ti" }); boost::optional<int> exitCode = cmd->complete(*prj, { "id", "ti" });
 
... ... TEST_CASE("Completion of first key name on set", "[cmds][set][completion]")
190 185 REQUIRE(*exitCode == EXIT_SUCCESS); REQUIRE(*exitCode == EXIT_SUCCESS);
191 186
192 187 const std::string expectedOut = const std::string expectedOut =
193 "title:\n"
194 "bug_number:\n";
188 "bug_number:\n"
189 "title:\n";
195 190 REQUIRE(out.str() == expectedOut); REQUIRE(out.str() == expectedOut);
196 191 REQUIRE(err.str() == std::string()); REQUIRE(err.str() == std::string());
197 192 } }
 
... ... TEST_CASE("Completion of next key name on set", "[cmds][set][completion]")
209 204
210 205 Command *const cmd = Commands::get("set"); Command *const cmd = Commands::get("set");
211 206
212 std::ostringstream out;
213 std::ostringstream err;
207 std::ostringstream out, err;
214 208 Tests::setStreams(out, err); Tests::setStreams(out, err);
215 209
216 210 boost::optional<int> exitCode = cmd->complete(*prj, boost::optional<int> exitCode = cmd->complete(*prj,
 
... ... TEST_CASE("Completion of a value on set", "[cmds][set][completion]")
236 230
237 231 Command *const cmd = Commands::get("set"); Command *const cmd = Commands::get("set");
238 232
239 std::ostringstream out;
240 std::ostringstream err;
233 std::ostringstream out, err;
241 234 Tests::setStreams(out, err); Tests::setStreams(out, err);
242 235
243 236 boost::optional<int> exitCode = cmd->complete(*prj, { "id", "title=" }); boost::optional<int> exitCode = cmd->complete(*prj, { "id", "title=" });
File tests/cmds/ShowCmd.cpp changed (mode: 100644) (index 8d247c0..bcbbc40)
... ... TEST_CASE("Too few args cause error.", "[cmds][show][args]")
36 36 Command *const cmd = Commands::get("show"); Command *const cmd = Commands::get("show");
37 37 std::unique_ptr<Project> prj = Tests::makeProject(); std::unique_ptr<Project> prj = Tests::makeProject();
38 38
39 std::ostringstream out;
40 std::ostringstream err;
39 std::ostringstream out, err;
41 40 Tests::setStreams(out, err); Tests::setStreams(out, err);
42 41
43 42 boost::optional<int> exitCode = cmd->run(*prj, { }); boost::optional<int> exitCode = cmd->run(*prj, { });
 
... ... TEST_CASE("Values are displayed in alphabetical order by default.",
66 65
67 66 Tests::storeItem(storage, std::move(item)); Tests::storeItem(storage, std::move(item));
68 67
69 std::ostringstream out;
70 std::ostringstream err;
68 std::ostringstream out, err;
71 69 Tests::setStreams(out, err); Tests::setStreams(out, err);
72 70
73 71 boost::optional<int> exitCode = cmd->run(*prj, { "id" }); boost::optional<int> exitCode = cmd->run(*prj, { "id" });
 
... ... TEST_CASE("Values are displayed in specified order.", "[cmds][show][order]")
100 98
101 99 Tests::storeItem(storage, std::move(item)); Tests::storeItem(storage, std::move(item));
102 100
103 std::ostringstream out;
104 std::ostringstream err;
101 std::ostringstream out, err;
105 102 Tests::setStreams(out, err); Tests::setStreams(out, err);
106 103
107 104 boost::optional<int> exitCode = cmd->run(*prj, { "id" }); boost::optional<int> exitCode = cmd->run(*prj, { "id" });
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/dit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/dit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master