parent
b53dd48429
commit
6c77fd9101
@ -5,8 +5,8 @@
|
|||||||
let s:TAGS_METADATA_FILE_NAME = '.tags'
|
let s:TAGS_METADATA_FILE_NAME = '.tags'
|
||||||
|
|
||||||
" Tags metadata in-memory format:
|
" Tags metadata in-memory format:
|
||||||
" metadata := [ entry, ... ]
|
" metadata := { 'pagename': [entries, ...] }
|
||||||
" entry := { 'tagname':..., 'pagename':..., 'lineno':..., 'link':... }
|
" entry := { 'tagname':..., 'lineno':..., 'link':... }
|
||||||
|
|
||||||
" Tags metadata in-file format:
|
" Tags metadata in-file format:
|
||||||
"
|
"
|
||||||
@ -23,7 +23,9 @@ let s:TAGS_METADATA_FILE_NAME = '.tags'
|
|||||||
" Update tags metadata.
|
" Update tags metadata.
|
||||||
" a:full_rebuild == 1: re-scan entire wiki
|
" a:full_rebuild == 1: re-scan entire wiki
|
||||||
" a:full_rebuild == 0: only re-scan current page
|
" a:full_rebuild == 0: only re-scan current page
|
||||||
function! vimwiki#tags#update_tags(full_rebuild) "{{{
|
" a:all_files == '': only if the file is newer than .tags
|
||||||
|
function! vimwiki#tags#update_tags(full_rebuild, all_files) "{{{
|
||||||
|
let all_files = a:all_files != ''
|
||||||
if !a:full_rebuild
|
if !a:full_rebuild
|
||||||
" Updating for one page (current)
|
" Updating for one page (current)
|
||||||
let page_name = VimwikiGet('subdir') . expand('%:t:r')
|
let page_name = VimwikiGet('subdir') . expand('%:t:r')
|
||||||
@ -34,26 +36,31 @@ function! vimwiki#tags#update_tags(full_rebuild) "{{{
|
|||||||
" Drop old tags
|
" Drop old tags
|
||||||
let metadata = s:remove_page_from_tags(metadata, page_name)
|
let metadata = s:remove_page_from_tags(metadata, page_name)
|
||||||
" Merge in the new ones
|
" Merge in the new ones
|
||||||
let metadata = s:merge_tags(metadata, tags)
|
let metadata = s:merge_tags(metadata, page_name, tags)
|
||||||
" Save
|
" Save
|
||||||
call s:write_tags_metadata(metadata)
|
call s:write_tags_metadata(metadata)
|
||||||
else " full rebuild
|
else " full rebuild
|
||||||
let files = vimwiki#base#find_files(g:vimwiki_current_idx, 0)
|
let files = vimwiki#base#find_files(g:vimwiki_current_idx, 0)
|
||||||
let metadata = []
|
let tags_file_last_modification = getftime(s:metadata_file_path())
|
||||||
|
let metadata = vimwiki#tags#load_tags_metadata()
|
||||||
for file in files
|
for file in files
|
||||||
|
if all_files || getftime(file) >= tags_file_last_modification
|
||||||
let page_name = fnamemodify(file, ':t:r')
|
let page_name = fnamemodify(file, ':t:r')
|
||||||
let tags = s:scan_tags(readfile(file), page_name)
|
let tags = s:scan_tags(readfile(file), page_name)
|
||||||
let metadata = s:merge_tags(metadata, tags)
|
let metadata = s:remove_page_from_tags(metadata, page_name)
|
||||||
|
let metadata = s:merge_tags(metadata, page_name, tags)
|
||||||
|
endif
|
||||||
endfor
|
endfor
|
||||||
call s:write_tags_metadata(metadata)
|
call s:write_tags_metadata(metadata)
|
||||||
endif
|
endif
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
|
||||||
" s:scan_tags
|
" s:scan_tags
|
||||||
" Scans the list of text lines (argument) and produces tags metadata.
|
" Scans the list of text lines (argument) and produces tags metadata as a
|
||||||
|
" list of tag entries.
|
||||||
function! s:scan_tags(lines, page_name) "{{{
|
function! s:scan_tags(lines, page_name) "{{{
|
||||||
|
|
||||||
let metadata = []
|
let entries = []
|
||||||
let page_name = a:page_name
|
let page_name = a:page_name
|
||||||
|
|
||||||
" Code wireframe to scan for headers -- borrowed from
|
" Code wireframe to scan for headers -- borrowed from
|
||||||
@ -110,7 +117,6 @@ function! s:scan_tags(lines, page_name) "{{{
|
|||||||
" Create metadata entry
|
" Create metadata entry
|
||||||
let entry = {}
|
let entry = {}
|
||||||
let entry.tagname = tag
|
let entry.tagname = tag
|
||||||
let entry.pagename = page_name
|
|
||||||
let entry.lineno = line_nr
|
let entry.lineno = line_nr
|
||||||
if line_nr <= (header_line_nr + PROXIMITY_LINES_NR)
|
if line_nr <= (header_line_nr + PROXIMITY_LINES_NR)
|
||||||
let entry.link = page_name . '#' . current_complete_anchor
|
let entry.link = page_name . '#' . current_complete_anchor
|
||||||
@ -120,12 +126,12 @@ function! s:scan_tags(lines, page_name) "{{{
|
|||||||
else
|
else
|
||||||
let entry.link = page_name . '#' . tag
|
let entry.link = page_name . '#' . tag
|
||||||
endif
|
endif
|
||||||
call add(metadata, entry)
|
call add(entries, entry)
|
||||||
endfor
|
endfor
|
||||||
endwhile
|
endwhile
|
||||||
|
|
||||||
endfor " loop over lines
|
endfor " loop over lines
|
||||||
return metadata
|
return entries
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
|
||||||
" s:metadata_file_path
|
" s:metadata_file_path
|
||||||
@ -139,9 +145,9 @@ endfunction " }}}
|
|||||||
function! vimwiki#tags#load_tags_metadata() abort "{{{
|
function! vimwiki#tags#load_tags_metadata() abort "{{{
|
||||||
let metadata_path = s:metadata_file_path()
|
let metadata_path = s:metadata_file_path()
|
||||||
if !filereadable(metadata_path)
|
if !filereadable(metadata_path)
|
||||||
return []
|
return {}
|
||||||
endif
|
endif
|
||||||
let metadata = []
|
let metadata = {}
|
||||||
for line in readfile(metadata_path)
|
for line in readfile(metadata_path)
|
||||||
if line =~ '^!_TAG_FILE_'
|
if line =~ '^!_TAG_FILE_'
|
||||||
continue
|
continue
|
||||||
@ -171,12 +177,16 @@ function! vimwiki#tags#load_tags_metadata() abort "{{{
|
|||||||
if len(vw_fields) != 2
|
if len(vw_fields) != 2
|
||||||
throw 'VimwikiTags5: Metadata file corrupted'
|
throw 'VimwikiTags5: Metadata file corrupted'
|
||||||
endif
|
endif
|
||||||
|
let pagename = vw_fields[0]
|
||||||
let entry = {}
|
let entry = {}
|
||||||
let entry.tagname = std_fields[0]
|
let entry.tagname = std_fields[0]
|
||||||
let entry.pagename = vw_fields[0]
|
|
||||||
let entry.lineno = std_fields[2]
|
let entry.lineno = std_fields[2]
|
||||||
let entry.link = vw_fields[1]
|
let entry.link = vw_fields[1]
|
||||||
call add(metadata, entry)
|
if has_key(metadata, pagename)
|
||||||
|
call add(metadata[pagename], entry)
|
||||||
|
else
|
||||||
|
let metadata[pagename] = [entry]
|
||||||
|
endif
|
||||||
endfor
|
endfor
|
||||||
return metadata
|
return metadata
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
@ -185,48 +195,57 @@ endfunction " }}}
|
|||||||
" Removes all entries for given page from metadata in-place. Returns updated
|
" Removes all entries for given page from metadata in-place. Returns updated
|
||||||
" metadata (just in case).
|
" metadata (just in case).
|
||||||
function! s:remove_page_from_tags(metadata, page_name) "{{{
|
function! s:remove_page_from_tags(metadata, page_name) "{{{
|
||||||
let metadata = filter(a:metadata,
|
if has_key(a:metadata, a:page_name)
|
||||||
\ "v:val.pagename != '" . substitute(a:page_name, "'", "''", '') . "'")
|
call remove(a:metadata, a:page_name)
|
||||||
return metadata
|
return a:metadata
|
||||||
|
else
|
||||||
|
return a:metadata
|
||||||
|
endif
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
|
||||||
" s:merge_tags
|
" s:merge_tags
|
||||||
" Merges two tags metadata objects into (new) one.
|
" Merges metadata of one file into a:metadata
|
||||||
function! s:merge_tags(metadata1, metadata2) "{{{
|
function! s:merge_tags(metadata, pagename, file_metadata) "{{{
|
||||||
return a:metadata1 + a:metadata2
|
let metadata = a:metadata
|
||||||
|
let metadata[a:pagename] = a:file_metadata
|
||||||
|
return metadata
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
|
||||||
" s:write_tags_metadata
|
" s:write_tags_metadata
|
||||||
" Saves metadata object into a file. Throws exceptions in case of problems.
|
" Saves metadata object into a file. Throws exceptions in case of problems.
|
||||||
function! s:write_tags_metadata(metadata) "{{{
|
function! s:write_tags_metadata(metadata) "{{{
|
||||||
let metadata_path = s:metadata_file_path()
|
let metadata_path = s:metadata_file_path()
|
||||||
let entries = []
|
let tags = []
|
||||||
for entry in a:metadata
|
for pagename in keys(a:metadata)
|
||||||
let entry_data = entry.pagename . "\t" . entry.link
|
for entry in a:metadata[pagename]
|
||||||
|
let entry_data = pagename . "\t" . entry.link
|
||||||
let entry_data = substitute(entry_data, "\\", '\\\\', 'g')
|
let entry_data = substitute(entry_data, "\\", '\\\\', 'g')
|
||||||
let entry_data = substitute(entry_data, "\t", '\\t', 'g')
|
let entry_data = substitute(entry_data, "\t", '\\t', 'g')
|
||||||
let entry_data = substitute(entry_data, "\r", '\\r', 'g')
|
let entry_data = substitute(entry_data, "\r", '\\r', 'g')
|
||||||
let entry_data = substitute(entry_data, "\n", '\\n', 'g')
|
let entry_data = substitute(entry_data, "\n", '\\n', 'g')
|
||||||
call add(entries,
|
call add(tags,
|
||||||
\ entry.tagname . "\t"
|
\ entry.tagname . "\t"
|
||||||
\ . entry.pagename . VimwikiGet('ext') . "\t"
|
\ . pagename . VimwikiGet('ext') . "\t"
|
||||||
\ . entry.lineno
|
\ . entry.lineno
|
||||||
\ . ';"'
|
\ . ';"'
|
||||||
\ . "\t" . "vimwiki:" . entry_data
|
\ . "\t" . "vimwiki:" . entry_data
|
||||||
\)
|
\)
|
||||||
endfor
|
endfor
|
||||||
call sort(entries)
|
endfor
|
||||||
call insert(entries, "!_TAG_FILE_SORTED\t1\t{anything}")
|
call sort(tags)
|
||||||
call writefile(entries, metadata_path)
|
call insert(tags, "!_TAG_FILE_SORTED\t1\t{anything}")
|
||||||
|
call writefile(tags, metadata_path)
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
|
||||||
" vimwiki#tags#get_tags
|
" vimwiki#tags#get_tags
|
||||||
" Returns list of unique tags found in metadata
|
" Returns list of unique tags found in metadata
|
||||||
function! vimwiki#tags#get_tags(metadata) "{{{
|
function! vimwiki#tags#get_tags(metadata) "{{{
|
||||||
let tags = {}
|
let tags = {}
|
||||||
for entry in a:metadata
|
for entries in values(a:metadata)
|
||||||
|
for entry in entries
|
||||||
let tags[entry.tagname] = 1
|
let tags[entry.tagname] = 1
|
||||||
endfor
|
endfor
|
||||||
|
endfor
|
||||||
return keys(tags)
|
return keys(tags)
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
|
||||||
@ -244,21 +263,29 @@ function! vimwiki#tags#generate_tags(...) abort "{{{
|
|||||||
\ '',
|
\ '',
|
||||||
\ substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Tags', '') ])
|
\ substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Tags', '') ])
|
||||||
|
|
||||||
call sort(metadata)
|
" make a dictionary { tag_name: [tag_links, ...] }
|
||||||
|
let tags_entries = {}
|
||||||
|
for entries in values(metadata)
|
||||||
|
for entry in entries
|
||||||
|
if has_key(tags_entries, entry.tagname)
|
||||||
|
call add(tags_entries[entry.tagname], entry.link)
|
||||||
|
else
|
||||||
|
let tags_entries[entry.tagname] = [entry.link]
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
let bullet = repeat(' ', vimwiki#lst#get_list_margin()).
|
let bullet = repeat(' ', vimwiki#lst#get_list_margin()).
|
||||||
\ vimwiki#lst#default_symbol().' '
|
\ vimwiki#lst#default_symbol().' '
|
||||||
let current_tag = ''
|
for tagname in sort(keys(tags_entries))
|
||||||
for entry in metadata
|
if need_all_tags || index(specific_tags, tagname) != -1
|
||||||
if need_all_tags || index(specific_tags, entry.tagname) != -1
|
|
||||||
if entry.tagname != current_tag
|
|
||||||
let current_tag = entry.tagname
|
|
||||||
call append(line('$'), [
|
call append(line('$'), [
|
||||||
\ '',
|
\ '',
|
||||||
\ substitute(g:vimwiki_rxH2_Template, '__Header__', entry.tagname, ''),
|
\ substitute(g:vimwiki_rxH2_Template, '__Header__', tagname, ''),
|
||||||
\ '' ])
|
\ '' ])
|
||||||
endif
|
for taglink in tags_entries[tagname]
|
||||||
call append(line('$'), bullet . '[[' . entry.link . ']]')
|
call append(line('$'), bullet . '[[' . taglink . ']]')
|
||||||
|
endfor
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
@ -310,7 +310,8 @@ command! -buffer VimwikiDiaryNextDay call vimwiki#diary#goto_next_day()
|
|||||||
command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day()
|
command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day()
|
||||||
|
|
||||||
" tags commands
|
" tags commands
|
||||||
command! -buffer VimwikiRebuildTags call vimwiki#tags#update_tags(1)
|
command! -buffer -bang
|
||||||
|
\ VimwikiRebuildTags call vimwiki#tags#update_tags(1, '<bang>')
|
||||||
command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags
|
command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags
|
||||||
\ VimwikiSearchTags VimwikiSearch /:<args>:/
|
\ VimwikiSearchTags VimwikiSearch /:<args>:/
|
||||||
command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags
|
command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags
|
||||||
@ -652,7 +653,7 @@ endif
|
|||||||
if VimwikiGet('auto_tags')
|
if VimwikiGet('auto_tags')
|
||||||
" Automatically update tags metadata on page write.
|
" Automatically update tags metadata on page write.
|
||||||
augroup vimwiki
|
augroup vimwiki
|
||||||
au BufWritePost <buffer> call vimwiki#tags#update_tags(0)
|
au BufWritePost <buffer> call vimwiki#tags#update_tags(0, '')
|
||||||
augroup END
|
augroup END
|
||||||
endif
|
endif
|
||||||
" AUTOCOMMANDS }}}
|
" AUTOCOMMANDS }}}
|
||||||
|
Loading…
Reference in New Issue
Block a user