diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..bffe109 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# Filing a bug + +Before filing a bug or starting to write a patch, check the latest development version from +https://github.com/vimwiki/vimwiki/tree/dev to see if your problem is already fixed. + +Issues can be filed at https://github.com/vimwiki/vimwiki/issues/ . + +# Creating a pull request +If you want to provide a pull request on GitHub, please start from the `dev` branch, not from the +`master` branch. (Caution, GitHub shows `master` as the default branch from which to start a PR.) + + +# More info for (aspiring) core developers +## Git branching model +- there are two branches with eternal lifetime: + - `dev`: This is where the main development happens. Tasks which are done in one or only a few + commits go here directly. Always try to keep this branch in a working state, that is, if the + task you work on requires multiple commits, make sure intermediate commits don't make Vimwiki + unusable (or at least push these commits at one go). + - `master`: This branches is for released states only. Whenever a reasonable set of changes has + piled up in the `dev` branch, a [release is done](#Preparing a release). After a release, + `dev` has been merged into `master` and `master` got exactly one additional commit in which + the version number in `plugin/vimwiki.vim` is updated. Apart from these commits and the merge + commit from `dev`, nothing happens on `master`. Never should `master` merge into `dev`. When + the users ask, we should recommend this branch for them to use. +- Larger changes which require multiple commits are done in feature branches. They are based on + `dev` and merge into `dev` when the work is done. + +## Preparing a release + +1. `git checkout dev` +2. Update the changelog in the doc, nicely grouped, with a new version number and release date. +3. Update the list of contributors. +4. Update the version number at the top of the doc file. +5. If necessary, update the Readme and the home page. +6. `git checkout master && git merge dev` +7. Update the version number at the top of plugin/vimwiki.vim. +8. Set a tag with the version number in Git: `git tag vX.Y` +9. `git push --tags` +10. In GitHub, go to _Releases_ -> _Draft a new release_ -> choose the tag, convert the changelog from the + doc to markdown and post it there. Make plans to build an automatic converter and immediately + forget this plan. +11. Tell the world. + + +%% vim:tw=99 diff --git a/README.md b/README.md index a407040..f831ec9 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,19 @@ Commands * `:Vimwiki2HTML` -- Convert current wiki link to HTML * `:VimwikiAll2HTML` -- Convert all your wiki links to HTML * `:help vimwiki-commands` -- list all commands + * `:help vimwiki` -- General vimwiki help docs + + +Changing Wiki Syntax +------------------------------------------------------------------------------ + + Vimwiki currently ships with 3 syntaxes: Vimwiki (default), Markdown (markdown), and MediaWiki (media) + + If you would prefer to use either Markdown or MediaWiki syntaxes, set the following option in your .vimrc: + ``` + let g:vimwiki_list = [{'path': '~/vimwiki/', + \ 'syntax': 'markdown', 'ext': '.md'}] + ``` Installation @@ -135,6 +148,15 @@ Installation using [Pathogen](http://www.vim.org/scripts/script.php?script_id=23 cd bundle git clone https://github.com/vimwiki/vimwiki.git +Installation using [Vim-Plug](https://github.com/junegunn/vim-plug) +------------------------------------------------------------------------------ + +Add the following to the plugin-configuration in your vimrc: + + Plug 'vimwiki/vimwiki', { 'branch': 'dev' } + +Then run `:PlugInstall`. + Installation using [Vundle](https://github.com/VundleVim/Vundle.vim) ------------------------------------------------------------------------------ @@ -146,6 +168,14 @@ Or download the [zip archive](https://github.com/vimwiki/vimwiki/archive/master. Then launch Vim, run `:Helptags` and then `:help vimwiki` to verify it was installed. + +Getting help +============================================================================== + +Have a question? Visit the IRC channel `#vimwiki` on Freenode ([webchat](https://webchat.freenode.net/?channels=#vimwiki)) +or post to the [mailing list](https://groups.google.com/forum/#!forum/vimwiki). + + ---- \* Screenshots made with the [solarized colorscheme](https://github.com/altercation/vim-colors-solarized) and [lightline](https://github.com/itchyny/lightline.vim) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index b734963..7507158 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -46,14 +46,20 @@ endfunction " Returns: the number of the wiki a file belongs to or -1 if it doesn't belong " to any registered wiki. function! vimwiki#base#find_wiki(file) + let bestmatch = -1 + let bestlen = 0 for idx in range(vimwiki#vars#number_of_wikis()) - if vimwiki#path#is_file_in_dir(a:file, vimwiki#vars#get_wikilocal('path', idx)) - return idx + let wiki_path = expand(vimwiki#vars#get_wikilocal('path', idx)) + let common_prefix = vimwiki#path#path_common_pfx(wiki_path, a:file) + if vimwiki#path#is_equal(common_prefix, wiki_path) + if len(common_prefix) > bestlen + let bestlen = len(common_prefix) + let bestmatch = idx + endif endif endfor - " an orphan page has been detected - return -1 + return bestmatch endfunction @@ -71,14 +77,9 @@ function! vimwiki#base#resolve_link(link_text, ...) let link_text = a:link_text - " if link is schemeless add wikiN: scheme - if link_text !~# vimwiki#vars#get_global('rxSchemeUrl') - let link_text = 'wiki'.source_wiki.':'.link_text - endif - let link_infos = { - \ 'index': -1, + \ 'index': 0, \ 'scheme': '', \ 'is_file': 0, " 1 for a file, 0 for a URL (e.g. when the link was [[http://foo.bar]]), \ " -1 if the whole link was malformed @@ -86,24 +87,29 @@ function! vimwiki#base#resolve_link(link_text, ...) \ 'anchor': '', \ } - - " extract scheme - let link_infos.scheme = matchstr(link_text, vimwiki#vars#get_global('rxSchemeUrlMatchScheme')) - if link_infos.scheme == '' || link_text == '' + if link_text == '' let link_infos.is_file = -1 return link_infos endif - if link_infos.scheme !~# '\mwiki\d\+\|diary\|local\|file' - " unknown scheme, may be a weblink - let link_infos.is_file = 0 - let link_infos.target = link_text - return link_infos + + let scheme = matchstr(link_text, '^\zs'.vimwiki#vars#get_global('rxSchemes').'\ze:') + if scheme == '' + let link_infos.scheme = 'wiki'.source_wiki + else + let link_infos.scheme = scheme + + if link_infos.scheme !~# '\mwiki\d\+\|diary\|local\|file' + " unknown scheme, may be a weblink + let link_infos.is_file = 0 + let link_infos.target = link_text + return link_infos + endif + + let link_infos.is_file = 1 + + let link_text = matchstr(link_text, '^'.vimwiki#vars#get_global('rxSchemes').':\zs.*\ze') endif - let link_infos.is_file = 1 - - let link_text = matchstr(link_text, vimwiki#vars#get_global('rxSchemeUrlMatchUrl')) - let is_wiki_link = link_infos.scheme =~# '\mwiki\d\+' || link_infos.scheme ==# 'diary' " extract anchor @@ -139,6 +145,7 @@ function! vimwiki#base#resolve_link(link_text, ...) let link_infos.index = eval(matchstr(link_infos.scheme, '\D\+\zs\d\+\ze')) if link_infos.index < 0 || link_infos.index >= vimwiki#vars#number_of_wikis() let link_infos.is_file = -1 + let link_infos.index = -1 return link_infos endif @@ -190,22 +197,32 @@ 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 - "disable 'shellslash', otherwise the url will be enclosed in single quotes, - "which is problematic - "see https://github.com/vimwiki/vimwiki/issues/54#issuecomment-48011289 - if exists('+shellslash') - let old_ssl = &shellslash - set noshellslash - let url = shellescape(a:url, 1) - let &shellslash = old_ssl + "Disable shellslash for cmd and command.com, but enable for all other shells + "See Issue #560 + if (&shell =~? "cmd") || (&shell =~? "command.com") + + if exists('+shellslash') + let old_ssl = &shellslash + set noshellslash + let url = shellescape(a:url, 1) + let &shellslash = old_ssl + else + let url = shellescape(a:url, 1) + endif + execute 'silent ! start "Title" /B ' . url + else - let url = shellescape(a:url, 1) - endif - if &l:shell ==? "powershell" - execute 'silent ! start ' . a:url - else - execute 'silent ! start "Title" /B ' . a:url + + if exists('+shellslash') + let old_ssl = &shellslash + set shellslash + let url = shellescape(a:url, 1) + let &shellslash = old_ssl + else + let url = shellescape(a:url, 1) + endif + execute 'silent ! start ' . url + endif endfunction function! s:macunix_handler(url) @@ -239,7 +256,11 @@ function! vimwiki#base#open_link(cmd, link, ...) endif if link_infos.is_file == -1 - echomsg 'Vimwiki Error: Unable to resolve link!' + if link_infos.index == -1 + echomsg 'Vimwiki Error: No registered wiki ''' . link_infos.scheme . '''.' + else + echomsg 'Vimwiki Error: Unable to resolve link!' + endif return endif @@ -696,19 +717,22 @@ function! vimwiki#base#edit_file(command, filename, anchor, ...) " This hack is necessary because apparently Vim messes up the result of " getpos() directly after this command. Strange. if !(a:command ==# ':e ' && vimwiki#path#is_equal(a:filename, expand('%:p'))) - try - if &autowriteall && !&hidden " in this case, the file is saved before switching to the - " new buffer. This causes Vim to show two messages in the command line which triggers - " the annoying hit-enter prompt. Solution: show no messages at all. - silent execute a:command fname - else + if &autowriteall && !&hidden " in this case, the file is saved before switching to the + " new buffer. This causes Vim to show two messages in the command line which triggers + " the annoying hit-enter prompt. Solution: show no messages at all. + silent execute a:command fname + else + try execute a:command fname - endif - catch /E37:/ - echomsg 'Vimwiki: The current file is modified. Hint: Take a look at' - \ ''':h g:vimwiki_autowriteall'' to see how to save automatically.' - return - endtry + catch /E37:/ + echomsg 'Vimwiki: Can''t leave the current buffer, because it is modified. Hint: Take a look at' + \ ''':h g:vimwiki_autowriteall'' to see how to save automatically.' + return + catch /E325:/ + echom 'Vimwiki: Vim couldn''t open the file, probably because a swapfile already exists. See :h E325.' + return + endtry + endif " If the opened file was not already loaded by Vim, an autocommand is " triggered at this point @@ -825,16 +849,17 @@ function! s:update_wiki_link(fname, old, new) endfunction -function! s:update_wiki_links_dir(dir, old_fname, new_fname) +function! s:update_wiki_links_dir(wiki_nr, dir, old_fname, new_fname) let old_fname = substitute(a:old_fname, '[/\\]', '[/\\\\]', 'g') let new_fname = a:new_fname let old_fname_r = vimwiki#base#apply_template( - \ vimwiki#vars#get_syntaxlocal('WikiLinkMatchUrlTemplate'), old_fname, '', '') + \ vimwiki#vars#get_syntaxlocal('WikiLinkMatchUrlTemplate', + \ vimwiki#vars#get_wikilocal('syntax', a:wiki_nr)), old_fname, '', '') - let files = split(glob(vimwiki#vars#get_wikilocal('path').a:dir.'*'. - \ vimwiki#vars#get_wikilocal('ext')), '\n') - for fname in files + let files = split(glob(vimwiki#vars#get_wikilocal('path', a:wiki_nr).a:dir.'*'. + \ vimwiki#vars#get_wikilocal('ext', a:wiki_nr)), '\n') + for fname in l:files call s:update_wiki_link(fname, old_fname_r, new_fname) endfor endfunction @@ -848,11 +873,11 @@ function! s:tail_name(fname) endfunction -function! s:update_wiki_links(old_fname, new_fname) +function! s:update_wiki_links(wiki_nr, old_fname, new_fname,old_fname_relpath) let old_fname = a:old_fname let new_fname = a:new_fname - let subdirs = split(a:old_fname, '[/\\]')[: -2] + let subdirs = split(a:old_fname_relpath, '[/\\]')[: -2] " TODO: Use Dictionary here... let dirs_keys = [''] @@ -874,7 +899,7 @@ function! s:update_wiki_links(old_fname, new_fname) while idx < len(dirs_keys) let dir = dirs_keys[idx] let new_dir = dirs_vals[idx] - call s:update_wiki_links_dir(dir, new_dir.old_fname, new_dir.new_fname) + call s:update_wiki_links_dir(a:wiki_nr, dir, new_dir.old_fname, new_dir.new_fname) let idx = idx + 1 endwhile endfunction @@ -974,7 +999,7 @@ endfunction " will only be updated if it already exists function! vimwiki#base#update_listing_in_buffer(strings, start_header, \ content_regex, default_lnum, create) - " apparently, Vim behaves strange when files change while in diff mode + " Vim behaves strangely when files change while in diff mode if &diff || &readonly return endif @@ -1020,8 +1045,8 @@ function! vimwiki#base#update_listing_in_buffer(strings, start_header, " fold gets deleted. So we temporarily disable folds, and then reenable " them right back. let foldenable_save = &l:foldenable - setlo nofoldenable - silent exe start_lnum.','.string(end_lnum - 1).'delete _' + setlocal nofoldenable + silent exe 'keepjumps ' . start_lnum.','.string(end_lnum - 1).'delete _' let &l:foldenable = foldenable_save let lines_diff = 0 - (end_lnum - start_lnum) else @@ -1036,16 +1061,16 @@ function! vimwiki#base#update_listing_in_buffer(strings, start_header, let new_header = whitespaces_in_first_line \ . s:safesubstitute(vimwiki#vars#get_syntaxlocal('rxH1_Template'), \ '__Header__', a:start_header, '') - call append(start_lnum - 1, new_header) + keepjumps call append(start_lnum - 1, new_header) let start_lnum += 1 let lines_diff += 1 + len(a:strings) for string in a:strings - call append(start_lnum - 1, string) + keepjumps call append(start_lnum - 1, string) let start_lnum += 1 endfor " append an empty line if there is not one if start_lnum <= line('$') && getline(start_lnum) !~# '\m^\s*$' - call append(start_lnum - 1, '') + keepjumps call append(start_lnum - 1, '') let lines_diff += 1 endif @@ -1077,8 +1102,10 @@ function! vimwiki#base#find_prev_link() endfunction -" This is an API function, that is, remappable by the user. Don't change the signature. -function! vimwiki#base#follow_link(split, reuse, move_cursor, ...) +function! vimwiki#base#follow_link(split, ...) + let reuse_other_split_window = a:0 >= 1 ? a:1 : 0 + let move_cursor_to_new_window = a:0 >= 2 ? a:2 : 1 + " Parse link at cursor and pass to VimwikiLinkHandler, or failing that, the " default open_link handler @@ -1114,7 +1141,7 @@ function! vimwiki#base#follow_link(split, reuse, move_cursor, ...) " if we want to and can reuse a split window, jump to that window and open " the new file there - if (a:split ==# 'hsplit' || a:split ==# 'vsplit') && a:reuse + if (a:split ==# 'hsplit' || a:split ==# 'vsplit') && reuse_other_split_window let previous_window_nr = winnr('#') if previous_window_nr > 0 && previous_window_nr != winnr() execute previous_window_nr . 'wincmd w' @@ -1138,7 +1165,7 @@ function! vimwiki#base#follow_link(split, reuse, move_cursor, ...) call vimwiki#base#open_link(cmd, lnk) - if !a:move_cursor + if !move_cursor_to_new_window if (a:split ==# 'hsplit' || a:split ==# 'vsplit') execute 'wincmd p' elseif a:split ==# 'tab' @@ -1147,8 +1174,8 @@ function! vimwiki#base#follow_link(split, reuse, move_cursor, ...) endif else - if a:0 > 0 - execute "normal! ".a:1 + if a:0 >= 3 + execute "normal! ".a:3 else call vimwiki#base#normalize_link(0) endif @@ -1247,12 +1274,10 @@ function! vimwiki#base#rename_link() let new_link = input('Enter new name: ') if new_link =~# '[/\\]' - " It is actually doable but I do not have free time to do it. echomsg 'Vimwiki Error: Cannot rename to a filename with path!' return endif - " check new_fname - it should be 'good', not empty if substitute(new_link, '\s', '', 'g') == '' echomsg 'Vimwiki Error: Cannot rename to an empty filename!' return @@ -1264,6 +1289,7 @@ function! vimwiki#base#rename_link() endif let new_link = subdir.new_link + let wiki_nr = vimwiki#vars#get_bufferlocal("wiki_nr") let new_fname = vimwiki#vars#get_wikilocal('path') . new_link . vimwiki#vars#get_wikilocal('ext') " do not rename if file with such name exists @@ -1307,7 +1333,7 @@ function! vimwiki#base#rename_link() setlocal nomore " update links - call s:update_wiki_links(s:tail_name(old_fname), new_link) + call s:update_wiki_links(wiki_nr, s:tail_name(old_fname), s:tail_name(new_link),old_fname) " restore wiki buffers for bitem in blist @@ -1760,13 +1786,31 @@ endfunction " a:create == 0: update if TOC exists function! vimwiki#base#table_of_contents(create) let headers = s:collect_headers() + let toc_header_text = vimwiki#vars#get_global('toc_header') + + if !a:create + " Do nothing if there is no TOC to update. (This is a small performance optimization -- if + " auto_toc == 1, but the current buffer has no TOC but is long, saving the buffer could + " otherwise take a few seconds for nothing.) + let toc_already_present = 0 + for entry in headers + if entry[2] ==# toc_header_text + let toc_already_present = 1 + break + endif + endfor + if !toc_already_present + return + endif + endif + let numbering = vimwiki#vars#get_global('html_header_numbering') let headers_levels = [['', 0], ['', 0], ['', 0], ['', 0], ['', 0], ['', 0]] let complete_header_infos = [] for header in headers let h_text = header[2] let h_level = header[1] - if h_text ==# vimwiki#vars#get_global('toc_header') " don't include the TOC's header itself + if h_text ==# toc_header_text " don't include the TOC's header itself continue endif let headers_levels[h_level-1] = [h_text, headers_levels[h_level-1][1]+1] @@ -1794,18 +1838,20 @@ function! vimwiki#base#table_of_contents(create) let indentstring = repeat(' ', vimwiki#u#sw()) let bullet = vimwiki#lst#default_symbol().' ' for [lvl, link, desc] in complete_header_infos - let esc_link = substitute(link, "'", "''", 'g') - let esc_desc = substitute(desc, "'", "''", 'g') - let link = s:safesubstitute(vimwiki#vars#get_global('WikiLinkTemplate2'), '__LinkUrl__', - \ '#'.esc_link, '') - let link = s:safesubstitute(link, '__LinkDescription__', esc_desc, '') + if vimwiki#vars#get_wikilocal('syntax') == 'markdown' + let link_tpl = vimwiki#vars#get_syntaxlocal('Weblink1Template') + else + let link_tpl = vimwiki#vars#get_global('WikiLinkTemplate2') + endif + let link = s:safesubstitute(link_tpl, '__LinkUrl__', + \ '#'.link, '') + let link = s:safesubstitute(link, '__LinkDescription__', desc, '') call add(lines, startindent.repeat(indentstring, lvl-1).bullet.link) endfor let links_rx = '\m^\s*'.vimwiki#u#escape(vimwiki#lst#default_symbol()).' ' - call vimwiki#base#update_listing_in_buffer(lines, - \ vimwiki#vars#get_global('toc_header'), links_rx, 1, a:create) + call vimwiki#base#update_listing_in_buffer(lines, toc_header_text, links_rx, 1, a:create) endfunction @@ -1830,17 +1876,21 @@ endfunction function! s:clean_url(url) - let url = split(a:url, '/\|=\|-\|&\|?\|\.') + " remove protocol and tld + let url = substitute(a:url, '^\a\+\d*:', '', '') + let url = substitute(url, '^//', '', '') + let url = substitute(url, '^\([^/]\+\)\.\a\{2,4}/', '\1/', '') + let url = split(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\:"') + if url[0] == "www" + let url = url[1:] + endif + if url[-1] =~ '^\(htm\|html\|php\)$' + let url = url[0:-2] + endif + " remove words consisting of only hexadecimal digits or non-word characters + let url = filter(url, 'v:val !~ "^\\A\\{4,}$"') + let url = filter(url, 'v:val !~ "^\\x\\{4,}$" || v:val !~ "\\d"') return join(url, " ") endfunction @@ -1881,12 +1931,12 @@ function! s:normalize_link_in_diary(lnk) let link_exists_in_wiki = filereadable(link_wiki) let link_is_date = a:lnk =~# '\d\d\d\d-\d\d-\d\d' - if ! link_exists_in_wiki || link_exists_in_diary || link_is_date + if link_exists_in_diary || link_is_date let str = a:lnk let rxUrl = vimwiki#vars#get_global('rxWord') let rxDesc = '' let template = vimwiki#vars#get_global('WikiLinkTemplate1') - else + elseif link_exists_in_wiki let relative_link = \ vimwiki#path#relpath(vimwiki#vars#get_wikilocal('diary_path'), \ vimwiki#vars#get_wikilocal('path')) @@ -1894,6 +1944,11 @@ function! s:normalize_link_in_diary(lnk) let rxUrl = '^.*\ze|' let rxDesc = '|\zs.*$' let template = vimwiki#vars#get_global('WikiLinkTemplate2') + else + let str = a:lnk + let rxUrl = '.*' + let rxDesc = '' + let template = vimwiki#vars#get_global('WikiLinkTemplate1') endif return vimwiki#base#normalize_link_helper(str, rxUrl, rxDesc, template) @@ -1937,9 +1992,8 @@ function! s:normalize_link_syntax_n() if s:is_diary_file(expand("%:p")) let sub = s:normalize_link_in_diary(lnk) else - let sub = vimwiki#base#normalize_link_helper(lnk, - \ vimwiki#vars#get_global('rxWord'), '', - \ vimwiki#vars#get_global('WikiLinkTemplate1')) + let sub = s:safesubstitute( + \ vimwiki#vars#get_global('WikiLinkTemplate1'), '__LinkUrl__', lnk, '') endif call vimwiki#base#replacestr_at_cursor('\V'.lnk, sub) return diff --git a/autoload/vimwiki/diary.vim b/autoload/vimwiki/diary.vim index dd154ec..5476ae5 100644 --- a/autoload/vimwiki/diary.vim +++ b/autoload/vimwiki/diary.vim @@ -149,17 +149,21 @@ function! s:format_diary() \ '__Header__', s:get_month_name(month), '')) for [fl, cap] in s:sort(items(g_files[year][month])) - if empty(cap) - let entry = substitute(vimwiki#vars#get_global('WikiLinkTemplate1'), - \ '__LinkUrl__', fl, '') - let entry = substitute(entry, '__LinkDescription__', cap, '') - call add(result, repeat(' ', vimwiki#lst#get_list_margin()).'* '.entry) - else - let entry = substitute(vimwiki#vars#get_global('WikiLinkTemplate2'), - \ '__LinkUrl__', fl, '') - let entry = substitute(entry, '__LinkDescription__', cap, '') - call add(result, repeat(' ', vimwiki#lst#get_list_margin()).'* '.entry) + let link_tpl = vimwiki#vars#get_global('WikiLinkTemplate2') + + if vimwiki#vars#get_wikilocal('syntax') == 'markdown' + let link_tpl = vimwiki#vars#get_syntaxlocal('Weblink1Template') + + if empty(cap) " When using markdown syntax, we should ensure we always have a link description. + let cap = fl + endif + elseif empty(cap) + let link_tpl = vimwiki#vars#get_global('WikiLinkTemplate1') endif + + let entry = substitute(link_tpl, '__LinkUrl__', fl, '') + let entry = substitute(entry, '__LinkDescription__', cap, '') + call add(result, repeat(' ', vimwiki#lst#get_list_margin()).'* '.entry) endfor endfor @@ -169,20 +173,27 @@ function! s:format_diary() endfunction +" The given wiki number a:wnum is 1 for the first wiki, 2 for the second and so on. This is in +" contrast to most other places, where counting starts with 0. When a:wnum is 0, the current wiki +" is used. function! vimwiki#diary#make_note(wnum, ...) - if a:wnum > vimwiki#vars#number_of_wikis() - echomsg 'Vimwiki Error: Wiki '.a:wnum.' is not registered in g:vimwiki_list!' + if a:wnum == 0 + let wiki_nr = vimwiki#vars#get_bufferlocal('wiki_nr') + if wiki_nr < 0 " this happens when e.g. VimwikiMakeDiaryNote was called outside a wiki buffer + let wiki_nr = 0 + endif + else + let wiki_nr = a:wnum - 1 + endif + + if wiki_nr >= vimwiki#vars#number_of_wikis() + echomsg 'Vimwiki Error: Wiki '.wiki_nr.' 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#path#mkdir(vimwiki#vars#get_wikilocal('diary_path', idx)) + call vimwiki#path#mkdir(vimwiki#vars#get_wikilocal('diary_path', wiki_nr)) let cmd = 'edit' if a:0 @@ -200,7 +211,7 @@ function! vimwiki#diary#make_note(wnum, ...) let link = 'diary:'.vimwiki#diary#diary_date_link() endif - call vimwiki#base#open_link(cmd, link, s:diary_index(idx)) + call vimwiki#base#open_link(cmd, link, s:diary_index(wiki_nr)) endfunction @@ -218,6 +229,11 @@ function! vimwiki#diary#goto_diary_index(wnum) endif call vimwiki#base#edit_file('e', s:diary_index(idx), '') + + if vimwiki#vars#get_wikilocal('auto_diary_index') + call vimwiki#diary#generate_diary_section() + write! " save changes + endif endfunction @@ -295,8 +311,7 @@ function! vimwiki#diary#calendar_action(day, month, year, week, dir) endif endif - " XXX: Well, +1 is for inconsistent index basing... - call vimwiki#diary#make_note(vimwiki#vars#get_bufferlocal('wiki_nr')+1, 0, link) + call vimwiki#diary#make_note(0, 0, link) endfunction diff --git a/autoload/vimwiki/html.vim b/autoload/vimwiki/html.vim index 197ac11..ddb8cb2 100644 --- a/autoload/vimwiki/html.vim +++ b/autoload/vimwiki/html.vim @@ -183,13 +183,6 @@ function! s:subst_func(line, regexp, func, ...) endfunction -function! s:save_vimwiki_buffer() - if &filetype ==? 'vimwiki' && filewritable(expand('%')) - silent update - endif -endfunction - - function! s:process_date(placeholders, default_date) if !empty(a:placeholders) for [placeholder, row, idx] in a:placeholders @@ -346,7 +339,7 @@ endfunction function! s:linkify_link(src, descr) let src_str = ' href="'.s:escape_html_attribute(a:src).'"' - let descr = substitute(a:descr,'^\s*\(.*\)\s*$','\1','') + let descr = vimwiki#u#trim(a:descr) let descr = (descr == "" ? a:src : descr) let descr_str = (descr =~# vimwiki#vars#get_global('rxWikiIncl') \ ? s:tag_wikiincl(descr) @@ -419,7 +412,8 @@ function! s:tag_wikilink(value) let str = a:value let url = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl')) let descr = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchDescr')) - let descr = (substitute(descr,'^\s*\(.*\)\s*$','\1','') != '' ? descr : url) + let descr = vimwiki#u#trim(descr) + let descr = (descr != '' ? descr : url) let line = VimwikiLinkConverter(url, s:current_wiki_file, s:current_html_file) if line == '' @@ -814,7 +808,7 @@ function! s:process_tag_math(line, math) " environment properly let s:current_math_env = matchstr(class, '^%\zs\S\+\ze%') if s:current_math_env != "" - call add(lines, substitute(class, '^%\(\S\+\)%','\\begin{\1}', '')) + call add(lines, substitute(class, '^%\(\S\+\)%', '\\begin{\1}', '')) elseif class != "" call add(lines, "\\\[".class) else @@ -1560,9 +1554,11 @@ function! vimwiki#html#WikiAll2HTML() echomsg 'Vimwiki: Saving Vimwiki files ...' let save_eventignore = &eventignore let &eventignore = "all" - let cur_buf = bufname('%') - bufdo call s:save_vimwiki_buffer() - exe 'buffer '.cur_buf + try + wall + catch + " just ignore errors + endtry let &eventignore = save_eventignore let path_html = vimwiki#vars#get_wikilocal('path_html') diff --git a/autoload/vimwiki/lst.vim b/autoload/vimwiki/lst.vim index d4ccbbd..201a658 100644 --- a/autoload/vimwiki/lst.vim +++ b/autoload/vimwiki/lst.vim @@ -299,6 +299,13 @@ function! s:regexp_of_marker(item) endfunction +" Returns: Whether or not the checkbox of a list item is [X] or [-] +function! s:is_closed(item) + let state = a:item.cb + return state ==# vimwiki#vars#get_syntaxlocal('listsyms_list')[-1] + \ || state ==# vimwiki#vars#get_global('listsym_rejected') +endfunction + " --------------------------------------------------------- " functions for navigating between items " --------------------------------------------------------- @@ -756,10 +763,47 @@ function! s:set_state(item, new_rate) endfunction -"Set state of the list item to [ ] or [o] or whatever -"Updates the states of its child items -function! s:set_state_plus_children(item, new_rate) - call s:set_state(a:item, a:new_rate) +" Sets the state of the list item to [ ] or [o] or whatever. Updates the states of its child items. +" If the new state should be [X] or [-], the state of the current list item is changed to this +" state, but if a child item already has [X] or [-] it is left alone. +function! s:set_state_plus_children(item, new_rate, ...) + let retain_state_if_closed = a:0 > 0 && a:1 > 0 + + if !(retain_state_if_closed && (a:new_rate == 100 || a:new_rate == -1) && s:is_closed(a:item)) + call s:set_state(a:item, a:new_rate) + endif + + let all_children_are_done = 1 + let all_children_are_rejected = 1 + + let child_item = s:get_first_child(a:item) + while 1 + if child_item.type == 0 + break + endif + if child_item.cb != vimwiki#vars#get_global('listsym_rejected') + let all_children_are_rejected = 0 + endif + if child_item.cb != vimwiki#vars#get_syntaxlocal('listsyms_list')[-1] + let all_children_are_done = 0 + endif + if !all_children_are_done && !all_children_are_rejected + break + endif + let child_item = s:get_next_child_item(a:item, child_item) + endwhile + + if (a:new_rate == 100 && all_children_are_done) || + \ (a:new_rate == -1) && all_children_are_rejected + return + endif + + if (a:new_rate == -1 && all_children_are_done) || + \ (a:new_rate == 100 && all_children_are_rejected) + let retain_closed_children = 0 + else + let retain_closed_children = 1 + endif let child_item = s:get_first_child(a:item) while 1 @@ -767,7 +811,7 @@ function! s:set_state_plus_children(item, new_rate) break endif if child_item.cb != '' - call s:set_state_plus_children(child_item, a:new_rate) + call s:set_state_plus_children(child_item, a:new_rate, retain_closed_children) endif let child_item = s:get_next_child_item(a:item, child_item) endwhile @@ -802,6 +846,7 @@ function! s:update_state(item) let sum_children_rate = 0 let count_children_with_cb = 0 + let count_rejected_children = 0 let child_item = s:get_first_child(a:item) @@ -811,16 +856,24 @@ function! s:update_state(item) endif if child_item.cb != '' let rate = s:get_rate(child_item) - if rate != -1 - let count_children_with_cb += 1 - let sum_children_rate += rate + if rate == -1 + " for calculating the parent rate, a [-] item counts as much as a [X] item ... + let rate = 100 + " ... with the exception that a parent with *only* [-] items will be [-] too + let count_rejected_children += 1 endif + let count_children_with_cb += 1 + let sum_children_rate += rate endif let child_item = s:get_next_child_item(a:item, child_item) endwhile if count_children_with_cb > 0 - let new_rate = sum_children_rate / count_children_with_cb + if count_rejected_children == count_children_with_cb + let new_rate = -1 + else + let new_rate = sum_children_rate / count_children_with_cb + endif call s:set_state_recursively(a:item, new_rate) else let rate = s:get_rate(a:item) @@ -841,13 +894,13 @@ endfunction "Creates checkbox in a list item. "Returns: 1 if successful -function! s:create_cb(item) +function! s:create_cb(item, start_rate) if a:item.type == 0 || a:item.cb != '' return 0 endif let new_item = a:item - let new_item.cb = vimwiki#vars#get_syntaxlocal('listsyms_list')[0] + let new_item.cb = s:rate_to_state(a:start_rate) call s:substitute_rx_in_line(new_item.lnum, \ vimwiki#u#escape(new_item.mrkr) . '\zs\ze', ' [' . new_item.cb . ']') @@ -866,8 +919,7 @@ function! s:remove_cb(item) endfunction -"Change state of checkbox -"in the lines of the given range +" Change state of the checkboxes in the lines of the given range function! s:change_cb(from_line, to_line, new_rate) let from_item = s:get_corresponding_item(a:from_line) if from_item.type == 0 @@ -894,9 +946,9 @@ function! s:change_cb(from_line, to_line, new_rate) endfunction -"Toggles checkbox between two states in the lines of the given range, -"creates chceckboxes if there aren't any. -function! s:toggle_create_cb(from_line, to_line, state1, state2) +" Toggles checkbox between two states in the lines of the given range, creates checkboxes (with +" a:start_rate as state) if there aren't any. +function! s:toggle_create_cb(from_line, to_line, state1, state2, start_rate) let from_item = s:get_corresponding_item(a:from_line) if from_item.type == 0 return @@ -908,7 +960,7 @@ function! s:toggle_create_cb(from_line, to_line, state1, state2) let parent_items_of_lines = [] for cur_ln in range(from_item.lnum, a:to_line) let cur_item = s:get_item(cur_ln) - let success = s:create_cb(cur_item) + let success = s:create_cb(cur_item, a:start_rate) if success let cur_parent_item = s:get_parent(cur_item) @@ -974,46 +1026,14 @@ endfunction "Toggles checkbox between [ ] and [X] or creates one "in the lines of the given range function! vimwiki#lst#toggle_cb(from_line, to_line) - return s:toggle_create_cb(a:from_line, a:to_line, 100, 0) + return s:toggle_create_cb(a:from_line, a:to_line, 100, 0, 0) endfunction "Toggles checkbox between [ ] and [-] or creates one "in the lines of the given range function! vimwiki#lst#toggle_rejected_cb(from_line, to_line) - return s:toggle_create_cb(a:from_line, a:to_line, -1, 0) -endfunction - - -"Increment checkbox between [ ] and [X] -"in the lines of the given range -function! vimwiki#lst#increment_cb(from_line, to_line) - let from_item = s:get_corresponding_item(a:from_line) - if from_item.type == 0 - return - endif - - "if from_line has CB, increment it and set all siblings to the same new state - let rate_first_line = s:get_rate(from_item) - let n = len(vimwiki#vars#get_syntaxlocal('listsyms_list')) - let new_rate = min([rate_first_line + 100/(n-1)+1, 100]) - - call s:change_cb(a:from_line, a:to_line, new_rate) - -endfunction - - -"Toggles checkbox between [ ] and [X] or creates one -"in the lines of the given range -function! vimwiki#lst#toggle_cb(from_line, to_line) - return s:toggle_create_cb(a:from_line, a:to_line, 100, 0) -endfunction - - -"Toggles checkbox between [ ] and [-] or creates one -"in the lines of the given range -function! vimwiki#lst#toggle_rejected_cb(from_line, to_line) - return s:toggle_create_cb(a:from_line, a:to_line, -1, 0) + return s:toggle_create_cb(a:from_line, a:to_line, -1, 0, -1) endfunction @@ -1395,7 +1415,7 @@ function! s:clone_marker_from_to(from, to) let new_indent = ( vimwiki#vars#get_syntaxlocal('recurring_bullets') ? 0 : indent(a:from) ) call s:set_indent(a:to, new_indent) if item_from.cb != '' - call s:create_cb(s:get_item(a:to)) + call s:create_cb(s:get_item(a:to), 0) call s:update_state(s:get_parent(s:get_item(a:to))) endif if item_from.type == 2 diff --git a/autoload/vimwiki/vars.vim b/autoload/vimwiki/vars.vim index d6f6480..7a200e1 100644 --- a/autoload/vimwiki/vars.vim +++ b/autoload/vimwiki/vars.vim @@ -13,7 +13,7 @@ " global user variables and syntax stuff which is the same for every syntax. " " - wiki-local variables. They are stored in g:vimwiki_wikilocal_vars which is a list of -" dictionaries. One dict for every registered wiki. The last dictionary contains default values +" dictionaries, one dict for every registered wiki. The last dictionary contains default values " (used for temporary wikis). " " - syntax variables. Stored in the dict g:vimwiki_syntax_variables which holds all the regexes and @@ -28,82 +28,38 @@ function! s:populate_global_variables() - let g:vimwiki_global_vars = { - \ 'CJK_length': 0, - \ 'auto_chdir': 0, - \ 'autowriteall': 1, - \ 'conceallevel': 2, - \ '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' - \ }, - \ 'dir_link': '', - \ 'ext2syntax': {}, - \ 'folding': '', - \ 'global_ext': 1, - \ 'hl_cb_checked': 0, - \ 'hl_headers': 0, - \ 'html_header_numbering': 0, - \ 'html_header_numbering_sym': '', - \ 'list_ignore_newline': 1, - \ 'text_ignore_newline': 1, - \ 'listsyms': ' .oOX', - \ 'listsym_rejected': '-', - \ 'map_prefix': 'w', - \ 'menu': 'Vimwiki', - \ 'table_auto_fmt': 1, - \ 'table_mappings': 1, - \ 'toc_header': 'Contents', - \ 'url_maxsave': 15, - \ 'use_calendar': 1, - \ 'use_mouse': 0, - \ 'user_htmls': '', - \ 'valid_html_tags': 'b,i,s,u,sub,sup,kbd,br,hr,div,center,strong,em', - \ 'w32_dir_enc': '', - \ } + let g:vimwiki_global_vars = {} - " copy the user's settings from variables of the form g:vimwiki_