vim9script # Folding for Markdown is sometimes too heavy. # This folding expression is based on some symbols: # - headers # - fenced code blocks # - `
Summary ...
` const EMPTY_STRING = "" const CODEBLOCK_START_PATTERN = '\v^\zs`{3,}\ze' const DETAILS_START_PATTERN = '\v^\$' const DETAILS_END_PATTERN = '\v^\$' const SUMMARY_END_PATTERN = '\v\' const HASH_HEADER_PATTERN = '\v^\zs#{1,}\ze' const EQUAL_H1_PATTERN = '\v^\={3,}$' const HYPHEN_H2_PATTERN = '\v^-{3,}$' export def Expr(): string const line = getline(v:lnum)->trim() if IsCodeblockEnd(line) unlet! w:markdown_fold_codeblock_backticks return "s1" elseif IsInCodeblock(line) return "=" elseif IsNoContent(line) return "=" elseif IsCodeblockStart(line) w:markdown_fold_codeblock_backticks = matchstr(line, CODEBLOCK_START_PATTERN) return "a1" elseif IsSummaryEnd(line) return "a1" elseif IsDetailsEnd(line) unlet! w:markdown_fold_details return "s1" elseif IsDetailsStart(line) w:markdown_fold_details = true return "=" elseif IsHashHeader(line) const hashes = matchstr(line, HASH_HEADER_PATTERN) return ">" .. string(len(hashes)) else const nextline = getline(v:lnum + 1)->trim() if IsEqualH1(nextline) return ">1" elseif IsHyphenH2(nextline) return ">2" else return "=" endif endif enddef def IsNoContent(line: string): bool return line ==# EMPTY_STRING enddef def IsHashHeader(line: string): bool return !!(line =~# HASH_HEADER_PATTERN) enddef def IsEqualH1(line: string): bool return !!(line =~# EQUAL_H1_PATTERN) enddef def IsHyphenH2(line: string): bool return !!(line =~# HYPHEN_H2_PATTERN) enddef def IsCodeblockStart(line: string): bool return !has_key(w:, "markdown_fold_codeblock_backticks") && !!(line =~# CODEBLOCK_START_PATTERN) enddef def IsCodeblockEnd(line: string): bool return !!has_key(w:, "markdown_fold_codeblock_backticks") && line ==# w:markdown_fold_codeblock_backticks enddef # Call this only if `IsCodeblockEnd()` returns `false` def IsInCodeblock(line: string): bool return !!has_key(w:, "markdown_fold_codeblock_backticks") enddef def IsDetailsStart(line: string): bool return !!(line =~# DETAILS_START_PATTERN) enddef def IsDetailsEnd(line: string): bool return !!has_key(w:, "markdown_fold_details") && !!(line =~# DETAILS_END_PATTERN) enddef def IsSummaryEnd(line: string): bool return !!has_key(w:, "markdown_fold_details") && !!(line =~# SUMMARY_END_PATTERN) enddef