MeanderingProgrammer / markdown.nvim

Plugin to improve viewing Markdown files in Neovim
MIT License
504 stars 20 forks source link

Links in tables are not concealed when rendering in enabled #40

Closed sergey-tikhonenko closed 1 month ago

sergey-tikhonenko commented 1 month ago

This plug-in great, but looks like, if rendering of tables is enabled, then links in cells are not concealed.

Example document:

# Tables

## with links

| Column1 | Column2 |
| --------| --------|
| Item1.1 | Item2.1 |
| Item1.2 | Item2.2 |

## without links

| Column1 | Column2 |
| --------| ------- |
| Item1.1 | [link1](https://example.org)   |
| Item1.2 | [link2](https://come.other.link)   |

Rendering with table_style = "normal" Screenshot at 2024-06-13 21-11-51 Rendering with table_style = "none" Screenshot at  2024-06-13 21-13-27

Saw at #21 that this possible to do, but there are some difficulties. Didn't quite understand which ones. Is there any chance to get rendering of links in tables implemented or this is postponed for a long time?

MeanderingProgrammer commented 1 month ago

Glad you're liking it!

The main issue is I'm not sure there is a better way to handle tables (at least for me personally) than what's currently implemented.

There are kind of 2 opposing ideas, concealing and consistency.

For tables in particular I like the raw view of them to also line up, which I know not everyone does or cares about. So without rendering when I have a table with links or code blocks I want it to look like this when I'm editing it:

| Column 1           | Column 2                      |
| ------------------ | ----------------------------- |
| Plaint Text Item 1 | [A Link](https://example.com) |
| Plaint Text Item 2 | `Some Inline Code`            |

Naturally if we enable concealing the rendered view is going to look something like:

| Column 1           | Column 2                      |
|--------------------|-------------------------------|
| Plaint Text Item 1 | A Link |
| Plaint Text Item 2 | Some Inline Code            |

You can go the other way around, and have things not line up when editing and account for spaces such that it renders nicely. However over this I prefer having the raw view always, hence the behavior of this plugin.

Am open to suggestions or thoughts you have if there's a way to do both

sergey-tikhonenko commented 1 month ago

Ok, I understand your position, apparently you mainly write content. For me, it's mostly note-taking and writing for memory. So it's ~ 80% reading and looking over notes and ~ 20% authoring of them. The main value of your plug-in is that it helps removing technical noise when viewing notes and makes browsing smoother. Thus, my main mode for tables is alignment of cell width for concealed content.

Since different people have different use cases and this plug-in purpose is about rendering, not about cells alignment. IMHO, it's best to let people align their tables as they wish and only give them the ability to choose how to render tables and cells separately.

I.e. the table_style option remains as is. In addition to this, a cell_mode option with values { 'conceal', 'none' } (or something similar) might be added.

What do you think about?

MeanderingProgrammer commented 1 month ago

It's a good mix, but yeah writing and reading are fairly even so both are important to me.

Using this plugin mainly for reading makes a lot of sense to me.

I think having it be a choice sounds like a good idea. I'll try implementing it in the near future and see how it turns out!

MeanderingProgrammer commented 1 month ago

Should be resolved by: https://github.com/MeanderingProgrammer/markdown.nvim/commit/973a5ac8a0a7e8721576d144af8ba5f95c057689

Can you update your config to use the new cell_style = 'raw' option:

require('render-markdown').setup({
    cell_style = 'raw',
})

LMK if it works!

sergey-tikhonenko commented 1 month ago

It's works for me. Thanks. изображение

One question a little of the topic: Is it possible to use the same highlighting group for rendering tables borders? They seem too bright for me. At least for the table body borders.

See below the original highlighting (with switched off rendering). изображение

Or define some other way to define color highlighting?

MeanderingProgrammer commented 1 month ago

Yeah, you configure the highlight groups for both the body and the header to be whatever you want.

The defaults are:

require('render-markdown').setup({
    highlights = {
        table = {
            head = '@markup.heading',
            row = 'Normal',
        },
    },
})

If you just want to set the body to be the same color as the header you can do:

require('render-markdown').setup({
    highlights = {
        table = {
            row = '@markup.heading',
        },
    },
})
MeanderingProgrammer commented 1 month ago

Quick question, I notice the colons in the delimiter row aren't being handled, kind of forgot about those.

I can patch that and have them be replaced with horizontal bars as well. Or do you prefer seeing that underlying information?

sergey-tikhonenko commented 1 month ago

They don't add any significant noise, but indicate column alignment. I'd prefer to keep this information, since we have no content alignment of columns. If you like, you could replace them with symbols like these: '›', '‹'.

One more off-topic question: have you any plans to handle backslash escaping, like this \$? To be honest, I spent half a day today trying to force backslash symbol (\) concealment, but without any success. Highlighting works , regions defined (with both keepend, concealends), but concealment doesn't work. изображение

MeanderingProgrammer commented 1 month ago

I don't really use them so no preference on keeping or not, will leave it as is.

As of now I don't have plans to handle backslashes. Is this because inline latex blocks and actually using the dollar sign are now indistinguishable, so you need the backslash? Are you just trying to conceal the first character in backslash escapes, meaning the backslash?

sergey-tikhonenko commented 1 month ago

Yes. I tried to solve the following problem: TeX math inline $...$ is too invasive. For the following ordinary sentence (Bananas: $1.34, Apples: $2.35.) markdown parser in NeoVim marks the part betweeen $ (1.34, Apples:) as latex_block. This might be avoided if the first $ symbol will be escaped.

To reduce technical noise I need to hide the backslash symbol \ in the concealed mode. What's why my question.

MeanderingProgrammer commented 1 month ago

I don't think this plugin should handle this.

Setting whether elements are concealed or not belongs in something like treesitter which does this with code blocks / links already. Users can also create custom treesitter queries to set the concealed attribute. Granted I am not sure how to write one for your exact use case.

Still I had a think and updated the custom_handlers feature of this plugin so it can extend the functionality of a builtin language, previously they could only replace: https://github.com/MeanderingProgrammer/markdown.nvim/commit/870426ea7efe3c0494f3673db7b3b4cb26135ded.

To implement the feature you want with this plugin your configuration will end up looking like so:

require('render-markdown').setup({
    custom_handlers = {
        markdown_inline = {
            render = function(namespace, root, buf)
                local query = vim.treesitter.query.parse('markdown_inline', '(backslash_escape) @escape')
                for _, node in query:iter_captures(root, buf) do
                    local start_row, start_col, end_row, _ = node:range()
                    vim.api.nvim_buf_set_extmark(buf, namespace, start_row, start_col, {
                        end_row = end_row,
                        end_col = start_col + 1,
                        conceal = '',
                    })
                end
            end,
            extends = true,
        },
    },
})

Though I do think there is a way to set the concealed attribute by extending the markdown_inline highlights.scm: https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/markdown_inline/highlights.scm with something based on backslash_escape.

sergey-tikhonenko commented 4 weeks ago

Thank you for your efforts. For such a small issue, you have implemented an extension point for custom code.

You are right, the problem must be solved by the highlights machinery. Finally I've coped with this machinery. The recipe was the following: ~/.config/nvim/after/queries/markdown_inline/highlights.scm

;extends

; highlight an escaped symbol
((backslash_escape) @string.escape
  (#offset! @string.escape 0 1 0 0))

; highlight and conceal the backslash symbol
((backslash_escape) @string.escape
  (#offset! @string.escape 0 0 0 -1)
  (#set! conceal ""))

PS. I also noted that concealed html entities like <, > (might be some others) disappear due to the plugin. Looks like this is not what you intended. Plugin disabled: изображение Plugin enabled: изображение

MeanderingProgrammer commented 4 weeks ago

Ah using an offset directive makes sense.

What's the markdown for the HTML section? If < / > symbols are concealed in HTML then I would expect this since concealing is all or nothing at the window level.

sergey-tikhonenko commented 4 weeks ago

This was the following markdown snippet:

-> &gt; &lt; <-

The HTML entities are supported by Markdown directly. Treesitter provides concealment for them in markdown_inline/highlights.scm

Thus my expectations were to see the > and < symbols, rather then nothing.

With default concealment (i.e. without the plugin) the behaviour is as expected. Cursor is in the line: изображение Cursor is out the line: изображение

MeanderingProgrammer commented 4 weeks ago

This is just based on how the different values of conceallevel work. More details in :h 'conceallevel'.

We set it to 3 when rendering by default, the value you want in this case is 2.

Here's the config:

require('render-markdown').setup({
    win_options = {
        conceallevel = { rendered = 2 },
    },
})
sergey-tikhonenko commented 4 weeks ago

Hm, that's interesting. It seems you are right. Thanks for clarification.