Feature: Markdown link: VimwikiTOC supports multiple heading with same name (Issue: #968, 666, #664)
Anchor can be suffixed with -1 -2 according to the heading number (in file) user want to reach. Implemented with a dictionary for caching anchor names (without sufix)
This commit is contained in:
parent
a27940a394
commit
428c60a45e
@ -692,16 +692,28 @@ endfunction
|
||||
" Called: normalize and unnormalize anchor
|
||||
function! s:get_punctuaction_regex() abort
|
||||
" From: https://gist.github.com/asabaylus/3071099#gistcomment-2563127
|
||||
return '[^0-9a-zA-Z\u4e00-\u9fff_ \-]'
|
||||
if v:version <= 703
|
||||
" Retrocompatibility: Get invalid range for vim 7.03
|
||||
return '[^0-9a-zA-Z_ \-]'
|
||||
else
|
||||
return '[^0-9a-zA-Z\u4e00-\u9fff_ \-]'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
" :param: anchor <string> <= Heading line
|
||||
" :param: (1) previous_anchors <dic[IN/OUT]> of previous normalized anchor
|
||||
" -- to know if must append -2, updated on the fly
|
||||
" Return: anchor <string> => link in TOC
|
||||
function! s:normalize_anchor(anchor) abort
|
||||
function! s:normalize_anchor(anchor, ...) abort
|
||||
" Note: See unormalize
|
||||
" 0 Get in
|
||||
let anchor = a:anchor
|
||||
if a:0
|
||||
let previous_anchors = a:1
|
||||
else
|
||||
let previous_anchors = {}
|
||||
endif
|
||||
|
||||
" A Trim space
|
||||
let anchor = vimwiki#u#trim(anchor)
|
||||
@ -717,14 +729,25 @@ function! s:normalize_anchor(anchor) abort
|
||||
" 3 Change any space to a hyphen
|
||||
let anchor = substitute(anchor, ' ', '-', 'g')
|
||||
|
||||
" 4.2 TODO anchor: If that is not unique, add '-1', '-2', '-3',... to make it unique
|
||||
" 4 Append '-1', '-2', '-3',... to make it unique <= If that not unique
|
||||
if has_key(previous_anchors, anchor)
|
||||
" Inc anchor number (before modifing the anchor)
|
||||
let anchor_nb = previous_anchors[anchor] + 1
|
||||
let previous_anchors[anchor] = anchor_nb
|
||||
" Append suffix
|
||||
let anchor .= '-' . string(anchor_nb)
|
||||
else
|
||||
" Save anchor in dic
|
||||
let previous_anchors[anchor] = 1
|
||||
endif
|
||||
|
||||
return anchor
|
||||
endfunction
|
||||
|
||||
|
||||
" :param: anchor <string> <= link
|
||||
" Return: anchor <regex> to look for
|
||||
" Return: [anchor_re <regex>, anchor_nb <number>] to look for
|
||||
" -- Ex: ['toto", 2] => search for the second occurrence of toto
|
||||
function! s:unnormalize_anchor(anchor) abort
|
||||
" Note:
|
||||
" -- Pandoc keep the '_' in anchor
|
||||
@ -736,26 +759,32 @@ function! s:unnormalize_anchor(anchor) abort
|
||||
|
||||
" 4 Add '-1', '-2', '-3',... to make it unique if not unique
|
||||
" -- Save the trailing -12
|
||||
let sufix = substitute(anchor, '^.*-\(\d\+\)$', '\1', '')
|
||||
if sufix !=# ''
|
||||
let sufix = '[ \-]' . sufix
|
||||
let anchor_nb = substitute(anchor, '^.*-\(\d\+\)$', '\1', '')
|
||||
if anchor_nb ==# '' || anchor_nb == 0
|
||||
" No Sufix: number = 1
|
||||
let sufix = ''
|
||||
let anchor_nb = 1
|
||||
else
|
||||
" Yes Sufix: number <- read suffix
|
||||
let sufix = '[ \-]' . anchor_nb
|
||||
let anchor_nb = str2nr(anchor_nb)
|
||||
endif
|
||||
" -- Remove it
|
||||
let anchor = substitute(anchor, '\(-\d\+\)$', '', '')
|
||||
|
||||
" For each char
|
||||
let anchor_r = ''
|
||||
let anchor_loop = ''
|
||||
for char in split(anchor, '\zs')
|
||||
" 3 Change any space to a hyphen
|
||||
if char ==# '-'
|
||||
let anchor_r .= '[ \-]'
|
||||
let anchor_loop .= '[ \-]'
|
||||
" 2 Remove anything that is not a letter, number, CJK character, hyphen or space
|
||||
" -- So add puncutation regex at each char
|
||||
else
|
||||
let anchor_r .= char . punctuation_rx
|
||||
let anchor_loop .= char . punctuation_rx
|
||||
endif
|
||||
endfor
|
||||
let anchor = punctuation_rx . anchor_r
|
||||
let anchor = punctuation_rx . anchor_loop
|
||||
|
||||
" 1 Downcase the string
|
||||
let anchor = '\c' . anchor
|
||||
@ -763,7 +792,7 @@ function! s:unnormalize_anchor(anchor) abort
|
||||
" 4.bis Add the optional suffix
|
||||
let anchor = anchor . '\(' . sufix . '\)\?'
|
||||
|
||||
return anchor
|
||||
return [anchor, anchor_nb]
|
||||
endfunction
|
||||
|
||||
|
||||
@ -771,32 +800,60 @@ endfunction
|
||||
" Called: edit_file
|
||||
" TODO treat the sufix: -2 -> Go to second anchor
|
||||
function! s:jump_to_anchor(anchor) abort
|
||||
" Save cursor %% Initialize at top of line
|
||||
let oldpos = getpos('.')
|
||||
call cursor(1, 1)
|
||||
|
||||
" Get segments <= anchor
|
||||
let anchor = vimwiki#u#escape(a:anchor)
|
||||
|
||||
let segments = split(anchor, '#', 0)
|
||||
|
||||
" For markdown: there is only one segment
|
||||
for segment in segments
|
||||
" Craft segment pattern so that it is case insensitive and also matches dashes
|
||||
" in anchor link with spaces in heading
|
||||
let segment = s:unnormalize_anchor(segment)
|
||||
let [segment_re, segment_nb] = s:unnormalize_anchor(segment)
|
||||
|
||||
let anchor_header = s:safesubstitute(
|
||||
\ vimwiki#vars#get_syntaxlocal('header_match'),
|
||||
\ '__Header__', segment, '')
|
||||
\ '__Header__', segment_re, '')
|
||||
let anchor_bold = s:safesubstitute(
|
||||
\ vimwiki#vars#get_syntaxlocal('bold_match'),
|
||||
\ '__Text__', segment, '')
|
||||
\ '__Text__', segment_re, '')
|
||||
let anchor_tag = s:safesubstitute(
|
||||
\ vimwiki#vars#get_syntaxlocal('tag_match'),
|
||||
\ '__Tag__', segment, '')
|
||||
\ '__Tag__', segment_re, '')
|
||||
|
||||
if !search(anchor_tag, 'Wc') && !search(anchor_header, 'Wc') && !search(anchor_bold, 'Wc')
|
||||
call setpos('.', oldpos)
|
||||
" Go: Move cursor: maybe more than onces (see markdown suffix)
|
||||
let success_nb = 0
|
||||
let fail = 0
|
||||
for i in range(segment_nb)
|
||||
" Search
|
||||
let pos = 0
|
||||
let pos = pos != 0 ? pos : search(anchor_tag, 'Wc')
|
||||
let pos = pos != 0 ? pos : search(anchor_header, 'Wc')
|
||||
let pos = pos != 0 ? pos : search(anchor_bold, 'Wc')
|
||||
|
||||
" Get the result and reloop or leave
|
||||
if pos != 0
|
||||
" Avance, one line more to not rematch the same pattern if not last segment_nb
|
||||
if success_nb < segment_nb-1 | let pos += 1 | endif
|
||||
call cursor(pos, 1)
|
||||
let success_nb += 1
|
||||
else
|
||||
" Next segment (default syntax)
|
||||
call setpos('.', oldpos)
|
||||
let fail = 1
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Check if happy
|
||||
if success_nb == segment_nb || fail == 1
|
||||
break
|
||||
endif
|
||||
|
||||
" Or keep on (i.e more than once segment)
|
||||
let oldpos = getpos('.')
|
||||
endfor
|
||||
endfunction
|
||||
@ -2296,6 +2353,8 @@ function! vimwiki#base#table_of_contents(create) abort
|
||||
let startindent = repeat(' ', vimwiki#lst#get_list_margin())
|
||||
let indentstring = repeat(' ', vimwiki#u#sw())
|
||||
let bullet = vimwiki#lst#default_symbol().' '
|
||||
" Keep previous anchor => if redundant => add suffix -2
|
||||
let previous_anchors = {}
|
||||
for [lvl, anchor, desc] in complete_header_infos
|
||||
if vimwiki#vars#get_wikilocal('syntax') ==# 'markdown'
|
||||
let link_tpl = vimwiki#vars#get_syntaxlocal('Weblink2Template')
|
||||
@ -2306,7 +2365,7 @@ function! vimwiki#base#table_of_contents(create) abort
|
||||
endif
|
||||
|
||||
" Normalize anchor
|
||||
let anchor = s:normalize_anchor(anchor)
|
||||
let anchor = s:normalize_anchor(anchor, previous_anchors)
|
||||
|
||||
" Insert link in template
|
||||
let link = s:safesubstitute(link_tpl, '__LinkUrl__',
|
||||
|
@ -1,5 +1,6 @@
|
||||
# VimwikiTOC {{{1
|
||||
#
|
||||
# TODO implement: If link in the heading (see README.md)
|
||||
# TODO (10min) test if g:vimwiki_to_header well readen
|
||||
# TODO (10min) test vimviki_toc_link_format
|
||||
# TODO (1h) test if really wiki dependant (for 2 diffrent wikis)
|
||||
@ -10,21 +11,52 @@
|
||||
# -- 3. changes any space to a hyphen => OK: from previous big
|
||||
# -- 4. If that is not unique, add "-1", "-2", "-3",... to make it unique => TODO not implemented
|
||||
#
|
||||
#
|
||||
# TODO if link in heading
|
||||
#Given vimwiki (Two same heading {{{1):
|
||||
# # Pre [link](anything no parenthesis) Post
|
||||
#
|
||||
#Execute (Set syntax markdown && Set sw=8):
|
||||
# call SetSyntax('markdown')
|
||||
# set sw=8
|
||||
# VimwikiTOC
|
||||
#
|
||||
#Expect (Suffix -1 and -2):
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
# Start {{{1
|
||||
|
||||
" TODO
|
||||
"Given vimwiki (Two same heading {{{1):
|
||||
" # One
|
||||
" ## two
|
||||
" ## Two
|
||||
"
|
||||
"Execute (Set syntax markdown && Set sw=8):
|
||||
" call SetSyntax('markdown')
|
||||
" set sw=8
|
||||
" VimwikiTOC
|
||||
"
|
||||
"Expect (Suffix -1 and -2):
|
||||
"
|
||||
|
||||
|
||||
Given vimwiki (Two same heading (#968) {{{1):
|
||||
# One
|
||||
toto
|
||||
# ONE
|
||||
like
|
||||
## oNe
|
||||
you
|
||||
|
||||
Execute (Set syntax markdown && Set sw=8):
|
||||
call SetSyntax('markdown')
|
||||
set sw=8
|
||||
VimwikiTOC
|
||||
|
||||
Expect (Suffix -2 and -3):
|
||||
# Contents
|
||||
|
||||
- [One](#one)
|
||||
- [ONE](#one-2)
|
||||
- [oNe](#one-3)
|
||||
|
||||
# One
|
||||
toto
|
||||
# ONE
|
||||
like
|
||||
## oNe
|
||||
you
|
||||
|
||||
|
||||
Given vimwiki (Heading with many bad caracters {{{1):
|
||||
# One !@#@#(!%#&$^(!@
|
||||
|
Loading…
Reference in New Issue
Block a user