1

I have python examples in a markdown file in a code fence (e.g. when I convert a jupyter notebook into a markdown document). These snippets sometimes have code comments in them starting with #. The markdown folder, however, recognizes these as headings, so folds them as chapters. This, in turn, messes up the document outline.

How can I prevent this?

| improve this question | | | | |
2

It would be really hard to do reliably.

Basically, if you brave enough, check what current markdown plugin uses for folding and try to rewrite it:

  1. :set foldmethod? to find out if it is expr or not
  2. :set foldexpr? to find out what is the function name expr uses
  3. create your own MarkdownFold() function (or whatever name is 2. showed)

So you would end up copy pasting existing MarkdownFold function to your vimrc and start hacking.

function! MarkdownFold()
  let line = getline(v:lnum)

  ...
  ...

  return "="
endfunction

In the end you will have to analyze if current line is python comment and skip it. Which would be the trickiest part. Is your line in a code block? How far backwards you should scan for code block beginning? Etc.

And depending on your implementation your vim would probably become slow for markdown files.

PS, I have tried to do similar thing for my implementation of folding for asciidoctor files, but couldn't do anything good, so I decided not to bother with it. Anyway == is far less common than ## :)

UPDATE

So it just came to my mind that it is possible to get syntax group of a current line. And you should be able to check if it is a markdown header or not. I have implemented it for my asciidoctor plugin and did this also for a markdown (I already have it in my after/ftplugin folder to tune it for markdown frontmatter).

Here is the result:

function! MarkdownFold()
  let line = getline(v:lnum)

  " Regular headers
  let depth = match(line, '\(^#\+\)\@<=\( .*$\)\@=')
  if depth > 0
    " check syntax, it should be markdownH1-6
    let syncode = synstack(v:lnum, 1)
    if len(syncode) > 0 && synIDattr(syncode[0], 'name') =~ 'markdownH[1-6]'
        return ">" . depth
    endif
  endif

  " Setext style headings
  let prevline = getline(v:lnum - 1)
  let nextline = getline(v:lnum + 1)
  if (line =~ '^.\+$') && (nextline =~ '^=\+$') && (prevline =~ '^\s*$')
    return ">1"
  endif

  if (line =~ '^.\+$') && (nextline =~ '^-\+$') && (prevline =~ '^\s*$')
    return ">2"
  endif

  " frontmatter
  if (v:lnum == 1) && (line =~ '^----*$')
      return ">1"
  endif

  return "="
endfunction

enter image description here

| improve this answer | | | | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.