Skip to content

Commit 5590eae

Browse files
committed
feat: add initial version of WikiPageRefile
refer: #58
1 parent 8e80def commit 5590eae

File tree

3 files changed

+178
-3
lines changed

3 files changed

+178
-3
lines changed

autoload/wiki/buffer.vim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ function! s:init_buffer_commands() abort " {{{1
6262
command! -buffer WikiLinkIncomingToggle call wiki#link#incoming_display_toggle()
6363
command! -buffer WikiLinkIncomingHover call wiki#link#incoming_hover()
6464
command! -buffer WikiPageDelete call wiki#page#delete()
65+
command! -buffer WikiPageRefile call wiki#page#refile()
6566
command! -buffer WikiPageRename call wiki#page#rename()
6667
command! -buffer WikiPageRenameSection call wiki#page#rename_section()
6768
command! -buffer WikiToc call g:wiki_select_method.toc()
@@ -113,6 +114,7 @@ function! s:init_buffer_mappings() abort " {{{1
113114
nnoremap <silent><buffer> <plug>(wiki-link-incoming-toggle) :WikiLinkIncomingToggle<cr>
114115
nnoremap <silent><buffer> <plug>(wiki-link-incoming-hover) :WikiLinkIncomingHover<cr>
115116
nnoremap <silent><buffer> <plug>(wiki-page-delete) :WikiPageDelete<cr>
117+
nnoremap <silent><buffer> <plug>(wiki-page-refile) :WikiPageRefile<cr>
116118
nnoremap <silent><buffer> <plug>(wiki-page-rename) :WikiPageRename<cr>
117119
nnoremap <silent><buffer> <plug>(wiki-page-rename-section) :WikiPageRenameSection<cr>
118120
nnoremap <silent><buffer> <plug>(wiki-toc-generate) :WikiTocGenerate<cr>
@@ -175,6 +177,7 @@ function! s:init_buffer_mappings() abort " {{{1
175177
\ '<plug>(wiki-link-incoming-toggle)': '<leader>wli',
176178
\ '<plug>(wiki-link-incoming-hover)': '<leader>wlI',
177179
\ '<plug>(wiki-page-delete)': '<leader>wd',
180+
\ '<plug>(wiki-page-refile)' : '<leader>wq',
178181
\ '<plug>(wiki-page-rename)': '<leader>wr',
179182
\ '<plug>(wiki-page-rename-section)': '<f2>',
180183
\ '<plug>(wiki-toc-generate)': '<leader>wt',

autoload/wiki/page.vim

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,39 @@ function! wiki#page#rename_section(...) abort "{{{1
162162
call s:update_links_external(l:source, l:target)
163163
endfunction
164164

165+
" }}}1
166+
function! wiki#page#refile(...) abort "{{{1
167+
let l:opts = extend(#{
168+
\ target_page: '',
169+
\ target_lnum: 0,
170+
\}, a:0 > 0 ? a:1 : {})
171+
172+
" target_page could be given by user input with something like this:
173+
" let l:opts.target_page = input('> ', '', 'customlist,wiki#complete#url')
174+
175+
let l:source = wiki#page#refile#collect_source(l:opts)
176+
if empty(l:source)
177+
return wiki#log#error('No source section recognized!')
178+
endif
179+
180+
try
181+
let l:target = wiki#page#refile#collect_target(l:opts, l:source)
182+
catch /wiki.vim: target page not found/
183+
return wiki#log#error('Target page was not found!')
184+
catch /wiki.vim: anchor not recognized/
185+
return wiki#log#error('Target anchor not recognized!')
186+
endtry
187+
188+
call wiki#log#info(
189+
\ printf('Moving section "%s" into "%s"',
190+
\ l:source.header, wiki#paths#to_node(l:target.path)))
191+
192+
call wiki#page#refile#move(l:source, l:target)
193+
194+
call s:update_links_local(l:source, l:target)
195+
call s:update_links_external(l:source, l:target)
196+
endfunction
197+
165198
" }}}1
166199
function! wiki#page#export(line1, line2, ...) abort " {{{1
167200
let l:cfg = deepcopy(g:wiki_export)
@@ -287,14 +320,20 @@ endfunction
287320
" }}}1
288321
function! s:update_links_local(old, new) abort "{{{1
289322
" Arguments:
290-
" old: dict(anchor)
291-
" new: dict(anchor)
323+
" old: dict(anchor, path?)
324+
" new: dict(anchor, path?)
292325
let l:pos = getcurpos()
326+
327+
let l:anchor = !has_key(a:old, 'path') || a:old.path ==# a:new.path
328+
\ ? a:new.anchor
329+
\ : wiki#paths#to_wiki_url(a:new.path) . a:new.anchor
330+
293331
keeppattern keepjumps execute printf('%%s/\V%s/%s/e%s',
294332
\ a:old.anchor,
295-
\ a:new.anchor,
333+
\ l:anchor,
296334
\ &gdefault ? '' : 'g')
297335
silent update
336+
298337
call cursor(l:pos[1:])
299338
endfunction
300339

autoload/wiki/page/refile.vim

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
" A wiki plugin for Vim
2+
"
3+
" Maintainer: Karl Yngve Lervåg
4+
5+
"
6+
7+
function! wiki#page#refile#collect_source(...) abort " {{{1
8+
" Returns:
9+
" source: dict(path, lnum, lnum_end, header, anchor, level)
10+
11+
let l:source = wiki#toc#get_section()
12+
if !empty(l:source)
13+
let l:source.path = expand('%:p')
14+
endif
15+
16+
return l:source
17+
endfunction
18+
19+
" }}}1
20+
function! wiki#page#refile#collect_target(opts, source) abort " {{{1
21+
" Arguments:
22+
" opts: dict(
23+
" target_page,
24+
" target_lnum,
25+
" target_anchor_before?,
26+
" )
27+
" source: dict(path, lnum, lnum_end, header, anchor)
28+
" Returns:
29+
" target: dict(path, lnum, anchor, level)
30+
31+
let l:path = wiki#u#eval_filename(a:opts.target_page)
32+
if !filereadable(l:path)
33+
throw 'wiki.vim: target page not found'
34+
endif
35+
36+
37+
if has_key(a:opts, 'target_anchor_before')
38+
return s:collect_target_by_anchor_before(
39+
\ l:path,
40+
\ a:opts.target_anchor_before,
41+
\ a:source
42+
\)
43+
endif
44+
45+
return s:collect_target_by_lnum(l:path, a:opts.target_lnum, a:source)
46+
endfunction
47+
48+
" }}}1
49+
function! wiki#page#refile#move(source, target) abort " {{{1
50+
" Arguments:
51+
" source: dict(path, lnum, lnum_end)
52+
" target: dict(path, lnum)
53+
54+
if a:target.level < a:source.level
55+
call execute(printf('%d,%dg/^#/normal! 0%dx',
56+
\ a:source.lnum, a:source.lnum_end, a:source.level - a:target.level))
57+
elseif a:target.level > a:source.level
58+
call execute(printf('%d,%dg/^#/normal! 0%di#',
59+
\ a:source.lnum, a:source.lnum_end, a:target.level - a:source.level))
60+
endif
61+
62+
if a:target.path ==# a:source.path
63+
call execute(printf('%d,%dm %d',
64+
\ a:source.lnum, a:source.lnum_end, a:target.lnum))
65+
silent write
66+
else
67+
let l:lines = getline(a:source.lnum, a:source.lnum_end)
68+
call deletebufline('', a:source.lnum, a:source.lnum_end)
69+
silent write
70+
71+
let l:current_bufnr = bufnr('')
72+
let l:was_loaded = bufloaded(a:target.path)
73+
keepalt execute 'silent edit' fnameescape(a:target.path)
74+
call append(a:target.lnum, l:lines)
75+
silent write
76+
if !l:was_loaded
77+
keepalt execute 'bwipeout'
78+
endif
79+
keepalt execute 'buffer' l:current_bufnr
80+
endif
81+
endfunction
82+
83+
" }}}1
84+
85+
function! s:collect_target_by_anchor_before(path, anchor, source) abort " {{{1
86+
let l:section = {}
87+
for l:section in wiki#toc#gather_entries(#{ path: a:path })
88+
if l:section.anchor ==# a:anchor
89+
break
90+
endif
91+
endfor
92+
93+
if empty(l:section)
94+
throw 'wiki.vim: anchor not recognized'
95+
endif
96+
97+
let l:anchors = get(l:section, 'anchors', [])
98+
if len(l:anchors) > 0
99+
call remove(l:anchors, -1)
100+
endif
101+
let l:anchors += [a:source.anchors[-1]]
102+
103+
return #{
104+
\ path: a:path,
105+
\ lnum: l:section.lnum - 1,
106+
\ anchor: '#' . join(l:anchors, '#'),
107+
\ level: len(l:anchors)
108+
\}
109+
endfunction
110+
111+
" }}}1
112+
function! s:collect_target_by_lnum(path, lnum, source) abort " {{{1
113+
let l:anchors = [a:source.anchors[-1]]
114+
115+
if a:source.level > 1
116+
let l:section = wiki#toc#get_section(#{ path: a:path, at_lnum: a:lnum })
117+
let l:target_anchors = get(l:section, 'anchors', [])
118+
call extend(
119+
\ l:anchors,
120+
\ l:target_anchors[:a:source.level - 2],
121+
\ 0
122+
\)
123+
endif
124+
125+
return #{
126+
\ path: a:path,
127+
\ lnum: a:lnum,
128+
\ anchor: '#' . join(l:anchors, '#'),
129+
\ level: len(l:anchors)
130+
\}
131+
endfunction
132+
133+
" }}}1

0 commit comments

Comments
 (0)