From 91b73c2aaca79d7c99a6117cbbf0bee31780517d Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sat, 3 Jan 2015 00:14:20 +0300 Subject: [PATCH 01/38] Basic documentation --- doc/vimwiki.txt | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index c145211..39a4419 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -38,6 +38,7 @@ CONTENTS *vimwiki-contents* 5.12. Schemes |vimwiki-syntax-schemes| 5.13. Transclusions |vimwiki-syntax-transclude| 5.14. Thumbnails |vimwiki-syntax-thumbnails| + 5.15. Tags |vimwiki-syntax-tags| 6. Folding/Outline |vimwiki-folding| 7. Placeholders |vimwiki-placeholders| 8. Lists |vimwiki-lists| @@ -1211,6 +1212,35 @@ in HTML: > + :ind +which opens up a popup menu with all tags defined in the wiki starting with +"ind". + +Note that tag search/jump/completion commands need certain metadata saved in +the wiki folder. This metadata can be manually updated by running +|:VimwikiGenerateTags|. There is an option |vimwiki-option-auto_tags|, when +enabled, tags metadata will be auto-updated on each page save. + ============================================================================== @@ -2032,6 +2062,18 @@ local mappings |vimwiki_glstar|, |vimwiki_gl#| |vimwiki_gl-|, |vimwiki_gl-|, Note: if you use MediaWiki syntax, you probably would like to set this option to 0, because every indented line is considered verbatim text. + +*vimwiki-option-auto_tags* +------------------------------------------------------------------------------ +Key Default value Values~ +auto_tags 0 0, 1 + +Description~ +Set this option to 1 to automatically update the tags metadata when the +current wiki page is saved: > + let g:vimwiki_list = [{'path': '~/my_site/', 'auto_tags': 1}] + + ------------------------------------------------------------------------------ 12.4 Global Options *vimwiki-global-options* From 7f5e51716233756ab4aa6dee4bf94a34c76ccdff Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sat, 3 Jan 2015 00:16:52 +0300 Subject: [PATCH 02/38] Default value for auto-tags option --- plugin/vimwiki.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/vimwiki.vim b/plugin/vimwiki.vim index 8d3a577..1405e08 100644 --- a/plugin/vimwiki.vim +++ b/plugin/vimwiki.vim @@ -410,6 +410,8 @@ let s:vimwiki_defaults.diary_link_fmt = '%Y-%m-%d' let s:vimwiki_defaults.custom_wiki2html = '' " let s:vimwiki_defaults.list_margin = -1 + +let s:vimwiki_defaults.auto_tags = 0 "}}} " DEFAULT options {{{ From 19cc1b873ac0f359b7ee4a286b16dddc377b9200 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sat, 3 Jan 2015 00:59:18 +0300 Subject: [PATCH 03/38] Added placeholders for tags on-page-save analysis --- autoload/vimwiki/base.vim | 55 +++++++++++++++++++++++++++++++++++++++ ftplugin/vimwiki.vim | 7 +++++ 2 files changed, 62 insertions(+) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index dceb57d..bb8bee4 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1928,6 +1928,61 @@ endfunction "}}} " }}} +" TAGS functions {{{ +" vimwiki#base#update_tags +" Update tags metadata. +" a:full_rebuild == 1: re-scan entire wiki +" a:full_rebuild == 0: only re-scan current page +function! vimwiki#base#update_tags(full_rebuild) "{{{ + if a:full_rebuild + throw 'vimwiki#base#update_tags1: full rebuild not supported yet' + endif + " + let page_name = expand('%:t:r') + " Collect tags in current file + let tags = vimwiki#base#scan_tags(getline(1, '$')) + " Load metadata file + let metadata = vimwiki#base#load_tags_metadata() + " Drop old tags + let metadata = vimwiki#base#remove_page_from_tags(metadata, page_name) + " Merge in the new ones + let metadata = vimwiki#base#merge_tags(metadata, tags) + " Save + call vimwiki#base#write_tags_metadata(metadata) +endfunction " }}} + +" vimwiki#base#scan_tags +" Scans the list (argument) and produces tags metadata dictionary. +function! vimwiki#base#scan_tags(lines) "{{{ + return {} +endfunction " }}} + +" vimwiki#base#load_tags_metadata +" Loads tags metadata from file, returns a dictionary +function! vimwiki#base#load_tags_metadata() "{{{ + return [] +endfunction " }}} + +" vimwiki#base#remove_page_from_tags +" Removes all entries for given page from metadata in-place. Returns updated +" metadata (just in case). +function! vimwiki#base#remove_page_from_tags(metadata, page_name) "{{{ + return [] +endfunction " }}} + +" vimwiki#base#merge_tags +" Merges two tags metadata objects into (new) one. +function! vimwiki#base#merge_tags(metadata1, metadata2) "{{{ + return [] +endfunction " }}} + +" vimwiki#base#write_tags_metadata +" Saves metadata object into a file. Throws exceptions in case of problems. +function! vimwiki#base#write_tags_metadata(metadata) "{{{ +endfunction " }}} + +" }}} + " Command completion functions {{{ " vimwiki#base#complete_links_escaped diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 8490984..29dc2a9 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -618,6 +618,13 @@ if VimwikiGet('auto_toc') au BufWritePre call vimwiki#base#table_of_contents(0) augroup END endif + +if VimwikiGet('auto_tags') + " Automatically update tags metadata on page write. + augroup vimwiki + au BufWritePost call vimwiki#base#update_tags(0) + augroup END +endif " AUTOCOMMANDS }}} " PASTE, CAT URL {{{ From 2d0616343dfe03ef130a0df11fbf446b0fe6b03b Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sun, 4 Jan 2015 00:03:13 +0300 Subject: [PATCH 04/38] Implemented tags scan function (go over range of lines and compose list of tag entries and their metadata --- autoload/vimwiki/base.vim | 79 +++++++++++++++++++++++++++++++++-- syntax/omnipresent_syntax.vim | 3 ++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index bb8bee4..3183ea7 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1929,6 +1929,11 @@ endfunction "}}} " }}} " TAGS functions {{{ + +" Tags metadata in-memory format: +" metadata := [ entry, ... ] +" entry := { 'tagname':..., 'pagename':..., 'lineno':..., 'link':... } + " vimwiki#base#update_tags " Update tags metadata. " a:full_rebuild == 1: re-scan entire wiki @@ -1940,7 +1945,7 @@ function! vimwiki#base#update_tags(full_rebuild) "{{{ " let page_name = expand('%:t:r') " Collect tags in current file - let tags = vimwiki#base#scan_tags(getline(1, '$')) + let tags = vimwiki#base#scan_tags(getline(1, '$'), page_name) " Load metadata file let metadata = vimwiki#base#load_tags_metadata() " Drop old tags @@ -1953,8 +1958,76 @@ endfunction " }}} " vimwiki#base#scan_tags " Scans the list (argument) and produces tags metadata dictionary. -function! vimwiki#base#scan_tags(lines) "{{{ - return {} +function! vimwiki#base#scan_tags(lines, page_name) "{{{ + + let metadata = [] + let page_name = a:page_name + + " Code wireframe to scan for headers -- borrowed from + " vimwiki#base#get_anchors(), with minor modifications. + + let rxheader = g:vimwiki_{VimwikiGet('syntax')}_header_search + let rxtag = g:vimwiki_{VimwikiGet('syntax')}_tag_search + + let anchor_level = ['', '', '', '', '', '', ''] + let current_complete_anchor = '' + + let PROXIMITY_LINES_NR = 5 + let header_line_nr = - (2 * PROXIMITY_LINES_NR) + + for line_nr in range(1, len(a:lines)) + let line = a:lines[line_nr - 1] + + " process headers + let h_match = matchlist(line, rxheader) + if !empty(h_match) " got a header + let header_line_nr = line_nr + let header = vimwiki#u#trim(h_match[2]) + let level = len(h_match[1]) + let anchor_level[level-1] = header + for l in range(level, 6) + let anchor_level[l] = '' + endfor + if level == 1 + let current_complete_anchor = header + else + let current_complete_anchor = '' + for l in range(level-1) + if anchor_level[l] != '' + let current_complete_anchor .= anchor_level[l].'#' + endif + endfor + let current_complete_anchor .= header + endif + continue " tags are not allowed in headers + endif + + " TODO ignore verbatim blocks + + " Scan line for tags. There can be many of them. + let str = line + while 1 + let tag = matchstr(str, rxtag) + if tag == '' + break + endif + let tagend = matchend(str, rxtag) + let str = str[(tagend):] + " Create metadata entry + let entry = {} + let entry.tagname = tag + let entry.pagename = page_name + let entry.lineno = line_nr + if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) + let entry.link = page_name . '#' . current_complete_anchor + else + let entry.link = page_name + endif + call add(metadata, entry) + endwhile + + endfor " loop over lines + return metadata endfunction " }}} " vimwiki#base#load_tags_metadata diff --git a/syntax/omnipresent_syntax.vim b/syntax/omnipresent_syntax.vim index fac11d9..bd8c5b0 100644 --- a/syntax/omnipresent_syntax.vim +++ b/syntax/omnipresent_syntax.vim @@ -14,12 +14,14 @@ let g:vimwiki_default_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\ let g:vimwiki_default_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_default_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_default_wikilink = '\[\[\zs[^\\\]|]\+\ze\%(|[^\\\]]\+\)\?\]\]' +let g:vimwiki_default_tag_search = ':\zs[^:[:space:]]\+\ze:' let g:vimwiki_markdown_header_search = '^\s*\(#\{1,6}\)\([^#].*\)$' let g:vimwiki_markdown_header_match = '^\s*\(#\{1,6}\)#\@!\s*__Header__\s*$' let g:vimwiki_markdown_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_markdown_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_markdown_wikilink = g:vimwiki_default_wikilink "XXX plus markdown-style links +let g:vimwiki_markdown_tag_search = g:vimwiki_default_tag_search let g:vimwiki_media_header_search = '^\s*\(=\{1,6}\)\([^=].*[^=]\)\1\s*$' let g:vimwiki_media_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\s*$' @@ -28,3 +30,4 @@ let g:vimwiki_media_bold_match = '''''''__Text__''''''' " ^- this strange looking thing is equivalent to "'''__Text__'''" but since we later " want to call escape() on this string, we must keep it in single quotes let g:vimwiki_media_wikilink = g:vimwiki_default_wikilink +let g:vimwiki_media_tag_search = g:vimwiki_default_tag_search " XXX rework to mediawiki categories format? From 6cafc97c9c39227deec13bb877f02e7105e31704 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sun, 4 Jan 2015 00:24:32 +0300 Subject: [PATCH 05/38] Implement saving metadata to file --- autoload/vimwiki/base.vim | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 3183ea7..fa2efcb 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1930,10 +1930,16 @@ endfunction "}}} " TAGS functions {{{ +let s:TAGS_METADATA_FILE_NAME = '.tags' + " Tags metadata in-memory format: " metadata := [ entry, ... ] " entry := { 'tagname':..., 'pagename':..., 'lineno':..., 'link':... } +" Tags metadata in-file format: +" * entry per line, +" * entry fields go in the same order as defined above, separated with TAB (\t) + " vimwiki#base#update_tags " Update tags metadata. " a:full_rebuild == 1: re-scan entire wiki @@ -2046,12 +2052,23 @@ endfunction " }}} " vimwiki#base#merge_tags " Merges two tags metadata objects into (new) one. function! vimwiki#base#merge_tags(metadata1, metadata2) "{{{ - return [] + return a:metadata1 + a:metadata2 endfunction " }}} " vimwiki#base#write_tags_metadata " Saves metadata object into a file. Throws exceptions in case of problems. function! vimwiki#base#write_tags_metadata(metadata) "{{{ + let metadata_path = VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME + let entries = [] + for entry in a:metadata + call add(entries, + \ entry.tagname . "\t" + \ . entry.pagename . "\t" + \ . entry.lineno . "\t" + \ . entry.link + \) + endfor + call writefile(entries, metadata_path) endfunction " }}} " }}} From c7436a44cf0849822b669c9b10d766a8a8f5e5bb Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Mon, 5 Jan 2015 00:39:26 +0300 Subject: [PATCH 06/38] Reading metadata file; filtering by page name --- autoload/vimwiki/base.vim | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index fa2efcb..befa9f0 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -2039,14 +2039,30 @@ endfunction " }}} " vimwiki#base#load_tags_metadata " Loads tags metadata from file, returns a dictionary function! vimwiki#base#load_tags_metadata() "{{{ - return [] + let metadata_path = VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME + let metadata = [] + for line in readfile(metadata_path) + let fields = split(line, '\t') + if len(fields) != 4 + throw 'VimwikiTags1: Metadata file corrupted' + endif + let entry = {} + let entry.tagname = fields[0] + let entry.pagename = fields[1] + let entry.lineno = fields[2] + let entry.link = fields[3] + call add(metadata, entry) + endfor + return metadata endfunction " }}} " vimwiki#base#remove_page_from_tags " Removes all entries for given page from metadata in-place. Returns updated " metadata (just in case). function! vimwiki#base#remove_page_from_tags(metadata, page_name) "{{{ - return [] + let metadata = filter(a:metadata, + \ "v:val.pagename != '" . substitute(a:page_name, "'", "''", '') . "'") + return metadata endfunction " }}} " vimwiki#base#merge_tags From a01290160c5e7543d04ae713eac0d4754e782616 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Mon, 5 Jan 2015 01:29:42 +0300 Subject: [PATCH 07/38] Support for omni completion of tags --- autoload/vimwiki/base.vim | 10 ++++++++++ ftplugin/vimwiki.vim | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index befa9f0..420760c 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -2087,6 +2087,16 @@ function! vimwiki#base#write_tags_metadata(metadata) "{{{ call writefile(entries, metadata_path) endfunction " }}} +" vimwiki#base#get_tags +" Returns list of unique tags found in metadata +function! vimwiki#base#get_tags(metadata) "{{{ + let tags = {} + for entry in a:metadata + let tags[entry.tagname] = 1 + endfor + return keys(tags) +endfunction " }}} + " }}} " Command completion functions {{{ diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 29dc2a9..313358b 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -49,9 +49,25 @@ function! Complete_wikifiles(findstart, base) return startofinlinelink endif endif + let startoftag = match(line, ':\zs[^:[:space:]]*$') + if startoftag != -1 + return startoftag + endif return -1 else - if a:base !~ '#' + " Completion works for wikilinks/anchors, and for tags. So first we have + " to find out what we're about to complete. + let column = col('.') + let line = getline('.')[:(column - len(a:base))] + let char_before_start = line[-1:-1] + if char_before_start == ':' + " Tags completion + let metadata = vimwiki#base#load_tags_metadata() + let tags = vimwiki#base#get_tags(metadata) + call filter(tags, + \ "v:val[:" . (len(a:base)-1) . "] == '" . substitute(a:base, "'", "''", '') . "'" ) + return tags + elseif a:base !~ '#' " we look for wiki files if a:base =~# '^wiki\d:' From 4f639cebeee65224fc671937b60f89e2203687fb Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Mon, 5 Jan 2015 01:44:24 +0300 Subject: [PATCH 08/38] Syntax definitions --- syntax/vimwiki.vim | 5 +++++ syntax/vimwiki_default.vim | 1 + 2 files changed, 6 insertions(+) diff --git a/syntax/vimwiki.vim b/syntax/vimwiki.vim index fb52ff6..00b54d2 100644 --- a/syntax/vimwiki.vim +++ b/syntax/vimwiki.vim @@ -485,6 +485,10 @@ if g:vimwiki_valid_html_tags != '' execute 'syntax match VimwikiComment /'.g:vimwiki_rxComment.'/ contains=@Spell' endif + +" tags +execute 'syntax match VimwikiTag /'.g:vimwiki_rxTags.'/' + " }}} " header groups highlighting "{{{ @@ -550,6 +554,7 @@ hi def link VimwikiListTodo VimwikiList hi def link VimwikiCheckBoxDone Comment hi def link VimwikiEmoticons Character hi def link VimwikiHR Identifier +hi def link VimwikiTag Keyword hi def link VimwikiDelText Constant hi def link VimwikiDelTextT VimwikiDelText diff --git a/syntax/vimwiki_default.vim b/syntax/vimwiki_default.vim index 0df4fb2..e0c73a5 100644 --- a/syntax/vimwiki_default.vim +++ b/syntax/vimwiki_default.vim @@ -95,3 +95,4 @@ let g:vimwiki_rxMathStart = '{{\$' let g:vimwiki_rxMathEnd = '}}\$' let g:vimwiki_rxComment = '^\s*%%.*$' +let g:vimwiki_rxTags = ':\([^:[:space:]]\+:\)\+' From df91772d7e12cb6ed441309be868be1260f49317 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Tue, 6 Jan 2015 22:30:28 +0300 Subject: [PATCH 09/38] Implement :VimwikiRebuildTags to rebuild metadata for all pages in current wiki --- autoload/vimwiki/base.vim | 36 ++++++++++++++++++++++-------------- doc/vimwiki.txt | 4 ++++ ftplugin/vimwiki.vim | 3 +++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 420760c..07a99e4 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1945,21 +1945,29 @@ let s:TAGS_METADATA_FILE_NAME = '.tags' " a:full_rebuild == 1: re-scan entire wiki " a:full_rebuild == 0: only re-scan current page function! vimwiki#base#update_tags(full_rebuild) "{{{ - if a:full_rebuild - throw 'vimwiki#base#update_tags1: full rebuild not supported yet' + if !a:full_rebuild + " Updating for one page (current) + let page_name = expand('%:t:r') + " Collect tags in current file + let tags = vimwiki#base#scan_tags(getline(1, '$'), page_name) + " Load metadata file + let metadata = vimwiki#base#load_tags_metadata() + " Drop old tags + let metadata = vimwiki#base#remove_page_from_tags(metadata, page_name) + " Merge in the new ones + let metadata = vimwiki#base#merge_tags(metadata, tags) + " Save + call vimwiki#base#write_tags_metadata(metadata) + else " full rebuild + let files = s:find_files(g:vimwiki_current_idx, 0) + let metadata = [] + for file in files + let page_name = fnamemodify(file, ':t:r') + let tags = vimwiki#base#scan_tags(readfile(file), page_name) + let metadata = vimwiki#base#merge_tags(metadata, tags) + endfor + call vimwiki#base#write_tags_metadata(metadata) endif - " - let page_name = expand('%:t:r') - " Collect tags in current file - let tags = vimwiki#base#scan_tags(getline(1, '$'), page_name) - " Load metadata file - let metadata = vimwiki#base#load_tags_metadata() - " Drop old tags - let metadata = vimwiki#base#remove_page_from_tags(metadata, page_name) - " Merge in the new ones - let metadata = vimwiki#base#merge_tags(metadata, tags) - " Save - call vimwiki#base#write_tags_metadata(metadata) endfunction " }}} " vimwiki#base#scan_tags diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index 39a4419..8df4a06 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -704,6 +704,10 @@ il A single list item. files are reachable from the index file. Errors are shown in the quickfix window. +*:VimwikiRebuildTags* + Iterates over all files in a current wiki and rebuilds tags metadata (to + enable tags related commands). + ============================================================================== 5. Wiki syntax *vimwiki-syntax* diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 313358b..3dc128f 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -302,6 +302,9 @@ command! -buffer VimwikiTableMoveColumnRight call vimwiki#tbl#move_column_right( command! -buffer VimwikiDiaryNextDay call vimwiki#diary#goto_next_day() command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day() +" tags commands +command! -buffer VimwikiRebuildTags call vimwiki#base#update_tags(1) + " COMMANDS }}} " KEYBINDINGS {{{ From a62bebceb20258e235812d9fba51efadeb37e8e8 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Tue, 6 Jan 2015 22:44:41 +0300 Subject: [PATCH 10/38] Implement :VimwikiSearchTags to look up tag instances in a wiki --- autoload/vimwiki/base.vim | 9 +++++++++ doc/vimwiki.txt | 6 +++++- ftplugin/vimwiki.vim | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 07a99e4..f5c792a 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -2109,6 +2109,15 @@ endfunction " }}} " Command completion functions {{{ +" vimwiki#base#complete_tags +function! vimwiki#base#complete_tags(ArgLead, CmdLine, CursorPos) abort " {{{ + " We can safely ignore args if we use -custom=complete option, Vim engine + " will do the job of filtering. + let metadata = vimwiki#base#load_tags_metadata() + let taglist = vimwiki#base#get_tags(metadata) + return join(taglist, "\n") +endfunction " }}} + " vimwiki#base#complete_links_escaped function! vimwiki#base#complete_links_escaped(ArgLead, CmdLine, CursorPos) abort " {{{ " We can safely ignore args if we use -custom=complete option, Vim engine diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index 8df4a06..a1db1b3 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -596,7 +596,7 @@ il A single list item. *:VimwikiGoto* Goto link provided by an argument. For example: > :VimwikiGoto HelloWorld -< opens opens/creates HelloWorld wiki page. +< opens opens/creates HelloWorld wiki page. Supports |cmdline-completion| for link name. @@ -708,6 +708,10 @@ il A single list item. Iterates over all files in a current wiki and rebuilds tags metadata (to enable tags related commands). +*:VimwikiSearchTags* + Searches over the pages in current wiki and finds all locations of a given + tag. Supports |cmdline-completion|. + ============================================================================== 5. Wiki syntax *vimwiki-syntax* diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 3dc128f..aa8dd17 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -304,6 +304,8 @@ command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day() " tags commands command! -buffer VimwikiRebuildTags call vimwiki#base#update_tags(1) +command! -buffer -nargs=* -complete=custom,vimwiki#base#complete_tags + \ VimwikiSearchTags VimwikiSearch /::/ " COMMANDS }}} From e44b188a497576393fab62d021e9f87c3ffe3a85 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Tue, 6 Jan 2015 23:13:28 +0300 Subject: [PATCH 11/38] :VimwikiGenerateTags --- autoload/vimwiki/base.vim | 33 +++++++++++++++++++++++++++++++++ doc/vimwiki.txt | 5 +++++ ftplugin/vimwiki.vim | 2 ++ 3 files changed, 40 insertions(+) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index f5c792a..b368042 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -2105,6 +2105,39 @@ function! vimwiki#base#get_tags(metadata) "{{{ return keys(tags) endfunction " }}} +" vimwiki#base#generate_tags +" Similar to vimwiki#base#generate_links. In the current buffer, appends +" tags and references to all their instances. If no arguments (tags) are +" specified, outputs all tags. +function! vimwiki#base#generate_tags(...) abort "{{{ + let need_all_tags = (a:0 == 0) + let specific_tags = a:000 + + let metadata = vimwiki#base#load_tags_metadata() + + call append(line('$'), [ + \ '', + \ substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Tags', '') ]) + + call sort(metadata) + + let bullet = repeat(' ', vimwiki#lst#get_list_margin()). + \ vimwiki#lst#default_symbol().' ' + let current_tag = '' + for entry in metadata + if need_all_tags || index(specific_tags, entry.tagname) != -1 + if entry.tagname != current_tag + let current_tag = entry.tagname + call append(line('$'), [ + \ '', + \ substitute(g:vimwiki_rxH2_Template, '__Header__', entry.tagname, ''), + \ '' ]) + endif + call append(line('$'), bullet . '[[' . entry.link . ']]') + endif + endfor +endfunction " }}} + " }}} " Command completion functions {{{ diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index a1db1b3..70bf723 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -712,6 +712,11 @@ il A single list item. Searches over the pages in current wiki and finds all locations of a given tag. Supports |cmdline-completion|. +*:VimwikiGenerateTags* + Similar to |:VimwikiGenerateLinks|. In the current buffer, appends tags + and references to all their instances. Supports |cmdline-completion|. If + no arguments (tags) are specified, outputs all tags. + ============================================================================== 5. Wiki syntax *vimwiki-syntax* diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index aa8dd17..434ed52 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -306,6 +306,8 @@ command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day() command! -buffer VimwikiRebuildTags call vimwiki#base#update_tags(1) command! -buffer -nargs=* -complete=custom,vimwiki#base#complete_tags \ VimwikiSearchTags VimwikiSearch /::/ +command! -buffer -nargs=* -complete=custom,vimwiki#base#complete_tags + \ VimwikiGenerateTags call vimwiki#base#generate_tags() " COMMANDS }}} From e6f6fdd359c5ee916a601be6cb8885197cb0c6d4 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Tue, 6 Jan 2015 23:26:48 +0300 Subject: [PATCH 12/38] Mention tags in ChangeLog --- doc/vimwiki.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index 70bf723..ef8d48c 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -2650,6 +2650,7 @@ Vim plugins: http://www.vim.org/scripts/script.php?script_id=2226 ???~ + * Support for tags. * Support for anchors, see |vimwiki-anchors| * in this context, add support for TOC, see |vimwiki-toc| * remove the now useless %toc placeholder From 8a0433dec5cdce5abf70a985c96f477440f8ff7a Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sat, 10 Jan 2015 00:51:37 +0300 Subject: [PATCH 13/38] Fix error 'metadata file not found' when tag functions are called first time --- autoload/vimwiki/base.vim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index b368042..c093844 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -2048,6 +2048,9 @@ endfunction " }}} " Loads tags metadata from file, returns a dictionary function! vimwiki#base#load_tags_metadata() "{{{ let metadata_path = VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME + if !filereadable(metadata_path) + return [] + endif let metadata = [] for line in readfile(metadata_path) let fields = split(line, '\t') From b99a3dc988dfae985617d9785de577f9d97e2e5f Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sat, 10 Jan 2015 01:44:25 +0300 Subject: [PATCH 14/38] Convert file format to CTAGS. Update docs --- autoload/vimwiki/base.vim | 63 +++++++++++++++++++++++++++++++-------- doc/vimwiki.txt | 10 ++++++- ftplugin/vimwiki.vim | 2 ++ 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index c093844..0d8f98b 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1937,8 +1937,15 @@ let s:TAGS_METADATA_FILE_NAME = '.tags' " entry := { 'tagname':..., 'pagename':..., 'lineno':..., 'link':... } " Tags metadata in-file format: -" * entry per line, -" * entry fields go in the same order as defined above, separated with TAB (\t) +" +" Is based on CTags format (see |tags-file-format|). +" +" {tagaddress} is set to lineno. We'll let vim search by exact line number; we +" can afford that, we assume metadata file is always updated before use. +" +" Pagename and link are not saved in standard ctags fields, so we'll add +" an optional field, "vimwiki:". In this field, we encode tab-separated values +" of missing parameters -- "pagename" and "link". " vimwiki#base#update_tags " Update tags metadata. @@ -2046,22 +2053,46 @@ endfunction " }}} " vimwiki#base#load_tags_metadata " Loads tags metadata from file, returns a dictionary -function! vimwiki#base#load_tags_metadata() "{{{ +function! vimwiki#base#load_tags_metadata() abort "{{{ let metadata_path = VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME if !filereadable(metadata_path) return [] endif let metadata = [] for line in readfile(metadata_path) - let fields = split(line, '\t') - if len(fields) != 4 + if line =~ '^!_TAG_FILE_' + continue + endif + let parts = matchlist(line, '^\(.\{-}\);"\(.*\)$') + if parts[0] == '' || parts[1] == '' || parts[2] == '' throw 'VimwikiTags1: Metadata file corrupted' endif + let std_fields = split(parts[1], '\t') + if len(std_fields) != 3 + throw 'VimwikiTags2: Metadata file corrupted' + endif + let vw_part = parts[2] + if vw_part[0] != "\t" + throw 'VimwikiTags3: Metadata file corrupted' + endif + let vw_fields = split(vw_part[1:], "\t") + if len(vw_fields) != 1 || vw_fields[0] !~ '^vimwiki:' + throw 'VimwikiTags4: Metadata file corrupted' + endif + let vw_data = substitute(vw_fields[0], '^vimwiki:', '', '') + let vw_data = substitute(vw_data, '\\n', "\n", 'g') + let vw_data = substitute(vw_data, '\\r', "\r", 'g') + let vw_data = substitute(vw_data, '\\t', "\t", 'g') + let vw_data = substitute(vw_data, '\\\\', "\\", 'g') + let vw_fields = split(vw_data, "\t") + if len(vw_fields) != 2 + throw 'VimwikiTags5: Metadata file corrupted' + endif let entry = {} - let entry.tagname = fields[0] - let entry.pagename = fields[1] - let entry.lineno = fields[2] - let entry.link = fields[3] + let entry.tagname = std_fields[0] + let entry.pagename = vw_fields[0] + let entry.lineno = std_fields[2] + let entry.link = vw_fields[1] call add(metadata, entry) endfor return metadata @@ -2088,13 +2119,21 @@ function! vimwiki#base#write_tags_metadata(metadata) "{{{ let metadata_path = VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME let entries = [] for entry in a:metadata + let entry_data = entry.pagename . "\t" . entry.link + let entry_data = substitute(entry_data, "\\", '\\\\', '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, "\n", '\\n', 'g') call add(entries, \ entry.tagname . "\t" - \ . entry.pagename . "\t" - \ . entry.lineno . "\t" - \ . entry.link + \ . entry.pagename . VimwikiGet('ext') . "\t" + \ . entry.lineno + \ . ';"' + \ . "\t" . "vimwiki:" . entry_data \) endfor + call sort(entries) + call insert(entries, "!_TAG_FILE_SORTED\t1\t{anything}") call writefile(entries, metadata_path) endfunction " }}} diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index ef8d48c..960bc7e 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -1251,9 +1251,17 @@ which opens up a popup menu with all tags defined in the wiki starting with Note that tag search/jump/completion commands need certain metadata saved in the wiki folder. This metadata can be manually updated by running -|:VimwikiGenerateTags|. There is an option |vimwiki-option-auto_tags|, when +|:VimwikiRebuildTags|. There is an option |vimwiki-option-auto_tags|, when enabled, tags metadata will be auto-updated on each page save. +Once tags metadata has been built, one can use Vim's built-in tag search +functionality (see |tagsrch.txt|). + +Tags-related commands and options: + * |:VimwikiRebuildTags| + * |:VimwikiGenerateTags| + * |:VimwikiSearchTags| + * |vimwiki-option-auto_tags| ============================================================================== diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 434ed52..e94f8f6 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -32,6 +32,8 @@ execute 'setlocal suffixesadd='.VimwikiGet('ext') setlocal isfname-=[,] " gf}}} +setlocal tags+=./.tags + " MISC }}} " COMPLETION {{{ From d72ef4dd707c986620755d159bc467b18150e826 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sat, 10 Jan 2015 16:39:11 +0300 Subject: [PATCH 15/38] Treat tags as anchors (wikilink completion, jumping to) --- autoload/vimwiki/base.vim | 21 ++++++++++++++++++++- doc/vimwiki.txt | 6 ++++++ syntax/omnipresent_syntax.vim | 3 +++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 0d8f98b..8c0d2a5 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -620,6 +620,7 @@ function! vimwiki#base#get_anchors(filename, syntax) "{{{ let rxheader = g:vimwiki_{a:syntax}_header_search let rxbold = g:vimwiki_{a:syntax}_bold_search + let rxtag = g:vimwiki_{a:syntax}_tag_search let anchor_level = ['', '', '', '', '', '', ''] let anchors = [] @@ -664,6 +665,20 @@ function! vimwiki#base#get_anchors(filename, syntax) "{{{ let bold_count += 1 endwhile + " collect tags text (there can be several in one line) + let tag_count = 1 + while 1 + let tag_text = matchstr(line, rxtag, 0, tag_count) + if tag_text == '' + break + endif + call add(anchors, tag_text) + if current_complete_anchor != '' + call add(anchors, current_complete_anchor.'#'.tag_text) + endif + let tag_count += 1 + endwhile + endfor return anchors @@ -684,8 +699,12 @@ function! s:jump_to_anchor(anchor) "{{{ \ '__Header__', "\\='".segment."'", '') let anchor_bold = substitute(g:vimwiki_{VimwikiGet('syntax')}_bold_match, \ '__Text__', "\\='".segment."'", '') + let anchor_tag = substitute(g:vimwiki_{VimwikiGet('syntax')}_tag_match, + \ '__Tag__', "\\='".segment."'", '') - if !search(anchor_header, 'Wc') && !search(anchor_bold, 'Wc') + if !search(anchor_header, 'Wc') + \ && !search(anchor_bold, 'Wc') + \ && !search(anchor_tag, 'Wc') call setpos('.', oldpos) break endif diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index 960bc7e..9159ada 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -1249,6 +1249,8 @@ Typing tags can be simplified by using Vim's omni completion (see which opens up a popup menu with all tags defined in the wiki starting with "ind". +Tags are also treated as |vimwiki-anchors| (similar to bold text). + Note that tag search/jump/completion commands need certain metadata saved in the wiki folder. This metadata can be manually updated by running |:VimwikiRebuildTags|. There is an option |vimwiki-option-auto_tags|, when @@ -1622,6 +1624,7 @@ of the form > For example, consider the following file "Todo.wiki": > = My tasks = + :todo-lists: == Home == - [ ] bathe my dog == Work == @@ -1637,6 +1640,9 @@ Then, to jump from your index.wiki directly to your knitting projects, use: > Or, to jump to an individual project, use this link: > [[Todo#pig]] +Or, to jump to a tag, use this link: > + [[Todo#todo-lists]] + If there are multiple instances of an anchor, you can use the long form which consists of the complete header hierarchy, separated by '#': > [[Todo#My tasks#Knitting club#Knitting projects#dog]] diff --git a/syntax/omnipresent_syntax.vim b/syntax/omnipresent_syntax.vim index bd8c5b0..a3c2058 100644 --- a/syntax/omnipresent_syntax.vim +++ b/syntax/omnipresent_syntax.vim @@ -15,6 +15,7 @@ let g:vimwiki_default_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:sp let g:vimwiki_default_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_default_wikilink = '\[\[\zs[^\\\]|]\+\ze\%(|[^\\\]]\+\)\?\]\]' let g:vimwiki_default_tag_search = ':\zs[^:[:space:]]\+\ze:' +let g:vimwiki_default_tag_match = ':__Tag__:' let g:vimwiki_markdown_header_search = '^\s*\(#\{1,6}\)\([^#].*\)$' let g:vimwiki_markdown_header_match = '^\s*\(#\{1,6}\)#\@!\s*__Header__\s*$' @@ -22,6 +23,7 @@ let g:vimwiki_markdown_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:s let g:vimwiki_markdown_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_markdown_wikilink = g:vimwiki_default_wikilink "XXX plus markdown-style links let g:vimwiki_markdown_tag_search = g:vimwiki_default_tag_search +let g:vimwiki_markdown_tag_match = g:vimwiki_default_tag_match let g:vimwiki_media_header_search = '^\s*\(=\{1,6}\)\([^=].*[^=]\)\1\s*$' let g:vimwiki_media_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\s*$' @@ -31,3 +33,4 @@ let g:vimwiki_media_bold_match = '''''''__Text__''''''' " want to call escape() on this string, we must keep it in single quotes let g:vimwiki_media_wikilink = g:vimwiki_default_wikilink let g:vimwiki_media_tag_search = g:vimwiki_default_tag_search " XXX rework to mediawiki categories format? +let g:vimwiki_media_tag_match = g:vimwiki_default_tag_match " XXX rework to mediawiki categories format? From b912e4e3c702f3ce617e54b846c13e1754e55d5d Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sat, 10 Jan 2015 17:10:18 +0300 Subject: [PATCH 16/38] Update :VimikiGenerateTags -- use tags as anchors in links --- autoload/vimwiki/base.vim | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 8c0d2a5..d227026 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1997,7 +1997,7 @@ function! vimwiki#base#update_tags(full_rebuild) "{{{ endfunction " }}} " vimwiki#base#scan_tags -" Scans the list (argument) and produces tags metadata dictionary. +" Scans the list of text lines (argument) and produces tags metadata. function! vimwiki#base#scan_tags(lines, page_name) "{{{ let metadata = [] @@ -2060,8 +2060,11 @@ function! vimwiki#base#scan_tags(lines, page_name) "{{{ let entry.lineno = line_nr if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) let entry.link = page_name . '#' . current_complete_anchor - else + elseif header_line_nr < 0 + " Tag appeared before the first header let entry.link = page_name + else + let entry.link = page_name . '#' . tag endif call add(metadata, entry) endwhile From 17cfd6e61366be08578781f167a781437f7393c9 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Fri, 23 Jan 2015 23:13:27 +0300 Subject: [PATCH 17/38] Modify patterns and code -- tag colons must be either at line boundary, or surrounded with white spaces --- autoload/vimwiki/base.vim | 48 +++++++++++++++++++---------------- syntax/omnipresent_syntax.vim | 4 +-- syntax/vimwiki_default.vim | 3 ++- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index d227026..2cb1c23 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -668,14 +668,16 @@ function! vimwiki#base#get_anchors(filename, syntax) "{{{ " collect tags text (there can be several in one line) let tag_count = 1 while 1 - let tag_text = matchstr(line, rxtag, 0, tag_count) - if tag_text == '' + let tag_group_text = matchstr(line, rxtag, 0, tag_count) + if tag_group_text == '' break endif - call add(anchors, tag_text) - if current_complete_anchor != '' - call add(anchors, current_complete_anchor.'#'.tag_text) - endif + for tag_text in split(tag_group_text, ':') + call add(anchors, tag_text) + if current_complete_anchor != '' + call add(anchors, current_complete_anchor.'#'.tag_text) + endif + endfor let tag_count += 1 endwhile @@ -2047,26 +2049,28 @@ function! vimwiki#base#scan_tags(lines, page_name) "{{{ " Scan line for tags. There can be many of them. let str = line while 1 - let tag = matchstr(str, rxtag) - if tag == '' + let tag_group = matchstr(str, rxtag) + if tag_group == '' break endif let tagend = matchend(str, rxtag) let str = str[(tagend):] - " Create metadata entry - let entry = {} - let entry.tagname = tag - let entry.pagename = page_name - let entry.lineno = line_nr - if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) - let entry.link = page_name . '#' . current_complete_anchor - elseif header_line_nr < 0 - " Tag appeared before the first header - let entry.link = page_name - else - let entry.link = page_name . '#' . tag - endif - call add(metadata, entry) + for tag in split(tag_group, ':') + " Create metadata entry + let entry = {} + let entry.tagname = tag + let entry.pagename = page_name + let entry.lineno = line_nr + if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) + let entry.link = page_name . '#' . current_complete_anchor + elseif header_line_nr < 0 + " Tag appeared before the first header + let entry.link = page_name + else + let entry.link = page_name . '#' . tag + endif + call add(metadata, entry) + endfor endwhile endfor " loop over lines diff --git a/syntax/omnipresent_syntax.vim b/syntax/omnipresent_syntax.vim index a3c2058..4afc4cc 100644 --- a/syntax/omnipresent_syntax.vim +++ b/syntax/omnipresent_syntax.vim @@ -14,8 +14,8 @@ let g:vimwiki_default_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\ let g:vimwiki_default_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_default_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_default_wikilink = '\[\[\zs[^\\\]|]\+\ze\%(|[^\\\]]\+\)\?\]\]' -let g:vimwiki_default_tag_search = ':\zs[^:[:space:]]\+\ze:' -let g:vimwiki_default_tag_match = ':__Tag__:' +let g:vimwiki_default_tag_search = '\(^\|\s\)\zs:\([^:[:space:]]\+:\)\+\ze\(\s\|$\)' +let g:vimwiki_default_tag_match = '\(^\|\s\):\([^:[:space:]]\+:\)*__Tag__:\([^:[:space:]]\+:\)*\(\s\|$\)' let g:vimwiki_markdown_header_search = '^\s*\(#\{1,6}\)\([^#].*\)$' let g:vimwiki_markdown_header_match = '^\s*\(#\{1,6}\)#\@!\s*__Header__\s*$' diff --git a/syntax/vimwiki_default.vim b/syntax/vimwiki_default.vim index e0c73a5..b8b9a65 100644 --- a/syntax/vimwiki_default.vim +++ b/syntax/vimwiki_default.vim @@ -95,4 +95,5 @@ let g:vimwiki_rxMathStart = '{{\$' let g:vimwiki_rxMathEnd = '}}\$' let g:vimwiki_rxComment = '^\s*%%.*$' -let g:vimwiki_rxTags = ':\([^:[:space:]]\+:\)\+' +let g:vimwiki_rxTags = '\(^\|\s\)\zs:\([^:[:space:]]\+:\)\+\ze\(\s\|$\)' +" see also g:vimwiki_default_tag_search From d2ff96717e9f5bb3392c42df79df5f7e4d8c0822 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Thu, 29 Jan 2015 13:48:15 +0400 Subject: [PATCH 18/38] Encapsulate tag path into a function; expand paths in it to make them absolute --- autoload/vimwiki/base.vim | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 2cb1c23..5541dbe 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -2077,10 +2077,16 @@ function! vimwiki#base#scan_tags(lines, page_name) "{{{ return metadata endfunction " }}} +" vimwiki#base#metadata_file_path +" Returns tags metadata file path +function! vimwiki#base#metadata_file_path() abort "{{{ + return fnamemodify(VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME, ':p') +endfunction " }}} + " vimwiki#base#load_tags_metadata " Loads tags metadata from file, returns a dictionary function! vimwiki#base#load_tags_metadata() abort "{{{ - let metadata_path = VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME + let metadata_path = vimwiki#base#metadata_file_path() if !filereadable(metadata_path) return [] endif @@ -2142,7 +2148,7 @@ endfunction " }}} " vimwiki#base#write_tags_metadata " Saves metadata object into a file. Throws exceptions in case of problems. function! vimwiki#base#write_tags_metadata(metadata) "{{{ - let metadata_path = VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME + let metadata_path = vimwiki#base#metadata_file_path() let entries = [] for entry in a:metadata let entry_data = entry.pagename . "\t" . entry.link From 42f427e718e5bfe55418d8e9adb63014d45bbb03 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Thu, 5 Feb 2015 00:05:04 +0300 Subject: [PATCH 19/38] Fix issue with tags completion not working right after the colon --- ftplugin/vimwiki.vim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index e94f8f6..130c091 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -66,8 +66,10 @@ function! Complete_wikifiles(findstart, base) " Tags completion let metadata = vimwiki#base#load_tags_metadata() let tags = vimwiki#base#get_tags(metadata) - call filter(tags, + if a:base != '' + call filter(tags, \ "v:val[:" . (len(a:base)-1) . "] == '" . substitute(a:base, "'", "''", '') . "'" ) + endif return tags elseif a:base !~ '#' " we look for wiki files From ac4f66586a5c154ef9defd6e32efba0d5a343c6f Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Mon, 9 Feb 2015 21:40:17 +0100 Subject: [PATCH 20/38] col('.') inside the omnicompletion function returns garbage so use a workaround --- ftplugin/vimwiki.vim | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 130c091..ea2be98 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -43,26 +43,30 @@ function! Complete_wikifiles(findstart, base) let line = getline('.')[:column] let startoflink = match(line, '\[\[\zs[^\\[]*$') if startoflink != -1 + let s:line_context = '[' return startoflink endif if VimwikiGet('syntax') == 'markdown' let startofinlinelink = match(line, '\[.*\](\zs.*$') if startofinlinelink != -1 + let s:line_context = '[' return startofinlinelink endif endif let startoftag = match(line, ':\zs[^:[:space:]]*$') if startoftag != -1 + let s:line_context = ':' return startoftag endif + let s:line_context = '' return -1 else - " Completion works for wikilinks/anchors, and for tags. So first we have - " to find out what we're about to complete. - let column = col('.') - let line = getline('.')[:(column - len(a:base))] - let char_before_start = line[-1:-1] - if char_before_start == ':' + " Completion works for wikilinks/anchors, and for tags. s:line_content + " tells us, which string came before a:base. There seems to be no easier + " solution, because calling col('.') here returns garbage. + if s:line_context == '' + return [] + elseif s:line_context == ':' " Tags completion let metadata = vimwiki#base#load_tags_metadata() let tags = vimwiki#base#get_tags(metadata) From df5e49c7fdb684bccd67ef4baac2c29e17745117 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Mon, 9 Feb 2015 21:56:28 +0100 Subject: [PATCH 21/38] Fix completion in some circumstances --- ftplugin/vimwiki.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index ea2be98..c6bc5cb 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -39,15 +39,15 @@ setlocal tags+=./.tags " COMPLETION {{{ function! Complete_wikifiles(findstart, base) if a:findstart == 1 - let column = col('.')-1 + let column = col('.')-2 let line = getline('.')[:column] - let startoflink = match(line, '\[\[\zs[^\\[]*$') + let startoflink = match(line, '\[\[\zs[^\\[\]]*$') if startoflink != -1 let s:line_context = '[' return startoflink endif if VimwikiGet('syntax') == 'markdown' - let startofinlinelink = match(line, '\[.*\](\zs.*$') + let startofinlinelink = match(line, '\[.*\](\zs[^)]*$') if startofinlinelink != -1 let s:line_context = '[' return startofinlinelink From 8055ef8608e4d24a75ddabf9778042b2ba1ae86f Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Mon, 16 Feb 2015 12:53:32 +0100 Subject: [PATCH 22/38] Fix highlighting of tags in some circumstances, e.g. - :Tag: the tag wasn't highlighted. Don't know why. --- syntax/vimwiki_default.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syntax/vimwiki_default.vim b/syntax/vimwiki_default.vim index fc22f66..dcc401c 100644 --- a/syntax/vimwiki_default.vim +++ b/syntax/vimwiki_default.vim @@ -92,5 +92,5 @@ let g:vimwiki_rxMathStart = '{{\$' let g:vimwiki_rxMathEnd = '}}\$' let g:vimwiki_rxComment = '^\s*%%.*$' -let g:vimwiki_rxTags = '\(^\|\s\)\zs:\([^:[:space:]]\+:\)\+\ze\(\s\|$\)' +let g:vimwiki_rxTags = '\%(^\|\s\)\@<=:\%([^:[:space:]]\+:\)\+\%(\s\|$\)\@=' " see also g:vimwiki_default_tag_search From 7e87e929549b3a4fb5d32d60c4e36fd4bd0d0d7e Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Mon, 23 Feb 2015 11:29:02 +0100 Subject: [PATCH 23/38] Move tags-related functions to extra file also rename some functions from vimwiki#tags#bla() to s:bla() --- autoload/vimwiki/base.vim | 274 -------------------------------------- autoload/vimwiki/tags.vim | 274 ++++++++++++++++++++++++++++++++++++++ ftplugin/vimwiki.vim | 14 +- 3 files changed, 281 insertions(+), 281 deletions(-) create mode 100644 autoload/vimwiki/tags.vim diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 39f7a81..8845f68 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1934,282 +1934,8 @@ endfunction "}}} " }}} -" TAGS functions {{{ - -let s:TAGS_METADATA_FILE_NAME = '.tags' - -" Tags metadata in-memory format: -" metadata := [ entry, ... ] -" entry := { 'tagname':..., 'pagename':..., 'lineno':..., 'link':... } - -" Tags metadata in-file format: -" -" Is based on CTags format (see |tags-file-format|). -" -" {tagaddress} is set to lineno. We'll let vim search by exact line number; we -" can afford that, we assume metadata file is always updated before use. -" -" Pagename and link are not saved in standard ctags fields, so we'll add -" an optional field, "vimwiki:". In this field, we encode tab-separated values -" of missing parameters -- "pagename" and "link". - -" vimwiki#base#update_tags -" Update tags metadata. -" a:full_rebuild == 1: re-scan entire wiki -" a:full_rebuild == 0: only re-scan current page -function! vimwiki#base#update_tags(full_rebuild) "{{{ - if !a:full_rebuild - " Updating for one page (current) - let page_name = expand('%:t:r') - " Collect tags in current file - let tags = vimwiki#base#scan_tags(getline(1, '$'), page_name) - " Load metadata file - let metadata = vimwiki#base#load_tags_metadata() - " Drop old tags - let metadata = vimwiki#base#remove_page_from_tags(metadata, page_name) - " Merge in the new ones - let metadata = vimwiki#base#merge_tags(metadata, tags) - " Save - call vimwiki#base#write_tags_metadata(metadata) - else " full rebuild - let files = s:find_files(g:vimwiki_current_idx, 0) - let metadata = [] - for file in files - let page_name = fnamemodify(file, ':t:r') - let tags = vimwiki#base#scan_tags(readfile(file), page_name) - let metadata = vimwiki#base#merge_tags(metadata, tags) - endfor - call vimwiki#base#write_tags_metadata(metadata) - endif -endfunction " }}} - -" vimwiki#base#scan_tags -" Scans the list of text lines (argument) and produces tags metadata. -function! vimwiki#base#scan_tags(lines, page_name) "{{{ - - let metadata = [] - let page_name = a:page_name - - " Code wireframe to scan for headers -- borrowed from - " vimwiki#base#get_anchors(), with minor modifications. - - let rxheader = g:vimwiki_{VimwikiGet('syntax')}_header_search - let rxtag = g:vimwiki_{VimwikiGet('syntax')}_tag_search - - let anchor_level = ['', '', '', '', '', '', ''] - let current_complete_anchor = '' - - let PROXIMITY_LINES_NR = 5 - let header_line_nr = - (2 * PROXIMITY_LINES_NR) - - for line_nr in range(1, len(a:lines)) - let line = a:lines[line_nr - 1] - - " process headers - let h_match = matchlist(line, rxheader) - if !empty(h_match) " got a header - let header_line_nr = line_nr - let header = vimwiki#u#trim(h_match[2]) - let level = len(h_match[1]) - let anchor_level[level-1] = header - for l in range(level, 6) - let anchor_level[l] = '' - endfor - if level == 1 - let current_complete_anchor = header - else - let current_complete_anchor = '' - for l in range(level-1) - if anchor_level[l] != '' - let current_complete_anchor .= anchor_level[l].'#' - endif - endfor - let current_complete_anchor .= header - endif - continue " tags are not allowed in headers - endif - - " TODO ignore verbatim blocks - - " Scan line for tags. There can be many of them. - let str = line - while 1 - let tag_group = matchstr(str, rxtag) - if tag_group == '' - break - endif - let tagend = matchend(str, rxtag) - let str = str[(tagend):] - for tag in split(tag_group, ':') - " Create metadata entry - let entry = {} - let entry.tagname = tag - let entry.pagename = page_name - let entry.lineno = line_nr - if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) - let entry.link = page_name . '#' . current_complete_anchor - elseif header_line_nr < 0 - " Tag appeared before the first header - let entry.link = page_name - else - let entry.link = page_name . '#' . tag - endif - call add(metadata, entry) - endfor - endwhile - - endfor " loop over lines - return metadata -endfunction " }}} - -" vimwiki#base#metadata_file_path -" Returns tags metadata file path -function! vimwiki#base#metadata_file_path() abort "{{{ - return fnamemodify(VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME, ':p') -endfunction " }}} - -" vimwiki#base#load_tags_metadata -" Loads tags metadata from file, returns a dictionary -function! vimwiki#base#load_tags_metadata() abort "{{{ - let metadata_path = vimwiki#base#metadata_file_path() - if !filereadable(metadata_path) - return [] - endif - let metadata = [] - for line in readfile(metadata_path) - if line =~ '^!_TAG_FILE_' - continue - endif - let parts = matchlist(line, '^\(.\{-}\);"\(.*\)$') - if parts[0] == '' || parts[1] == '' || parts[2] == '' - throw 'VimwikiTags1: Metadata file corrupted' - endif - let std_fields = split(parts[1], '\t') - if len(std_fields) != 3 - throw 'VimwikiTags2: Metadata file corrupted' - endif - let vw_part = parts[2] - if vw_part[0] != "\t" - throw 'VimwikiTags3: Metadata file corrupted' - endif - let vw_fields = split(vw_part[1:], "\t") - if len(vw_fields) != 1 || vw_fields[0] !~ '^vimwiki:' - throw 'VimwikiTags4: Metadata file corrupted' - endif - let vw_data = substitute(vw_fields[0], '^vimwiki:', '', '') - let vw_data = substitute(vw_data, '\\n', "\n", 'g') - let vw_data = substitute(vw_data, '\\r', "\r", 'g') - let vw_data = substitute(vw_data, '\\t', "\t", 'g') - let vw_data = substitute(vw_data, '\\\\', "\\", 'g') - let vw_fields = split(vw_data, "\t") - if len(vw_fields) != 2 - throw 'VimwikiTags5: Metadata file corrupted' - endif - let entry = {} - let entry.tagname = std_fields[0] - let entry.pagename = vw_fields[0] - let entry.lineno = std_fields[2] - let entry.link = vw_fields[1] - call add(metadata, entry) - endfor - return metadata -endfunction " }}} - -" vimwiki#base#remove_page_from_tags -" Removes all entries for given page from metadata in-place. Returns updated -" metadata (just in case). -function! vimwiki#base#remove_page_from_tags(metadata, page_name) "{{{ - let metadata = filter(a:metadata, - \ "v:val.pagename != '" . substitute(a:page_name, "'", "''", '') . "'") - return metadata -endfunction " }}} - -" vimwiki#base#merge_tags -" Merges two tags metadata objects into (new) one. -function! vimwiki#base#merge_tags(metadata1, metadata2) "{{{ - return a:metadata1 + a:metadata2 -endfunction " }}} - -" vimwiki#base#write_tags_metadata -" Saves metadata object into a file. Throws exceptions in case of problems. -function! vimwiki#base#write_tags_metadata(metadata) "{{{ - let metadata_path = vimwiki#base#metadata_file_path() - let entries = [] - for entry in a:metadata - let entry_data = entry.pagename . "\t" . entry.link - let entry_data = substitute(entry_data, "\\", '\\\\', '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, "\n", '\\n', 'g') - call add(entries, - \ entry.tagname . "\t" - \ . entry.pagename . VimwikiGet('ext') . "\t" - \ . entry.lineno - \ . ';"' - \ . "\t" . "vimwiki:" . entry_data - \) - endfor - call sort(entries) - call insert(entries, "!_TAG_FILE_SORTED\t1\t{anything}") - call writefile(entries, metadata_path) -endfunction " }}} - -" vimwiki#base#get_tags -" Returns list of unique tags found in metadata -function! vimwiki#base#get_tags(metadata) "{{{ - let tags = {} - for entry in a:metadata - let tags[entry.tagname] = 1 - endfor - return keys(tags) -endfunction " }}} - -" vimwiki#base#generate_tags -" Similar to vimwiki#base#generate_links. In the current buffer, appends -" tags and references to all their instances. If no arguments (tags) are -" specified, outputs all tags. -function! vimwiki#base#generate_tags(...) abort "{{{ - let need_all_tags = (a:0 == 0) - let specific_tags = a:000 - - let metadata = vimwiki#base#load_tags_metadata() - - call append(line('$'), [ - \ '', - \ substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Tags', '') ]) - - call sort(metadata) - - let bullet = repeat(' ', vimwiki#lst#get_list_margin()). - \ vimwiki#lst#default_symbol().' ' - let current_tag = '' - for entry in metadata - if need_all_tags || index(specific_tags, entry.tagname) != -1 - if entry.tagname != current_tag - let current_tag = entry.tagname - call append(line('$'), [ - \ '', - \ substitute(g:vimwiki_rxH2_Template, '__Header__', entry.tagname, ''), - \ '' ]) - endif - call append(line('$'), bullet . '[[' . entry.link . ']]') - endif - endfor -endfunction " }}} - -" }}} - " Command completion functions {{{ -" vimwiki#base#complete_tags -function! vimwiki#base#complete_tags(ArgLead, CmdLine, CursorPos) abort " {{{ - " We can safely ignore args if we use -custom=complete option, Vim engine - " will do the job of filtering. - let metadata = vimwiki#base#load_tags_metadata() - let taglist = vimwiki#base#get_tags(metadata) - return join(taglist, "\n") -endfunction " }}} - " vimwiki#base#complete_links_escaped function! vimwiki#base#complete_links_escaped(ArgLead, CmdLine, CursorPos) abort " {{{ " We can safely ignore args if we use -custom=complete option, Vim engine diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim new file mode 100644 index 0000000..0575d77 --- /dev/null +++ b/autoload/vimwiki/tags.vim @@ -0,0 +1,274 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" Vimwiki autoload plugin file + + +let s:TAGS_METADATA_FILE_NAME = '.tags' + +" Tags metadata in-memory format: +" metadata := [ entry, ... ] +" entry := { 'tagname':..., 'pagename':..., 'lineno':..., 'link':... } + +" Tags metadata in-file format: +" +" Is based on CTags format (see |tags-file-format|). +" +" {tagaddress} is set to lineno. We'll let vim search by exact line number; we +" can afford that, we assume metadata file is always updated before use. +" +" Pagename and link are not saved in standard ctags fields, so we'll add +" an optional field, "vimwiki:". In this field, we encode tab-separated values +" of missing parameters -- "pagename" and "link". + +" vimwiki#tags#update_tags +" Update tags metadata. +" a:full_rebuild == 1: re-scan entire wiki +" a:full_rebuild == 0: only re-scan current page +function! vimwiki#tags#update_tags(full_rebuild) "{{{ + if !a:full_rebuild + " Updating for one page (current) + let page_name = expand('%:t:r') + " Collect tags in current file + let tags = s:scan_tags(getline(1, '$'), page_name) + " Load metadata file + let metadata = vimwiki#tags#load_tags_metadata() + " Drop old tags + let metadata = s:remove_page_from_tags(metadata, page_name) + " Merge in the new ones + let metadata = s:merge_tags(metadata, tags) + " Save + call s:write_tags_metadata(metadata) + else " full rebuild + let files = s:find_files(g:vimwiki_current_idx, 0) + let metadata = [] + for file in files + let page_name = fnamemodify(file, ':t:r') + let tags = s:scan_tags(readfile(file), page_name) + let metadata = s:merge_tags(metadata, tags) + endfor + call s:write_tags_metadata(metadata) + endif +endfunction " }}} + +" s:scan_tags +" Scans the list of text lines (argument) and produces tags metadata. +function! s:scan_tags(lines, page_name) "{{{ + + let metadata = [] + let page_name = a:page_name + + " Code wireframe to scan for headers -- borrowed from + " vimwiki#base#get_anchors(), with minor modifications. + + let rxheader = g:vimwiki_{VimwikiGet('syntax')}_header_search + let rxtag = g:vimwiki_{VimwikiGet('syntax')}_tag_search + + let anchor_level = ['', '', '', '', '', '', ''] + let current_complete_anchor = '' + + let PROXIMITY_LINES_NR = 5 + let header_line_nr = - (2 * PROXIMITY_LINES_NR) + + for line_nr in range(1, len(a:lines)) + let line = a:lines[line_nr - 1] + + " process headers + let h_match = matchlist(line, rxheader) + if !empty(h_match) " got a header + let header_line_nr = line_nr + let header = vimwiki#u#trim(h_match[2]) + let level = len(h_match[1]) + let anchor_level[level-1] = header + for l in range(level, 6) + let anchor_level[l] = '' + endfor + if level == 1 + let current_complete_anchor = header + else + let current_complete_anchor = '' + for l in range(level-1) + if anchor_level[l] != '' + let current_complete_anchor .= anchor_level[l].'#' + endif + endfor + let current_complete_anchor .= header + endif + continue " tags are not allowed in headers + endif + + " TODO ignore verbatim blocks + + " Scan line for tags. There can be many of them. + let str = line + while 1 + let tag_group = matchstr(str, rxtag) + if tag_group == '' + break + endif + let tagend = matchend(str, rxtag) + let str = str[(tagend):] + for tag in split(tag_group, ':') + " Create metadata entry + let entry = {} + let entry.tagname = tag + let entry.pagename = page_name + let entry.lineno = line_nr + if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) + let entry.link = page_name . '#' . current_complete_anchor + elseif header_line_nr < 0 + " Tag appeared before the first header + let entry.link = page_name + else + let entry.link = page_name . '#' . tag + endif + call add(metadata, entry) + endfor + endwhile + + endfor " loop over lines + return metadata +endfunction " }}} + +" s:metadata_file_path +" Returns tags metadata file path +function! s:metadata_file_path() abort "{{{ + return fnamemodify(VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME, ':p') +endfunction " }}} + +" vimwiki#tags#load_tags_metadata +" Loads tags metadata from file, returns a dictionary +function! vimwiki#tags#load_tags_metadata() abort "{{{ + let metadata_path = s:metadata_file_path() + if !filereadable(metadata_path) + return [] + endif + let metadata = [] + for line in readfile(metadata_path) + if line =~ '^!_TAG_FILE_' + continue + endif + let parts = matchlist(line, '^\(.\{-}\);"\(.*\)$') + if parts[0] == '' || parts[1] == '' || parts[2] == '' + throw 'VimwikiTags1: Metadata file corrupted' + endif + let std_fields = split(parts[1], '\t') + if len(std_fields) != 3 + throw 'VimwikiTags2: Metadata file corrupted' + endif + let vw_part = parts[2] + if vw_part[0] != "\t" + throw 'VimwikiTags3: Metadata file corrupted' + endif + let vw_fields = split(vw_part[1:], "\t") + if len(vw_fields) != 1 || vw_fields[0] !~ '^vimwiki:' + throw 'VimwikiTags4: Metadata file corrupted' + endif + let vw_data = substitute(vw_fields[0], '^vimwiki:', '', '') + let vw_data = substitute(vw_data, '\\n', "\n", 'g') + let vw_data = substitute(vw_data, '\\r', "\r", 'g') + let vw_data = substitute(vw_data, '\\t', "\t", 'g') + let vw_data = substitute(vw_data, '\\\\', "\\", 'g') + let vw_fields = split(vw_data, "\t") + if len(vw_fields) != 2 + throw 'VimwikiTags5: Metadata file corrupted' + endif + let entry = {} + let entry.tagname = std_fields[0] + let entry.pagename = vw_fields[0] + let entry.lineno = std_fields[2] + let entry.link = vw_fields[1] + call add(metadata, entry) + endfor + return metadata +endfunction " }}} + +" s:remove_page_from_tags +" Removes all entries for given page from metadata in-place. Returns updated +" metadata (just in case). +function! s:remove_page_from_tags(metadata, page_name) "{{{ + let metadata = filter(a:metadata, + \ "v:val.pagename != '" . substitute(a:page_name, "'", "''", '') . "'") + return metadata +endfunction " }}} + +" s:merge_tags +" Merges two tags metadata objects into (new) one. +function! s:merge_tags(metadata1, metadata2) "{{{ + return a:metadata1 + a:metadata2 +endfunction " }}} + +" s:write_tags_metadata +" Saves metadata object into a file. Throws exceptions in case of problems. +function! s:write_tags_metadata(metadata) "{{{ + let metadata_path = s:metadata_file_path() + let entries = [] + for entry in a:metadata + let entry_data = entry.pagename . "\t" . entry.link + let entry_data = substitute(entry_data, "\\", '\\\\', '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, "\n", '\\n', 'g') + call add(entries, + \ entry.tagname . "\t" + \ . entry.pagename . VimwikiGet('ext') . "\t" + \ . entry.lineno + \ . ';"' + \ . "\t" . "vimwiki:" . entry_data + \) + endfor + call sort(entries) + call insert(entries, "!_TAG_FILE_SORTED\t1\t{anything}") + call writefile(entries, metadata_path) +endfunction " }}} + +" vimwiki#tags#get_tags +" Returns list of unique tags found in metadata +function! vimwiki#tags#get_tags(metadata) "{{{ + let tags = {} + for entry in a:metadata + let tags[entry.tagname] = 1 + endfor + return keys(tags) +endfunction " }}} + +" vimwiki#tags#generate_tags +" Similar to vimwiki#base#generate_links. In the current buffer, appends +" tags and references to all their instances. If no arguments (tags) are +" specified, outputs all tags. +function! vimwiki#tags#generate_tags(...) abort "{{{ + let need_all_tags = (a:0 == 0) + let specific_tags = a:000 + + let metadata = vimwiki#tags#load_tags_metadata() + + call append(line('$'), [ + \ '', + \ substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Tags', '') ]) + + call sort(metadata) + + let bullet = repeat(' ', vimwiki#lst#get_list_margin()). + \ vimwiki#lst#default_symbol().' ' + let current_tag = '' + for entry in metadata + if need_all_tags || index(specific_tags, entry.tagname) != -1 + if entry.tagname != current_tag + let current_tag = entry.tagname + call append(line('$'), [ + \ '', + \ substitute(g:vimwiki_rxH2_Template, '__Header__', entry.tagname, ''), + \ '' ]) + endif + call append(line('$'), bullet . '[[' . entry.link . ']]') + endif + endfor +endfunction " }}} + +" vimwiki#tags#complete_tags +function! vimwiki#tags#complete_tags(ArgLead, CmdLine, CursorPos) abort " {{{ + " We can safely ignore args if we use -custom=complete option, Vim engine + " will do the job of filtering. + let metadata = vimwiki#tags#load_tags_metadata() + let taglist = vimwiki#tags#get_tags(metadata) + return join(taglist, "\n") +endfunction " }}} + diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 73b6ec7..6b4538a 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -68,8 +68,8 @@ function! Complete_wikifiles(findstart, base) return [] elseif s:line_context == ':' " Tags completion - let metadata = vimwiki#base#load_tags_metadata() - let tags = vimwiki#base#get_tags(metadata) + let metadata = vimwiki#tags#load_tags_metadata() + let tags = vimwiki#tags#get_tags(metadata) if a:base != '' call filter(tags, \ "v:val[:" . (len(a:base)-1) . "] == '" . substitute(a:base, "'", "''", '') . "'" ) @@ -311,11 +311,11 @@ command! -buffer VimwikiDiaryNextDay call vimwiki#diary#goto_next_day() command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day() " tags commands -command! -buffer VimwikiRebuildTags call vimwiki#base#update_tags(1) -command! -buffer -nargs=* -complete=custom,vimwiki#base#complete_tags +command! -buffer VimwikiRebuildTags call vimwiki#tags#update_tags(1) +command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags \ VimwikiSearchTags VimwikiSearch /::/ -command! -buffer -nargs=* -complete=custom,vimwiki#base#complete_tags - \ VimwikiGenerateTags call vimwiki#base#generate_tags() +command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags + \ VimwikiGenerateTags call vimwiki#tags#generate_tags() " COMMANDS }}} @@ -653,7 +653,7 @@ endif if VimwikiGet('auto_tags') " Automatically update tags metadata on page write. augroup vimwiki - au BufWritePost call vimwiki#base#update_tags(0) + au BufWritePost call vimwiki#tags#update_tags(0) augroup END endif " AUTOCOMMANDS }}} From 55adfca6a11ba3d0ded6b6efb29daeb857799686 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Tue, 24 Feb 2015 09:39:03 +0100 Subject: [PATCH 24/38] Rename a function, fixes previous commit --- autoload/vimwiki/base.vim | 10 +++++----- autoload/vimwiki/tags.vim | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 8845f68..d10ea7f 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -514,7 +514,7 @@ function! vimwiki#base#backlinks() "{{{ let locations = [] for idx in range(len(g:vimwiki_list)) let syntax = VimwikiGet('syntax', idx) - let wikifiles = s:find_files(idx, 0) + let wikifiles = vimwiki#base#find_files(idx, 0) for source_file in wikifiles let links = s:get_links(source_file, idx) for [target_file, _, lnum, col] in links @@ -538,7 +538,7 @@ endfunction "}}} " Returns: a list containing all files of the given wiki as absolute file path. " If the given wiki number is negative, the diary of the current wiki is used " If the second argument is not zero, only directories are found -function! s:find_files(wiki_nr, directories_only) +function! vimwiki#base#find_files(wiki_nr, directories_only) let wiki_nr = a:wiki_nr if wiki_nr >= 0 let root_directory = VimwikiGet('path', wiki_nr) @@ -565,7 +565,7 @@ endfunction " Returns: a list containing the links to all wiki files for the given wiki " If the given wiki number is negative, the diary of the current wiki is used function! vimwiki#base#get_wikilinks(wiki_nr) - let files = s:find_files(a:wiki_nr, 0) + let files = vimwiki#base#find_files(a:wiki_nr, 0) if a:wiki_nr == g:vimwiki_current_idx let cwd = vimwiki#path#wikify_path(expand('%:p:h')) elseif a:wiki_nr < 0 @@ -584,7 +584,7 @@ endfunction " Returns: a list containing function! vimwiki#base#get_wiki_directories(wiki_nr) - let dirs = s:find_files(a:wiki_nr, 1) + let dirs = vimwiki#base#find_files(a:wiki_nr, 1) if a:wiki_nr == g:vimwiki_current_idx let cwd = vimwiki#path#wikify_path(expand('%:p:h')) else @@ -786,7 +786,7 @@ function! vimwiki#base#check_links() "{{{ let errors = [] for idx in range(len(g:vimwiki_list)) let syntax = VimwikiGet('syntax', idx) - let wikifiles = s:find_files(idx, 0) + let wikifiles = vimwiki#base#find_files(idx, 0) for wikifile in wikifiles let links_of_files[wikifile] = s:get_links(wikifile, idx) let anchors_of_files[wikifile] = vimwiki#base#get_anchors(wikifile, syntax) diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index 0575d77..9fc6288 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -38,7 +38,7 @@ function! vimwiki#tags#update_tags(full_rebuild) "{{{ " Save call s:write_tags_metadata(metadata) else " full rebuild - let files = s:find_files(g:vimwiki_current_idx, 0) + let files = vimwiki#base#find_files(g:vimwiki_current_idx, 0) let metadata = [] for file in files let page_name = fnamemodify(file, ':t:r') From c543f8cfb18ab58db474ce64546eb191809a90c4 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Wed, 25 Mar 2015 21:44:44 +0300 Subject: [PATCH 25/38] Fixed issue with tags in subfolders not being saved in tags file properly (subdir name lost) --- autoload/vimwiki/tags.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index 9fc6288..f81ff76 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -26,7 +26,7 @@ let s:TAGS_METADATA_FILE_NAME = '.tags' function! vimwiki#tags#update_tags(full_rebuild) "{{{ if !a:full_rebuild " Updating for one page (current) - let page_name = expand('%:t:r') + let page_name = VimwikiGet('subdir') . expand('%:t:r') " Collect tags in current file let tags = s:scan_tags(getline(1, '$'), page_name) " Load metadata file From 4617576c2005d07ce6cd7c52b9c5a966ca9485f6 Mon Sep 17 00:00:00 2001 From: Ivan Tishchenko Date: Sun, 26 Apr 2015 22:13:03 +0300 Subject: [PATCH 26/38] Fix bug: tags would not work in subfolders ('tags file not found') --- ftplugin/vimwiki.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 72f5e99..2cc745d 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -31,7 +31,7 @@ execute 'setlocal suffixesadd='.VimwikiGet('ext') setlocal isfname-=[,] " gf}}} -setlocal tags+=./.tags +setlocal tags+=.tags " MISC }}} From 6c77fd9101f84a32c463ddd1753996ce28beaa03 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Fri, 15 May 2015 10:56:46 +0200 Subject: [PATCH 27/38] :VimwikiRebuildTags! only reads files newer than .tags file Ref #85 --- autoload/vimwiki/tags.vim | 135 +++++++++++++++++++++++--------------- ftplugin/vimwiki.vim | 5 +- 2 files changed, 84 insertions(+), 56 deletions(-) diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index f81ff76..45e86b6 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -5,8 +5,8 @@ let s:TAGS_METADATA_FILE_NAME = '.tags' " Tags metadata in-memory format: -" metadata := [ entry, ... ] -" entry := { 'tagname':..., 'pagename':..., 'lineno':..., 'link':... } +" metadata := { 'pagename': [entries, ...] } +" entry := { 'tagname':..., 'lineno':..., 'link':... } " Tags metadata in-file format: " @@ -23,7 +23,9 @@ let s:TAGS_METADATA_FILE_NAME = '.tags' " Update tags metadata. " a:full_rebuild == 1: re-scan entire wiki " 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 " Updating for one page (current) let page_name = VimwikiGet('subdir') . expand('%:t:r') @@ -34,26 +36,31 @@ function! vimwiki#tags#update_tags(full_rebuild) "{{{ " Drop old tags let metadata = s:remove_page_from_tags(metadata, page_name) " Merge in the new ones - let metadata = s:merge_tags(metadata, tags) + let metadata = s:merge_tags(metadata, page_name, tags) " Save call s:write_tags_metadata(metadata) else " full rebuild 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 - let page_name = fnamemodify(file, ':t:r') - let tags = s:scan_tags(readfile(file), page_name) - let metadata = s:merge_tags(metadata, tags) + if all_files || getftime(file) >= tags_file_last_modification + let page_name = fnamemodify(file, ':t:r') + let tags = s:scan_tags(readfile(file), page_name) + let metadata = s:remove_page_from_tags(metadata, page_name) + let metadata = s:merge_tags(metadata, page_name, tags) + endif endfor call s:write_tags_metadata(metadata) endif endfunction " }}} " 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) "{{{ - let metadata = [] + let entries = [] let page_name = a:page_name " Code wireframe to scan for headers -- borrowed from @@ -110,7 +117,6 @@ function! s:scan_tags(lines, page_name) "{{{ " Create metadata entry let entry = {} let entry.tagname = tag - let entry.pagename = page_name let entry.lineno = line_nr if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) let entry.link = page_name . '#' . current_complete_anchor @@ -120,12 +126,12 @@ function! s:scan_tags(lines, page_name) "{{{ else let entry.link = page_name . '#' . tag endif - call add(metadata, entry) + call add(entries, entry) endfor endwhile endfor " loop over lines - return metadata + return entries endfunction " }}} " s:metadata_file_path @@ -139,9 +145,9 @@ endfunction " }}} function! vimwiki#tags#load_tags_metadata() abort "{{{ let metadata_path = s:metadata_file_path() if !filereadable(metadata_path) - return [] + return {} endif - let metadata = [] + let metadata = {} for line in readfile(metadata_path) if line =~ '^!_TAG_FILE_' continue @@ -171,12 +177,16 @@ function! vimwiki#tags#load_tags_metadata() abort "{{{ if len(vw_fields) != 2 throw 'VimwikiTags5: Metadata file corrupted' endif + let pagename = vw_fields[0] let entry = {} let entry.tagname = std_fields[0] - let entry.pagename = vw_fields[0] let entry.lineno = std_fields[2] 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 return metadata endfunction " }}} @@ -185,47 +195,56 @@ endfunction " }}} " Removes all entries for given page from metadata in-place. Returns updated " metadata (just in case). function! s:remove_page_from_tags(metadata, page_name) "{{{ - let metadata = filter(a:metadata, - \ "v:val.pagename != '" . substitute(a:page_name, "'", "''", '') . "'") - return metadata + if has_key(a:metadata, a:page_name) + call remove(a:metadata, a:page_name) + return a:metadata + else + return a:metadata + endif endfunction " }}} " s:merge_tags -" Merges two tags metadata objects into (new) one. -function! s:merge_tags(metadata1, metadata2) "{{{ - return a:metadata1 + a:metadata2 +" Merges metadata of one file into a:metadata +function! s:merge_tags(metadata, pagename, file_metadata) "{{{ + let metadata = a:metadata + let metadata[a:pagename] = a:file_metadata + return metadata endfunction " }}} " s:write_tags_metadata " Saves metadata object into a file. Throws exceptions in case of problems. function! s:write_tags_metadata(metadata) "{{{ let metadata_path = s:metadata_file_path() - let entries = [] - for entry in a:metadata - let entry_data = entry.pagename . "\t" . entry.link - let entry_data = substitute(entry_data, "\\", '\\\\', '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, "\n", '\\n', 'g') - call add(entries, - \ entry.tagname . "\t" - \ . entry.pagename . VimwikiGet('ext') . "\t" - \ . entry.lineno - \ . ';"' - \ . "\t" . "vimwiki:" . entry_data - \) + let tags = [] + for pagename in keys(a:metadata) + 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, "\t", '\\t', 'g') + let entry_data = substitute(entry_data, "\r", '\\r', 'g') + let entry_data = substitute(entry_data, "\n", '\\n', 'g') + call add(tags, + \ entry.tagname . "\t" + \ . pagename . VimwikiGet('ext') . "\t" + \ . entry.lineno + \ . ';"' + \ . "\t" . "vimwiki:" . entry_data + \) + endfor endfor - call sort(entries) - call insert(entries, "!_TAG_FILE_SORTED\t1\t{anything}") - call writefile(entries, metadata_path) + call sort(tags) + call insert(tags, "!_TAG_FILE_SORTED\t1\t{anything}") + call writefile(tags, metadata_path) endfunction " }}} " vimwiki#tags#get_tags " Returns list of unique tags found in metadata function! vimwiki#tags#get_tags(metadata) "{{{ let tags = {} - for entry in a:metadata - let tags[entry.tagname] = 1 + for entries in values(a:metadata) + for entry in entries + let tags[entry.tagname] = 1 + endfor endfor return keys(tags) endfunction " }}} @@ -244,21 +263,29 @@ function! vimwiki#tags#generate_tags(...) abort "{{{ \ '', \ 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()). \ vimwiki#lst#default_symbol().' ' - let current_tag = '' - for entry in metadata - if need_all_tags || index(specific_tags, entry.tagname) != -1 - if entry.tagname != current_tag - let current_tag = entry.tagname - call append(line('$'), [ - \ '', - \ substitute(g:vimwiki_rxH2_Template, '__Header__', entry.tagname, ''), - \ '' ]) - endif - call append(line('$'), bullet . '[[' . entry.link . ']]') + for tagname in sort(keys(tags_entries)) + if need_all_tags || index(specific_tags, tagname) != -1 + call append(line('$'), [ + \ '', + \ substitute(g:vimwiki_rxH2_Template, '__Header__', tagname, ''), + \ '' ]) + for taglink in tags_entries[tagname] + call append(line('$'), bullet . '[[' . taglink . ']]') + endfor endif endfor endfunction " }}} diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 9466e75..f61c7eb 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -310,7 +310,8 @@ command! -buffer VimwikiDiaryNextDay call vimwiki#diary#goto_next_day() command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day() " tags commands -command! -buffer VimwikiRebuildTags call vimwiki#tags#update_tags(1) +command! -buffer -bang + \ VimwikiRebuildTags call vimwiki#tags#update_tags(1, '') command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags \ VimwikiSearchTags VimwikiSearch /::/ command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags @@ -652,7 +653,7 @@ endif if VimwikiGet('auto_tags') " Automatically update tags metadata on page write. augroup vimwiki - au BufWritePost call vimwiki#tags#update_tags(0) + au BufWritePost call vimwiki#tags#update_tags(0, '') augroup END endif " AUTOCOMMANDS }}} From 8bbe0408f983f8627a3e3bac7c29d5d51055f7af Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Fri, 15 May 2015 11:01:55 +0200 Subject: [PATCH 28/38] Set the 'tags' option correctly Ref #85 --- autoload/vimwiki/tags.vim | 11 ++++++----- ftplugin/vimwiki.vim | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index 45e86b6..b5d788d 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -41,7 +41,8 @@ function! vimwiki#tags#update_tags(full_rebuild, all_files) "{{{ call s:write_tags_metadata(metadata) else " full rebuild let files = vimwiki#base#find_files(g:vimwiki_current_idx, 0) - let tags_file_last_modification = getftime(s:metadata_file_path()) + let tags_file_last_modification = + \ getftime(vimwiki#tags#metadata_file_path()) let metadata = vimwiki#tags#load_tags_metadata() for file in files if all_files || getftime(file) >= tags_file_last_modification @@ -134,16 +135,16 @@ function! s:scan_tags(lines, page_name) "{{{ return entries endfunction " }}} -" s:metadata_file_path +" vimwiki#tags#metadata_file_path " Returns tags metadata file path -function! s:metadata_file_path() abort "{{{ +function! vimwiki#tags#metadata_file_path() abort "{{{ return fnamemodify(VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME, ':p') endfunction " }}} " vimwiki#tags#load_tags_metadata " Loads tags metadata from file, returns a dictionary function! vimwiki#tags#load_tags_metadata() abort "{{{ - let metadata_path = s:metadata_file_path() + let metadata_path = vimwiki#tags#metadata_file_path() if !filereadable(metadata_path) return {} endif @@ -214,7 +215,7 @@ endfunction " }}} " s:write_tags_metadata " Saves metadata object into a file. Throws exceptions in case of problems. function! s:write_tags_metadata(metadata) "{{{ - let metadata_path = s:metadata_file_path() + let metadata_path = vimwiki#tags#metadata_file_path() let tags = [] for pagename in keys(a:metadata) for entry in a:metadata[pagename] diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index f61c7eb..5cfd9e4 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -31,7 +31,7 @@ execute 'setlocal suffixesadd='.VimwikiGet('ext') setlocal isfname-=[,] " gf}}} -setlocal tags+=.tags +exe "setlocal tags+=" . vimwiki#tags#metadata_file_path() " MISC }}} From 3a333881d8d8a25d3e0716bdb222f4b782482df9 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Fri, 15 May 2015 11:03:14 +0200 Subject: [PATCH 29/38] When jumping to anchor, tags have highest precedence Otherwise, in the list generated by VimwikiGenerateTags, Vimwiki would jump to the header of the concerning tag rather than to the tag Ref #85 --- autoload/vimwiki/base.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index a8a38dd..32fd5d5 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -692,9 +692,9 @@ function! s:jump_to_anchor(anchor) "{{{ let anchor_tag = substitute(g:vimwiki_{VimwikiGet('syntax')}_tag_match, \ '__Tag__', "\\='".segment."'", '') - if !search(anchor_header, 'Wc') + if !search(anchor_tag, 'Wc') + \ && !search(anchor_header, 'Wc') \ && !search(anchor_bold, 'Wc') - \ && !search(anchor_tag, 'Wc') call setpos('.', oldpos) break endif From a2a28a2d916bf3f1633cdc177fddd1f30aadb622 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Fri, 15 May 2015 11:04:53 +0200 Subject: [PATCH 30/38] Make work also when the user jumped to a tag Ref #85 --- autoload/vimwiki/base.vim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 32fd5d5..9bb7e9f 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1164,6 +1164,9 @@ function! vimwiki#base#go_back_link() "{{{ let prev_word = b:vimwiki_prev_link execute ":e ".substitute(prev_word[0], '\s', '\\\0', 'g') call setpos('.', prev_word[1]) + else + " maybe we came here by jumping to a tag -> pop from the tag stack + silent! pop! endif endfunction " }}} From d28b61528619eac04612958419a8534c981f1e23 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Fri, 15 May 2015 11:18:40 +0200 Subject: [PATCH 31/38] two small things Ref #85 --- autoload/vimwiki/tags.vim | 2 +- doc/vimwiki.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index b5d788d..dbc35f3 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -234,7 +234,7 @@ function! s:write_tags_metadata(metadata) "{{{ endfor endfor call sort(tags) - call insert(tags, "!_TAG_FILE_SORTED\t1\t{anything}") + call insert(tags, "!_TAG_FILE_SORTED\t1\t") call writefile(tags, metadata_path) endfunction " }}} diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index 90aaa4a..fb4d1da 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -1632,7 +1632,7 @@ See |g:vimwiki_use_calendar| option to turn it off/on. ============================================================================== 12. Anchors *vimwiki-anchors* -Every header and every bold text is an anchor. To jump to it, use a wikilink +Every header, tag, and bold text is an anchor. To jump to it, use a wikilink of the form > [[file#anchor]] From b808dcfdc153ca9f8a11526311655ebcd07e3387 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Wed, 10 Jun 2015 22:00:07 +0200 Subject: [PATCH 32/38] Simplify a function call --- autoload/vimwiki/tags.vim | 20 ++++++++++---------- ftplugin/vimwiki.vim | 3 +-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index dbc35f3..aa2cb0f 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -32,7 +32,7 @@ function! vimwiki#tags#update_tags(full_rebuild, all_files) "{{{ " Collect tags in current file let tags = s:scan_tags(getline(1, '$'), page_name) " Load metadata file - let metadata = vimwiki#tags#load_tags_metadata() + let metadata = s:load_tags_metadata() " Drop old tags let metadata = s:remove_page_from_tags(metadata, page_name) " Merge in the new ones @@ -43,7 +43,7 @@ function! vimwiki#tags#update_tags(full_rebuild, all_files) "{{{ let files = vimwiki#base#find_files(g:vimwiki_current_idx, 0) let tags_file_last_modification = \ getftime(vimwiki#tags#metadata_file_path()) - let metadata = vimwiki#tags#load_tags_metadata() + let metadata = s:load_tags_metadata() for file in files if all_files || getftime(file) >= tags_file_last_modification let page_name = fnamemodify(file, ':t:r') @@ -141,9 +141,9 @@ function! vimwiki#tags#metadata_file_path() abort "{{{ return fnamemodify(VimwikiGet('path') . '/' . s:TAGS_METADATA_FILE_NAME, ':p') endfunction " }}} -" vimwiki#tags#load_tags_metadata +" s:load_tags_metadata " Loads tags metadata from file, returns a dictionary -function! vimwiki#tags#load_tags_metadata() abort "{{{ +function! s:load_tags_metadata() abort "{{{ let metadata_path = vimwiki#tags#metadata_file_path() if !filereadable(metadata_path) return {} @@ -239,10 +239,11 @@ function! s:write_tags_metadata(metadata) "{{{ endfunction " }}} " vimwiki#tags#get_tags -" Returns list of unique tags found in metadata -function! vimwiki#tags#get_tags(metadata) "{{{ +" Returns list of unique tags found in the .tags file +function! vimwiki#tags#get_tags() "{{{ + let metadata = s:load_tags_metadata() let tags = {} - for entries in values(a:metadata) + for entries in values(metadata) for entry in entries let tags[entry.tagname] = 1 endfor @@ -258,7 +259,7 @@ function! vimwiki#tags#generate_tags(...) abort "{{{ let need_all_tags = (a:0 == 0) let specific_tags = a:000 - let metadata = vimwiki#tags#load_tags_metadata() + let metadata = s:load_tags_metadata() call append(line('$'), [ \ '', @@ -295,8 +296,7 @@ endfunction " }}} function! vimwiki#tags#complete_tags(ArgLead, CmdLine, CursorPos) abort " {{{ " We can safely ignore args if we use -custom=complete option, Vim engine " will do the job of filtering. - let metadata = vimwiki#tags#load_tags_metadata() - let taglist = vimwiki#tags#get_tags(metadata) + let taglist = vimwiki#tags#get_tags() return join(taglist, "\n") endfunction " }}} diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 5cfd9e4..e606880 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -67,8 +67,7 @@ function! Complete_wikifiles(findstart, base) return [] elseif s:line_context == ':' " Tags completion - let metadata = vimwiki#tags#load_tags_metadata() - let tags = vimwiki#tags#get_tags(metadata) + let tags = vimwiki#tags#get_tags() if a:base != '' call filter(tags, \ "v:val[:" . (len(a:base)-1) . "] == '" . substitute(a:base, "'", "''", '') . "'" ) From 7aa273fd7c3e0cec792ddb6f45a232115c791de1 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Wed, 10 Jun 2015 22:04:21 +0200 Subject: [PATCH 33/38] A file tag must be at the very top of the file Ref #85 --- autoload/vimwiki/tags.vim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index aa2cb0f..1191673 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -119,11 +119,11 @@ function! s:scan_tags(lines, page_name) "{{{ let entry = {} let entry.tagname = tag let entry.lineno = line_nr - if line_nr <= (header_line_nr + PROXIMITY_LINES_NR) - let entry.link = page_name . '#' . current_complete_anchor - elseif header_line_nr < 0 - " Tag appeared before the first header + if line_nr <= PROXIMITY_LINES_NR && header_line_nr < 0 + " Tag appeared at the top of the file let entry.link = page_name + elseif line_nr <= (header_line_nr + PROXIMITY_LINES_NR) + let entry.link = page_name . '#' . current_complete_anchor else let entry.link = page_name . '#' . tag endif From 642a94ffaedc68f7ea63df16a3a946927805aa95 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Mon, 9 Nov 2015 15:45:56 +0100 Subject: [PATCH 34/38] :VimwikiGenerateTags now updates a potentially existing listing instead of adding it to the end. Ref #85 --- autoload/vimwiki/base.vim | 139 +++++++++++++++++++++++-------------- autoload/vimwiki/diary.vim | 54 ++------------ autoload/vimwiki/tags.vim | 17 +++-- 3 files changed, 104 insertions(+), 106 deletions(-) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index 9bb7e9f..1e59779 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -465,10 +465,9 @@ endfunction " }}} " vimwiki#base#generate_links function! vimwiki#base#generate_links() "{{{ + let lines = [] + let links = vimwiki#base#get_wikilinks(g:vimwiki_current_idx, 0) - - call append(line('$'), substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Links', '')) - call sort(links) let bullet = repeat(' ', vimwiki#lst#get_list_margin()). @@ -476,10 +475,15 @@ function! vimwiki#base#generate_links() "{{{ for link in links let abs_filepath = vimwiki#path#abs_path_of_link(link) if !s:is_diary_file(abs_filepath) - call append(line('$'), bullet. + call add(lines, bullet. \ substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', '\='."'".link."'", '')) endif endfor + + let links_rx = '\m^\s*'.vimwiki#u#escape(vimwiki#lst#default_symbol()).' ' + + call vimwiki#base#update_listing_in_buffer(lines, 'Generated Links', links_rx, + \ line('$')+1, 1) endfunction " }}} " vimwiki#base#goto @@ -1087,6 +1091,74 @@ function! vimwiki#base#nested_syntax(filetype, start, end, textSnipHl) abort "{{ endif endfunction "}}} +" creates or updates auto-generated listings in a wiki file, like TOC, diary +" links, tags list etc. +" - the listing consists of a level 1 header and a list of strings as content +" - a:content_regex is used to determine how long a potentially existing list is +" - a:default_lnum is the line number where the new listing should be placed if +" it's not already present +" - if a:create is true, it will be created if it doesn't exist, otherwise it +" will only be updated if it already exists +function! vimwiki#base#update_listing_in_buffer(strings, start_header, + \ content_regex, default_lnum, create) "{{{ + " apparently, Vim behaves strange when files change while in diff mode + if &diff || &readonly + return + endif + + " check if the listing is already there + let already_there = 0 + + let header_rx = '\m^\s*'. + \ substitute(g:vimwiki_rxH1_Template, '__Header__', a:start_header, '') + \ .'\s*$' + + let start_lnum = 1 + while start_lnum <= line('$') + if getline(start_lnum) =~# header_rx + let already_there = 1 + break + endif + let start_lnum += 1 + endwhile + + if !already_there && !a:create + return + endif + + let old_cursor_pos = getpos('.') + + if already_there + " delete the old listing + let whitespaces_in_first_line = matchstr(getline(start_lnum), '\m^\s*') + let end_lnum = start_lnum + 1 + while end_lnum <= line('$') && getline(end_lnum) =~# a:content_regex + let end_lnum += 1 + endwhile + silent exe start_lnum.','.string(end_lnum - 1).'delete _' + else + let start_lnum = a:default_lnum + let whitespaces_in_first_line = '' + endif + + " write new listing + let new_header = whitespaces_in_first_line + \ . substitute(g:vimwiki_rxH1_Template, + \ '__Header__', '\='."'".a:start_header."'", '') + call append(start_lnum - 1, new_header) + let start_lnum += 1 + for string in a:strings + call append(start_lnum - 1, string) + let start_lnum += 1 + endfor + " append an empty line if there is not one + if start_lnum <= line('$') && getline(start_lnum) !~# '\m^\s*$' + call append(start_lnum - 1, '') + endif + + call setpos('.', old_cursor_pos) +endfunction "}}} + " WIKI link following functions {{{ " vimwiki#base#find_next_link function! vimwiki#base#find_next_link() "{{{ @@ -1630,44 +1702,6 @@ endfunction " }}} " a:create == 1: creates or updates TOC in current file " a:create == 0: update if TOC exists function! vimwiki#base#table_of_contents(create) - " apparently, Vim behaves strange when files change while in diff mode - if &diff - return - endif - - " look for existing TOC - let toc_header = '^\s*'.substitute(g:vimwiki_rxH1_Template, '__Header__', - \ '\='."'".g:vimwiki_toc_header."'", '').'\s*$' - let toc_line = 0 - let lnum = 1 - while lnum <= &modelines + 2 && lnum <= line('$') - if getline(lnum) =~# toc_header - let toc_line = lnum - break - endif - let lnum += 1 - endwhile - - if !a:create && toc_line <= 0 - return - endif - - let old_cursor_pos = getpos('.') - let bullet = vimwiki#lst#default_symbol().' ' - let rx_bullet = vimwiki#u#escape(bullet) - let whitespaces = matchstr(getline(toc_line), '^\s*') - - " delete old TOC - if toc_line > 0 - let endoftoc = toc_line+1 - while endoftoc <= line('$') && getline(endoftoc) =~# '^\s*'.rx_bullet.g:vimwiki_rxWikiLink.'\s*$' - let endoftoc += 1 - endwhile - silent exe toc_line.','.string(endoftoc-1).'delete _' - else - let toc_line = 1 - endif - " collect new headers let headers = [] let headers_levels = [['', 0], ['', 0], ['', 0], ['', 0], ['', 0], ['', 0]] @@ -1678,6 +1712,9 @@ function! vimwiki#base#table_of_contents(create) endif let h_level = vimwiki#u#count_first_sym(line_content) let h_text = vimwiki#u#trim(matchstr(line_content, g:vimwiki_rxHeader)) + if h_text ==# g:vimwiki_toc_header " don't include the TOC's header itself + continue + endif let headers_levels[h_level-1] = [h_text, headers_levels[h_level-1][1]+1] for idx in range(h_level, 5) | let headers_levels[idx] = ['', 0] | endfor @@ -1700,25 +1737,23 @@ function! vimwiki#base#table_of_contents(create) call add(headers, [h_level, h_complete_id, h_text]) endfor - " write new TOC - call append(toc_line-1, whitespaces . substitute(g:vimwiki_rxH1_Template, - \ '__Header__', '\='."'".g:vimwiki_toc_header."'", '')) - + let lines = [] let startindent = repeat(' ', vimwiki#lst#get_list_margin()) let indentstring = repeat(' ', vimwiki#u#sw()) + let bullet = vimwiki#lst#default_symbol().' ' for [lvl, link, desc] in headers let esc_link = substitute(link, "'", "''", 'g') let esc_desc = substitute(desc, "'", "''", 'g') let link = substitute(g:vimwiki_WikiLinkTemplate2, '__LinkUrl__', \ '\='."'".'#'.esc_link."'", '') let link = substitute(link, '__LinkDescription__', '\='."'".esc_desc."'", '') - call append(toc_line, startindent.repeat(indentstring, lvl-1).bullet.link) - let toc_line += 1 + call add(lines, startindent.repeat(indentstring, lvl-1).bullet.link) endfor - if getline(toc_line+1) !~# '^\s*$' - call append(toc_line, '') - endif - call setpos('.', old_cursor_pos) + + let links_rx = '\m^\s*'.vimwiki#u#escape(vimwiki#lst#default_symbol()).' ' + + call vimwiki#base#update_listing_in_buffer(lines, g:vimwiki_toc_header, links_rx, + \ 1, a:create) endfunction "}}} diff --git a/autoload/vimwiki/diary.vim b/autoload/vimwiki/diary.vim index d131efe..540a766 100644 --- a/autoload/vimwiki/diary.vim +++ b/autoload/vimwiki/diary.vim @@ -121,36 +121,31 @@ fun! s:group_links(links) "{{{ return result endfun "}}} -fun! s:sort(lst) "{{{ +function! s:sort(lst) "{{{ if VimwikiGet("diary_sort") ==? 'desc' return reverse(sort(a:lst)) else return sort(a:lst) endif -endfun "}}} +endfunction "}}} -fun! s:format_diary(...) "{{{ +function! s:format_diary(...) "{{{ let result = [] - call add(result, substitute(g:vimwiki_rxH1_Template, '__Header__', VimwikiGet('diary_header'), '')) - if a:0 let g_files = s:group_links(s:get_diary_links(a:1)) else let g_files = s:group_links(s:get_diary_links()) endif - " for year in s:rev(sort(keys(g_files))) for year in s:sort(keys(g_files)) call add(result, '') call add(result, substitute(g:vimwiki_rxH2_Template, '__Header__', year , '')) - " for month in s:rev(sort(keys(g_files[year]))) for month in s:sort(keys(g_files[year])) call add(result, '') call add(result, substitute(g:vimwiki_rxH3_Template, '__Header__', s:get_month_name(month), '')) - " for [fl, cap] in s:rev(sort(items(g_files[year][month]))) for [fl, cap] in s:sort(items(g_files[year][month])) if empty(cap) let entry = substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', fl, '') @@ -165,46 +160,8 @@ fun! s:format_diary(...) "{{{ endfor endfor - call add(result, '') return result -endfun "}}} - -function! s:delete_diary_section() "{{{ - " remove diary section - let old_pos = getpos('.') - let ln_start = -1 - let ln_end = -1 - call cursor(1, 1) - if search(substitute(g:vimwiki_rxH1_Template, '__Header__', VimwikiGet('diary_header'), ''), 'Wc') - let ln_start = line('.') - if search(g:vimwiki_rxH1, 'W') - let ln_end = line('.') - 1 - else - let ln_end = line('$') - endif - endif - - if ln_start < 0 || ln_end < 0 - call setpos('.', old_pos) - return - endif - - if !&readonly - exe ln_start.",".ln_end."delete _" - endif - - call setpos('.', old_pos) -endfunction "}}} - -function! s:insert_diary_section() "{{{ - if !&readonly - let ln = line('.') - call append(ln, s:format_diary()) - if ln == 1 && getline(ln) == '' - 1,1delete - endif - endif endfunction "}}} " Diary index stuff }}} @@ -300,8 +257,9 @@ function! vimwiki#diary#generate_diary_section() "{{{ let current_file = vimwiki#path#path_norm(expand("%:p")) let diary_file = vimwiki#path#path_norm(s:diary_index()) if vimwiki#path#is_equal(current_file, diary_file) - call s:delete_diary_section() - call s:insert_diary_section() + let content_rx = '^\%(\s*\* \)\|\%(^\s*$\)\|\%('.g:vimwiki_rxHeader.'\)' + call vimwiki#base#update_listing_in_buffer(s:format_diary(), + \ VimwikiGet('diary_header'), content_rx, line('$')+1, 1) else echom "vimwiki: You can generate diary links only in a diary index page!" endif diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim index 1191673..4bd13a9 100644 --- a/autoload/vimwiki/tags.vim +++ b/autoload/vimwiki/tags.vim @@ -261,10 +261,6 @@ function! vimwiki#tags#generate_tags(...) abort "{{{ let metadata = s:load_tags_metadata() - call append(line('$'), [ - \ '', - \ substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Tags', '') ]) - " make a dictionary { tag_name: [tag_links, ...] } let tags_entries = {} for entries in values(metadata) @@ -277,19 +273,28 @@ function! vimwiki#tags#generate_tags(...) abort "{{{ endfor endfor + let lines = [] let bullet = repeat(' ', vimwiki#lst#get_list_margin()). \ vimwiki#lst#default_symbol().' ' for tagname in sort(keys(tags_entries)) if need_all_tags || index(specific_tags, tagname) != -1 - call append(line('$'), [ + call extend(lines, [ \ '', \ substitute(g:vimwiki_rxH2_Template, '__Header__', tagname, ''), \ '' ]) for taglink in tags_entries[tagname] - call append(line('$'), bullet . '[[' . taglink . ']]') + call add(lines, bullet . + \ substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', taglink, '')) endfor endif endfor + + let links_rx = '\m\%(^\s*$\)\|\%('.g:vimwiki_rxH2.'\)\|\%(^\s*' + \ .vimwiki#u#escape(vimwiki#lst#default_symbol()).' ' + \ .g:vimwiki_rxWikiLink.'$\)' + + call vimwiki#base#update_listing_in_buffer(lines, 'Generated Tags', links_rx, + \ line('$')+1, 1) endfunction " }}} " vimwiki#tags#complete_tags From 52634a6753d4745bbd63052e23508562782affd9 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Tue, 10 Nov 2015 14:37:25 +0100 Subject: [PATCH 35/38] add HTML processing for tags Ref #85 --- autoload/vimwiki/html.vim | 22 ++++++++++++++++++++++ autoload/vimwiki/style.css | 1 + 2 files changed, 23 insertions(+) diff --git a/autoload/vimwiki/html.vim b/autoload/vimwiki/html.vim index 60f77f9..43c9603 100644 --- a/autoload/vimwiki/html.vim +++ b/autoload/vimwiki/html.vim @@ -289,6 +289,27 @@ function! s:tag_strong(value, header_ids) "{{{ \ .id.'">'.text.'' endfunction "}}} +function! s:tag_tags(value, header_ids) "{{{ + let complete_id = '' + for level in range(6) + if a:header_ids[level][0] != '' + let complete_id .= a:header_ids[level][0].'-' + endif + endfor + if a:header_ids[5][0] == '' + let complete_id = complete_id[:-2] + endif + let complete_id = s:safe_html_anchor(complete_id) + + let result = [] + for tag in split(a:value, ':') + let id = s:safe_html_anchor(tag) + call add(result, ''.tag.'') + endfor + return join(result) +endfunction "}}} + function! s:tag_todo(value) "{{{ return ''.a:value.'' endfunction "}}} @@ -552,6 +573,7 @@ function! s:process_tags_typefaces(line, header_ids) "{{{ let line = s:make_tag(line, g:vimwiki_rxSubScript, 's:tag_sub') let line = s:make_tag(line, g:vimwiki_rxCode, 's:tag_code') let line = s:make_tag(line, g:vimwiki_rxEqIn, 's:tag_eqin') + let line = s:make_tag(line, g:vimwiki_rxTags, 's:tag_tags', a:header_ids) return line endfunction " }}} diff --git a/autoload/vimwiki/style.css b/autoload/vimwiki/style.css index 752867b..b9d1c02 100644 --- a/autoload/vimwiki/style.css +++ b/autoload/vimwiki/style.css @@ -24,6 +24,7 @@ del {text-decoration: line-through; color: #777777;} .justright {text-align: right;} .justcenter {text-align: center;} .center {margin-left: auto; margin-right: auto;} +.tag {background-color: #eeeeee; font-family: monospace; padding: 2px;} /* classes for items of todo lists */ .done0 { From 977f234f6deb45d1d5bfdfa1463f1696903f2945 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Wed, 11 Nov 2015 12:01:01 +0100 Subject: [PATCH 36/38] Allow tags in markdown and mediawiki syntax as well Ref #85 --- syntax/vimwiki_markdown.vim | 1 + syntax/vimwiki_media.vim | 1 + 2 files changed, 2 insertions(+) diff --git a/syntax/vimwiki_markdown.vim b/syntax/vimwiki_markdown.vim index 31667e2..c32c7d7 100644 --- a/syntax/vimwiki_markdown.vim +++ b/syntax/vimwiki_markdown.vim @@ -88,3 +88,4 @@ let g:vimwiki_rxMathStart = '\$\$' let g:vimwiki_rxMathEnd = '\$\$' let g:vimwiki_rxComment = '^\s*%%.*$' +let g:vimwiki_rxTags = '\%(^\|\s\)\@<=:\%([^:[:space:]]\+:\)\+\%(\s\|$\)\@=' diff --git a/syntax/vimwiki_media.vim b/syntax/vimwiki_media.vim index 37c24db..9c0498e 100644 --- a/syntax/vimwiki_media.vim +++ b/syntax/vimwiki_media.vim @@ -69,3 +69,4 @@ let g:vimwiki_rxMathStart = '{{\$' let g:vimwiki_rxMathEnd = '}}\$' let g:vimwiki_rxComment = '^\s*%%.*$' +let g:vimwiki_rxTags = '\%(^\|\s\)\@<=:\%([^:[:space:]]\+:\)\+\%(\s\|$\)\@=' From a043e7d9735812a97712735a3d957087265c606a Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Wed, 11 Nov 2015 12:56:28 +0100 Subject: [PATCH 37/38] Don't allow ' in tags Ref #85 --- syntax/omnipresent_syntax.vim | 4 ++-- syntax/vimwiki_default.vim | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/syntax/omnipresent_syntax.vim b/syntax/omnipresent_syntax.vim index f3b9c43..aaf3545 100644 --- a/syntax/omnipresent_syntax.vim +++ b/syntax/omnipresent_syntax.vim @@ -13,8 +13,8 @@ let g:vimwiki_default_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\ let g:vimwiki_default_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_default_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' let g:vimwiki_default_wikilink = '\[\[\zs[^\\\]|]\+\ze\%(|[^\\\]]\+\)\?\]\]' -let g:vimwiki_default_tag_search = '\(^\|\s\)\zs:\([^:[:space:]]\+:\)\+\ze\(\s\|$\)' -let g:vimwiki_default_tag_match = '\(^\|\s\):\([^:[:space:]]\+:\)*__Tag__:\([^:[:space:]]\+:\)*\(\s\|$\)' +let g:vimwiki_default_tag_search = '\(^\|\s\)\zs:\([^:''[:space:]]\+:\)\+\ze\(\s\|$\)' +let g:vimwiki_default_tag_match = '\(^\|\s\):\([^:''[:space:]]\+:\)*__Tag__:\([^:[:space:]]\+:\)*\(\s\|$\)' let g:vimwiki_markdown_header_search = '^\s*\(#\{1,6}\)\([^#].*\)$' let g:vimwiki_markdown_header_match = '^\s*\(#\{1,6}\)#\@!\s*__Header__\s*$' diff --git a/syntax/vimwiki_default.vim b/syntax/vimwiki_default.vim index 2a038da..6150f99 100644 --- a/syntax/vimwiki_default.vim +++ b/syntax/vimwiki_default.vim @@ -91,5 +91,5 @@ let g:vimwiki_rxMathStart = '{{\$' let g:vimwiki_rxMathEnd = '}}\$' let g:vimwiki_rxComment = '^\s*%%.*$' -let g:vimwiki_rxTags = '\%(^\|\s\)\@<=:\%([^:[:space:]]\+:\)\+\%(\s\|$\)\@=' +let g:vimwiki_rxTags = '\%(^\|\s\)\@<=:\%([^:''[:space:]]\+:\)\+\%(\s\|$\)\@=' " see also g:vimwiki_default_tag_search From e8164bb58a37698157012fd0b435daaeb5851fc4 Mon Sep 17 00:00:00 2001 From: EinfachToll Date: Wed, 11 Nov 2015 13:18:09 +0100 Subject: [PATCH 38/38] Add description of :VimwikiRebuildTags! to the help file Ref #85 --- doc/vimwiki.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index fb4d1da..7e93348 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -705,8 +705,10 @@ il A single list item. window. *:VimwikiRebuildTags* - Iterates over all files in a current wiki and rebuilds tags metadata (to - enable tags related commands). + Rebuilds the tags metadata file for the current wiki file. + Necessary for all tags related commands: |vimwiki-syntax-tags|. + + :VimwikiRebuildTags! does the same for all files in the current wiki. *:VimwikiSearchTags* Searches over the pages in current wiki and finds all locations of a given