Tab completion for paths

There were several problems with the implementation of the completion.
Firstly, a way to propagate completions back from the parser was needed.
That was rather easy to solve with the ParserContext class. Next problem
was prefix matching, or specifically, where will it happen. There are
three possible situations, that can happen, after the input goes through
the parser:

1) The parsing was successful and there is no more input. Then there is
no need for prefix matching and completions are returned as they are:
if there was a valid path "first/second" and the user entered "cd
first/second/". Then the whole input would be parsed and completions
would be the nodes contained within "first/second".

2) The parsing was successful and there is more unparsed input. Then the
completions need to be matched with the input and the common prefix
deleted: if there were valid paths "first/second", "first/service" and
"first/something", and the user inputs "cd first/se", then "se" would be
left unparsed and it would be used as a prefix to change the
completions: they would be "cond" and "rvice".

3) The parsing was successful, there is no more input, but the parsed
input could still be completed. This means I need to know, where exactly
(in the input string) were the completions generated. Example: if there
were valid paths "first/min" and "first/minister", and the user inputs
"cd first/min". Then the parsing is completed successfully, the user
could press enter and execute the command, or generate completions and
"minister" would pop up.

Because there is no way to see the whole input in the AST handlers, the
matching had to be done outside the grammar (that is, in the
completeCommand method). The problem is mainly with the third situation.
Fortunately, I can save the position, where the completions were
generated, and use this information in the completeCommand method. This
solution also has the advantage of less duplicate code since we do all
matching in the same place.

The last problem was when do we exactly create the suggestions. One
option was to create them right after the "node" parser succeeds (in its
AST handler). Unfortunately, that created some problems if the parsing
succeeded but no additional user input was present. To solve this, a
pseudo-parser (a nothing parser) called createSuggestions was created.
This parser generates suggestions in-between nodes, so it's not
dependent on the "node" parser.

Change-Id: I02d9b5d23d7e695bfe7a5e168d9fefe931bc04ef
diff --git a/src/utils.cpp b/src/utils.cpp
index f9eae06..358bc05 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -5,6 +5,8 @@
  * Written by Václav Kubernát <kubervac@fit.cvut.cz>
  *
 */
+#include <boost/algorithm/string/erase.hpp>
+#include <boost/algorithm/string/predicate.hpp>
 #include "utils.hpp"
 
 std::string joinPaths(const std::string& prefix, const std::string& suffix)
@@ -64,3 +66,18 @@
 {
     return fullNodeName(dataPathToSchemaPath(location), pair);
 }
+
+std::set<std::string> filterAndErasePrefix(const std::set<std::string>& set, const std::string_view prefix)
+{
+    std::set<std::string> filtered;
+    std::copy_if(set.begin(), set.end(),
+            std::inserter(filtered, filtered.end()),
+            [prefix] (auto it) { return boost::starts_with(it, prefix); });
+
+    std::set<std::string> withoutPrefix;
+    std::transform(filtered.begin(), filtered.end(),
+            std::inserter(withoutPrefix, withoutPrefix.end()),
+            [prefix] (auto it) { boost::erase_first(it, prefix); return it; });
+    return withoutPrefix;
+}
+