" vim: set fdm=marker et ts=4 sw=4 sts=4: function! pandoc#hypertext#Init() abort if !exists('g:pandoc#hypertext#open_editable_alternates') let g:pandoc#hypertext#open_editable_alternates = 1 endif if !exists('g:pandoc#hypertext#editable_alternates_extensions') let g:pandoc#hypertext#editable_alternates_extensions ='\(pdf\|htm\|odt\|doc\)' endif if !exists('g:pandoc#hypertext#create_if_no_alternates_exists') let g:pandoc#hypertext#create_if_no_alternates_exists = 0 endif if !exists('g:pandoc#hypertext#split_open_cmd') let g:pandoc#hypertext#split_open_cmd = 'botright vsplit' endif if !exists('g:pandoc#hypertext#edit_open_cmd') let g:pandoc#hypertext#edit_open_cmd = 'edit' endif if !exists('g:pandoc#hypertext#preferred_alternate') let g:pandoc#hypertext#preferred_alternate = 'md' endif if !exists('g:pandoc#hypertext#use_default_mappings') let g:pandoc#hypertext#use_default_mappings = 1 endif if !exists('g:pandoc#hypertext#autosave_on_edit_open_link') let g:pandoc#hypertext#autosave_on_edit_open_link = 0 endif if exists('g:pandoc#hypertext#automatic_link_regex') let s:automatic_link_regex = g:pandoc#hypertext#automatic_link_regex else let s:automatic_link_regex = '\v\<([^>]+)\>' endif if exists('g:pandoc#hypertext#inline_link_regex') let s:inline_link_regex = g:pandoc#hypertext#inline_link_regex else let s:inline_link_regex = '\v!?\[[^]]+\]\(([^) \t]+).*\)' endif if exists('g:pandoc#hypertext#reference_link_regex') let s:reference_link_regex = g:pandoc#hypertext#reference_link_regex else let s:reference_link_regex = '\v!?\[[^]]+\]%(\[([^]]*)\])?' endif if exists('g:pandoc#hypertext#referenced_link_regex') let s:referenced_link_regex = g:pandoc#hypertext#referenced_link_regex else let s:referenced_link_regex = '\v\[[^]]+\]:\s*([^\t ]+)' endif nnoremap (pandoc-hypertext-open-local) :call pandoc#hypertext#OpenLocal() nnoremap (pandoc-hypertext-open-system) :call pandoc#hypertext#OpenSystem() nnoremap (pandoc-hypertext-goto-id) :call pandoc#hypertext#GotoID() if g:pandoc#hypertext#use_default_mappings == 1 nmap gf (pandoc-hypertext-open-local) nmap gx (pandoc-hypertext-open-system) nmap xi (pandoc-hypertext-goto-id) endif endfunction function! s:IsEditable(path) abort let exts = [] for type_exts in values(g:pandoc_extensions_table) for ext in type_exts call add(exts, fnamemodify('*.'.ext, ':e')) endfor endfor if index(exts, fnamemodify(a:path, ':e')) > -1 return 1 endif return 0 endfunction function! s:SortAlternates(a, b) abort let ext = fnamemodify(a:a, ':e') if ext ==? g:pandoc#hypertext#preferred_alternate " return 1 will cass the preferred on at the last return -1 endif " return 0 will cause others before the preferred return 1 endfunction function! s:FindAlternates(path) abort let candidates = glob(fnamemodify(a:path, ':r').'.*', 0, 1) if candidates !=# [] return filter(candidates, 's:IsEditable(v:val) && v:val !=# glob(a:path)') endif return [] endfunction function! s:ExtendedCFILE() abort let orig_isfname = &isfname let &isfname = orig_isfname . ',?,&,:' let addr = expand('') let &isfname = orig_isfname return addr endfunction function! pandoc#hypertext#PushLink(link) abort if !exists('w:link_stack') let w:link_stack = [] endif let w:link_stack = add(w:link_stack, a:link) endfunction function! pandoc#hypertext#PopLink() abort if exists('w:link_stack') try let link = remove(w:link_stack,-1) catch return ['',''] endtry else return ['',''] endif return link endfunction " MatchstrAtCursor(pattern) " Returns part of the line that matches pattern at cursor " Copied from vimwiki plugin: autoload/base.vim function! s:MatchstrAtCursor(pattern) abort "{{{1 let col = col('.') - 1 let line = getline('.') let ebeg = -1 let cont = match(line, a:pattern, 0) while (ebeg >= 0 || (0 <= cont) && (cont <= col)) let contn = matchend(line, a:pattern, cont) if (cont <= col) && (col < contn) let ebeg = match(line, a:pattern, cont) let elen = contn - ebeg break else let cont = match(line, a:pattern, contn) endif endwh if ebeg >= 0 return strpart(line, ebeg, elen) else return '' endif endfunc " }}}1 " GetLinkAtCursor(pat) " get the specified type of link at cursor function! s:GetLinkAtCursor(pat) abort "{{{1 let matched_str = s:MatchstrAtCursor(a:pat) let url = substitute(matched_str, a:pat, '\1', 'g') let indices = [1, 2] if '!' ==# matched_str[:0] let indices = [2, 3] endif if '][]' ==# matched_str[-3:] let indices[1] += 2 endif " for [hypertext][] if url ==# '' let url = strpart(matched_str, indices[0], strlen(matched_str) - indices[1]) endif return url endfunc " }}}1 function! s:GetReferenceUrl(ref) abort let pattern = '\v\c\s*\['.a:ref.'\]:\s*([^ ]+)' let linenum = search(pattern, 'nw') let url = substitute(getline(linenum), pattern, '\1', 'g') " if no reference URL exists, fall back to an implicit header reference if url ==# '' let url = '#' . markdown#headers#GetAutomaticID(a:ref) endif return url endfunction " GetLinkAddress " get the link at cursor function! pandoc#hypertext#GetLinkAddress() abort let link = s:GetLinkAtCursor(s:automatic_link_regex) " get link at cursor if link ==# '' let link = s:GetLinkAtCursor(s:inline_link_regex) if link ==# '' let link = s:GetLinkAtCursor(s:reference_link_regex) if link ==# '' let link = s:GetLinkAtCursor(s:referenced_link_regex) else " find the reference link let link = s:GetReferenceUrl(link) endif endif endif return link endfunction function! pandoc#hypertext#OpenFileWithCmd(file, cmd, push) abort if a:cmd ==# g:pandoc#hypertext#edit_open_cmd if &modified ==# 1 && \ g:pandoc#hypertext#autosave_on_edit_open_link == 1 exe 'write' endif if a:push == 1 call pandoc#hypertext#PushLink( ['file', expand('%:p')] ) endif endif exe a:cmd . ' ' . a:file endfunction function! pandoc#hypertext#OpenLocal(...) abort if exists('a:1') let addr = a:1 else let addr = s:ExtendedCFILE() endif if exists('a:2') let cmd = a:2 else let cmd = g:pandoc#hypertext#split_open_cmd endif if g:pandoc#hypertext#open_editable_alternates == 1 let ext = fnamemodify(addr, ':e') if ext =~ g:pandoc#hypertext#editable_alternates_extensions let alt_addrs = s:FindAlternates(addr) if alt_addrs !=# [] let pos = 0 if len(alt_addrs) > 1 let alt_file = fnamemodify(addr, ':r') . '.' . g:pandoc#hypertext#preferred_alternate let pos = index(alt_addrs, glob(alt_file)) if pos == -1 let pos = 0 endif endif let addr = alt_addrs[pos] else " check weather to create the alternate file if g:pandoc#hypertext#create_if_no_alternates_exists == 1 let dir = fnamemodify(addr, ':p:h') if !isdirectory(dir) call system('mkdir -p '.dir) endif let addr = fnamemodify(addr, ':r') . '.' . g:pandoc#hypertext#preferred_alternate call pandoc#hypertext#OpenFileWithCmd(addr, cmd, 1) else call pandoc#hypertext#OpenSystem(addr) endif return endif endif endif if glob(addr) !=# '' || g:pandoc#hypertext#create_if_no_alternates_exists == 1 call pandoc#hypertext#OpenFileWithCmd(addr, cmd, 1) endif endfunction function! pandoc#hypertext#OpenSystem(...) abort if exists('a:1') let addr = a:1 else let addr = s:ExtendedCFILE() endif if has('unix') && executable('xdg-open') call system('xdg-open '. shellescape(expand(addr,':p'))) elseif has('win32') || has('win64') call system('cmd /c "start '. addr .'"') elseif has('macunix') call system('open '. addr) endif endfunction function! pandoc#hypertext#OpenLink(cmd) abort let url = pandoc#hypertext#GetLinkAddress() let ext = fnamemodify(url, ':e') let hashnum = match(url, '#') let sname = synIDattr(synID(line('.'), col('.'), 0), 'name') let curpos = getcurpos() let pos = getpos('.') let curfile = expand('%:p') if hashnum != -1 && hashnum != 0 let id = url[hashnum + 1:] let url = url[:hashnum - 1] let ext = fnamemodify(url, ':e') endif if '#' ==# url[:0] call pandoc#hypertext#GotoID(url[1:], sname, curpos, pos) elseif ext =~ g:pandoc#hypertext#editable_alternates_extensions || s:IsEditable(url) call pandoc#hypertext#OpenLocal(url, a:cmd) if hashnum != -1 call pandoc#hypertext#GotoID(id, sname, curpos, pos) call pandoc#hypertext#PushLink( ['file', curfile] ) endif else call pandoc#hypertext#OpenSystem(url) endif endfunction function! pandoc#hypertext#BackFromLink() abort let [type, link] = pandoc#hypertext#PopLink() if type ==# 'position' call setpos('.', link) elseif type ==# 'file' call pandoc#hypertext#OpenFileWithCmd(link, g:pandoc#hypertext#edit_open_cmd, 0) endif endfunction function! pandoc#hypertext#BackFromFile() abort if exists('w:link_stack') let types = map(reverse(copy(w:link_stack)), 'v:val[0]') let i = index(types, 'file') if i != -1 let w:link_stack = w:link_stack[0:-i-1] call pandoc#hypertext#BackFromLink() endif endif endfunction function! pandoc#hypertext#GotoID(...) abort if a:2 !=# 'pandocHeaderID' if exists('a:1') let id = a:1 else let id = expand('') endif try " call pandoc#hypertext#PushLink( ['position',getcurpos()] ) call pandoc#hypertext#PushLink( ['position',a:3] ) catch /E117/ " call pandoc#hypertext#PushLink( ['position',getpos('.')] ) call pandoc#hypertext#PushLink( ['position', a:4] ) endtry " header indentifier let header_pos = markdown#headers#GetAllIDs() let line = get(header_pos, id) if line > 0 call cursor(line, 1) else call pandoc#hypertext#BackFromLink() endif endif endfunction