Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace multiple space into single space on markdown text in hover #844

Conversation

msivasubramaniaan
Copy link
Contributor

Signed-off-by: msivasubramaniaan msivasub@redhat.com

What does this PR do?

This PR shows the description without escape sequence char even description has indentation on hover

What issues does this PR fix or reference?

redhat-developer/vscode-yaml#886

Is it tested? How?

Yes. Added UT

Signed-off-by: msivasubramaniaan <msivasub@redhat.com>
@coveralls
Copy link

coveralls commented Feb 13, 2023

Coverage Status

Coverage: 83.248% (+0.005%) from 83.243% when pulling d0f43fc on 886-yaml-underscore-being-escaped-in-description-attribute-when-hovering-over-an-attribute into ba7452e on main.

@fabiodouek
Copy link

fabiodouek commented Feb 14, 2023

Hi, thanks a lot for looking into this issue.
I had a quick look into this PR. It seems that the adopted solution is to replace multiple spaces by a single space, which in fact is a workaround to the issue.
However, in my view, spaces should be preserved. In my specific case, in the json schema, the description attribute has python code snippets and json snippets. If the spaces are not preserved, the code/json will be unreadable.
Could we preserve the spaces and address the backslash issue?

Thanks,
Fabio.

@msivasubramaniaan
Copy link
Contributor Author

msivasubramaniaan commented Feb 16, 2023

Hi, thanks a lot for looking into this issue. I had a quick look into this PR. It seems that the adopted solution is to replace multiple spaces by a single space, which in fact is a workaround to the issue. However, in my view, spaces should be preserved. In my specific case, in the json schema, the description attribute has python code snippets and json snippets. If the spaces are not preserved, the code/json will be unreadable. Could we preserve the spaces and address the backslash issue?

Thanks, Fabio.

Thanks for your response. I will try to preserve the space from string

@fabiodouek
Copy link

Hi, thanks a lot for looking into this issue. I had a quick look into this PR. It seems that the adopted solution is to replace multiple spaces by a single space, which in fact is a workaround to the issue. However, in my view, spaces should be preserved. In my specific case, in the json schema, the description attribute has python code snippets and json snippets. If the spaces are not preserved, the code/json will be unreadable. Could we preserve the spaces and address the backslash issue?
Thanks, Fabio.

Thanks for your response. I will try to preserve the space from string

Thanks a lot. Please let me know how it goes, Hopefully the spaces can be preserved, otherwise it would have a big impact for our users.

Signed-off-by: msivasubramaniaan <msivasub@redhat.com>
@msivasubramaniaan
Copy link
Contributor Author

Hi, thanks a lot for looking into this issue. I had a quick look into this PR. It seems that the adopted solution is to replace multiple spaces by a single space, which in fact is a workaround to the issue. However, in my view, spaces should be preserved. In my specific case, in the json schema, the description attribute has python code snippets and json snippets. If the spaces are not preserved, the code/json will be unreadable. Could we preserve the spaces and address the backslash issue?
Thanks, Fabio.

Thanks for your response. I will try to preserve the space from string

Thanks a lot. Please let me know how it goes, Hopefully the spaces can be preserved, otherwise it would have a big impact for our users.

Hello @fabiodouek,

As I am preserving the space from string. Please refer the attachment
image

…tion-attribute-when-hovering-over-an-attribute
Signed-off-by: msivasubramaniaan <msivasub@redhat.com>
@fabiodouek
Copy link

msivasubramaniaan

Hi @msivasubramaniaan , that's great, thanks a lot for that.
No pressure, but do you know roughly when this fix will be released?

Thanks,
Fabio.

@msivasubramaniaan
Copy link
Contributor Author

Hello @fabiodouek

You can expect the release 1st week of March. The pre-release by end of next week.

…tion-attribute-when-hovering-over-an-attribute
@rgrunber
Copy link
Member

rgrunber commented Feb 23, 2023

I don't think this is the right approach. The language server is behaving exactly per the spec. The problem is with the client not being able to handle the response.

The language server returns a { contents: MarkupContent, range: Range } which is fine. The VS Code client expects a { contents: Array<MarkdownString | MarkedString>, range: Range } .

https://github.com/microsoft/vscode-languageserver-node/blob/release/client/7.0.0/client/src/common/protocolConverter.ts#L361 is probably what gets called to convert our hover LS response into a VS Code hover so I think we just need to figure out what's going wrong there.

FWIW, I see that vscode-java properly deals with the hover and doesn't unescape the underscores.

msivasubramaniaan and others added 2 commits February 27, 2023 15:16
…tion-attribute-when-hovering-over-an-attribute
Signed-off-by: msivasubramaniaan <msivasub@redhat.com>
@@ -10,7 +10,8 @@
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/out/server/**/*.ts"],
"protocol": "inspector",
"trace": true
"trace": true,
"preLaunchTask": "watch typescript",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added pre launch check

@@ -86,9 +88,10 @@ export class YAMLHover {
);

const createHover = (contents: string): Hover => {
const regex = new RegExp(this.indentation, 'g');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rgrunber
Tabs and whitespace have a special meaning in Markdown. So converted spaces into non braking space as a workaround here.

Copy link
Member

@rgrunber rgrunber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is pretty reasonable, so feel free to merge when ready. If in the future we end up having to do more replacement (beyond just the indentation string), it might be good to create a separate helper method.

@msivasubramaniaan msivasubramaniaan merged commit 47e9259 into main Feb 27, 2023
@msivasubramaniaan msivasubramaniaan deleted the 886-yaml-underscore-being-escaped-in-description-attribute-when-hovering-over-an-attribute branch February 27, 2023 19:49
@polyzen
Copy link
Contributor

polyzen commented Mar 8, 2023

Seems this broke presentation in Neovim:

&emsp;#&emsp;#&emsp;#&emsp;#&emsp; &emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;\&emsp;-&emsp;c&emsp;i&emsp; &emsp;|&emsp;|&emsp; &emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;\&emsp;-&emsp;c&emsp;i&emsp;
&emsp;
&emsp; &emsp;
&emsp;
&emsp;S&emsp;o&emsp;u&emsp;r&emsp;c&emsp;e&emsp;:&emsp; &emsp;[&emsp;c&emsp;i&emsp;.&emsp;j&emsp;s&emsp;o&emsp;n&emsp;]&emsp;(&emsp;h&emsp;t&emsp;t&emsp;p&emsp;s&emsp;:&emsp;/&emsp;/&emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;.&emsp;c&emsp;o&emsp;m&emsp;/&emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;-&emsp;o&emsp;r&emsp;g&emsp;/&emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;/&emsp;-&emsp;/&emsp;r&emsp;a&emsp;w&emsp;/&emsp;m&emsp;a&emsp;s&emsp;t&emsp;e&emsp;r&emsp;/&emsp;a&emsp;p&emsp;p&emsp;/&emsp;a&emsp;s&emsp;s&emsp;e&emsp;t&emsp;s&emsp;/&emsp;j&emsp;a&emsp;v&emsp;a&emsp;s&emsp;c&emsp;r&emsp;i&emsp;p&emsp;t&emsp;s&emsp;/&emsp;e&emsp;d&emsp;i&emsp;t&emsp;o&emsp;r&emsp;/&emsp;s&emsp;c&emsp;h&emsp;e&emsp;m&emsp;a&emsp;/&emsp;c&emsp;i&emsp;.&emsp;j&emsp;s&emsp;o&emsp;n&emsp;)&emsp;

@rgrunber
Copy link
Member

rgrunber commented Mar 8, 2023

@polyzen , I'm guessing Neovim doesn't handle Markdown coming from the hovers ? @msivasubramaniaan , could #837 solve this issue ?

@polyzen
Copy link
Contributor

polyzen commented Mar 8, 2023

https://neovim.io/doc/user/lsp.html#lsp-util
convert_input_to_markdown_lines({input}, {contents})

Not really sure how it works.

@rgrunber
Copy link
Member

rgrunber commented Mar 9, 2023

It mentions : ... Converts any of MarkedString | MarkedString[] | MarkupContent into a list of lines containing valid markdown.

However, if you look at MarkupContent, its kind field determines whether the string value is markdown or plain text. In our case, markdown is always sent back.

.

The other thing to check is if we respect https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#hoverClientCapabilities , which allows the clients to set their preferred format through contentFormat.

@polyzen

This comment was marked as resolved.

@polyzen
Copy link
Contributor

polyzen commented Mar 9, 2023

If value: contents, is used as before, it renders again:
2023-03-08T23:07:30-05:00

@msivasubramaniaan
Copy link
Contributor Author

msivasubramaniaan commented Mar 9, 2023

@polyzen , I'm guessing Neovim doesn't handle Markdown coming from the hovers ? @msivasubramaniaan , could #837 solve this issue ?

Yes @rgrunber I hope #837 will resolve.

@polyzen Can you please share the init.vim for better understanding of plugin which you have used and configuration on the hover things.

@Kasama
Copy link
Contributor

Kasama commented Mar 23, 2023

I'm facing the same issue as polyzen

I'm guessing Neovim doesn't handle Markdown coming from the hovers

Actually neovim handles markdown from hovers and parses it a bit for better stylization. The thing is that it doesn't actually handle HTML escape sequences, so the &emsp; sequences are left as-is.

Consider the following content returned from a textDocument/hover request:

{
  "contents": {
    "kind": "markdown",
    "value": "&emsp;#&emsp;#&emsp;#&emsp;#&emsp; &emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;\\&emsp;-&emsp;c&emsp;i&emsp;\n&emsp;\n&emsp;T&emsp;h&emsp;e&emsp; &emsp;n&emsp;a&emsp;m&emsp;e&emsp; &emsp;o&emsp;f&emsp; &emsp;o&emsp;n&emsp;e&emsp; &emsp;o&emsp;r&emsp; &emsp;m&emsp;o&emsp;r&emsp;e&emsp; &emsp;j&emsp;o&emsp;b&emsp;s&emsp; &emsp;t&emsp;o&emsp; &emsp;i&emsp;n&emsp;h&emsp;e&emsp;r&emsp;i&emsp;t&emsp; &emsp;c&emsp;o&emsp;n&emsp;f&emsp;i&emsp;g&emsp;u&emsp;r&emsp;a&emsp;t&emsp;i&emsp;o&emsp;n&emsp; &emsp;f&emsp;r&emsp;o&emsp;m&emsp;\\&emsp;.&emsp;\n&emsp;\n&emsp;S&emsp;o&emsp;u&emsp;r&emsp;c&emsp;e&emsp;:&emsp; &emsp;[&emsp;c&emsp;i&emsp;.&emsp;j&emsp;s&emsp;o&emsp;n&emsp;]&emsp;(&emsp;h&emsp;t&emsp;t&emsp;p&emsp;s&emsp;:&emsp;/&emsp;/&emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;.&emsp;c&emsp;o&emsp;m&emsp;/&emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;-&emsp;o&emsp;r&emsp;g&emsp;/&emsp;g&emsp;i&emsp;t&emsp;l&emsp;a&emsp;b&emsp;/&emsp;-&emsp;/&emsp;r&emsp;a&emsp;w&emsp;/&emsp;m&emsp;a&emsp;s&emsp;t&emsp;e&emsp;r&emsp;/&emsp;a&emsp;p&emsp;p&emsp;/&emsp;a&emsp;s&emsp;s&emsp;e&emsp;t&emsp;s&emsp;/&emsp;j&emsp;a&emsp;v&emsp;a&emsp;s&emsp;c&emsp;r&emsp;i&emsp;p&emsp;t&emsp;s&emsp;/&emsp;e&emsp;d&emsp;i&emsp;t&emsp;o&emsp;r&emsp;/&emsp;s&emsp;c&emsp;h&emsp;e&emsp;m&emsp;a&emsp;/&emsp;c&emsp;i&emsp;.&emsp;j&emsp;s&emsp;o&emsp;n&emsp;)&emsp;"
  },
  "range": {
    "end": {
      "character": 9,
      "line": 2377
    },
    "start": {
      "character": 2,
      "line": 2377
    }
  }
}

The return itself is weird, containing &emsp; sequences between every character.

In neovim we can treat this by adding a wrapper function to handle the textDocument/hover responses

local function hover_wrapper(err, request, ctx, config)
  local bufnr, winnr = vim.lsp.handlers.hover(err, request, ctx, config)
  local contents = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
  contents = vim.tbl_map(
    function(line)
      return string.gsub(line, "&emsp;", " ")
    end,
    contents
  )
  contents = vim.lsp.util.trim_empty_lines(contents)
  vim.api.nvim_buf_set_option(bufnr, 'modifiable', true)
  vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, contents)
  vim.api.nvim_buf_set_option(bufnr, 'modifiable', false)
  vim.api.nvim_win_set_height(winnr, #contents)
end

vim.lsp.handlers["textDocument/hover"] = hover_wrapper

Even so, by replacing "&emsp;" with a space " ", the content is still pretty weird, with spaces around every character.

image

while replacing it with nothing "" yields the expected result

image


I'm not sure I understand the reasoning behind replacing indentations with &emsp; or why it's causing it to be inserted between every character, but I believe this is a bug with this implementation.

Aside from that, I also think that neovim can benefit from properly handling HTML escape sequences, I'll create an issue there as well about this.

@Kasama
Copy link
Contributor

Kasama commented Mar 23, 2023

Oh yeah, I almost forgot. To reproduce this, here's a minimal init.lua

local settings = {
  yaml = {
    schemas = {
      ["https://gitlab.com/gitlab-org/gitlab/-/raw/master/app/assets/javascripts/editor/schema/ci.json"] = ".gitlab-ci.y*l",
    },
    hover = true,
  }
}

vim.api.nvim_create_autocmd('FileType', {
  pattern = "yaml",
  callback = function(args)
    vim.lsp.start({
      name = 'yamlls',
      cmd = { 'yaml-language-server', '--stdio' },
      root_dir = vim.fn.fnamemodify('./.gitlab-ci.yaml', ':p:h'),
      settings = settings
    })
  end
})

vim.keymap.set('n', '<space>', vim.lsp.buf.hover, {})
  • run cd $(mktemp -d), and copy the contents above to a file called init.lua.

  • create a file called .gitlab-ci.yaml with the following contents

stages:
  - hello
  • run neovim (v0.8.3 in my case) with nvim --noplugin -u init.lua .gitlab-ci.yaml.

  • give it a couple of seconds to spin up yaml-language-server and press <space> with the cursor on top of the stages word.

image

  • you can then apply the patch I showed in my last message to reproduce the "correct" behavior. (change the gsub call to replace "&emsp;" with "")

@EdgeJ
Copy link

EdgeJ commented May 3, 2023

One small tweak to @Kasama's fix that will account for instances where there is no LSP information for a hover (e.g. a yaml file without an accompanying schema):

 local function hover_wrapper(err, request, ctx, config)
  local bufnr, winnr = vim.lsp.handlers.hover(err, request, ctx, config)
  if bufnr then
    local contents = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
    contents = vim.tbl_map(
      function(line)
        return string.gsub(line, "&emsp;", "")
      end,
      contents
    )
    contents = vim.lsp.util.trim_empty_lines(contents)
    vim.api.nvim_buf_set_option(bufnr, 'modifiable', true)
    vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, contents)
    vim.api.nvim_buf_set_option(bufnr, 'modifiable', false)
    vim.api.nvim_win_set_height(winnr, #contents)
  end
end

vim.lsp.handlers["textDocument/hover"] = hover_wrapper

Prevents issues like:

No information available
Error executing vim.schedule lua callback: ../.config/nvim/lsp.lua:82 Expected lua number
stack traceback:
    [C]: in function 'nvim_buf_get_lines'
    .../.config/nvim/lsp.lua:82: in function 'handler'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Underscore being escaped in description attribute when hovering over an attribute
7 participants