sainnhe / gruvbox-material

Gruvbox with Material Palette
MIT License
1.83k stars 164 forks source link

Differentiate parameters from variables and builtin variables when LSP is enabled #174

Closed noomly closed 1 year ago

noomly commented 1 year ago

Since neovim's new version (0.9.0), semantic highlighting has been enabled by default. This makes colorschemes able to, for example, visually differentiate variables from function parameters. Gruvbox-material technically makes use of this feature since https://github.com/sainnhe/gruvbox-material/commit/95b85a3282a5c8c7fe70a6907d29911032b92f7c although both @lsp.type.variable and @lsp.type.parameter are eventually linked to the same group Fg which makes them white.

It also seems that builtins (console in typescript for example) are now the same colors as variables even though they used to be in different colors without semantic highlighting enabled. However, I'm not sure something can be done about this as as I don't see any "builtin" option listed here https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens...

Anyway, it would be nice to better take advantage of this new feature to make parameters and variables looks different. There are maybe other instances that could be improved, although I haven't noticed any other than variables vs parameters yet.

antoineco commented 1 year ago

The impact of using LSP semantic tokens on syntax highlighting very much varies depending on the LSP server.

Parenthesis: Here is my analysis, and conclusion, after experimenting with the feature in Lua and Go: https://github.com/sainnhe/everforest/issues/119

For the record, Tree-sitter can differentiate between a variable and parameter pretty well, without LSP semantic tokens. The reasons for not highlighting parameters differently from variables is mostly aesthetics. We could of course have a colorscheme with as many colors as Tree-sitter tokens and LSP semantic tokens, but that would result in a "box of crayons" effect (sometimes called "clown theme"). Color schemes have to adopt a semantics which make sense while remaining unintrusive to the user, meaning not abusing accent colors, etc.

I think changing @lsp.type.parameter to another color should be relatively unintrusive for other highlight groups. However, it could be very intrusive on screen, therefore the theme's palette defines variables and parameters as being the same color: https://github.com/sainnhe/everforest/blob/master/palette.md. (This is for Everforest, but the semantics largely apply to Gruvbox Material.)

If you have an example of language where highlighting functions parameters

  1. doesn't cause (too much) overlap with other highlight semantics
  2. isn't visually agressive

by any mean feel free to try out for a period of time with an autogroup like the one below, and report here with a suggestion. We'll be happy to include it if it feel reasonnable.

local grpid = vim.api.nvim_create_augroup('custom_highlights_gruvboxmaterial', {})
vim.api.nvim_create_autocmd('ColorScheme', {
  group = grpid,
  pattern = 'gruvbox-material',
  callback = function()
    -- functions parameters
    vim.api.nvim_set_hl(0, '@lsp.type.parameter', { link = 'Blue' })
  end
})

Examples

Lua, the parameters are now blue inside the function and in annotations, notice how the vars and their attributes are now the same color:

image image

Go, more subtle than Lua in the example, but the parameters are also blue inside the function, so the same pattern will appear when we access parameters' attributes:

image image

antoineco commented 1 year ago

To your question about TypeScript, here are the highlight groups being applied both in Tree-sitter and LSP semantic highlights:

image

@lsp.typemod.variable.defaultLibrary maps quite nicely to Tree-sitter's @variable.builtin. I actually highlighted that exact group for the Go language in Everforest: https://github.com/sainnhe/everforest/commit/4e9104ad9628cd9c95617c5e4c1a99402eb67833. We could do the same for JavaScript and TypeScript.


Example

image image

antoineco commented 1 year ago

I linked the groups for JavaScript and TypeScript, but I'll leave @lsp.type.parameter as it is because I have a feeling that overriding it with an accent color will be too controversial.

As for all colorscheme customizations, using an augroup is the preferred way to override default highlight groups if desired.