| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- " 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 <silent> <buffer> <Plug>(pandoc-hypertext-open-local) :<C-u>call pandoc#hypertext#OpenLocal()<cr>
- nnoremap <silent> <buffer> <Plug>(pandoc-hypertext-open-system) :<C-u>call pandoc#hypertext#OpenSystem()<cr>
- nnoremap <silent> <buffer> <Plug>(pandoc-hypertext-goto-id) :<C-u>call pandoc#hypertext#GotoID()<cr>
- if g:pandoc#hypertext#use_default_mappings == 1
- nmap <buffer> gf <Plug>(pandoc-hypertext-open-local)
- nmap <buffer> gx <Plug>(pandoc-hypertext-open-system)
- nmap <buffer> <localleader>xi <Plug>(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('<cfile>')
- 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('<cfile>')
- 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
|