commit 6922836a0cbfb7e539bb1cf458eb8f1619d6188f
parent 8d7d568214cff5b9932b5ad1d0aeca39b8798969
Author: EinfachToll <istjanichtzufassen@googlemail.com>
Date: Fri, 13 Mar 2015 16:31:15 +0100
Wiki links starting with / are always relative to the wiki root
Also, links with the file: scheme are absolute iff they start with / or
drive letter
Ref #105
Diffstat:
4 files changed, 160 insertions(+), 104 deletions(-)
diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim
@@ -224,6 +224,143 @@ function! vimwiki#base#invsubdir(subdir) " {{{
return substitute(a:subdir, '[^/\.]\+/', '../', 'g')
endfunction " }}}
+
+" Returns: the number of the wiki a file belongs to
+function! vimwiki#base#find_wiki(path) "{{{
+ let path = vimwiki#path#path_norm(vimwiki#path#chomp_slash(a:path))
+ let idx = 0
+ while idx < len(g:vimwiki_list)
+ let idx_path = expand(VimwikiGet('path', idx))
+ let idx_path = vimwiki#path#path_norm(vimwiki#path#chomp_slash(idx_path))
+ if vimwiki#path#is_equal(
+ \ vimwiki#path#path_common_pfx(idx_path, path), idx_path)
+ return idx
+ endif
+ let idx += 1
+ endwhile
+
+ " an orphan page has been detected
+ return -1
+endfunction "}}}
+
+
+" THE central function of Vimwiki. Extract infos about the target from a link.
+" If the second parameter is present, which should be an absolute file path, it
+" is assumed that the link appears in that file. Without it, the current file
+" is used.
+function! vimwiki#base#resolve_link(link_text, ...) "{{{
+ if a:0
+ let source_wiki = vimwiki#base#find_wiki(a:1)
+ let source_file = a:1
+ else
+ let source_wiki = g:vimwiki_current_idx
+ let source_file = expand('%:p')
+ endif
+
+ let link_text = a:link_text
+
+ " if link is schemeless add wikiN: scheme
+ if link_text !~# g:vimwiki_rxSchemeUrl
+ let link_text = 'wiki'.source_wiki.':'.link_text
+ endif
+
+
+ let link_infos = {
+ \ 'index': -1,
+ \ 'scheme': '',
+ \ 'filename': '',
+ \ 'anchor': '',
+ \ }
+
+
+ " extract scheme
+ let link_infos.scheme = matchstr(link_text, g:vimwiki_rxSchemeUrlMatchScheme)
+ if !(link_infos.scheme =~# '\mwiki\d\+' || link_infos.scheme ==# 'diary' ||
+ \ link_infos.scheme ==# 'local' || link_infos.scheme ==# 'file')
+ let link_infos.filename = '' " malformed link
+ return link_infos
+ endif
+ let link_text = matchstr(link_text, g:vimwiki_rxSchemeUrlMatchUrl)
+
+ let is_wiki_link = link_infos.scheme =~# '\mwiki\d\+' ||
+ \ link_infos.scheme ==# 'diary'
+
+ " extract anchor
+ if is_wiki_link
+ let split_lnk = split(link_text, '#', 1)
+ let link_text = split_lnk[0]
+ if len(split_lnk) > 1 && split_lnk[-1] != ''
+ let link_infos.anchor = join(split_lnk[1:], '#')
+ endif
+ if link_text == '' " because the link was of the form '#anchor'
+ let link_text = fnamemodify(source_file, ':p:t:r')
+ endif
+ endif
+
+ " check if absolute or relative path
+ if is_wiki_link && link_text[0] == '/'
+ let link_text = link_text[1:]
+ let is_relative = 0
+ elseif !is_wiki_link && (link_text[0] == '/' ||
+ \ (link_text =~? '\m^\a:' && vimwiki#u#is_windows()))
+ let is_relative = 0
+ else
+ let is_relative = 1
+ let root_dir = fnamemodify(source_file, ':p:h') . '/'
+ endif
+
+
+ " extract the other items depending on the scheme
+ if link_infos.scheme =~# '\mwiki\d\+'
+ let link_infos.index = eval(matchstr(link_infos.scheme, '\D\+\zs\d\+\ze'))
+ if link_infos.index < 0 || link_infos.index >= len(g:vimwiki_list)
+ let link_infos.filename = ''
+ return link_infos
+ endif
+
+ if !is_relative
+ let root_dir = VimwikiGet('path', link_infos.index)
+ endif
+
+ let link_infos.filename = root_dir . link_text
+
+ if vimwiki#path#is_link_to_dir(link_text)
+ if g:vimwiki_dir_link != ''
+ let link_infos.filename .= g:vimwiki_dir_link .
+ \ VimwikiGet('ext', link_infos.index)
+ endif
+ else
+ let link_infos.filename .= VimwikiGet('ext', link_infos.index)
+ endif
+
+ elseif link_infos.scheme ==# 'diary'
+ let link_infos.index = source_wiki
+
+ let link_infos.filename =
+ \ VimwikiGet('path', link_infos.index) .
+ \ VimwikiGet('diary_rel_path', link_infos.index) .
+ \ link_text .
+ \ VimwikiGet('ext', link_infos.index)
+ elseif (link_infos.scheme ==# 'file' && is_relative) ||
+ \ link_infos.scheme ==# 'local'
+ let link_infos.filename = root_dir . link_text
+ else " absolute file link
+ " collapse repeated leading "/"'s within a link
+ let link_text = substitute(link_text, '\m^/*', '/', '')
+ " convert "/~..." into "~..." for fnamemodify
+ let link_text = substitute(link_text, '\m^/\~', '\~', '')
+ " convert /C: to C: (or fnamemodify(...":p:h") interpret it as C:\C:)
+ if vimwiki#u#is_windows()
+ let link_text = substitute(link_text, '\m^/\ze[[:alpha:]]:', '', '')
+ endif
+ let link_infos.filename = link_text
+ endif
+
+ let link_infos.filename = vimwiki#path#normalize(link_infos.filename)
+ return link_infos
+endfunction "}}}
+
+
" vimwiki#base#resolve_scheme
function! vimwiki#base#resolve_scheme(lnk, as_html, ...) " {{{ Resolve scheme
let quiet = a:0 && a:1 ? 1 : 0
@@ -405,31 +542,22 @@ endfunction "}}}
" vimwiki#base#open_link
function! vimwiki#base#open_link(cmd, link, ...) "{{{
- let [idx, scheme, path, subdir, lnk, ext, url, anchor] =
- \ vimwiki#base#resolve_scheme(a:link, 0)
+ let link_infos = vimwiki#base#resolve_link(a:link)
- " wikilinks of the form [[#anchor]]
- if url == '' && anchor != ''
- let lnk = expand('%:t:r')
- let url = path.subdir.lnk.ext
+ if g:vimwiki_debug
+ echom 'open_link:' string(link_infos)
endif
- if url == ''
- if g:vimwiki_debug
- echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url.', anchor='.anchor
- endif
+ if link_infos.filename == ''
echom 'Vimwiki Error: Unable to resolve link!'
return
endif
- let update_prev_link = ( (scheme == '' || scheme =~# 'wiki' || scheme =~# 'diary')
- \ && !vimwiki#path#is_equal(lnk, expand('%:t:r'))
- \ ? 1 : 0)
+ let is_wiki_link = link_infos.scheme =~# '\mwiki\d\+'
+ \ || link_infos.scheme =~# 'diary'
- let use_system_open = (
- \ scheme == '' ||
- \ scheme =~# 'wiki' ||
- \ scheme =~# 'diary' ? 0 : 1)
+ let update_prev_link = is_wiki_link &&
+ \ !vimwiki#path#is_equal(link_infos.filename, expand('%:p'))
let vimwiki_prev_link = []
" update previous link for wiki pages
@@ -442,19 +570,15 @@ function! vimwiki#base#open_link(cmd, link, ...) "{{{
endif
" open/edit
- if g:vimwiki_debug
- 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, anchor,
+ if is_wiki_link
+ call vimwiki#base#edit_file(a:cmd, link_infos.filename, link_infos.anchor,
\ vimwiki_prev_link, update_prev_link)
- if idx != g:vimwiki_current_idx
+ if link_infos.index != g:vimwiki_current_idx
" this call to setup_buffer_state may not be necessary
- call vimwiki#base#setup_buffer_state(idx)
+ call vimwiki#base#setup_buffer_state(link_infos.index)
endif
+ else
+ call vimwiki#base#system_open_link(link_infos.filename)
endif
endfunction " }}}
@@ -678,50 +802,6 @@ function! s:jump_to_anchor(anchor) "{{{
endfor
endfunction "}}}
-" Returns: the absolute file path (and possibly an anchor) of the target file,
-" if a link with the given link text appears in the given wiki file, which
-" belongs to the given wiki nr
-function! s:link_target(source_file, wiki_nr, link_text) "{{{
- let [target_idx, scheme, path, subdir, lnk, ext, url, anchor] =
- \ vimwiki#base#resolve_scheme(a:link_text, 0, 1)
- let source_dir = fnamemodify(a:source_file, ':p:h').'/'
-
- if lnk =~# '/$' " link to a directory
- return []
- elseif url == '' && anchor != '' " only anchor
- return [fnamemodify(a:source_file, ':p'), anchor]
- elseif scheme ==# 'file'
- return [url, '']
- elseif scheme ==# 'local'
- return [vimwiki#path#normalize(source_dir.lnk), '']
- elseif target_idx >= len(g:vimwiki_list) " a malformed link
- return ['', '']
- elseif scheme !~# '^wiki\d\+\|diary' " unknown scheme
- return []
- endif
-
- if scheme ==# 'diary'
- let root_dir = VimwikiGet('path',a:wiki_nr).
- \ VimwikiGet('diary_rel_path', a:wiki_nr)
- let ext = VimwikiGet('ext', a:wiki_nr)
- else
- " a schemeless link is like a link to the current wiki
- if a:link_text !~# '^wiki\d\+:'
- let target_idx = a:wiki_nr
- endif
-
- if target_idx == a:wiki_nr
- let root_dir = source_dir
- else
- let root_dir = VimwikiGet('path', target_idx)
- endif
- let ext = VimwikiGet('ext', target_idx)
- endif
-
- let target_file = root_dir . lnk . ext
- return [vimwiki#path#normalize(target_file), anchor]
-endfunction "}}}
-
" Params: full path to a wiki file and its wiki number
" Returns: a list of all links inside the wiki file
" Every list item has the form
@@ -747,11 +827,9 @@ function! s:get_links(wikifile, idx) "{{{
break
endif
let link_count += 1
- let target = s:link_target(a:wikifile, a:idx, link_text)
- if !empty(target)
- call add(target, lnum)
- call add(target, col)
- call add(links, target)
+ let target = vimwiki#base#resolve_link(link_text, a:wikifile)
+ if target.filename != ''
+ call add(links, [target.filename, target.anchor, lnum, col])
endif
endwhile
endfor
diff --git a/autoload/vimwiki/path.vim b/autoload/vimwiki/path.vim
@@ -49,10 +49,7 @@ endfunction "}}}
function! vimwiki#path#is_link_to_dir(link) "{{{
" Check if link is to a directory.
" It should be ended with \ or /.
- if a:link =~# '.\+[/\\]$'
- return 1
- endif
- return 0
+ return a:link =~# '\m[/\\]$'
endfunction "}}}
function! vimwiki#path#abs_path_of_link(link) "{{{
diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim
@@ -84,9 +84,9 @@ function! Complete_wikifiles(findstart, base)
let segments = split(a:base, '#', 1)
let given_wikifile = segments[0] == '' ? expand('%:t:r') : segments[0]
- let link_infos = vimwiki#base#resolve_scheme(given_wikifile.'#', 0, 1)
- let wikifile = link_infos[6]
- let syntax = VimwikiGet('syntax', link_infos[0])
+ let link_infos = vimwiki#base#resolve_link(given_wikifile.'#')
+ let wikifile = link_infos.filename
+ let syntax = VimwikiGet('syntax', link_infos.index)
let anchors = vimwiki#base#get_anchors(wikifile, syntax)
let filtered_anchors = []
diff --git a/plugin/vimwiki.vim b/plugin/vimwiki.vim
@@ -31,23 +31,6 @@ function! s:default(varname, value) "{{{
endif
endfunction "}}}
-function! s:find_wiki(path) "{{{
- " XXX: find_wiki() does not (yet) take into consideration the ext
- let path = vimwiki#path#path_norm(vimwiki#path#chomp_slash(a:path))
- let idx = 0
- while idx < len(g:vimwiki_list)
- let idx_path = expand(VimwikiGet('path', idx))
- let idx_path = vimwiki#path#path_norm(vimwiki#path#chomp_slash(idx_path))
- if vimwiki#path#is_equal(
- \ vimwiki#path#path_common_pfx(idx_path, path), idx_path)
- return idx
- endif
- let idx += 1
- endwhile
- return -1
- " an orphan page has been detected
-endfunction "}}}
-
function! s:path_html(idx) "{{{
let path_html = VimwikiGet('path_html', a:idx)
if !empty(path_html)
@@ -114,8 +97,7 @@ function! s:setup_filetype() "{{{
let time0 = reltime() " start the clock "XXX
" Find what wiki current buffer belongs to.
let path = expand('%:p:h')
- " XXX: find_wiki() does not (yet) take into consideration the ext
- let idx = s:find_wiki(path)
+ let idx = vimwiki#base#find_wiki(path)
if g:vimwiki_debug == 3
echom " Setup_filetype g:curr_idx=".g:vimwiki_current_idx." find_idx=".idx." b:curr_idx=".s:vimwiki_idx().""
endif
@@ -166,8 +148,7 @@ function! s:setup_buffer_enter() "{{{
" buffer's path and ext.
" Else set g:vimwiki_current_idx to that wiki index.
let path = expand('%:p:h')
- " XXX: find_wiki() does not (yet) take into consideration the ext
- let idx = s:find_wiki(path)
+ let idx = vimwiki#base#find_wiki(path)
if g:vimwiki_debug ==3
echom " Setup_buffer_enter g:curr_idx=".g:vimwiki_current_idx." find_idx=".idx." b:curr_idx=".s:vimwiki_idx().""