Add Language detection and dispatch logic#210
Draft
6cdh wants to merge 8 commits intojeapostrophe:masterfrom
Draft
Add Language detection and dispatch logic#2106cdh wants to merge 8 commits intojeapostrophe:masterfrom
6cdh wants to merge 8 commits intojeapostrophe:masterfrom
Conversation
Imported racket-lexer does not return a good meaningful type for some tokens, so add a extra pass to normalize them.
Add doc-lang module for parseing #lang, #reader, and raw module forms, extract language info, and match against a predefined known language list. Fallback to URI suffix based recognization if not found language header.
dannypsnl
reviewed
Apr 25, 2026
- Stop pass indenter to services, it's not used by them - Improve dignostics module - Skip formatting for not-Sexp languages - Move indenter lookup into doc-lang.rkt
And make test not require rhombus installed.
Also removed get-indenter test because it returns false now for all builtin languages.
dannypsnl
reviewed
Apr 26, 2026
| Returns a list of @racket[TextEdit] values to apply, or @racket[#f] if no | ||
| indenter is available (e.g., the document lacks a @tt{#lang} line). | ||
| Returns a list of @racket[TextEdit] values to apply. For documents without | ||
| a recognized s-expression language, returns an empty list. |
Collaborator
There was a problem hiding this comment.
Do we only handle s-expression language here? There are actually many non s-expression languages in Racket system.
Collaborator
Author
There was a problem hiding this comment.
This is a problem. We shouldn't route non-Sexp languages to fixw or other Sexp formatters, while almost all formatters in Racket community are Sexp formatters. So we have to have a guard in format logic.
I'm thinking three methods:
- Specialize for common non-Sexp languages when we have dedicated formatters for them, for example, scribble or rhombus.
- Use the language provided indenter if it provides
'drracket:indentationprocedure. But this indent procedure requires acolor-textoid<%>argument. Current text buffer does not implementcolor-textoid<%>interface. And it requires some effort to implement it. My attempt shows it needs another 300 lines of complex code. This is still a good option, if we want best support for various languages. Our old handwritten formatter used this method, but used the text buffer that defined inframeworkthat is a GUI library. - Use method 2, but in a external formatter, so this external formatter becomes a universal indenter for Racket ecosystem. And we just route non S-exp languages to it. We don't route all languages to it because a Sexp formatter usually does more than just indent.
Collaborator
Author
There was a problem hiding this comment.
I'd like to delay the decision, and avoid to make a color-textoid<%> interface implementation here. AI can do it quickly, but review would be pain.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The current LSP server's behavior for non-Racket or non-Lisp languages is unclear. For example, we don't have clear idea what features support what languages. Almost all features target to Racket, but services that operate on expanded code seems more general purpose.
This PR adds language detection and dispatch logic depends on language. And define clear behavior of features for various languages.
TODO:
#lang ...(including#lang reader ...),#reader ...,(module id mod-path ...), if no languag header found, fallback to guess language from special file suffix, like.rhm,.scrbl#;The language header detection is based on the Sexp token tree parser. I didn't use regex because comments can appear before language line, especially Sexp comment. So it builds a small Sexp token tree before the language header. Then recognize the language, if it's in the predefined list, and is a Sexp language, the token tree parser will continue to parse the rest code (continue parsing logic not yet implemented). For non-Sexp language, its Sexp token tree only contains the code before and including the language header. If the language header is missing, the Sexp token tree parser can potentially read the whole document.
The token tree parser can also support non Sexp, but not yet. Because each non Sexp language can have its special syntax, and make the implementation more complex.