Back to Fresh

Language & Syntax Highlighting Support Review

docs/internal/language-support-review.md

0.3.221.2 KB
Original Source

Language & Syntax Highlighting Support Review

How Syntax Highlighting Works in Fresh

Fresh keeps every known language in a unified grammar catalog (GrammarRegistry::catalog). Each entry records which engines can serve it:

  • Syntect (TextMate/Sublime grammars) — the primary highlighting engine, covering ~115 built-in and embedded grammars.
  • Tree-sitter — used for structural features (auto-indent, bracket matching, semantic highlighting) and as a highlighting fallback for the ~18 languages it supports. Notably, TypeScript is tree-sitter-only — syntect ships no grammar for it.

A single catalog entry may be served by syntect, tree-sitter, or both.

Lookup API

All resolution happens through three methods on GrammarRegistry:

  • find_by_path(&Path) — filename → glob → extension, honouring user [languages] config (filenames, globs, extensions all merged into the catalog via apply_language_config).
  • find_by_name(&str) — display name, language id, short alias, all case-insensitive, single HashMap lookup.
  • find_by_extension(&str) — just the extension index.

Each returns Option<&GrammarEntry>. HighlightEngine::from_entry and DetectedLanguage::from_entry consume those entries. The "prefer syntect, else tree-sitter, else None" fallback lives in exactly one place: HighlightEngine::from_entry.

Adding a language

  • New syntect grammar — drop a .sublime-syntax into crates/fresh-editor/src/grammars/ and register it in GrammarRegistry::add_embedded_grammars. The catalog picks it up on the next rebuild.
  • New tree-sitter language — add a variant to fresh_languages::Language (extensions, display_name, highlight_config). The catalog auto-creates a tree-sitter-only entry if no syntect grammar matches.
  • User config mapping — edit ~/.config/fresh/config.toml [languages] section. Extensions, exact filenames, and globs all merge through apply_language_config into the catalog.

Summary

This document catalogs all language support requests from GitHub issues, combined with common DevOps/infrastructure languages and file types that developers expect modern editors to handle. It compares against Fresh's current support levels.

Support Level Key

LevelMeaning
Syntect (built-in)Highlighting via syntect's built-in TextMate grammar defaults (~100 languages)
Embedded grammarCustom .sublime-syntax file bundled with Fresh (better/specialized highlighting)
Tree-sitterStructural features: auto-indent, bracket matching, semantic highlighting; fallback syntax highlighting
LSP configBuilt-in LSP server configuration in config.example.json
NoneNo current support

Languages Requested in GitHub Issues

LanguageIssue(s)StatusCurrent SupportWhat's Missing
Dart#1252OpenSyntect (basic)LSP config (dart analyze --lsp)
KDL#1266OpenNoneTextMate grammar (.sublime-syntax)
Hyprlang#1266OpenNoneTextMate grammar (.sublime-syntax)
Nushell#1031OpenNoneTextMate grammar, LSP config (nu --lsp)
Solidity#857ClosedNoneTextMate grammar, LSP config (solc --lsp)
Deno (TS variant)#1191OpenTypeScript supportedDeno LSP auto-detection (deno.json presence)
LaTeX#807Closed/AddedSyntect + LSP configDone (highlighting via syntect)
Zig#737Closed/AddedEmbedded grammar + LSPDone
Bash/Zsh configs#383Closed/AddedTree-sitter + SyntectDone
Config file fallback#1219Added (v0.2.18)fallback config fieldSet "fallback": {"grammar": "bash", "comment_prefix": "#"} in config. See Configuration docs.

Common DevOps / Infrastructure Languages & Files

Language / File TypeFile Extensions / NamesCurrent SupportRecommendation
DockerfileDockerfile, Dockerfile.*, *.dockerfileSyntect + LSP configAdequate (highlighting works)
Docker Composedocker-compose.yml, compose.ymlYAML (Syntect)Adequate (YAML grammar)
MakefileMakefile, *.mk, GNUmakefileSyntect + LSP configAdequate (highlighting works)
CMakeCMakeLists.txt, *.cmakeSyntectAdd LSP config (cmake-language-server)
Terraform / HCL*.tf, *.tfvars, *.hclNoneAdd TextMate grammar + LSP config (terraform-ls)
Helm templates*.tpl (in chart dirs)NoneAdd Go template grammar
Nix*.nix, flake.nixSyntectAdd LSP config (nil/nixd)
Shell (POSIX)*.sh, *.bash, *.zshSyntect + Tree-sitter + LSPDone
PowerShell*.ps1, *.psm1, *.psd1SyntectAdd LSP config (powershell-editor-services)
YAML*.yml, *.yamlSyntect + LSP configAdequate (highlighting works)
TOML*.tomlEmbedded grammar + LSPAdequate
JSON / JSONC*.json, *.jsoncSyntect + Tree-sitter + LSPDone
XML*.xml, *.xsl, *.xsd, *.svgSyntectAdequate; optionally add LSP config
INI / CONF*.ini, *.conf, *.cfg, *.envSyntect (INI)Add .env grammar
Protobuf*.protoNoneAdd TextMate grammar + LSP config (buf-language-server)
GraphQL*.graphql, *.gqlNoneAdd TextMate grammar + LSP config (graphql-lsp)
SQL*.sqlSyntectAdd LSP config (sqls)

Common Programming Languages (Not Yet Fully Supported)

LanguageFile ExtensionsCurrent SupportRecommendation
Kotlin*.kt, *.ktsSyntectAdd LSP config (kotlin-language-server)
Swift*.swiftSyntectAdd LSP config (sourcekit-lsp)
Scala*.scala, *.scSyntectAdd LSP config (metals)
Elixir*.ex, *.exsSyntectAdd LSP config (elixir-ls)
Erlang*.erl, *.hrlSyntectAdd LSP config (erlang_ls)
Haskell*.hs, *.lhsSyntectAdd LSP config (haskell-language-server)
OCaml*.ml, *.mliSyntectAdd LSP config (ocamllsp)
Clojure*.clj, *.cljs, *.cljcSyntectAdd LSP config (clojure-lsp)
R*.r, *.R, *.RmdSyntectAdd LSP config (languageserver)
Julia*.jlNoneAdd TextMate grammar + LSP config (LanguageServer.jl)
Perl*.pl, *.pmSyntectAdd LSP config (Perl::LanguageServer)
Dart*.dartSyntect (basic)Add LSP config (dart analyze --lsp)
V*.vNoneAdd TextMate grammar
Nim*.nim, *.nimsNoneAdd TextMate grammar, LSP config (nimlangserver)
Gleam*.gleamNoneAdd TextMate grammar, LSP config (gleam lsp)

Web Frontend Languages

LanguageFile ExtensionsCurrent SupportRecommendation
Vue*.vueNoneAdd TextMate grammar + LSP config (vue-language-server)
Svelte*.svelteNoneAdd TextMate grammar + LSP config (svelte-language-server)
Astro*.astroNoneAdd TextMate grammar + LSP config (@astrojs/language-server)
SCSS*.scssSyntect (Sass)Add LSP config (vscode-css-languageserver)
LESS*.lessSyntectAdd LSP config (vscode-css-languageserver)
Tailwind CSS(within HTML/JSX)NoneAdd LSP config (tailwindcss-language-server)

Package Manager & Build Tool Config Files

File TypeFile Names / ExtensionsCurrent SupportRecommendation
npmpackage.json, package-lock.json, .npmrcJSON grammarAdequate
pip / PyPIrequirements.txt, pyproject.toml, setup.cfg, PipfileTOML/INI grammarsAdequate
uvuv.toml, uv.lockTOML grammarAdequate
Cargo (Rust)Cargo.toml, Cargo.lockTOML grammarAdequate
Go modulesgo.mod, go.sumNone (specific)Add go.mod grammar
Gradlebuild.gradle, build.gradle.kts, settings.gradleSyntect (Groovy) / None (kts)Add Kotlin script support
Mavenpom.xmlXML grammarAdequate
Bazel / BuckBUILD, BUILD.bazel, WORKSPACE, *.bzlNoneAdd Starlark grammar
Mesonmeson.build, meson_options.txtNoneAdd grammar
Justfilejustfile, Justfile, .justfileNoneAdd grammar (similar to Makefile)
TaskfileTaskfile.yml, Taskfile.yamlYAML grammarAdequate
TiltfileTiltfileNoneAdd Starlark grammar
EarthfileEarthfileNoneAdd Dockerfile-like grammar
PodfilePodfileSyntect (Ruby)Adequate
GemfileGemfile, *.gemspecSyntect (Ruby)Adequate
BrewfileBrewfileNoneMap to Ruby grammar

CI/CD & Orchestration Config Files

File TypeFile Names / ExtensionsCurrent SupportRecommendation
GitHub Actions.github/workflows/*.ymlYAML grammarAdequate
GitLab CI.gitlab-ci.ymlYAML grammarAdequate
JenkinsfileJenkinsfileNoneMap to Groovy grammar
CircleCI.circleci/config.ymlYAML grammarAdequate
Kubernetes manifests*.yaml (k8s)YAML grammarAdequate
Ansible*.yml (playbooks)YAML grammarAdequate
VagrantVagrantfileNoneMap to Ruby grammar

Data & Markup Formats

FormatFile ExtensionsCurrent SupportRecommendation
Markdown*.md, *.mdxSyntect + LSP configAdequate (highlighting works)
reStructuredText*.rstSyntectAdequate
AsciiDoc*.adoc, *.asciidocNoneAdd grammar
CSV / TSV*.csv, *.tsvNoneAdd basic grammar (rainbow CSV)
Diff / Patch*.diff, *.patchSyntectAdequate
Dotenv.env, .env.*NoneAdd grammar
EditorConfig.editorconfigNoneMap to INI grammar
Ignore files.gitignore, .dockerignoreEmbedded grammarDone

Priority Recommendations

High Priority (Frequently Requested + Common DevOps)

#Language/FileWhat to AddReason
1Terraform / HCLTextMate grammar + LSP configVery common in DevOps, zero support
2DartLSP configRequested in #1252, already has syntect highlighting
3NixLSP config (nil/nixd)Already has syntect highlighting, project uses Nix
4Vue / SvelteTextMate grammar + LSP configVery popular web frameworks, no support at all
5ProtobufTextMate grammar + LSP configCommon in microservices, no support
6GraphQLTextMate grammar + LSP configCommon in web APIs, no support
7KotlinLSP configAlready has syntect highlighting, major language
8SQLLSP config (sqls)Already has syntect highlighting, very common
9CMakeLSP configAlready has syntect highlighting, common build system
10PowerShellLSP configAlready has syntect highlighting, common on Windows

Medium Priority (Requested in Issues)

#Language/FileReason
11KDLRequested in #1266
12HyprlangRequested in #1266, niche but passionate users
13NushellRequested in #1031
14SolidityRequested in #857
15Deno LSP detectionRequested in #1191
16Config file fallbackRequested in #1219, broad impact

Lower Priority (Nice to Have)

#Language/FileReason
17Starlark (Bazel/Tiltfile/Buck)Niche but useful
18JustfileGrowing popularity
19GleamNew but growing
20NimSmall community
21AstroWeb framework
22DotenvSimple but useful
23go.modSmall grammar
24MesonBuild system

Validated Syntax Highlighting Results (tmux capture-pane -e)

Tested by opening each file in Fresh via tmux, capturing the terminal output with ANSI escape codes (tmux capture-pane -e -p), and checking for syntax-colored tokens (colors beyond default text white/gray).

WORKING - Full syntax highlighting (55 files)

FileDetected SyntaxEngineColors
hello.rsRusttree-sitter4 (keywords, strings, functions, types)
hello.pyPythontree-sitter5
hello.jsJavaScripttree-sitter4
hello.tstypescripttree-sitter6
hello.tsxtypescripttree-sitter6
hello.jsxJavaScriptsyntect6
hello.mjsJavaScriptsyntect6
hello.goGosyntect5
hello.cCsyntect5
hello.hCsyntect6
hello.cppC++syntect5
hello.ccC++syntect6
hello.hppC++syntect6
hello.csC#syntect4
hello.javaJavasyntect4
hello.phpPHPsyntect5
hello.rbRubysyntect4
hello.luaLuasyntect5
hello.shBourne Again Shellsyntect4
hello.bashBourne Again Shellsyntect4
hello.zshBourne Again Shellsyntect3
dot_bashrcBourne Again Shellsyntect4
dot_profileBourne Again Shellsyntect4
hello.jsonJSONtree-sitter3
hello.htmlHTMLsyntect3
hello.cssCSSsyntect3
hello.pyPythonsyntect5
hello.pyiPythonsyntect5
hello.tomlTOMLsyntect (embedded)4
hello.zigZigsyntect (embedded)6
hello.odinOdinsyntect (embedded)6
hello.typTypstsyntect (embedded)5
hello.gitconfigGit Configsyntect (embedded)3
hello.yamlYAMLsyntect3
docker-compose.ymlYAMLsyntect3
hello.xmlXMLsyntect4
hello.mdMarkdownsyntect5
hello.sqlSQLsyntect6
hello.texLaTeXsyntect5
hello.rRsyntect5
hello.scalaScalasyntect4
hello.hsHaskellsyntect6
hello.cljClojuresyntect6
hello.erlErlangsyntect6
hello.mlOCamlsyntect6
hello.plPerlsyntect6
hello.lispLispsyntect6
hello.dDsyntect6
hello.batBatch Filesyntect4
MakefileMakefilesyntect5
GNUmakefileMakefilesyntect5
hello.mkMakefilesyntect5
GemfileRubysyntect4
RakefileRubysyntect6
VagrantfileRubysyntect6

PARTIAL - Detected but minimal/no highlighting colors (4 files)

FileDetected SyntaxIssue
hello.gitignoreGitignoreOnly 2 highlight colors (comment green + path gray)
hello.diffDiffSyntax detected but 0 highlight colors (scope-to-category mapping gap)
hello.mtstypescriptTree-sitter detected but no highlighting rendered
hello.vuetextOnly tag bracket color (220/gold)

NOT WORKING - No syntax highlighting (35 files)

FileDetected AsReasonFix Needed
DockerfiledockerfileTree-sitter detects language but no TextMate grammarAdd Dockerfile.sublime-syntax
Dockerfile.devtextNot detected at all (variant filename)Add filename pattern
ContainerfiledockerfileSame as DockerfileAdd Dockerfile.sublime-syntax
CMakeLists.txtPlain TextNo CMake grammar in syntect defaultsAdd CMake.sublime-syntax
hello.kttextNo Kotlin grammar in syntectAdd Kotlin.sublime-syntax
hello.swifttextNo Swift grammar in syntectAdd Swift.sublime-syntax
hello.darttextNo Dart grammar in syntectAdd Dart.sublime-syntax
hello.extextNo Elixir grammar in syntectAdd Elixir.sublime-syntax
hello.fstextNo F# grammar in syntectAdd FSharp.sublime-syntax
hello.nixtextNo Nix grammar in syntectAdd Nix.sublime-syntax
hello.ps1textNo PowerShell grammar in syntectAdd PowerShell.sublime-syntax
hello.scsstextNo SCSS grammar in syntectAdd SCSS.sublime-syntax
hello.lesstextNo LESS grammar in syntectAdd LESS.sublime-syntax
hello.initextNo INI grammar in syntectAdd INI.sublime-syntax
hello.cjstext.cjs not mapped to JavaScriptAdd extension mapping
hello.jltextNo Julia grammar in syntectAdd Julia.sublime-syntax
hello.nimtextNo Nim grammar in syntectAdd Nim.sublime-syntax
hello.gleamtextNo Gleam grammar in syntectAdd Gleam.sublime-syntax
hello.vtextNo V grammar in syntectAdd V.sublime-syntax
hello.soltextNo Solidity grammar in syntectAdd Solidity.sublime-syntax
hello.kdltextNo KDL grammar in syntectAdd KDL.sublime-syntax
hello.nutextNo Nushell grammar in syntectAdd Nushell.sublime-syntax
hello.tftextNo Terraform/HCL grammarAdd HCL.sublime-syntax
hello.prototextNo Protobuf grammar in syntectAdd Protobuf.sublime-syntax
hello.graphqltextNo GraphQL grammar in syntectAdd GraphQL.sublime-syntax
hello.astrotextNo Astro grammar in syntectAdd Astro.sublime-syntax
hello.sveltetextNo Svelte grammar (partial tag color)Add Svelte.sublime-syntax
hello.envtextNo dotenv grammarAdd env.sublime-syntax
hello.editorconfigtextNo editorconfig grammarMap to INI grammar
BUILD.bazeltextNo Starlark grammarAdd Starlark.sublime-syntax
JenkinsfiletextNot mapped to GroovyAdd filename mapping
TiltfiletextNo Starlark grammarAdd Starlark.sublime-syntax
EarthfiletextNo Earthfile grammarAdd Earthfile.sublime-syntax
justfiletextNo Justfile grammarAdd Justfile.sublime-syntax
go.modtextNo go.mod grammarAdd go.mod.sublime-syntax

Bugs Found

  1. hello.diff: Diff grammar IS in syntect and IS detected, but produces zero highlight colors. The scope-to-category mapping in textmate_engine.rs doesn't handle Diff scopes (markup.inserted, markup.deleted, meta.diff.header, punctuation.definition.from-file).

  2. hello.mts: Tree-sitter detects TypeScript but produces no colors. The .mts extension may not be triggering the highlight engine properly despite status bar showing "typescript".

  3. Dockerfile / Containerfile: Tree-sitter detects the language (status bar shows "dockerfile") but there's no TextMate grammar and tree-sitter fallback isn't producing colors.

  4. Jenkinsfile: Syntect has Groovy grammar (with .groovy, .gvy, .gradle extensions) but Jenkinsfile isn't mapped to it.

  5. hello.cjs: JavaScript grammar exists but .cjs extension isn't in its extension list (["js", "htc"]). Same issue for .mjs detection (though it works - may go through tree-sitter JS).


Current Support Summary

  • Syntect defaults (57 syntaxes): Primary highlighting engine. The actual built-in set is MUCH smaller than previously claimed (~57 syntaxes, NOT 100+). Notable absences: Kotlin, Swift, Dart, Elixir, Nix, PowerShell, SCSS, LESS, CMake, Dockerfile, F#, Julia, Nim, INI.
  • Embedded grammars (9): TOML, Odin, Zig, Typst, Git Rebase, Git Commit, Gitignore, Git Config, Git Attributes
  • Tree-sitter (18): Rust, Python, JavaScript, TypeScript, HTML, CSS, C, C++, Go, JSON, Java, C#, PHP, Ruby, Bash, Lua, Pascal, Odin. Used for auto-indent/brackets, and as highlighting fallback (works for TS/TSX, but NOT for Dockerfile).
  • LSP configs (23): Bash, C, C++, C#, CSS, Go, HTML, Java, JavaScript, JSON, LaTeX, Lua, Markdown, PHP, Python, Ruby, Rust, Templ, TOML, TypeScript, Typst, YAML, Zig

What "adding a language" means in practice

NeedActionEffort
Syntax highlighting for a language not in syntect defaultsAdd a .sublime-syntax file to crates/fresh-editor/src/grammars/Medium
LSP support for a language already highlightedAdd server config to config.example.jsonLow
Better indentation/brackets for an existing languageAdd tree-sitter parser + indent queriesHigh
Extension mapping for an existing grammarAdd to file_extensions list or filename_scopesLow

Priority fixes (bugs in existing support)

  1. Fix Diff scope-to-category mapping (markup.inserted/deleted not handled)
  2. Fix .mts tree-sitter highlighting (detected but not rendered)
  3. Add Dockerfile TextMate grammar (tree-sitter detects but can't highlight)
  4. Map Jenkinsfile -> Groovy grammar
  5. Map .cjs -> JavaScript grammar