This actually builds up after my previous question:
How to provider user with autocomplete suggestions for given boost::spirit grammar?
To Sehe solution I've added annotater for syntax coloring:
First by adopting hints
structure to this (note: ast_type_t
is an enum class
):
template <class ast_type_t> class hints_t
{
struct by_location_t
{
template<typename T, typename U> bool operator()(T const& a, U const& b) const
{
if(loc(a) == loc(b)) return size(a) > size(b);
return loc(a) < loc(b);
}
private:
static location_t loc(source_t const& s)
{
return s.begin();
}
static location_t loc(location_t const& l)
{
return l;
}
static std::size_t size(source_t const& s)
{
return s.end() - s.begin();
}
static std::size_t size(location_t const& s)
{
return 1;
}
};
public:
std::map<location_t, std::string, by_location_t> incomplete;
std::map<source_t, candidates_t, by_location_t> suggestions;
std::map<source_t, ast_type_t, by_location_t> annotations;
operator bool() const
{
return incomplete.size() || suggestions.size();
}
};
Then by adding annotater itself:
struct annotation_t
{
typedef void result_type;
hints_t* hints;
template<typename first_t, typename last_t>
void operator()(ast::type_t id, first_t f, last_t l) const
{
if (hints)
{
source_t loc(&*f, l - f);
if (loc.size() > 0)
{
auto inserted = hints->annotations.emplace(loc, id);
if (!inserted.second) inserted.first->second = id;
}
}
}
};
::boost::phoenix::function<annotation_t> annotate{annotation_t{hints}};
And lastly by including them in parser itself:
on_success(lang_text, annotate(ast::type_t::lang_text, ::boost::spirit::qi::_1, ::boost::spirit::qi::_3));
This generally works, but I've hit another road blocker; I need autocompletion that actually can build dynamic list of suggestion based on previously parsed values; The best example would be to use foo.member1.member2
from sehe comment on original question. I do not allow member definition inside parsed text itself, they are always provided by external C++ class;
An example of such C++ class:
class member_provider_t
{
public: virtual ~member_provider_t() {}
public: virtual std::vector<std::string> possible_identifiers_after(...) = 0;
}
Now it get tricky - I would like to pass entire parse result (up to this point) into to ...
placeholder (in form of parsed ast). Example: parsing uri of custom schema:
schema://main.menu.screen/show/ab... (suggest: about*)
(*about
- This depends on entire url parsed so far)
If this is not possible, then any other way to pass as many parsed parts as possible to provider function would suit me.