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
|
" Called: normalize and unnormalize anchor
|
||||||
function! s:get_punctuaction_regex() abort
|
function! s:get_punctuaction_regex() abort
|
||||||
" From: https://gist.github.com/asabaylus/3071099#gistcomment-2563127
|
" From: https://gist.github.com/asabaylus/3071099#gistcomment-2563127
|
||||||
|
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_ \-]'
|
return '[^0-9a-zA-Z\u4e00-\u9fff_ \-]'
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" :param: anchor <string> <= Heading line
|
" :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
|
" Return: anchor <string> => link in TOC
|
||||||
function! s:normalize_anchor(anchor) abort
|
function! s:normalize_anchor(anchor, ...) abort
|
||||||
" Note: See unormalize
|
" Note: See unormalize
|
||||||
" 0 Get in
|
" 0 Get in
|
||||||
let anchor = a:anchor
|
let anchor = a:anchor
|
||||||
|
if a:0
|
||||||
|
let previous_anchors = a:1
|
||||||
|
else
|
||||||
|
let previous_anchors = {}
|
||||||
|
endif
|
||||||
|
|
||||||
" A Trim space
|
" A Trim space
|
||||||
let anchor = vimwiki#u#trim(anchor)
|
let anchor = vimwiki#u#trim(anchor)
|
||||||
@ -717,14 +729,25 @@ function! s:normalize_anchor(anchor) abort
|
|||||||
" 3 Change any space to a hyphen
|
" 3 Change any space to a hyphen
|
||||||
let anchor = substitute(anchor, ' ', '-', 'g')
|
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
|
return anchor
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" :param: anchor <string> <= link
|
" :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
|
function! s:unnormalize_anchor(anchor) abort
|
||||||
" Note:
|
" Note:
|
||||||
" -- Pandoc keep the '_' in anchor
|
" -- 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
|
" 4 Add '-1', '-2', '-3',... to make it unique if not unique
|
||||||
" -- Save the trailing -12
|
" -- Save the trailing -12
|
||||||
let sufix = substitute(anchor, '^.*-\(\d\+\)$', '\1', '')
|
let anchor_nb = substitute(anchor, '^.*-\(\d\+\)$', '\1', '')
|
||||||
if sufix !=# ''
|
if anchor_nb ==# '' || anchor_nb == 0
|
||||||
let sufix = '[ \-]' . sufix
|
" 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
|
endif
|
||||||
" -- Remove it
|
" -- Remove it
|
||||||
let anchor = substitute(anchor, '\(-\d\+\)$', '', '')
|
let anchor = substitute(anchor, '\(-\d\+\)$', '', '')
|
||||||
|
|
||||||
" For each char
|
" For each char
|
||||||
let anchor_r = ''
|
let anchor_loop = ''
|
||||||
for char in split(anchor, '\zs')
|
for char in split(anchor, '\zs')
|
||||||
" 3 Change any space to a hyphen
|
" 3 Change any space to a hyphen
|
||||||
if char ==# '-'
|
if char ==# '-'
|
||||||
let anchor_r .= '[ \-]'
|
let anchor_loop .= '[ \-]'
|
||||||
" 2 Remove anything that is not a letter, number, CJK character, hyphen or space
|
" 2 Remove anything that is not a letter, number, CJK character, hyphen or space
|
||||||
" -- So add puncutation regex at each char
|
" -- So add puncutation regex at each char
|
||||||
else
|
else
|
||||||
let anchor_r .= char . punctuation_rx
|
let anchor_loop .= char . punctuation_rx
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
let anchor = punctuation_rx . anchor_r
|
let anchor = punctuation_rx . anchor_loop
|
||||||
|
|
||||||
" 1 Downcase the string
|
" 1 Downcase the string
|
||||||
let anchor = '\c' . anchor
|
let anchor = '\c' . anchor
|
||||||
@ -763,7 +792,7 @@ function! s:unnormalize_anchor(anchor) abort
|
|||||||
" 4.bis Add the optional suffix
|
" 4.bis Add the optional suffix
|
||||||
let anchor = anchor . '\(' . sufix . '\)\?'
|
let anchor = anchor . '\(' . sufix . '\)\?'
|
||||||
|
|
||||||
return anchor
|
return [anchor, anchor_nb]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@ -771,32 +800,60 @@ endfunction
|
|||||||
" Called: edit_file
|
" Called: edit_file
|
||||||
" TODO treat the sufix: -2 -> Go to second anchor
|
" TODO treat the sufix: -2 -> Go to second anchor
|
||||||
function! s:jump_to_anchor(anchor) abort
|
function! s:jump_to_anchor(anchor) abort
|
||||||
|
" Save cursor %% Initialize at top of line
|
||||||
let oldpos = getpos('.')
|
let oldpos = getpos('.')
|
||||||
call cursor(1, 1)
|
call cursor(1, 1)
|
||||||
|
|
||||||
|
" Get segments <= anchor
|
||||||
let anchor = vimwiki#u#escape(a:anchor)
|
let anchor = vimwiki#u#escape(a:anchor)
|
||||||
|
|
||||||
let segments = split(anchor, '#', 0)
|
let segments = split(anchor, '#', 0)
|
||||||
|
|
||||||
|
" For markdown: there is only one segment
|
||||||
for segment in segments
|
for segment in segments
|
||||||
" Craft segment pattern so that it is case insensitive and also matches dashes
|
" Craft segment pattern so that it is case insensitive and also matches dashes
|
||||||
" in anchor link with spaces in heading
|
" 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(
|
let anchor_header = s:safesubstitute(
|
||||||
\ vimwiki#vars#get_syntaxlocal('header_match'),
|
\ vimwiki#vars#get_syntaxlocal('header_match'),
|
||||||
\ '__Header__', segment, '')
|
\ '__Header__', segment_re, '')
|
||||||
let anchor_bold = s:safesubstitute(
|
let anchor_bold = s:safesubstitute(
|
||||||
\ vimwiki#vars#get_syntaxlocal('bold_match'),
|
\ vimwiki#vars#get_syntaxlocal('bold_match'),
|
||||||
\ '__Text__', segment, '')
|
\ '__Text__', segment_re, '')
|
||||||
let anchor_tag = s:safesubstitute(
|
let anchor_tag = s:safesubstitute(
|
||||||
\ vimwiki#vars#get_syntaxlocal('tag_match'),
|
\ vimwiki#vars#get_syntaxlocal('tag_match'),
|
||||||
\ '__Tag__', segment, '')
|
\ '__Tag__', segment_re, '')
|
||||||
|
|
||||||
if !search(anchor_tag, 'Wc') && !search(anchor_header, 'Wc') && !search(anchor_bold, 'Wc')
|
" 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)
|
call setpos('.', oldpos)
|
||||||
|
let fail = 1
|
||||||
break
|
break
|
||||||
endif
|
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('.')
|
let oldpos = getpos('.')
|
||||||
endfor
|
endfor
|
||||||
endfunction
|
endfunction
|
||||||
@ -2296,6 +2353,8 @@ function! vimwiki#base#table_of_contents(create) abort
|
|||||||
let startindent = repeat(' ', vimwiki#lst#get_list_margin())
|
let startindent = repeat(' ', vimwiki#lst#get_list_margin())
|
||||||
let indentstring = repeat(' ', vimwiki#u#sw())
|
let indentstring = repeat(' ', vimwiki#u#sw())
|
||||||
let bullet = vimwiki#lst#default_symbol().' '
|
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
|
for [lvl, anchor, desc] in complete_header_infos
|
||||||
if vimwiki#vars#get_wikilocal('syntax') ==# 'markdown'
|
if vimwiki#vars#get_wikilocal('syntax') ==# 'markdown'
|
||||||
let link_tpl = vimwiki#vars#get_syntaxlocal('Weblink2Template')
|
let link_tpl = vimwiki#vars#get_syntaxlocal('Weblink2Template')
|
||||||
@ -2306,7 +2365,7 @@ function! vimwiki#base#table_of_contents(create) abort
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
" Normalize anchor
|
" Normalize anchor
|
||||||
let anchor = s:normalize_anchor(anchor)
|
let anchor = s:normalize_anchor(anchor, previous_anchors)
|
||||||
|
|
||||||
" Insert link in template
|
" Insert link in template
|
||||||
let link = s:safesubstitute(link_tpl, '__LinkUrl__',
|
let link = s:safesubstitute(link_tpl, '__LinkUrl__',
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# VimwikiTOC {{{1
|
# 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 if g:vimwiki_to_header well readen
|
||||||
# TODO (10min) test vimviki_toc_link_format
|
# TODO (10min) test vimviki_toc_link_format
|
||||||
# TODO (1h) test if really wiki dependant (for 2 diffrent wikis)
|
# 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
|
# -- 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
|
# -- 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
|
# Start {{{1
|
||||||
|
|
||||||
" TODO
|
|
||||||
"Given vimwiki (Two same heading {{{1):
|
|
||||||
" # One
|
Given vimwiki (Two same heading (#968) {{{1):
|
||||||
" ## two
|
# One
|
||||||
" ## Two
|
toto
|
||||||
"
|
# ONE
|
||||||
"Execute (Set syntax markdown && Set sw=8):
|
like
|
||||||
" call SetSyntax('markdown')
|
## oNe
|
||||||
" set sw=8
|
you
|
||||||
" VimwikiTOC
|
|
||||||
"
|
Execute (Set syntax markdown && Set sw=8):
|
||||||
"Expect (Suffix -1 and -2):
|
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):
|
Given vimwiki (Heading with many bad caracters {{{1):
|
||||||
# One !@#@#(!%#&$^(!@
|
# One !@#@#(!%#&$^(!@
|
||||||
|
Loading…
Reference in New Issue
Block a user