folke / noice.nvim

💥 Highly experimental plugin that completely replaces the UI for messages, cmdline and the popupmenu.
Apache License 2.0
4.24k stars 96 forks source link

bug: Invalid character in group name #902

Closed lostl1ght closed 2 months ago

lostl1ght commented 2 months ago

Did you check docs and existing issues?

Neovim version (nvim -v)

0.10.0

Operating system/version

Debian 12

Describe the bug

Error ``` Error detected while processing nvim_exec2(): Error executing vim.schedule lua callback: .../site/pack/deps/opt/noice.nvim/lua/noice/text/syntax.lua:9: Error executing lua: vim/_editor.lua:0: nvim_exec2(): Vim(syntax):E5248: Invalid character in group name stack traceback: [C]: in function 'nvim_exec2' vim/_editor.lua: in function 'cmd' .../site/pack/deps/opt/noice.nvim/lua/noice/text/syntax.lua:18: in function <.../site/pack/deps/opt/noice.nvim/lua/noice/text/syntax.lua:9> [C]: in function 'nvim_buf_call' .../site/pack/deps/opt/noice.nvim/lua/noice/text/syntax.lua:9: in function 'highlight' ...im/site/pack/deps/opt/noice.nvim/lua/noice/text/init.lua:70: in function 'highlight' ...e/nvim/site/pack/deps/opt/nui.nvim/lua/nui/line/init.lua:58: in function 'highlight' ...e/nvim/site/pack/deps/opt/nui.nvim/lua/nui/line/init.lua:73: in function 'render' ...m/site/pack/deps/opt/noice.nvim/lua/noice/text/block.lua:98: in function 'render' ...site/pack/deps/opt/noice.nvim/lua/noice/lsp/override.lua:52: in function 'stylize_markdown' ...m/site/pack/deps/opt/nvim-cmp/lua/cmp/view/docs_view.lua:64: in function 'open' .../share/nvim/site/pack/deps/opt/nvim-cmp/lua/cmp/view.lua:292: in function 'callback' ...nvim/site/pack/deps/opt/nvim-cmp/lua/cmp/utils/async.lua:138: in function '' vim/_editor.lua: in function stack traceback: [C]: in function 'nvim_buf_call' .../site/pack/deps/opt/noice.nvim/lua/noice/text/syntax.lua:9: in function 'highlight' ...im/site/pack/deps/opt/noice.nvim/lua/noice/text/init.lua:70: in function 'highlight' ...e/nvim/site/pack/deps/opt/nui.nvim/lua/nui/line/init.lua:58: in function 'highlight' ...e/nvim/site/pack/deps/opt/nui.nvim/lua/nui/line/init.lua:73: in function 'render' ...m/site/pack/deps/opt/noice.nvim/lua/noice/text/block.lua:98: in function 'render' ...site/pack/deps/opt/noice.nvim/lua/noice/lsp/override.lua:52: in function 'stylize_markdown' ...m/site/pack/deps/opt/nvim-cmp/lua/cmp/view/docs_view.lua:64: in function 'open' .../share/nvim/site/pack/deps/opt/nvim-cmp/lua/cmp/view.lua:292: in function 'callback' ...nvim/site/pack/deps/opt/nvim-cmp/lua/cmp/utils/async.lua:138: in function '' vim/_editor.lua: in function E21: Cannot make changes, 'modifiable' is off ```

Under certain circumstances completion produces the error above.

Apparently, the value of lang variable in M.highlight() function becomes {toml} for some reason.

I'm able to reliably reproduce the error with these snippets of code:

Code **Cargo.toml** ```toml [package] name = "tom" version = "0.1.0" edition = "2021" [dependencies] convert_case = "0.6.0" ``` **main.rs** ```rust use convert_case; fn main() { println!("Hello, world!"); } ```

Steps To Reproduce

  1. Install 'rust-analyzer'
  2. cargo new tom
  3. Set the contents of Cargo.toml as above
  4. Set the contets of main.rs as above
  5. Wait for 'rust-analyzer' to load
  6. Put the cursor on convert_case and press K
  7. Observe the error

Expected Behavior

No error

Repro

vim.env.LAZY_STDPATH = '.repro'
load(vim.fn.system('curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua'))()

require('lazy.minit').repro({
  spec = {
    { 'MunifTanjim/nui.nvim' },
    { 'folke/noice.nvim', opts = {} },
    -- add any other plugins here
    { 'neovim/nvim-lspconfig' },
  },
})

require('lspconfig').rust_analyzer.setup({})
lostl1ght commented 2 months ago

This hack helps:

-- lua/noice/text/syntax.lua

lang = lang:gsub('[^%w_-]', '')
lostl1ght commented 2 months ago

Upon further inspection, documentation indeed has {toml} in code block section:

Request ```lua vim.lsp.buf_request(0, vim.lsp.protocol.Methods.textDocument_hover, vim.lsp.util.make_position_params(), function(err, result) vim.print(result) end) ```
Response ```lua { contents = { kind = "markdown", value = "\n```rust\nextern crate convert_case\n```\n\n---\n\nConverts to and from various cases.\n\n# Command Line Utility `ccase`\n\nThis library was developed for the purposes of a command line utility for converting\nthe case of strings and filenames. You can check out \n[`ccase` on Github](https://github.com/rutrum/convert-case/tree/master/ccase).\n\n# Rust Library\n\nProvides a [`Case`](https://docs.rs/convert_case/0.6.0/convert_case/enum.Case.html) enum which defines a variety of cases to convert into.\nStrings have implemented the [`Casing`](https://docs.rs/convert_case/0.6.0/convert_case/trait.Casing.html) trait, which adds methods for \ncase conversion.\n\nYou can convert strings into a case using the [`to_case`](https://docs.rs/convert_case/0.6.0/convert_case/trait.Casing.html) method.\n\n```rust\nuse convert_case::{Case, Casing};\n\nassert_eq!(\"Ronnie James Dio\", \"ronnie james dio\".to_case(Case::Title));\nassert_eq!(\"ronnieJamesDio\", \"Ronnie_James_dio\".to_case(Case::Camel));\nassert_eq!(\"Ronnie-James-Dio\", \"RONNIE_JAMES_DIO\".to_case(Case::Train));\n```\n\nBy default, `to_case` will split along a set of default word boundaries, that is\n\n* space characters ` `,\n* underscores `_`,\n* hyphens `-`,\n* changes in capitalization from lowercase to uppercase `aA`,\n* adjacent digits and letters `a1`, `1a`, `A1`, `1A`,\n* and acroynms `AAa` (as in `HTTPRequest`).\n\nFor more accuracy, the `from_case` method splits based on the word boundaries\nof a particular case. For example, splitting from snake case will only use\nunderscores as word boundaries.\n\n```rust\nuse convert_case::{Case, Casing};\n\nassert_eq!(\n \"2020 04 16 My Cat Cali\",\n \"2020-04-16_my_cat_cali\".to_case(Case::Title)\n);\nassert_eq!(\n \"2020-04-16 My Cat Cali\",\n \"2020-04-16_my_cat_cali\".from_case(Case::Snake).to_case(Case::Title)\n);\n```\n\nCase conversion can detect acronyms for camel-like strings. It also ignores any leading, \ntrailing, or duplicate delimiters.\n\n```rust\nuse convert_case::{Case, Casing};\n\nassert_eq!(\"io_stream\", \"IOStream\".to_case(Case::Snake));\nassert_eq!(\"my_json_parser\", \"myJSONParser\".to_case(Case::Snake));\n\nassert_eq!(\"weird_var_name\", \"__weird--var _name-\".to_case(Case::Snake));\n```\n\nIt also works non-ascii characters. However, no inferences on the language itself is made.\nFor instance, the digraph `ij` in Dutch will not be capitalized, because it is represented\nas two distinct Unicode characters. However, `æ` would be capitalized. Accuracy with unicode\ncharacters is done using the `unicode-segmentation` crate, the sole dependency of this crate.\n\n```rust\nuse convert_case::{Case, Casing};\n\nassert_eq!(\"granat-äpfel\", \"GranatÄpfel\".to_case(Case::Kebab));\nassert_eq!(\"Перспектива 24\", \"ПЕРСПЕКТИВА24\".to_case(Case::Title));\n\n// The example from str::to_lowercase documentation\nlet odysseus = \"ὈΔΥΣΣΕΎΣ\";\nassert_eq!(\"ὀδυσσεύς\", odysseus.to_case(Case::Lower));\n```\n\nBy default, characters followed by digits and vice-versa are\nconsidered word boundaries. In addition, any special ASCII characters (besides `_` and `-`)\nare ignored.\n\n```rust\nuse convert_case::{Case, Casing};\n\nassert_eq!(\"e_5150\", \"E5150\".to_case(Case::Snake));\nassert_eq!(\"10,000_days\", \"10,000Days\".to_case(Case::Snake));\nassert_eq!(\"HELLO, WORLD!\", \"Hello, world!\".to_case(Case::Upper));\nassert_eq!(\"One\\ntwo\\nthree\", \"ONE\\nTWO\\nTHREE\".to_case(Case::Title));\n```\n\nYou can also test what case a string is in.\n\n```rust\nuse convert_case::{Case, Casing};\n\nassert!( \"css-class-name\".is_case(Case::Kebab));\nassert!(!\"css-class-name\".is_case(Case::Snake));\nassert!(!\"UPPER_CASE_VAR\".is_case(Case::Snake));\n```\n\n# Note on Accuracy\n\nThe `Casing` methods `from_case` and `to_case` do not fail. Conversion to a case will always\nsucceed. However, the results can still be unexpected. Failure to detect any word boundaries\nfor a particular case means the entire string will be considered a single word.\n\n```rust\nuse convert_case::{Case, Casing};\n\n// Mistakenly parsing using Case::Snake\nassert_eq!(\"My-kebab-var\", \"my-kebab-var\".from_case(Case::Snake).to_case(Case::Title));\n\n// Converts using an unexpected method\nassert_eq!(\"my_kebab_like_variable\", \"myKebab-like-variable\".to_case(Case::Snake));\n```\n\n# Boundary Specificity\n\nIt can be difficult to determine how to split a string into words. That is why this case\nprovides the [`from_case`](https://docs.rs/convert_case/0.6.0/convert_case/trait.Casing.html) functionality, but sometimes that isn't enough\nto meet a specific use case.\n\nTake an identifier has the word `2D`, such as `scale2D`. No exclusive usage of `from_case` will\nbe enough to solve the problem. In this case we can further specify which boundaries to split\nthe string on. `convert_case` provides some patterns for achieving this specificity.\nWe can specify what boundaries we want to split on using the [`Boundary` enum](https://docs.rs/convert_case/0.6.0/convert_case/segmentation/enum.Boundary.html).\n\n```rust\nuse convert_case::{Boundary, Case, Casing};\n\n// Not quite what we want\nassert_eq!(\n \"scale_2_d\",\n \"scale2D\"\n .from_case(Case::Camel)\n .to_case(Case::Snake)\n);\n\n// Remove boundary from Case::Camel\nassert_eq!(\n \"scale_2d\",\n \"scale2D\"\n .from_case(Case::Camel)\n .without_boundaries(&[Boundary::DigitUpper, Boundary::DigitLower])\n .to_case(Case::Snake)\n);\n\n// Write boundaries explicitly\nassert_eq!(\n \"scale_2d\",\n \"scale2D\"\n .with_boundaries(&[Boundary::LowerDigit])\n .to_case(Case::Snake)\n);\n```\n\nThe `Casing` trait provides initial methods, but any subsequent methods that do not resolve\nthe conversion return a [`StateConverter`](https://docs.rs/convert_case/0.6.0/convert_case/struct.StateConverter.html) struct. It contains similar methods as `Casing`.\n\n# Custom Cases\n\nBecause `Case` is an enum, you can't create your own variant for your use case. However\nthe parameters for case conversion have been encapsulated into the [`Converter`](https://docs.rs/convert_case/0.6.0/convert_case/converter/struct.Converter.html) struct\nwhich can be used for specific use cases.\n\nSuppose you wanted to format a word like camel case, where the first word is lower case and the\nrest are capitalized. But you want to include a delimeter like underscore. This case isn't\navailable as a `Case` variant, but you can create it by constructing the parameters of the\n`Converter`.\n\n```rust\nuse convert_case::{Case, Casing, Converter, Pattern};\n\nlet conv = Converter::new()\n .set_pattern(Pattern::Camel)\n .set_delim(\"_\");\n\nassert_eq!(\n \"my_Special_Case\",\n conv.convert(\"My Special Case\")\n)\n```\n\nJust as with the `Casing` trait, you can also manually set the boundaries strings are split \non. You can use any of the [`Pattern`](https://docs.rs/convert_case/0.6.0/convert_case/pattern/enum.Pattern.html) variants available. This even includes [`Pattern::Sentence`](https://docs.rs/convert_case/0.6.0/convert_case/pattern/enum.Pattern.html)\nwhich isn't used in any `Case` variant. You can also set no pattern at all, which will\nmaintain the casing of each letter in the input string. You can also, of course, set any string as your\ndelimeter.\n\nFor more details on how strings are converted, see the docs for [`Converter`](https://docs.rs/convert_case/0.6.0/convert_case/converter/struct.Converter.html).\n\n# Random Feature\n\nTo ensure this library had zero dependencies, randomness was moved to the *random* feature,\nwhich requires the `rand` crate. You can enable this feature by including the\nfollowing in your `Cargo.toml`.\n\n```{toml}\n[dependencies]\nconvert_case = { version = \"^0.3.0\", features = [\"random\"] }\n```\n\nThis will add two additional cases: Random and PseudoRandom. You can read about their\nconstruction in the [Case enum](https://docs.rs/convert_case/0.6.0/convert_case/enum.Case.html)." }, range = { ["end"] = { character = 16, line = 0 }, start = { character = 4, line = 0 } } } ```

It's almost at the end there:

\n\n```{toml}\n[dependencies]\nconvert_case = { version = \"^0.3.0\", features = [\"random\"] }\n```