From d5a6d097da1c67e07b3fb073f22217c7462f5088 Mon Sep 17 00:00:00 2001 From: Maxim Kim Date: Thu, 7 Jun 2012 00:00:00 +0000 Subject: [PATCH] Version 2.0.stu This release is partly incompatible with 1.2. You should delete previous version of vimwiki before install. = Summary = * Quick page-link creation. * Redesign of link syntaxes (!) * No more CamelCase links. Check the ways to convert them http://goo.gl/15ctX * No more [[link][desc]] links. * No more [http://link description] links. * No more plain image links. Use transclusions. * No more image links identified by extension. Use transclusions. * Interwiki links. * Link schemes. * Transclusions. * Normalize link command. * Improved diary organization and generation. * List manipulation. * Markdown support. * Mathjax support. * Improved handling of special characters and punctuation in filenames and urls. * Back links command: list links referring to the current page. * Highlighting nonexisted links are off by default. * Table syntax change. Row separator uses | instead of +. * Fold multilined list items. * Custom wiki to HTML converters. * Conceal long weblinks. * Option to disable table mappings. For detailed information see issues list on http://code.google.com/p/vimwiki/issues/list --- README | 39 +- autoload/vimwiki/base.vim | 1192 ++++++++++++++++------- autoload/vimwiki/diary.vim | 434 +++++---- autoload/vimwiki/html.vim | 686 +++++++------ autoload/vimwiki/lst.vim | 206 +++- autoload/vimwiki/markdown_base.vim | 111 +++ autoload/vimwiki/style.css | 64 +- autoload/vimwiki/tbl.vim | 302 ++++-- autoload/vimwiki/u.vim | 77 ++ doc/vimwiki.txt | 1458 ++++++++++++++-------------- ftplugin/vimwiki.vim | 137 ++- plugin/vimwiki.vim | 449 +++++---- syntax/vimwiki.vim | 485 +++++++-- syntax/vimwiki_default.vim | 36 +- syntax/vimwiki_markdown.vim | 89 ++ syntax/vimwiki_markdown_custom.vim | 367 +++++++ syntax/vimwiki_media.vim | 40 +- 17 files changed, 4161 insertions(+), 2011 deletions(-) create mode 100644 autoload/vimwiki/markdown_base.vim create mode 100644 autoload/vimwiki/u.vim create mode 100644 syntax/vimwiki_markdown.vim create mode 100644 syntax/vimwiki_markdown_custom.vim diff --git a/README b/README index d0556ae..08c8081 100644 --- a/README +++ b/README @@ -5,8 +5,6 @@ A Personal Wiki For Vim Plugin Screenshots are available on http://code.google.com/p/vimwiki/ There are also zipped vimwiki files there in case you do not like vimball archives. -Vimwiki quick reference card http://vimwiki.googlecode.com/hg/misc/Vimwiki1.1.1QR.pdf. - Prerequisites ============================================================================== @@ -24,31 +22,35 @@ Intro Vimwiki is a personal wiki for Vim -- a number of linked text files that have their own syntax highlighting. -With vimwiki you can - - organize notes and ideas - - manage todo-lists - - write documentation +With vimwiki you can: + - organize notes and ideas; + - manage todo-lists; + - write documentation. To do a quick start press ww (this is usually \ww) to go to your index -wiki file. By default it is located in: +wiki file. By default it is located in: ~/vimwiki/index.wiki Feed it with the following example: = My knowledge base = - * MyUrgentTasks -- things to be done _yesterday_!!! - * ProjectGutenberg -- good books are power. - * ScratchPad -- various temporary stuff. + * Tasks -- things to be done _yesterday_!!! + * Project Gutenberg -- good books are power. + * Scratchpad -- various temporary stuff. +Place your cursor on 'Tasks' and press Enter to create a link. Once pressed, +'Tasks' will become '[[Tasks]]' -- a vimwiki link. Press Enter again to +open it. Edit the file, save it, and then press Backspace to jump back to your +index. -Notice that !ProjectGutenberg, !MyUrgentTasks and !ScratchPad curly underlined. -These are links in CamelCase form that do not exists yet. (CamelCase -form -- capitalized word connected with other capitalized words) +A vimwiki link can be constructed from more than one word. Just visually +select the words to be linked and press Enter. Try it with 'Project +Gutenberg'. The result should look something like: -Place cursor on ProjectGutenberg and press . Now you are in -ProjectGutenberg. Edit and save it, then press Backspace to return to parent -wiki page. You should see the difference now -- ProjectGutenberg is -highlighted as a link. += My knowledge base = + * [[Tasks]] -- things to be done _yesterday_!!! + * [[Project Gutenberg]] -- good books are power. + * Scratchpad -- various temporary stuff. For the various options see :h vimwiki-options. @@ -60,9 +62,8 @@ see :h vimwiki-syntax *bold* -- bold _italic_ -- italic -WikiWord -- link to WikiWord + [[wiki link]] -- link with spaces -[[wiki link][description]] -- link with description [[wiki link|description]] -- link with description Lists: diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index b56eff6..5e39b6f 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -8,143 +8,492 @@ if exists("g:loaded_vimwiki_auto") || &cp endif let g:loaded_vimwiki_auto = 1 -if has("win32") - let s:os_sep = '\' -else - let s:os_sep = '/' -endif - -let s:badsymbols = '['.g:vimwiki_badsyms.g:vimwiki_stripsym.'<>|?*:"]' +" ------------------------------------------------------------------------- +" Load syntax-specific Wiki functionality +execute 'runtime! autoload/vimwiki/'.VimwikiGet('syntax').'_base.vim' +" ------------------------------------------------------------------------- " MISC helper functions {{{ -function! vimwiki#base#chomp_slash(str) "{{{ - return substitute(a:str, '[/\\]\+$', '', '') +function! s:normalize_path(path) "{{{ + let g:VimwikiLog.normalize_path += 1 "XXX + " resolve doesn't work quite right with symlinks ended with / or \ + return resolve(expand(substitute(a:path, '[/\\]\+$', '', ''))).'/' endfunction "}}} -function! vimwiki#base#path_norm(path) "{{{ - return substitute(a:path, '\', '/', 'g') +function! s:path_html(idx) "{{{ + let path_html = VimwikiGet('path_html', a:idx) + if !empty(path_html) + return path_html + else + let g:VimwikiLog.path_html += 1 "XXX + let path = VimwikiGet('path', a:idx) + return substitute(path, '[/\\]\+$', '', '').'_html/' + endif endfunction "}}} -function! vimwiki#base#mkdir(path) "{{{ +" }}} + +function! vimwiki#base#apply_wiki_options(options) " {{{ Update the current + " wiki using the options dictionary + for kk in keys(a:options) + let g:vimwiki_list[g:vimwiki_current_idx][kk] = a:options[kk] + endfor + call vimwiki#base#validate_wiki_options(g:vimwiki_current_idx) + call vimwiki#base#setup_buffer_state(g:vimwiki_current_idx) +endfunction " }}} + +function! vimwiki#base#read_wiki_options(check) " {{{ Attempt to read wiki + " options from the current page's directory, or its ancesters. If a file + " named vimwiki.vimrc is found, which declares a wiki-options dictionary + " named g:local_wiki, a message alerts the user that an update has been + " found and may be applied. If the argument check=1, the user is queried + " before applying the update to the current wiki's option. + + " Save global vimwiki options ... after all, the global list is often + " initialized for the first time in vimrc files, and we don't want to + " overwrite !! (not to mention all the other globals ...) + let l:vimwiki_list = deepcopy(g:vimwiki_list, 1) + " + if a:check + call vimwiki#base#print_wiki_state() + echo " \n" + endif + " + let g:local_wiki = {} + let done = 0 + " ... start the wild-goose chase! + for invsubdir in ['.', '..', '../..', '../../..'] + " other names are possible, but most vimrc files will cause grief! + for nm in ['vimwiki.vimrc'] + " TODO: use an alternate strategy, instead of source, to read options + if done | + continue + endif + " + let local_wiki_options_filename = expand('%:p:h').'/'.invsubdir.'/'.nm + if !filereadable(local_wiki_options_filename) + continue + endif + " + echo "\nFound file : ".local_wiki_options_filename + let query = "Vimwiki: Check for options in this file [Y]es/[n]o? " + if a:check && (tolower(input(query)) !~ "y") + continue + endif + " + try + execute 'source '.local_wiki_options_filename + catch + endtry + if empty(g:local_wiki) + continue + endif + " + if a:check + echo "\n\nFound wiki options\n g:local_wiki = ".string(g:local_wiki) + let query = "Vimwiki: Apply these options [Y]es/[n]o? " + if tolower(input(query)) !~ "y" + let g:local_wiki = {} + continue + endif + endif + " + " restore global list + " - this prevents corruption by g:vimwiki_list in options_file + let g:vimwiki_list = deepcopy(l:vimwiki_list, 1) + " + call vimwiki#base#apply_wiki_options(g:local_wiki) + let done = 1 + endfor + endfor + if !done + " + " restore global list, if no local options were found + " - this prevents corruption by g:vimwiki_list in options_file + let g:vimwiki_list = deepcopy(l:vimwiki_list, 1) + " + endif + if a:check + echo " \n " + if done + call vimwiki#base#print_wiki_state() + else + echo "Vimwiki: No options were applied." + endif + endif +endfunction " }}} + +function! vimwiki#base#validate_wiki_options(idx) " {{{ Validate wiki options + " Only call this function *before* opening a wiki page. + " + " XXX: It's too early to update global / buffer variables, because they are + " still needed in their existing state for s:setup_buffer_leave() + "" let g:vimwiki_current_idx = a:idx + + " update normalized path & path_html + call VimwikiSet('path', s:normalize_path(VimwikiGet('path', a:idx)), a:idx) + call VimwikiSet('path_html', s:normalize_path(s:path_html(a:idx)), a:idx) + call VimwikiSet('template_path', + \ s:normalize_path(VimwikiGet('template_path', a:idx)), a:idx) + call VimwikiSet('diary_rel_path', + \ s:normalize_path(VimwikiGet('diary_rel_path', a:idx)), a:idx) + + " XXX: It's too early to update global / buffer variables, because they are + " still needed in their existing state for s:setup_buffer_leave() + "" call vimwiki#base#cache_buffer_state() +endfunction " }}} + +function! vimwiki#base#setup_buffer_state(idx) " {{{ Init page-specific variables + " Only call this function *after* opening a wiki page. + if a:idx < 0 + return + endif + + let g:vimwiki_current_idx = a:idx + + " The following state depends on the current active wiki page + let subdir = vimwiki#base#current_subdir(a:idx) + call VimwikiSet('subdir', subdir, a:idx) + call VimwikiSet('invsubdir', vimwiki#base#invsubdir(subdir), a:idx) + call VimwikiSet('url', vimwiki#html#get_wikifile_url(expand('%:p')), a:idx) + + " update cache + call vimwiki#base#cache_buffer_state() +endfunction " }}} + +function! vimwiki#base#cache_buffer_state() "{{{ + if !exists('g:vimwiki_current_idx') && g:vimwiki_debug + echo "[Vimwiki Internal Error]: Missing global state variable: 'g:vimwiki_current_idx'" + endif + let b:vimwiki_idx = g:vimwiki_current_idx +endfunction "}}} + +function! vimwiki#base#recall_buffer_state() "{{{ + if !exists('b:vimwiki_idx') + if g:vimwiki_debug + echo "[Vimwiki Internal Error]: Missing buffer state variable: 'b:vimwiki_idx'" + endif + return 0 + else + let g:vimwiki_current_idx = b:vimwiki_idx + return 1 + endif +endfunction " }}} + +function! vimwiki#base#print_wiki_state() "{{{ print wiki options + " and buffer state variables + let g_width = 18 + let b_width = 18 + echo "- Wiki Options (idx=".g:vimwiki_current_idx.") -" + for kk in VimwikiGetOptionNames() + echo " '".kk."': ".repeat(' ', g_width-len(kk)).string(VimwikiGet(kk)) + endfor + if !exists('b:vimwiki_list') + return + endif + echo "- Cached Variables -" + for kk in keys(b:vimwiki_list) + echo " '".kk."': ".repeat(' ', b_width-len(kk)).string(b:vimwiki_list[kk]) + endfor +endfunction "}}} + +" If the optional argument 'confirm' == 1 is provided, +" vimwiki#base#mkdir will ask before creating a directory +function! vimwiki#base#mkdir(path, ...) "{{{ let path = expand(a:path) if !isdirectory(path) && exists("*mkdir") - let path = vimwiki#base#chomp_slash(path) - if s:is_windows() && !empty(g:vimwiki_w32_dir_enc) + let path = vimwiki#u#chomp_slash(path) + if vimwiki#u#is_windows() && !empty(g:vimwiki_w32_dir_enc) let path = iconv(path, &enc, g:vimwiki_w32_dir_enc) endif + if a:0 && a:1 && tolower(input("Vimwiki: Make new directory: ".path."\n [Y]es/[n]o? ")) !~ "y" + return 0 + endif call mkdir(path, "p") endif + return 1 endfunction " }}} -function! vimwiki#base#safe_link(link) "{{{ - " handling Windows absolute paths - if a:link =~ '^[[:alpha:]]:[/\\].*' - let link_start = a:link[0 : 2] - let link = a:link[3 : ] - else - let link_start = '' - let link = a:link - endif - let link = substitute(link, s:badsymbols, g:vimwiki_stripsym, 'g') - return link_start.link +function! vimwiki#base#file_pattern(files) "{{{ Get search regex from glob() + " string. Aim to support *all* special characters, forcing the user to choose + " names that are compatible with any external restrictions that they + " encounter (e.g. filesystem, wiki conventions, other syntaxes, ...). + " See: http://code.google.com/p/vimwiki/issues/detail?id=316 + " Change / to [/\\] to allow "Windows paths" + " TODO: boundary cases ... + " e.g. "File$", "^File", "Fi]le", "Fi[le", "Fi\le", "Fi/le" + " XXX: (remove my comment if agreed) Maxim: with \V (very nomagic) boundary + " cases works for 1 and 2. + " 3, 4, 5 is not highlighted as links thus wouldn't be highlighted. + " 6 is a regular vimwiki link with subdirectory... + " + let pattern = vimwiki#base#branched_pattern(a:files,"\n") + return '\V'.pattern.'\m' endfunction "}}} -function! vimwiki#base#unsafe_link(string) "{{{ - if len(g:vimwiki_stripsym) > 0 - return substitute(a:string, g:vimwiki_stripsym, s:badsymbols, 'g') - else - return a:string - endif +function! vimwiki#base#branched_pattern(string,separator) "{{{ get search regex +" from a string-list; separators assumed at start and end as well + let pattern = substitute(a:string, a:separator, '\\|','g') + let pattern = substitute(pattern, '\%^\\|', '\\%(','') + let pattern = substitute(pattern,'\\|\%$', '\\)','') + return pattern endfunction "}}} +"FIXME TODO slow and faulty function! vimwiki#base#subdir(path, filename)"{{{ - let path = expand(a:path) - let filename = expand(a:filename) + let g:VimwikiLog.subdir += 1 "XXX + let path = a:path + " ensure that we are not fooled by a symbolic link + "FIXME if we are not "fooled", we end up in a completely different wiki? + let filename = resolve(a:filename) let idx = 0 + "FIXME this can terminate in the middle of a path component! while path[idx] ==? filename[idx] let idx = idx + 1 endwhile let p = split(strpart(filename, idx), '[/\\]') - let res = join(p[:-2], s:os_sep) + let res = join(p[:-2], '/') if len(res) > 0 - let res = res.s:os_sep + let res = res.'/' endif return res +endfunction "}}} + +function! vimwiki#base#current_subdir(idx)"{{{ + return vimwiki#base#subdir(VimwikiGet('path', a:idx), expand('%:p')) endfunction"}}} -function! vimwiki#base#current_subdir()"{{{ - return vimwiki#base#subdir(VimwikiGet('path'), expand('%:p')) -endfunction"}}} +function! vimwiki#base#invsubdir(subdir) " {{{ + return substitute(a:subdir, '[^/\.]\+/', '../', 'g') +endfunction " }}} + +function! vimwiki#base#resolve_scheme(lnk, as_html) " {{{ Resolve scheme + " - Only return non-negative index when valid wiki link found + " + " if link is schemeless add wikiN: scheme + let lnk = a:lnk + let is_schemeless = lnk !~ g:vimwiki_rxSchemeUrl + let lnk = (is_schemeless ? 'wiki'.g:vimwiki_current_idx.':'.lnk : lnk) + + " Get scheme + let scheme = matchstr(lnk, g:vimwiki_rxSchemeUrlMatchScheme) + " Get link (without scheme) + let lnk = matchstr(lnk, g:vimwiki_rxSchemeUrlMatchUrl) + let path = '' + let subdir = '' + let ext = '' + let idx = -1 + + " do nothing if scheme is unknown to vimwiki + if !(scheme =~ 'wiki.*' || scheme =~ 'diary' || scheme =~ 'local' + \ || scheme =~ 'file') + return [idx, scheme, path, subdir, lnk, ext, scheme.':'.lnk] + endif + + " scheme behaviors + if scheme =~ 'wiki\d\+' + let idx = eval(matchstr(scheme, '\D\+\zs\d\+\ze')) + if idx < 0 || idx >= len(g:vimwiki_list) + echom 'Vimwiki Error: Numbered scheme refers to a non-existent wiki!' + return [idx,'','','','','',''] + else + if idx != g:vimwiki_current_idx + call vimwiki#base#validate_wiki_options(idx) + endif + endif + + if a:as_html + if idx == g:vimwiki_current_idx + let path = VimwikiGet('path_html') + else + let path = VimwikiGet('path_html', idx) + endif + else + if idx == g:vimwiki_current_idx + let path = VimwikiGet('path') + else + let path = VimwikiGet('path', idx) + endif + endif + + " For Issue 310. Otherwise current subdir is used for another wiki. + if idx == g:vimwiki_current_idx + let subdir = VimwikiGet('subdir') + else + let subdir = "" + endif + + if a:as_html + let ext = '.html' + else + if idx == g:vimwiki_current_idx + let ext = VimwikiGet('ext') + else + let ext = VimwikiGet('ext', idx) + endif + endif + + " default link for directories + if vimwiki#u#is_link_to_dir(lnk) + let ext = (g:vimwiki_dir_link != '' ? g:vimwiki_dir_link. ext : '') + endif + elseif scheme =~ 'diary' + if a:as_html + " use cached value (save time when converting diary index!) + let path = VimwikiGet('invsubdir') + let ext = '.html' + else + let path = VimwikiGet('path') + let ext = VimwikiGet('ext') + endif + let subdir = VimwikiGet('diary_rel_path') + elseif scheme =~ 'local' + " revisiting the 'lcd'-bug ... + let path = VimwikiGet('path') + let subdir = VimwikiGet('subdir') + if a:as_html + " prepend browser-specific file: scheme + let path = 'file://'.fnamemodify(path, ":p") + endif + elseif scheme =~ 'file' + " RM repeated leading "/"'s within a link + let lnk = substitute(lnk, '^/*', '/', '') + " convert "/~..." into "~..." for fnamemodify + let lnk = substitute(lnk, '^/\~', '\~', '') + " convert /C: to C: (or fnamemodify(...":p:h") interpret it as C:\C: + if vimwiki#u#is_windows() + let lnk = substitute(lnk, '^/\ze[[:alpha:]]:', '', '') + endif + if a:as_html + " prepend browser-specific file: scheme + let path = 'file://'.fnamemodify(lnk, ":p:h").'/' + else + let path = fnamemodify(lnk, ":p:h").'/' + endif + let lnk = fnamemodify(lnk, ":p:t") + let subdir = '' + endif + + + " construct url from parts + if is_schemeless && a:as_html + let scheme = '' + let url = lnk.ext + else + let url = path.subdir.lnk.ext + endif + + " result + return [idx, scheme, path, subdir, lnk, ext, url] +endfunction "}}} + +function! vimwiki#base#system_open_link(url) "{{{ + " handlers + function! s:win32_handler(url) + "http://vim.wikia.com/wiki/Opening_current_Vim_file_in_your_Windows_browser + execute 'silent ! start "Title" /B ' . shellescape(a:url, 1) + endfunction + function! s:macunix_handler(url) + execute '!open ' . shellescape(a:url, 1) + endfunction + function! s:linux_handler(url) + execute 'silent !xdg-open ' . shellescape(a:url, 1) + endfunction + let success = 0 + try + if vimwiki#u#is_windows() + call s:win32_handler(a:url) + return + elseif has("macunix") + call s:macunix_handler(a:url) + return + else + call s:linux_handler(a:url) + return + endif + endtry + echomsg 'Default Vimwiki link handler was unable to open the HTML file!' +endfunction "}}} function! vimwiki#base#open_link(cmd, link, ...) "{{{ - if vimwiki#base#is_non_wiki_link(a:link) - if s:is_path_absolute(a:link) - call vimwiki#base#edit_file(a:cmd, a:link) - else - call vimwiki#base#edit_file(a:cmd, VimwikiGet('path').a:link) + let [idx, scheme, path, subdir, lnk, ext, url] = + \ vimwiki#base#resolve_scheme(a:link, 0) + + if url == '' + if g:vimwiki_debug + echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url endif - else + echom 'Vimwiki Error: Unable to resolve link!' + return + endif + + let update_prev_link = ( + \ scheme == '' || + \ scheme =~ 'wiki' || + \ scheme =~ 'diary' ? 1 : 0) + + let use_system_open = ( + \ scheme == '' || + \ scheme =~ 'wiki' || + \ scheme =~ 'diary' ? 0 : 1) + + let vimwiki_prev_link = [] + " update previous link for wiki pages + if update_prev_link if a:0 let vimwiki_prev_link = [a:1, []] elseif &ft == 'vimwiki' let vimwiki_prev_link = [expand('%:p'), getpos('.')] endif + endif - if vimwiki#base#is_link_to_dir(a:link) - if g:vimwiki_dir_link == '' - call vimwiki#base#edit_file(a:cmd, VimwikiGet('path').a:link) - else - call vimwiki#base#edit_file(a:cmd, - \ VimwikiGet('path').a:link. - \ g:vimwiki_dir_link. - \ VimwikiGet('ext')) - endif - else - call vimwiki#base#edit_file(a:cmd, VimwikiGet('path').a:link.VimwikiGet('ext')) - endif + " open/edit + if g:vimwiki_debug + echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url + endif - if exists('vimwiki_prev_link') - let b:vimwiki_prev_link = vimwiki_prev_link + if use_system_open + call vimwiki#base#system_open_link(url) + else + call vimwiki#base#edit_file(a:cmd, url, + \ vimwiki_prev_link, update_prev_link) + if idx != g:vimwiki_current_idx + " this call to setup_buffer_state may not be necessary + call vimwiki#base#setup_buffer_state(idx) endif endif endfunction " }}} -function! vimwiki#base#select(wnum)"{{{ - if a:wnum < 1 || a:wnum > len(g:vimwiki_list) - return - endif - if &ft == 'vimwiki' - let b:vimwiki_idx = g:vimwiki_current_idx - endif - let g:vimwiki_current_idx = a:wnum - 1 -endfunction -" }}} +function! vimwiki#base#generate_links() "{{{only get links from the current dir + " change to the directory of the current file + let orig_pwd = getcwd() + lcd! %:h + " all path are relative to the current file's location + let globlinks = glob('*'.VimwikiGet('ext'),1)."\n" + " remove extensions + let globlinks = substitute(globlinks, '\'.VimwikiGet('ext').'\ze\n', '', 'g') + " restore the original working directory + exe 'lcd! '.orig_pwd -function! vimwiki#base#generate_links()"{{{ - let links = s:get_links('*'.VimwikiGet('ext')) - - " We don't want link to itself. - let cur_link = expand('%:t:r') - call filter(links, 'v:val != cur_link') - - if len(links) - call append(line('$'), '= Generated Links =') - endif + " We don't want link to itself. XXX Why ??? + " let cur_link = expand('%:t:r') + " call filter(links, 'v:val != cur_link') + let links = split(globlinks,"\n") + call append(line('$'), substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Links', '')) call sort(links) + let bullet = repeat(' ', vimwiki#lst#get_list_margin()). + \ vimwiki#lst#default_symbol().' ' for link in links - if s:is_wiki_word(link) - call append(line('$'), '- '.link) - else - call append(line('$'), '- [['.link.']]') - endif + call append(line('$'), bullet. + \ substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', '\='."'".link."'", '')) endfor endfunction " }}} @@ -155,17 +504,30 @@ function! vimwiki#base#goto(key) "{{{ \ VimwikiGet('ext')) endfunction "}}} -function! s:is_windows() "{{{ - return has("win32") || has("win64") || has("win95") || has("win16") +function! vimwiki#base#backlinks() "{{{ + execute 'lvimgrep "\%(^\|[[:blank:][:punct:]]\)'. + \ expand("%:t:r"). + \ '\([[:blank:][:punct:]]\|$\)" '. + \ escape(VimwikiGet('path').'**/*'.VimwikiGet('ext'), ' ') endfunction "}}} -function! s:is_path_absolute(path) "{{{ - return a:path =~ '^/.*' || a:path =~ '^[[:alpha:]]:[/\\].*' -endfunction "}}} +function! vimwiki#base#get_links(pat) "{{{ return string-list for files + " in the current wiki matching the pattern "pat" + " search all wiki files (or directories) in wiki 'path' and its subdirs. -function! s:get_links(pat) "{{{ - " search all wiki files in 'path' and its subdirs. - let subdir = vimwiki#base#current_subdir() + let time1 = reltime() " start the clock XXX + + " XXX: + " if maxhi = 1 and ww before loading any vimwiki file + " cached 'subdir' is not set up + try + let subdir = VimwikiGet('subdir') + " FIXED: was previously converting './' to '../' + let invsubdir = VimwikiGet('invsubdir') + catch + let subdir = '' + let invsubdir = '' + endtry " if current wiki is temporary -- was added by an arbitrary wiki file then do " not search wiki files in subdirectories. Or it would hang the system if @@ -175,68 +537,92 @@ function! s:get_links(pat) "{{{ else let search_dirs = '**/' endif - let globlinks = glob(VimwikiGet('path').subdir.search_dirs.a:pat) + " let globlinks = "\n".glob(VimwikiGet('path').search_dirs.a:pat,1)."\n" - " remove extensions (and backup extensions too: .wiki~) - let globlinks = substitute(globlinks, '\'.VimwikiGet('ext').'\~\?', "", "g") - let links = split(globlinks, '\n') + "save pwd, do lcd %:h, restore old pwd; getcwd() + " change to the directory of the current file + let orig_pwd = getcwd() - " remove paths - let rem_path = escape(expand(VimwikiGet('path')).subdir, '\') - call map(links, 'substitute(v:val, rem_path, "", "g")') + " calling from other than vimwiki file + let path_base = vimwiki#u#path_norm(vimwiki#u#chomp_slash(VimwikiGet('path'))) + let path_file = vimwiki#u#path_norm(vimwiki#u#chomp_slash(expand('%:p:h'))) - " Remove trailing slashes. - call map(links, 'substitute(v:val, "[/\\\\]*$", "", "g")') + if vimwiki#u#path_common_pfx(path_file, path_base) != path_base + exe 'lcd! '.path_base + else + lcd! %:p:h + endif - return links + " all path are relative to the current file's location + let globlinks = "\n".glob(invsubdir.search_dirs.a:pat,1)."\n" + " remove extensions + let globlinks = substitute(globlinks,'\'.VimwikiGet('ext').'\ze\n', '', 'g') + " standardize path separators on Windows + let globlinks = substitute(globlinks,'\\', '/', 'g') + + " shortening those paths ../../dir1/dir2/ that can be shortened + " first for the current directory, then for parent etc. + let sp_rx = '\n\zs' . invsubdir . subdir . '\ze' + for i in range(len(invsubdir)/3) "XXX multibyte? + let globlinks = substitute(globlinks, sp_rx, '', 'g') + let sp_rx = substitute(sp_rx,'\\zs../','../\\zs','') + let sp_rx = substitute(sp_rx,'[^/]\+/\\ze','\\ze','') + endfor + " for directories: add ./ (instead of now empty) and invsubdir (if distinct) + if a:pat == '*/' + let globlinks = substitute(globlinks, "\n\n", "\n./\n",'') + if invsubdir != '' + let globlinks .= invsubdir."\n" + else + let globlinks .= "./\n" + endif + endif + + " restore the original working directory + exe 'lcd! '.orig_pwd + + let time2 = vimwiki#u#time(time1) + call VimwikiLog_extend('timing',['base:afterglob('.len(split(globlinks, '\n')).')',time2]) + return globlinks endfunction "}}} -" Builtin cursor doesn't work right with unicode characters. -function! s:cursor(lnum, cnum) "{{{ - exe a:lnum - exe 'normal! 0'.a:cnum.'|' -endfunction "}}} - -function! s:filename(link) "{{{ - let result = vimwiki#base#safe_link(a:link) - if a:link =~ '|' - let result = vimwiki#base#safe_link(split(a:link, '|')[0]) - elseif a:link =~ '][' - let result = vimwiki#base#safe_link(split(a:link, '][')[0]) - endif - return result -endfunction -" }}} - -function! s:is_wiki_word(str) "{{{ - if a:str =~ g:vimwiki_rxWikiWord && a:str !~ '[[:space:]\\/]' - return 1 - endif - return 0 -endfunction -" }}} - -function! vimwiki#base#edit_file(command, filename) "{{{ - let fname = escape(a:filename, '% ') - call vimwiki#base#mkdir(fnamemodify(a:filename, ":p:h")) - try +function! vimwiki#base#edit_file(command, filename, ...) "{{{ + " XXX: Should we allow * in filenames!? + " Maxim: It is allowed, escaping here is for vim to be able to open files + " which have that symbols. + " Try to remove * from escaping and open&save : + " [[testBLAfile]]... + " then + " [[test*file]]... + " you'll have E77: Too many file names + let fname = escape(a:filename, '% *|') + let dir = fnamemodify(a:filename, ":p:h") + if vimwiki#base#mkdir(dir, 1) execute a:command.' '.fname - catch /E37/ " catch 'No write since last change' error - execute ':split '.fname - catch /E325/ " catch 'ATTENTION' error (:h E325) - endtry + else + echom ' ' + echom 'Vimwiki: Unable to edit file in non-existent directory: '.dir + endif + + " save previous link + " a:1 -- previous vimwiki link to save + " a:2 -- should we update previous link + if a:0 && a:2 && len(a:1) > 0 + let b:vimwiki_prev_link = a:1 + endif endfunction " }}} -function! s:search_word(wikiRx, cmd) "{{{ +function! vimwiki#base#search_word(wikiRx, cmd) "{{{ let match_line = search(a:wikiRx, 's'.a:cmd) if match_line == 0 - echomsg "vimwiki: Wiki link not found." + echomsg 'vimwiki: Wiki link not found.' endif endfunction " }}} -function! s:get_word_at_cursor(wikiRX) "{{{ +" Returns part of the line that matches wikiRX at cursor +function! vimwiki#base#matchstr_at_cursor(wikiRX) "{{{ let col = col('.') - 1 let line = getline('.') let ebeg = -1 @@ -258,44 +644,27 @@ function! s:get_word_at_cursor(wikiRX) "{{{ endif endf "}}} -function! s:strip_word(word) "{{{ - let result = a:word - if strpart(a:word, 0, 2) == "[[" - " get rid of [[ and ]] - let w = strpart(a:word, 2, strlen(a:word)-4) - - if w =~ '|' - " we want "link" from [[link|link desc]] - let w = split(w, "|")[0] - elseif w =~ '][' - " we want "link" from [[link][link desc]] - let w = split(w, "][")[0] +function! vimwiki#base#replacestr_at_cursor(wikiRX, sub) "{{{ + let col = col('.') - 1 + let line = getline('.') + let ebeg = -1 + let cont = match(line, a:wikiRX, 0) + while (ebeg >= 0 || (0 <= cont) && (cont <= col)) + let contn = matchend(line, a:wikiRX, cont) + if (cont <= col) && (col < contn) + let ebeg = match(line, a:wikiRX, cont) + let elen = contn - ebeg + break + else + let cont = match(line, a:wikiRX, contn) endif - - let result = vimwiki#base#safe_link(w) + endwh + if ebeg >= 0 + " TODO: There might be problems with Unicode chars... + let newline = strpart(line, 0, ebeg).a:sub.strpart(line, ebeg+elen) + call setline(line('.'), newline) endif - return result -endfunction -" }}} - -function! vimwiki#base#is_non_wiki_link(lnk) "{{{ - let exts = '.\+\.\%('. - \ join(split(g:vimwiki_file_exts, '\s*,\s*'), '\|'). - \ '\)$' - if a:lnk =~ exts - return 1 - endif - return 0 -endfunction "}}} - -function! vimwiki#base#is_link_to_dir(link) "{{{ - " Check if link is to a directory. - " It should be ended with \ or /. - if a:link =~ '.\+[/\\]$' - return 1 - endif - return 0 -endfunction " }}} +endf "}}} function! s:print_wiki_list() "{{{ let idx = 0 @@ -322,6 +691,7 @@ function! s:update_wiki_link(fname, old, new) " {{{ if !has_updates && match(line, a:old) != -1 let has_updates = 1 endif + " XXX: any other characters to escape!? call add(dest, substitute(line, a:old, escape(a:new, "&"), "g")) endfor " add exception handling... @@ -339,16 +709,10 @@ function! s:update_wiki_links_dir(dir, old_fname, new_fname) " {{{ let old_fname_r = old_fname let new_fname_r = new_fname - if !s:is_wiki_word(new_fname) && s:is_wiki_word(old_fname) - let new_fname_r = '[['.new_fname.']]' - endif - - if !s:is_wiki_word(old_fname) - let old_fname_r = '\[\[\zs'.vimwiki#base#unsafe_link(old_fname). - \ '\ze\%(|.*\)\?\%(\]\[.*\)\?\]\]' - else - let old_fname_r = '!\@' - endif + let old_fname_r = vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate1, + \ '\zs'.old_fname.'\ze', '.*', ''). + \ '\|'. vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate2, + \ '\zs'.old_fname.'\ze', '.*', '') let files = split(glob(VimwikiGet('path').a:dir.'*'.VimwikiGet('ext')), '\n') for fname in files @@ -419,128 +783,6 @@ function! s:open_wiki_buffer(item) "{{{ endif endfunction " }}} -" }}} - -" SYNTAX highlight {{{ -function! vimwiki#base#highlight_links() "{{{ - try - syntax clear VimwikiNoExistsLink - syntax clear VimwikiNoExistsLinkT - syntax clear VimwikiLink - syntax clear VimwikiLinkT - catch - endtry - - "" use max highlighting - could be quite slow if there are too many wikifiles - if VimwikiGet('maxhi') - " Every WikiWord is nonexistent - if g:vimwiki_camel_case - execute 'syntax match VimwikiNoExistsLink /'.g:vimwiki_rxWikiWord.'/ display' - execute 'syntax match VimwikiNoExistsLinkT /'.g:vimwiki_rxWikiWord.'/ display contained' - endif - execute 'syntax match VimwikiNoExistsLink /'.g:vimwiki_rxWikiLink1.'/ display contains=VimwikiNoLinkChar' - execute 'syntax match VimwikiNoExistsLink /'.g:vimwiki_rxWikiLink2.'/ display contains=VimwikiNoLinkChar' - - execute 'syntax match VimwikiNoExistsLinkT /'.g:vimwiki_rxWikiLink1.'/ display contained' - execute 'syntax match VimwikiNoExistsLinkT /'.g:vimwiki_rxWikiLink2.'/ display contained' - - " till we find them in vimwiki's path - call s:highlight_existed_links() - else - " A WikiWord (unqualifiedWikiName) - execute 'syntax match VimwikiLink /\<'.g:vimwiki_rxWikiWord.'\>/' - " A [[bracketed wiki word]] - execute 'syntax match VimwikiLink /'.g:vimwiki_rxWikiLink1.'/ display contains=VimwikiLinkChar' - execute 'syntax match VimwikiLink /'.g:vimwiki_rxWikiLink2.'/ display contains=VimwikiLinkChar' - - execute 'syntax match VimwikiLinkT /\<'.g:vimwiki_rxWikiWord.'\>/ display contained' - execute 'syntax match VimwikiLinkT /'.g:vimwiki_rxWikiLink1.'/ display contained' - execute 'syntax match VimwikiLinkT /'.g:vimwiki_rxWikiLink2.'/ display contained' - endif - - execute 'syntax match VimwikiLink `'.g:vimwiki_rxWeblink.'` display contains=@NoSpell' -endfunction "}}} - -function! s:highlight_existed_links() "{{{ - let links = s:get_links('*'.VimwikiGet('ext')) - - " Links with subdirs should be highlighted for linux and windows separators - " Change \ or / to [/\\] - let os_p = '[/\\]' - let os_p2 = escape(os_p, '\') - call map(links, 'substitute(v:val, os_p, os_p2, "g")') - - for link in links - if g:vimwiki_camel_case && - \ link =~ g:vimwiki_rxWikiWord && !vimwiki#base#is_non_wiki_link(link) - execute 'syntax match VimwikiLink /!\@/ display' - endif - execute 'syntax match VimwikiLink /\[\['. - \ escape(vimwiki#base#unsafe_link(link), '~&$.*'). - \ '\%(|\+.\{-}\)\{-}\]\]/ display contains=VimwikiLinkChar' - execute 'syntax match VimwikiLink /\[\['. - \ escape(vimwiki#base#unsafe_link(link), '~&$.*'). - \ '\]\[.\{-1,}\]\]/ display contains=VimwikiLinkChar' - - execute 'syntax match VimwikiLinkT /\[\['. - \ escape(vimwiki#base#unsafe_link(link), '~&$.*'). - \ '\%(|\+.\{-}\)\{-}\]\]/ display contained' - execute 'syntax match VimwikiLinkT /\[\['. - \ escape(vimwiki#base#unsafe_link(link), '~&$.*'). - \ '\]\[.\{-1,}\]\]/ display contained' - endfor - execute 'syntax match VimwikiLink /\[\[.\+\.\%(jpg\|png\|gif\)\%(|\+.*\)*\]\]/ display contains=VimwikiLinkChar' - execute 'syntax match VimwikiLink /\[\[.\+\.\%(jpg\|png\|gif\)\]\[.\+\]\]/ display contains=VimwikiLinkChar' - - execute 'syntax match VimwikiLinkT /\[\[.\+\.\%(jpg\|png\|gif\)\%(|\+.*\)*\]\]/ display contained' - execute 'syntax match VimwikiLinkT /\[\[.\+\.\%(jpg\|png\|gif\)\]\[.\+\]\]/ display contained' - - " Issue 103: Always highlight links to non-wiki files as existed. - execute 'syntax match VimwikiLink /\[\[.\+\.\%('. - \join(split(g:vimwiki_file_exts, '\s*,\s*'), '\|'). - \'\)\%(|\+.*\)*\]\]/ display contains=VimwikiLinkChar' - execute 'syntax match VimwikiLink /\[\[.\+\.\%('. - \join(split(g:vimwiki_file_exts, '\s*,\s*'), '\|'). - \'\)\]\[.\+\]\]/ display contains=VimwikiLinkChar' - - execute 'syntax match VimwikiLinkT /\[\[.\+\.\%('. - \join(split(g:vimwiki_file_exts, '\s*,\s*'), '\|'). - \'\)\%(|\+.*\)*\]\]/ display contained' - execute 'syntax match VimwikiLinkT /\[\[.\+\.\%('. - \join(split(g:vimwiki_file_exts, '\s*,\s*'), '\|'). - \'\)\]\[.\+\]\]/ display contained' - - " highlight dirs - let dirs = s:get_links('*/') - call map(dirs, 'substitute(v:val, os_p, os_p2, "g")') - for dir in dirs - execute 'syntax match VimwikiLink /\[\['. - \ escape(vimwiki#base#unsafe_link(dir), '~&$.*'). - \ '[/\\]*\%(|\+.*\)*\]\]/ display contains=VimwikiLinkChar' - execute 'syntax match VimwikiLink /\[\['. - \ escape(vimwiki#base#unsafe_link(dir), '~&$.*'). - \ '[/\\]*\%(\]\[\+.*\)*\]\]/ display contains=VimwikiLinkChar' - - execute 'syntax match VimwikiLinkT /\[\['. - \ escape(vimwiki#base#unsafe_link(dir), '~&$.*'). - \ '[/\\]*\%(|\+.*\)*\]\]/ display contained' - execute 'syntax match VimwikiLinkT /\[\['. - \ escape(vimwiki#base#unsafe_link(dir), '~&$.*'). - \ '[/\\]*\%(\]\[\+.*\)*\]\]/ display contained' - endfor -endfunction "}}} - -function! vimwiki#base#hl_exists(hl) "{{{ - if !hlexists(a:hl) - return 0 - endif - redir => hlstatus - exe "silent hi" a:hl - redir END - return (hlstatus !~ "cleared") -endfunction -"}}} - function! vimwiki#base#nested_syntax(filetype, start, end, textSnipHl) abort "{{{ " From http://vim.wikia.com/wiki/VimTip857 let ft=toupper(a:filetype) @@ -588,64 +830,116 @@ function! vimwiki#base#nested_syntax(filetype, start, end, textSnipHl) abort "{{ endif endfunction "}}} -"}}} +" }}} -" WIKI functions {{{ +" WIKI link following functions {{{ function! vimwiki#base#find_next_link() "{{{ - call s:search_word(g:vimwiki_rxWikiLink.'\|'.g:vimwiki_rxWeblink, '') + call vimwiki#base#search_word(g:vimwiki_rxAnyLink, '') endfunction " }}} function! vimwiki#base#find_prev_link() "{{{ - call s:search_word(g:vimwiki_rxWikiLink.'\|'.g:vimwiki_rxWeblink, 'b') + call vimwiki#base#search_word(g:vimwiki_rxAnyLink, 'b') endfunction " }}} -function! vimwiki#base#follow_link(split) "{{{ - if a:split == "split" - let cmd = ":split " - elseif a:split == "vsplit" - let cmd = ":vsplit " - elseif a:split == "tabnew" - let cmd = ":tabnew " - else - let cmd = ":e " - endif - - let link = s:strip_word(s:get_word_at_cursor(g:vimwiki_rxWikiLink)) - if link == "" - let weblink = s:strip_word(s:get_word_at_cursor(g:vimwiki_rxWeblink)) - if weblink != "" - call VimwikiWeblinkHandler(escape(weblink, '#')) +" follow_link +function! vimwiki#base#follow_link(split, ...) "{{{ Parse link at cursor and pass + " to VimwikiLinkHandler, or failing that, the default open_link handler + if exists('*vimwiki#base_'.VimwikiGet('syntax').'#follow_link') + " Syntax-specific links + " XXX: @Stuart: do we still need it? + " XXX: @Maxim: most likely! I am still working on a seemless way to + " integrate regexp's without complicating syntax/vimwiki.vim + if a:0 + call vimwiki#base_{VimwikiGet('syntax')}#follow_link(a:split, a:1) else - execute "normal! \n" + call vimwiki#base_{VimwikiGet('syntax')}#follow_link(a:split) + endif + else + if a:split == "split" + let cmd = ":split " + elseif a:split == "vsplit" + let cmd = ":vsplit " + elseif a:split == "tabnew" + let cmd = ":tabnew " + else + let cmd = ":e " endif - return - endif - let subdir = vimwiki#base#current_subdir() - call vimwiki#base#open_link(cmd, subdir.link) + " try WikiLink + let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiLink), + \ g:vimwiki_rxWikiLinkMatchUrl) + " try WikiIncl + if lnk == "" + let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiIncl), + \ g:vimwiki_rxWikiInclMatchUrl) + endif + " try Weblink + if lnk == "" + let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWeblink), + \ g:vimwiki_rxWeblinkMatchUrl) + endif + + if lnk != "" + if !VimwikiLinkHandler(lnk) + call vimwiki#base#open_link(cmd, lnk) + endif + return + endif + + if a:0 > 0 + execute "normal! ".a:1 + else + call vimwiki#base#normalize_link(0) + endif + endif endfunction " }}} function! vimwiki#base#go_back_link() "{{{ if exists("b:vimwiki_prev_link") - " go back to saved WikiWord + " go back to saved wiki link let prev_word = b:vimwiki_prev_link execute ":e ".substitute(prev_word[0], '\s', '\\\0', 'g') call setpos('.', prev_word[1]) endif endfunction " }}} -function! vimwiki#base#goto_index(index) "{{{ - call vimwiki#base#select(a:index) - call vimwiki#base#edit_file('e', - \ VimwikiGet('path').VimwikiGet('index').VimwikiGet('ext')) +function! vimwiki#base#goto_index(wnum, ...) "{{{ + if a:wnum > len(g:vimwiki_list) + echom "vimwiki: Wiki ".a:wnum." is not registered in g:vimwiki_list!" + return + endif + + " usually a:wnum is greater then 0 but with the following command it is == 0: + " vim -n -c "exe 'VimwikiIndex' | echo g:vimwiki_current_idx" + if a:wnum > 0 + let idx = a:wnum - 1 + else + let idx = 0 + endif + + if a:0 + let cmd = 'tabedit' + else + let cmd = 'edit' + endif + + if g:vimwiki_debug == 3 + echom "--- Goto_index g:curr_idx=".g:vimwiki_current_idx." ww_idx=".idx."" + endif + + call vimwiki#base#validate_wiki_options(idx) + call vimwiki#base#edit_file(cmd, + \ VimwikiGet('path', idx).VimwikiGet('index', idx). + \ VimwikiGet('ext', idx)) + call vimwiki#base#setup_buffer_state(idx) endfunction "}}} function! vimwiki#base#delete_link() "{{{ "" file system funcs - "" Delete WikiWord you are in from filesystem + "" Delete wiki link you are in from filesystem let val = input('Delete ['.expand('%').'] (y/n)? ', "") if val != 'y' return @@ -657,17 +951,19 @@ function! vimwiki#base#delete_link() "{{{ echomsg 'vimwiki: Cannot delete "'.expand('%:t:r').'"!' return endtry + + call vimwiki#base#go_back_link() execute "bdelete! ".escape(fname, " ") - " reread buffer => deleted WikiWord should appear as non-existent + " reread buffer => deleted wiki link should appear as non-existent if expand('%:p') != "" execute "e" endif endfunction "}}} function! vimwiki#base#rename_link() "{{{ - "" Rename WikiWord, update all links to renamed WikiWord - let subdir = vimwiki#base#current_subdir() + "" Rename wiki link, update all links to renamed WikiWord + let subdir = VimwikiGet('subdir') let old_fname = subdir.expand('%:t') " there is no file (new one maybe) @@ -695,23 +991,23 @@ function! vimwiki#base#rename_link() "{{{ echomsg 'vimwiki: Cannot rename to an empty filename!' return endif - if vimwiki#base#is_non_wiki_link(new_link) - echomsg 'vimwiki: Cannot rename to a filename with extension (ie .txt .html)!' - return + + let url = matchstr(new_link, g:vimwiki_rxWikiLinkMatchUrl) + if url != '' + let new_link = url endif let new_link = subdir.new_link - let new_link = s:strip_word(new_link) - let new_fname = VimwikiGet('path').s:filename(new_link).VimwikiGet('ext') + let new_fname = VimwikiGet('path').new_link.VimwikiGet('ext') - " do not rename if word with such name exists + " do not rename if file with such name exists let fname = glob(new_fname) if fname != '' echomsg 'vimwiki: Cannot rename to "'.new_fname. \ '". File with that name exist!' return endif - " rename WikiWord file + " rename wiki link file try echomsg "Renaming ".VimwikiGet('path').old_fname." to ".new_fname let res = rename(expand('%:p'), expand(new_fname)) @@ -765,7 +1061,7 @@ function! vimwiki#base#rename_link() "{{{ let &more = setting_more endfunction " }}} -function! vimwiki#base#ui_select()"{{{ +function! vimwiki#base#ui_select() "{{{ call s:print_wiki_list() let idx = input("Select Wiki (specify number): ") if idx == "" @@ -774,7 +1070,6 @@ function! vimwiki#base#ui_select()"{{{ call vimwiki#base#goto_index(idx) endfunction "}}} - " }}} " TEXT OBJECTS functions {{{ @@ -789,7 +1084,7 @@ function! vimwiki#base#TO_header(inner, visual) "{{{ let block_start = line(".") let advance = 0 - let level = vimwiki#base#count_first_sym(getline('.')) + let level = vimwiki#u#count_first_sym(getline('.')) let is_header_selected = sel_start == block_start \ && sel_start != sel_end @@ -887,7 +1182,7 @@ function! vimwiki#base#TO_table_cell(inner, visual) "{{{ endfunction "}}} function! vimwiki#base#TO_table_col(inner, visual) "{{{ - let t_rows = vimwiki_tbl#get_rows(line('.')) + let t_rows = vimwiki#tbl#get_rows(line('.')) if empty(t_rows) return endif @@ -903,7 +1198,7 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ if firsttime " place cursor to the top row of the table - call s:cursor(t_rows[0][0], virtcol('.')) + call vimwiki#u#cursor(t_rows[0][0], virtcol('.')) " do not accept the match at cursor position if cursor is next to column " separator of the table separator (^ is a cursor): " |-----^-+-------| @@ -948,7 +1243,7 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ normal! h endif " expand selection to the bottom line of the table - call s:cursor(t_rows[-1][0], virtcol('.')) + call vimwiki#u#cursor(t_rows[-1][0], virtcol('.')) let sel_end = getpos('.') call setpos('.', sel_start) @@ -957,7 +1252,7 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ else " place cursor to the top row of the table - call s:cursor(t_rows[0][0], virtcol('.')) + call vimwiki#u#cursor(t_rows[0][0], virtcol('.')) " do not accept the match at cursor position if cursor is next to column " separator of the table separator (^ is a cursor): " |-----^-+-------| @@ -996,33 +1291,36 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ normal! h endif " expand selection to the bottom line of the table - call s:cursor(t_rows[-1][0], virtcol('.')) + call vimwiki#u#cursor(t_rows[-1][0], virtcol('.')) endif endfunction "}}} +" }}} -function! vimwiki#base#count_first_sym(line) "{{{ - let first_sym = matchstr(a:line, '\S') - return len(matchstr(a:line, first_sym.'\+')) -endfunction "}}} - +" HEADER functions {{{ function! vimwiki#base#AddHeaderLevel() "{{{ let lnum = line('.') let line = getline(lnum) - + let rxHdr = g:vimwiki_rxH if line =~ '^\s*$' return endif - if line =~ '^\s*\(=\+\).\+\1\s*$' - let level = vimwiki#base#count_first_sym(line) + if line =~ g:vimwiki_rxHeader + let level = vimwiki#u#count_first_sym(line) if level < 6 - let line = substitute(line, '\(=\+\).\+\1', '=&=', '') + if g:vimwiki_symH + let line = substitute(line, '\('.rxHdr.'\+\).\+\1', rxHdr.'&'.rxHdr, '') + else + let line = substitute(line, '\('.rxHdr.'\+\).\+', rxHdr.'&', '') + endif call setline(lnum, line) endif else - let line = substitute(line, '^\s*', '&= ', '') - let line = substitute(line, '\s*$', ' =&', '') - call setline(lnum, line) + let line = substitute(line, '^\s*', '&'.rxHdr.' ', '') + if g:vimwiki_symH + let line = substitute(line, '\s*$', ' '.rxHdr.'&', '') + endif + call setline(lnum, line) endif endfunction "}}} @@ -1030,27 +1328,175 @@ endfunction function! vimwiki#base#RemoveHeaderLevel() "{{{ let lnum = line('.') let line = getline(lnum) - + let rxHdr = g:vimwiki_rxH if line =~ '^\s*$' return endif - if line =~ '^\s*\(=\+\).\+\1\s*$' - let level = vimwiki#base#count_first_sym(line) - let old = repeat('=', level) - let new = repeat('=', level - 1) + if line =~ g:vimwiki_rxHeader + let level = vimwiki#u#count_first_sym(line) + let old = repeat(rxHdr, level) + let new = repeat(rxHdr, level - 1) - let chomp = line =~ '=\s' + let chomp = line =~ rxHdr.'\s' - let line = substitute(line, old, new, 'g') + if g:vimwiki_symH + let line = substitute(line, old, new, 'g') + else + let line = substitute(line, old, new, '') + endif if level == 1 && chomp let line = substitute(line, '^\s', '', 'g') let line = substitute(line, '\s$', '', 'g') endif + + let line = substitute(line, '\s*$', '', '') + call setline(lnum, line) endif endfunction " }}} +"}}} + +" LINK functions {{{ +" Construct a regular expression matching from template (with special +" characters properly escaped), by substituting rxUrl for __LinkUrl__, rxDesc +" for __LinkDescription__, and rxStyle for __LinkStyle__. The three +" arguments rxUrl, rxDesc, and rxStyle are copied verbatim, without any +" special character escapes or substitutions. +function! vimwiki#base#apply_template(template, rxUrl, rxDesc, rxStyle) "{{{ + let magic_chars = '.*[\^$' + let lnk = escape(a:template, magic_chars) + if a:rxUrl != "" + let lnk = substitute(lnk, '__LinkUrl__', '\='."'".a:rxUrl."'", '') + endif + if a:rxDesc != "" + let lnk = substitute(lnk, '__LinkDescription__', '\='."'".a:rxDesc."'", '') + endif + if a:rxStyle != "" + let lnk = substitute(lnk, '__LinkStyle__', '\='."'".a:rxStyle."'", '') + endif + return lnk +endfunction +" }}} + +function! s:clean_url(url) " {{{ + let url = split(a:url, '/\|=\|-\|&\|?\|\.') + let url = filter(url, 'v:val != ""') + let url = filter(url, 'v:val != "www"') + let url = filter(url, 'v:val != "com"') + let url = filter(url, 'v:val != "org"') + let url = filter(url, 'v:val != "net"') + let url = filter(url, 'v:val != "edu"') + let url = filter(url, 'v:val != "http\:"') + let url = filter(url, 'v:val != "https\:"') + let url = filter(url, 'v:val != "file\:"') + let url = filter(url, 'v:val != "xml\:"') + return join(url, " ") +endfunction " }}} + +function! vimwiki#base#normalize_link_helper(str, rxUrl, rxDesc, template) " {{{ + let str = a:str + let url = matchstr(str, a:rxUrl) + let descr = matchstr(str, a:rxDesc) + let template = a:template + if descr == "" + let descr = s:clean_url(url) + endif + let lnk = substitute(template, '__LinkDescription__', '\="'.descr.'"', '') + let lnk = substitute(lnk, '__LinkUrl__', '\="'.url.'"', '') + return lnk +endfunction " }}} + +function! vimwiki#base#normalize_imagelink_helper(str, rxUrl, rxDesc, rxStyle, template) "{{{ + let lnk = vimwiki#base#normalize_link_helper(a:str, a:rxUrl, a:rxDesc, a:template) + let style = matchstr(str, a:rxStyle) + let lnk = substitute(lnk, '__LinkStyle__', '\="'.style.'"', '') + return lnk +endfunction " }}} + +function! s:normalize_link_syntax_n() " {{{ + let lnum = line('.') + + " try WikiLink + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiLink) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ g:vimwiki_rxWikiLinkMatchUrl, g:vimwiki_rxWikiLinkMatchDescr, + \ g:vimwiki_WikiLinkTemplate2) + call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWikiLink, sub) + if g:vimwiki_debug > 1 + echomsg "WikiLink: ".lnk." Sub: ".sub + endif + return + endif + + " try WikiIncl + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiIncl) + if !empty(lnk) + " NO-OP !! + if g:vimwiki_debug > 1 + echomsg "WikiIncl: ".lnk." Sub: ".lnk + endif + return + endif + + " try Word (any characters except separators) + " rxWord is less permissive than rxWikiLinkUrl which is used in + " normalize_link_syntax_v + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWord) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ g:vimwiki_rxWord, '', + \ g:vimwiki_WikiLinkTemplate1) + call vimwiki#base#replacestr_at_cursor('\V'.lnk, sub) + if g:vimwiki_debug > 1 + echomsg "Word: ".lnk." Sub: ".sub + endif + return + endif + +endfunction " }}} + +function! s:normalize_link_syntax_v() " {{{ + let lnum = line('.') + let sel_save = &selection + let &selection = "old" + let rv = @" + let rt = getregtype('"') + let done = 0 + + try + norm! gvy + let visual_selection = @" + let visual_selection = substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', '\='."'".visual_selection."'", '') + + call setreg('"', visual_selection, 'v') + + " paste result + norm! `>pgvd + + finally + call setreg('"', rv, rt) + let &selection = sel_save + endtry + +endfunction " }}} + +" normalize_link +function! vimwiki#base#normalize_link(is_visual_mode) "{{{ + if exists('*vimwiki#'.VimwikiGet('syntax').'_base#normalize_link') + " Syntax-specific links + call vimwiki#{VimwikiGet('syntax')}_base#normalize_link(a:is_visual_mode) + else + if !a:is_visual_mode + call s:normalize_link_syntax_n() + elseif visualmode() ==# 'v' && line("'<") == line("'>") + " action undefined for 'line-wise' or 'multi-line' visual mode selections + call s:normalize_link_syntax_v() + endif + endif +endfunction "}}} " }}} diff --git a/autoload/vimwiki/diary.vim b/autoload/vimwiki/diary.vim index 7c7f51e..56234f7 100644 --- a/autoload/vimwiki/diary.vim +++ b/autoload/vimwiki/diary.vim @@ -11,6 +11,9 @@ endif let g:loaded_vimwiki_diary_auto = 1 "}}} +let s:vimwiki_max_scan_for_caption = 5 + +" Helpers {{{ function! s:prefix_zero(num) "{{{ if a:num < 10 return '0'.a:num @@ -18,10 +21,6 @@ function! s:prefix_zero(num) "{{{ return a:num endfunction "}}} -function! s:desc(d1, d2) "{{{ - return a:d1 == a:d2 ? 0 : a:d1 < a:d2 ? 1 : -1 -endfunction "}}} - function! s:get_date_link(fmt) "{{{ return strftime(a:fmt) endfunction "}}} @@ -37,76 +36,26 @@ function! s:link_exists(lines, link) "{{{ return link_exists endfunction "}}} -function! s:diary_path() "{{{ - return VimwikiGet('path').VimwikiGet('diary_rel_path') +function! s:diary_path(...) "{{{ + let idx = a:0 == 0 ? g:vimwiki_current_idx : a:1 + return VimwikiGet('path', idx).VimwikiGet('diary_rel_path', idx) endfunction "}}} -function! s:diary_index() "{{{ - return s:diary_path().VimwikiGet('diary_index').VimwikiGet('ext') +function! s:diary_index(...) "{{{ + let idx = a:0 == 0 ? g:vimwiki_current_idx : a:1 + return s:diary_path(idx).VimwikiGet('diary_index', idx).VimwikiGet('ext', idx) endfunction "}}} -function! s:get_diary_range(lines, header) "{{{ - let rx = '\[\[\d\{4}-\d\d-\d\d\]\]' - let idx = 0 - let ln_start = -1 - let ln_end = -1 - for line in a:lines - if ln_start != -1 - if line =~ '^\s*\(=\)\+.*\1\s*$' || (line !~ rx && line !~ '^\s*$') - break - endif - endif - if line =~ '^\s*\(=\)\+\s*'.a:header.'\s*\1\s*$' - let ln_start = idx + 1 - endif - let idx += 1 - endfor - - let ln_end = idx - return [ln_start, ln_end] -endfunction "}}} - -function! s:diary_date_link() "{{{ - return s:get_date_link(VimwikiGet('diary_link_fmt')) -endfunction "}}} - -function! s:get_file_contents(file_name) "{{{ - let lines = [] - let bufnr = bufnr(expand(a:file_name)) - if bufnr != -1 - let lines = getbufline(bufnr, 1, '$') - else - try - let lines = readfile(expand(a:file_name)) - catch - endtry - endif - return [lines, bufnr] -endfunction "}}} - -function! s:get_links() "{{{ - let rx = '\d\{4}-\d\d-\d\d' - let s_links = glob(VimwikiGet('path').VimwikiGet('diary_rel_path'). - \ '*'.VimwikiGet('ext')) - - let s_links = substitute(s_links, '\'.VimwikiGet('ext'), "", "g") - let links = split(s_links, '\n') - - " remove backup files (.wiki~) - call filter(links, 'v:val !~ ''.*\~$''') - - " remove paths - call map(links, 'fnamemodify(v:val, ":t")') - - call filter(links, 'v:val =~ "'.escape(rx, '\').'"') - return links +function! s:diary_date_link(...) "{{{ + let idx = a:0 == 0 ? g:vimwiki_current_idx : a:1 + return s:get_date_link(VimwikiGet('diary_link_fmt', idx)) endfunction "}}} function! s:get_position_links(link) "{{{ let idx = -1 let links = [] - if a:link =~ '\d\{4}-\d\d-\d\d' - let links = s:get_links() + if a:link =~ '^\d\{4}-\d\d-\d\d' + let links = keys(s:get_diary_links()) " include 'today' into links if index(links, s:diary_date_link()) == -1 call add(links, s:diary_date_link()) @@ -117,103 +66,263 @@ function! s:get_position_links(link) "{{{ return [idx, links] endfunction "}}} -function! s:format_links(links) "{{{ - let lines = [] - let line = '| ' - let idx = 0 - let trigger = 0 - while idx < len(a:links) - if idx/VimwikiGet('diary_link_count') > trigger - let trigger = idx/VimwikiGet('diary_link_count') - call add(lines, substitute(line, '\s\+$', '', '')) - let line = '| ' - endif - let line .= a:links[idx].' | ' - let idx += 1 - endwhile - call add(lines, substitute(line, '\s\+$', '', '')) - call extend(lines, ['']) +fun! s:get_month_name(month) "{{{ + return g:vimwiki_diary_months[str2nr(a:month)] +endfun "}}} - return lines -endfunction "}}} +" Helpers }}} -function! s:add_link(page, header, link) "{{{ - let [lines, bufnr] = s:get_file_contents(a:page) +" Diary index stuff {{{ +fun! s:read_captions(files) "{{{ + let result = {} + for fl in a:files + " remove paths and extensions + let fl_key = fnamemodify(fl, ':t:r') - let [ln_start, ln_end] = s:get_diary_range(lines, a:header) - - let link = '[['.a:link.']]' - - let link_exists = s:link_exists(lines[ln_start : ln_end], link) - - if !link_exists - - if ln_start == -1 - call insert(lines, '= '.a:header.' =') - let ln_start = 1 - let ln_end = 1 + if filereadable(fl) + for line in readfile(fl, '', s:vimwiki_max_scan_for_caption) + if line =~ g:vimwiki_rxHeader && !has_key(result, fl_key) + let result[fl_key] = vimwiki#u#trim(matchstr(line, g:vimwiki_rxHeader)) + endif + endfor endif - " removing 'old' links - let idx = ln_end - ln_start - while idx > 0 - call remove(lines, ln_start) - let idx -= 1 - endwhile - - " get all diary links from filesystem - let links = s:get_links() - call map(links, '"[[".v:val."]]"') - - " add current link - if index(links, link) == -1 - call add(links, link) + if !has_key(result, fl_key) + let result[fl_key] = '' endif - let links = sort(links, 's:desc') - call extend(lines, s:format_links(links), ln_start) + endfor + return result +endfun "}}} - if bufnr != -1 - exe 'buffer '.bufnr - if !&readonly - 1,$delete _ - call append(1, lines) - 1,1delete _ - endif +fun! s:get_diary_links(...) "{{{ + let rx = '^\d\{4}-\d\d-\d\d' + let s_files = glob(VimwikiGet('path').VimwikiGet('diary_rel_path').'*'.VimwikiGet('ext')) + let files = split(s_files, '\n') + call filter(files, 'fnamemodify(v:val, ":t") =~ "'.escape(rx, '\').'"') + + " remove backup files (.wiki~) + call filter(files, 'v:val !~ ''.*\~$''') + + if a:0 + call add(files, a:1) + endif + let links_with_captions = s:read_captions(files) + + return links_with_captions +endfun "}}} + +fun! s:group_links(links) "{{{ + let result = {} + let p_year = 0 + let p_month = 0 + for fl in sort(keys(a:links)) + let year = strpart(fl, 0, 4) + let month = strpart(fl, 5, 2) + if p_year != year + let result[year] = {} + let p_month = 0 + endif + if p_month != month + let result[year][month] = {} + endif + let result[year][month][fl] = a:links[fl] + let p_year = year + let p_month = month + endfor + return result +endfun "}}} + +fun! s:sort(lst) "{{{ + if VimwikiGet("diary_sort") == 'desc' + return reverse(sort(a:lst)) + else + return sort(a:lst) + endif +endfun "}}} + +fun! 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, '') + let entry = substitute(entry, '__LinkDescription__', cap, '') + call add(result, repeat(' ', &sw).'* '.entry) + else + let entry = substitute(g:vimwiki_WikiLinkTemplate2, '__LinkUrl__', fl, '') + let entry = substitute(entry, '__LinkDescription__', cap, '') + call add(result, repeat(' ', &sw).'* '.entry) + endif + endfor + + 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 - call writefile(lines, expand(a:page)) + 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 "}}} -function! s:make_date_link(...) "{{{ - if a:0 - let link = a:1 - else - let link = s:diary_date_link() +" Diary index stuff }}} + +function! vimwiki#diary#make_note(wnum, ...) "{{{ + if a:wnum > len(g:vimwiki_list) + echom "vimwiki: Wiki ".a:wnum." is not registered in g:vimwiki_list!" + return endif - let header = VimwikiGet('diary_header') - call s:add_link(s:diary_index(), header, link) - return VimwikiGet('diary_rel_path').link -endfunction "}}} -function! vimwiki#diary#make_note(index, ...) "{{{ - call vimwiki#base#select(a:index) - call vimwiki#base#mkdir(VimwikiGet('path').VimwikiGet('diary_rel_path')) - if a:0 - let link = s:make_date_link(a:1) + " TODO: refactor it. base#goto_index uses the same + if a:wnum > 0 + let idx = a:wnum - 1 else - let link = s:make_date_link() + let idx = 0 endif - call vimwiki#base#open_link(':e ', link, s:diary_index()) + + call vimwiki#base#validate_wiki_options(idx) + call vimwiki#base#mkdir(VimwikiGet('path', idx).VimwikiGet('diary_rel_path', idx)) + + if a:0 + let cmd = 'tabedit' + else + let cmd = 'edit' + endif + if len(a:0)>1 + let link = 'diary:'.a:2 + else + let link = 'diary:'.s:diary_date_link(idx) + endif + + call vimwiki#base#open_link(cmd, link, s:diary_index(idx)) + call vimwiki#base#setup_buffer_state(idx) endfunction "}}} -function! vimwiki#diary#goto_index(index) "{{{ - call vimwiki#base#select(a:index) - call vimwiki#base#edit_file(':e', s:diary_index()) +function! vimwiki#diary#goto_diary_index(wnum) "{{{ + if a:wnum > len(g:vimwiki_list) + echom "vimwiki: Wiki ".a:wnum." is not registered in g:vimwiki_list!" + return + endif + + " TODO: refactor it. base#goto_index uses the same + if a:wnum > 0 + let idx = a:wnum - 1 + else + let idx = 0 + endif + + call vimwiki#base#validate_wiki_options(idx) + call vimwiki#base#edit_file('e', s:diary_index(idx)) + call vimwiki#base#setup_buffer_state(idx) endfunction "}}} -" Calendar.vim callback function. +function! vimwiki#diary#goto_next_day() "{{{ + let link = '' + let [idx, links] = s:get_position_links(expand('%:t:r')) + + if idx == (len(links) - 1) + return + endif + + if idx != -1 && idx < len(links) - 1 + let link = 'diary:'.links[idx+1] + else + " goto today + let link = 'diary:'.s:diary_date_link() + endif + + if len(link) + call vimwiki#base#open_link(':e ', link) + endif +endfunction "}}} + +function! vimwiki#diary#goto_prev_day() "{{{ + let link = '' + let [idx, links] = s:get_position_links(expand('%:t:r')) + + if idx == 0 + return + endif + + if idx > 0 + let link = 'diary:'.links[idx-1] + else + " goto today + let link = 'diary:'.s:diary_date_link() + endif + + if len(link) + call vimwiki#base#open_link(':e ', link) + endif +endfunction "}}} + +function! vimwiki#diary#generate_diary_section() "{{{ + let current_file = vimwiki#u#path_norm(expand("%:p")) + let diary_file = vimwiki#u#path_norm(s:diary_index()) + if current_file == diary_file + call s:delete_diary_section() + call s:insert_diary_section() + else + echom "vimwiki: You can generate diary links only in a diary index page!" + endif +endfunction "}}} + +" Calendar.vim {{{ +" Callback function. function! vimwiki#diary#calendar_action(day, month, year, week, dir) "{{{ let day = s:prefix_zero(a:day) let month = s:prefix_zero(a:month) @@ -233,10 +342,10 @@ function! vimwiki#diary#calendar_action(day, month, year, week, dir) "{{{ endif " Create diary note for a selected date in default wiki. - call vimwiki#diary#make_note(1, link) + call vimwiki#diary#make_note(1, 0, link) endfunction "}}} -" Calendar.vim sign function. +" Sign function. function vimwiki#diary#calendar_sign(day, month, year) "{{{ let day = s:prefix_zero(a:day) let month = s:prefix_zero(a:month) @@ -245,42 +354,5 @@ function vimwiki#diary#calendar_sign(day, month, year) "{{{ return filereadable(expand(sfile)) endfunction "}}} -function! vimwiki#diary#goto_next_day() "{{{ - let link = '' - let [idx, links] = s:get_position_links(expand('%:t:r')) +" Calendar.vim }}} - if idx == (len(links) - 1) - return - endif - - if idx != -1 && idx < len(links) - 1 - let link = VimwikiGet('diary_rel_path').links[idx+1] - else - " goto today - let link = VimwikiGet('diary_rel_path').s:diary_date_link() - endif - - if len(link) - call vimwiki#base#open_link(':e ', link) - endif -endfunction "}}} - -function! vimwiki#diary#goto_prev_day() "{{{ - let link = '' - let [idx, links] = s:get_position_links(expand('%:t:r')) - - if idx == 0 - return - endif - - if idx > 0 - let link = VimwikiGet('diary_rel_path').links[idx-1] - else - " goto today - let link = VimwikiGet('diary_rel_path').s:diary_date_link() - endif - - if len(link) - call vimwiki#base#open_link(':e ', link) - endif -endfunction "}}} diff --git a/autoload/vimwiki/html.vim b/autoload/vimwiki/html.vim index 3d685d6..4bd45b6 100644 --- a/autoload/vimwiki/html.vim +++ b/autoload/vimwiki/html.vim @@ -14,6 +14,15 @@ let g:loaded_vimwiki_html_auto = 1 "}}} " UTILITY "{{{ +function s:get_completion_index(sym) "{{{ + for idx in range(1, 5) + if match(g:vimwiki_listsyms, '\C\%'.idx.'v'.a:sym) != -1 + return (idx-1) + endif + endfor + return 0 +endfunction "}}} + function! s:root_path(subdir) "{{{ return repeat('../', len(split(a:subdir, '[/\\]'))) endfunction "}}} @@ -36,7 +45,7 @@ function! s:is_web_link(lnk) "{{{ endfunction "}}} function! s:is_img_link(lnk) "{{{ - if a:lnk =~ '\.\%(png\|jpg\|gif\|jpeg\)$' + if tolower(a:lnk) =~ '\.\%(png\|jpg\|gif\|jpeg\)$' return 1 endif return 0 @@ -59,9 +68,14 @@ function! s:find_autoload_file(name) " {{{ return '' endfunction " }}} -function! s:create_default_CSS(path) " {{{ +function! s:default_CSS_full_name(path) " {{{ let path = expand(a:path) let css_full_name = path.VimwikiGet('css_name') + return css_full_name +endfunction "}}} + +function! s:create_default_CSS(path) " {{{ + let css_full_name = s:default_CSS_full_name(a:path) if glob(css_full_name) == "" call vimwiki#base#mkdir(fnamemodify(css_full_name, ':p:h')) let default_css = s:find_autoload_file('style.css') @@ -81,8 +95,7 @@ function! s:template_full_name(name) "{{{ endif let fname = expand(VimwikiGet('template_path'). - \name. - \VimwikiGet('template_ext')) + \ name.VimwikiGet('template_ext')) if filereadable(fname) return fname @@ -95,8 +108,8 @@ function! s:get_html_template(wikifile, template) "{{{ " TODO: refactor it!!! let lines=[] - let template_name = s:template_full_name(a:template) - if template_name != '' + if a:template != '' + let template_name = s:template_full_name(a:template) try let lines = readfile(template_name) return lines @@ -106,27 +119,40 @@ function! s:get_html_template(wikifile, template) "{{{ endtry endif - " if no VimwikiGet('html_template') set up or error while reading template - " file -- use default one. - let default_tpl = s:find_autoload_file('default.tpl') - if default_tpl != '' - let lines = readfile(default_tpl) + let default_tpl = s:template_full_name('') + + if default_tpl == '' + let default_tpl = s:find_autoload_file('default.tpl') endif + + let lines = readfile(default_tpl) return lines endfunction "}}} +function! s:safe_html_tags(line) "{{{ + let line = substitute(a:line,'<','\<', 'g') + let line = substitute(line,'>','\>', 'g') + return line +endfunction "}}} + function! s:safe_html(line) "{{{ + " escape & < > when producing HTML text + " uses variables s:lt_pattern, s:gt_pattern that are + " set in vimwiki#html#Wiki2HTML() according to g:vimwiki_valid_html_tags "" htmlize symbols: < > & let line = substitute(a:line, '&', '\&', 'g') + " the following depends on g:vimwiki_valid_html_tags + let line = substitute(line,s:lt_pattern,'\<', 'g') + let line = substitute(line,s:gt_pattern,'\>', 'g') - let tags = join(split(g:vimwiki_valid_html_tags, '\s*,\s*'), '\|') - let line = substitute(line,'<\%(/\?\%(' - \.tags.'\)\%(\s\{-1}\S\{-}\)\{-}/\?>\)\@!', - \'\<', 'g') - let line = substitute(line,'\%(', - \'\>', 'g') + "let tags = join(split(g:vimwiki_valid_html_tags, '\s*,\s*'), '\|') + "let line = substitute(line,'<\%(/\?\%(' + " \.tags.'\)\%(\s\{-1}\S\{-}\)\{-}/\?>\)\@!', + " \'\<', 'g') + "let line = substitute(line,'\%(', + " \'\>', 'g') return line endfunction "}}} @@ -140,8 +166,8 @@ function! s:delete_html_files(path) "{{{ " delete if there is no corresponding wiki file let subdir = vimwiki#base#subdir(VimwikiGet('path_html'), fname) - let wikifile = VimwikiGet("path").subdir. - \fnamemodify(fname, ":t:r").VimwikiGet("ext") + let wikifile = VimwikiGet('path').subdir. + \fnamemodify(fname, ":t:r").VimwikiGet('ext') if filereadable(wikifile) continue endif @@ -182,12 +208,6 @@ function! s:save_vimwiki_buffer() "{{{ endif endfunction "}}} -function! s:trim(string) "{{{ - let res = substitute(a:string, '^\s\+', '', '') - let res = substitute(res, '\s\+$', '', '') - return res -endfunction "}}} - function! s:get_html_toc(toc_list) "{{{ " toc_list is list of [level, header_text, header_id] " ex: [[1, "Header", "toc1"], [2, "Header2", "toc2"], ...] @@ -265,8 +285,7 @@ function! s:is_html_uptodate(wikifile) "{{{ endif let wikifile = fnamemodify(a:wikifile, ":p") - let subdir = vimwiki#base#subdir(VimwikiGet('path'), wikifile) - let htmlfile = expand(VimwikiGet('path_html').subdir. + let htmlfile = expand(VimwikiGet('path_html').VimwikiGet('subdir'). \fnamemodify(wikifile, ":t:r").".html") if getftime(wikifile) <= getftime(htmlfile) && tpl_time <= getftime(htmlfile) @@ -299,6 +318,11 @@ endfunction "}}} "}}} " INLINE TAGS "{{{ +function! s:tag_eqin(value) "{{{ + " mathJAX wants \( \) for inline maths + return '\('.s:mid(a:value, 1).'\)' +endfunction "}}} + function! s:tag_em(value) "{{{ return ''.s:mid(a:value, 1).'' endfunction "}}} @@ -324,141 +348,113 @@ function! s:tag_sub(value) "{{{ endfunction "}}} function! s:tag_code(value) "{{{ - return ''.s:mid(a:value, 1).'' + return ''.s:safe_html_tags(s:mid(a:value, 1)).'' endfunction "}}} -function! s:tag_pre(value) "{{{ - return ''.s:mid(a:value, 3).'' +"function! s:tag_pre(value) "{{{ +" return ''.s:mid(a:value, 3).'' +"endfunction "}}} + +"FIXME dead code? +"function! s:tag_math(value) "{{{ +" return '\['.s:mid(a:value, 3).'\]' +"endfunction "}}} + + +"{{{ v2.0 links +" match n-th ARG within {{URL[|ARG1|ARG2|...]}} " {{{ +" *c,d,e),... +function! vimwiki#html#incl_match_arg(nn_index) + let rx = g:vimwiki_rxWikiInclPrefix. g:vimwiki_rxWikiInclUrl + let rx = rx. repeat(g:vimwiki_rxWikiInclSeparator. g:vimwiki_rxWikiInclArg, a:nn_index-1) + if a:nn_index > 0 + let rx = rx. g:vimwiki_rxWikiInclSeparator. '\zs'. g:vimwiki_rxWikiInclArg. '\ze' + endif + let rx = rx. g:vimwiki_rxWikiInclArgs. g:vimwiki_rxWikiInclSuffix + return rx +endfunction +"}}} + +function! vimwiki#html#linkify_link(src, descr) "{{{ + let src_str = ' href="'.a:src.'"' + let descr = substitute(a:descr,'^\s*\(.*\)\s*$','\1','') + let descr = (descr == "" ? a:src : descr) + let descr_str = (descr =~ g:vimwiki_rxWikiIncl + \ ? s:tag_wikiincl(descr) + \ : descr) + return ''.descr_str.'' endfunction "}}} -function! s:tag_internal_link(value) "{{{ - " Make This is a link - " from [[This is a link]] - " Make This is a link - " from [[link|This is a link]] - " Make This is a link - " from [[link][This is a link]] - " TODO: rename function -- it makes not only internal links. - " TODO: refactor it. +function! vimwiki#html#linkify_image(src, descr, verbatim_str) "{{{ + let src_str = ' src="'.a:src.'"' + let descr_str = (a:descr != '' ? ' alt="'.a:descr.'"' : '') + let verbatim_str = (a:verbatim_str != '' ? ' '.a:verbatim_str : '') + return '' +endfunction "}}} - function! s:linkify(src, caption, style) "{{{ - if a:style == '' - let style_str = '' - else - let style_str = ' style="'.a:style.'"' - endif - - if s:is_img_link(a:caption) - let link = ''. - \ '' - elseif vimwiki#base#is_non_wiki_link(a:src) - let link = ''.a:caption.'' - elseif s:is_img_link(a:src) - let link = ''.a:caption.'' - elseif vimwiki#base#is_link_to_dir(a:src) - if g:vimwiki_dir_link == '' - let link = ''.a:caption.'' - else - let link = ''.a:caption.'' - endif - else - let link = ''.a:caption.'' - endif - - return link - endfunction "}}} - - let value = s:mid(a:value, 2) - - let line = '' - if value =~ '|' - let link_parts = split(value, "|", 1) - else - let link_parts = split(value, "][", 1) - endif - - - if len(link_parts) > 1 - if len(link_parts) < 3 - let style = "" - else - let style = link_parts[2] - endif - - let line = s:linkify(link_parts[0], link_parts[1], style) - - else - let line = s:linkify(value, value, '') - endif +function! s:tag_weblink(value) "{{{ + " Weblink Template -> descr + let str = a:value + let url = matchstr(str, g:vimwiki_rxWeblinkMatchUrl) + let descr = matchstr(str, g:vimwiki_rxWeblinkMatchDescr) + let line = vimwiki#html#linkify_link(url, descr) return line endfunction "}}} -function! s:tag_external_link(value) "{{{ - "" Make link desc - "" from [link link desc] - - let value = s:mid(a:value, 1) - - let line = '' - if s:is_web_link(value) - let lnkElements = split(value) - let head = lnkElements[0] - let rest = join(lnkElements[1:]) - if rest=="" - let rest=head +function! s:tag_wikiincl(value) "{{{ + " {{imgurl|arg1|arg2}} -> ??? + " {{imgurl}} -> + " {{imgurl|descr|style="A"}} -> descr + " {{imgurl|descr|class="B"}} -> descr + let str = a:value + " custom transclusions + let line = VimwikiWikiIncludeHandler(str) + " otherwise, assume image transclusion + if line == '' + let url_0 = matchstr(str, g:vimwiki_rxWikiInclMatchUrl) + let descr = matchstr(str, vimwiki#html#incl_match_arg(1)) + let verbatim_str = matchstr(str, vimwiki#html#incl_match_arg(2)) + " resolve url + let [idx, scheme, path, subdir, lnk, ext, url] = + \ vimwiki#base#resolve_scheme(url_0, 1) + " generate html output + " TODO: migrate non-essential debugging messages into g:VimwikiLog + if g:vimwiki_debug > 1 + echom '{{idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.'}}' endif - if s:is_img_link(rest) - if rest!=head - let line = '' - else - let line = '' - endif - else - let line = ''.rest.'' - endif - elseif s:is_img_link(value) - let line = '' - else - " [alskfj sfsf] shouldn't be a link. So return it as it was -- - " enclosed in [...] - let line = '['.value.']' - endif - return line -endfunction "}}} - -function! s:tag_wikiword_link(value) "{{{ - " Make WikiWord from WikiWord - if a:value[0] == '!' - return a:value[1:] - elseif g:vimwiki_camel_case - let line = ''.a:value.'' + let url = escape(url, '#') + let line = vimwiki#html#linkify_image(url, descr, verbatim_str) return line - else - return a:value - endif -endfunction "}}} - -function! s:tag_barebone_link(value) "{{{ - "" Make http://habamax.ru - "" from http://habamax.ru - - if s:is_img_link(a:value) - let line = '' - else - let line = ''.a:value.'' endif return line endfunction "}}} -function! s:tag_no_wikiword_link(value) "{{{ - if a:value[0] == '!' - return a:value[1:] - else - return a:value +function! s:tag_wikilink(value) "{{{ + " [[url]] -> url + " [[url|descr]] -> descr + " [[url|{{...}}]] -> ... + " [[fileurl.ext|descr]] -> descr + " [[dirurl/|descr]] -> descr + let str = a:value + let url = matchstr(str, g:vimwiki_rxWikiLinkMatchUrl) + let descr = matchstr(str, g:vimwiki_rxWikiLinkMatchDescr) + let descr = (substitute(descr,'^\s*\(.*\)\s*$','\1','') != '' ? descr : url) + + " resolve url + let [idx, scheme, path, subdir, lnk, ext, url] = + \ vimwiki#base#resolve_scheme(url, 1) + + " generate html output + " TODO: migrate non-essential debugging messages into g:VimwikiLog + if g:vimwiki_debug > 1 + echom '[[idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.']]' endif + let url = escape(url, '#') + let line = vimwiki#html#linkify_link(url, descr) + return line endfunction "}}} +"}}} v1.3 links + function! s:tag_remove_internal_link(value) "{{{ let value = s:mid(a:value, 2) @@ -508,10 +504,16 @@ endfunction "}}} function! s:make_tag(line, regexp, func) "{{{ " Make tags for a given matched regexp. " Exclude preformatted text and href links. + " FIXME + let patt_splitter = '\(`[^`]\+`\)\|'. + \ '\('.g:vimwiki_rxPreStart.'.\+'.g:vimwiki_rxPreEnd.'\)\|'. + \ '\(\)\|'. + \ '\(\)\|'. + \ '\('.g:vimwiki_rxEqIn.'\)' - let patt_splitter = '\(`[^`]\+`\)\|\({{{.\+}}}\)\|'. - \ '\(\)\|\(\)' - if '`[^`]\+`' == a:regexp || '{{{.\+}}}' == a:regexp + "FIXME FIXME !!! these can easily occur on the same line! + "XXX {{{ }}} ??? obsolete + if '`[^`]\+`' == a:regexp || '{{{.\+}}}' == a:regexp || g:vimwiki_rxEqIn == a:regexp let res_line = s:subst_func(a:line, a:regexp, a:func) else let pos = 0 @@ -541,7 +543,6 @@ endfunction " }}} function! s:process_tags_typefaces(line) "{{{ let line = a:line - let line = s:make_tag(line, g:vimwiki_rxNoWikiWord, 's:tag_no_wikiword_link') let line = s:make_tag(line, g:vimwiki_rxItalic, 's:tag_em') let line = s:make_tag(line, g:vimwiki_rxBold, 's:tag_strong') let line = s:make_tag(line, g:vimwiki_rxTodo, 's:tag_todo') @@ -549,15 +550,15 @@ function! s:process_tags_typefaces(line) "{{{ let line = s:make_tag(line, g:vimwiki_rxSuperScript, 's:tag_super') 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') return line endfunction " }}} function! s:process_tags_links(line) " {{{ let line = a:line - let line = s:make_tag(line, '\[\[.\{-}\]\]', 's:tag_internal_link') - let line = s:make_tag(line, '\[.\{-}\]', 's:tag_external_link') - let line = s:make_tag(line, g:vimwiki_rxWeblink, 's:tag_barebone_link') - let line = s:make_tag(line, g:vimwiki_rxWikiWord, 's:tag_wikiword_link') + let line = s:make_tag(line, g:vimwiki_rxWikiLink, 's:tag_wikilink') + let line = s:make_tag(line, g:vimwiki_rxWikiIncl, 's:tag_wikiincl') + let line = s:make_tag(line, g:vimwiki_rxWeblink, 's:tag_weblink') return line endfunction " }}} @@ -577,6 +578,14 @@ function! s:close_tag_pre(pre, ldest) "{{{ return a:pre endfunction "}}} +function! s:close_tag_math(math, ldest) "{{{ + if a:math[0] + call insert(a:ldest, "\\\]") + return 0 + endif + return a:math +endfunction "}}} + function! s:close_tag_quote(quote, ldest) "{{{ if a:quote call insert(a:ldest, "") @@ -745,11 +754,15 @@ endfunction! "}}} function! s:process_tag_pre(line, pre) "{{{ " pre is the list of [is_in_pre, indent_of_pre] + "XXX always outputs a single line or empty list! let lines = [] let pre = a:pre let processed = 0 - if !pre[0] && a:line =~ '^\s*{{{[^\(}}}\)]*\s*$' + "XXX huh? + "if !pre[0] && a:line =~ '^\s*{{{[^\(}}}\)]*\s*$' + if !pre[0] && a:line =~ '^\s*{{{' let class = matchstr(a:line, '{{{\zs.*$') + "FIXME class cannot contain arbitrary strings let class = substitute(class, '\s\+$', '', 'g') if class != "" call add(lines, "
")
@@ -764,11 +777,48 @@ function! s:process_tag_pre(line, pre) "{{{
     let processed = 1
   elseif pre[0]
     let processed = 1
-    call add(lines, substitute(a:line, '^\s\{'.pre[1].'}', '', ''))
+    "XXX destroys indent in general!
+    "call add(lines, substitute(a:line, '^\s\{'.pre[1].'}', '', ''))
+    call add(lines, s:safe_html_tags(a:line))
   endif
   return [processed, lines, pre]
 endfunction "}}}
 
+function! s:process_tag_math(line, math) "{{{
+  " math is the list of [is_in_math, indent_of_math]
+  let lines = []
+  let math = a:math
+  let processed = 0
+  if !math[0] && a:line =~ '^\s*{{\$[^\(}}$\)]*\s*$'
+    let class = matchstr(a:line, '{{$\zs.*$')
+    "FIXME class cannot be any string!
+    let class = substitute(class, '\s\+$', '', 'g')
+    " Check the math placeholder (default: displaymath)
+    let b:vimwiki_mathEnv = matchstr(class, '^%\zs\S\+\ze%')
+    if b:vimwiki_mathEnv != ""
+        call add(lines, substitute(class, '^%\(\S\+\)%','\\begin{\1}', ''))
+    elseif class != ""
+      call add(lines, "\\\[".class)
+    else
+      call add(lines, "\\\[")
+    endif
+    let math = [1, len(matchstr(a:line, '^\s*\ze{{\$'))]
+    let processed = 1
+  elseif math[0] && a:line =~ '^\s*}}\$\s*$'
+    let math = [0, 0]
+    if b:vimwiki_mathEnv != ""
+      call add(lines, "\\end{".b:vimwiki_mathEnv."}")
+    else
+      call add(lines, "\\\]")
+    endif
+    let processed = 1
+  elseif math[0]
+    let processed = 1
+    call add(lines, substitute(a:line, '^\s\{'.math[1].'}', '', ''))
+  endif
+  return [processed, lines, math]
+endfunction "}}}
+
 function! s:process_tag_quote(line, quote) "{{{
   let lines = []
   let quote = a:quote
@@ -800,7 +850,8 @@ function! s:process_tag_list(line, lists) "{{{
         if chk[1] =~ '[.*\\^$~]'
           let chk[1] ='\'.chk[1]
         endif
-        let completion = match(g:vimwiki_listsyms, '\C' . chk[1])
+        " let completion = match(g:vimwiki_listsyms, '\C' . chk[1])
+        let completion = s:get_completion_index(chk[1])
         if completion >= 0 && completion <=4
           let st_tag = '
  • ' endif @@ -935,18 +986,9 @@ function! s:process_tag_h(line, id) "{{{ let h_level = 0 let h_text = '' let h_id = '' - if a:line =~ g:vimwiki_rxH6 - let h_level = 6 - elseif a:line =~ g:vimwiki_rxH5 - let h_level = 5 - elseif a:line =~ g:vimwiki_rxH4 - let h_level = 4 - elseif a:line =~ g:vimwiki_rxH3 - let h_level = 3 - elseif a:line =~ g:vimwiki_rxH2 - let h_level = 2 - elseif a:line =~ g:vimwiki_rxH1 - let h_level = 1 + + if a:line =~ g:vimwiki_rxHeader + let h_level = vimwiki#u#count_first_sym(a:line) endif if h_level > 0 let a:id[h_level] += 1 @@ -960,8 +1002,6 @@ function! s:process_tag_h(line, id) "{{{ let centered = 1 endif - let line = s:trim(line) - let h_number = '' for l in range(1, h_level-1) let h_number .= a:id[l].'.' @@ -978,7 +1018,8 @@ function! s:process_tag_h(line, id) "{{{ let h_part .= '>' endif - let h_text = s:trim(strpart(line, h_level, len(line) - h_level * 2)) + let h_text = vimwiki#u#trim(matchstr(line, g:vimwiki_rxHeader)) + if g:vimwiki_html_header_numbering let num = matchstr(h_number, \ '^\(\d.\)\{'.(g:vimwiki_html_header_numbering-1).'}\zs.*') @@ -1046,14 +1087,15 @@ function! s:process_tag_table(line, table) "{{{ let lines = [] let processed = 0 - if a:line =~ '^\s*|[-+]\+|\s*$' + if vimwiki#tbl#is_separator(a:line) call extend(table, s:table_add_row(a:table, a:line)) let processed = 1 - elseif a:line =~ '^\s*|.\+|\s*$' + elseif vimwiki#tbl#is_table(a:line) call extend(table, s:table_add_row(a:table, a:line)) let processed = 1 - let cells = split(a:line, '\s*|\s*', 1)[1: -2] + " let cells = split(a:line, vimwiki#tbl#cell_splitter(), 1)[1: -2] + let cells = vimwiki#tbl#get_cells(a:line) call map(cells, 's:table_empty_cell(v:val)') call extend(table[-1], cells) else @@ -1072,6 +1114,7 @@ function! s:parse_line(line, state) " {{{ let state.para = a:state.para let state.quote = a:state.quote let state.pre = a:state.pre[:] + let state.math = a:state.math[:] let state.table = a:state.table[:] let state.lists = a:state.lists[:] let state.deflist = a:state.deflist @@ -1135,6 +1178,9 @@ function! s:parse_line(line, state) " {{{ " if processed && len(state.lists) " call s:close_tag_list(state.lists, lines) " endif + if !processed + let [processed, lines, state.math] = s:process_tag_math(line, state.math) + endif if processed && len(state.table) let state.table = s:close_tag_table(state.table, lines) endif @@ -1160,6 +1206,9 @@ function! s:parse_line(line, state) " {{{ if processed && state.pre[0] let state.pre = s:close_tag_pre(state.pre, lines) endif + if processed && state.math[0] + let state.math = s:close_tag_math(state.math, lines) + endif if processed && len(state.table) let state.table = s:close_tag_table(state.table, lines) endif @@ -1183,6 +1232,7 @@ function! s:parse_line(line, state) " {{{ call s:close_tag_list(state.lists, res_lines) let state.table = s:close_tag_table(state.table, res_lines) let state.pre = s:close_tag_pre(state.pre, res_lines) + let state.math = s:close_tag_math(state.math, res_lines) let state.quote = s:close_tag_quote(state.quote, res_lines) let state.para = s:close_tag_para(state.para, res_lines) @@ -1218,6 +1268,9 @@ function! s:parse_line(line, state) " {{{ if processed && state.pre[0] let state.pre = s:close_tag_pre(state.pre, lines) endif + if processed && state.math[0] + let state.math = s:close_tag_math(state.math, lines) + endif if processed && state.para let state.para = s:close_tag_para(state.para, lines) endif @@ -1235,6 +1288,7 @@ function! s:parse_line(line, state) " {{{ call s:close_tag_list(state.lists, res_lines) let state.table = s:close_tag_table(state.table, res_lines) let state.pre = s:close_tag_pre(state.pre, res_lines) + let state.math = s:close_tag_math(state.math, res_lines) call add(res_lines, line) endif endif @@ -1262,6 +1316,9 @@ function! s:parse_line(line, state) " {{{ if processed && state.pre[0] let state.pre = s:close_tag_pre(state.pre, res_lines) endif + if processed && state.math[0] + let state.math = s:close_tag_math(state.math, res_lines) + endif if processed && len(state.table) let state.table = s:close_tag_table(state.table, res_lines) endif @@ -1281,128 +1338,174 @@ function! s:parse_line(line, state) " {{{ endfunction " }}} -function! vimwiki#html#Wiki2HTML(path, wikifile) "{{{ +function! s:use_custom_wiki2html() "{{{ + let custom_wiki2html = VimwikiGet('custom_wiki2html') + return !empty(custom_wiki2html) && s:file_exists(custom_wiki2html) +endfunction " }}} + +function! vimwiki#html#CustomWiki2HTML(path, wikifile, force) "{{{ + call vimwiki#base#mkdir(a:path) + execute '!'.VimwikiGet('custom_wiki2html'). ' ' + \ a:force. ' '. + \ VimwikiGet('syntax'). ' '. + \ strpart(VimwikiGet('ext'), 1). ' '. + \ a:path. ' '. + \ a:wikifile. ' '. + \ s:default_CSS_full_name(a:path) +endfunction " }}} + +function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ let starttime = reltime() " start the clock - echo 'Generating HTML ... ' - if !s:syntax_supported() - echomsg 'vimwiki: Only vimwiki_default syntax supported!!!' - return - endif + + let done = 0 let wikifile = fnamemodify(a:wikifile, ":p") - let subdir = vimwiki#base#subdir(VimwikiGet('path'), wikifile) - let path = expand(a:path).subdir + let path_html = expand(a:path_html).VimwikiGet('subdir') let htmlfile = fnamemodify(wikifile, ":t:r").'.html' - let lsource = readfile(wikifile) - let ldest = [] + if s:use_custom_wiki2html() + let force = 1 + call vimwiki#html#CustomWiki2HTML(path_html, wikifile, force) + let done = 1 + endif - call vimwiki#base#mkdir(path) + if s:syntax_supported() && done == 0 + let lsource = readfile(wikifile) + let ldest = [] - " nohtml placeholder -- to skip html generation. - let nohtml = 0 + "if g:vimwiki_debug + " echo 'Generating HTML ... ' + "endif - " template placeholder - let template_name = '' + call vimwiki#base#mkdir(path_html) - " for table of contents placeholders. - let placeholders = [] + " nohtml placeholder -- to skip html generation. + let nohtml = 0 - " current state of converter - let state = {} - let state.para = 0 - let state.quote = 0 - let state.pre = [0, 0] " [in_pre, indent_pre] - let state.table = [] - let state.deflist = 0 - let state.lists = [] - let state.placeholder = [] - let state.toc = [] - let state.toc_id = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0 } + " template placeholder + let template_name = '' - for line in lsource - let oldquote = state.quote - let [lines, state] = s:parse_line(line, state) + " for table of contents placeholders. + let placeholders = [] - " Hack: There could be a lot of empty strings before s:process_tag_quote - " find out `quote` is over. So we should delete them all. Think of the way - " to refactor it out. - if oldquote != state.quote - call s:remove_blank_lines(ldest) + " current state of converter + let state = {} + let state.para = 0 + let state.quote = 0 + let state.pre = [0, 0] " [in_pre, indent_pre] + let state.math = [0, 0] " [in_math, indent_math] + let state.table = [] + let state.deflist = 0 + let state.lists = [] + let state.placeholder = [] + let state.toc = [] + let state.toc_id = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0 } + + " prepare constants for s:safe_html() + let s:lt_pattern = '<' + let s:gt_pattern = '>' + if g:vimwiki_valid_html_tags != '' + let tags = join(split(g:vimwiki_valid_html_tags, '\s*,\s*'), '\|') + let s:lt_pattern = '<\%(/\?\%('.tags.'\)\%(\s\{-1}\S\{-}\)\{-}/\?>\)\@!' + let s:gt_pattern = '\%(' endif - if !empty(state.placeholder) - if state.placeholder[0] == 'nohtml' - let nohtml = 1 - break - elseif state.placeholder[0] == 'template' - let template_name = state.placeholder[1] - else - call add(placeholders, [state.placeholder, len(ldest), len(placeholders)]) + for line in lsource + let oldquote = state.quote + let [lines, state] = s:parse_line(line, state) + + " Hack: There could be a lot of empty strings before s:process_tag_quote + " find out `quote` is over. So we should delete them all. Think of the way + " to refactor it out. + if oldquote != state.quote + call s:remove_blank_lines(ldest) endif - let state.placeholder = [] + + if !empty(state.placeholder) + if state.placeholder[0] == 'nohtml' + let nohtml = 1 + break + elseif state.placeholder[0] == 'template' + let template_name = state.placeholder[1] + else + call add(placeholders, [state.placeholder, len(ldest), len(placeholders)]) + endif + let state.placeholder = [] + endif + + call extend(ldest, lines) + endfor + + + if nohtml + echon "\r"."%nohtml placeholder found" + return endif + let toc = s:get_html_toc(state.toc) + call s:process_toc(ldest, placeholders, toc) + call s:remove_blank_lines(ldest) + + "" process end of file + "" close opened tags if any + let lines = [] + call s:close_tag_quote(state.quote, lines) + call s:close_tag_para(state.para, lines) + call s:close_tag_pre(state.pre, lines) + call s:close_tag_math(state.math, lines) + call s:close_tag_list(state.lists, lines) + call s:close_tag_def_list(state.deflist, lines) + call s:close_tag_table(state.table, lines) call extend(ldest, lines) - endfor + let title = s:process_title(placeholders, fnamemodify(a:wikifile, ":t:r")) - if nohtml - echon "\r"."%nohtml placeholder found" + let html_lines = s:get_html_template(a:wikifile, template_name) + + " processing template variables (refactor to a function) + call map(html_lines, 'substitute(v:val, "%title%", "'. title .'", "g")') + call map(html_lines, 'substitute(v:val, "%root_path%", "'. + \ s:root_path(VimwikiGet('subdir')) .'", "g")') + + let css_name = expand(VimwikiGet('css_name')) + let css_name = substitute(css_name, '\', '/', 'g') + call map(html_lines, 'substitute(v:val, "%css%", "'. css_name .'", "g")') + + let enc = &fileencoding + if enc == '' + let enc = &encoding + endif + call map(html_lines, 'substitute(v:val, "%encoding%", "'. enc .'", "g")') + + let html_lines = s:html_insert_contents(html_lines, ldest) " %contents% + + "" make html file. + call writefile(html_lines, path_html.htmlfile) + let done = 1 + + endif + + if done == 0 + echomsg 'vimwiki: conversion to HTML is not supported for this syntax!!!' return endif - let toc = s:get_html_toc(state.toc) - call s:process_toc(ldest, placeholders, toc) - call s:remove_blank_lines(ldest) + " measure the elapsed time + let time1 = vimwiki#u#time(starttime) "XXX + call VimwikiLog_extend('html',[htmlfile,time1]) + "if g:vimwiki_debug + " echon "\r".htmlfile.' written (time: '.time1.'s)' + "endif - "" process end of file - "" close opened tags if any - let lines = [] - call s:close_tag_quote(state.quote, lines) - call s:close_tag_para(state.para, lines) - call s:close_tag_pre(state.pre, lines) - call s:close_tag_list(state.lists, lines) - call s:close_tag_def_list(state.deflist, lines) - call s:close_tag_table(state.table, lines) - call extend(ldest, lines) - - let title = s:process_title(placeholders, fnamemodify(a:wikifile, ":t:r")) - - let html_lines = s:get_html_template(a:wikifile, template_name) - - " processing template variables (refactor to a function) - call map(html_lines, 'substitute(v:val, "%title%", "'. title .'", "g")') - call map(html_lines, 'substitute(v:val, "%root_path%", "'. - \ s:root_path(subdir) .'", "g")') - - let css_name = expand(VimwikiGet('css_name')) - let css_name = substitute(css_name, '\', '/', 'g') - call map(html_lines, 'substitute(v:val, "%css%", "'. css_name .'", "g")') - - let enc = &fileencoding - if enc == '' - let enc = &encoding - endif - call map(html_lines, 'substitute(v:val, "%encoding%", "'. enc .'", "g")') - - let html_lines = s:html_insert_contents(html_lines, ldest) " %contents% - - "" make html file. - call writefile(html_lines, path.htmlfile) - - " measure the elapsed time and cut away miliseconds and smaller - let elapsedtimestr = matchstr(reltimestr(reltime(starttime)),'\d\+\(\.\d\d\)\=') - echon "\r".htmlfile.' written (time: '.elapsedtimestr.'s)' - return path.htmlfile + return path_html.htmlfile endfunction "}}} -function! vimwiki#html#WikiAll2HTML(path) "{{{ - if !s:syntax_supported() - echomsg 'vimwiki: Only vimwiki_default syntax supported!!!' +function! vimwiki#html#WikiAll2HTML(path_html) "{{{ + if !s:syntax_supported() && !s:use_custom_wiki2html() + echomsg 'vimwiki: conversion to HTML is not supported for this syntax!!!' return endif @@ -1414,28 +1517,63 @@ function! vimwiki#html#WikiAll2HTML(path) "{{{ exe 'buffer '.cur_buf let &eventignore = save_eventignore - let path = expand(a:path) - call vimwiki#base#mkdir(path) + let path_html = expand(a:path_html) + call vimwiki#base#mkdir(path_html) echomsg 'Deleting non-wiki html files...' - call s:delete_html_files(path) + call s:delete_html_files(path_html) echomsg 'Converting wiki to html files...' let setting_more = &more setlocal nomore + " temporarily adjust current_subdir global state variable + let current_subdir = VimwikiGet('subdir') + let current_invsubdir = VimwikiGet('invsubdir') + let wikifiles = split(glob(VimwikiGet('path').'**/*'.VimwikiGet('ext')), '\n') for wikifile in wikifiles + let wikifile = fnamemodify(wikifile, ":p") + + " temporarily adjust 'subdir' and 'invsubdir' state variables + let subdir = vimwiki#base#subdir(VimwikiGet('path'), wikifile) + call VimwikiSet('subdir', subdir) + call VimwikiSet('invsubdir', vimwiki#base#invsubdir(subdir)) + if !s:is_html_uptodate(wikifile) echomsg 'Processing '.wikifile - call vimwiki#html#Wiki2HTML(path, wikifile) + + call vimwiki#html#Wiki2HTML(path_html, wikifile) else echomsg 'Skipping '.wikifile endif endfor - call s:create_default_CSS(path) + " reset 'subdir' state variable + call VimwikiSet('subdir', current_subdir) + call VimwikiSet('invsubdir', current_invsubdir) + + call s:create_default_CSS(path_html) echomsg 'Done!' let &more = setting_more endfunction "}}} + +function! s:file_exists(fname) "{{{ + return !empty(getftype(a:fname)) +endfunction "}}} + +" uses VimwikiGet('path') +function! vimwiki#html#get_wikifile_url(wikifile) "{{{ + return VimwikiGet('path_html'). + \ vimwiki#base#subdir(VimwikiGet('path'), a:wikifile). + \ fnamemodify(a:wikifile, ":t:r").'.html' +endfunction "}}} + +function! vimwiki#html#PasteUrl(wikifile) "{{{ + execute 'r !echo file://'.vimwiki#html#get_wikifile_url(a:wikifile) +endfunction "}}} + +function! vimwiki#html#CatUrl(wikifile) "{{{ + execute '!echo file://'.vimwiki#html#get_wikifile_url(a:wikifile) +endfunction "}}} "}}} diff --git a/autoload/vimwiki/lst.vim b/autoload/vimwiki/lst.vim index 2e21502..7d42517 100644 --- a/autoload/vimwiki/lst.vim +++ b/autoload/vimwiki/lst.vim @@ -15,24 +15,36 @@ let s:rx_li_box = '\[.\?\]' " Script functions {{{ +" Get unicode string symbol at index +function! s:str_idx(str, idx) "{{{ + " Unfortunatly vimscript cannot get symbol at index in unicode string such as + " '✗○◐●✓' + return matchstr(a:str, '\%'.a:idx.'v.') +endfunction "}}} + " Get checkbox regexp function! s:rx_li_symbol(rate) "{{{ let result = '' if a:rate == 100 - let result = g:vimwiki_listsyms[4] + let result = s:str_idx(g:vimwiki_listsyms, 5) elseif a:rate == 0 - let result = g:vimwiki_listsyms[0] + let result = s:str_idx(g:vimwiki_listsyms, 1) elseif a:rate >= 67 - let result = g:vimwiki_listsyms[3] + let result = s:str_idx(g:vimwiki_listsyms, 4) elseif a:rate >= 34 - let result = g:vimwiki_listsyms[2] + let result = s:str_idx(g:vimwiki_listsyms, 3) else - let result = g:vimwiki_listsyms[1] + let result = s:str_idx(g:vimwiki_listsyms, 2) endif return '\['.result.'\]' endfunction "}}} +" Get blank checkbox +function! s:blank_checkbox() "{{{ + return '['.s:str_idx(g:vimwiki_listsyms, 1).'] ' +endfunction "}}} + " Get regexp of the list item. function! s:rx_list_item() "{{{ return '\('.g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber.'\)' @@ -46,7 +58,7 @@ endfunction "}}} " Get level of the list item. function! s:get_level(lnum) "{{{ if VimwikiGet('syntax') == 'media' - let level = vimwiki#base#count_first_sym(getline(a:lnum)) + let level = vimwiki#u#count_first_sym(getline(a:lnum)) else let level = indent(a:lnum) endif @@ -222,7 +234,7 @@ function! s:create_cb_list_item(lnum) "{{{ let m = matchstr(line, s:rx_list_item()) if m != '' let li_content = substitute(strpart(line, len(m)), '^\s*', '', '') - let line = substitute(m, '\s*$', ' ', '').'[ ] '.li_content + let line = substitute(m, '\s*$', ' ', '').s:blank_checkbox().li_content call setline(a:lnum, line) endif endfunction "}}} @@ -320,7 +332,7 @@ function! vimwiki#lst#kbd_cr() "{{{ " This function is heavily relies on proper 'set comments' option. let cr = "\" if getline('.') =~ s:rx_cb_list_item() - let cr .= '[ ] ' + let cr .= s:blank_checkbox() endif return cr endfunction "}}} @@ -341,11 +353,10 @@ function! vimwiki#lst#kbd_oO(cmd) "{{{ let lnum = line('.') endif - " let line = substitute(m, '\s*$', ' ', '').'[ ] '.li_content let m = matchstr(line, s:rx_list_item()) let res = '' if line =~ s:rx_cb_list_item() - let res = substitute(m, '\s*$', ' ', '').'[ ] ' + let res = substitute(m, '\s*$', ' ', '').s:blank_checkbox() elseif line =~ s:rx_list_item() let res = substitute(m, '\s*$', ' ', '') elseif &autoindent || &smartindent @@ -367,3 +378,178 @@ function! vimwiki#lst#kbd_oO(cmd) "{{{ endfunction "}}} +function! vimwiki#lst#default_symbol() "{{{ + " TODO: initialize default symbol from syntax/vimwiki_xxx.vim + if VimwikiGet('syntax') == 'default' + return '-' + else + return '*' + endif +endfunction "}}} + +function vimwiki#lst#get_list_margin() "{{{ + if VimwikiGet('list_margin') < 0 + return &sw + else + return VimwikiGet('list_margin') + endif +endfunction "}}} + +function s:get_list_sw() "{{{ + if VimwikiGet('syntax') == 'media' + return 1 + else + return &sw + endif +endfunction "}}} + +function s:get_list_nesting_level(lnum) "{{{ + if VimwikiGet('syntax') == 'media' + if getline(a:lnum) !~ s:rx_list_item() + let level = 0 + else + let level = vimwiki#u#count_first_sym(getline(a:lnum)) - 1 + let level = level < 0 ? 0 : level + endif + else + let level = indent(a:lnum) + endif + return level +endfunction "}}} + +function s:get_list_indent(lnum) "{{{ + if VimwikiGet('syntax') == 'media' + return indent(a:lnum) + else + return 0 + endif +endfunction "}}} + +function! s:compose_list_item(n_indent, n_nesting, sym_nest, sym_bullet, li_content, ...) "{{{ + if a:0 + let sep = a:1 + else + let sep = '' + endif + let li_indent = repeat(' ', max([0,a:n_indent])).sep + let li_nesting = repeat(a:sym_nest, max([0,a:n_nesting])).sep + if len(a:sym_bullet) > 0 + let li_bullet = a:sym_bullet.' '.sep + else + let li_bullet = ''.sep + endif + return li_indent.li_nesting.li_bullet.a:li_content +endfunction "}}} + +function s:compose_cb_bullet(prev_cb_bullet, sym) "{{{ + return a:sym.matchstr(a:prev_cb_bullet, '\S*\zs\s\+.*') +endfunction "}}} + +function! vimwiki#lst#change_level(...) "{{{ + let default_sym = vimwiki#lst#default_symbol() + let cmd = '>>' + let sym = default_sym + + " parse argument + if a:0 + if a:1 != '<<' && a:1 != '>>' + let cmd = '--' + let sym = a:1 + else + let cmd = a:1 + endif + endif + " is symbol valid + if sym.' ' !~ s:rx_cb_list_item() && sym.' ' !~ s:rx_list_item() + return + endif + + " parsing setup + let lnum = line('.') + let line = getline('.') + + let list_margin = vimwiki#lst#get_list_margin() + let list_sw = s:get_list_sw() + let n_nesting = s:get_list_nesting_level(lnum) + let n_indent = s:get_list_indent(lnum) + + " remove indent and nesting + let li_bullet_and_content = strpart(line, n_nesting + n_indent) + + " list bullet and checkbox + let cb_bullet = matchstr(li_bullet_and_content, s:rx_list_item()). + \ matchstr(li_bullet_and_content, s:rx_cb_list_item()) + + " XXX: it could be not unicode proof --> if checkboxes are set up with unicode syms + " content + let li_content = strpart(li_bullet_and_content, len(cb_bullet)) + + " trim + let cb_bullet = vimwiki#u#trim(cb_bullet) + let li_content = vimwiki#u#trim(li_content) + + " nesting symbol + if VimwikiGet('syntax') == 'media' + if len(cb_bullet) > 0 + let sym_nest = cb_bullet[0] + else + let sym_nest = sym + endif + else + let sym_nest = ' ' + endif + + if g:vimwiki_debug + echomsg "PARSE: Sw [".list_sw."]" + echomsg s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content, '|') + endif + + " change level + if cmd == '--' + let cb_bullet = s:compose_cb_bullet(cb_bullet, sym) + if VimwikiGet('syntax') == 'media' + let sym_nest = sym + endif + elseif cmd == '>>' + if cb_bullet == '' + let cb_bullet = sym + else + let n_nesting = n_nesting + list_sw + endif + elseif cmd == '<<' + let n_nesting = n_nesting - list_sw + if VimwikiGet('syntax') == 'media' + if n_nesting < 0 + let cb_bullet = '' + endif + else + if n_nesting < list_margin + let cb_bullet = '' + endif + endif + endif + + let n_nesting = max([0, n_nesting]) + + if g:vimwiki_debug + echomsg "SHIFT:" + echomsg s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content, '|') + endif + + " XXX: this is the code that adds the initial indent + let add_nesting = VimwikiGet('syntax') != 'media' + if n_indent + n_nesting*(add_nesting) < list_margin + let n_indent = list_margin - n_nesting*(add_nesting) + endif + + if g:vimwiki_debug + echomsg "INDENT:" + echomsg s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content, '|') + endif + + let line = s:compose_list_item(n_indent, n_nesting, sym_nest, cb_bullet, li_content) + + " replace + call setline(lnum, line) + call cursor(lnum, match(line, '\S') + 1) +endfunction "}}} diff --git a/autoload/vimwiki/markdown_base.vim b/autoload/vimwiki/markdown_base.vim new file mode 100644 index 0000000..b77606d --- /dev/null +++ b/autoload/vimwiki/markdown_base.vim @@ -0,0 +1,111 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" Vimwiki autoload plugin file +" Desc: Link functions for markdown syntax +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ + + +function! s:normalize_link_syntax_n() " {{{ + let lnum = line('.') + + " try WikiIncl + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiIncl) + if !empty(lnk) + " NO-OP !! + if g:vimwiki_debug > 1 + echomsg "WikiIncl: ".lnk." Sub: ".lnk + endif + return + endif + + " try WikiLink0: replace with WikiLink1 + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiLink0) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ g:vimwiki_rxWikiLinkMatchUrl, g:vimwiki_rxWikiLinkMatchDescr, + \ g:vimwiki_WikiLink1Template2) + call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWikiLink0, sub) + if g:vimwiki_debug > 1 + echomsg "WikiLink: ".lnk." Sub: ".sub + endif + return + endif + + " try WikiLink1: replace with WikiLink0 + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiLink1) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ g:vimwiki_rxWikiLinkMatchUrl, g:vimwiki_rxWikiLinkMatchDescr, + \ g:vimwiki_WikiLinkTemplate2) + call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWikiLink1, sub) + if g:vimwiki_debug > 1 + echomsg "WikiLink: ".lnk." Sub: ".sub + endif + return + endif + + " try Weblink + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWeblink) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ g:vimwiki_rxWeblinkMatchUrl, g:vimwiki_rxWeblinkMatchDescr, + \ g:vimwiki_Weblink1Template) + call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWeblink, sub) + if g:vimwiki_debug > 1 + echomsg "WebLink: ".lnk." Sub: ".sub + endif + return + endif + + " try Word (any characters except separators) + " rxWord is less permissive than rxWikiLinkUrl which is used in + " normalize_link_syntax_v + let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWord) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ g:vimwiki_rxWord, '', + \ g:vimwiki_WikiLinkTemplate1) + call vimwiki#base#replacestr_at_cursor('\V'.lnk, sub) + if g:vimwiki_debug > 1 + echomsg "Word: ".lnk." Sub: ".sub + endif + return + endif + +endfunction " }}} + +function! s:normalize_link_syntax_v() " {{{ + let lnum = line('.') + let sel_save = &selection + let &selection = "old" + let rv = @" + let rt = getregtype('"') + let done = 0 + + try + norm! gvy + let visual_selection = @" + let visual_selection = substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', '\='."'".visual_selection."'", '') + + call setreg('"', visual_selection, 'v') + + " paste result + norm! `>pgvd + + finally + call setreg('"', rv, rt) + let &selection = sel_save + endtry + +endfunction " }}} + +" normalize_link +function! vimwiki#markdown_base#normalize_link(is_visual_mode) "{{{ + if !a:is_visual_mode + call s:normalize_link_syntax_n() + elseif visualmode() ==# 'v' && line("'<") == line("'>") + " action undefined for 'line-wise' or 'multi-line' visual mode selections + call s:normalize_link_syntax_v() + endif +endfunction "}}} + diff --git a/autoload/vimwiki/style.css b/autoload/vimwiki/style.css index c19c6f3..752867b 100644 --- a/autoload/vimwiki/style.css +++ b/autoload/vimwiki/style.css @@ -24,16 +24,56 @@ del {text-decoration: line-through; color: #777777;} .justright {text-align: right;} .justcenter {text-align: center;} .center {margin-left: auto; margin-right: auto;} + /* classes for items of todo lists */ -.done0:before {content: "\2592\2592\2592\2592"; color: SkyBlue;} -.done1:before {content: "\2588\2592\2592\2592"; color: SkyBlue;} -.done2:before {content: "\2588\2588\2592\2592"; color: SkyBlue;} -.done3:before {content: "\2588\2588\2588\2592"; color: SkyBlue;} -.done4:before {content: "\2588\2588\2588\2588"; color: SkyBlue;} -/* comment the next four or five lines out * - * if you do not want color-coded todo lists */ -.done0 {color: #c00000;} -.done1 {color: #c08000;} -.done2 {color: #80a000;} -.done3 {color: #00c000;} -.done4 {color: #7f7f7f; text-decoration: line-through;} +.done0 { + /* list-style: none; */ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAA7SURBVCiR7dMxEgAgCANBI3yVRzF5KxNbW6wsuH7LQ2YKQK1mkswBVERYF5Os3UV3gwd/jF2SkXy66gAZkxS6BniubAAAAABJRU5ErkJggg==); + background-repeat: no-repeat; + background-position: 0 .2em; + margin-left: -2em; + padding-left: 1.5em; +} +.done1 { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABtSURBVCiR1ZO7DYAwDER9BDmTeZQMFXmUbGYpOjrEryA0wOvO8itOslFrJYAug5BMM4BeSkmjsrv3aVTa8p48Xw1JSkSsWVUFwD05IqS1tmYzk5zzae9jnVVVzGyXb8sALjse+euRkEzu/uirFomVIdDGOLjuAAAAAElFTkSuQmCC); + background-repeat: no-repeat; + background-position: 0 .15em; + margin-left: -2em; + padding-left: 1.5em; +} +.done2 { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAB1SURBVCiRzdO5DcAgDAVQGxjAYgTvxlDIu1FTIRYAp8qlFISkSH7l5kk+ZIwxKiI2mIyqWoeILYRgZ7GINDOLjnmF3VqklKCUMgTee2DmM661Qs55iI3Zm/1u5h9sm4ig9z4ERHTFzLyd4G4+nFlVrYg8+qoF/c0kdpeMsmcAAAAASUVORK5CYII=); + background-repeat: no-repeat; + background-position: 0 .15em; + margin-left: -2em; + padding-left: 1.5em; +} +.done3 { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABoSURBVCiR7dOxDcAgDATA/0DtUdiKoZC3YhLkHjkVKF3idJHiztKfvrHZWnOSE8Fx95RJzlprimJVnXktvXeY2S0SEZRSAAAbmxnGGKH2I5T+8VfxPhIReQSuuY3XyYWa3T2p6quvOgGrvSFGlewuUAAAAABJRU5ErkJggg==); + background-repeat: no-repeat; + background-position: 0 .15em; + margin-left: -2em; + padding-left: 1.5em; +} +.done4 { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAzgAAAM4BlP6ToAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIISURBVDiNnZQ9SFtRFMd/773kpTaGJoQk1im4VDpWQcTNODhkFBcVTCNCF0NWyeDiIIiCm82QoIMIUkHUxcFBg1SEQoZszSat6cdTn1qNue92CMbEr9Sey+XC/Z/zu+f8h6ukUil3sVg0+M+4cFxk42/jH2wAqqqKSCSiPQdwcHHAnDHH9s/tN1h8V28ETdP+eU8fT9Nt62ancYdIPvJNtsu87bmjrJlrTDVM4RROJs1JrHPrD4Bar7A6cpc54iKOaTdJXCUI2UMVrQZ0Js7YPN18ECKkYNQcJe/OE/4dZsw7VqNXQMvHy3QZXQypQ6ycrtwDjf8aJ+PNEDSCzLpn7+m2pD8ZKHlKarYhy6XjEoCYGcN95qansQeA3fNdki+SaJZGTMQIOoL3W/Z89rxv+tokubNajlvk/vm+LFpF2XnUKZHI0I+QrI7Dw0OZTqdzUkpsM7mZTyfy5OPGyw1tK7AFSvmB/Ks8w8YwbUYbe6/3QEKv0vugfxWPnMLJun+d/kI/WLdizpNjMbAIKrhMF4OuwadBALqqs+RfInwUvuNi+fBd+wjogfogAFVRmffO02q01mZZ0HHdgXIzdz0QQLPezIQygX6llxNKKgOFARYCC49CqhoHIUTlss/Vx2phlYwjw8j1CAlfAiwQiJpiy7o1VHnsG5FISkoJu7Q/2YmmaV+i0ei7v38L2CBguSi5AAAAAElFTkSuQmCC); + background-repeat: no-repeat; + background-position: 0 .15em; + margin-left: -2em; + padding-left: 1.5em; +} + +code { + font-family: Monaco,"Courier New","DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + padding: 0px 3px; + display: inline-block; + color: #52595d; + border: 1px solid #ccc; + background-color: #f9f9f9; +} diff --git a/autoload/vimwiki/tbl.vim b/autoload/vimwiki/tbl.vim index 9f745c7..67a0f8f 100644 --- a/autoload/vimwiki/tbl.vim +++ b/autoload/vimwiki/tbl.vim @@ -2,7 +2,7 @@ " Vimwiki autoload plugin file " Desc: Tables " | Easily | manageable | text | tables | ! | -" |--------+------------+-------+--------+---------| +" |--------|------------|-------|--------|---------| " | Have | fun! | Drink | tea | Period. | " " Author: Maxim Kim @@ -16,6 +16,8 @@ let g:loaded_vimwiki_tbl_auto = 1 "}}} let s:textwidth = &tw +let s:rxSep = g:vimwiki_rxTableSep + " Misc functions {{{ function! s:wide_len(str) "{{{ @@ -40,21 +42,37 @@ function! s:wide_len(str) "{{{ return ret endfunction "}}} +function! s:cell_splitter() "{{{ + return '\s*'.s:rxSep.'\s*' +endfunction "}}} + +function! s:sep_splitter() "{{{ + return '-'.s:rxSep.'-' +endfunction "}}} + function! s:is_table(line) "{{{ - return a:line =~ '^\s*\%(|[^|]\+\)\+|\s*$' || s:is_separator(a:line) + return s:is_separator(a:line) || (a:line !~ s:rxSep.s:rxSep && a:line =~ '^\s*'.s:rxSep.'.\+'.s:rxSep.'\s*$') endfunction "}}} function! s:is_separator(line) "{{{ - return a:line =~ '^\s*[|+]\s*--[-|+]\+' + return a:line =~ '^\s*'.s:rxSep.'\(--\+'.s:rxSep.'\)\+\s*$' +endfunction "}}} + +function! s:is_separator_tail(line) "{{{ + return a:line =~ '^\{-1}\%(\s*\|-*\)\%('.s:rxSep.'-\+\)\+'.s:rxSep.'\s*$' endfunction "}}} function! s:is_last_column(lnum, cnum) "{{{ - return strpart(getline(a:lnum), a:cnum - 1) =~ '^[^|]*|\s*$' + let line = strpart(getline(a:lnum), a:cnum - 1) + "echomsg "DEBUG is_last_column> ".(line =~ s:rxSep.'\s*$' && line !~ s:rxSep.'.*'.s:rxSep.'\s*$') + return line =~ s:rxSep.'\s*$' && line !~ s:rxSep.'.*'.s:rxSep.'\s*$' + endfunction "}}} function! s:is_first_column(lnum, cnum) "{{{ let line = strpart(getline(a:lnum), 0, a:cnum - 1) - return line =~ '^\s*|[^|]*$' || line =~ '^\s*$' + "echomsg "DEBUG is_first_column> ".(line =~ '^\s*'.s:rxSep && line !~ '^\s*'.s:rxSep.'.*'.s:rxSep) + return line =~ '^\s*$' || (line =~ '^\s*'.s:rxSep && line !~ '^\s*'.s:rxSep.'.*'.s:rxSep) endfunction "}}} function! s:count_separators_up(lnum) "{{{ @@ -82,11 +100,10 @@ function! s:count_separators_down(lnum) "{{{ endfunction "}}} function! s:create_empty_row(cols) "{{{ - let first_cell = "| |" - let cell = " |" - let row = first_cell + let row = s:rxSep + let cell = " ".s:rxSep - for c in range(a:cols - 1) + for c in range(a:cols) let row .= cell endfor @@ -94,36 +111,71 @@ function! s:create_empty_row(cols) "{{{ endfunction "}}} function! s:create_row_sep(cols) "{{{ - let first_cell = "|---+" - let cell = "---+" - let last_cell = "---|" + let row = s:rxSep + let cell = "---".s:rxSep - if a:cols < 2 - return "|---|" - endif - - let row = first_cell - - for c in range(a:cols - 2) + for c in range(a:cols) let row .= cell endfor - let row .= last_cell - return row endfunction "}}} -function! s:get_values(line) "{{{ - return split(a:line, '\s*|\s*', 1)[1:-2] +function! vimwiki#tbl#get_cells(line) "{{{ + let result = [] + let cell = '' + let quote = '' + let state = 'NONE' + + " 'Simple' FSM + for idx in range(strlen(a:line)) + " The only way I know Vim can do Unicode... + let ch = a:line[idx] + if state == 'NONE' + if ch == '|' + let state = 'CELL' + endif + elseif state == 'CELL' + if ch == '[' || ch == '{' + let state = 'BEFORE_QUOTE_START' + let quote = ch + elseif ch == '|' + call add(result, vimwiki#u#trim(cell)) + let cell = "" + else + let cell .= ch + endif + elseif state == 'BEFORE_QUOTE_START' + if ch == '[' || ch == '{' + let state = 'QUOTE' + let quote .= ch + else + let state = 'CELL' + let cell .= quote.ch + let quote = '' + endif + elseif state == 'QUOTE' + if ch == ']' || ch == '}' + let state = 'BEFORE_QUOTE_END' + endif + let quote .= ch + elseif state == 'BEFORE_QUOTE_END' + if ch == ']' || ch == '}' + let state = 'CELL' + endif + let cell .= quote.ch + let quote = '' + endif + endfor + + if cell.quote != '' + call add(result, vimwiki#u#trim(cell.quote, '|')) + endif + return result endfunction "}}} function! s:col_count(lnum) "{{{ - let line = getline(a:lnum) - if !s:is_separator(line) - return len(split(line, '\s*|\s*', 1)[1:-2]) - else - return len(split(line, '-+-', 1)) - endif + return len(vimwiki#tbl#get_cells(getline(a:lnum))) endfunction "}}} function! s:get_indent(lnum) "{{{ @@ -155,7 +207,7 @@ function! s:get_rows(lnum) "{{{ let lower_rows = [] let lnum = a:lnum - 1 - while lnum > 1 + while lnum >= 1 let line = getline(lnum) if s:is_table(line) call add(upper_rows, [lnum, line]) @@ -186,7 +238,7 @@ function! s:get_cell_max_lens(lnum) "{{{ if s:is_separator(row) continue endif - let cells = s:get_values(row) + let cells = vimwiki#tbl#get_cells(row) for idx in range(len(cells)) let value = cells[idx] if has_key(max_lens, idx) @@ -219,17 +271,13 @@ function! s:cur_column() "{{{ if !s:is_table(line) return -1 endif - if s:is_separator(line) - let sep = '[+|]' - else - let sep = '|' - endif + " TODO: do we need conditional: if s:is_separator(line) let curs_pos = col('.') - let mpos = match(line, '|', 0) + let mpos = match(line, s:rxSep, 0) let col = -1 while mpos < curs_pos && mpos != -1 - let mpos = match(line, sep, mpos+1) + let mpos = match(line, s:rxSep, mpos+1) if mpos != -1 let col += 1 endif @@ -253,8 +301,8 @@ function! s:fmt_cell(cell, max_len) "{{{ endfunction "}}} function! s:fmt_row(line, max_lens, col1, col2) "{{{ - let new_line = '|' - let cells = s:get_values(a:line) + let new_line = s:rxSep + let cells = vimwiki#tbl#get_cells(a:line) for idx in range(len(cells)) if idx == a:col1 let idx = a:col2 @@ -262,12 +310,12 @@ function! s:fmt_row(line, max_lens, col1, col2) "{{{ let idx = a:col1 endif let value = cells[idx] - let new_line .= s:fmt_cell(value, a:max_lens[idx]).'|' + let new_line .= s:fmt_cell(value, a:max_lens[idx]).s:rxSep endfor let idx = len(cells) while idx < len(a:max_lens) - let new_line .= s:fmt_cell('', a:max_lens[idx]).'|' + let new_line .= s:fmt_cell('', a:max_lens[idx]).s:rxSep let idx += 1 endwhile return new_line @@ -282,17 +330,16 @@ function! s:fmt_cell_sep(max_len) "{{{ endfunction "}}} function! s:fmt_sep(max_lens, col1, col2) "{{{ - let sep = '|' + let new_line = s:rxSep for idx in range(len(a:max_lens)) if idx == a:col1 let idx = a:col2 elseif idx == a:col2 let idx = a:col1 endif - let sep .= s:fmt_cell_sep(a:max_lens[idx]).'+' + let new_line .= s:fmt_cell_sep(a:max_lens[idx]).s:rxSep endfor - let sep = substitute(sep, '+$', '|', '') - return sep + return new_line endfunction "}}} "}}} @@ -300,41 +347,94 @@ endfunction "}}} function! s:kbd_create_new_row(cols, goto_first) "{{{ let cmd = "\o".s:create_empty_row(a:cols) let cmd .= "\:call vimwiki#tbl#format(line('.'))\" + let cmd .= "\0" if a:goto_first - let cmd .= "\0:call search('|', 'c', line('.'))\la" + let cmd .= ":call search('\\(".s:rxSep."\\)\\zs', 'c', line('.'))\" else - let cmd .= "0".(col('.')-1)."lT|a" + let cmd .= (col('.')-1)."l" + let cmd .= ":call search('\\(".s:rxSep."\\)\\zs', 'bc', line('.'))\" endif + let cmd .= "a" + return cmd endfunction "}}} function! s:kbd_goto_next_row() "{{{ - let cmd = "\jt|T|a" + let cmd = "\j" + let cmd .= ":call search('.\\(".s:rxSep."\\)', 'c', line('.'))\" + let cmd .= ":call search('\\(".s:rxSep."\\)\\zs', 'bc', line('.'))\" + let cmd .= "a" return cmd endfunction "}}} function! s:kbd_goto_prev_row() "{{{ - let cmd = "\jt|T|a" + let cmd = "\k" + let cmd .= ":call search('.\\(".s:rxSep."\\)', 'c', line('.'))\" + let cmd .= ":call search('\\(".s:rxSep."\\)\\zs', 'bc', line('.'))\" + let cmd .= "a" return cmd endfunction "}}} -function! s:kbd_goto_next_col(last) "{{{ - if a:last +" Used in s:kbd_goto_next_col +function! vimwiki#tbl#goto_next_col() "{{{ + let curcol = virtcol('.') + let lnum = line('.') + let newcol = s:get_indent(lnum) + let max_lens = s:get_cell_max_lens(lnum) + for cell_len in values(max_lens) + if newcol >= curcol-1 + break + endif + let newcol += cell_len + 3 " +3 == 2 spaces + 1 separator |... + endfor + let newcol += 2 " +2 == 1 separator + 1 space |la" - else - let cmd = "\:call search('|', 'c', line('.'))\la" + let cmd .= seps."j0" endif + let cmd .= ":call vimwiki#tbl#goto_next_col()\a" return cmd endfunction "}}} -function! s:kbd_goto_prev_col(first) "{{{ - if a:first +" Used in s:kbd_goto_prev_col +function! vimwiki#tbl#goto_prev_col() "{{{ + let curcol = virtcol('.') + let lnum = line('.') + let newcol = s:get_indent(lnum) + let max_lens = s:get_cell_max_lens(lnum) + let prev_cell_len = 0 + echom string(max_lens) + for cell_len in values(max_lens) + let delta = cell_len + 3 " +3 == 2 spaces + 1 separator |... + if newcol + delta > curcol-1 + let newcol -= (prev_cell_len + 3) " +3 == 2 spaces + 1 separator |... + break + elseif newcol + delta == curcol-1 + break + endif + let prev_cell_len = cell_len + let newcol += delta + endfor + let newcol += 2 " +2 == 1 separator + 1 space |la" - else - let cmd = "\2F|la" + let cmd .= seps."k" + let cmd .= "$" endif + let cmd .= ":call vimwiki#tbl#goto_prev_col()\a" + " let cmd .= ":call search('\\(".s:rxSep."\\)\\zs', 'b', line('.'))\" + " let cmd .= "a" + "echomsg "DEBUG kbd_goto_prev_col> ".cmd return cmd endfunction "}}} @@ -348,7 +448,7 @@ function! vimwiki#tbl#kbd_cr() "{{{ endif if s:is_separator(getline(lnum+1)) || !s:is_table(getline(lnum+1)) - let cols = len(s:get_values(getline(lnum))) + let cols = len(vimwiki#tbl#get_cells(getline(lnum))) return s:kbd_create_new_row(cols, 0) else return s:kbd_goto_next_row() @@ -362,11 +462,13 @@ function! vimwiki#tbl#kbd_tab() "{{{ endif let last = s:is_last_column(lnum, col('.')) - if last && !s:is_table(getline(lnum+1)) - let cols = len(s:get_values(getline(lnum))) + let is_sep = s:is_separator_tail(getline(lnum)) + "echomsg "DEBUG kbd_tab> last=".last.", is_sep=".is_sep + if (is_sep || last) && !s:is_table(getline(lnum+1)) + let cols = len(vimwiki#tbl#get_cells(getline(lnum))) return s:kbd_create_new_row(cols, 1) endif - return s:kbd_goto_next_col(last) + return s:kbd_goto_next_col(is_sep || last) endfunction "}}} function! vimwiki#tbl#kbd_shift_tab() "{{{ @@ -376,10 +478,12 @@ function! vimwiki#tbl#kbd_shift_tab() "{{{ endif let first = s:is_first_column(lnum, col('.')) - if first && !s:is_table(getline(lnum-1)) + let is_sep = s:is_separator_tail(getline(lnum)) + "echomsg "DEBUG kbd_tab> ".first + if (is_sep || first) && !s:is_table(getline(lnum-1)) return "" endif - return s:kbd_goto_prev_col(first) + return s:kbd_goto_prev_col(is_sep || first) endfunction "}}} function! vimwiki#tbl#format(lnum, ...) "{{{ @@ -462,7 +566,12 @@ endfunction "}}} " TODO: move_column_left and move_column_right are good candidates to be " refactored. function! vimwiki#tbl#move_column_left() "{{{ - if !s:is_table(getline('.')) + + "echomsg "DEBUG move_column_left: " + + let line = getline('.') + + if !s:is_table(line) return endif @@ -474,16 +583,28 @@ function! vimwiki#tbl#move_column_left() "{{{ if cur_col > 0 call vimwiki#tbl#format(line('.'), cur_col-1, cur_col) call cursor(line('.'), 1) - if !s:is_separator(getline('.')) - call search('\%(|[^|]\+\)\{'.(cur_col-1).'}| .', 'eW') - else - call search('|\%([^+]\++\)\{'.(cur_col-1).'}--', 'eW') - endif + + let sep = '\('.s:rxSep.'\).\zs' + let mpos = -1 + let col = -1 + while col < cur_col-1 + let mpos = match(line, sep, mpos+1) + if mpos != -1 + let col += 1 + else + break + endif + endwhile + endif + endfunction "}}} function! vimwiki#tbl#move_column_right() "{{{ - if !s:is_table(getline('.')) + + let line = getline('.') + + if !s:is_table(line) return endif @@ -495,16 +616,41 @@ function! vimwiki#tbl#move_column_right() "{{{ if cur_col < s:col_count(line('.'))-1 call vimwiki#tbl#format(line('.'), cur_col, cur_col+1) call cursor(line('.'), 1) - if !s:is_separator(getline('.')) - call search('\%(|[^|]\+\)\{'.(cur_col+1).'}| .', 'eW') - else - call search('|\%([^+]\++\)\{'.(cur_col+1).'}--', 'eW') - endif + + let sep = '\('.s:rxSep.'\).\zs' + let mpos = -1 + let col = -1 + while col < cur_col+1 + let mpos = match(line, sep, mpos+1) + if mpos != -1 + let col += 1 + else + break + endif + endwhile + endif + endfunction "}}} function! vimwiki#tbl#get_rows(lnum) "{{{ return s:get_rows(a:lnum) endfunction "}}} +function! vimwiki#tbl#is_table(line) "{{{ + return s:is_table(a:line) +endfunction "}}} + +function! vimwiki#tbl#is_separator(line) "{{{ + return s:is_separator(a:line) +endfunction "}}} + +function! vimwiki#tbl#cell_splitter() "{{{ + return s:cell_splitter() +endfunction "}}} + +function! vimwiki#tbl#sep_splitter() "{{{ + return s:sep_splitter() +endfunction "}}} + "}}} diff --git a/autoload/vimwiki/u.vim b/autoload/vimwiki/u.vim new file mode 100644 index 0000000..9680a27 --- /dev/null +++ b/autoload/vimwiki/u.vim @@ -0,0 +1,77 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" Vimwiki autoload plugin file +" Utility functions +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ + +function! vimwiki#u#trim(string, ...) "{{{ + let chars = '' + if a:0 > 0 + let chars = a:1 + endif + let res = substitute(a:string, '^[[:space:]'.chars.']\+', '', '') + let res = substitute(res, '[[:space:]'.chars.']\+$', '', '') + return res +endfunction "}}} + + +" Builtin cursor doesn't work right with unicode characters. +function! vimwiki#u#cursor(lnum, cnum) "{{{ + exe a:lnum + exe 'normal! 0'.a:cnum.'|' +endfunction "}}} + +function! vimwiki#u#is_windows() "{{{ + return has("win32") || has("win64") || has("win95") || has("win16") +endfunction "}}} + +function! vimwiki#u#chomp_slash(str) "{{{ + return substitute(a:str, '[/\\]\+$', '', '') +endfunction "}}} + +function! vimwiki#u#time(starttime) "{{{ + " measure the elapsed time and cut away miliseconds and smaller + return matchstr(reltimestr(reltime(a:starttime)),'\d\+\(\.\d\d\)\=') +endfunction "}}} + +function! vimwiki#u#path_norm(path) "{{{ + " /-slashes + let path = substitute(a:path, '\', '/', 'g') + " treat multiple consecutive slashes as one path separator + let path = substitute(path, '/\+', '/', 'g') + " ensure that we are not fooled by a symbolic link + return resolve(path) +endfunction "}}} + +function! vimwiki#u#is_link_to_dir(link) "{{{ + " Check if link is to a directory. + " It should be ended with \ or /. + if a:link =~ '.\+[/\\]$' + return 1 + endif + return 0 +endfunction " }}} + +function! vimwiki#u#count_first_sym(line) "{{{ + let first_sym = matchstr(a:line, '\S') + return len(matchstr(a:line, first_sym.'\+')) +endfunction "}}} + +" return longest common path prefix of 2 given paths. +" '~/home/usrname/wiki', '~/home/usrname/wiki/shmiki' => '~/home/usrname/wiki' +function! vimwiki#u#path_common_pfx(path1, path2) "{{{ + let p1 = split(a:path1, '[/\\]', 1) + let p2 = split(a:path2, '[/\\]', 1) + + let idx = 0 + let minlen = min([len(p1), len(p2)]) + while (idx < minlen) && (p1[idx] ==? p2[idx]) + let idx = idx + 1 + endwhile + if idx == 0 + return '' + else + return join(p1[: idx-1], '/') + endif +endfunction "}}} + diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index 5d10190..62dbbd1 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -9,7 +9,7 @@ |___| |___| |_| |_||__| |__||___| |___| |_||___| ~ - Version: 1.2 + Version: 2.0 'stu' ============================================================================== CONTENTS *vimwiki-contents* @@ -31,15 +31,23 @@ CONTENTS *vimwiki-contents* 5.5. Lists |vimwiki-syntax-lists| 5.6. Tables |vimwiki-syntax-tables| 5.7. Preformatted text |vimwiki-syntax-preformatted| - 5.8. Blockquotes |vimwiki-syntax-blockquotes| - 5.9. Comments |vimwiki-syntax-comments| - 5.10. Horizontal line |vimwiki-syntax-hr| + 5.8. Mathematical formulae |vimwiki-syntax-math| + 5.9. Blockquotes |vimwiki-syntax-blockquotes| + 5.10. Comments |vimwiki-syntax-comments| + 5.11. Horizontal line |vimwiki-syntax-hr| + 5.12. Schemes |vimwiki-syntax-schemes| + 5.13. Transclusions |vimwiki-syntax-transclude| + 5.14. Thumbnails |vimwiki-syntax-thumbnails| 6. Folding/Outline |vimwiki-folding| 7. Placeholders |vimwiki-placeholders| 8. Todo lists |vimwiki-todo-lists| 9. Tables |vimwiki-tables| 10. Diary |vimwiki-diary| 11. Options |vimwiki-options| + 11.1. Registered Wiki |vimwiki-register-wiki| + 11.2. Temporary Wiki |vimwiki-temporary-wiki| + 11.3. Per-Wiki Options |vimwiki-local-options| + 11.4. Global Options |viwmiki-global-options| 12. Help |vimwiki-help| 13. Developers |vimwiki-developers| 14. Changelog |vimwiki-changelog| @@ -58,26 +66,29 @@ With vimwiki you can: - write documentation. To do a quick start press ww (this is usually \ww) to go to your index -wiki file. By default it is located in: > +wiki file. By default it is located in: > ~/vimwiki/index.wiki Feed it with the following example: = My knowledge base = - * MyUrgentTasks -- things to be done _yesterday_!!! - * ProjectGutenberg -- good books are power. - * ScratchPad -- various temporary stuff. + * Tasks -- things to be done _yesterday_!!! + * Project Gutenberg -- good books are power. + * Scratchpad -- various temporary stuff. +Place your cursor on 'Tasks' and press Enter to create a link. Once pressed, +'Tasks' will become '[[Tasks]]' -- a vimwiki link. Press Enter again to +open it. Edit the file, save it, and then press Backspace to jump back to your +index. -Notice that ProjectGutenberg, MyUrgentTasks and ScratchPad are highlighted as -errors. These are links in CamelCase form that do not exists yet. (CamelCase -form -- capitalized word connected with other capitalized words) - -Place cursor on ProjectGutenberg and press . Now you are in -ProjectGutenberg. Edit and save it, then press Backspace to return to previous -wiki file. You should see the difference now -- ProjectGutenberg is -highlighted as a link. +A vimwiki link can be constructed from more than one word. Just visually +select the words to be linked and press Enter. Try it with 'Project +Gutenberg'. The result should look something like: += My knowledge base = + * [[Tasks]] -- things to be done _yesterday_!!! + * [[Project Gutenberg]] -- good books are power. + * Scratchpad -- various temporary stuff. ============================================================================== 2. Prerequisites *vimwiki-prerequisites* @@ -107,7 +118,7 @@ There are global and local mappings in vimwiki. 3ww opens the third wiki from |g:vimwiki_list|. etc. To remap: > - :map w VimwikiIndex + :nmap w VimwikiIndex < See also |:VimwikiIndex| @@ -121,7 +132,7 @@ See also |:VimwikiIndex| 3wt tabopens the third wiki from |g:vimwiki_list|. etc. To remap: > - :map t VimwikiTabIndex + :nmap t VimwikiTabIndex < See also |:VimwikiTabIndex| @@ -129,7 +140,7 @@ See also |:VimwikiTabIndex| ws or VimwikiUISelect List and select available wikies. To remap: > - :map wq VimwikiUISelect + :nmap wq VimwikiUISelect < See also |:VimwikiUISelect| @@ -144,7 +155,7 @@ See also |:VimwikiUISelect| |g:vimwiki_list|. etc. To remap: > - :map i VimwikiDiaryIndex + :nmap i VimwikiDiaryIndex See also |:VimwikiDiaryIndex| @@ -162,7 +173,7 @@ See also |:VimwikiDiaryIndex| from |g:vimwiki_list|. etc. To remap: > - :map d VimwikiMakeDiaryNote + :nmap d VimwikiMakeDiaryNote < See also |:VimwikiMakeDiaryNote| @@ -180,7 +191,7 @@ See also |:VimwikiMakeDiaryNote| wiki from |g:vimwiki_list|. etc. To remap: > - :map dt VimwikiTabMakeDiaryNote + :nmap dt VimwikiTabMakeDiaryNote < See also |:VimwikiTabMakeDiaryNote| @@ -193,27 +204,35 @@ NORMAL MODE *vimwiki-local-mappings* wh Convert current wiki page to HTML. Maps to |:Vimwiki2HTML| To remap: > - :map wc Vimwiki2HTML + :nmap wc Vimwiki2HTML < *vimwiki_whh* whh Convert current wiki page to HTML and open it in webbrowser. Maps to |:Vimwiki2HTML| To remap: > - :map wcc Vimwiki2HTMLBrowse + :nmap wcc Vimwiki2HTMLBrowse +< + *vimwiki_wi* +wi Update diary section (delete old, insert new) + Only works from the diary index. + Maps to |:VimwikiDiaryGenerateLinks| + To remap: > + :nmap wcr VimwikiDiaryGenerateLinks < *vimwiki_* - Follow wiki link (create target wiki page if needed). + Follow/create wiki link (create target wiki page if + needed). Maps to |:VimwikiFollowLink|. To remap: > - :map wf VimwikiFollowLink + :nmap wf VimwikiFollowLink < *vimwiki_* Split and follow (create target wiki page if needed). May not work in some terminals. Remapping could help. Maps to |:VimwikiSplitLink|. To remap: > - :map we VimwikiSplitLink + :nmap we VimwikiSplitLink < *vimwiki_* Vertical split and follow (create target wiki page if @@ -221,7 +240,7 @@ NORMAL MODE *vimwiki-local-mappings* May not work in some terminals. Remapping could help. Maps to |:VimwikiVSplitLink|. To remap: > - :map wq VimwikiVSplitLink + :nmap wq VimwikiVSplitLink < *vimwiki_* *vimwiki_* , Follow wiki link (create target wiki page if needed), @@ -229,53 +248,87 @@ NORMAL MODE *vimwiki-local-mappings* May not work in some terminals. Remapping could help. Maps to |:VimwikiTabnewLink|. To remap: > - :map wt VimwikiTabnewLink + :nmap wt VimwikiTabnewLink < *vimwiki_* Go back to previous wiki page. Maps to |:VimwikiGoBackLink|. To remap: > - :map wb VimwikiGoBackLink + :nmap wb VimwikiGoBackLink < *vimwiki_* Find next link on the current page. Maps to |:VimwikiNextLink|. To remap: > - :map wn VimwikiNextLink + :nmap wn VimwikiNextLink < *vimwiki_* Find previous link on the current page. Maps to |:VimwikiPrevLink|. To remap: > - :map wp VimwikiPrevLink + :nmap wp VimwikiPrevLink < *vimwiki_wd* wd Delete wiki page you are in. Maps to |:VimwikiDeleteLink|. To remap: > - :map dd VimwikiDeleteLink + :nmap dd VimwikiDeleteLink < *vimwiki_wr* wr Rename wiki page you are in. Maps to |:VimwikiRenameLink|. To remap: > - :map rr VimwikiRenameLink + :nmap rr VimwikiRenameLink < *vimwiki_* Toggle list item on/off (checked/unchecked) Maps to |:VimwikiToggleListItem|. To remap: > - :map tt VimwikiToggleListItem + :nmap tt VimwikiToggleListItem < See |vimwiki-todo-lists|. *vimwiki_=* = Add header level. Create if needed. There is nothing to indent with '==' command in vimwiki, so it should be ok to use '=' here. - + To remap: > + :nmap == VimwikiAddHeaderLevel +< *vimwiki_-* - Remove header level. + To remap: > + :nmap -- VimwikiRemoveHeaderLevel +< + *vimwiki_+* ++ Create and/or decorate links. Depending on the + context, this command will: convert words into + Wikilinks; convert raw URLs into Wikilinks; and add + placeholder text to Wiki- or Weblinks that are missing + descriptions. Can be activated in normal mode with + the cursor over a word or link, or in visual mode with + the selected text . + *vimwiki_glm* +glm Increase the indent of a single-line list item. + + *vimwiki_gll* +gll Decrease the indent of a single-line list item. + + *vimwiki_glstar* *vimwiki_gl8* +gl* or gl8 Switch or insert a "*" symbol. Only available in + supported syntaxes. + + *vimwiki_gl#* *vimwiki_gl3* +gl# or gl3 Switch or insert a "#" symbol. Only available in + supported syntaxes. + + *vimwiki_gl-* +gl- Switch or insert a "-" symbol. Only available in + supported syntaxes. + + *vimwiki_gl1* +gl1 Switch or insert a "1." symbol. Only available in + supported syntaxes. *vimwiki_gqq* *vimwiki_gww* gqq Format table. If you made some changes to a table @@ -286,13 +339,13 @@ gww will reformat it. Move current table column to the left. See |:VimwikiTableMoveColumnLeft| To remap: > - :map wtl VimwikiTableMoveColumnLeft + :nmap wtl VimwikiTableMoveColumnLeft < *vimwiki_* Move current table column to the right. See |:VimwikiTableMoveColumnRight| To remap: > - :map wtr VimwikiTableMoveColumnRight + :nmap wtr VimwikiTableMoveColumnRight < *vimwiki_* Open the previous day's diary link if available. @@ -326,9 +379,7 @@ INSERT MODE *vimwiki-table-mappings* *vimwiki_i_* Go to the next table cell, create a new row if on the last cell. - - *vimwiki_i_* - Insert
    and a newline. +See |g:vimwiki_table_mappings| to turn them off. ------------------------------------------------------------------------------ @@ -408,18 +459,26 @@ ic An inner column in a table. Rename the wiki page that you are in. *:Vimwiki2HTML* - Convert current wiki page to HTML. + Convert current wiki page to HTML using vimwiki's own converter or a + user-supplied script (see |vimwiki-option-custom_wiki2html|). *:Vimwiki2HTMLBrowse* - Convert current wiki page to HTML and open in in webbrowser. + Convert current wiki page to HTML and open it in webbrowser. *:VimwikiAll2HTML* Convert all wiki pages to HTML. + Default css file (style.css) is created if there is no one. *:VimwikiToggleListItem* Toggle list item on/off (checked/unchecked) See |vimwiki-todo-lists|. +*:VimwikiListChangeLevel* CMD + Change the nesting level, or symbol, for a single-line list item. + CMD may be ">>" or "<<" to change the indentation of the item, or + one of the syntax-specific bullets: "*", "#", "1.", "-". + See |vimwiki-todo-lists|. + *:VimwikiSearch* /pattern/ *:VWS* /pattern/ Search for /pattern/ in all files of current wiki. @@ -427,6 +486,14 @@ ic An inner column in a table. To display next match use |:lnext| command. To display previous match use |:lprevious| command. +*:VimwikiBacklinks* +*:VWB* + Search for wikilinks to the [[current wiki page]] + in all files of current wiki. + To display all matches use |:lopen| command. + To display next match use |:lnext| command. + To display previous match use |:lprevious| command. + *:VimwikiTable* Create a table with 5 cols and 2 rows. @@ -443,7 +510,7 @@ ic An inner column in a table. Example: > | head1 | head2 | head3 | head4 | head5 | - |--------+--------+--------+--------+--------| + |--------|--------|--------|--------|--------| | value1 | value2 | value3 | value4 | value5 | @@ -451,14 +518,14 @@ ic An inner column in a table. :VimwikiTableMoveColumnRight | head2 | head1 | head3 | head4 | head5 | - |--------+--------+--------+--------+--------| + |--------|--------|--------|--------|--------| | value2 | value1 | value3 | value4 | value5 | Cursor is on 'head3'. :VimwikiTableMoveColumnLeft | head2 | head3 | head1 | head4 | head5 | - |--------+--------+--------+--------+--------| + |--------|--------|--------|--------|--------| | value2 | value3 | value1 | value4 | value5 | < @@ -468,6 +535,9 @@ ic An inner column in a table. *:VimwikiGenerateLinks* Insert all available links into current buffer. +*:VimwikiDiaryGenerateLinks* + Delete old, insert new diary section into diary index file. + *:VimwikiDiaryNextDay* Open next day diary link if available. Mapped to . @@ -480,14 +550,24 @@ ic An inner column in a table. ============================================================================== 5. Wiki syntax *vimwiki-syntax* + There are a lot of different wikies out there. Most of them have their own -syntax and vimwiki is not an exception here. Default vimwiki's syntax is a -subset of google's wiki syntax markup. +syntax and vimwiki's default syntax is not an exception here. -There is MediaWiki syntax file included in the distribution (it doesn't have -all the fancy stuff original MediaWiki syntax has though). -See |vimwiki-option-syntax|. +Vimwiki has evolved its own syntax that closely resembles google's wiki +markup. This syntax is described in detail below. +Vimwiki also supports alternative syntaxes, like Markdown and MediaWiki, to +varying degrees; see |vimwiki-option-syntax|. Static elements like headers, +quotations, and lists are customized in syntax/vimwiki_xxx.vim, where xxx +stands for the chosen syntax. + +Interactive elements such as links and vimwiki commands are supported by +definitions and routines in syntax/vimwiki_xxx_custom.vim and +autoload/vimwiki/xxx_base.vim. Currently, only Markdown includes this level +of support. + +Vimwiki2HTML is currently functional only for the default syntax. ------------------------------------------------------------------------------ 5.1. Typefaces *vimwiki-syntax-typefaces* @@ -505,81 +585,48 @@ text should be decorated: > ------------------------------------------------------------------------------ 5.2. Links *vimwiki-syntax-links* -Internal links~ -WikiWords: > - CapitalizedWordsConnected - -You can prevent linking of WikiWords by adding an exclamation mark in front of -them: > - !CapitalizedWordsConnected - -Or disable it completely with |g:vimwiki_camel_case|. +Wikilinks~ Link with spaces in it: > [[This is a link]] or: > [[This is a link source|Description of the link]] -or: > - [[This is a link source][Description of the link]] -External links~ -Plain link: > - http://code.google.com/p/vimwiki - mailto:habamax@gmail.com - ftp://vim.org +Links to directories (ending with a "/") are also supported: > + [[/home/somebody/|Home Directory]] -Link with description: > - [http://habamax.ru/blog habamax home page] - [mailto:habamax@gmail.com Drop a line to Maxim Kim] +Use |g:vimwiki_dir_link| to control the behaviour when opening directories. -Images and image links~ -An image link is a link to a file with a jpg, png or gif extension. -Plain image link: > - http://someaddr.com/picture.jpg -in HTML: > - +Raw URLs~ -Link to a local image: > - [[images/pabloymoira.jpg]] -in HTML: > - -Path to image (ie. images/pabloymoira.jpg) is relative to -|vimwiki-option-path_html|. +Raw URLs are also supported: > + http://code.google.com/p/vimwiki + mailto:habamax@gmail.com + ftp://vim.org -Double bracketed link to an image: > - [[http://habamax.ru/blog/wp-content/uploads/2009/01/2740254sm.jpg]] -in HTML: > - -Double bracketed link to an image with description text: > - [[http://habamax.ru/blog/wp-content/uploads/2009/01/2740254sm.jpg|dance]] -in HTML: > -
    dance +Markdown Links~ -Double bracketed link to an image with alternate text: > - [[http://habamax.ru/blog/wp-content/uploads/2009/01/2740254sm.jpg|dance|]] -in HTML: > - dance +These links are only available for Markdown syntax. See +http://daringfireball.net/projects/markdown/syntax#link. -Double bracketed link to an image with alternate text and some style: > - [[http://helloworld.com/blabla.jpg|cool stuff|width:150px; height: 120px;]] -in HTML: > - cool stuff +Inline links: > + [Looks like this](URL) -Double bracketed link to an image without alternate text and some style: > - [[http://helloworld.com/blabla.jpg||width:150px; height: 120px;]] -in HTML: > - +Image links: > + ![Looks like this](URL) -Thumbnail link: > - [http://someaddr.com/bigpicture.jpg http://someaddr.com/thumbnail.jpg] -or > - [[http://someaddr.com/bigpicture.jpg|http://someaddr.com/thumbnail.jpg]] -in HTML: > - - | Year | Temperature (low) | Temperature (high) | - |------+-------------------+--------------------| + |------|-------------------|--------------------| | 1900 | -10 | 25 | | 1910 | -15 | 30 | | 1920 | -10 | 32 | @@ -712,7 +759,7 @@ For example: > In HTML the following part > | Year | Temperature (low) | Temperature (high) | - |------+-------------------+--------------------| + |------|-------------------|--------------------| > is higlighted as a table header. @@ -730,9 +777,6 @@ For example: > See |vimwiki-tables| for more details on how to manage tables. -Note: You can not use [[link|description]] type of links in tables. Use -[[link][description]] instead. - ------------------------------------------------------------------------------ 5.7. Preformatted text *vimwiki-syntax-preformatted* @@ -772,7 +816,72 @@ See |vimwiki-option-nested_syntaxes| ------------------------------------------------------------------------------ -5.8. Blockquotes *vimwiki-syntax-blockquotes* +5.8. Mathematical formulae *vimwiki-syntax-math* + +Mathematical formulae are highlighted, and can be rendered in HTML using the +powerful open source display engine MathJax (http://www.mathjax.org/). + +There are three supported syntaxes, which are inline, block display and +block environment. + +Inline math is for short formulae within text. It is enclosed by single +dollar signs, e.g.: + $ \sum_i a_i^2 = 1 $ + +Block display creates a centered formula with some spacing before and after +it. It must start with a line including only {{$, then an arbitrary number +of mathematical text are allowed, and it must end with a line including only +}}$. +E.g.: + {{$ + \sum_i a_i^2 + = + 1 + }}$ + +Note: no matter how many lines are used in the text file, the HTML will +compress it to *one* line only. + +Block environment is similar to block display, but is able to use specific +LaTeX environments, such as 'align'. The syntax is the same as for block +display, except for the first line which is {{$%environment%. +E.g.: + {{$%align% + \sum_i a_i^2 &= 1 + 1 \\ + &= 2. + }}$ + +Similar compression rules for the HTML page hold (as MathJax interprets the +LaTeX code). + +Note: the highlighting in VIM is automatic. For the rendering in HTML, you +have two *alternative* options: + +1. using the MathJax server for rendering (needs an internet connection). +Add to your HTML template the following line: + + + +2. installing MathJax locally (faster, no internet required). Choose a +folder on your hard drive and save MathJax in it. Then add to your HTML +template the following line: + + + +where is the folder on your HD, as a relative path to the +template folder. For instance, a sensible folder structure could be: + +- wiki + - text + - html + - templates + - mathjax + +In this case, would be "../mathjax" (without quotes). + + +------------------------------------------------------------------------------ +5.9. Blockquotes *vimwiki-syntax-blockquotes* Text started with 4 or more spaces is a blockquote. @@ -782,7 +891,7 @@ Text started with 4 or more spaces is a blockquote. ------------------------------------------------------------------------------ -5.9. Comments *vimwiki-syntax-comments* +5.10. Comments *vimwiki-syntax-comments* Text line started with %% is a comment. E.g.: > @@ -791,12 +900,128 @@ E.g.: > ------------------------------------------------------------------------------ -5.10. Horizontal line *vimwiki-syntax-hr* +5.11. Horizontal line *vimwiki-syntax-hr* 4 or more dashes at the start of the line is a 'horizontal line' (
    ): > ---- < +------------------------------------------------------------------------------ +5.12. Schemes *vimwiki-syntax-schemes* + +In addition to standard web schemes (e.g. `http:`, `https:`, `ftp:`, etc.) a +number of special schemes are supported: "wiki#:", "local:", "diary:", +"file:", and schemeless. + +While "wiki:#", "diary" and schemeless links are automatically opened in Vi, +all other links are opened with the system command. To customize this +behavior, see |VimwikiLinkHandler|. + +Interwiki:~ + +If you maintain more than one wiki, you can create interwiki links between them +by adding a numbered prefix "wiki#:" in front of a link: > + [[wiki#:This is a link]] +or: > + [[wiki#:This is a link source|Description of the link]] + +The number "#", in the range 0..N-1, identifies the destination wiki in +|g:vimwiki_list|. + +Diary:~ + +The diary scheme is used to concisely link to diary entries: > + [[diary:2012-03-05]] + +This scheme precludes explicit inclusion of |vimwiki-option-diary_rel_path|, +and is most useful on subwiki pages to avoid links such as: > + [[../../diary/2012-03-05]] + +Local:~ + +A local resource that is not a wiki page may be specified with a path relative +to the current page: > + [[local:../assets/data.csv|data (CSV)]] + +When followed or converted to HTML, extensions of local-scheme links are not +modified. + +File:~ + +The file scheme allows you to directly link to arbitray resources using +absolute paths and extensions: > + [[file:///home/somebody/a/b/c/music.mp3]] + +Schemeless:~ + +Schemeless URLs, which are the default, are treated internally as "wiki#:" +URLs in all respects except when converted to Html. + +Schemeless links convert to plain relative path URLs, nearly verbatim: > + relpath/wikipage.html + +The "wiki#:", "local:", and "diary:" schemes use absolute paths as URLs: > + file:///abs_path_to_html#/relpath/wikipage.html + +When |vimwiki-option-maxhi| equals 1, a distinct highlighting style is used to +identify schemeless links whose targets are not found. All other links appear +as regular links even if the files to which they refer do not exist. + + +------------------------------------------------------------------------------ +5.13. Transclusions *vimwiki-syntax-transclude* + +Transclusion (Wiki-Include) Links~ + +Links that use "{{" and "}}" delimiters signify content that is to be +included into the Html output, rather than referenced via hyperlink. + +Wiki-include URLs may use any of the supported schemes, may be absolute or +relative, and need not end with an extension. + +The primary purpose for wiki-include links is to include images. + +Transclude from a local URL: > + {{local:../../images/vimwiki_logo.png}} +or from a universal URL: > + {{http://vimwiki.googlecode.com/hg/images/vimwiki_logo.png}} + +Transclude image with alternate text: > + {{http://vimwiki.googlecode.com/hg/images/vimwiki_logo.png|Vimwiki}} +in HTML: > + Vimwiki + +Transclude image with alternate text and some style: > + {{http://.../vimwiki_logo.png|cool stuff|style="width:150px; height: 120px;"}} +in HTML: > + cool stuff + +Transclude image _without_ alternate text and with css class: > + {{http://.../vimwiki_logo.png||class="center flow blabla"}} +in HTML: > + + +A trial feature allows you to supply your own handler for wiki-include links. +See |VimwikiWikiIncludeHandler|. + + +------------------------------------------------------------------------------ +5.14. Thumbnails *vimwiki-syntax-thumbnails* + +Thumbnail links~ +> +Thumbnail links are constructed like this: > + [[http://someaddr.com/bigpicture.jpg|{{http://someaddr.com/thumbnail.jpg}}]] + +in HTML: > +
    + + let g:vimwiki_ext2syntax = {'.md': 'markdown', + \ '.mkd': 'markdown', + \ '.wiki': 'media'} + +An extension that is registered with vimwiki can trigger creation of a +|vimwiki-temporary-wiki| with the associated syntax. File extensions used in +|g:vimwiki_list| are automatically registered with vimwiki using the default +syntax. + +Default: {'.md': 'markdown'} ------------------------------------------------------------------------------ *g:vimwiki_auto_checkbox* @@ -1439,31 +1755,6 @@ etc. Default: 'Vimwiki' ------------------------------------------------------------------------------- -*g:vimwiki_stripsym* - -Change strip symbol -- in Windows you cannot use /*?<>:" in filenames, so -vimwiki replaces them with a neutral symbol (_ is default): > - let g:vimwiki_stripsym = '_' - -You can change it to a for example: > - let g:vimwiki_stripsym = ' ' - - ------------------------------------------------------------------------------- -*g:vimwiki_badsyms* - -If you do not like spaces in filenames (as some vimwiki users do), you can set -up bad symbols to include spaces, so that they are also converted: -|g:vimwiki_stripsym|: > - let g:vimwiki_badsyms = ' ' - -Now files for all [[links with spaces]] would be created like -'links_with_spaces'. - -This option is a complement one to |g:vimwiki_stripsym|. - - ------------------------------------------------------------------------------ *g:vimwiki_listsyms* @@ -1511,30 +1802,6 @@ Value Description~ Default: 0 ------------------------------------------------------------------------------- -*g:vimwiki_fold_trailing_empty_lines* - -Fold or do not fold empty lines between folded headers. - -Value Description~ -0 Fold only one empty line. Leave the rest of the empty lines. -1 Fold in all empty lines. - -Default: 0 - - ------------------------------------------------------------------------------- -*g:vimwiki_camel_case* - -If you do not want WikiWord to be a link, this setting is just for you. - -Value Description~ -0 Do not make links from CamelCased words. -1 Make links from CamelCased words. - -Default: 1 - - ------------------------------------------------------------------------------ *g:vimwiki_list_ignore_newline* @@ -1562,34 +1829,110 @@ Default: 1 ------------------------------------------------------------------------------ -*g:vimwiki_browsers* *VimwikiWeblinkHandler* +*VimwikiLinkHandler* -You can open external weblinks in a webbrowser. Webbrowsers are listed in -|g:vimwiki_browsers|. +A customizable link handler, |VimwikiLinkHandler|, can be defined to override +Vimwiki's opening of links. Each recognized link, whether it is a wikilink, +wiki-include link or a weblink, is first passed to |VimwikiLinkHandler| to see +if it can be handled. The return value 1/0 indicates success. -For win32 it is: chrome, opera, firefox and explorer. -For other OSes it is: opera, firefox and konqueror. +If the link is not handled successfully, the behaviour of Vimwiki depends on +the scheme. Wiki:, diary: or schemeless links are opened in Vim. All others, +including local: and file: schemes, are opened with a system default handler; +i.e. Linux (!xdg-open), Mac (!open), and Windows (!start). -The first available browser from the list is used to open the weblink. -If you have opera and firefox and want weblinks to be opened in the latter, -just specify: > - let g:vimwiki_browsers=['C:\Program Files\Firefox\firefox.exe'] +You can redefine |VimwikiLinkHandler| function to do something else: > -or redefine VimwikiWeblinkHandler function: > - function! VimwikiWeblinkHandler(weblink) - let browser = 'C:\Program Files\Firefox\firefox.exe' - execute '!start "'.browser.'" ' . a:weblink + function! VimwikiLinkHandler(link) + try + let browser = 'C:\Program Files\Firefox\firefox.exe' + execute '!start "'.browser.'" ' . a:link + return 1 + catch + echo "This can happen for a variety of reasons ..." + endtry + return 0 endfunction +A second example handles two new schemes, 'vlocal:' and 'vfile:', which behave +similar to 'local:' and 'file:' schemes, but are always opened with Vim: > + + function! VimwikiLinkHandler(link) "{{{ Use Vim to open links with the + " 'vlocal:' or 'vfile:' schemes. E.g.: + " 1) [[vfile:///~/Code/PythonProject/abc123.py]], and + " 2) [[vlocal:./|Wiki Home]] + let link = a:link + if link =~ "vlocal:" || link =~ "vfile:" + let link = link[1:] + else + return 0 + endif + let [idx, scheme, path, subdir, lnk, ext, url] = + \ vimwiki#base#resolve_scheme(link, 0) + if g:vimwiki_debug + echom 'LinkHandler: idx='.idx.', scheme=[v]'.scheme.', path='.path. + \ ', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url + endif + if url == '' + echom 'Vimwiki Error: Unable to resolve link!' + return 0 + else + call vimwiki#base#edit_file('tabnew', url, [], 0) + return 1 + endif + endfunction " }}} + + +----------------------------------------------------------------------------- +*VimwikiWikiIncludeHandler*~ + +Vimwiki includes the contents of a wiki-include URL as an image by default. + +A trial feature allows you to supply your own handler for wiki-include links. +The handler should return the empty string when it does not recognize or +cannot otherwise convert the link. A customized handler might look like this: > + + " Convert {{URL|#|ID}} -> URL#ID + function! VimwikiWikiIncludeHandler(value) "{{{ + let str = a:value + + " complete URL + let url_0 = matchstr(str, g:vimwiki_rxWikiInclMatchUrl) + " URL parts + let [scheme, path, subdir, lnk, ext, url] = + \ vimwiki#base#resolve_scheme(url_0, VimwikiGet('ext')) + let arg1 = matchstr(str, VimwikiWikiInclMatchArg(1)) + let arg2 = matchstr(str, VimwikiWikiInclMatchArg(2)) + + if arg1 =~ '#' + return url.'#'.arg2 + endif + + " Return the empty string when unable to process link + return '' + endfunction "}}} +< + +------------------------------------------------------------------------------ +*g:vimwiki_table_mappings* + +Enable/disable table mappings for INSERT mode. + +Value Description~ +0 Disable table mappings. +1 Enable table mappings. + +Default: 1 + ------------------------------------------------------------------------------ *g:vimwiki_table_auto_fmt* -Turn on/off table auto-formatting. +Enable/disable table auto formatting after leaving INSERT mode. Value Description~ -0 Do not auto-format tables. -1 Auto-format tables. +0 Disable table auto formatting. +1 Enable table auto formatting. Default: 1 @@ -1691,7 +2034,7 @@ Value Description~ etc. With - let g:vimwiki_html_header_numbering = '.' + let g:vimwiki_html_header_numbering_sym = '.' headers would look like: > 1. Header1 1.1. Header2 @@ -1706,20 +2049,6 @@ headers would look like: > Default: '' (empty) ------------------------------------------------------------------------------- -*g:vimwiki_file_exts* - -Comma-separated list of file extensions. - -Consider you have the following link: [[my_script.php][my script]]. -If there is a 'php' extension in g:vimwiki_file_exts, this link would be -htmlized to my script. -Otherwise it would be my script (note .html) - - -Default: 'pdf,txt,doc,rtf,xls,php,zip,rar,7z,html,gz' - - ------------------------------------------------------------------------------ *g:vimwiki_valid_html_tags* @@ -1752,7 +2081,67 @@ a new tab or window, it would be set to default value. Vimwiki sets |conceallevel| to g:vimwiki_conceallevel everytime vimwiki buffer is entered. -Default: 3 +Default: 2 + + +------------------------------------------------------------------------------ +*g:vimwiki_url_mingain* + +The minimum number of characters that should be gained by concealing URLs. If +the length of the concealed part of the URL would be less than +|g:vimwiki_url_mingain|, the URL is not concealed at all. +The conceal feature works only with vim >= 7.3. + +Default: 12 + + +------------------------------------------------------------------------------ +*g:vimwiki_url_maxsave* + +The maximum number of characters that is retained at the end after concealing +URLs. At most there will be |g:vimwiki_url_maxsave| characters left at the end of the URL. +However, it could be less when one of /,#,? can be found at the end. +In that case the URL will be concealed right before the last occurrence of one +of these characters. +The conceal feature works only with vim >= 7.3. Beware: when using the default +'wrap' option, the effect is not always pleasing. + +Default: 15 + + +------------------------------------------------------------------------------ +*g:vimwiki_debug* + +Controls verbosity of debugging output, for example, the diagnostic +information about HTML conversion. + +Value Description~ +0 Do not show debug messages. +1 Show debug messages. + +Default: 0 + +------------------------------------------------------------------------------ +*g:vimwiki_diary_months* + +It is a |Dictionary| with the numbers of months and corresponding names. Diary +uses it. + +Redefine it in your .vimrc to get localized months in your diary: +let g:vimwiki_diary_months = { + \ 1: 'Январь', 2: 'Февраль', 3: 'Март', + \ 4: 'Апрель', 5: 'Май', 6: 'Июнь', + \ 7: 'Июль', 8: 'Август', 9: 'Сентябрь', + \ 10: 'Октябрь', 11: 'Ноябрь', 12: 'Декабрь' + \ } + +Default: +let g:vimwiki_diary_months = { + \ 1: 'January', 2: 'February', 3: 'March', + \ 4: 'April', 5: 'May', 6: 'June', + \ 7: 'July', 8: 'August', 9: 'September', + \ 10: 'October', 11: 'November', 12: 'December' + \ } ============================================================================== @@ -1769,6 +2158,8 @@ Issues can be filed at http://code.google.com/p/vimwiki/issues . 13. Developers *vimwiki-developers* - Maxim Kim as original author. + - Stuart Andrews + - Tomas Pospichal - See the http://code.google.com/p/vimwiki/people/list for the others. Web: http://code.google.com/p/vimwiki/ @@ -1779,6 +2170,42 @@ Vim plugins: http://www.vim.org/scripts/script.php?script_id=2226 ============================================================================== 14. Changelog *vimwiki-changelog* +2.0 'stu'~ + +This release is partly incompatible with previous. + +Summary ~ + + * Quick page-link creation. + * Redesign of link syntaxes (!) + * No more CamelCase links. Check the ways to convert them + https://groups.google.com/forum/?fromgroups#!topic/vimwiki/NdS9OBG2dys + * No more [[link][desc]] links. + * No more [http://link description] links. + * No more plain image links. Use transclusions. + * No more image links identified by extension. Use transclusions. + * Interwiki links. See |vimwiki-syntax-schemes|. + * Link schemes. See |vimwiki-syntax-schemes|. + * Transclusions. See |vimwiki-syntax-transclude|. + * Normalize link command. See |vimwiki_+|. + * Improved diary organization and generation. See |vimwiki-diary|. + * List manipulation. See |vimwiki-list-manipulation|. + * Markdown support. + * Mathjax support. See |vimwiki-syntax-math|. + * Improved handling of special characters and punctuation in filenames and + urls. + * Back links command: list links referring to the current page. + * Highlighting nonexisted links are off by default. + * Table syntax change. Row separator uses | instead of +. + * Fold multilined list items. + * Custom wiki to HTML converters. See |vimwiki-option-custom_wiki2html|. + * Conceal long weblinks. See |g:vimwiki_url_mingain|. + * Option to disable table mappings. See |g:vimwiki_table_mappings|. + +For detailed information see issues list on +http://code.google.com/p/vimwiki/issues/list + + 1.2~ * Issue 70: Table spanning cell support. * Issue 72: Do not convert again for unchanged file. |:VimwikiAll2HTML| @@ -1842,468 +2269,11 @@ Vim plugins: http://www.vim.org/scripts/script.php?script_id=2226 * NEW: Added wh mapping to call |:Vimwiki2HTML| -1.1.1~ - * FIX: Issue 122: Dot character in vimwiki's directory path isn't escaped. - * FIX: Issue 123: Where is Vimwiki2HTML and other commands? Sometimes - filetype is not set up to vimwiki. - * FIX: Issue 124: Highlight group not found: Normal +... -1.1~ - * NEW: Issue 57: Make it possible to have pre block inside list item. - * NEW: Issue 82: Add quick goto command. See |:VimwikiGoto|. - * NEW: Issue 83: Quick switch in diary. See |:VimwikiDiaryNextDay| and - |:VimwikiDiaryPrevDay| commands. - * FIX: Issue 84: Vimwiki rename removed the WikiWord display name. - * FIX: Issue 85: Errors if you have '~' subdirectory in a wiki directory. - * FIX: Issue 86: Existed links '[[WikiLink1|Alias1]] | [[WikiLink2]]' are - highlighted as a single link. - * FIX: Issue 88: Underline text. See |g:vimwiki_valid_html_tags|. - * FIX: Issue 92: Wikies in a subdir could be renamed to an empty file. - * FIX: Issue 93: Use alias name in HTML title. See |vimwiki-title|. - * FIX: Issue 94: Relative links to PHP files are broken. See - |g:vimwiki_file_exts| for details. - * FIX: Issue 96: Closing bracket at the end of weblink shouldn't be a part - of that link. - * FIX: Issue 97: Error opening weblink in a browser if it has # inside. - * FIX: Issue 99: Vim is not responding while opening arbitrary wiki file. - * FIX: Issue 100: Additional content on diary index page could be - corrupted. - * NEW: Issue 101: Customized HTML tags. See |g:vimwiki_valid_html_tags| - * NEW: Issue 102: Conceal feature usage. See |g:vimwiki_conceallevel|. - * FIX: Issue 103: Always highlight links to non-wiki files as existed. - * FIX: Issue 104: vimwiki#nested_syntax needs 'keepend' to avoid contained - language syntax eat needed '}}}'. - * FIX: Issue 105: on a todo list item with [ ] doesn't create new - todo list item. - * FIX: Issue 106: With MediaWiki syntax on a child todo list - item produce errors. - * FIX: Issue 107: With MediaWiki syntax on a list item creates - todo list item without space between * and [ ]. - * FIX: Issue 110: Syntax highlighting doesn't work for indented codeblock. - * FIX: Issue 115: Nested Perl syntax highlighting differs from regular - one. - * MISC: Many vimwiki commands were renamed from Vimwiki.*Word to - Vimwiki.*Link. VimwikiGoHome is renamed to VimwikiIndex, - VimwikiTabGoHome to VimwikiTabIndex. - * MISC: vimwiki-option-gohome is removed. +39 releases -1.0~ - * NEW: Issue 41: Table cell and column text objects. See - |vimwiki-text-objects|. - * NEW: Issue 42: Commands to move table columns left and right. See - |:VimwikiTableMoveColumnLeft| and |:VimwikiTableMoveColumnRight|. - * NEW: Issue 44: should move cursor to the previous table cell. - * NEW: Issue 45: It should be possible to indent tables. Indented tables - are centered in HTML. - * NEW: Issue 46: Do not htmlize some wiki pages (blacklist). New - placeholder is added: %nohtml. See |vimwiki-nohtml|. - * FIX: Issue 47: Lists aren't HTMLized properly. - * FIX: Issue 48: With autochdir it is impossible to have path_html such as - 'd:\vimwiki\html\' - * FIX: Issue 49: Table is not HTMLized properly at the end of wiki page. - * FIX: Issue 50: Inline formatting is not performed in table cells. - * FIX: Issue 51: Cannot insert '-' (minus) into table cells of the first - column. - * FIX: Issue 52: Table cell width is incorrect when double wide characters - are used (ie. Chinese). Check |g:vimwiki_CJK_length|. - * NEW: Issue 53: Wiki markup can not nested. (Use links and inline markup - in Headers). - * NEW: Issue 54: Highlight for placeholders. - * NEW: Issue 56: Directory indexes. See |g:vimwiki_dir_link| option and - |:VimwikiGenerateLinks| command. - * NEW: Issue 58: Html new lines with
    . Could be inserted with - in insert mode. - * FIX: Issue 59: List item's text can't be started from *. - * NEW: Issue 60: Links inside completed gtd-items. - * NEW: Issue 61: Headers numbering. See |g:vimwiki_html_header_numbering| - and |g:vimwiki_html_header_numbering_sym| options. - * FIX: Issue 63: Table cannot have leading empty cells in HTML. - * FIX: Issue 65: Table separator is not htmlized right if on top of the - table. - * FIX: Issue 66: Table empty cells are very small in HTML. - * FIX: Issue 67: Wrong HTML conversion of multilined list item with bold - text on the start of next line. - * FIX: Issue 68: auto-indent problem with langmap. - * FIX: Issue 73: Link navigation by Tab. "Escaped" wiki-word should be - skipped for navigation with . - * FIX: Issue 75: `code` syntax doesn't display correctly in toc. - * FIX: Issue 77: Diary index only showing link to today's diary entry - file for extensions other than '.wiki'. - * FIX: Issue 79: Further calendar.vim integration -- add sign to calendar - date if it has corresponding diary page. - * FIX: Issue 80: Debian Lenny GUI Vim 7.2 has problems with toggling inner - todo list items. - * FIX: Issue 81: Don't convert WikiWord as a link in HTML when - `let g:vimwiki_camel_case = 0` - -0.9.9~ - * NEW: Diary. Help in making daily notes. See |vimwiki-diary|. Now you can - really easy add information into vimwiki that should be sorted out - later. - * NEW: Tables are redesigned. Syntax is changed. Now they are - auto-formattable. You can navigate them with and in insert - mode. See |vimwiki-syntax-tables| and |vimwiki-tables| for more details. - * NEW: Keyword STARTED: is added. - * NEW: Words TODO:, DONE:, STARTED:, XXX:, FIXME:, FIXED: are highlighed - inside headers. - * FIX: Export to HTML external links with 'file://' protocol. Ex: - [file:///home/user1/book.pdf my book]. - * FIX: Menu is corrupted if wiki's path contains spaces. - * FIX: Settings |wrap| and |linebreak| are removed from ftplugin. Add them - into your personal settings file `.vim/after/ftplugin/vimwiki.vim` if - needed. - * NEW: Headers are highlighted in different colors by default. - See |g:vimwiki_hl_headers| to turn it off. - * FIX: Issue 40: Links with russian subdirs don't work. - * NEW: It is now possible to generate HTML files automatically on page - save. See |vimwiki-option-auto_export|. - - -0.9.8~ - * NEW: Rename |g:vimwiki_fold_empty_lines| to - |g:vimwiki_fold_trailing_empty_lines|. - * NEW: One can use '-' along with '*' to start unordered list item. - * NEW: List items could be started from the first column. - As a result some limitations appeared: - - a space after *, - or # for a list item is mandatory. - - |g:vimwiki_fold_trailing_empty_lines| if set to 0 folds one trailing - empty line. - * NEW: Folding is off by default. Use |g:vimwiki_folding| to enable it. - * NEW: Speed up vimwiki's folding a bit. Should lag a bit less in a long - todo lists. - * NEW: Centered headers. Start header with at least one space to make it - HTML centered. - * NEW: Change in default CSS: header's colors. - * NEW: Vimwiki is aware of |GetLatestVimScripts| now. - * FIX: Use tag instead of custom in HTML. - * FIX: There are no text styling in htmlized quoted text. - * FIX: set default value of g:vimwiki_fold_lists to 0 as written in this - help. - * FIX: Issue 33: Folded list items have wrong indentation when 'tabs' are - used. - * FIX: Issue 34: vimwiki#subdir got wrong dir when VimwikiGet('path') is a - symbolic link. Thanks lilydjwg for the patch. - * FIX: Issue 28: todo-list auto-indent enhancement. New item should always - be unchecked. - * Issue 36: Change the name of the Search command to VimwikiSearch as it - conflicts with MultipleSearch. Alias :VWS is also available. - * NEW: You can generate 'Table of contents' of your wiki page. See - |vimwiki-toc| for details. - -0.9.701~ - * FIX: Issue 30: Highlighting doesn't work for checked list item. - -0.9.7~ - * NEW: Default checkbox symbols are changed to [ ], [.], [o], [O], [X]. - You can change them using |g:vimwiki_listsyms| variable. - * NEW: Color group names are renamed from wikiBold, wikiItalic, etc to - VimwikiBold, VimwikiItalic, etc. - * NEW: Open external links in a browser. There are default browsers - defined in |g:vimwiki_browsers| list. You can also redefine - |VimwikiWeblinkHandler| function to open weblinks in other programs. - * NEW: Issue 25: Toggle the states of multiple TODO list items at a time - (in VISUAL and in VISUAL LINE modes) - * NEW: Issue 26: Highlight code snippets in vimwiki's pre. See - |vimwiki-option-nested_syntaxes|. Thanks kriomant. - * NEW: Issue 27: Automatic garbage deletion from HTML directory. - * NEW: Save all open vimwiki buffers before export to HTML. - * NEW: Issue 29: Custom :Search command. - * NEW: Header text objects are now expandable in VISUAL mode. Tap 'vah' to - select a header. Tap again 'ah' to expand selection further. Thanks Andy - Wokula. - * FIX: Folding settings are reset to vim defaults in a new tab (think of - \wt) so you cannot hide things in folds. - * FIX: https links in form of [https://hello.world.com] are not exported - into HTML. Thanks Saurabh Sarpal for the patch. - -0.9.6~ - * NEW: You can have multiline list items. See |vimwiki-syntax-lists|. - * NEW: You can ignore newlines in multiline list items when do export to - HTML. See |g:vimwiki_list_ignore_newline| option. - * NEW: Different checkbox symbols [.], [:], [o] are added. See - |vimwiki-todo-lists|. - * NEW: Now there is no longer syntax of preformatted text that is started - by a whitespace. - * NEW: Blockquotes. See |vimwiki-syntax-blockquote|. - * NEW: Per wiki folding option (vimwiki-option-folding) is removed. Global - |g:vimwiki_folding| and |g:vimwiki_fold_lists| are added. - * NEW: Due to being quite slow folding of list items is off by default. - Use |g:vimwiki_fold_lists| to turn it on. - * NEW: If you want replace some symbols in a wikifilename use - |g:vimwiki_badsyms| option (Andreas Baldeau). - * FIX: Command |:VimwikiToggleListItem| doesn't work for one of the two - wikies opened at the same time with different syntaxes. - * FIX: Command |:VimwikiToggleListItem| do not switch parent checkboxes if - there are non-checkbox list items available. - * FIX: Issue 24: Link error in HTML when write [[one.two.three]]. - * FIX: Rename WikiWord to something with a colon (:) does nasty things. - * FIX: Command |:VimwikiToggleListItem| do not switch right if there are - list items without checkboxes in the list. - -0.9.5~ - * NEW: Added |g:vimwiki_global_ext| to control creation of temporary - wikies in dirs that are not listed in |g:vimwiki_list|. - * NEW: Added |g:vimwiki_hl_headers| to highlight headers with different - predefined colors. - * NEW: Checked [X] items are not highlighted with Comment syntax group by - default. Use |g:vimwiki_hl_cb_checked| to turn it on. - * NEW: Added new syntax for links: [[link address][link description]]. - * NEW: Added allias of mapping for *nix systems. - * NEW: Added |g:vimwiki_camel_case|. Set it to 0 if you do not want - CamelCased WikiWords to be linkified. - * FIX: Links with g:vimwiki_stripsym (default '_') [[My_Link|Text]] are - not highlighted when created. - * FIX: indent/vimwiki.vim is obsolete. If you upgrade from previous - versions remove it. It causes wrong list indentation if noexpandtab is - set. - * FIX: If tabs and spaces are used to indent list items HTML export gives - error. Thanks Klaus Ethgen for report. - * FIX: Some HTML export fixes. - -0.9.4~ - * NEW: Links with directories: [[dir1/dir2/Link|Text]]. Thanks Jie Wu. - * NEW: Added %root_path% template variable to get relative root dir of - path_html. See |vimwiki-option-html_header|. - * FIX: Indent is incorrect for vim without "float" compile option. Thanks - Julian Kooij. - * FIX: Convert to HTML doesn't work right with links like [[foo::bar]]. - * FIX: Rename wikiword doesn't work right when rename WikiWord to - [[WikiWord blablabla]]. - * FIX: Renaming of links with description doesn't work. - * FIX: Weblinks with commas are not highlighted. - * MISC: Some changes in default CSS file. - -0.9.3~ - * NEW: g:vimwiki_menu option is a string which is menu path. So one can - use let g:vimwiki_menu = 'Plugin.Vimwiki' to set the menu to the right - place. - * NEW: g:vimwiki_fold_empty_lines -- don't or do fold in empty lines - between headers. See |g:vimwiki_fold_empty_lines| - * FIX: Encoding error when running vimwiki in Windows XP Japanese. - Thanks KarasAya. - -0.9.2c~ - * FIX: Regression: Export HTML link error with [[Link|Text]]. - -0.9.2b~ - * FIX: Installation on Linux doesn't work. (Dos line endings in Vimball - archive file). - * FIX: Clear out FlexWiki ftplugin's setup. Now you don't have to hack - filetype.vim to get rid of unexpected ':setlocal bomb' from FlexWiki's - ftplugin. - * FIX: When write done: it will show another done: in HTML file. - -0.9.2a~ - * FIX: Installation on Linux doesn't work. (Dos line endings in - autoload/vimwiki_lst.vim and indent/vimwiki.vim). - -0.9.2~ - * NEW: Option 'folding' added to turn folding on/off. - * NEW: Header text object. See |vimwiki-text-objects|. - * NEW: Add/remove Header levels with '=' and '-'. See |vimwiki_=|. - * NEW: Vimwiki GUI menu to select available wikies. See |g:vimwiki_menu|. - * NEW: You can specify the name of your CSS file now. See - |vimwiki-option-css_name| - * NEW: You can add styles to image links, see |vimwiki-syntax-links|. - * FIX: History doesn't work after |VimwikiRenameWord|. - * FIX: Some of wikipedia links are not correctly highlighted. Links with - parentheses. - * MISC: Renamed vimwiki_gtd to vimwiki_lst. - -0.9.1~ - * NEW: HTML Table cell text alignment, see |vimwiki-syntax-tables| - * NEW: Wikipage history simplified. Each vimwiki buffer now holds - b:vimwiki_prev_word which is list of [PrevWord, getpos()]. - * NEW: If highlight for groups wikiHeader1..wikiHeader6 exist (defined in - a colorscheme) -- use it. Otherwise use Title highlight for all Headers. - * FIX: Warn only once if 'html_header' or 'html_footer' does not exist. - * FIX: Wrong folding for the text after the last nested list item. - * FIX: Bold and Italic aren't highlighted in tables without spaces - between || and * or _. ||*bold*||_asdf_ || (Thanks Brett Stahlman) - -0.9.0~ - * NEW: You can add classes to 'pre' tag -- |vimwiki-syntax-preformatted|. - This might be useful for coloring some programming code with external js - tools like google syntax highlighter. - * NEW: !WikiPage is not highlighted. It is just a plain word WikiPage in - HTML, without exclamation mark - * NEW: Definition lists, see |vimwiki-syntax-lists|. - * NEW: New implementation of |:VimwikiRenameWord|. CAUTION: It was tested - on 2 computers only, backup your wiki before use it. Email me if it - doesn't work for you. - * FIX: Less than 3 symbols are not highlighted in Bold and Italic. - * FIX: Added vimwiki autocmd group to avoid clashes with user defined - autocmds. - * FIX: Pressing ESC while |:VimwikiUISelect| opens current wiki index - file. Should cancel wiki selection. - -0.8.3~ - * NEW: on a list item creates checkbox. - * FIX: With * in the first column, shouldn't insert more * (default - syntax). - * FIX: With MediaWiki's ** [ ], should insert it on the next line. - * FIX: HTML export should use 'fileencoding' instead of 'encoding'. - * FIX: Code cleanup. - -0.8.2~ - * DEL: Removed google syntax file. - * NEW: Default vimwiki syntax is a subset of google's one. Header's has - been changed from !Header to =Header=. It is easier to maintain only 2 - syntaxes. See |vimwiki-syntax-headers|. - * NEW: Multiline paragraphs -- less longlines. - * NEW: Comments. See |vimwiki-syntax-comments|. - * DEL: Removed setlocal textwidth = 0 from ftplugin. - * FIX: New regexps for bold, italic, bolditalic. - * FIX: The last item in List sometimes fold-in incorrectly. - * FIX: Minor tweaks on default CSS. - -0.8.1~ - * NEW: Vimwiki's foldmethod changed from syntax to expr. Foldtext is - changed to be nicer with folded list items. - * NEW: Fold/outline list items. - * NEW: It is possible now to edit wiki files in arbitrary directories - which is not in g:vimwiki_list's paths. New WikiWords are created in the - path of the current WikiWord. - * NEW: User can remap Vimwiki's built in mappings. - * NEW: Added |g:vimwiki_use_mouse|. It is off by default. - * FIX: Removed mapping. - -0.8.0~ - * NEW: Multiple wikies support. A lot of options have been changed, see - |vimwiki-options| - * NEW: Auto create directories. - * NEW: Checked list item highlighted as comment. - * FIX: Multiple 'set ft=vimwiki' for each buffer disabled. Vimwiki should - load its buffers a bit faster now. - -0.7.1~ - * NEW: VimwikiToggleListItem added to be able to remap to - anything user prefers more. - * FIX: Toggleable list items do not work with MediaWiki markup. - * FIX: Changing g:vimwiki_home_html to path with ~ while vimwiki is - loaded gives errors for HTML export. - * DEL: Command :VimwikiExploreHome. - -0.7.0~ - * NEW: GTD stuff -- toggleable list items. See |vimwiki-todo-lists|. - * FIX: Headers do not fold inner headers. (Thanks Brett Stahlman) - * FIX: Remove last blank lines from preformatted text at the end of file. - * DEL: Removed g:vimwiki_smartCR option. - -0.6.2~ - * NEW: [[link|description]] is available now. - * FIX: Barebone links (ie: http://bla-bla-bla.org/h.pl?id=98) get extra - escaping of ? and friends so they become invalid in HTML. - * FIX: In linux going to [[wiki with whitespaces]] and then pressing BS - to go back to prev wikipage produce error. (Thanks Brendon Bensel for - the fix) - * FIX: Remove setlocal encoding and fileformat from vimwiki ftplugin. - * FIX: Some tweaks on default style.css - -0.6.1~ - * FIX: [blablabla bla] shouldn't be converted to a link. - * FIX: Remove extra annoing empty strings from PRE tag made from - whitespaces in HTML export. - * FIX: Moved functions related to HTML converting to new autoload module - to increase a bit vimwiki startup time. - -0.6~ - * NEW: Header and footer templates. See|g:vimwiki_html_header| and - |g:vimwiki_html_footer|. - * FIX: |:Vimwiki2HTML| does not recognize ~ as part of a valid path. - -0.5.3~ - * FIX: Fixed |:VimwikiRenameWord|. Error when g:vimwiki_home had - whitespaces in path. - * FIX: |:VimwikiSplitWord| and |:VimwikiVSplitWord| didn't work. - -0.5.2~ - * NEW: Added |:VimwikiGoHome|, |:VimwikiTabGoHome| and - |:VimwikiExploreHome| commands. - * NEW: Added wt mapping to open vimwiki index file in a new tab. - * NEW: Added g:vimwiki_gohome option that controls how|:VimwikiGoHome| - works when current buffer is changed. (Thanks Timur Zaripov) - * FIX: Fixed |:VimwikiRenameWord|. Very bad behaviour when autochdir - isn't set up. - * FIX: Fixed commands :Wiki2HTML and :WikiAll2HTML to be available only - for vimwiki buffers. - * FIX: Renamed :Wiki2HTML and :WikiAll2HTML to |:Vimwiki2HTML| and - |:VimwikiAll2HTML| commands. - * FIX: Help file corrections. - -0.5.1~ - * NEW: This help is created. - * NEW: Now you can fold headers. - * NEW: VimwikiGoHome and VimwikiExploreHome were added. - * FIX: Bug with {{{HelloWikiWord}}} export to HTML is fixed. - * DEL: Sync option removed from: Syntax highlighting for preformatted - text {{{ }}}. - -0.5~ - * NEW: vimwiki default markup to HTML conversion improved. - * NEW: Added basic GoogleWiki and MediaWiki markup languages. - * NEW: Chinese [[complex wiki words]]. - -0.4~ - * NEW: vimwiki=>HTML converter in plain Vim language. - * NEW: Plugin autoload. - -0.3.4~ - * FIX: Backup files (.wiki~) caused a bunch of errors while opening wiki - files. - -0.3.3~ - * FIX: [[wiki word with dots at the end...]] didn't work. - * NEW: Added error handling for delete wiki word function. - * NEW: Added keybindings o and O for list items when g:vimwiki_smartCR=1. - * NEW: Added keybinding wh to visit wiki home directory. - -0.3.2~ - * FIX: Renaming -- error if complex wiki word contains %. - * FIX: Syntax highlighting for preformatted text {{{ }}}. Sync option - added. - * FIX: smartCR bug fix. - -0.3.1~ - * FIX: Renaming -- [[hello world?]] to [[hello? world]] links are not - updated. - * FIX: Buffers menu is a bit awkward after renaming. - * NEW: Use mouse to follow links. Left double-click to follow WikiWord, - Rightclick then Leftclick to go back. - -0.3~ - * NEW: Highlight non-existent WikiWords. - * NEW: Delete current WikiWord (wd). - * NEW: g:vimwiki_smartCR=2 => use Vim comments (see :h comments :h - formatoptions) feature to deal with list items. (thx -- Dmitry - Alexandrov) - * NEW: Highlight TODO:, DONE:, FIXED:, FIXME:. - * NEW: Rename current WikiWord -- be careful on Windows you cannot rename - wikiword to WikiWord. After renaming update all links to that renamed - WikiWord. - * FIX: Bug -- do not duplicate WikiWords in wiki history. - * FIX: After renaming [[wiki word]] twice buffers are not deleted. - * FIX: Renaming from [[wiki word]] to WikiWord result is [[WikiWord]] - * FIX: More than one complex words on one line is bugging each other when - try go to one of them. [[bla bla bla]] [[dodo dodo dodo]] becomes bla - bla bla]] [[dodo dodo dodo. - - -0.2.2~ - * NEW: Added keybinding -- split WikiWord - * NEW: Added keybinding -- vertical split WikiWord - -0.2.1~ - * NEW: Install on Linux now works. - -0.2~ - * NEW: Added part of Google's Wiki syntax. - * NEW: Added auto insert # with ENTER. - * NEW: On/Off auto insert bullet with ENTER. - * NEW: Strip [[complex wiki name]] from symbols that cannot be used in - file names. - * NEW: Links to non-wiki files. Non wiki files are files with extensions - ie [[hello world.txt]] or [[my homesite.html]] +... 0.1~ * First public version. diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 5d31b37..bf6e7b5 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -35,13 +35,17 @@ setlocal isfname-=[,] " Autocreate list items {{{ " for list items, and list items with checkboxes +setlocal formatoptions+=tnro +setlocal formatoptions-=cq if VimwikiGet('syntax') == 'default' setl comments=b:*,b:#,b:- setl formatlistpat=^\\s*[*#-]\\s* +elseif VimwikiGet('syntax') == 'markdown' + setlocal comments=fb:*,fb:-,fb:+,nb:> commentstring=\ >\ %s + setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\|^[-*+]\\s\\+j else setl comments=n:*,n:# endif -setlocal formatoptions=tnro if !empty(&langmap) " Valid only if langmap is a comma separated pairs of chars @@ -64,23 +68,15 @@ function! VimwikiFoldLevel(lnum) "{{{ " Header folding... if line =~ g:vimwiki_rxHeader - let n = vimwiki#base#count_first_sym(line) + let n = vimwiki#u#count_first_sym(line) return '>'.n endif - if g:vimwiki_fold_trailing_empty_lines == 0 && line =~ '^\s*$' - let nnline = getline(nextnonblank(a:lnum + 1)) - else - let nnline = getline(a:lnum + 1) - endif - if nnline =~ g:vimwiki_rxHeader - let n = vimwiki#base#count_first_sym(nnline) - return '<'.n - endif + let base_level = s:get_base_level(a:lnum) " List item folding... if g:vimwiki_fold_lists - let base_level = s:get_base_level(a:lnum) + let nnline = getline(a:lnum + 1) let rx_list_item = '\('. \ g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber. @@ -95,6 +91,10 @@ function! VimwikiFoldLevel(lnum) "{{{ if leveln > level return ">".(base_level+leveln-adj) + " check if multilined list item + elseif (nnum-a:lnum) > 1 + \ && nline =~ rx_list_item && nnline !~ '^\s*$' + return ">".(base_level+level+1-adj) else return (base_level+level-adj) endif @@ -102,34 +102,23 @@ function! VimwikiFoldLevel(lnum) "{{{ " process multilined list items let [pnum, pline] = s:find_backward(rx_list_item, a:lnum) if pline =~ rx_list_item - if indent(a:lnum) > indent(pnum) + if indent(a:lnum) >= indent(pnum) && line !~ '^\s*$' let level = s:get_li_level(pnum) let adj = s:get_li_level(s:get_start_list(rx_list_item, pnum)) - - let [nnum, nline] = s:find_forward(rx_list_item, a:lnum) - if nline =~ rx_list_item - let leveln = s:get_li_level(nnum) - if leveln > level - return (base_level+leveln-adj) - endif - endif - - return (base_level+level-adj) + return (base_level+level+1-adj) endif endif endif - - return base_level endif - return -1 + return base_level endfunction "}}} function! s:get_base_level(lnum) "{{{ let lnum = a:lnum - 1 while lnum > 0 if getline(lnum) =~ g:vimwiki_rxHeader - return vimwiki#base#count_first_sym(getline(lnum)) + return vimwiki#u#count_first_sym(getline(lnum)) endif let lnum -= 1 endwhile @@ -169,7 +158,7 @@ endfunction "}}} function! s:get_li_level(lnum) "{{{ if VimwikiGet('syntax') == 'media' - let level = vimwiki#base#count_first_sym(getline(a:lnum)) + let level = vimwiki#u#count_first_sym(getline(a:lnum)) else let level = (indent(a:lnum) / &sw) endif @@ -198,12 +187,16 @@ endfunction "}}} " COMMANDS {{{ command! -buffer Vimwiki2HTML - \ w call vimwiki#html#Wiki2HTML(expand(VimwikiGet('path_html')), + \ silent w + \ let res = vimwiki#html#Wiki2HTML(expand(VimwikiGet('path_html')), \ expand('%')) + \ + \ if res != '' | echo 'Vimwiki: HTML conversion is done.' | endif command! -buffer Vimwiki2HTMLBrowse - \ w call VimwikiWeblinkHandler( - \ vimwiki#html#Wiki2HTML(expand(VimwikiGet('path_html')), - \ expand('%'))) + \ silent w + \ call vimwiki#base#system_open_link(vimwiki#html#Wiki2HTML( + \ expand(VimwikiGet('path_html')), + \ expand('%'))) command! -buffer VimwikiAll2HTML \ call vimwiki#html#WikiAll2HTML(expand(VimwikiGet('path_html'))) @@ -216,12 +209,17 @@ command! -buffer VimwikiGoBackLink call vimwiki#base#go_back_link() command! -buffer VimwikiSplitLink call vimwiki#base#follow_link('split') command! -buffer VimwikiVSplitLink call vimwiki#base#follow_link('vsplit') +command! -buffer -nargs=? VimwikiNormalizeLink call vimwiki#base#normalize_link() + command! -buffer VimwikiTabnewLink call vimwiki#base#follow_link('tabnew') command! -buffer -range VimwikiToggleListItem call vimwiki#lst#ToggleListItem(, ) command! -buffer VimwikiGenerateLinks call vimwiki#base#generate_links() +command! -buffer -nargs=0 VimwikiBacklinks call vimwiki#base#backlinks() +command! -buffer -nargs=0 VWB call vimwiki#base#backlinks() + exe 'command! -buffer -nargs=* VimwikiSearch lvimgrep '. \ escape(VimwikiGet('path').'**/*'.VimwikiGet('ext'), ' ') @@ -230,6 +228,10 @@ exe 'command! -buffer -nargs=* VWS lvimgrep '. command! -buffer -nargs=1 VimwikiGoto call vimwiki#base#goto("") + +" list commands +command! -buffer -nargs=* VimwikiListChangeLevel call vimwiki#lst#change_level() + " table commands command! -buffer -nargs=* VimwikiTable call vimwiki#tbl#create() command! -buffer VimwikiTableAlignQ call vimwiki#tbl#align_or_cmd('gqq') @@ -247,7 +249,7 @@ command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day() if g:vimwiki_use_mouse nmap nmap - nnoremap <2-LeftMouse> :VimwikiFollowLink + nnoremap <2-LeftMouse> :call vimwiki#base#follow_link("nosplit", "\2-LeftMouse>") nnoremap :VimwikiSplitLink nnoremap :VimwikiVSplitLink nnoremap :VimwikiGoBackLink @@ -284,6 +286,24 @@ endif nnoremap