When handling grammars, fetching and building is done in a thread
pool. Results are communicated over channels and the receiving
channel is closed on first error. This causes subsequent sends to
fail causing a mess in stderr. This ignores all SendErrors causing
only the first error to be printed.
Earlier in the builder we enable C++ (`.cpp(true)`) but only mention
the C compiler in the build failure message. Some grammars that have
C++ external scanners can provoke build failures in this step if a
C++ compiler isn't installed, so mentioning it in the error message
should help out debugging.
This is a bit of a micro-optimization: in the current setup we waste
a thread in the pool for a local grammar only to println! a message
saying we're skipping fetching because it's a local grammar.
This is a rather large refactor that moves most of the code for
loading, fetching, and building grammars into a new helix-loader
module. This works well with the [[grammars]] syntax for
languages.toml defined earlier: we only have to depend on the types
for GrammarConfiguration in helix-loader and can leave all the
[[language]] entries for helix-core.