Add anchors, jumping to anchors, TOC and completion

Ref #10
This commit is contained in:
EinfachToll 2014-02-13 12:42:24 +01:00
parent cec6acd2f0
commit 8097083f46
7 changed files with 509 additions and 200 deletions

View File

@ -326,8 +326,14 @@ endfunction " }}}
" vimwiki#base#resolve_scheme
function! vimwiki#base#resolve_scheme(lnk, as_html) " {{{ Resolve scheme
" if link is schemeless add wikiN: scheme
let lnk = a:lnk
" a link starting with # means current file with an anchor
if lnk =~ '^#'
let lnk = expand('%:t:r').lnk
endif
" if link is schemeless add wikiN: scheme
let is_schemeless = lnk !~ g:vimwiki_rxSchemeUrl
let lnk = (is_schemeless ? 'wiki'.g:vimwiki_current_idx.':'.lnk : lnk)
@ -339,11 +345,23 @@ function! vimwiki#base#resolve_scheme(lnk, as_html) " {{{ Resolve scheme
let subdir = ''
let ext = ''
let idx = -1
let anchor = ''
"extract anchor
if scheme =~ 'wiki' || scheme =~ 'diary'
let split_lnk = split(lnk, '#', 1)
let lnk = split_lnk[0]
if len(split_lnk) <= 1 || split_lnk[-1] == ''
let anchor = ''
else
let anchor = join(split_lnk[1:], '#')
endif
endif
" do nothing if scheme is unknown to vimwiki
if !(scheme =~ 'wiki.*' || scheme =~ 'diary' || scheme =~ 'local'
\ || scheme =~ 'file')
return [idx, scheme, path, subdir, lnk, ext, scheme.':'.lnk]
return [idx, scheme, path, subdir, lnk, ext, scheme.':'.lnk, anchor]
endif
" scheme behaviors
@ -351,7 +369,7 @@ function! vimwiki#base#resolve_scheme(lnk, as_html) " {{{ Resolve scheme
let idx = eval(matchstr(scheme, '\D\+\zs\d\+\ze'))
if idx < 0 || idx >= len(g:vimwiki_list)
echom 'Vimwiki Error: Numbered scheme refers to a non-existent wiki!'
return [idx,'','','','','','']
return [idx,'','','','','','', '']
else
if idx != g:vimwiki_current_idx
call vimwiki#base#validate_wiki_options(idx)
@ -440,7 +458,7 @@ function! vimwiki#base#resolve_scheme(lnk, as_html) " {{{ Resolve scheme
endif
" result
return [idx, scheme, path, subdir, lnk, ext, url]
return [idx, scheme, path, subdir, lnk, ext, url, anchor]
endfunction "}}}
" vimwiki#base#system_open_link
@ -474,21 +492,20 @@ endfunction "}}}
" vimwiki#base#open_link
function! vimwiki#base#open_link(cmd, link, ...) "{{{
let [idx, scheme, path, subdir, lnk, ext, url] =
let [idx, scheme, path, subdir, lnk, ext, url, anchor] =
\ vimwiki#base#resolve_scheme(a:link, 0)
if url == ''
if g:vimwiki_debug
echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url
echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url.', anchor='.anchor
endif
echom 'Vimwiki Error: Unable to resolve link!'
return
endif
let update_prev_link = (
\ scheme == '' ||
\ scheme =~ 'wiki' ||
\ scheme =~ 'diary' ? 1 : 0)
let update_prev_link = ( (scheme == '' || scheme =~ 'wiki' || scheme =~ 'diary')
\ && lnk != expand('%:t:r')
\ ? 1 : 0)
let use_system_open = (
\ scheme == '' ||
@ -507,13 +524,13 @@ function! vimwiki#base#open_link(cmd, link, ...) "{{{
" open/edit
if g:vimwiki_debug
echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url
echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url.'anchor='.anchor
endif
if use_system_open
call vimwiki#base#system_open_link(url)
else
call vimwiki#base#edit_file(a:cmd, url,
call vimwiki#base#edit_file(a:cmd, url, anchor,
\ vimwiki_prev_link, update_prev_link)
if idx != g:vimwiki_current_idx
" this call to setup_buffer_state may not be necessary
@ -551,11 +568,15 @@ function! vimwiki#base#generate_links() "{{{only get links from the current dir
endfunction " }}}
" vimwiki#base#goto
function! vimwiki#base#goto(key) "{{{
function! vimwiki#base#goto(...) "{{{
let key = a:1
let anchor = a:0 > 1 ? a:2 : ''
call vimwiki#base#edit_file(':e',
\ VimwikiGet('path').
\ a:key.
\ VimwikiGet('ext'))
\ key.
\ VimwikiGet('ext'),
\ anchor)
endfunction "}}}
" vimwiki#base#backlinks
@ -642,8 +663,31 @@ function! vimwiki#base#get_links(pat) "{{{ return string-list for files
return globlinks
endfunction "}}}
function! s:jump_to_anchor(anchor)
let oldpos = getpos('.')
call cursor(1, 1)
let anchor = vimwiki#u#escape(a:anchor)
let segments = split(anchor, '#', 0)
for segment in segments
let anchor_header = substitute(
\ g:vimwiki_{VimwikiGet('syntax')}_header_match,
\ '__Header__', "\\='".segment."'", '')
let anchor_bold = substitute(g:vimwiki_{VimwikiGet('syntax')}_bold_match,
\ '__Text__', "\\='".segment."'", '')
if !search(anchor_header, 'c') && !search(anchor_bold, 'c')
call setpos('.', oldpos)
break
endif
let oldpos = getpos('.')
endfor
endfunction
" vimwiki#base#edit_file
function! vimwiki#base#edit_file(command, filename, ...) "{{{
function! vimwiki#base#edit_file(command, filename, anchor, ...) "{{{
" XXX: Should we allow * in filenames!?
" Maxim: It is allowed, escaping here is for vim to be able to open files
" which have that symbols.
@ -655,7 +699,16 @@ function! vimwiki#base#edit_file(command, filename, ...) "{{{
let fname = escape(a:filename, '% *|#')
let dir = fnamemodify(a:filename, ":p:h")
if vimwiki#base#mkdir(dir, 1)
" check if the file we want to open is already the current file
" which happens if we jump to an achor in the current file.
" This hack is necessary because apparently Vim messes up the result of
" getpos() directly after this command. Strange.
if !(a:command == ':e ' && a:filename == expand('%:p'))
execute a:command.' '.fname
endif
if a:anchor != ''
call s:jump_to_anchor(a:anchor)
endif
else
echom ' '
echom 'Vimwiki: Unable to edit file in non-existent directory: '.dir
@ -769,9 +822,9 @@ function! s:update_wiki_links_dir(dir, old_fname, new_fname) " {{{
let new_fname_r = new_fname
let old_fname_r = vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate1,
\ '\zs'.old_fname.'\ze', '.*', '').
\ '\zs'.old_fname.'\ze\%(#.*\)\?', '.*', '').
\ '\|'. vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate2,
\ '\zs'.old_fname.'\ze', '.*', '')
\ '\zs'.old_fname.'\ze\%(#.*\)\?', '.*', '')
let files = split(glob(VimwikiGet('path').a:dir.'*'.VimwikiGet('ext')), '\n')
for fname in files
@ -839,7 +892,7 @@ endfunction " }}}
" s:open_wiki_buffer
function! s:open_wiki_buffer(item) "{{{
call vimwiki#base#edit_file(':e', a:item[0])
call vimwiki#base#edit_file(':e', a:item[0], '')
if !empty(a:item[1])
call setbufvar(a:item[0], "vimwiki_prev_link", a:item[1])
endif
@ -1004,7 +1057,8 @@ function! vimwiki#base#goto_index(wnum, ...) "{{{
call vimwiki#base#validate_wiki_options(idx)
call vimwiki#base#edit_file(cmd,
\ VimwikiGet('path', idx).VimwikiGet('index', idx).
\ VimwikiGet('ext', idx))
\ VimwikiGet('ext', idx),
\ '')
call vimwiki#base#setup_buffer_state(idx)
endfunction "}}}
@ -1432,6 +1486,90 @@ function! vimwiki#base#RemoveHeaderLevel() "{{{
call setline(lnum, line)
endif
endfunction " }}}
"creates or updates TOC in current file
function! vimwiki#base#table_of_contents()
let old_cursor_pos = getpos('.')
let bullet = vimwiki#lst#default_symbol().' '
let rx_bullet = vimwiki#u#escape(bullet)
let toc_line = 0
let whitespaces = ''
" delete old TOC
let toc_header = '^\s*'.substitute(g:vimwiki_rxH1_Template, '__Header__',
\ '\='."'".g:vimwiki_toc_string."'", '').'\s*$'
let lnum = 1
while lnum <= &modelines + 2 && lnum <= line('$')
let line_content = getline(lnum)
if line_content =~# toc_header
let toc_line = lnum - 1
let whitespaces = matchstr(line_content, '^\s*')
let tl = lnum
while 1
let tl += 1
if tl > line('$') || getline(tl) !~ '^\s*'.rx_bullet.g:vimwiki_rxWikiLink.'\s*$'
silent exe lnum.','.string(tl-1).'delete _'
break
endif
endwhile
break
endif
let lnum += 1
endwhile
" collect new headers
let toc_lines = []
let headers_levels = [['', 0], ['', 0], ['', 0], ['', 0], ['', 0], ['', 0]]
for lnum in range(1, line('$'))
let line_content = getline(lnum)
if line_content !~ g:vimwiki_rxHeader
continue
endif
let h_level = vimwiki#u#count_first_sym(line_content)
let h_text = vimwiki#u#trim(matchstr(line_content, g:vimwiki_rxHeader))
let headers_levels[h_level-1] = [h_text, headers_levels[h_level-1][1]+1]
for idx in range(h_level, 5) | let headers_levels[idx] = ['', 0] | endfor
let h_complete_id = ''
for l in range(h_level-1)
if headers_levels[l][0] != ''
let h_complete_id .= headers_levels[l][0].'#'
endif
endfor
let h_complete_id .= headers_levels[h_level-1][0]
if g:vimwiki_html_header_numbering > 0
\ && g:vimwiki_html_header_numbering <= h_level
let h_number = join(map(copy(headers_levels[
\ g:vimwiki_html_header_numbering-1 : h_level-1]), 'v:val[1]'), '.')
let h_number .= g:vimwiki_html_header_numbering_sym
let h_text = h_number.' '.h_text
endif
call add(toc_lines, [h_level, h_complete_id, h_text])
endfor
" write new TOC
call append(toc_line, whitespaces . substitute(g:vimwiki_rxH1_Template,
\ '__Header__', '\='."'".g:vimwiki_toc_string."'", ''))
let toc_line += 1
let startindent = repeat(' ', vimwiki#lst#get_list_margin())
let indentstring = repeat(' ', &shiftwidth)
for [lvl, link, desc] in toc_lines
let esc_link = substitute(link, "'", "''", 'g')
let esc_desc = substitute(desc, "'", "''", 'g')
let link = substitute(g:vimwiki_WikiLinkTemplate2, '__LinkUrl__',
\ '\='."'".'#'.esc_link."'", '')
let link = substitute(link, '__LinkDescription__', '\='."'".esc_desc."'", '')
call append(toc_line, startindent.repeat(indentstring, lvl-1).bullet.link)
let toc_line += 1
endfor
if getline(toc_line+1) !~ '^\s*$'
call append(toc_line, '')
endif
call setpos('.', old_cursor_pos)
endfunction
"}}}
" LINK functions {{{

View File

@ -266,7 +266,7 @@ function! vimwiki#diary#goto_diary_index(wnum) "{{{
endif
call vimwiki#base#validate_wiki_options(idx)
call vimwiki#base#edit_file('e', s:diary_index(idx))
call vimwiki#base#edit_file('e', s:diary_index(idx), '')
call vimwiki#base#setup_buffer_state(idx)
endfunction "}}}

View File

@ -128,13 +128,21 @@ function! s:get_html_template(wikifile, template) "{{{
return lines
endfunction "}}}
function! s:safe_html_tags(line) "{{{
function! s:safe_html_preformatted(line) "{{{
let line = substitute(a:line,'<','\&lt;', 'g')
let line = substitute(line,'>','\&gt;', 'g')
return line
endfunction "}}}
function! s:safe_html(line) "{{{
function! s:safe_html_anchor(string) "{{{
let string = substitute(a:string, '"', '\&quot;', 'g')
let string = substitute(string, "'", '\&#39;', 'g')
let string = substitute(string, '/', '\&#47;', 'g')
let string = substitute(string, '\t', ' ', 'g') " &#9; doesn't work
return string
endfunction "}}}
function! s:safe_html_line(line) "{{{
" escape & < > when producing HTML text
" s:lt_pattern, s:gt_pattern depend on g:vimwiki_valid_html_tags
" and are set in vimwiki#html#Wiki2HTML()
@ -173,7 +181,7 @@ function! s:mid(value, cnt) "{{{
return strpart(a:value, a:cnt, len(a:value) - 2 * a:cnt)
endfunction "}}}
function! s:subst_func(line, regexp, func) " {{{
function! s:subst_func(line, regexp, func, ...) " {{{
" Substitute text found by regexp with result of
" func(matched) function.
@ -184,8 +192,12 @@ function! s:subst_func(line, regexp, func) " {{{
let res_line = res_line.line
let matched = matchstr(a:line, a:regexp, pos)
if matched != ""
if a:0
let res_line = res_line.{a:func}(matched, a:1)
else
let res_line = res_line.{a:func}(matched)
endif
endif
let pos = matchend(a:line, a:regexp, pos)
endfor
return res_line
@ -197,61 +209,6 @@ function! s:save_vimwiki_buffer() "{{{
endif
endfunction "}}}
function! s:get_html_toc(toc_list) "{{{
" toc_list is list of [level, header_text, header_id]
" ex: [[1, "Header", "toc1"], [2, "Header2", "toc2"], ...]
function! s:close_list(toc, plevel, level) "{{{
let plevel = a:plevel
while plevel > a:level
call add(a:toc, '</ul>')
let plevel -= 1
endwhile
return plevel
endfunction "}}}
if empty(a:toc_list)
return []
endif
let toc = ['<div class="toc">']
let level = 0
let plevel = 0
for [level, text, id] in a:toc_list
if level > plevel
call add(toc, '<ul>')
elseif level < plevel
let plevel = s:close_list(toc, plevel, level)
endif
let toc_text = s:process_tags_remove_links(text)
let toc_text = s:process_tags_typefaces(toc_text)
call add(toc, '<li><a href="#'.id.'">'.toc_text.'</a>')
let plevel = level
endfor
call s:close_list(toc, level, 0)
call add(toc, '</div>')
return toc
endfunction "}}}
" insert toc into dest.
function! s:process_toc(dest, placeholders, toc) "{{{
let toc_idx = 0
if !empty(a:placeholders)
for [placeholder, row, idx] in a:placeholders
let [type, param] = placeholder
if type == 'toc'
let toc = a:toc[:]
if !empty(param)
call insert(toc, '<h1>'.param.'</h1>')
endif
let shift = toc_idx * len(toc)
call extend(a:dest, toc, row + shift)
let toc_idx += 1
endif
endfor
endif
endfunction "}}}
" get title.
function! s:process_title(placeholders, default_title) "{{{
if !empty(a:placeholders)
@ -316,8 +273,21 @@ function! s:tag_em(value) "{{{
return '<em>'.s:mid(a:value, 1).'</em>'
endfunction "}}}
function! s:tag_strong(value) "{{{
return '<strong>'.s:mid(a:value, 1).'</strong>'
function! s:tag_strong(value, header_ids) "{{{
let text = s:mid(a:value, 1)
let id = s:safe_html_anchor(text)
let complete_id = ''
for l in range(6)
if a:header_ids[l][0] != ''
let complete_id .= a:header_ids[l][0].'-'
endif
endfor
if a:header_ids[5][0] == ''
let complete_id = complete_id[:-2]
endif
let complete_id .= '-'.id
return '<div id="'.s:safe_html_anchor(complete_id).'"></div><strong id="'
\ .id.'">'.text.'</strong>'
endfunction "}}}
function! s:tag_todo(value) "{{{
@ -337,7 +307,7 @@ function! s:tag_sub(value) "{{{
endfunction "}}}
function! s:tag_code(value) "{{{
return '<code>'.s:safe_html_tags(s:mid(a:value, 1)).'</code>'
return '<code>'.s:safe_html_preformatted(s:mid(a:value, 1)).'</code>'
endfunction "}}}
"function! s:tag_pre(value) "{{{
@ -365,7 +335,7 @@ endfunction
"}}}
function! vimwiki#html#linkify_link(src, descr) "{{{
let src_str = ' href="'.a:src.'"'
let src_str = ' href="'.s:safe_html_anchor(a:src).'"'
let descr = substitute(a:descr,'^\s*\(.*\)\s*$','\1','')
let descr = (descr == "" ? a:src : descr)
let descr_str = (descr =~ g:vimwiki_rxWikiIncl
@ -404,7 +374,7 @@ function! s:tag_wikiincl(value) "{{{
let descr = matchstr(str, vimwiki#html#incl_match_arg(1))
let verbatim_str = matchstr(str, vimwiki#html#incl_match_arg(2))
" resolve url
let [idx, scheme, path, subdir, lnk, ext, url] =
let [idx, scheme, path, subdir, lnk, ext, url, anchor] =
\ vimwiki#base#resolve_scheme(url_0, 1)
" generate html output
" TODO: migrate non-essential debugging messages into g:VimwikiLog
@ -431,13 +401,15 @@ function! s:tag_wikilink(value) "{{{
" [[url|{{...}}]] -> <a href="url.html"> ... </a>
" [[fileurl.ext|descr]] -> <a href="fileurl.ext">descr</a>
" [[dirurl/|descr]] -> <a href="dirurl/index.html">descr</a>
" [[url#a1#a2]] -> <a href="url.html#a1-a2">url#a1#a2</a>
" [[#a1#a2]] -> <a href="file.html#a1-a2">#a1#a2</a>
let str = a:value
let url = matchstr(str, g:vimwiki_rxWikiLinkMatchUrl)
let descr = matchstr(str, g:vimwiki_rxWikiLinkMatchDescr)
let descr = (substitute(descr,'^\s*\(.*\)\s*$','\1','') != '' ? descr : url)
" resolve url
let [idx, scheme, path, subdir, lnk, ext, url] =
let [idx, scheme, path, subdir, lnk, ext, url, anchor] =
\ vimwiki#base#resolve_scheme(url, 1)
" generate html output
@ -445,7 +417,8 @@ function! s:tag_wikilink(value) "{{{
if g:vimwiki_debug > 1
echom '[[idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.']]'
endif
let line = vimwiki#html#linkify_link(url, descr)
let anchor = substitute(anchor, '#', '-', 'g')
let line = vimwiki#html#linkify_link(url.'#'.anchor, descr)
return line
endfunction "}}}
"}}}
@ -496,7 +469,7 @@ function! s:tag_remove_external_link(value) "{{{
return line
endfunction "}}}
function! s:make_tag(line, regexp, func) "{{{
function! s:make_tag(line, regexp, func, ...) "{{{
" Make tags for a given matched regexp.
" Exclude preformatted text and href links.
" FIXME
@ -521,7 +494,11 @@ function! s:make_tag(line, regexp, func) "{{{
let lines = split(a:line, patt_splitter, 1)
let res_line = ""
for line in lines
if a:0
let res_line = res_line.s:subst_func(line, a:regexp, a:func, a:1)
else
let res_line = res_line.s:subst_func(line, a:regexp, a:func)
endif
let res_line = res_line.matchstr(a:line, patt_splitter, pos)
let pos = matchend(a:line, patt_splitter, pos)
endfor
@ -536,10 +513,10 @@ function! s:process_tags_remove_links(line) " {{{
return line
endfunction " }}}
function! s:process_tags_typefaces(line) "{{{
function! s:process_tags_typefaces(line, header_ids) "{{{
let line = a:line
let line = s:make_tag(line, g:vimwiki_rxItalic, 's:tag_em')
let line = s:make_tag(line, g:vimwiki_rxBold, 's:tag_strong')
let line = s:make_tag(line, g:vimwiki_rxBold, 's:tag_strong', a:header_ids)
let line = s:make_tag(line, g:vimwiki_rxTodo, 's:tag_todo')
let line = s:make_tag(line, g:vimwiki_rxDelText, 's:tag_strike')
let line = s:make_tag(line, g:vimwiki_rxSuperScript, 's:tag_super')
@ -557,9 +534,9 @@ function! s:process_tags_links(line) " {{{
return line
endfunction " }}}
function! s:process_inline_tags(line) "{{{
function! s:process_inline_tags(line, header_ids) "{{{
let line = s:process_tags_links(a:line)
let line = s:process_tags_typefaces(line)
let line = s:process_tags_typefaces(line, a:header_ids)
return line
endfunction " }}}
"}}}
@ -597,7 +574,7 @@ function! s:close_tag_para(para, ldest) "{{{
return a:para
endfunction "}}}
function! s:close_tag_table(table, ldest) "{{{
function! s:close_tag_table(table, ldest, header_ids) "{{{
" The first element of table list is a string which tells us if table should be centered.
" The rest elements are rows which are lists of columns:
" ['center',
@ -654,7 +631,7 @@ function! s:close_tag_table(table, ldest) "{{{
endfor
endfunction "}}}
function! s:close_tag_row(row, header, ldest) "{{{
function! s:close_tag_row(row, header, ldest, header_ids) "{{{
call add(a:ldest, '<tr>')
" Set tag element of columns
@ -682,7 +659,7 @@ function! s:close_tag_table(table, ldest) "{{{
endif
call add(a:ldest, '<' . tag_name . rowspan_attr . colspan_attr .'>')
call add(a:ldest, s:process_inline_tags(cell.body))
call add(a:ldest, s:process_inline_tags(cell.body, a:header_ids))
call add(a:ldest, '</'. tag_name . '>')
endfor
@ -715,15 +692,15 @@ function! s:close_tag_table(table, ldest) "{{{
if head > 0
for row in table[1 : head-1]
if !empty(filter(row, '!empty(v:val)'))
call s:close_tag_row(row, 1, ldest)
call s:close_tag_row(row, 1, ldest, a:header_ids)
endif
endfor
for row in table[head+1 :]
call s:close_tag_row(row, 0, ldest)
call s:close_tag_row(row, 0, ldest, a:header_ids)
endfor
else
for row in table[1 :]
call s:close_tag_row(row, 0, ldest)
call s:close_tag_row(row, 0, ldest, a:header_ids)
endfor
endif
call add(ldest, "</table>")
@ -774,7 +751,7 @@ function! s:process_tag_pre(line, pre) "{{{
let processed = 1
"XXX destroys indent in general!
"call add(lines, substitute(a:line, '^\s\{'.pre[1].'}', '', ''))
call add(lines, s:safe_html_tags(a:line))
call add(lines, s:safe_html_preformatted(a:line))
endif
return [processed, lines, pre]
endfunction "}}}
@ -977,34 +954,30 @@ function! s:process_tag_h(line, id) "{{{
let h_level = vimwiki#u#count_first_sym(a:line)
endif
if h_level > 0
let a:id[h_level] += 1
" reset higher level ids
for level in range(h_level+1, 6)
let a:id[level] = 0
endfor
let centered = 0
if a:line =~ '^\s\+'
let centered = 1
endif
let h_number = ''
for l in range(1, h_level-1)
let h_number .= a:id[l].'.'
endfor
let h_number .= a:id[h_level]
let h_id = 'toc_'.h_number
let h_part = '<h'.h_level.' id="'.h_id.'"'
if centered
let h_part .= ' class="justcenter">'
else
let h_part .= '>'
endif
let h_text = vimwiki#u#trim(matchstr(line, g:vimwiki_rxHeader))
let h_number = ''
let h_complete_id = ''
let h_id = s:safe_html_anchor(h_text)
let centered = (a:line =~ '^\s')
if h_text != g:vimwiki_toc_string
let a:id[h_level-1] = [h_text, a:id[h_level-1][1]+1]
" reset higher level ids
for level in range(h_level, 5)
let a:id[level] = ['', 0]
endfor
for l in range(h_level-1)
let h_number .= a:id[l][1].'.'
if a:id[l][0] != ''
let h_complete_id .= a:id[l][0].'-'
endif
endfor
let h_number .= a:id[h_level-1][1]
let h_complete_id .= a:id[h_level-1][0]
if g:vimwiki_html_header_numbering
let num = matchstr(h_number,
@ -1014,11 +987,27 @@ function! s:process_tag_h(line, id) "{{{
endif
let h_text = num.' '.h_text
endif
let h_complete_id = s:safe_html_anchor(h_complete_id)
let h_part = '<div id="'.h_complete_id.'"><h'.h_level.' id="'.h_id.'"'
else
let h_part = '<div id="'.h_id.'" class="toc"><h1 id="'.h_id.'"'
endif
if centered
let h_part .= ' class="justcenter">'
else
let h_part .= '>'
endif
let line = h_part.h_text.'</h'.h_level.'></div>'
let line = h_part.h_text.'</h'.h_level.'>'
let processed = 1
endif
return [processed, line, h_level, h_text, h_id]
return [processed, line]
endfunction "}}}
function! s:process_tag_hr(line) "{{{
@ -1031,7 +1020,7 @@ function! s:process_tag_hr(line) "{{{
return [processed, line]
endfunction "}}}
function! s:process_tag_table(line, table) "{{{
function! s:process_tag_table(line, table, header_ids) "{{{
function! s:table_empty_cell(value) "{{{
let cell = {}
@ -1085,7 +1074,7 @@ function! s:process_tag_table(line, table) "{{{
call map(cells, 's:table_empty_cell(v:val)')
call extend(table[-1], cells)
else
let table = s:close_tag_table(table, lines)
let table = s:close_tag_table(table, lines, a:header_ids)
endif
return [processed, lines, table]
endfunction "}}}
@ -1105,12 +1094,11 @@ function! s:parse_line(line, state) " {{{
let state.lists = a:state.lists[:]
let state.deflist = a:state.deflist
let state.placeholder = a:state.placeholder
let state.toc = a:state.toc
let state.toc_id = a:state.toc_id
let state.header_ids = a:state.header_ids
let res_lines = []
let line = s:safe_html(a:line)
let line = s:safe_html_line(a:line)
let processed = 0
@ -1147,16 +1135,6 @@ function! s:parse_line(line, state) " {{{
endif
"}}}
" toc -- placeholder "{{{
if !processed
if line =~ '^\s*%toc'
let processed = 1
let param = matchstr(line, '^\s*%toc\s\zs.*')
let state.placeholder = ['toc', param]
endif
endif
"}}}
" pres "{{{
if !processed
let [processed, lines, state.pre] = s:process_tag_pre(line, state.pre)
@ -1168,7 +1146,7 @@ function! s:parse_line(line, state) " {{{
let [processed, lines, state.math] = s:process_tag_math(line, state.math)
endif
if processed && len(state.table)
let state.table = s:close_tag_table(state.table, lines)
let state.table = s:close_tag_table(state.table, lines, state.header_ids)
endif
if processed && state.deflist
let state.deflist = s:close_tag_def_list(state.deflist, lines)
@ -1196,7 +1174,7 @@ function! s:parse_line(line, state) " {{{
let state.math = s:close_tag_math(state.math, lines)
endif
if processed && len(state.table)
let state.table = s:close_tag_table(state.table, lines)
let state.table = s:close_tag_table(state.table, lines, state.header_ids)
endif
if processed && state.deflist
let state.deflist = s:close_tag_def_list(state.deflist, lines)
@ -1205,7 +1183,7 @@ function! s:parse_line(line, state) " {{{
let state.para = s:close_tag_para(state.para, lines)
endif
call map(lines, 's:process_inline_tags(v:val)')
call map(lines, 's:process_inline_tags(v:val, state.header_ids)')
call extend(res_lines, lines)
endif
@ -1213,28 +1191,27 @@ function! s:parse_line(line, state) " {{{
" headers "{{{
if !processed
let [processed, line, h_level, h_text, h_id] = s:process_tag_h(line, state.toc_id)
let [processed, line] = s:process_tag_h(line, state.header_ids)
if processed
call s:close_tag_list(state.lists, res_lines)
let state.table = s:close_tag_table(state.table, res_lines)
let state.table = s:close_tag_table(state.table, res_lines,
\ state.header_ids)
let state.pre = s:close_tag_pre(state.pre, res_lines)
let state.math = s:close_tag_math(state.math, res_lines)
let state.quote = s:close_tag_quote(state.quote, res_lines)
let state.para = s:close_tag_para(state.para, res_lines)
let line = s:process_inline_tags(line)
let line = s:process_inline_tags(line, state.header_ids)
call add(res_lines, line)
" gather information for table of contents
call add(state.toc, [h_level, h_text, h_id])
endif
endif
"}}}
" tables "{{{
if !processed
let [processed, lines, state.table] = s:process_tag_table(line, state.table)
let [processed, lines, state.table] = s:process_tag_table(line,
\ state.table, state.header_ids)
call extend(res_lines, lines)
endif
"}}}
@ -1249,7 +1226,7 @@ function! s:parse_line(line, state) " {{{
let state.deflist = s:close_tag_def_list(state.deflist, lines)
endif
if processed && len(state.table)
let state.table = s:close_tag_table(state.table, lines)
let state.table = s:close_tag_table(state.table, lines, state.header_ids)
endif
if processed && state.pre[0]
let state.pre = s:close_tag_pre(state.pre, lines)
@ -1261,7 +1238,7 @@ function! s:parse_line(line, state) " {{{
let state.para = s:close_tag_para(state.para, lines)
endif
call map(lines, 's:process_inline_tags(v:val)')
call map(lines, 's:process_inline_tags(v:val, state.header_ids)')
call extend(res_lines, lines)
endif
@ -1272,7 +1249,8 @@ function! s:parse_line(line, state) " {{{
let [processed, line] = s:process_tag_hr(line)
if processed
call s:close_tag_list(state.lists, res_lines)
let state.table = s:close_tag_table(state.table, res_lines)
let state.table = s:close_tag_table(state.table, res_lines,
\ state.header_ids)
let state.pre = s:close_tag_pre(state.pre, res_lines)
let state.math = s:close_tag_math(state.math, res_lines)
call add(res_lines, line)
@ -1284,7 +1262,7 @@ function! s:parse_line(line, state) " {{{
if !processed
let [processed, lines, state.deflist] = s:process_tag_def_list(line, state.deflist)
call map(lines, 's:process_inline_tags(v:val)')
call map(lines, 's:process_inline_tags(v:val, state.header_ids)')
call extend(res_lines, lines)
endif
@ -1306,10 +1284,11 @@ function! s:parse_line(line, state) " {{{
let state.math = s:close_tag_math(state.math, res_lines)
endif
if processed && len(state.table)
let state.table = s:close_tag_table(state.table, res_lines)
let state.table = s:close_tag_table(state.table, res_lines,
\ state.header_ids)
endif
call map(lines, 's:process_inline_tags(v:val)')
call map(lines, 's:process_inline_tags(v:val, state.header_ids)')
call extend(res_lines, lines)
endif
@ -1390,10 +1369,10 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{
let state.deflist = 0
let state.lists = []
let state.placeholder = []
let state.toc = []
let state.toc_id = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0 }
let state.header_ids = [['', 0], ['', 0], ['', 0], ['', 0], ['', 0], ['', 0]]
" [last seen header text in this level, number]
" prepare constants for s:safe_html()
" prepare constants for s:safe_html_line()
let s:lt_pattern = '<'
let s:gt_pattern = '>'
if g:vimwiki_valid_html_tags != ''
@ -1439,8 +1418,6 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{
return
endif
let toc = s:get_html_toc(state.toc)
call s:process_toc(ldest, placeholders, toc)
call s:remove_blank_lines(ldest)
"" process end of file
@ -1452,7 +1429,7 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{
call s:close_tag_math(state.math, lines)
call s:close_tag_list(state.lists, lines)
call s:close_tag_def_list(state.deflist, lines)
call s:close_tag_table(state.table, lines)
call s:close_tag_table(state.table, lines, state.header_ids)
call extend(ldest, lines)
let title = s:process_title(placeholders, fnamemodify(a:wikifile, ":t:r"))

View File

@ -43,15 +43,16 @@ CONTENTS *vimwiki-contents*
8. Lists |vimwiki-lists|
9. Tables |vimwiki-tables|
10. Diary |vimwiki-diary|
11. Options |vimwiki-options|
11.1. Registered Wiki |vimwiki-register-wiki|
11.2. Temporary Wiki |vimwiki-temporary-wiki|
11.3. Per-Wiki Options |vimwiki-local-options|
11.4. Global Options |vimwiki-global-options|
12. Help |vimwiki-help|
13. Developers |vimwiki-developers|
14. Changelog |vimwiki-changelog|
15. License |vimwiki-license|
11. Anchors |vimwiki-anchors|
12. Options |vimwiki-options|
12.1. Registered Wiki |vimwiki-register-wiki|
12.2. Temporary Wiki |vimwiki-temporary-wiki|
12.3. Per-Wiki Options |vimwiki-local-options|
12.4. Global Options |vimwiki-global-options|
13. Help |vimwiki-help|
14. Developers |vimwiki-developers|
15. Changelog |vimwiki-changelog|
16. License |vimwiki-license|
==============================================================================
@ -755,6 +756,16 @@ Raw URLs are also supported: >
mailto:habamax@gmail.com
ftp://vim.org
Anchors~
A URL can be followed by a '#' and the name of an anchor. When opening a
link, Vimwiki then jumps to the anchor. >
[[Todo List#Tomorrow|Tasks for tomorrow]]
To jump inside the current wiki file you can omit the file: >
[[#Tomorrow]]
See |vimwiki-anchors|.
Markdown Links~
@ -795,6 +806,10 @@ as a wiki page.
To scan the page for new or changed definitions for reference-links, simply
re-open the page ":e<CR>".
Typing wikilinks can be simplified by using Vim's omni completion (see
|compl-omni|) like so: >
[[ind<C-X><C-O>
which opens up a popup menu with all the wiki files starting with "ind".
------------------------------------------------------------------------------
5.3. Headers *vimwiki-syntax-headers*
@ -1565,9 +1580,42 @@ Get it from http://www.vim.org/scripts/script.php?script_id=52
See |g:vimwiki_use_calendar| option to turn it off/on.
==============================================================================
12. Anchors *vimwiki-anchors*
Every header and every bold text is an anchor. To jump to it, use a wikilink
of the form >
[[file#anchor]]
For example, consider the following file "Todo.wiki": >
= My tasks =
== Home ==
- [ ] bathe my *dog*
== Work ==
- [ ] beg for *pay rise*
== Knitting club =
=== Knitting projects ===
- [ ] a funny *pig*
- [ ] a scary *dog*
Then, to jump from your index.wiki directly to your knitting projects, use: >
[[Todo#Knitting projects]]
Or, to jump to an individual project, use this link: >
[[Todo#pig]]
If there are multiple instances of an anchor, you can use the long form which
consists of the complete header hierarchy, separated by '#': >
[[Todo#My Tasks#Knitting club#Knitting projects#dog]]
If you don't feel like typing the whole stuff, type just [[Todo# and then
|i_CTRL-X_CTRL-O| to start the omni completion of anchors.
For jumping inside a single file, you can omit the file in the link: >
[[#pay rise]]
==============================================================================
11. Options *vimwiki-options*
12. Options *vimwiki-options*
There are global options and local (per-wiki) options available to tune
vimwiki.
@ -1583,7 +1631,7 @@ described in |vimwiki-temporary-wiki|. For a list of per-wiki options, see
------------------------------------------------------------------------------
11.1 Registered Wiki *g:vimwiki_list* *vimwiki-register-wiki*
12.1 Registered Wiki *g:vimwiki_list* *vimwiki-register-wiki*
One or more wikis can be registered using the |g:vimwiki_list| variable.
@ -1624,7 +1672,7 @@ For clarity, in your .vimrc file you can define wiki options using separate
------------------------------------------------------------------------------
11.2 Temporary Wiki *vimwiki-temporary-wiki*
12.2 Temporary Wiki *vimwiki-temporary-wiki*
The creation of temporary wikis allows you to open files that would not
@ -1651,7 +1699,7 @@ NOTE: Vimwiki assumes that the locations of distinct wikis do not overlap.
------------------------------------------------------------------------------
11.3 Per-Wiki Options *vimwiki-local-options*
12.3 Per-Wiki Options *vimwiki-local-options*
*vimwiki-option-path*
@ -1967,7 +2015,7 @@ Note: if you use MediaWiki syntax, you probably would like to set this option
to 0, because every indented line is considered verbatim text.
------------------------------------------------------------------------------
11.4 Global Options *vimwiki-global-options*
12.4 Global Options *vimwiki-global-options*
Global options are configured using the following pattern: >
@ -2176,17 +2224,18 @@ similar to 'local:' and 'file:' schemes, but are always opened with Vim: >
else
return 0
endif
let [idx, scheme, path, subdir, lnk, ext, url] =
let [idx, scheme, path, subdir, lnk, ext, url, anchor] =
\ vimwiki#base#resolve_scheme(link, 0)
if g:vimwiki_debug
echom 'LinkHandler: idx='.idx.', scheme=[v]'.scheme.', path='.path.
\ ', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url
\ ', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url.
\ ', anchor='.anchor
endif
if url == ''
echom 'Vimwiki Error: Unable to resolve link!'
return 0
else
call vimwiki#base#edit_file('tabnew', url, [], 0)
call vimwiki#base#edit_file('tabnew', url, '', [], 0)
return 1
endif
endfunction " }}}
@ -2208,7 +2257,7 @@ cannot otherwise convert the link. A customized handler might look like this: >
" complete URL
let url_0 = matchstr(str, g:vimwiki_rxWikiInclMatchUrl)
" URL parts
let [scheme, path, subdir, lnk, ext, url] =
let [scheme, path, subdir, lnk, ext, url, anchor] =
\ vimwiki#base#resolve_scheme(url_0, VimwikiGet('ext'))
let arg1 = matchstr(str, VimwikiWikiInclMatchArg(1))
let arg2 = matchstr(str, VimwikiWikiInclMatchArg(2))
@ -2471,7 +2520,7 @@ let g:vimwiki_diary_months = {
==============================================================================
12. Help *vimwiki-help*
13. Help *vimwiki-help*
Your help in making vimwiki better is really appreciated!
Any help, whether it is a spelling correction or a code snippet to patch --
@ -2481,7 +2530,7 @@ Issues can be filed at http://code.google.com/p/vimwiki/issues .
==============================================================================
13. Developers *vimwiki-developers*
14. Developers *vimwiki-developers*
- Maxim Kim <habamax@gmail.com> as original author.
- Stuart Andrews
@ -2494,7 +2543,7 @@ Vim plugins: http://www.vim.org/scripts/script.php?script_id=2226
==============================================================================
14. Changelog *vimwiki-changelog*
15. Changelog *vimwiki-changelog*
???~
@ -2644,7 +2693,7 @@ http://code.google.com/p/vimwiki/issues/list
* First public version.
==============================================================================
15. License *vimwiki-license*
16. License *vimwiki-license*
The MIT Licence
http://www.opensource.org/licenses/mit-license.php

View File

@ -26,13 +26,156 @@ if g:vimwiki_conceallevel && exists("+conceallevel")
let &l:conceallevel = g:vimwiki_conceallevel
endif
" MISC }}}
" GOTO FILE: gf {{{
execute 'setlocal suffixesadd='.VimwikiGet('ext')
setlocal isfname-=[,]
" gf}}}
" omnicomplete function for wiki files and anchors {{{
" XXX move to an appropriate place
let g:vimwiki_default_header_search = '^\s*\(=\{1,6}\)\([^=].*[^=]\)\1\s*$'
let g:vimwiki_default_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\s*$'
let g:vimwiki_markdown_header_search = '^\s*\(#\{1,6}\)\([^#].*\)$'
let g:vimwiki_markdown_header_match = '^\s*\(#\{1,6}\)#\@!\s*__Header__\s*$'
let g:vimwiki_media_header_search = '^\s*\(=\{1,6}\)\([^=].*[^=]\)\1\s*$'
let g:vimwiki_media_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\s*$'
let g:vimwiki_default_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@='
let g:vimwiki_default_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@='
let g:vimwiki_markdown_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@='
let g:vimwiki_markdown_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@='
let g:vimwiki_media_bold_search = "'''\\zs[^']\\+\\ze'''"
let g:vimwiki_media_bold_match = '''''''__Text__'''''''
" ^- looks strange, but is equivalent to "'''__Text__'''" but since we later
" want to call escape() on this string, we must keep it in single quotes
function! g:complete_wikifiles(findstart, base)
if a:findstart == 1
let column = col('.')-1
let line = getline('.')[:column]
let startoflink = match(line, '\[\[\zs[^\\[]*$')
if startoflink != -1
return startoflink
endif
if VimwikiGet('syntax') == 'markdown'
let startofinlinelink = match(line, '\[.*\](\zs.*$')
if startofinlinelink != -1
return startofinlinelink
endif
endif
return -1
else
if a:base !~ '#'
" we look for wiki files
if a:base =~# '^wiki\d:'
let wikinumber = eval(matchstr(a:base, '^wiki\zs\d'))
let directory = VimwikiGet('path', wikinumber)
let ext = VimwikiGet('ext', wikinumber)
let prefix = matchstr(a:base, '^wiki\d:\zs.*')
let scheme = matchstr(a:base, '^wiki\d:\ze')
elseif a:base =~# '^diary:'
let directory = VimwikiGet('path').'/'.VimwikiGet('diary_rel_path')
let ext = VimwikiGet('ext')
let prefix = matchstr(a:base, '^diary:\zs.*')
let scheme = matchstr(a:base, '^diary:\ze')
else
let directory = VimwikiGet('path')
let ext = VimwikiGet('ext')
let prefix = a:base
let scheme = ''
endif
let result = []
for wikifile in split(globpath(directory, '**/*'.ext), '\n')
" get the filename relative to the wiki path:
let subdir_filename = substitute(fnamemodify(wikifile, ':p:r'),
\ '\V'.fnamemodify(directory, ':p'), '', '')
if subdir_filename =~ '^'.prefix
call add(result, scheme . subdir_filename)
endif
endfor
return result
else
" we look for anchors in the given wikifile
let segments = split(a:base, '#', 1)
let link_infos = vimwiki#base#resolve_scheme(segments[0].'#', 0)
let wikifile = link_infos[6]
let syntax = VimwikiGet('syntax', link_infos[0])
let rxheader = g:vimwiki_{syntax}_header_search
let rxbold = g:vimwiki_{syntax}_bold_search
if !filereadable(wikifile)
return []
endif
let filecontent = readfile(wikifile)
let anchor_level = ['', '', '', '', '', '', '']
let anchors = []
for line in filecontent
" collect headers
let h_match = matchlist(line, rxheader)
if !empty(h_match)
let header = vimwiki#u#trim(h_match[2])
let level = len(h_match[1])
let anchor_level[level-1] = header
for l in range(level, 6)
let anchor_level[l] = ''
endfor
call add(anchors, header)
let complete_anchor = ''
for l in range(level-1)
if anchor_level[l] != ''
let complete_anchor .= anchor_level[l].'#'
endif
endfor
let complete_anchor .= header
call add(anchors, complete_anchor)
endif
" collect bold text (there can be several in one line)
let bold_count = 0
let bold_end = 0
while 1
let bold_text = matchstr(line, rxbold, bold_end, bold_count)
let bold_end = matchend(line, rxbold, bold_end, bold_count) + 1
if bold_text == ""
break
endif
let anchor_level[6] = bold_text
call add(anchors, bold_text)
let complete_anchor = ''
for l in range(6)
if anchor_level[l] != ''
let complete_anchor .= anchor_level[l].'#'
endif
endfor
let complete_anchor .= bold_text
call add(anchors, complete_anchor)
let bold_count += 1
endwhile
endfor
let filtered_anchors = []
let given_anchor = join(segments[1:], '#')
for anchor in anchors
if anchor =~# '^'.given_anchor
call add(filtered_anchors, segments[0].'#'.anchor)
endif
endfor
return filtered_anchors
endif
endif
endfunction
setlocal omnifunc=g:complete_wikifiles
" omnicomplete }}}
" MISC }}}
" LIST STUFF {{{
" settings necessary for the automatic formatting of lists
setlocal autoindent
@ -156,6 +299,8 @@ command! -buffer Vimwiki2HTMLBrowse
command! -buffer VimwikiAll2HTML
\ call vimwiki#html#WikiAll2HTML(expand(VimwikiGet('path_html')))
command! -buffer VimwikiTOC call vimwiki#base#table_of_contents()
command! -buffer VimwikiNextLink call vimwiki#base#find_next_link()
command! -buffer VimwikiPrevLink call vimwiki#base#find_prev_link()
command! -buffer VimwikiDeleteLink call vimwiki#base#delete_link()
@ -180,7 +325,7 @@ exe 'command! -buffer -nargs=* VimwikiSearch lvimgrep <args> '.
exe 'command! -buffer -nargs=* VWS lvimgrep <args> '.
\ escape(VimwikiGet('path').'**/*'.VimwikiGet('ext'), ' ')
command! -buffer -nargs=1 VimwikiGoto call vimwiki#base#goto("<args>")
command! -buffer -nargs=+ VimwikiGoto call vimwiki#base#goto(<f-args>)
" list commands

View File

@ -401,6 +401,7 @@ call s:default('dir_link', '')
call s:default('valid_html_tags', 'b,i,s,u,sub,sup,kbd,br,hr,div,center,strong,em')
call s:default('user_htmls', '')
call s:default('autowriteall', 1)
call s:default('toc_string', 'Contents')
call s:default('html_header_numbering', 0)
call s:default('html_header_numbering_sym', '')

View File

@ -449,7 +449,6 @@ execute 'syntax region VimwikiMath start=/^\s*'.g:vimwiki_rxMathStart.
" placeholders
syntax match VimwikiPlaceholder /^\s*%toc\%(\s.*\)\?$/ contains=VimwikiPlaceholderParam
syntax match VimwikiPlaceholder /^\s*%nohtml\s*$/
syntax match VimwikiPlaceholder /^\s*%title\%(\s.*\)\?$/ contains=VimwikiPlaceholderParam
syntax match VimwikiPlaceholder /^\s*%template\%(\s.*\)\?$/ contains=VimwikiPlaceholderParam