@@ -169,6 +169,84 @@ function! wiki#page#rename_section(...) abort "{{{1
169169 call s: update_links (l: old_anchor , l: new_anchor , ' rename_section' )
170170endfunction
171171
172+ " }}}1
173+ function ! wiki#page#refile (... ) abort " {{{1
174+ " This function refiles a page section from one page to another.
175+ "
176+ " Input: An optional dictionary with the following keys:
177+ " target_page: The target page name
178+ " target_lnum: The line number in target page where to refile
179+
180+ " Parse options
181+ let l: opts = extend (#{
182+ \ target_page: ' ' ,
183+ \ target_lnum: 0 ,
184+ \} , a: 0 > 0 ? a: 1 : {})
185+ if empty (l: opts .target_page)
186+ let l: opts .target_page = input (' > ' , ' ' , ' customlist,wiki#complete#link' )
187+ endif
188+
189+ let l: resolved_page = wiki#url#resolve (l: opts .target_page)
190+ if ! filereadable (l: resolved_page .path )
191+ echo wiki#log#warn (l: resolved_page )
192+ return wiki#log#error (' Target page was not found!' )
193+ endif
194+
195+ " Get the relevant sections and start/end line numbers
196+ let l: sections = wiki#toc#gather_entries ()
197+ let l: idx = indexof (l: sections , { _, x - > x .lnum > line (' .' ) }) - 1
198+ if l: idx < 0
199+ return wiki#log#error (' No current section recognized!' )
200+ endif
201+
202+ let l: sections = l: sections [l: idx :]
203+ let l: sec = l: sections [0 ]
204+ let l: lnum_start = l: sec .lnum
205+ let l: lnum_end = line (' $' )
206+ if len (l: sections ) > 1
207+ let l: idx = indexof (l: sections [1 :], { _, x - > x .level <= l: sec .level })
208+ if l: idx >= 0
209+ let l: sections = l: sections [:l: idx + 1 ]
210+ let l: lnum_end = l: sections [1 ].lnum - 1
211+ endif
212+ endif
213+
214+ call wiki#log#info (
215+ \ printf (' Refiling section "%s" to page "%s"' ,
216+ \ l: sec .header, l: opts .target_page))
217+
218+ " Get the lines of the section to refile
219+ let l: lines = getline (l: lnum_start , l: lnum_end )
220+
221+ " Append lines to target page
222+ let l: current_bufnr = bufnr (' ' )
223+ silent execute ' edit' fnameescape (l: resolved_page .path )
224+ call append (l: opts .target_lnum, l: lines )
225+ silent update
226+ execute ' buffer' l: current_bufnr
227+
228+ " Delete lines from source page
229+ call deletebufline (' ' , l: lnum_start , l: lnum_end )
230+
231+ " Update local links
232+ let l: pos = getcurpos ()
233+ keepjumps execute printf (
234+ \ ' %%s/\V\ze%s/%s/e%s' ,
235+ \ l: sec .anchor,
236+ \ wiki#paths#to_wiki_url (l: resolved_page .path , wiki#get_root ()),
237+ \ &gdefault ? ' ' : ' g' )
238+ call cursor (l: pos [1 :])
239+ silent update
240+
241+ " Update links
242+ " * It is enough to update the "outer" anchor because the more specific
243+ " anchors should be covered by these as well.
244+ call s: update_links (
245+ \ #{anchor: l: sec .anchor, path : expand (' %:p' )},
246+ \ #{anchor: l: sec .anchor, path : l: resolved_page .path },
247+ \ ' refile' )
248+ endfunction
249+
172250" }}}1
173251function ! wiki#page#export (line1, line2, ... ) abort " {{{1
174252 let l: cfg = deepcopy (g: wiki_export )
@@ -381,6 +459,35 @@ function! s:update_link_rename_section(anchor_old, anchor_new) abort "{{{1
381459 return [len (l: all_links ), len (l: files_with_links )]
382460endfunction
383461
462+ " }}}1
463+ function ! s: update_link_refile (old, new ) abort " {{{1
464+ let l: replacement_patterns
465+ \ = s: get_replacement_patterns (a: old .path , a: new .path )
466+
467+ let l: graph = wiki#graph#builder#get ()
468+ let l: all_links = filter (
469+ \ l: graph .get_links_to (a: old .path ),
470+ \ { _, x - > x .anchor = ~# ' ^' . a: old .anchor })
471+ let l: files_with_links = wiki#u#group_by (l: all_links , ' filename_from' )
472+ for [l: file , l: file_links ] in items (l: files_with_links )
473+ let l: lines = readfile (l: file )
474+
475+ for l: link in l: file_links
476+ for [l: pattern , l: replace ] in l: replacement_patterns
477+ let l: lines [l: link .lnum - 1 ] = substitute (
478+ \ l: lines [l: link .lnum - 1 ],
479+ \ l: pattern ,
480+ \ l: replace ,
481+ \ ' g' )
482+ endfor
483+ endfor
484+
485+ call writefile (l: lines , l: file , ' s' )
486+ endfor
487+
488+ return [len (l: all_links ), len (l: files_with_links )]
489+ endfunction
490+
384491" }}}1
385492function ! s: get_replacement_patterns (path_old, path_new) abort " {{{1
386493 " Update "absolute" links (i.e. assume link is rooted)
0 commit comments