marshallward / vim-restructuredtext

Syntax file for reStructuredText on Vim.
26 stars 12 forks source link

rst code directive must be followed by empty line #28

Open anntzer opened 6 years ago

anntzer commented 6 years ago
.. code:: python

   print(hello)

is valid rst but

.. code:: python
   print(hello)

is not (as checked per rst2html, as well as the spec: http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#directives "If either arguments and/or options are employed by the directive, a blank line must separate them from the directive content.")

But vim-restructuredtext highlights both blocks in the same manner. It would be mildly helpful if e.g. there was no highlighting in the second case (hinting that something is incorrect).

marshallward commented 6 years ago

I'm looking into this now, and have some idea about the problem, but wanted to raise a related issue. It seems like .. code:: is not being interpreted as a code block, and is instead being treated as an rstExDirective section.

I think the underlying problem still exists, but something else is is also happening with syntax regions being overridden by other more general ones. This may be due to some reordering of definitions which was done to fix other problems.

marshallward commented 6 years ago

Been looking further into this. The problem could be solved by extending the start regex from this

start='::\_s*\n\ze\z(\s\+\)'

to something like this

start='::\s*\n\_s*\n\ze\z(\s\+\)'

There's probably some way to streamline that, it's probably got some redundancy in it.

This would be an improvement, but it would be need to be manually added to all of the region definitions. It would be great to consolidate them into a more general definition that is in one place. I have noticed that inconsistency between the various region definitions have started to appear.

Either way, before moving forward on this, I'm testing out some alternative approaches that look for space prior to the ::, rather than space after the first line of the block, and see if it can solve some of these other indented block issues.

marshallward commented 6 years ago

The following seems to fix a lot of the problems that have been around for a while. (For literal blocks, but should be applicable to code blocks).

syn region  rstLiteralBlock         matchgroup=rstDelimiter
      \ start='^\z(\s*\).*\zs::\n\s*\n' skip='^\s*$' end='^\(\z1\s\+\)\@!'
      \ contains=@NoSpell

It grabs the whitespace prior to the first line and then uses it to check for a line with this space or less (not\z1\s\+). This differs from the current approach, which looks for the first blank line and grabs its leading whitespace. This new method seems to address a lot of the reported issues (including this one) and many others that I've also found.

The only problem (so far) is that inline highlights, like Emphasis, seem to disable it. For example, this only highlights the emphasis and disables the literal block:

Any *inline* literal breaks the parsing! ::

   This is a valid literal block but is not highlighted (nor is ::)

This may actually not be a problem for code blocks and other directives, since they do not have inline literals.

Anyway just writing down my thoughts before I forget them.

marshallward commented 5 years ago

I've made a change that appears to fix a wide host of problems with literal blocks:

syn region  rstLiteralBlock         matchgroup=rstDelimiter                     
      \ start='\(^\z(\s*\).*\)\@<=::\n\s*\n' skip='^\s*$' end='^\(\z1\s\+\)\@!' 
      \ contains=@NoSpell                                                       

The main change is using \z( ... \) to track whitespace and replace \zs with a lookbehind \@<= which preserves syntax up to the :: directive marker.

Along with this, it appears to fix the line issue by requiring ::\n\s*\n at the start.

As far as I can see, it seems to fix every issue that I can find.

I think this technique can be applied to code blocks and other directives.

Edit: Of course I naturally forgot to say that this is thanks to user Rich at the Vi Stack Exchange: https://vi.stackexchange.com/questions/18732/syntax-highlighting-a-region-inside-the-start-match-of-another-region/18976?noredirect=1#comment32962_18976

anntzer commented 5 years ago

thanks for figuring this out :)