Skip to content

Commit

Permalink
feat: add initial version of WikiPageRefile
Browse files Browse the repository at this point in the history
refer: #58
  • Loading branch information
lervag committed Feb 11, 2024
1 parent 8e80def commit 5590eae
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 3 deletions.
3 changes: 3 additions & 0 deletions autoload/wiki/buffer.vim
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function! s:init_buffer_commands() abort " {{{1
command! -buffer WikiLinkIncomingToggle call wiki#link#incoming_display_toggle()
command! -buffer WikiLinkIncomingHover call wiki#link#incoming_hover()
command! -buffer WikiPageDelete call wiki#page#delete()
command! -buffer WikiPageRefile call wiki#page#refile()
command! -buffer WikiPageRename call wiki#page#rename()
command! -buffer WikiPageRenameSection call wiki#page#rename_section()
command! -buffer WikiToc call g:wiki_select_method.toc()
Expand Down Expand Up @@ -113,6 +114,7 @@ function! s:init_buffer_mappings() abort " {{{1
nnoremap <silent><buffer> <plug>(wiki-link-incoming-toggle) :WikiLinkIncomingToggle<cr>
nnoremap <silent><buffer> <plug>(wiki-link-incoming-hover) :WikiLinkIncomingHover<cr>
nnoremap <silent><buffer> <plug>(wiki-page-delete) :WikiPageDelete<cr>
nnoremap <silent><buffer> <plug>(wiki-page-refile) :WikiPageRefile<cr>
nnoremap <silent><buffer> <plug>(wiki-page-rename) :WikiPageRename<cr>
nnoremap <silent><buffer> <plug>(wiki-page-rename-section) :WikiPageRenameSection<cr>
nnoremap <silent><buffer> <plug>(wiki-toc-generate) :WikiTocGenerate<cr>
Expand Down Expand Up @@ -175,6 +177,7 @@ function! s:init_buffer_mappings() abort " {{{1
\ '<plug>(wiki-link-incoming-toggle)': '<leader>wli',
\ '<plug>(wiki-link-incoming-hover)': '<leader>wlI',
\ '<plug>(wiki-page-delete)': '<leader>wd',
\ '<plug>(wiki-page-refile)' : '<leader>wq',
\ '<plug>(wiki-page-rename)': '<leader>wr',
\ '<plug>(wiki-page-rename-section)': '<f2>',
\ '<plug>(wiki-toc-generate)': '<leader>wt',
Expand Down
45 changes: 42 additions & 3 deletions autoload/wiki/page.vim
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,39 @@ function! wiki#page#rename_section(...) abort "{{{1
call s:update_links_external(l:source, l:target)
endfunction

" }}}1
function! wiki#page#refile(...) abort "{{{1
let l:opts = extend(#{
\ target_page: '',
\ target_lnum: 0,
\}, a:0 > 0 ? a:1 : {})

" target_page could be given by user input with something like this:
" let l:opts.target_page = input('> ', '', 'customlist,wiki#complete#url')

let l:source = wiki#page#refile#collect_source(l:opts)
if empty(l:source)
return wiki#log#error('No source section recognized!')
endif

try
let l:target = wiki#page#refile#collect_target(l:opts, l:source)
catch /wiki.vim: target page not found/
return wiki#log#error('Target page was not found!')
catch /wiki.vim: anchor not recognized/
return wiki#log#error('Target anchor not recognized!')
endtry

call wiki#log#info(
\ printf('Moving section "%s" into "%s"',
\ l:source.header, wiki#paths#to_node(l:target.path)))

call wiki#page#refile#move(l:source, l:target)

call s:update_links_local(l:source, l:target)
call s:update_links_external(l:source, l:target)
endfunction

" }}}1
function! wiki#page#export(line1, line2, ...) abort " {{{1
let l:cfg = deepcopy(g:wiki_export)
Expand Down Expand Up @@ -287,14 +320,20 @@ endfunction
" }}}1
function! s:update_links_local(old, new) abort "{{{1
" Arguments:
" old: dict(anchor)
" new: dict(anchor)
" old: dict(anchor, path?)
" new: dict(anchor, path?)
let l:pos = getcurpos()

let l:anchor = !has_key(a:old, 'path') || a:old.path ==# a:new.path
\ ? a:new.anchor
\ : wiki#paths#to_wiki_url(a:new.path) . a:new.anchor

keeppattern keepjumps execute printf('%%s/\V%s/%s/e%s',
\ a:old.anchor,
\ a:new.anchor,
\ l:anchor,
\ &gdefault ? '' : 'g')
silent update

call cursor(l:pos[1:])
endfunction

Expand Down
133 changes: 133 additions & 0 deletions autoload/wiki/page/refile.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
" A wiki plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email: [email protected]
"

function! wiki#page#refile#collect_source(...) abort " {{{1
" Returns:
" source: dict(path, lnum, lnum_end, header, anchor, level)

let l:source = wiki#toc#get_section()
if !empty(l:source)
let l:source.path = expand('%:p')
endif

return l:source
endfunction

" }}}1
function! wiki#page#refile#collect_target(opts, source) abort " {{{1
" Arguments:
" opts: dict(
" target_page,
" target_lnum,
" target_anchor_before?,
" )
" source: dict(path, lnum, lnum_end, header, anchor)
" Returns:
" target: dict(path, lnum, anchor, level)

let l:path = wiki#u#eval_filename(a:opts.target_page)
if !filereadable(l:path)
throw 'wiki.vim: target page not found'
endif


if has_key(a:opts, 'target_anchor_before')
return s:collect_target_by_anchor_before(
\ l:path,
\ a:opts.target_anchor_before,
\ a:source
\)
endif

return s:collect_target_by_lnum(l:path, a:opts.target_lnum, a:source)
endfunction

" }}}1
function! wiki#page#refile#move(source, target) abort " {{{1
" Arguments:
" source: dict(path, lnum, lnum_end)
" target: dict(path, lnum)

if a:target.level < a:source.level
call execute(printf('%d,%dg/^#/normal! 0%dx',
\ a:source.lnum, a:source.lnum_end, a:source.level - a:target.level))
elseif a:target.level > a:source.level
call execute(printf('%d,%dg/^#/normal! 0%di#',
\ a:source.lnum, a:source.lnum_end, a:target.level - a:source.level))
endif

if a:target.path ==# a:source.path
call execute(printf('%d,%dm %d',
\ a:source.lnum, a:source.lnum_end, a:target.lnum))
silent write
else
let l:lines = getline(a:source.lnum, a:source.lnum_end)
call deletebufline('', a:source.lnum, a:source.lnum_end)
silent write

let l:current_bufnr = bufnr('')
let l:was_loaded = bufloaded(a:target.path)
keepalt execute 'silent edit' fnameescape(a:target.path)
call append(a:target.lnum, l:lines)
silent write
if !l:was_loaded
keepalt execute 'bwipeout'
endif
keepalt execute 'buffer' l:current_bufnr
endif
endfunction

" }}}1

function! s:collect_target_by_anchor_before(path, anchor, source) abort " {{{1
let l:section = {}
for l:section in wiki#toc#gather_entries(#{ path: a:path })
if l:section.anchor ==# a:anchor
break
endif
endfor

if empty(l:section)
throw 'wiki.vim: anchor not recognized'
endif

let l:anchors = get(l:section, 'anchors', [])
if len(l:anchors) > 0
call remove(l:anchors, -1)
endif
let l:anchors += [a:source.anchors[-1]]

return #{
\ path: a:path,
\ lnum: l:section.lnum - 1,
\ anchor: '#' . join(l:anchors, '#'),
\ level: len(l:anchors)
\}
endfunction

" }}}1
function! s:collect_target_by_lnum(path, lnum, source) abort " {{{1
let l:anchors = [a:source.anchors[-1]]

if a:source.level > 1
let l:section = wiki#toc#get_section(#{ path: a:path, at_lnum: a:lnum })
let l:target_anchors = get(l:section, 'anchors', [])
call extend(
\ l:anchors,
\ l:target_anchors[:a:source.level - 2],
\ 0
\)
endif

return #{
\ path: a:path,
\ lnum: a:lnum,
\ anchor: '#' . join(l:anchors, '#'),
\ level: len(l:anchors)
\}
endfunction

" }}}1

0 comments on commit 5590eae

Please sign in to comment.