A nice thing to have is a general purpose crate that takes in file paths, errors, line numbers and severity, and number of lines of context to highlight.
The librustc_errors crate in rustc is what emits errors. It's currently tied to rust source. The syntex crate extracts it out, but it is no longer maintained.