I'm writing C++ and running into problems with font-lock-mode often getting confused by more obscure language features (e.g., operator""_ud). I also find that indentation doesn't work very well with less common C++ idioms (e.g., when the body of a function is a try/catch block, or after a multi-line requires clause). I've tried the default cc-mode, the latest version from sourceforge, and also modern-cpp-font-lock, but all of them have annoying quirks.

My question: is there any way to rely on LSP for syntax highlighting and/or indentation? I've tried both eglot and lsp-mode, and both work well for xref. (I've also used rtags, which, while not LSP, is a similar idea and also works well for navigating source.) I do see that lsp-mode allows a bunch of faces to be customized, but these don't seem to affect the normal syntax highlighting. Are there any packages that leverage LSP (or some other language-aware back-end like rtags) to improve basic editing beyond navigation and completion?

1 Answer 1


Not really. LSP has a defined set of messages that can be sent back and forth between the editor and the compiler/language environment, and none of them have anything to do with syntax highlighting or presentation. Indentation is not a focus either, although you can ask the compiler to reformat the whole file if it supports that.

What usually happens is that someone gets so annoyed at the quirks and limitations of the modes they are using that they are motivated to fix them. Having done so, they send the patch to the emacs-devel mailing list to be included in the next release.

  • But can't the LSP messages tell you what is a function definition? One of the things I want is for my function definitions to be left-justified, and this seems to get messed up by certain requires clauses. Also, if a symbol is defined in a certain place, then clearly that shouldn't be in the middle of a string, so couldn't emacs stop, say, highlighting the entire source file as though it is a giant raw string when it isn't? Commented Jun 27, 2022 at 3:13
  • Kinda. You can send a message with a filename and a byte offset asking for the location of the definition of the symbol at that point. If it knows the location, it sends back a filename and byte offset pointing to the definition.
    – db48x
    Commented Jun 27, 2022 at 3:33
  • But I can also swap between a definition and a declaration, right? So it must also know when I'm on a definition to send me to the declaration, no? But you are saying there is no semantic information (like you are defining a function rather than a variable)? Commented Jun 27, 2022 at 3:35
  • You can see the protocol definition here: microsoft.github.io/language-server-protocol/specifications/lsp/… Notice that the editor can send the message textDocument/declaration which is defined as extending TextDocumentPositionParams, so it encodes a filename and byte offset. The response is either a Location, an array of Location, or a LocationLink. Those encode byte ranges within a file, but they don’t tell the editor anything about what is in that range. Usually it is the same identifier, but now as part of the declaration.
    – db48x
    Commented Jun 27, 2022 at 4:01
  • But critically, there is no real information about the identifier itself, or the declaration. The LSP has another message for finding the definition of a symbol, but not all languages have definitions separate from declarations, so often the server returns the same location or list of locations for both queries. There is no information here about the presentation of the document, or about the semantics of the language, just the specific actions desired by one particular IDE. You could in principle scan the document making these queries and building a map, but it would be slow and imprecise.
    – db48x
    Commented Jun 27, 2022 at 4:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.