diff --git a/etc/soft/nvim/+plugins/vimwiki/CONTRIBUTING.md b/etc/soft/nvim/+plugins/vimwiki/CONTRIBUTING.md new file mode 100644 index 0000000..1685084 --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/CONTRIBUTING.md @@ -0,0 +1,63 @@ +# 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.) + +Make sure to update `doc/vimwiki.txt` with the following information: + +1. Update the changelog to include information on the new feature the PR introduces or the bug it + is fixing. +2. Add a help section to describe any new features or options. +2. If you are a first time contributor add your name to the list of contributors. + +# More info and advice for (aspiring) core developers + +- Before implementing a non-trivial feature, think twice what it means for the user. We should + always try to keep backward compatibility. If you are not sure, discuss it on GitHub. +- Also, when thinking about adding a new feature, it should be something which fits into the + overall design of Vimwiki and which a significant portion of the users may like. Keep in mind + that everybody has their own way to use Vimwiki. +- Keep the coding style consistent. +- Test your changes. Keep in mind that Vim has a ton of options and the users tons of different + setups. Take a little time to think about under which circumstances your changes could break. + +## 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 branch 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/etc/soft/nvim/+plugins/vimwiki/LICENSE.md b/etc/soft/nvim/+plugins/vimwiki/LICENSE.md new file mode 100644 index 0000000..cdf8546 --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/LICENSE.md @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2008-2010 Maxim Kim + 2013-2017 Daniel Schemala + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/etc/soft/nvim/+plugins/vimwiki/README-cn.md b/etc/soft/nvim/+plugins/vimwiki/README-cn.md new file mode 100644 index 0000000..5d1a064 --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/README-cn.md @@ -0,0 +1,161 @@ +VimWiki —— Vim 个人 Wiki 插件 +============================================================================== + +[English](README.md) + +![screenshot1](doc/screenshot_1.png) +![screenshot2](doc/screenshot_2.png) * + +介绍 +------------------------------------------------------------------------------ + +Vimwiki 是 Vim 中的个人 Wiki —— 一组链接起来的、有独特语法高亮的文本文件。 + +通过 Vimwiki,你可以: + + * 组织笔记和想法 + * 管理待办事项 + * 编写文档 + * 坚持写日记 + * 将这一切导出成 HTML 网页 + +马上开始!按下 `ww`(通常是 `\ww`)进入作为目录页的 wiki 文件,这个文件默认存放在 `~/vimwiki/index.wiki`。 + +在该文件中输入以下示例: + + = 我的个人知识库 = + * 任务列表 -- _昨天_ 就该完成的事!!! + * Gutenberg 计划 -- 好书给我力量。 + * 草稿 -- 临时记录一些东西。 + +把光标移到 `任务` 二字上,按 Enter(回车)创建链接。按下后,`任务`二字会变成 `[[任务]]` —— 这是一个 Vimwiki 链接。再次按 Enter 即可进入这个链接(打开新的 wiki 文件)。编辑这个新文件,保存,然后按 Backspace(退格)就能回到目录页。 + +如果 Vimwiki 链接长度不止一个单词(指的是英文单词),只需在 Visual 模式选择这段文本后按 Enter 即可。用上面的 `Gutenberg 计划` 试试吧。最终结果是这样: + + = 我的个人知识库 = + * [[任务列表]] -- _昨天_ 就该完成的事!!! + * [[Gutenberg 计划]] -- 好书给我力量。 + * 草稿 -- 临时记录一些东西。 + + +基本标记 +------------------------------------------------------------------------------ + + = 一级标题 = + == 二级标题 == + === 三级标题 === + + + *bold* -- 粗体文本 + _italic_ -- 斜体文本 + (应用于句中的汉字文本时,必须在标记前后加空格,例如:一段 *中文* 文本) + + [[wiki link]] -- wiki 链接 + [[wiki link|description]] -- 带有描述文本的 wiki 链接 + + +列表: + + * bullet list item 1(无编号列表) + - bullet list item 2 + - bullet list item 3 + * bullet list item 4 + * bullet list item 5 + * bullet list item 6 + * bullet list item 7 + - bullet list item 8 + - bullet list item 9 + + 1. numbered list item 1(有编号列表) + 2. numbered list item 2 + a) numbered list item 3 + b) numbered list item 4 + + +更多格式说明,请阅 `:h vimwiki-syntax` + + +键位绑定 +------------------------------------------------------------------------------ + +normal 模式: + + * `ww` -- 打开默认的 wiki 目录文件 + * `wt` -- 在新标签(Tab)中打开 wiki 目录文件 + * `ws` -- 在多个 wiki 中选择并打开该 wiki 的目录文件 + * `wd` -- 删除当前 wiki 文件 + * `wr` -- 重命名当前 wiki 文件 + * `` -- 创建或打开 wiki 链接 + * `` -- 先上下分屏再打开 wiki 链接(若非链接则先创建) + * `` -- 先左右分屏再打开 wiki 链接(若非链接则先创建) + * `` -- 返回之前浏览的 wiki 文件 + * `` -- 跳到本文件中下一个 wiki 链接 + * `` -- 跳到本文件中上一个 wiki 链接 + +更多快捷键说明,请阅 `:h vimwiki-mappings` + + +命令 +------------------------------------------------------------------------------ + + * `:Vimwiki2HTML` -- 将当前 wiki 文件转换成 HTML 网页 + * `:VimwikiAll2HTML` -- 把所有 wiki 文件转换成 HTML 网页 + * `:help vimwiki-commands` -- 显示全部命令 + + +安装 +============================================================================== + +准备工作 +------------------------------------------------------------------------------ + +确保在 `vimrc` 中加入了以下设置: + + set nocompatible + filetype plugin on + syntax on + +没有这些设置,Vimwiki 将无法正常工作。 + +通过 [Vim packages](http://vimhelp.appspot.com/repeat.txt.html#packages) 安装(Vim 7.4.1528 后) +------------------------------------------------------------------------------ + + git clone https://github.com/vimwiki/vimwiki.git ~/.vim/pack/plugins/start/vimwiki + +通过 [Pathogen](http://www.vim.org/scripts/script.php?script_id=2332) 安装 +------------------------------------------------------------------------------ + + cd ~/.vim + mkdir bundle + cd bundle + git clone https://github.com/vimwiki/vimwiki.git + +通过 [Vim-Plug](https://github.com/junegunn/vim-plug) 安装 +------------------------------------------------------------------------------ + +在 `vimrc` 中加入以下插件设置: + + Plug 'vimwiki/vimwiki' + +然后运行 `:PlugInstall`。 + +通过 [Vundle](https://github.com/VundleVim/Vundle.vim) 安装 +------------------------------------------------------------------------------ + +在 `vimrc` 中加入 `Plugin 'vimwiki/vimwiki'`,然后执行: + + vim +PluginInstall +qall + +或者下载 [zip 压缩包](https://github.com/vimwiki/vimwiki/archive/master.zip)然后解压到 `~/.vim/bundle/` 目录下。 + +安装后,启动 Vim 并执行 `:Helptags` 以及 `:help vimwiki`,检查安装是否成功。 + + +获取帮助 +============================================================================== + +遇到问题?在 Freenode 的 IRC 频道 `#vimwiki`([网页聊天](https://webchat.freenode.net/?channels=#vimwiki))提问,或者发送问题到[邮件列表](https://groups.google.com/forum/#!forum/vimwiki)上吧。 + + +---- +\* 前面截图中用的是 [solarized 配色方案](https://github.com/altercation/vim-colors-solarized)以及 [lightline](https://github.com/itchyny/lightline.vim) 插件。 diff --git a/etc/soft/nvim/+plugins/vimwiki/README.md b/etc/soft/nvim/+plugins/vimwiki/README.md new file mode 100644 index 0000000..6edd731 --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/README.md @@ -0,0 +1,250 @@ +# VimWiki: A Personal Wiki For Vim + +[中文](README-cn.md) + +- [Intro](#intro) +- [Installation](#installation) + - [Prerequisites](#prerequisites) + - [VIM Packages](#installation-using-vim-packages-since-vim-741528) + - [Pathogen](#installation-using-pathogen) + - [Vim-Plug](#installation-using-vim-plug) + - [Vundle](#installation-using-vundle) +- [Basic Markup](#basic-markup) + - [Lists](#lists) +- [Key Bindings](#key-bindings) +- [Commands](#commands) +- [Changing Wiki Syntax](#changing-wiki-syntax) +- [Getting Help](#getting-help) +- [Helping VimWiki](#helping-vimwiki) +- [Wiki](https://github.com/vimwiki/vimwiki/wiki) +- [License](#license) + +## 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 to-do lists + * Write documentation + * Maintain a diary + * Export everything to HTML + +To do a quick start press `ww` (this is usually `\ww`) to go to your +index wiki file. By default it is located in `~/vimwiki/index.wiki`. + +Feed it with the following example: + +``` + += My knowledge base = + * 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. + +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. + +``` + +## Screenshots + +![Lists View](doc/lists.png) +![Entries View](doc/entries.png) +![Todos View](doc/todos.png) +![Wiki View](doc/wiki.png) + +## Installation + +### Prerequisites + +Make sure you have these settings in your vimrc file: + +```vim + +set nocompatible +filetype plugin on +syntax on + +``` + +Without them VimWiki will not work properly. + + +#### Installation using [Vim packages](http://vimhelp.appspot.com/repeat.txt.html#packages) (since Vim 7.4.1528) + +```sh + +git clone https://github.com/vimwiki/vimwiki.git ~/.vim/pack/plugins/start/vimwiki + +``` + +#### Installation using [Pathogen](http://www.vim.org/scripts/script.php?script_id=2332) + +```sh + +cd ~/.vim +mkdir bundle +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: + +```vim + +Plug 'vimwiki/vimwiki' + +``` + +Then run `:PlugInstall`. + +#### Installation using [Vundle](https://github.com/VundleVim/Vundle.vim) + +Add `Plugin 'vimwiki/vimwiki'` to your vimrc file and run + +```sh + +vim +PluginInstall +qall + +``` + +Or download the [zip +archive](https://github.com/vimwiki/vimwiki/archive/master.zip) and extract it +in `~/.vim/bundle/` + +Then launch Vim, run `:Helptags` and then `:help vimwiki` to verify it was +installed. + +## Basic Markup + +``` += Header1 = +== Header2 == +=== Header3 === + + +*bold* -- bold text +_italic_ -- italic text + +[[wiki link]] -- wiki link +[[wiki link|description]] -- wiki link with description +``` + +### Lists: + +``` +* bullet list item 1 + - bullet list item 2 + - bullet list item 3 + * bullet list item 4 + * bullet list item 5 +* bullet list item 6 +* bullet list item 7 + - bullet list item 8 + - bullet list item 9 + +1. numbered list item 1 +2. numbered list item 2 + a) numbered list item 3 + b) numbered list item 4 +``` + +For other syntax elements, see `:h vimwiki-syntax` + +## Key bindings + +Normal mode: + + * `ww` -- Open default wiki index file. + * `wt` -- Open default wiki index file in a new tab. + * `ws` -- Select and open wiki index file. + * `wd` -- Delete wiki file you are in. + * `wr` -- Rename wiki file you are in. + * `` -- Follow/Create wiki link + * `` -- Split and follow/create wiki link + * `` -- Vertical split and follow/create wiki link + * `` -- Go back to parent(previous) wiki link + * `` -- Find next wiki link + * `` -- Find previous wiki link + +For more keys, see `:h vimwiki-mappings` + +## 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: + +```vim + +let g:vimwiki_list = [{'path': '~/vimwiki/', + \ 'syntax': 'markdown', 'ext': '.md'}] + +``` + +## Getting help + +**Have a question?** +Visit the IRC channel [`#vimwiki`](https://webchat.freenode.net/?channels=#vimwiki) on Freenode ([webchat](https://webchat.freenode.net/?channels=#vimwiki), also synced to Matrix/Riot: `#vimwiki:matrix.org`) or post to the [mailing list](https://groups.google.com/forum/#!forum/vimwiki). + +## Helping VimWiki + +VimWiki has a lot of users but only very few recurring developers or people +helping the community. Your help is therefore appreciated. Everyone can help! +See [#625](https://github.com/vimwiki/vimwiki/issues/625) for information on +how you can help. + +## License + +MIT License + +Copyright (c) 2008-2010 Maxim Kim + 2013-2017 Daniel Schemala + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/base.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/base.vim index fc6168f..7986609 100644 --- a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/base.vim +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/base.vim @@ -1,242 +1,796 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Author: Maxim Kim -" Home: http://code.google.com/p/vimwiki/ +" Desc: Basic functionality +" Home: https://github.com/vimwiki/vimwiki/ if exists("g:loaded_vimwiki_auto") || &cp finish 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.'<>|?*:"]' +function! s:safesubstitute(text, search, replace, mode) + " Substitute regexp but do not interpret replace + let escaped = escape(a:replace, '\&') + return substitute(a:text, a:search, escaped, a:mode) +endfunction -" MISC helper functions {{{ -function! vimwiki#base#chomp_slash(str) "{{{ - return substitute(a:str, '[/\\]\+$', '', '') -endfunction "}}} +function! s:vimwiki_get_known_syntaxes() + " Getting all syntaxes that different wikis could have + let syntaxes = {} + let syntaxes['default'] = 1 + for wiki_nr in range(vimwiki#vars#number_of_wikis()) + let wiki_syntax = vimwiki#vars#get_wikilocal('syntax', wiki_nr) + let syntaxes[wiki_syntax] = 1 + endfor + " also consider the syntaxes from g:vimwiki_ext2syntax + for syn in values(vimwiki#vars#get_global('ext2syntax')) + let syntaxes[syn] = 1 + endfor + return keys(syntaxes) +endfunction -function! vimwiki#base#path_norm(path) "{{{ - return substitute(a:path, '\', '/', 'g') -endfunction "}}} -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 = iconv(path, &enc, g:vimwiki_w32_dir_enc) - endif - call mkdir(path, "p") - endif +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: https://github.com/vimwiki-backup/vimwiki/issues/316 + " Change / to [/\\] to allow "Windows paths" + return '\V\%('.join(a:files, '\|').'\)\m' 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 -endfunction -"}}} -function! vimwiki#base#unsafe_link(string) "{{{ - if len(g:vimwiki_stripsym) > 0 - return substitute(a:string, g:vimwiki_stripsym, s:badsymbols, 'g') +"FIXME TODO slow and faulty +function! vimwiki#base#subdir(path, filename) + 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? + if a:filename !~# '^scp:' + let filename = resolve(a:filename) else - return a:string + let filename = a:filename endif -endfunction -"}}} - -function! vimwiki#base#subdir(path, filename)"{{{ - let path = expand(a:path) - let filename = expand(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"}}} +endfunction -function! vimwiki#base#current_subdir()"{{{ - return vimwiki#base#subdir(VimwikiGet('path'), expand('%:p')) -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) +function! vimwiki#base#current_subdir() + return vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path'), expand('%:p')) +endfunction + + +function! vimwiki#base#invsubdir(subdir) + return substitute(a:subdir, '[^/\.]\+/', '../', 'g') +endfunction + + +" Returns: the number of the wiki a file belongs to or -1 if it doesn't belong +" to any registered wiki. +" The path can be the full path or just the directory of the file +function! vimwiki#base#find_wiki(path) + let bestmatch = -1 + let bestlen = 0 + let path = vimwiki#path#path_norm(vimwiki#path#chomp_slash(a:path)) + for idx in range(vimwiki#vars#number_of_wikis()) + let idx_path = expand(vimwiki#vars#get_wikilocal('path', idx)) + let idx_path = vimwiki#path#path_norm(vimwiki#path#chomp_slash(idx_path)) + let common_pfx = vimwiki#path#path_common_pfx(idx_path, path) + if vimwiki#path#is_equal(common_pfx, idx_path) + if len(common_pfx) > bestlen + let bestlen = len(common_pfx) + let bestmatch = idx + endif endif + endfor + + return bestmatch +endfunction + + +" THE central function of Vimwiki. Extract infos about the target from a link. +" If the second parameter is present, which should be an absolute file path, it +" is assumed that the link appears in that file. Without it, the current file +" is used. +function! vimwiki#base#resolve_link(link_text, ...) + if a:0 + let source_wiki = vimwiki#base#find_wiki(a:1) + let source_file = a:1 else - if a:0 - let vimwiki_prev_link = [a:1, []] - elseif &ft == 'vimwiki' - let vimwiki_prev_link = [expand('%:p'), getpos('.')] + let source_wiki = vimwiki#vars#get_bufferlocal('wiki_nr') + let source_file = vimwiki#path#current_wiki_file() + endif + + let link_text = a:link_text + + + let link_infos = { + \ 'index': -1, + \ 'scheme': '', + \ 'filename': '', + \ 'anchor': '', + \ } + + if link_text == '' + return link_infos + endif + + 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' + let link_infos.filename = link_text " unknown scheme, may be a weblink + return link_infos 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) + let link_text = matchstr(link_text, '^'.vimwiki#vars#get_global('rxSchemes').':\zs.*\ze') + endif + + let is_wiki_link = link_infos.scheme =~# '\mwiki\d\+' || link_infos.scheme ==# 'diary' + + " extract anchor + if is_wiki_link + let split_lnk = split(link_text, '#', 1) + let link_text = split_lnk[0] + if len(split_lnk) > 1 && split_lnk[-1] != '' + let link_infos.anchor = join(split_lnk[1:], '#') + endif + if link_text == '' " because the link was of the form '#anchor' + let expected_ext = vimwiki#u#escape(vimwiki#vars#get_wikilocal('ext')).'$' + if source_file =~# expected_ext + " Source file has expected extension. Remove it, it will be added later on + let ext_len = strlen(vimwiki#vars#get_wikilocal('ext')) + let link_text = fnamemodify(source_file, ':p:t')[:-ext_len-1] + endif + + endif + endif + + " check if absolute or relative path + if is_wiki_link && link_text[0] == '/' + if link_text != '/' + let link_text = link_text[1:] + endif + let is_relative = 0 + elseif !is_wiki_link && vimwiki#path#is_absolute(link_text) + let is_relative = 0 + else + let is_relative = 1 + let root_dir = fnamemodify(source_file, ':p:h') . '/' + endif + + + " extract the other items depending on the scheme + if link_infos.scheme =~# '\mwiki\d\+' + 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.index = -1 + let link_infos.filename = '' + return link_infos + endif + + if !is_relative || link_infos.index != source_wiki + let root_dir = vimwiki#vars#get_wikilocal('path', link_infos.index) + endif + + let link_infos.filename = root_dir . link_text + + if vimwiki#path#is_link_to_dir(link_text) + if vimwiki#vars#get_global('dir_link') != '' + let link_infos.filename .= vimwiki#vars#get_global('dir_link') . + \ vimwiki#vars#get_wikilocal('ext', link_infos.index) + endif + else + let link_infos.filename .= vimwiki#vars#get_wikilocal('ext', link_infos.index) + endif + + elseif link_infos.scheme ==# 'diary' + let link_infos.index = source_wiki + + let link_infos.filename = + \ vimwiki#vars#get_wikilocal('path', link_infos.index) . + \ vimwiki#vars#get_wikilocal('diary_rel_path', link_infos.index) . + \ link_text . + \ vimwiki#vars#get_wikilocal('ext', link_infos.index) + elseif (link_infos.scheme ==# 'file' || link_infos.scheme ==# 'local') && is_relative + let link_infos.filename = simplify(root_dir . link_text) + else " absolute file link + " collapse repeated leading "/"'s within a link + let link_text = substitute(link_text, '\m^/\+', '/', '') + " expand ~/ + let link_text = fnamemodify(link_text, ':p') + let link_infos.filename = simplify(link_text) + endif + + let link_infos.filename = vimwiki#path#normalize(link_infos.filename) + return link_infos +endfunction + + +function! vimwiki#base#system_open_link(url) + " handlers + function! s:win32_handler(url) + "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 - call vimwiki#base#edit_file(a:cmd, - \ VimwikiGet('path').a:link. - \ g:vimwiki_dir_link. - \ VimwikiGet('ext')) + let url = shellescape(a:url, 1) endif + execute 'silent ! start "Title" /B ' . url + else - call vimwiki#base#edit_file(a:cmd, VimwikiGet('path').a:link.VimwikiGet('ext')) + + 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 - - if exists('vimwiki_prev_link') - let b:vimwiki_prev_link = vimwiki_prev_link + endfunction + function! s:macunix_handler(url) + call system('open ' . shellescape(a:url).' &') + endfunction + function! s:linux_handler(url) + call system('xdg-open ' . shellescape(a:url).' &') + endfunction + try + if vimwiki#u#is_windows() + call s:win32_handler(a:url) + return + elseif vimwiki#u#is_macos() + call s:macunix_handler(a:url) + return + else + call s:linux_handler(a:url) + return endif - endif + endtry + echomsg 'Vimwiki Error: Default Vimwiki link handler was unable to open the HTML file!' endfunction -" }}} -function! vimwiki#base#select(wnum)"{{{ - if a:wnum < 1 || a:wnum > len(g:vimwiki_list) + +function! vimwiki#base#open_link(cmd, link, ...) + let link_infos = {} + if a:0 + let link_infos = vimwiki#base#resolve_link(a:link, a:1) + else + let link_infos = vimwiki#base#resolve_link(a:link) + endif + + if link_infos.filename == '' + 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 - if &ft == 'vimwiki' - let b:vimwiki_idx = g:vimwiki_current_idx + + let is_wiki_link = link_infos.scheme =~# '\mwiki\d\+' || link_infos.scheme =~# 'diary' + + let update_prev_link = is_wiki_link && + \ !vimwiki#path#is_equal(link_infos.filename, vimwiki#path#current_wiki_file()) + + 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 = [vimwiki#path#current_wiki_file(), getpos('.')] + endif + endif + + " open/edit + if is_wiki_link + call vimwiki#base#edit_file(a:cmd, link_infos.filename, link_infos.anchor, + \ vimwiki_prev_link, update_prev_link) + else + call vimwiki#base#system_open_link(link_infos.filename) endif - let g:vimwiki_current_idx = a:wnum - 1 endfunction -" }}} -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') +function! vimwiki#base#get_globlinks_escaped() abort + " 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('*'.vimwiki#vars#get_wikilocal('ext'), 1)."\n" + " remove extensions + let globlinks = substitute(globlinks, '\'.vimwiki#vars#get_wikilocal('ext').'\ze\n', '', 'g') + " restore the original working directory + exe 'lcd! '.orig_pwd + " convert to a List + let lst = split(globlinks, '\n') + " Apply fnameescape() to each item + call map(lst, 'fnameescape(v:val)') + " Convert back to newline-separated list + let globlinks = join(lst, "\n") + " return all escaped links as a single newline-separated string + return globlinks +endfunction - if len(links) - call append(line('$'), '= Generated Links =') - endif +function! vimwiki#base#generate_links() + let lines = [] + + let links = vimwiki#base#get_wikilinks(vimwiki#vars#get_bufferlocal('wiki_nr'), 0) 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.']]') + let abs_filepath = vimwiki#path#abs_path_of_link(link) + if !s:is_diary_file(abs_filepath) + call add(lines, bullet. + \ s:safesubstitute(vimwiki#vars#get_global('WikiLinkTemplate1'), + \ '__LinkUrl__', link, '')) endif endfor -endfunction " }}} -function! vimwiki#base#goto(key) "{{{ - call vimwiki#base#edit_file(':e', - \ VimwikiGet('path'). - \ a:key. - \ VimwikiGet('ext')) -endfunction "}}} + let links_rx = '\m^\s*'.vimwiki#u#escape(vimwiki#lst#default_symbol()).' ' + + call vimwiki#base#update_listing_in_buffer(lines, 'Generated Links', links_rx, line('$')+1, 1) +endfunction -function! s:is_windows() "{{{ - return has("win32") || has("win64") || has("win95") || has("win16") -endfunction "}}} -function! s:is_path_absolute(path) "{{{ - return a:path =~ '^/.*' || a:path =~ '^[[:alpha:]]:[/\\].*' -endfunction "}}} +function! vimwiki#base#goto(...) + let key = a:1 + let anchor = a:0 > 1 ? a:2 : '' + + call vimwiki#base#edit_file(':e', + \ vimwiki#vars#get_wikilocal('path') . key . vimwiki#vars#get_wikilocal('ext'), + \ anchor) +endfunction -function! s:get_links(pat) "{{{ - " search all wiki files in 'path' and its subdirs. - let subdir = vimwiki#base#current_subdir() +function! vimwiki#base#backlinks() + let current_filename = expand("%:p") + let locations = [] + for idx in range(vimwiki#vars#number_of_wikis()) + let syntax = vimwiki#vars#get_wikilocal('syntax', idx) + let wikifiles = vimwiki#base#find_files(idx, 0) + for source_file in wikifiles + let links = s:get_links(source_file, idx) + for [target_file, _, lnum, col] in links + " don't include links from the current file to itself + if vimwiki#path#is_equal(target_file, current_filename) && + \ !vimwiki#path#is_equal(target_file, source_file) + call add(locations, {'filename':source_file, 'lnum':lnum, 'col':col}) + endif + endfor + endfor + endfor + + if empty(locations) + echomsg 'Vimwiki: No other file links to this file' + else + call setloclist(0, locations, 'r') + lopen + endif +endfunction + + +" Returns: a list containing all files of the given wiki as absolute file path. +" If the given wiki number is negative, the diary of the current wiki is used +" If the second argument is not zero, only directories are found +function! vimwiki#base#find_files(wiki_nr, directories_only) + let wiki_nr = a:wiki_nr + if wiki_nr >= 0 + let root_directory = vimwiki#vars#get_wikilocal('path', wiki_nr) + else + let root_directory = vimwiki#vars#get_wikilocal('path') . + \ vimwiki#vars#get_wikilocal('diary_rel_path') + let wiki_nr = vimwiki#vars#get_bufferlocal('wiki_nr') + endif + if a:directories_only + let ext = '/' + else + let ext = vimwiki#vars#get_wikilocal('ext', wiki_nr) + endif " 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 " wiki file was created in $HOME or C:/ dirs. - if VimwikiGet('temp') - let search_dirs = '' + if vimwiki#vars#get_wikilocal('is_temporary_wiki', wiki_nr) + let pattern = '*'.ext else - let search_dirs = '**/' + let pattern = '**/*'.ext endif - let globlinks = glob(VimwikiGet('path').subdir.search_dirs.a:pat) + return split(globpath(root_directory, pattern), '\n') +endfunction - " remove extensions (and backup extensions too: .wiki~) - let globlinks = substitute(globlinks, '\'.VimwikiGet('ext').'\~\?', "", "g") - let links = split(globlinks, '\n') - " remove paths - let rem_path = escape(expand(VimwikiGet('path')).subdir, '\') - call map(links, 'substitute(v:val, rem_path, "", "g")') +" Returns: a list containing the links to get from the current file to all wiki +" files in the given wiki. +" If the given wiki number is negative, the diary of the current wiki is used. +" If also_absolute_links is nonzero, also return links of the form /file +function! vimwiki#base#get_wikilinks(wiki_nr, also_absolute_links) + let files = vimwiki#base#find_files(a:wiki_nr, 0) + if a:wiki_nr == vimwiki#vars#get_bufferlocal('wiki_nr') + let cwd = vimwiki#path#wikify_path(expand('%:p:h')) + elseif a:wiki_nr < 0 + let cwd = vimwiki#vars#get_wikilocal('path') . vimwiki#vars#get_wikilocal('diary_rel_path') + else + let cwd = vimwiki#vars#get_wikilocal('path', a:wiki_nr) + endif + let result = [] + for wikifile in files + let wikifile = fnamemodify(wikifile, ':r') " strip extension + let wikifile = vimwiki#path#relpath(cwd, wikifile) + call add(result, wikifile) + endfor + if a:also_absolute_links + for wikifile in files + if a:wiki_nr == vimwiki#vars#get_bufferlocal('wiki_nr') + let cwd = vimwiki#vars#get_wikilocal('path') + elseif a:wiki_nr < 0 + let cwd = vimwiki#vars#get_wikilocal('path') . vimwiki#vars#get_wikilocal('diary_rel_path') + endif + let wikifile = fnamemodify(wikifile, ':r') " strip extension + let wikifile = '/'.vimwiki#path#relpath(cwd, wikifile) + call add(result, wikifile) + endfor + endif + return result +endfunction - " Remove trailing slashes. - call map(links, 'substitute(v:val, "[/\\\\]*$", "", "g")') - return links -endfunction "}}} +" Returns: a list containing the links to all directories from the current file +function! vimwiki#base#get_wiki_directories(wiki_nr) + let dirs = vimwiki#base#find_files(a:wiki_nr, 1) + if a:wiki_nr == vimwiki#vars#get_bufferlocal('wiki_nr') + let cwd = vimwiki#path#wikify_path(expand('%:p:h')) + let root_dir = vimwiki#vars#get_wikilocal('path') + else + let cwd = vimwiki#vars#get_wikilocal('path', a:wiki_nr) + endif + let result = ['./'] + for wikidir in dirs + let wikidir_relative = vimwiki#path#relpath(cwd, wikidir) + call add(result, wikidir_relative) + if a:wiki_nr == vimwiki#vars#get_bufferlocal('wiki_nr') + let wikidir_absolute = '/'.vimwiki#path#relpath(root_dir, wikidir) + call add(result, wikidir_absolute) + endif + endfor + return result +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]) +function! vimwiki#base#get_anchors(filename, syntax) + if !filereadable(a:filename) + return [] endif - return result + + let rxheader = vimwiki#vars#get_syntaxlocal('header_search', a:syntax) + let rxbold = vimwiki#vars#get_syntaxlocal('bold_search', a:syntax) + let rxtag = vimwiki#vars#get_syntaxlocal('tag_search', a:syntax) + + let anchor_level = ['', '', '', '', '', '', ''] + let anchors = [] + let current_complete_anchor = '' + for line in readfile(a:filename) + + " collect headers + let h_match = matchlist(line, rxheader) + if !empty(h_match) + let header = vimwiki#u#trim(h_match[2]) + let level = len(h_match[1]) + call add(anchors, header) + let anchor_level[level-1] = header + for l in range(level, 6) + let anchor_level[l] = '' + endfor + if level == 1 + let current_complete_anchor = header + else + let current_complete_anchor = '' + for l in range(level-1) + if anchor_level[l] != '' + let current_complete_anchor .= anchor_level[l].'#' + endif + endfor + let current_complete_anchor .= header + call add(anchors, current_complete_anchor) + endif + endif + + " collect bold text (there can be several in one line) + let bold_count = 1 + while 1 + let bold_text = matchstr(line, rxbold, 0, bold_count) + if bold_text == '' + break + endif + call add(anchors, bold_text) + if current_complete_anchor != '' + call add(anchors, current_complete_anchor.'#'.bold_text) + endif + let bold_count += 1 + endwhile + + " collect tags text (there can be several in one line) + let tag_count = 1 + while 1 + let tag_group_text = matchstr(line, rxtag, 0, tag_count) + if tag_group_text == '' + break + endif + for tag_text in split(tag_group_text, ':') + call add(anchors, tag_text) + if current_complete_anchor != '' + call add(anchors, current_complete_anchor.'#'.tag_text) + endif + endfor + let tag_count += 1 + endwhile + + endfor + + return anchors +endfunction + + +function! s:jump_to_anchor(anchor) + let oldpos = getpos('.') + call cursor(1, 1) + + let anchor = vimwiki#u#escape(a:anchor) + + let segments = split(anchor, '#', 0) + + for segment in segments + + let anchor_header = s:safesubstitute( + \ vimwiki#vars#get_syntaxlocal('header_match'), + \ '__Header__', segment, '') + let anchor_bold = s:safesubstitute( + \ vimwiki#vars#get_syntaxlocal('bold_match'), + \ '__Text__', segment, '') + let anchor_tag = s:safesubstitute( + \ vimwiki#vars#get_syntaxlocal('tag_match'), + \ '__Tag__', segment, '') + + if !search(anchor_tag, 'Wc') && !search(anchor_header, 'Wc') && !search(anchor_bold, 'Wc') + call setpos('.', oldpos) + break + endif + let oldpos = getpos('.') + endfor endfunction -" }}} -function! s:is_wiki_word(str) "{{{ - if a:str =~ g:vimwiki_rxWikiWord && a:str !~ '[[:space:]\\/]' - return 1 + +" Params: full path to a wiki file and its wiki number +" Returns: a list of all links inside the wiki file +" Every list item has the form +" [target file, anchor, line number of the link in source file, column number] +function! s:get_links(wikifile, idx) + if !filereadable(a:wikifile) + return [] endif - return 0 + + let syntax = vimwiki#vars#get_wikilocal('syntax', a:idx) + let rx_link = vimwiki#vars#get_syntaxlocal('wikilink', syntax) + let links = [] + let lnum = 0 + + for line in readfile(a:wikifile) + let lnum += 1 + + let link_count = 1 + while 1 + let col = match(line, rx_link, 0, link_count)+1 + let link_text = matchstr(line, rx_link, 0, link_count) + if link_text == '' + break + endif + let link_count += 1 + let target = vimwiki#base#resolve_link(link_text, a:wikifile) + if target.filename != '' && target.scheme =~# '\mwiki\d\+\|diary\|file\|local' + call add(links, [target.filename, target.anchor, lnum, col]) + endif + endwhile + endfor + + return links endfunction -" }}} -function! vimwiki#base#edit_file(command, filename) "{{{ - let fname = escape(a:filename, '% ') - call vimwiki#base#mkdir(fnamemodify(a:filename, ":p:h")) - try - execute a:command.' '.fname - catch /E37/ " catch 'No write since last change' error - execute ':split '.fname - catch /E325/ " catch 'ATTENTION' error (:h E325) - endtry + +function! vimwiki#base#check_links() + let anchors_of_files = {} + let links_of_files = {} + let errors = [] + for idx in range(vimwiki#vars#number_of_wikis()) + let syntax = vimwiki#vars#get_wikilocal('syntax', idx) + let wikifiles = vimwiki#base#find_files(idx, 0) + for wikifile in wikifiles + let links_of_files[wikifile] = s:get_links(wikifile, idx) + let anchors_of_files[wikifile] = vimwiki#base#get_anchors(wikifile, syntax) + endfor + endfor + + for wikifile in keys(links_of_files) + for [target_file, target_anchor, lnum, col] in links_of_files[wikifile] + if target_file == '' && target_anchor == '' + call add(errors, {'filename':wikifile, 'lnum':lnum, 'col':col, + \ 'text': "numbered scheme refers to a non-existent wiki"}) + elseif has_key(anchors_of_files, target_file) + if target_anchor != '' && index(anchors_of_files[target_file], target_anchor) < 0 + call add(errors, {'filename':wikifile, 'lnum':lnum, 'col':col, + \'text': "there is no such anchor: ".target_anchor}) + endif + else + if target_file =~ '\m/$' " maybe it's a link to a directory + if !isdirectory(target_file) + call add(errors, {'filename':wikifile, 'lnum':lnum, 'col':col, + \'text': "there is no such directory: ".target_file}) + endif + else " maybe it's a non-wiki file + if filereadable(target_file) + let anchors_of_files[target_file] = [] + else + call add(errors, {'filename':wikifile, 'lnum':lnum, 'col':col, + \'text': "there is no such file: ".target_file}) + endif + endif + endif + endfor + endfor + + + " Check which wiki files are reachable from at least one of the index files. + " First, all index files are marked as reachable. Then, pick a reachable file + " and mark all files to which it links as reachable, too. Repeat until the + " links of all reachable files have been checked. + + " Map every wiki file to a number. 0 means not reachable from any index file, + " 1 means reachable, but the outgoing links are not checked yet, 2 means + " reachable and done. + let reachable_wikifiles = {} + + " first, all files are considered not reachable + for wikifile in keys(links_of_files) + let reachable_wikifiles[wikifile] = 0 + endfor + + " mark every index file as reachable + for idx in range(vimwiki#vars#number_of_wikis()) + let index_file = vimwiki#vars#get_wikilocal('path', idx) . + \ vimwiki#vars#get_wikilocal('index', idx) . vimwiki#vars#get_wikilocal('ext', idx) + if filereadable(index_file) + let reachable_wikifiles[index_file] = 1 + endif + endfor + + while 1 + let next_unvisited_wikifile = '' + for wf in keys(reachable_wikifiles) + if reachable_wikifiles[wf] == 1 + let next_unvisited_wikifile = wf + let reachable_wikifiles[wf] = 2 + break + endif + endfor + if next_unvisited_wikifile == '' + break + endif + for [target_file, target_anchor, lnum, col] in links_of_files[next_unvisited_wikifile] + if has_key(reachable_wikifiles, target_file) && reachable_wikifiles[target_file] == 0 + let reachable_wikifiles[target_file] = 1 + endif + endfor + endwhile + + for wf in keys(reachable_wikifiles) + if reachable_wikifiles[wf] == 0 + call add(errors, {'text':wf." is not reachable from the index file"}) + endif + endfor + + if empty(errors) + echomsg 'Vimwiki: All links are OK' + else + call setqflist(errors, 'r') + copen + endif endfunction -" }}} -function! s:search_word(wikiRx, cmd) "{{{ + +function! vimwiki#base#edit_file(command, filename, anchor, ...) + let fname = escape(a:filename, '% *|#`') + let dir = fnamemodify(a:filename, ":p:h") + + let ok = vimwiki#path#mkdir(dir, 1) + + if !ok + echomsg ' ' + echomsg 'Vimwiki Error: Unable to edit file in non-existent directory: '.dir + return + endif + + " Check if the file we want to open is already the current file + " which happens if we jump to an achor in the current file. + " 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'))) + 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 + 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 + + " Make sure no other plugin takes ownership over the new file. Vimwiki + " rules them all! Well, except for directories, which may be opened with + " Netrw + if &filetype != 'vimwiki' && fname !~ '\m/$' + setfiletype vimwiki + endif + endif + if a:anchor != '' + call s:jump_to_anchor(a:anchor) + 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 + call vimwiki#vars#set_bufferlocal('prev_link', a:1) + endif +endfunction + + +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 @@ -256,65 +810,50 @@ function! s:get_word_at_cursor(wikiRX) "{{{ else return "" endif -endf "}}} +endfunction -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 " }}} -function! s:print_wiki_list() "{{{ +function! s:print_wiki_list() let idx = 0 - while idx < len(g:vimwiki_list) - if idx == g:vimwiki_current_idx + while idx < vimwiki#vars#number_of_wikis() + if idx == vimwiki#vars#get_bufferlocal('wiki_nr') let sep = ' * ' echohl PmenuSel else let sep = ' ' echohl None endif - echo (idx + 1).sep.VimwikiGet('path', idx) + echo (idx + 1) . sep . vimwiki#vars#get_wikilocal('path', idx) let idx += 1 endwhile echohl None endfunction -" }}} -function! s:update_wiki_link(fname, old, new) " {{{ + +function! s:update_wiki_link(fname, old, new) echo "Updating links in ".a:fname let has_updates = 0 let dest = [] @@ -322,6 +861,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... @@ -331,44 +871,37 @@ function! s:update_wiki_link(fname, old, new) " {{{ call delete(a:fname.'#vimwiki_upd#') endif 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 = 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 + let old_fname_r = vimwiki#base#apply_template( + \ vimwiki#vars#get_syntaxlocal('WikiLinkMatchUrlTemplate', + \ vimwiki#vars#get_wikilocal('syntax', a:wiki_nr)), old_fname, '', '') - 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 files = split(glob(VimwikiGet('path').a:dir.'*'.VimwikiGet('ext')), '\n') - for fname in files - call s:update_wiki_link(fname, old_fname_r, new_fname_r) + 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 -" }}} -function! s:tail_name(fname) "{{{ + +function! s:tail_name(fname) let result = substitute(a:fname, ":", "__colon__", "g") let result = fnamemodify(result, ":t:r") let result = substitute(result, "__colon__", ":", "g") return result -endfunction "}}} +endfunction + -function! s:update_wiki_links(old_fname, new_fname) " {{{ - let old_fname = s:tail_name(a:old_fname) - let new_fname = s:tail_name(a: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 = [''] @@ -390,158 +923,40 @@ 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 " }}} +endfunction -function! s:get_wiki_buffers() "{{{ + +function! s:get_wiki_buffers() let blist = [] let bcount = 1 while bcount<=bufnr("$") if bufexists(bcount) let bname = fnamemodify(bufname(bcount), ":p") - if bname =~ VimwikiGet('ext')."$" - let bitem = [bname, getbufvar(bname, "vimwiki_prev_link")] + " this may find buffers that are not part of the current wiki, but that + " doesn't hurt + if bname =~# vimwiki#vars#get_wikilocal('ext')."$" + let bitem = [bname, vimwiki#vars#get_bufferlocal('prev_link', bcount)] call add(blist, bitem) endif endif let bcount = bcount + 1 endwhile return blist -endfunction " }}} - -function! s:open_wiki_buffer(item) "{{{ - call vimwiki#base#edit_file(':e', a:item[0]) - if !empty(a:item[1]) - call setbufvar(a:item[0], "vimwiki_prev_link", a:item[1]) - 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 "}}} +endfunction -function! vimwiki#base#hl_exists(hl) "{{{ - if !hlexists(a:hl) - return 0 + +function! s:open_wiki_buffer(item) + call vimwiki#base#edit_file(':e', a:item[0], '') + if !empty(a:item[1]) + call vimwiki#vars#set_bufferlocal('prev_link', a:item[1], a:item[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 "{{{ + +function! vimwiki#base#nested_syntax(filetype, start, end, textSnipHl) abort " From http://vim.wikia.com/wiki/VimTip857 let ft=toupper(a:filetype) let group='textGroup'.ft @@ -557,8 +972,9 @@ function! vimwiki#base#nested_syntax(filetype, start, end, textSnipHl) abort "{{ " let b:skip_set_iskeyword = 1 let is_keyword = &iskeyword - execute 'syntax include @'.group.' syntax/'.a:filetype.'.vim' try + " keep going even if syntax file is not found + execute 'syntax include @'.group.' syntax/'.a:filetype.'.vim' execute 'syntax include @'.group.' after/syntax/'.a:filetype.'.vim' catch endtry @@ -570,6 +986,14 @@ function! vimwiki#base#nested_syntax(filetype, start, end, textSnipHl) abort "{{ else unlet b:current_syntax endif + + " Fix issue #236: tell Vimwiki to think in maths when encountering maths + " blocks like {{$ }}$. Here, we don't want the tex highlight group, but the + " group for tex math. + if a:textSnipHl ==# 'VimwikiMath' + let group='texMathZoneGroup' + endif + execute 'syntax region textSnip'.ft. \ ' matchgroup='.a:textSnipHl. \ ' start="'.a:start.'" end="'.a:end.'"'. @@ -579,154 +1003,340 @@ function! vimwiki#base#nested_syntax(filetype, start, end, textSnipHl) abort "{{ " regular one. " Perl syntax file has perlFunctionName which is usually has no effect due to " 'contained' flag. Now we have 'syntax include' that makes all the groups - " included as 'contained' into specific group. + " included as 'contained' into specific group. " Here perlFunctionName (with quite an angry regexp "\h\w*[^:]") clashes with " the rest syntax rules as now it has effect being really 'contained'. " Clear it! - if ft =~ 'perl' - syntax clear perlFunctionName + if ft =~? 'perl' + syntax clear perlFunctionName + endif +endfunction + + +" creates or updates auto-generated listings in a wiki file, like TOC, diary +" links, tags list etc. +" - the listing consists of a level 1 header and a list of strings as content +" - a:content_regex is used to determine how long a potentially existing list is +" - a:default_lnum is the line number where the new listing should be placed if +" it's not already present +" - if a:create is true, it will be created if it doesn't exist, otherwise it +" will only be updated if it already exists +function! vimwiki#base#update_listing_in_buffer(strings, start_header, + \ content_regex, default_lnum, create) + " Vim behaves strangely when files change while in diff mode + if &diff || &readonly + return + endif + + " check if the listing is already there + let already_there = 0 + + let header_rx = '\m^\s*'.substitute(vimwiki#vars#get_syntaxlocal('rxH1_Template'), + \ '__Header__', a:start_header, '') .'\s*$' + + let start_lnum = 1 + while start_lnum <= line('$') + if getline(start_lnum) =~# header_rx + let already_there = 1 + break + endif + let start_lnum += 1 + endwhile + + if !already_there && !a:create + return + endif + + let winview_save = winsaveview() + let cursor_line = winview_save.lnum + let is_cursor_after_listing = 0 + + let is_fold_closed = 1 + + let lines_diff = 0 + + if already_there + let is_fold_closed = ( foldclosed(start_lnum) > -1 ) + " delete the old listing + let whitespaces_in_first_line = matchstr(getline(start_lnum), '\m^\s*') + let end_lnum = start_lnum + 1 + while end_lnum <= line('$') && getline(end_lnum) =~# a:content_regex + let end_lnum += 1 + endwhile + let is_cursor_after_listing = ( cursor_line >= end_lnum ) + " We'll be removing a range. But, apparently, if folds are enabled, Vim + " won't let you remove a range that overlaps with closed fold -- the entire + " fold gets deleted. So we temporarily disable folds, and then reenable + " them right back. + let foldenable_save = &l:foldenable + 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 + let start_lnum = a:default_lnum + let is_cursor_after_listing = ( cursor_line > a:default_lnum ) + let whitespaces_in_first_line = '' + endif + + let start_of_listing = start_lnum + + " write new listing + let new_header = whitespaces_in_first_line + \ . s:safesubstitute(vimwiki#vars#get_syntaxlocal('rxH1_Template'), + \ '__Header__', a:start_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 + 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*$' + keepjumps call append(start_lnum - 1, '') + let lines_diff += 1 + endif + + " Open fold, if needed + if !is_fold_closed && ( foldclosed(start_of_listing) > -1 ) + exe start_of_listing + norm! zo endif -endfunction "}}} -"}}} + if is_cursor_after_listing + let winview_save.lnum += lines_diff + endif + call winrestview(winview_save) +endfunction -" WIKI functions {{{ -function! vimwiki#base#find_next_link() "{{{ - call s:search_word(g:vimwiki_rxWikiLink.'\|'.g:vimwiki_rxWeblink, '') + +function! vimwiki#base#find_next_link() + call vimwiki#base#search_word(vimwiki#vars#get_syntaxlocal('rxAnyLink'), '') endfunction -" }}} -function! vimwiki#base#find_prev_link() "{{{ - call s:search_word(g:vimwiki_rxWikiLink.'\|'.g:vimwiki_rxWeblink, 'b') + +function! vimwiki#base#find_prev_link() + "Jump 2 times if the cursor is in the middle of a link + if synIDattr(synID(line('.'), col('.'), 0), "name") =~# "VimwikiLink.*" && + \ synIDattr(synID(line('.'), col('.')-1, 0), "name") =~# "VimwikiLink.*" + call vimwiki#base#search_word(vimwiki#vars#get_syntaxlocal('rxAnyLink'), 'b') + endif + call vimwiki#base#search_word(vimwiki#vars#get_syntaxlocal('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 " + +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 + + " try WikiLink + let lnk = matchstr(vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink')), + \ vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl')) + " try WikiIncl + if lnk == "" + let lnk = matchstr(vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_global('rxWikiIncl')), + \ vimwiki#vars#get_global('rxWikiInclMatchUrl')) + endif + " try Weblink + if lnk == "" + let lnk = matchstr(vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWeblink')), + \ vimwiki#vars#get_syntaxlocal('rxWeblinkMatchUrl')) 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, '#')) + if lnk != "" " cursor is indeed on a link + let processed_by_user_defined_handler = VimwikiLinkHandler(lnk) + if processed_by_user_defined_handler + return + endif + + if a:split ==# "hsplit" + let cmd = ":split " + elseif a:split ==# "vsplit" + let cmd = ":vsplit " + elseif a:split ==# "tab" + let cmd = ":tabnew " else - execute "normal! \n" + let cmd = ":e " + endif + + " 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') && reuse_other_split_window + let previous_window_nr = winnr('#') + if previous_window_nr > 0 && previous_window_nr != winnr() + execute previous_window_nr . 'wincmd w' + let cmd = ':e' + endif + endif + + + if vimwiki#vars#get_wikilocal('syntax') == 'markdown' + let processed_by_markdown_reflink = vimwiki#markdown_base#open_reflink(lnk) + if processed_by_markdown_reflink + return + endif + + " remove the extension from the filename if exists, because non-vimwiki + " markdown files usually include the extension in links + let lnk = substitute(lnk, '\'.vimwiki#vars#get_wikilocal('ext').'$', '', '') + endif + + let current_tab_page = tabpagenr() + + call vimwiki#base#open_link(cmd, lnk) + + if !move_cursor_to_new_window + if (a:split ==# 'hsplit' || a:split ==# 'vsplit') + execute 'wincmd p' + elseif a:split ==# 'tab' + execute 'tabnext ' . current_tab_page + endif + endif + + else + if a:0 >= 3 + execute "normal! ".a:3 + else + call vimwiki#base#normalize_link(0) endif - return endif +endfunction + + +function! vimwiki#base#go_back_link() + let prev_link = vimwiki#vars#get_bufferlocal('prev_link') + if !empty(prev_link) + " go back to saved wiki link + call vimwiki#base#edit_file(':e ', prev_link[0], '') + call setpos('.', prev_link[1]) + else + " maybe we came here by jumping to a tag -> pop from the tag stack + silent! pop! + endif +endfunction - let subdir = vimwiki#base#current_subdir() - call vimwiki#base#open_link(cmd, subdir.link) -endfunction " }}} +function! vimwiki#base#goto_index(wnum, ...) + if a:wnum > vimwiki#vars#number_of_wikis() + echomsg 'Vimwiki Error: Wiki '.a:wnum.' is not registered in your Vimwiki settings!' + return + endif + + " usually a:wnum is greater then 0 but with the following command it is == 0: + " vim -n -c ":VimwikiIndex" + if a:wnum > 0 + let idx = a:wnum - 1 + else + let idx = 0 + endif -function! vimwiki#base#go_back_link() "{{{ - if exists("b:vimwiki_prev_link") - " go back to saved WikiWord - let prev_word = b:vimwiki_prev_link - execute ":e ".substitute(prev_word[0], '\s', '\\\0', 'g') - call setpos('.', prev_word[1]) + if a:0 + if a:1 == 1 + let cmd = 'tabedit' + elseif a:1 == 2 + let cmd = 'split' + elseif a:1 == 3 + let cmd = 'vsplit' + endif + else + let cmd = 'edit' 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')) -endfunction "}}} + let index_file = vimwiki#vars#get_wikilocal('path', idx). + \ vimwiki#vars#get_wikilocal('index', idx). + \ vimwiki#vars#get_wikilocal('ext', idx) + + call vimwiki#base#edit_file(cmd, index_file, '') +endfunction + -function! vimwiki#base#delete_link() "{{{ - "" file system funcs - "" Delete WikiWord you are in from filesystem - let val = input('Delete ['.expand('%').'] (y/n)? ', "") - if val != 'y' +function! vimwiki#base#delete_link() + " Delete wiki file you are in from filesystem + let val = input('Delete "'.expand('%').'" [y]es/[N]o? ') + if val !~? '^y' return endif let fname = expand('%:p') try call delete(fname) catch /.*/ - echomsg 'vimwiki: Cannot delete "'.expand('%:t:r').'"!' + echomsg 'Vimwiki Error: 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 "}}} +endfunction + -function! vimwiki#base#rename_link() "{{{ - "" Rename WikiWord, update all links to renamed WikiWord - let subdir = vimwiki#base#current_subdir() +" Rename current file, update all links to it +function! vimwiki#base#rename_link() + let subdir = vimwiki#vars#get_bufferlocal('subdir') let old_fname = subdir.expand('%:t') " there is no file (new one maybe) if glob(expand('%:p')) == '' - echomsg 'vimwiki: Cannot rename "'.expand('%:p'). + echomsg 'Vimwiki Error: Cannot rename "'.expand('%:p'). \'". It does not exist! (New file? Save it before renaming.)' return endif - let val = input('Rename "'.expand('%:t:r').'" (y/n)? ', "") - if val!='y' + let val = input('Rename "'.expand('%:t:r').'" [y]es/[N]o? ') + if val !~? '^y' return endif - let new_link = input('Enter new name: ', "") + 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: Cannot rename to a filename with path!' + if new_link =~# '[/\\]' + 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: Cannot rename to an empty filename!' + echomsg 'Vimwiki Error: 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, vimwiki#vars#get_syntaxlocal('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 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 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!' + echomsg 'Vimwiki Error: 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 + echomsg 'Vimwiki: Renaming '.vimwiki#vars#get_wikilocal('path').old_fname.' to '.new_fname let res = rename(expand('%:p'), expand(new_fname)) if res != 0 throw "Cannot rename!" end catch /.*/ - echomsg 'vimwiki: Cannot rename "'.expand('%:t:r').'" to "'.new_fname.'"' + echomsg 'Vimwiki Error: Cannot rename "'.expand('%:t:r').'" to "'.new_fname.'"' return endtry let &buftype="nofile" - let cur_buffer = [expand('%:p'), - \getbufvar(expand('%:p'), "vimwiki_prev_link")] + let cur_buffer = [expand('%:p'), vimwiki#vars#get_bufferlocal('prev_link')] let blist = s:get_wiki_buffers() @@ -747,25 +1357,25 @@ function! vimwiki#base#rename_link() "{{{ setlocal nomore " update links - call s:update_wiki_links(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 - if bitem[0] != cur_buffer[0] + if !vimwiki#path#is_equal(bitem[0], cur_buffer[0]) call s:open_wiki_buffer(bitem) endif endfor - call s:open_wiki_buffer([new_fname, - \ cur_buffer[1]]) + call s:open_wiki_buffer([new_fname, cur_buffer[1]]) " execute 'bwipeout '.escape(cur_buffer[0], ' ') - echomsg old_fname." is renamed to ".new_fname + echomsg 'Vimwiki: '.old_fname.' is renamed to '.new_fname let &more = setting_more -endfunction " }}} +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 == "" @@ -773,56 +1383,62 @@ function! vimwiki#base#ui_select()"{{{ endif call vimwiki#base#goto_index(idx) endfunction -"}}} -" }}} -" TEXT OBJECTS functions {{{ - -function! vimwiki#base#TO_header(inner, visual) "{{{ - if !search('^\(=\+\).\+\1\s*$', 'bcW') +function! vimwiki#base#TO_header(inner, including_subheaders, count) + let headers = s:collect_headers() + if empty(headers) return endif - - let sel_start = line("'<") - let sel_end = line("'>") - let block_start = line(".") - let advance = 0 - let level = vimwiki#base#count_first_sym(getline('.')) + let current_line = line('.') - let is_header_selected = sel_start == block_start - \ && sel_start != sel_end + let current_header_index = s:current_header(headers, current_line) - if a:visual && is_header_selected - if level > 1 - let level -= 1 - call search('^\(=\{'.level.'\}\).\+\1\s*$', 'bcW') - else - let advance = 1 - endif + if current_header_index < 0 + return endif - normal! V + " from which to which header + if !a:including_subheaders && a:count <= 1 + let first_line = headers[current_header_index][0] + let last_line = current_header_index == len(headers)-1 ? line('$') : + \ headers[current_header_index + 1][0] - 1 + else + let first_header_index = current_header_index + for _ in range(a:count - 1) + let parent = s:get_another_header(headers, first_header_index, -1, '<') + if parent < 0 + break + else + let first_header_index = parent + endif + endfor - if a:visual && is_header_selected - call cursor(sel_end + advance, 0) + let next_sibling_or_higher = s:get_another_header(headers, first_header_index, +1, '<=') + + let first_line = headers[first_header_index][0] + let last_line = + \ next_sibling_or_higher >= 0 ? headers[next_sibling_or_higher][0] - 1 : line('$') endif - if search('^\(=\{1,'.level.'}\).\+\1\s*$', 'W') - call cursor(line('.') - 1, 0) - else - call cursor(line('$'), 0) + if a:inner + let first_line += 1 + let last_line = prevnonblank(last_line) endif - if a:inner && getline(line('.')) =~ '^\s*$' - let lnum = prevnonblank(line('.') - 1) - call cursor(lnum, 0) + if first_line > last_line + " this can happen e.g. when doing vih on a header with another header in the very next line + return endif + + call cursor(first_line, 1) + normal! V + call cursor(last_line, 1) endfunction -"}}} -function! vimwiki#base#TO_table_cell(inner, visual) "{{{ + +function! vimwiki#base#TO_table_cell(inner, visual) if col('.') == col('$')-1 return endif @@ -866,7 +1482,7 @@ function! vimwiki#base#TO_table_cell(inner, visual) "{{{ " XXX: WORKAROUND. " if blockwise selection is ended at | character then pressing j to extend - " selection furhter fails. But if we shake the cursor left and right then + " selection further fails. But if we shake the cursor left and right then " it works. normal! hl else @@ -884,10 +1500,11 @@ function! vimwiki#base#TO_table_cell(inner, visual) "{{{ normal! 2h endif endif -endfunction "}}} +endfunction + -function! vimwiki#base#TO_table_col(inner, visual) "{{{ - let t_rows = vimwiki_tbl#get_rows(line('.')) +function! vimwiki#base#TO_table_col(inner, visual) + let t_rows = vimwiki#tbl#get_rows(line('.')) if empty(t_rows) return endif @@ -903,14 +1520,14 @@ 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): " |-----^-+-------| " | bla | bla | " |-------+-------| " or it will select wrong column. - if strpart(getline('.'), virtcol('.')-1) =~ '^-+' + if strpart(getline('.'), virtcol('.')-1) =~# '^-+' let s_flag = 'b' else let s_flag = 'cb' @@ -933,7 +1550,7 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ normal! `> if !firsttime && getline('.')[virtcol('.')] == '|' normal! l - elseif a:inner && getline('.')[virtcol('.')+1] =~ '[|+]' + elseif a:inner && getline('.')[virtcol('.')+1] =~# '[|+]' normal! 2l endif " search for the next column separator @@ -948,7 +1565,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,14 +1574,14 @@ 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): " |-----^-+-------| " | bla | bla | " |-------+-------| " or it will select wrong column. - if strpart(getline('.'), virtcol('.')-1) =~ '^-+' + if strpart(getline('.'), virtcol('.')-1) =~# '^-+' let s_flag = 'b' else let s_flag = 'cb' @@ -996,61 +1613,484 @@ 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 "}}} +endfunction -function! vimwiki#base#count_first_sym(line) "{{{ - let first_sym = matchstr(a:line, '\S') - return len(matchstr(a:line, first_sym.'\+')) -endfunction "}}} -function! vimwiki#base#AddHeaderLevel() "{{{ +function! vimwiki#base#AddHeaderLevel() let lnum = line('.') let line = getline(lnum) - - if line =~ '^\s*$' + let rxHdr = vimwiki#vars#get_syntaxlocal('rxH') + if line =~# '^\s*$' return endif - if line =~ '^\s*\(=\+\).\+\1\s*$' - let level = vimwiki#base#count_first_sym(line) + if line =~# vimwiki#vars#get_syntaxlocal('rxHeader') + let level = vimwiki#u#count_first_sym(line) if level < 6 - let line = substitute(line, '\(=\+\).\+\1', '=&=', '') + if vimwiki#vars#get_syntaxlocal('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 vimwiki#vars#get_syntaxlocal('symH') + let line = substitute(line, '\s*$', ' '.rxHdr.'&', '') + endif + call setline(lnum, line) endif endfunction -"}}} -function! vimwiki#base#RemoveHeaderLevel() "{{{ + +function! vimwiki#base#RemoveHeaderLevel() let lnum = line('.') let line = getline(lnum) - - if line =~ '^\s*$' + let rxHdr = vimwiki#vars#get_syntaxlocal('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 =~# vimwiki#vars#get_syntaxlocal('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 vimwiki#vars#get_syntaxlocal('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 -" }}} -" }}} + + +" Returns all the headers in the current buffer as a list of the form +" [[line_number, header_level, header_text], [...], [...], ...] +function! s:collect_headers() + let is_inside_pre_or_math = 0 " 1: inside pre, 2: inside math, 0: outside + let headers = [] + for lnum in range(1, line('$')) + let line_content = getline(lnum) + if (is_inside_pre_or_math == 1 && line_content =~# vimwiki#vars#get_syntaxlocal('rxPreEnd')) || + \ (is_inside_pre_or_math == 2 && line_content =~# vimwiki#vars#get_syntaxlocal('rxMathEnd')) + let is_inside_pre_or_math = 0 + continue + endif + if is_inside_pre_or_math > 0 + continue + endif + if line_content =~# vimwiki#vars#get_syntaxlocal('rxPreStart') + let is_inside_pre_or_math = 1 + continue + endif + if line_content =~# vimwiki#vars#get_syntaxlocal('rxMathStart') + let is_inside_pre_or_math = 2 + continue + endif + if line_content !~# vimwiki#vars#get_syntaxlocal('rxHeader') + continue + endif + let header_level = vimwiki#u#count_first_sym(line_content) + let header_text = + \ vimwiki#u#trim(matchstr(line_content, vimwiki#vars#get_syntaxlocal('rxHeader'))) + call add(headers, [lnum, header_level, header_text]) + endfor + + return headers +endfunction + + +function! s:current_header(headers, line_number) + if empty(a:headers) + return -1 + endif + + if a:line_number >= a:headers[-1][0] + return len(a:headers) - 1 + endif + + let current_header_index = -1 + while a:headers[current_header_index+1][0] <= a:line_number + let current_header_index += 1 + endwhile + return current_header_index +endfunction + + +function! s:get_another_header(headers, current_index, direction, operation) + if empty(a:headers) || a:current_index < 0 + return -1 + endif + let current_level = a:headers[a:current_index][1] + let index = a:current_index + a:direction + + while 1 + if index < 0 || index >= len(a:headers) + return -1 + endif + if eval('a:headers[index][1] ' . a:operation . ' current_level') + return index + endif + let index += a:direction + endwhile +endfunction + + +function! vimwiki#base#goto_parent_header() + let headers = s:collect_headers() + let current_header_index = s:current_header(headers, line('.')) + let parent_header = s:get_another_header(headers, current_header_index, -1, '<') + if parent_header >= 0 + call cursor(headers[parent_header][0], 1) + else + echo 'Vimwiki: no parent header found' + endif +endfunction + + +function! vimwiki#base#goto_next_header() + let headers = s:collect_headers() + let current_header_index = s:current_header(headers, line('.')) + if current_header_index >= 0 && current_header_index < len(headers) - 1 + call cursor(headers[current_header_index + 1][0], 1) + elseif current_header_index < 0 && !empty(headers) " we're above the first header + call cursor(headers[0][0], 1) + else + echo 'Vimwiki: no next header found' + endif +endfunction + + +function! vimwiki#base#goto_prev_header() + let headers = s:collect_headers() + let current_header_index = s:current_header(headers, line('.')) + " if the cursor already was on a header, jump to the previous one + if current_header_index >= 1 && headers[current_header_index][0] == line('.') + let current_header_index -= 1 + endif + if current_header_index >= 0 + call cursor(headers[current_header_index][0], 1) + else + echo 'Vimwiki: no previous header found' + endif +endfunction + + +function! vimwiki#base#goto_sibling(direction) + let headers = s:collect_headers() + let current_header_index = s:current_header(headers, line('.')) + let next_potential_sibling = + \ s:get_another_header(headers, current_header_index, a:direction, '<=') + if next_potential_sibling >= 0 && headers[next_potential_sibling][1] == + \ headers[current_header_index][1] + call cursor(headers[next_potential_sibling][0], 1) + else + echo 'Vimwiki: no sibling header found' + endif +endfunction + + +" a:create == 1: creates or updates TOC in current file +" a:create == 0: update if TOC exists +function! vimwiki#base#table_of_contents(create) + 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 ==# 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] + for idx in range(h_level, 5) | let headers_levels[idx] = ['', 0] | endfor + + let h_complete_id = '' + for l in range(h_level-1) + if headers_levels[l][0] != '' + let h_complete_id .= headers_levels[l][0].'#' + endif + endfor + let h_complete_id .= headers_levels[h_level-1][0] + + if numbering > 0 && numbering <= h_level + let h_number = join(map(copy(headers_levels[numbering-1 : h_level-1]), 'v:val[1]'), '.') + let h_number .= vimwiki#vars#get_global('html_header_numbering_sym') + let h_text = h_number.' '.h_text + endif + + call add(complete_header_infos, [h_level, h_complete_id, h_text]) + endfor + + let lines = [] + let startindent = repeat(' ', vimwiki#lst#get_list_margin()) + let indentstring = repeat(' ', vimwiki#u#sw()) + let bullet = vimwiki#lst#default_symbol().' ' + for [lvl, link, desc] in complete_header_infos + 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, toc_header_text, links_rx, 1, a:create) +endfunction + + +" 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 lnk = a:template + if a:rxUrl != "" + let lnk = s:safesubstitute(lnk, '__LinkUrl__', a:rxUrl, 'g') + endif + if a:rxDesc != "" + let lnk = s:safesubstitute(lnk, '__LinkDescription__', a:rxDesc, 'g') + endif + if a:rxStyle != "" + let lnk = s:safesubstitute(lnk, '__LinkStyle__', a:rxStyle, 'g') + endif + return lnk +endfunction + + +function! s:clean_url(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 !=# ""') + 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 + + +function! s:is_diary_file(filename) + let file_path = vimwiki#path#path_norm(a:filename) + let rel_path = vimwiki#vars#get_wikilocal('diary_rel_path') + let diary_path = vimwiki#path#path_norm(vimwiki#vars#get_wikilocal('path') . rel_path) + return rel_path != '' && file_path =~# '^'.vimwiki#u#escape(diary_path) +endfunction + + +function! vimwiki#base#normalize_link_helper(str, rxUrl, rxDesc, template) + let url = matchstr(a:str, a:rxUrl) + let descr = matchstr(a:str, a:rxDesc) + if descr == "" + let descr = s:clean_url(url) + endif + let lnk = s:safesubstitute(a:template, '__LinkDescription__', descr, '') + let lnk = s:safesubstitute(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(a:str, a:rxStyle) + let lnk = s:safesubstitute(lnk, '__LinkStyle__', style, '') + return lnk +endfunction + + +function! s:normalize_link_in_diary(lnk) + let link = a:lnk . vimwiki#vars#get_wikilocal('ext') + let link_wiki = vimwiki#vars#get_wikilocal('path') . '/' . link + let link_diary = vimwiki#vars#get_wikilocal('path') . '/' + \ . vimwiki#vars#get_wikilocal('diary_rel_path') . '/' . link + let link_exists_in_diary = filereadable(link_diary) + 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_diary || link_is_date + let str = a:lnk + let rxUrl = vimwiki#vars#get_global('rxWord') + let rxDesc = '' + let template = vimwiki#vars#get_global('WikiLinkTemplate1') + elseif link_exists_in_wiki + let depth = len(split(vimwiki#vars#get_wikilocal('diary_rel_path'), '/')) + let str = repeat('../', depth) . a:lnk . '|' . a: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) +endfunction + + +function! s:normalize_link_syntax_n() + + " try WikiLink + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink')) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl'), + \ vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchDescr'), + \ vimwiki#vars#get_global('WikiLinkTemplate2')) + call vimwiki#base#replacestr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink'), sub) + return + endif + + " try WikiIncl + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_global('rxWikiIncl')) + if !empty(lnk) + " NO-OP !! + return + endif + + " try Weblink + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWeblink')) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ lnk, '', vimwiki#vars#get_global('WikiLinkTemplate2')) + call vimwiki#base#replacestr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWeblink'), sub) + 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(vimwiki#vars#get_global('rxWord')) + if !empty(lnk) + if s:is_diary_file(expand("%:p")) + let sub = s:normalize_link_in_diary(lnk) + else + let sub = s:safesubstitute( + \ vimwiki#vars#get_global('WikiLinkTemplate1'), '__LinkUrl__', lnk, '') + endif + call vimwiki#base#replacestr_at_cursor('\V'.lnk, sub) + return + endif + +endfunction + + +function! s:normalize_link_syntax_v() + let sel_save = &selection + let &selection = "old" + let default_register_save = @" + let registertype_save = getregtype('"') + + try + " Save selected text to register " + normal! gv""y + + " Set substitution + if s:is_diary_file(expand("%:p")) + let sub = s:normalize_link_in_diary(@") + else + let sub = s:safesubstitute(vimwiki#vars#get_global('WikiLinkTemplate1'), + \ '__LinkUrl__', @", '') + endif + + " Put substitution in register " and change text + call setreg('"', substitute(sub, '\n', '', ''), visualmode()) + normal! `>""pgvd + finally + call setreg('"', default_register_save, registertype_save) + let &selection = sel_save + endtry +endfunction + + +function! vimwiki#base#normalize_link(is_visual_mode) + if exists('*vimwiki#'.vimwiki#vars#get_wikilocal('syntax').'_base#normalize_link') + " Syntax-specific links + call vimwiki#{vimwiki#vars#get_wikilocal('syntax')}_base#normalize_link(a:is_visual_mode) + else + if !a:is_visual_mode + call s:normalize_link_syntax_n() + elseif line("'<") == line("'>") + " action undefined for multi-line visual mode selections + call s:normalize_link_syntax_v() + endif + endif +endfunction + + +function! vimwiki#base#detect_nested_syntax() + let last_word = '\v.*<(\w+)\s*$' + let lines = map(filter(getline(1, "$"), 'v:val =~ "\\%({{{\\|```\\)" && v:val =~ last_word'), + \ 'substitute(v:val, last_word, "\\=submatch(1)", "")') + let dict = {} + for elem in lines + let dict[elem] = elem + endfor + return dict +endfunction + + +function! vimwiki#base#complete_links_escaped(ArgLead, CmdLine, CursorPos) abort + " We can safely ignore args if we use -custom=complete option, Vim engine + " will do the job of filtering. + return vimwiki#base#get_globlinks_escaped() +endfunction + + +" ------------------------------------------------------------------------- +" Load syntax-specific Wiki functionality +for s:syn in s:vimwiki_get_known_syntaxes() + execute 'runtime! autoload/vimwiki/'.s:syn.'_base.vim' +endfor +" ------------------------------------------------------------------------- + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/customwiki2html.sh b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/customwiki2html.sh new file mode 100755 index 0000000..6b0c17a --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/customwiki2html.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# +# This script converts markdown into html, to be used with vimwiki's +# "customwiki2html" option. Experiment with the two proposed methods by +# commenting / uncommenting the relevant lines below. +# +# NEW! An alternative converter was developed by Jason6Anderson, and can +# be located at https://github.com/vimwiki-backup/vimwiki/issues/384 +# +# +# To use this script, you must have the Discount converter installed. +# +# http://www.pell.portland.or.us/~orc/Code/discount/ +# +# To verify your installation, check that the commands markdown and mkd2text, +# are on your path. +# +# Also verify that this file is executable. +# +# Then, in your .vimrc file, set: +# +# g:vimwiki_customwiki2html=$HOME.'/.vim/autoload/vimwiki/customwiki2html.sh' +# +# On your next restart, Vimwiki will run this script instead of using the +# internal wiki2html converter. +# + +MARKDOWN=markdown +MKD2HTML=mkd2html + + +FORCE="$1" +SYNTAX="$2" +EXTENSION="$3" +OUTPUTDIR="$4" +INPUT="$5" +CSSFILE="$6" + +FORCEFLAG= + +[ $FORCE -eq 0 ] || { FORCEFLAG="-f"; }; +[ $SYNTAX = "markdown" ] || { echo "Error: Unsupported syntax"; exit -2; }; + +OUTPUT="$OUTPUTDIR"/$(basename "$INPUT" .$EXTENSION).html + +# # Method 1: +# # markdown [-d] [-T] [-V] [-b url-base] [-C prefix] [-F bitmap] [-f flags] [-o file] [-s text] [-t text] [textfile] +# +# URLBASE=http://example.com +# $MARKDOWN -T -b $URLBASE -o $OUTPUT $INPUT + + +# Method 2: +# mkd2html [-css file] [-header string] [-footer string] [file] + +$MKD2HTML -css "$CSSFILE" "$INPUT" +OUTPUTTMP=$(dirname "$INPUT")/$(basename "$INPUT" ."$EXTENSION").html +mv -f "$OUTPUTTMP" "$OUTPUT" + + + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/default.tpl b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/default.tpl index 3e31d99..3a4045f 100644 --- a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/default.tpl +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/default.tpl @@ -1,4 +1,4 @@ - + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/diary.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/diary.vim index a38d547..37f6d5c 100644 --- a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/diary.vim +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/diary.vim @@ -1,251 +1,245 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Desc: Handle diary notes -" Author: Maxim Kim -" Home: http://code.google.com/p/vimwiki/ +" Description: Handle diary notes +" Home: https://github.com/vimwiki/vimwiki/ + -" Load only once {{{ if exists("g:loaded_vimwiki_diary_auto") || &cp finish endif let g:loaded_vimwiki_diary_auto = 1 -"}}} -function! s:prefix_zero(num) "{{{ + +let s:vimwiki_max_scan_for_caption = 5 + + +function! s:prefix_zero(num) if a:num < 10 return '0'.a:num endif 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 "}}} - -function! s:link_exists(lines, link) "{{{ - let link_exists = 0 - for line in a:lines - if line =~ escape(a:link, '[]\') - let link_exists = 1 - break - endif - endfor - return link_exists -endfunction "}}} - -function! s:diary_path() "{{{ - return VimwikiGet('path').VimwikiGet('diary_rel_path') -endfunction "}}} - -function! s:diary_index() "{{{ - return s:diary_path().VimwikiGet('diary_index').VimwikiGet('ext') -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 +endfunction - 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:diary_path(...) + let idx = a:0 == 0 ? vimwiki#vars#get_bufferlocal('wiki_nr') : a:1 + return vimwiki#vars#get_wikilocal('path', idx).vimwiki#vars#get_wikilocal('diary_rel_path', idx) +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')) +function! s:diary_index(...) + let idx = a:0 == 0 ? vimwiki#vars#get_bufferlocal('wiki_nr') : a:1 + return s:diary_path(idx).vimwiki#vars#get_wikilocal('diary_index', idx). + \ vimwiki#vars#get_wikilocal('ext', idx) +endfunction - 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")') +function! vimwiki#diary#diary_date_link(...) + if a:0 + return strftime('%Y-%m-%d', a:1) + else + return strftime('%Y-%m-%d') + endif +endfunction - call filter(links, 'v:val =~ "'.escape(rx, '\').'"') - return links -endfunction "}}} -function! s:get_position_links(link) "{{{ +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 = map(s:get_diary_files(), 'fnamemodify(v:val, ":t:r")') " include 'today' into links - if index(links, s:diary_date_link()) == -1 - call add(links, s:diary_date_link()) + if index(links, vimwiki#diary#diary_date_link()) == -1 + call add(links, vimwiki#diary#diary_date_link()) endif call sort(links) let idx = index(links, a:link) endif 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, ['']) +endfunction - return lines -endfunction "}}} -function! s:add_link(page, header, link) "{{{ - let [lines, bufnr] = s:get_file_contents(a:page) +function! s:get_month_name(month) + return vimwiki#vars#get_global('diary_months')[str2nr(a:month)] +endfunction - let [ln_start, ln_end] = s:get_diary_range(lines, a:header) - let link = '[['.a:link.']]' +function! s:read_captions(files) + let result = {} + let rx_header = vimwiki#vars#get_syntaxlocal('rxHeader') + for fl in a:files + " remove paths and extensions + let fl_key = substitute(fnamemodify(fl, ':t'), vimwiki#vars#get_wikilocal('ext').'$', '', '') - 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 =~# rx_header && !has_key(result, fl_key) + let result[fl_key] = vimwiki#u#trim(matchstr(line, rx_header)) + 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 +endfunction + - if bufnr != -1 - exe 'buffer '.bufnr - if !&readonly - 1,$delete _ - call append(1, lines) - 1,1delete _ - endif - else - call writefile(lines, expand(a:page)) +function! s:get_diary_files() + let rx = '^\d\{4}-\d\d-\d\d' + let s_files = glob(vimwiki#vars#get_wikilocal('path'). + \ vimwiki#vars#get_wikilocal('diary_rel_path').'*'.vimwiki#vars#get_wikilocal('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 !~# ''.*\~$''') + + return files +endfunction + + +function! 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 +endfunction + + +function! s:sort(lst) + if vimwiki#vars#get_wikilocal('diary_sort') ==? 'desc' + return reverse(sort(a:lst)) + else + return sort(a:lst) endif -endfunction "}}} +endfunction -function! s:make_date_link(...) "{{{ - if a:0 - let link = a:1 + +function! s:format_diary() + let result = [] + + let links_with_captions = s:read_captions(s:get_diary_files()) + let g_files = s:group_links(links_with_captions) + + for year in s:sort(keys(g_files)) + call add(result, '') + call add(result, + \ substitute(vimwiki#vars#get_syntaxlocal('rxH2_Template'), '__Header__', year , '')) + + for month in s:sort(keys(g_files[year])) + call add(result, '') + call add(result, substitute(vimwiki#vars#get_syntaxlocal('rxH3_Template'), + \ '__Header__', s:get_month_name(month), '')) + + for [fl, cap] in s:sort(items(g_files[year][month])) + 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 + endfor + + return result +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 == 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 link = s:diary_date_link() + 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 - 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')) + + " TODO: refactor it. base#goto_index uses the same + + call vimwiki#path#mkdir(vimwiki#vars#get_wikilocal('path', wiki_nr). + \ vimwiki#vars#get_wikilocal('diary_rel_path', wiki_nr)) + + let cmd = 'edit' if a:0 - let link = s:make_date_link(a:1) + if a:1 == 1 + let cmd = 'tabedit' + elseif a:1 == 2 + let cmd = 'split' + elseif a:1 == 3 + let cmd = 'vsplit' + endif + endif + if a:0>1 + let link = 'diary:'.a:2 else - let link = s:make_date_link() + let link = 'diary:'.vimwiki#diary#diary_date_link() endif - call vimwiki#base#open_link(':e ', link, s:diary_index()) -endfunction "}}} -function! vimwiki#diary#goto_index(index) "{{{ - call vimwiki#base#select(a:index) - call vimwiki#base#edit_file(':e', s:diary_index()) -endfunction "}}} + call vimwiki#base#open_link(cmd, link, s:diary_index(wiki_nr)) +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) - let link = a:year.'-'.month.'-'.day - if winnr('#') == 0 - if a:dir == 'V' - vsplit - else - split - endif +function! vimwiki#diary#goto_diary_index(wnum) + if a:wnum > vimwiki#vars#number_of_wikis() + echomsg 'Vimwiki Error: 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 - wincmd p - if !&hidden && &modified - new - endif + let idx = 0 endif - " Create diary note for a selected date in default wiki. - call vimwiki#diary#make_note(1, link) -endfunction "}}} + 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 -" Calendar.vim sign function. -function vimwiki#diary#calendar_sign(day, month, year) "{{{ - let day = s:prefix_zero(a:day) - let month = s:prefix_zero(a:month) - let sfile = VimwikiGet('path').VimwikiGet('diary_rel_path'). - \ a:year.'-'.month.'-'.day.VimwikiGet('ext') - return filereadable(expand(sfile)) -endfunction "}}} -function! vimwiki#diary#goto_next_day() "{{{ +function! vimwiki#diary#goto_next_day() let link = '' let [idx, links] = s:get_position_links(expand('%:t:r')) @@ -254,18 +248,19 @@ function! vimwiki#diary#goto_next_day() "{{{ endif if idx != -1 && idx < len(links) - 1 - let link = VimwikiGet('diary_rel_path').links[idx+1] + let link = 'diary:'.links[idx+1] else " goto today - let link = VimwikiGet('diary_rel_path').s:diary_date_link() + let link = 'diary:'.vimwiki#diary#diary_date_link() endif if len(link) call vimwiki#base#open_link(':e ', link) endif -endfunction "}}} +endfunction + -function! vimwiki#diary#goto_prev_day() "{{{ +function! vimwiki#diary#goto_prev_day() let link = '' let [idx, links] = s:get_position_links(expand('%:t:r')) @@ -274,13 +269,59 @@ function! vimwiki#diary#goto_prev_day() "{{{ endif if idx > 0 - let link = VimwikiGet('diary_rel_path').links[idx-1] + let link = 'diary:'.links[idx-1] else " goto today - let link = VimwikiGet('diary_rel_path').s:diary_date_link() + let link = 'diary:'.vimwiki#diary#diary_date_link() endif if len(link) call vimwiki#base#open_link(':e ', link) endif -endfunction "}}} +endfunction + + +function! vimwiki#diary#generate_diary_section() + let current_file = vimwiki#path#path_norm(expand("%:p")) + let diary_file = vimwiki#path#path_norm(s:diary_index()) + if vimwiki#path#is_equal(current_file, diary_file) + let content_rx = '^\%(\s*\* \)\|\%(^\s*$\)\|\%('.vimwiki#vars#get_syntaxlocal('rxHeader').'\)' + call vimwiki#base#update_listing_in_buffer(s:format_diary(), + \ vimwiki#vars#get_wikilocal('diary_header'), content_rx, line('$')+1, 1) + else + echomsg 'Vimwiki Error: You can generate diary links only in a diary index page!' + endif +endfunction + + +" Callback function for Calendar.vim +function! vimwiki#diary#calendar_action(day, month, year, week, dir) + let day = s:prefix_zero(a:day) + let month = s:prefix_zero(a:month) + + let link = a:year.'-'.month.'-'.day + if winnr('#') == 0 + if a:dir ==? 'V' + vsplit + else + split + endif + else + wincmd p + if !&hidden && &modified + new + endif + endif + + call vimwiki#diary#make_note(0, 0, link) +endfunction + + +function vimwiki#diary#calendar_sign(day, month, year) + let day = s:prefix_zero(a:day) + let month = s:prefix_zero(a:month) + let sfile = vimwiki#vars#get_wikilocal('path').vimwiki#vars#get_wikilocal('diary_rel_path'). + \ a:year.'-'.month.'-'.day.vimwiki#vars#get_wikilocal('ext') + return filereadable(expand(sfile)) +endfunction + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/html.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/html.vim index 0dbe9d1..ba2cc4c 100644 --- a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/html.vim +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/html.vim @@ -1,55 +1,57 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Export to HTML -" Author: Maxim Kim -" Home: http://code.google.com/p/vimwiki/ +" Description: HTML export +" Home: https://github.com/vimwiki/vimwiki/ -" XXX: This file should be refactored! -" Load only once {{{ if exists("g:loaded_vimwiki_html_auto") || &cp finish endif let g:loaded_vimwiki_html_auto = 1 -"}}} -" UTILITY "{{{ -function! s:root_path(subdir) "{{{ + +function! s:root_path(subdir) return repeat('../', len(split(a:subdir, '[/\\]'))) -endfunction "}}} +endfunction + + +function! s:syntax_supported() + return vimwiki#vars#get_wikilocal('syntax') ==? "default" +endfunction -function! s:syntax_supported() " {{{ - return VimwikiGet('syntax') == "default" -endfunction " }}} -function! s:remove_blank_lines(lines) " {{{ - while !empty(a:lines) && a:lines[-1] =~ '^\s*$' +function! s:remove_blank_lines(lines) + while !empty(a:lines) && a:lines[-1] =~# '^\s*$' call remove(a:lines, -1) endwhile -endfunction "}}} +endfunction -function! s:is_web_link(lnk) "{{{ - if a:lnk =~ '^\%(https://\|http://\|www.\|ftp://\|file://\|mailto:\)' + +function! s:is_web_link(lnk) + if a:lnk =~# '^\%(https://\|http://\|www.\|ftp://\|file://\|mailto:\)' return 1 endif return 0 -endfunction "}}} +endfunction + -function! s:is_img_link(lnk) "{{{ - if a:lnk =~ '\.\%(png\|jpg\|gif\|jpeg\)$' +function! s:is_img_link(lnk) + if tolower(a:lnk) =~# '\.\%(png\|jpg\|gif\|jpeg\)$' return 1 endif return 0 -endfunction "}}} +endfunction -function! s:has_abs_path(fname) "{{{ - if a:fname =~ '\(^.:\)\|\(^/\)' + +function! s:has_abs_path(fname) + if a:fname =~# '\(^.:\)\|\(^/\)' return 1 endif return 0 -endfunction "}}} +endfunction + -function! s:find_autoload_file(name) " {{{ +function! s:find_autoload_file(name) for path in split(&runtimepath, ',') let fname = path.'/autoload/vimwiki/'.a:name if glob(fname) != '' @@ -57,91 +59,110 @@ function! s:find_autoload_file(name) " {{{ endif endfor return '' -endfunction " }}} +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') + let css_full_name = path . vimwiki#vars#get_wikilocal('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')) + call vimwiki#path#mkdir(fnamemodify(css_full_name, ':p:h')) let default_css = s:find_autoload_file('style.css') if default_css != '' let lines = readfile(default_css) call writefile(lines, css_full_name) - echomsg "Default style.css has been created." + return 1 endif endif -endfunction "}}} + return 0 +endfunction -function! s:template_full_name(name) "{{{ + +function! s:template_full_name(name) if a:name == '' - let name = VimwikiGet('template_default') + let name = vimwiki#vars#get_wikilocal('template_default') else let name = a:name endif - let fname = expand(VimwikiGet('template_path'). - \name. - \VimwikiGet('template_ext')) + let fname = expand(vimwiki#vars#get_wikilocal('template_path'). + \ name . vimwiki#vars#get_wikilocal('template_ext')) if filereadable(fname) return fname else return '' endif -endfunction "}}} +endfunction + -function! s:get_html_template(wikifile, template) "{{{ +function! s:get_html_template(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 catch /E484/ - echomsg 'vimwiki: html template '.template_name. - \ ' does not exist!' + echomsg 'Vimwiki: HTML template '.template_name. ' does not exist!' 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 "}}} +endfunction + + +function! s:safe_html_preformatted(line) + let line = substitute(a:line,'<','\<', 'g') + let line = substitute(line,'>','\>', 'g') + return line +endfunction + + +function! s:escape_html_attribute(string) + return substitute(a:string, '"', '\"', 'g') +endfunction -function! s:safe_html(line) "{{{ - "" htmlize symbols: < > & +function! s:safe_html_line(line) + " escape & < > when producing HTML text + " s:lt_pattern, s:gt_pattern depend on g:vimwiki_valid_html_tags + " and are set in vimwiki#html#Wiki2HTML() let line = substitute(a:line, '&', '\&', 'g') + 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') return line -endfunction "}}} +endfunction -function! s:delete_html_files(path) "{{{ + +function! s:delete_html_files(path) let htmlfiles = split(glob(a:path.'**/*.html'), '\n') for fname in htmlfiles " ignore user html files, e.g. search.html,404.html - if stridx(g:vimwiki_user_htmls, fnamemodify(fname, ":t")) >= 0 + if stridx(vimwiki#vars#get_global('user_htmls'), fnamemodify(fname, ":t")) >= 0 continue endif " 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 subdir = vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path_html'), fname) + let wikifile = vimwiki#vars#get_wikilocal('path').subdir. + \fnamemodify(fname, ":t:r").vimwiki#vars#get_wikilocal('ext') if filereadable(wikifile) continue endif @@ -149,16 +170,18 @@ function! s:delete_html_files(path) "{{{ try call delete(fname) catch - echomsg 'vimwiki: Cannot delete '.fname + echomsg 'Vimwiki Error: Cannot delete '.fname endtry endfor -endfunction "}}} +endfunction + -function! s:mid(value, cnt) "{{{ +function! s:mid(value, cnt) return strpart(a:value, a:cnt, len(a:value) - 2 * a:cnt) -endfunction "}}} +endfunction -function! s:subst_func(line, regexp, func) " {{{ + +function! s:subst_func(line, regexp, func, ...) " Substitute text found by regexp with result of " func(matched) function. @@ -169,94 +192,45 @@ function! s:subst_func(line, regexp, func) " {{{ let res_line = res_line.line let matched = matchstr(a:line, a:regexp, pos) if matched != "" - let res_line = res_line.{a:func}(matched) + if a:0 + let res_line = res_line.{a:func}(matched, a:1) + else + let res_line = res_line.{a:func}(matched) + endif endif let pos = matchend(a:line, a:regexp, pos) endfor return res_line -endfunction " }}} +endfunction -function! s:save_vimwiki_buffer() "{{{ - if &filetype == 'vimwiki' - silent update - 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"], ...] - function! s:close_list(toc, plevel, level) "{{{ - let plevel = a:plevel - while plevel > a:level - call add(a:toc, '') - let plevel -= 1 - endwhile - return plevel - endfunction "}}} - - if empty(a:toc_list) - return [] - endif - - let toc = ['
'] - let level = 0 - let plevel = 0 - for [level, text, id] in a:toc_list - if level > plevel - call add(toc, '
    ') - elseif level < plevel - let plevel = s:close_list(toc, plevel, level) - endif - let toc_text = s:process_tags_remove_links(text) - let toc_text = s:process_tags_typefaces(toc_text) - call add(toc, '
  • '.toc_text.'') - let plevel = level - endfor - call s:close_list(toc, level, 0) - call add(toc, '
') - return toc -endfunction "}}} - -" insert toc into dest. -function! s:process_toc(dest, placeholders, toc) "{{{ - let toc_idx = 0 +function! s:process_date(placeholders, default_date) if !empty(a:placeholders) for [placeholder, row, idx] in a:placeholders let [type, param] = placeholder - if type == 'toc' - let toc = a:toc[:] - if !empty(param) - call insert(toc, '

'.param.'

') - endif - let shift = toc_idx * len(toc) - call extend(a:dest, toc, row + shift) - let toc_idx += 1 + if type ==# 'date' && !empty(param) + return param endif endfor endif -endfunction "}}} + return a:default_date +endfunction -" get title. -function! s:process_title(placeholders, default_title) "{{{ + +function! s:process_title(placeholders, default_title) if !empty(a:placeholders) for [placeholder, row, idx] in a:placeholders let [type, param] = placeholder - if type == 'title' && !empty(param) + if type ==# 'title' && !empty(param) return param endif endfor endif return a:default_title -endfunction "}}} +endfunction + -function! s:is_html_uptodate(wikifile) "{{{ +function! s:is_html_uptodate(wikifile) let tpl_time = -1 let tpl_file = s:template_full_name('') @@ -265,20 +239,20 @@ 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. - \fnamemodify(wikifile, ":t:r").".html") + let htmlfile = expand(vimwiki#vars#get_wikilocal('path_html') . + \ vimwiki#vars#get_bufferlocal('subdir') . fnamemodify(wikifile, ":t:r").".html") if getftime(wikifile) <= getftime(htmlfile) && tpl_time <= getftime(htmlfile) return 1 endif return 0 -endfunction "}}} +endfunction -function! s:html_insert_contents(html_lines, content) "{{{ + +function! s:html_insert_contents(html_lines, content) let lines = [] for line in a:html_lines - if line =~ '%content%' + if line =~# '%content%' let parts = split(line, '%content%', 1) if empty(parts) call extend(lines, a:content) @@ -295,176 +269,217 @@ function! s:html_insert_contents(html_lines, content) "{{{ endif endfor return lines -endfunction "}}} -"}}} +endfunction -" INLINE TAGS "{{{ -function! s:tag_em(value) "{{{ - return ''.s:mid(a:value, 1).'' -endfunction "}}} -function! s:tag_strong(value) "{{{ - return ''.s:mid(a:value, 1).'' -endfunction "}}} +function! s:tag_eqin(value) + " mathJAX wants \( \) for inline maths + return '\('.s:mid(a:value, 1).'\)' +endfunction -function! s:tag_todo(value) "{{{ - return ''.a:value.'' -endfunction "}}} -function! s:tag_strike(value) "{{{ - return ''.s:mid(a:value, 2).'' -endfunction "}}} +function! s:tag_em(value) + return ''.s:mid(a:value, 1).'' +endfunction -function! s:tag_super(value) "{{{ - return ''.s:mid(a:value, 1).'' -endfunction "}}} -function! s:tag_sub(value) "{{{ - return ''.s:mid(a:value, 2).'' -endfunction "}}} - -function! s:tag_code(value) "{{{ - return ''.s:mid(a:value, 1).'' -endfunction "}}} - -function! s:tag_pre(value) "{{{ - return ''.s:mid(a:value, 3).'' -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! 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.'' +function! s:tag_strong(value, header_ids) + let text = s:mid(a:value, 1) + let id = s:escape_html_attribute(text) + let complete_id = '' + for l in range(6) + if a:header_ids[l][0] != '' + let complete_id .= a:header_ids[l][0].'-' endif + endfor + if a:header_ids[5][0] == '' + let complete_id = complete_id[:-2] + endif + let complete_id .= '-'.id + return ''.text.'' +endfunction - 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) +function! s:tag_tags(value, header_ids) + let complete_id = '' + for level in range(6) + if a:header_ids[level][0] != '' + let complete_id .= a:header_ids[level][0].'-' + endif + endfor + if a:header_ids[5][0] == '' + let complete_id = complete_id[:-2] endif + let complete_id = s:escape_html_attribute(complete_id) + let result = [] + for tag in split(a:value, ':') + let id = s:escape_html_attribute(tag) + call add(result, ''.tag.'') + endfor + return join(result) +endfunction - 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) +function! s:tag_todo(value) + return ''.a:value.'' +endfunction - else - let line = s:linkify(value, value, '') - endif - return line -endfunction "}}} -function! s:tag_external_link(value) "{{{ - "" Make link desc - "" from [link link desc] +function! s:tag_strike(value) + return ''.s:mid(a:value, 2).'' +endfunction - 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 - endif - if s:is_img_link(rest) - if rest!=head - let line = '' - else - let line = '' +function! s:tag_super(value) + return ''.s:mid(a:value, 1).'' +endfunction + + +function! s:tag_sub(value) + return ''.s:mid(a:value, 2).'' +endfunction + + +function! s:tag_code(value) + return ''.s:safe_html_preformatted(s:mid(a:value, 1)).'' +endfunction + + +" match n-th ARG within {{URL[|ARG1|ARG2|...]}} +" *c,d,e),... +function! s:incl_match_arg(nn_index) + let rx = vimwiki#vars#get_global('rxWikiInclPrefix'). vimwiki#vars#get_global('rxWikiInclUrl') + let rx = rx . repeat(vimwiki#vars#get_global('rxWikiInclSeparator') . + \ vimwiki#vars#get_global('rxWikiInclArg'), a:nn_index-1) + if a:nn_index > 0 + let rx = rx. vimwiki#vars#get_global('rxWikiInclSeparator'). '\zs' . + \ vimwiki#vars#get_global('rxWikiInclArg') . '\ze' + endif + let rx = rx . vimwiki#vars#get_global('rxWikiInclArgs') . + \ vimwiki#vars#get_global('rxWikiInclSuffix') + return rx +endfunction + + +function! s:linkify_link(src, descr) + let src_str = ' href="'.s:escape_html_attribute(a:src).'"' + 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) + \ : descr) + return ''.descr_str.'' +endfunction + + +function! s: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:tag_weblink(value) + " Weblink Template -> descr + let str = a:value + let url = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWeblinkMatchUrl')) + let descr = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWeblinkMatchDescr')) + let line = s:linkify_link(url, descr) + return line +endfunction + + +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, vimwiki#vars#get_global('rxWikiInclMatchUrl')) + let descr = matchstr(str, s:incl_match_arg(1)) + let verbatim_str = matchstr(str, s:incl_match_arg(2)) + + let link_infos = vimwiki#base#resolve_link(url_0) + + if link_infos.scheme =~# '\mlocal\|wiki\d\+\|diary' + let url = vimwiki#path#relpath(fnamemodify(s:current_html_file, ':h'), link_infos.filename) + " strip the .html extension when we have wiki links, so that the user can + " simply write {{image.png}} to include an image from the wiki directory + if link_infos.scheme =~# '\mwiki\d\+\|diary' + let url = fnamemodify(url, ':r') endif else - let line = ''.rest.'' + let url = link_infos.filename 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.']' + + let url = escape(url, '#') + let line = s:linkify_image(url, descr, verbatim_str) 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.'' - return line - else - return a:value - endif -endfunction "}}} - -function! s:tag_barebone_link(value) "{{{ - "" Make http://habamax.ru - "" from http://habamax.ru +endfunction + + +function! s:tag_wikilink(value) + " [[url]] -> url + " [[url|descr]] -> descr + " [[url|{{...}}]] -> ... + " [[fileurl.ext|descr]] -> descr + " [[dirurl/|descr]] -> descr + " [[url#a1#a2]] -> url#a1#a2 + " [[#a1#a2]] -> #a1#a2 + let str = a:value + let url = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl')) + let descr = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchDescr')) + 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 == '' + let link_infos = vimwiki#base#resolve_link(url, s:current_wiki_file) + + if link_infos.scheme ==# 'file' + " external file links are always absolute + let html_link = link_infos.filename + elseif link_infos.scheme ==# 'local' + let html_link = vimwiki#path#relpath(fnamemodify(s:current_html_file, ':h'), + \ link_infos.filename) + elseif link_infos.scheme =~# '\mwiki\d\+\|diary' + " wiki links are always relative to the current file + let html_link = vimwiki#path#relpath( + \ fnamemodify(s:current_wiki_file, ':h'), + \ fnamemodify(link_infos.filename, ':r')) + if html_link !~ '\m/$' + let html_link .= '.html' + endif + else " other schemes, like http, are left untouched + let html_link = link_infos.filename + endif - if s:is_img_link(a:value) - let line = '' - else - let line = ''.a:value.'' + if link_infos.anchor != '' + let anchor = substitute(link_infos.anchor, '#', '-', 'g') + let html_link .= '#'.anchor + endif + let line = html_link endif + + let line = s:linkify_link(line, descr) return line -endfunction "}}} +endfunction -function! s:tag_no_wikiword_link(value) "{{{ - if a:value[0] == '!' - return a:value[1:] - else - return a:value - endif -endfunction "}}} -function! s:tag_remove_internal_link(value) "{{{ +function! s:tag_remove_internal_link(value) let value = s:mid(a:value, 2) let line = '' - if value =~ '|' + if value =~# '|' let link_parts = split(value, "|", 1) else let link_parts = split(value, "][", 1) @@ -481,9 +496,10 @@ function! s:tag_remove_internal_link(value) "{{{ let line = value endif return line -endfunction "}}} +endfunction -function! s:tag_remove_external_link(value) "{{{ + +function! s:tag_remove_external_link(value) let value = s:mid(a:value, 1) let line = '' @@ -491,8 +507,8 @@ function! s:tag_remove_external_link(value) "{{{ let lnkElements = split(value) let head = lnkElements[0] let rest = join(lnkElements[1:]) - if rest=="" - let rest=head + if rest == "" + let rest = head endif let line = rest elseif s:is_img_link(value) @@ -503,15 +519,25 @@ function! s:tag_remove_external_link(value) "{{{ let line = '['.value.']' endif return line -endfunction "}}} +endfunction + -function! s:make_tag(line, regexp, func) "{{{ +function! s:make_tag(line, regexp, func, ...) " Make tags for a given matched regexp. " Exclude preformatted text and href links. - - let patt_splitter = '\(`[^`]\+`\)\|\({{{.\+}}}\)\|'. - \ '\(\)\|\(\)' - if '`[^`]\+`' == a:regexp || '{{{.\+}}}' == a:regexp + " FIXME + let patt_splitter = '\(`[^`]\+`\)\|'. + \ '\('.vimwiki#vars#get_syntaxlocal('rxPreStart').'.\+'. + \ vimwiki#vars#get_syntaxlocal('rxPreEnd').'\)\|'. + \ '\(\)\|'. + \ '\(\)\|'. + \ '\(\)\|'. + \ '\('.vimwiki#vars#get_syntaxlocal('rxEqIn').'\)' + + "FIXME FIXME !!! these can easily occur on the same line! + "XXX {{{ }}} ??? obsolete + if '`[^`]\+`' ==# a:regexp || '{{{.\+}}}' ==# a:regexp || + \ vimwiki#vars#get_syntaxlocal('rxEqIn') ==# a:regexp let res_line = s:subst_func(a:line, a:regexp, a:func) else let pos = 0 @@ -524,90 +550,109 @@ function! s:make_tag(line, regexp, func) "{{{ let lines = split(a:line, patt_splitter, 1) let res_line = "" for line in lines - let res_line = res_line.s:subst_func(line, a:regexp, a:func) + if a:0 + let res_line = res_line.s:subst_func(line, a:regexp, a:func, a:1) + else + let res_line = res_line.s:subst_func(line, a:regexp, a:func) + endif let res_line = res_line.matchstr(a:line, patt_splitter, pos) let pos = matchend(a:line, patt_splitter, pos) endfor endif return res_line -endfunction "}}} +endfunction -function! s:process_tags_remove_links(line) " {{{ + +function! s:process_tags_remove_links(line) let line = a:line let line = s:make_tag(line, '\[\[.\{-}\]\]', 's:tag_remove_internal_link') let line = s:make_tag(line, '\[.\{-}\]', 's:tag_remove_external_link') return line -endfunction " }}} +endfunction + -function! s:process_tags_typefaces(line) "{{{ +function! s:process_tags_typefaces(line, header_ids) 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') - let line = s:make_tag(line, g:vimwiki_rxDelText, 's:tag_strike') - 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, vimwiki#vars#get_syntaxlocal('rxItalic'), 's:tag_em') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxBold'), 's:tag_strong', a:header_ids) + let line = s:make_tag(line, vimwiki#vars#get_global('rxTodo'), 's:tag_todo') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxDelText'), 's:tag_strike') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxSuperScript'), 's:tag_super') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxSubScript'), 's:tag_sub') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxCode'), 's:tag_code') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxEqIn'), 's:tag_eqin') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxTags'), 's:tag_tags', a:header_ids) return line -endfunction " }}} +endfunction -function! s:process_tags_links(line) " {{{ + +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, vimwiki#vars#get_syntaxlocal('rxWikiLink'), 's:tag_wikilink') + let line = s:make_tag(line, vimwiki#vars#get_global('rxWikiIncl'), 's:tag_wikiincl') + let line = s:make_tag(line, vimwiki#vars#get_syntaxlocal('rxWeblink'), 's:tag_weblink') return line -endfunction " }}} +endfunction + -function! s:process_inline_tags(line) "{{{ +function! s:process_inline_tags(line, header_ids) let line = s:process_tags_links(a:line) - let line = s:process_tags_typefaces(line) + let line = s:process_tags_typefaces(line, a:header_ids) return line -endfunction " }}} -"}}} +endfunction -" BLOCK TAGS {{{ -function! s:close_tag_pre(pre, ldest) "{{{ + +function! s:close_tag_pre(pre, ldest) if a:pre[0] call insert(a:ldest, "") return 0 endif return a:pre -endfunction "}}} +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) "{{{ +function! s:close_tag_quote(quote, ldest) if a:quote call insert(a:ldest, "") return 0 endif return a:quote -endfunction "}}} +endfunction -function! s:close_tag_para(para, ldest) "{{{ + +function! s:close_tag_para(para, ldest) if a:para call insert(a:ldest, "

") return 0 endif return a:para -endfunction "}}} +endfunction + -function! s:close_tag_table(table, ldest) "{{{ +function! s:close_tag_table(table, ldest, header_ids) " The first element of table list is a string which tells us if table should be centered. " The rest elements are rows which are lists of columns: - " ['center', + " ['center', " [ CELL1, CELL2, CELL3 ], " [ CELL1, CELL2, CELL3 ], " [ CELL1, CELL2, CELL3 ], " ] " And CELLx is: { 'body': 'col_x', 'rowspan': r, 'colspan': c } - function! s:sum_rowspan(table) "{{{ + function! s:sum_rowspan(table) let table = a:table " Get max cells - let max_cells = 0 + let max_cells = 0 for row in table[1:] let n_cells = len(row) if n_cells > max_cells @@ -633,9 +678,9 @@ function! s:close_tag_table(table, ldest) "{{{ endif endfor endfor - endfunction "}}} + endfunction - function! s:sum_colspan(table) "{{{ + function! s:sum_colspan(table) for row in a:table[1:] let cols = 1 @@ -648,19 +693,19 @@ function! s:close_tag_table(table, ldest) "{{{ endif endfor endfor - endfunction "}}} + endfunction - function! s:close_tag_row(row, header, ldest) "{{{ + function! s:close_tag_row(row, header, ldest, header_ids) call add(a:ldest, '') - " Set tag element of columns + " Set tag element of columns if a:header let tag_name = 'th' else let tag_name = 'td' end - " Close tag of columns + " Close tag of columns for cell in a:row if cell.rowspan == 0 || cell.colspan == 0 continue @@ -678,12 +723,12 @@ function! s:close_tag_table(table, ldest) "{{{ endif call add(a:ldest, '<' . tag_name . rowspan_attr . colspan_attr .'>') - call add(a:ldest, s:process_inline_tags(cell.body)) + call add(a:ldest, s:process_inline_tags(cell.body, a:header_ids)) call add(a:ldest, '') endfor call add(a:ldest, '') - endfunction "}}} + endfunction let table = a:table let ldest = a:ldest @@ -691,7 +736,7 @@ function! s:close_tag_table(table, ldest) "{{{ call s:sum_rowspan(table) call s:sum_colspan(table) - if table[0] == 'center' + if table[0] ==# 'center' call add(ldest, "") else call add(ldest, "
") @@ -711,45 +756,52 @@ function! s:close_tag_table(table, ldest) "{{{ if head > 0 for row in table[1 : head-1] if !empty(filter(row, '!empty(v:val)')) - call s:close_tag_row(row, 1, ldest) + call s:close_tag_row(row, 1, ldest, a:header_ids) endif endfor for row in table[head+1 :] - call s:close_tag_row(row, 0, ldest) + call s:close_tag_row(row, 0, ldest, a:header_ids) endfor else for row in table[1 :] - call s:close_tag_row(row, 0, ldest) + call s:close_tag_row(row, 0, ldest, a:header_ids) endfor endif call add(ldest, "
") let table = [] endif return table -endfunction "}}} +endfunction -function! s:close_tag_list(lists, ldest) "{{{ + +function! s:close_tag_list(lists, ldest) while len(a:lists) let item = remove(a:lists, 0) call insert(a:ldest, item[0]) endwhile -endfunction! "}}} +endfunction + -function! s:close_tag_def_list(deflist, ldest) "{{{ +function! s:close_tag_def_list(deflist, ldest) if a:deflist call insert(a:ldest, "") return 0 endif return a:deflist -endfunction! "}}} +endfunction + -function! s:process_tag_pre(line, pre) "{{{ +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, "
")
@@ -758,22 +810,62 @@ function! s:process_tag_pre(line, pre) "{{{
     endif
     let pre = [1, len(matchstr(a:line, '^\s*\ze{{{'))]
     let processed = 1
-  elseif pre[0] && a:line =~ '^\s*}}}\s*$'
+  elseif pre[0] && a:line =~# '^\s*}}}\s*$'
     let pre = [0, 0]
     call add(lines, "
") 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_preformatted(a:line)) endif return [processed, lines, pre] -endfunction "}}} +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') + " store the environment name in a global variable in order to close the + " 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}', '')) + 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 s:current_math_env != "" + call add(lines, "\\end{".s:current_math_env."}") + 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) "{{{ +function! s:process_tag_quote(line, quote) let lines = [] let quote = a:quote let processed = 0 - if a:line =~ '^\s\{4,}\S' + if a:line =~# '^\s\{4,}\S' if !quote call add(lines, "
") let quote = 1 @@ -785,37 +877,38 @@ function! s:process_tag_quote(line, quote) "{{{ let quote = 0 endif return [processed, lines, quote] -endfunction "}}} +endfunction -function! s:process_tag_list(line, lists) "{{{ - function! s:add_checkbox(line, rx_list, st_tag, en_tag) "{{{ - let st_tag = a:st_tag - let en_tag = a:en_tag +function! s:process_tag_list(line, lists) + function! s:add_checkbox(line, rx_list) + let st_tag = '
  • ' let chk = matchlist(a:line, a:rx_list) - if len(chk) > 0 - if len(chk[1])>0 - "wildcard characters are difficult to match correctly - if chk[1] =~ '[.*\\^$~]' - let chk[1] ='\'.chk[1] - endif - let completion = match(g:vimwiki_listsyms, '\C' . chk[1]) - if completion >= 0 && completion <=4 - let st_tag = '
  • ' - endif + if !empty(chk) && len(chk[1]) > 0 + let completion = index(vimwiki#vars#get_syntaxlocal('listsyms_list'), chk[1]) + let n = len(vimwiki#vars#get_syntaxlocal('listsyms_list')) + if completion == 0 + let st_tag = '
  • ' + elseif completion == -1 && chk[1] == vimwiki#vars#get_global('listsym_rejected') + let st_tag = '
  • ' + elseif completion > 0 && completion < n + let completion = float2nr(round(completion / (n-1.0) * 3.0 + 0.5 )) + let st_tag = '
  • ' endif endif - return [st_tag, en_tag] - endfunction "}}} + return [st_tag, ''] + endfunction + let in_list = (len(a:lists) > 0) " If it is not list yet then do not process line that starts from *bold* " text. + " XXX necessary? in *bold* text, no space must follow the first * if !in_list - let pos = match(a:line, g:vimwiki_rxBold) - if pos != -1 && strpart(a:line, 0, pos) =~ '^\s*$' + let pos = match(a:line, '^\s*'.vimwiki#vars#get_syntaxlocal('rxBold')) + if pos != -1 return [0, []] endif endif @@ -823,16 +916,16 @@ function! s:process_tag_list(line, lists) "{{{ let lines = [] let processed = 0 - if a:line =~ g:vimwiki_rxListBullet - let lstSym = matchstr(a:line, '[*-]') + if a:line =~# '^\s*'.s:bullets.'\s' + let lstSym = matchstr(a:line, s:bullets) let lstTagOpen = '
      ' let lstTagClose = '
    ' - let lstRegExp = g:vimwiki_rxListBullet - elseif a:line =~ g:vimwiki_rxListNumber - let lstSym = '#' + let lstRegExp = '^\s*'.s:bullets.'\s' + elseif a:line =~# '^\s*'.s:numbers.'\s' + let lstSym = matchstr(a:line, s:numbers) let lstTagOpen = '
      ' let lstTagClose = '
    ' - let lstRegExp = g:vimwiki_rxListNumber + let lstRegExp = '^\s*'.s:numbers.'\s' else let lstSym = '' let lstTagOpen = '' @@ -846,9 +939,8 @@ function! s:process_tag_list(line, lists) "{{{ let line = substitute(a:line, '\t', repeat(' ', &tabstop), 'g') let indent = stridx(line, lstSym) - let checkbox = '\s*\[\(.\?\)\]\s*' - let [st_tag, en_tag] = s:add_checkbox(line, - \ lstRegExp.checkbox, '
  • ', '') + let checkbox = '\s*\[\(.\)\]\s*' + let [st_tag, en_tag] = s:add_checkbox(line, lstRegExp.checkbox) if !in_list call add(a:lists, [lstTagClose, indent]) @@ -871,11 +963,10 @@ function! s:process_tag_list(line, lists) "{{{ call add(a:lists, [en_tag, indent]) call add(lines, st_tag) - call add(lines, - \ substitute(a:line, lstRegExp.'\%('.checkbox.'\)\?', '', '')) + call add(lines, substitute(a:line, lstRegExp.'\%('.checkbox.'\)\?', '', '')) let processed = 1 - elseif in_list > 0 && a:line =~ '^\s\+\S\+' - if g:vimwiki_list_ignore_newline + elseif in_list && a:line =~# '^\s\+\S\+' + if vimwiki#vars#get_global('list_ignore_newline') call add(lines, a:line) else call add(lines, '
    '.a:line) @@ -885,9 +976,10 @@ function! s:process_tag_list(line, lists) "{{{ call s:close_tag_list(a:lists, lines) endif return [processed, lines] -endfunction "}}} +endfunction -function! s:process_tag_def_list(line, deflist) "{{{ + +function! s:process_tag_def_list(line, deflist) let lines = [] let deflist = a:deflist let processed = 0 @@ -909,68 +1001,86 @@ function! s:process_tag_def_list(line, deflist) "{{{ call add(lines, "") endif return [processed, lines, deflist] -endfunction "}}} +endfunction + -function! s:process_tag_para(line, para) "{{{ +function! s:process_tag_para(line, para) let lines = [] let para = a:para let processed = 0 - if a:line =~ '^\s\{,3}\S' + if a:line =~# '^\s\{,3}\S' if !para call add(lines, "

    ") let para = 1 endif let processed = 1 - call add(lines, a:line) - elseif para && a:line =~ '^\s*$' + if vimwiki#vars#get_global('text_ignore_newline') + call add(lines, a:line) + else + call add(lines, a:line."
    ") + endif + elseif para && a:line =~# '^\s*$' call add(lines, "

    ") let para = 0 endif return [processed, lines, para] -endfunction "}}} +endfunction + -function! s:process_tag_h(line, id) "{{{ +function! s:process_tag_h(line, id) let line = a:line let processed = 0 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 =~# vimwiki#vars#get_syntaxlocal('rxHeader') + let h_level = vimwiki#u#count_first_sym(a:line) endif if h_level > 0 - let a:id[h_level] += 1 - " reset higher level ids - for level in range(h_level+1, 6) - let a:id[level] = 0 - endfor - let centered = 0 - if a:line =~ '^\s\+' - let centered = 1 - endif + let h_text = vimwiki#u#trim(matchstr(line, vimwiki#vars#get_syntaxlocal('rxHeader'))) + let h_number = '' + let h_complete_id = '' + let h_id = s:escape_html_attribute(h_text) + let centered = (a:line =~# '^\s') - let line = s:trim(line) + if h_text !=# vimwiki#vars#get_global('toc_header') - let h_number = '' - for l in range(1, h_level-1) - let h_number .= a:id[l].'.' - endfor - let h_number .= a:id[h_level] + let a:id[h_level-1] = [h_text, a:id[h_level-1][1]+1] + + " reset higher level ids + for level in range(h_level, 5) + let a:id[level] = ['', 0] + endfor - let h_id = 'toc_'.h_number + for l in range(h_level-1) + let h_number .= a:id[l][1].'.' + if a:id[l][0] != '' + let h_complete_id .= a:id[l][0].'-' + endif + endfor + let h_number .= a:id[h_level-1][1] + let h_complete_id .= a:id[h_level-1][0] + + if vimwiki#vars#get_global('html_header_numbering') + let num = matchstr(h_number, + \ '^\(\d.\)\{'.(vimwiki#vars#get_global('html_header_numbering')-1).'}\zs.*') + if !empty(num) + let num .= vimwiki#vars#get_global('html_header_numbering_sym') + endif + let h_text = num.' '.h_text + endif + let h_complete_id = s:escape_html_attribute(h_complete_id) + let h_part = '
    ' - let line = h_part.h_text.'' let processed = 1 endif - return [processed, line, h_level, h_text, h_id] -endfunction "}}} + return [processed, line] +endfunction + -function! s:process_tag_hr(line) "{{{ +function! s:process_tag_hr(line) let line = a:line let processed = 0 - if a:line =~ '^-----*$' + if a:line =~# '^-----*$' let line = '
    ' let processed = 1 endif return [processed, line] -endfunction "}}} +endfunction -function! s:process_tag_table(line, table) "{{{ - function! s:table_empty_cell(value) "{{{ + +function! s:process_tag_table(line, table, header_ids) + function! s:table_empty_cell(value) let cell = {} - if a:value =~ '^\s*\\/\s*$' + if a:value =~# '^\s*\\/\s*$' let cell.body = '' let cell.rowspan = 0 let cell.colspan = 1 - elseif a:value =~ '^\s*>\s*$' + elseif a:value =~# '^\s*>\s*$' let cell.body = '' let cell.rowspan = 1 let cell.colspan = 0 - elseif a:value =~ '^\s*$' + elseif a:value =~# '^\s*$' let cell.body = ' ' let cell.rowspan = 1 let cell.colspan = 1 @@ -1027,11 +1132,11 @@ function! s:process_tag_table(line, table) "{{{ endif return cell - endfunction "}}} + endfunction - function! s:table_add_row(table, line) "{{{ + function! s:table_add_row(table, line) if empty(a:table) - if a:line =~ '^\s\+' + if a:line =~# '^\s\+' let row = ['center', []] else let row = ['normal', []] @@ -1040,60 +1145,83 @@ function! s:process_tag_table(line, table) "{{{ let row = [[]] endif return row - endfunction "}}} + endfunction let table = a: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 - let table = s:close_tag_table(table, lines) + let table = s:close_tag_table(table, lines, a:header_ids) endif return [processed, lines, table] -endfunction "}}} - -"}}} +endfunction -" }}} -" WIKI2HTML "{{{ -function! s:parse_line(line, state) " {{{ +function! s:parse_line(line, state) let 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 let state.placeholder = a:state.placeholder - let state.toc = a:state.toc - let state.toc_id = a:state.toc_id + let state.header_ids = a:state.header_ids let res_lines = [] - let line = s:safe_html(a:line) + let line = s:safe_html_line(a:line) let processed = 0 + " pres + if !processed + let [processed, lines, state.pre] = s:process_tag_pre(line, state.pre) + " pre is just fine to be in the list -- do not close list item here. + " 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, state.header_ids) + endif + if processed && state.deflist + let state.deflist = s:close_tag_def_list(state.deflist, lines) + endif + if processed && state.quote + let state.quote = s:close_tag_quote(state.quote, lines) + endif + if processed && state.para + let state.para = s:close_tag_para(state.para, lines) + endif + call extend(res_lines, lines) + endif + + if !processed - if line =~ g:vimwiki_rxComment + if line =~# vimwiki#vars#get_syntaxlocal('rxComment') let processed = 1 endif endif " nohtml -- placeholder if !processed - if line =~ '^\s*%nohtml' + if line =~# '\m^\s*%nohtml\s*$' let processed = 1 let state.placeholder = ['nohtml'] endif @@ -1101,57 +1229,40 @@ function! s:parse_line(line, state) " {{{ " title -- placeholder if !processed - if line =~ '^\s*%title' + if line =~# '\m^\s*%title\%(\s.*\)\?$' let processed = 1 - let param = matchstr(line, '^\s*%title\s\zs.*') + let param = matchstr(line, '\m^\s*%title\s\+\zs.*') let state.placeholder = ['title', param] endif endif - " html template -- placeholder "{{{ + " date -- placeholder if !processed - if line =~ '^\s*%template' + if line =~# '\m^\s*%date\%(\s.*\)\?$' let processed = 1 - let param = matchstr(line, '^\s*%template\s\zs.*') - let state.placeholder = ['template', param] + let param = matchstr(line, '\m^\s*%date\s\+\zs.*') + let state.placeholder = ['date', param] endif endif - "}}} - " toc -- placeholder "{{{ + " html template -- placeholder if !processed - if line =~ '^\s*%toc' + if line =~# '\m^\s*%template\%(\s.*\)\?$' let processed = 1 - let param = matchstr(line, '^\s*%toc\s\zs.*') - let state.placeholder = ['toc', param] + let param = matchstr(line, '\m^\s*%template\s\+\zs.*') + let state.placeholder = ['template', param] endif endif - "}}} - " pres "{{{ + + " tables if !processed - let [processed, lines, state.pre] = s:process_tag_pre(line, state.pre) - " pre is just fine to be in the list -- do not close list item here. - " if processed && len(state.lists) - " call s:close_tag_list(state.lists, lines) - " endif - if processed && len(state.table) - let state.table = s:close_tag_table(state.table, lines) - endif - if processed && state.deflist - let state.deflist = s:close_tag_def_list(state.deflist, lines) - endif - if processed && state.quote - let state.quote = s:close_tag_quote(state.quote, lines) - endif - if processed && state.para - let state.para = s:close_tag_para(state.para, lines) - endif + let [processed, lines, state.table] = s:process_tag_table(line, state.table, state.header_ids) call extend(res_lines, lines) endif - "}}} - " lists "{{{ + + " lists if !processed let [processed, lines] = s:process_tag_list(line, state.lists) if processed && state.quote @@ -1160,8 +1271,11 @@ 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) + let state.table = s:close_tag_table(state.table, lines, state.header_ids) endif if processed && state.deflist let state.deflist = s:close_tag_def_list(state.deflist, lines) @@ -1170,40 +1284,29 @@ function! s:parse_line(line, state) " {{{ let state.para = s:close_tag_para(state.para, lines) endif - call map(lines, 's:process_inline_tags(v:val)') + call map(lines, 's:process_inline_tags(v:val, state.header_ids)') call extend(res_lines, lines) endif - "}}} - " headers "{{{ + + " headers if !processed - let [processed, line, h_level, h_text, h_id] = s:process_tag_h(line, state.toc_id) + let [processed, line] = s:process_tag_h(line, state.header_ids) if processed call s:close_tag_list(state.lists, res_lines) - let state.table = s:close_tag_table(state.table, res_lines) + let state.table = s:close_tag_table(state.table, res_lines, state.header_ids) 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) - let line = s:process_inline_tags(line) - call add(res_lines, line) - - " gather information for table of contents - call add(state.toc, [h_level, h_text, h_id]) endif endif - "}}} - " tables "{{{ - if !processed - let [processed, lines, state.table] = s:process_tag_table(line, state.table) - call extend(res_lines, lines) - endif - "}}} - " quotes "{{{ + " quotes if !processed let [processed, lines, state.quote] = s:process_tag_quote(line, state.quote) if processed && len(state.lists) @@ -1213,44 +1316,48 @@ function! s:parse_line(line, state) " {{{ let state.deflist = s:close_tag_def_list(state.deflist, lines) endif if processed && len(state.table) - let state.table = s:close_tag_table(state.table, lines) + let state.table = s:close_tag_table(state.table, lines, state.header_ids) endif 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 - call map(lines, 's:process_inline_tags(v:val)') + call map(lines, 's:process_inline_tags(v:val, state.header_ids)') call extend(res_lines, lines) endif - "}}} - " horizontal rules "{{{ + + " horizontal rules if !processed let [processed, line] = s:process_tag_hr(line) if processed call s:close_tag_list(state.lists, res_lines) - let state.table = s:close_tag_table(state.table, res_lines) + let state.table = s:close_tag_table(state.table, res_lines, state.header_ids) 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 - "}}} - " definition lists "{{{ + + " definition lists if !processed let [processed, lines, state.deflist] = s:process_tag_def_list(line, state.deflist) - call map(lines, 's:process_inline_tags(v:val)') + call map(lines, 's:process_inline_tags(v:val, state.header_ids)') call extend(res_lines, lines) endif - "}}} - "" P "{{{ + + "" P if !processed let [processed, lines, state.para] = s:process_tag_para(line, state.para) if processed && len(state.lists) @@ -1262,15 +1369,18 @@ 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) + let state.table = s:close_tag_table(state.table, res_lines, state.header_ids) endif - call map(lines, 's:process_inline_tags(v:val)') + call map(lines, 's:process_inline_tags(v:val, state.header_ids)') call extend(res_lines, lines) endif - "}}} + "" add the rest if !processed @@ -1279,163 +1389,276 @@ function! s:parse_line(line, state) " {{{ return [res_lines, state] -endfunction " }}} - -function! vimwiki#html#Wiki2HTML(path, wikifile) "{{{ - - let starttime = reltime() " start the clock - " echo 'Generating HTML ... ' - if !s:syntax_supported() - echomsg 'vimwiki: Only vimwiki_default syntax supported!!!' - return - endif +endfunction + + +function! s:use_custom_wiki2html() + let custom_wiki2html = vimwiki#vars#get_wikilocal('custom_wiki2html') + return !empty(custom_wiki2html) && + \ (s:file_exists(custom_wiki2html) || s:binary_exists(custom_wiki2html)) +endfunction + + +function! vimwiki#html#CustomWiki2HTML(path, wikifile, force) + call vimwiki#path#mkdir(a:path) + echomsg system(vimwiki#vars#get_wikilocal('custom_wiki2html'). ' '. + \ a:force. ' '. + \ vimwiki#vars#get_wikilocal('syntax'). ' '. + \ strpart(vimwiki#vars#get_wikilocal('ext'), 1). ' '. + \ shellescape(a:path). ' '. + \ shellescape(a:wikifile). ' '. + \ shellescape(s:default_CSS_full_name(a:path)). ' '. + \ (len(vimwiki#vars#get_wikilocal('template_path')) > 1 ? + \ shellescape(expand(vimwiki#vars#get_wikilocal('template_path'))) : '-'). ' '. + \ (len(vimwiki#vars#get_wikilocal('template_default')) > 0 ? + \ vimwiki#vars#get_wikilocal('template_default') : '-'). ' '. + \ (len(vimwiki#vars#get_wikilocal('template_ext')) > 0 ? + \ vimwiki#vars#get_wikilocal('template_ext') : '-'). ' '. + \ (len(vimwiki#vars#get_bufferlocal('subdir')) > 0 ? + \ shellescape(s:root_path(vimwiki#vars#get_bufferlocal('subdir'))) : '-'). ' '. + \ (len(vimwiki#vars#get_wikilocal('custom_wiki2html_args')) > 0 ? + \ vimwiki#vars#get_wikilocal('custom_wiki2html_args') : '-')) +endfunction + + +function! s:convert_file(path_html, wikifile) + 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).vimwiki#vars#get_bufferlocal('subdir') let htmlfile = fnamemodify(wikifile, ":t:r").'.html' - let lsource = readfile(wikifile) - let ldest = [] + " the currently processed file name is needed when processing links + " yeah yeah, shame on me for using (quasi-) global variables + let s:current_wiki_file = wikifile + let s:current_html_file = path_html . htmlfile - call vimwiki#base#mkdir(path) + if s:use_custom_wiki2html() + let force = 1 + call vimwiki#html#CustomWiki2HTML(path_html, wikifile, force) + let done = 1 + endif - " nohtml placeholder -- to skip html generation. - let nohtml = 0 + if s:syntax_supported() && done == 0 + let lsource = readfile(wikifile) + let ldest = [] + + call vimwiki#path#mkdir(path_html) + + " nohtml placeholder -- to skip html generation. + let nohtml = 0 + + " template placeholder + let template_name = '' + + " for table of contents placeholders. + let placeholders = [] + + " 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.header_ids = [['', 0], ['', 0], ['', 0], ['', 0], ['', 0], ['', 0]] + " [last seen header text in this level, number] + + " prepare constants for s:safe_html_line() + let s:lt_pattern = '<' + let s:gt_pattern = '>' + if vimwiki#vars#get_global('valid_html_tags') != '' + let tags = join(split(vimwiki#vars#get_global('valid_html_tags'), '\s*,\s*'), '\|') + let s:lt_pattern = '\c<\%(/\?\%('.tags.'\)\%(\s\{-1}\S\{-}\)\{-}/\?>\)\@!' + let s:gt_pattern = '\c\%(' + endif - " template placeholder - let template_name = '' + " prepare regexps for lists + let s:bullets = '[*-]' + let s:numbers = '\C\%(#\|\d\+)\|\d\+\.\|[ivxlcdm]\+)\|[IVXLCDM]\+)\|\l\{1,2})\|\u\{1,2})\)' - " for table of contents placeholders. - let placeholders = [] + for line in lsource + let oldquote = state.quote + let [lines, state] = s:parse_line(line, state) - " 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 } - - 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 - - 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)]) + " 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 + + 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 - let state.placeholder = [] + + call extend(ldest, lines) + endfor + + + if nohtml + echon "\r"."%nohtml placeholder found" + return '' endif + 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, state.header_ids) call extend(ldest, lines) - endfor + let title = s:process_title(placeholders, fnamemodify(a:wikifile, ":t:r")) + let date = s:process_date(placeholders, strftime('%Y-%m-%d')) - if nohtml - echon "\r"."%nohtml placeholder found" - return - endif + let html_lines = s:get_html_template(template_name) - let toc = s:get_html_toc(state.toc) - call s:process_toc(ldest, placeholders, toc) - call s:remove_blank_lines(ldest) + " processing template variables (refactor to a function) + call map(html_lines, 'substitute(v:val, "%title%", "'. title .'", "g")') + call map(html_lines, 'substitute(v:val, "%date%", "'. date .'", "g")') + call map(html_lines, 'substitute(v:val, "%root_path%", "'. + \ s:root_path(vimwiki#vars#get_bufferlocal('subdir')) .'", "g")') - "" 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 + let css_name = expand(vimwiki#vars#get_wikilocal('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% + + call writefile(html_lines, path_html.htmlfile) + let done = 1 + + endif + + if done == 0 + echomsg 'Vimwiki Error: Conversion to HTML is not supported for this syntax' + return '' 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) + return path_html.htmlfile +endfunction - " 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 -endfunction "}}} + +function! vimwiki#html#Wiki2HTML(path_html, wikifile) + let result = s:convert_file(a:path_html, a:wikifile) + if result != '' + call s:create_default_CSS(a:path_html) + endif + return result +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 Error: Conversion to HTML is not supported for this syntax' return endif - echomsg 'Saving vimwiki files...' + 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 = expand(a:path) - call vimwiki#base#mkdir(path) + let path_html = expand(a:path_html) + call vimwiki#path#mkdir(path_html) - echomsg 'Deleting non-wiki html files...' - call s:delete_html_files(path) + echomsg 'Vimwiki: Deleting non-wiki html files ...' + call s:delete_html_files(path_html) - echomsg 'Converting wiki to html files...' + echomsg 'Vimwiki: Converting wiki to html files ...' let setting_more = &more setlocal nomore - let wikifiles = split(glob(VimwikiGet('path').'**/*'.VimwikiGet('ext')), '\n') + " temporarily adjust current_subdir global state variable + let current_subdir = vimwiki#vars#get_bufferlocal('subdir') + let current_invsubdir = vimwiki#vars#get_bufferlocal('invsubdir') + + let wikifiles = split(glob(vimwiki#vars#get_wikilocal('path').'**/*'. + \ vimwiki#vars#get_wikilocal('ext')), '\n') for wikifile in wikifiles + let wikifile = fnamemodify(wikifile, ":p") + + " temporarily adjust 'subdir' and 'invsubdir' state variables + let subdir = vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path'), wikifile) + call vimwiki#vars#set_bufferlocal('subdir', subdir) + call vimwiki#vars#set_bufferlocal('invsubdir', vimwiki#base#invsubdir(subdir)) + if !s:is_html_uptodate(wikifile) - echomsg 'Processing '.wikifile - call vimwiki#html#Wiki2HTML(path, wikifile) + echomsg 'Vimwiki: Processing '.wikifile + + call s:convert_file(path_html, wikifile) else - echomsg 'Skipping '.wikifile + echomsg 'Vimwiki: Skipping '.wikifile endif endfor - call s:create_default_CSS(path) - echomsg 'Done!' + " reset 'subdir' state variable + call vimwiki#vars#set_bufferlocal('subdir', current_subdir) + call vimwiki#vars#set_bufferlocal('invsubdir', current_invsubdir) + + let created = s:create_default_CSS(path_html) + if created + echomsg 'Vimwiki: Default style.css has been created' + endif + echomsg 'Vimwiki: HTML exported to '.path_html + echomsg 'Vimwiki: Done!' let &more = setting_more -endfunction "}}} -"}}} +endfunction + + +function! s:file_exists(fname) + return !empty(getftype(expand(a:fname))) +endfunction + + +function! s:binary_exists(fname) + return executable(expand(a:fname)) +endfunction + + +function! s:get_wikifile_url(wikifile) + return vimwiki#vars#get_wikilocal('path_html') . + \ vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path'), a:wikifile). + \ fnamemodify(a:wikifile, ":t:r").'.html' +endfunction + + +function! vimwiki#html#PasteUrl(wikifile) + execute 'r !echo file://'.s:get_wikifile_url(a:wikifile) +endfunction + + +function! vimwiki#html#CatUrl(wikifile) + execute '!echo file://'.s:get_wikifile_url(a:wikifile) +endfunction + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/lst.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/lst.vim index a359d96..201a658 100644 --- a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/lst.vim +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/lst.vim @@ -1,369 +1,1697 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Todo lists related stuff here. -" Author: Maxim Kim -" Home: http://code.google.com/p/vimwiki/ +" Description: Everything concerning lists and checkboxes +" Home: https://github.com/vimwiki/vimwiki/ + if exists("g:loaded_vimwiki_list_auto") || &cp finish endif -let g:loaded_vimwiki_lst_auto = 1 +let g:loaded_vimwiki_list_auto = 1 -" Script variables {{{ -let s:rx_li_box = '\[.\?\]' -" }}} -" Script functions {{{ +" --------------------------------------------------------- +" incrementation functions for the various kinds of numbers +" --------------------------------------------------------- -" Get checkbox regexp -function! s:rx_li_symbol(rate) "{{{ - let result = '' - if a:rate == 100 - let result = g:vimwiki_listsyms[4] - elseif a:rate == 0 - let result = g:vimwiki_listsyms[0] - elseif a:rate >= 67 - let result = g:vimwiki_listsyms[3] - elseif a:rate >= 34 - let result = g:vimwiki_listsyms[2] +function! s:increment_1(value) + return eval(a:value) + 1 +endfunction + + +function! s:increment_A(value) + let list_of_chars = split(a:value, '.\zs') + let done = 0 + for idx in reverse(range(len(list_of_chars))) + let cur_num = char2nr(list_of_chars[idx]) + if cur_num < 90 + let list_of_chars[idx] = nr2char(cur_num + 1) + let done = 1 + break + else + let list_of_chars[idx] = 'A' + endif + endfor + if !done + call insert(list_of_chars, 'A') + endif + return join(list_of_chars, '') +endfunction + + +function! s:increment_a(value) + let list_of_chars = split(a:value, '.\zs') + let done = 0 + for idx in reverse(range(len(list_of_chars))) + let cur_num = char2nr(list_of_chars[idx]) + if cur_num < 122 + let list_of_chars[idx] = nr2char(cur_num + 1) + let done = 1 + break + else + let list_of_chars[idx] = 'a' + endif + endfor + if !done + call insert(list_of_chars, 'a') + endif + return join(list_of_chars, '') +endfunction + + +function! s:increment_I(value) + let subst_list = [ ['XLVIII$', 'IL'], ['VIII$', 'IX'], ['III$', 'IV'], + \ ['DCCCXCIX$', 'CM'], ['CCCXCIX$', 'CD'], ['LXXXIX$', 'XC'], + \ ['XXXIX$', 'XL'], ['\(I\{1,2\}\)$', '\1I'], ['CDXCIX$', 'D'], + \ ['CMXCIX$', 'M'], ['XCIX$', 'C'], ['I\([VXLCDM]\)$', '\1'], + \ ['\([VXLCDM]\)$', '\1I'] ] + for [regex, subst] in subst_list + if a:value =~# regex + return substitute(a:value, regex, subst, '') + endif + endfor + return '' +endfunction + + +function! s:increment_i(value) + let subst_list = [ ['xlviii$', 'il'], ['viii$', 'ix'], ['iii$', 'iv'], + \ ['dcccxcix$', 'cm'], ['cccxcix$', 'cd'], ['lxxxix$', 'xc'], + \ ['xxxix$', 'xl'], ['\(i\{1,2\}\)$', '\1i'], ['cdxcix$', 'd'], + \ ['cmxcix$', 'm'], ['xcix$', 'c'], ['i\([vxlcdm]\)$', '\1'], + \ ['\([vxlcdm]\)$', '\1i'] ] + for [regex, subst] in subst_list + if a:value =~# regex + return substitute(a:value, regex, subst, '') + endif + endfor + return '' +endfunction + + +" --------------------------------------------------------- +" utility functions +" --------------------------------------------------------- + +function! s:substitute_rx_in_line(lnum, pattern, new_string) + call setline(a:lnum, substitute(getline(a:lnum), a:pattern, a:new_string, '')) +endfunction + + +function! s:substitute_string_in_line(lnum, old_string, new_string) + call s:substitute_rx_in_line(a:lnum, vimwiki#u#escape(a:old_string), a:new_string) +endfunction + + +function! s:first_char(string) + return matchstr(a:string, '^.') +endfunction + + +if exists("*strdisplaywidth") + function! s:string_length(str) + return strdisplaywidth(a:str) + endfunction +else + function! s:string_length(str) + return strlen(substitute(a:str, '.', 'x', 'g')) + endfunction +endif + + +function! vimwiki#lst#default_symbol() + return vimwiki#vars#get_syntaxlocal('list_markers')[0] +endfunction + + +function! vimwiki#lst#get_list_margin() + let list_margin = vimwiki#vars#get_wikilocal('list_margin') + if list_margin < 0 + return &sw else - let result = g:vimwiki_listsyms[1] + return list_margin endif +endfunction - return '\['.result.'\]' -endfunction "}}} -" Get regexp of the list item. -function! s:rx_list_item() "{{{ - return '\('.g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber.'\)' -endfunction "}}} +"Returns: the column where the text of a line starts (possible list item +"markers and checkboxes are skipped) +function! s:text_begin(lnum) + return s:string_length(matchstr(getline(a:lnum), vimwiki#vars#get_syntaxlocal('rxListItem'))) +endfunction -" Get regexp of the list item with checkbox. -function! s:rx_cb_list_item() "{{{ - return s:rx_list_item().'\s*\zs\[.\?\]' -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)) +"Returns: 2 if there is a marker and text +" 1 for a marker and no text +" 0 for no marker at all (empty line or only text) +function! s:line_has_marker(lnum) + if getline(a:lnum) =~# vimwiki#vars#get_syntaxlocal('rxListItem').'\s*$' + return 1 + elseif getline(a:lnum) =~# vimwiki#vars#get_syntaxlocal('rxListItem').'\s*\S' + return 2 else + return 0 + endif +endfunction + + +" --------------------------------------------------------- +" get properties of a list item +" --------------------------------------------------------- + +"Returns: the mainly used data structure in this file +"An item represents a single list item and is a dictionary with the keys +"lnum - the line number of the list item +"type - 1 for bulleted item, 2 for numbered item, 0 for a regular line +"mrkr - the concrete marker, e.g. '**' or 'b)' +"cb - the char in the checkbox or '' if there is no checkbox +function! s:get_item(lnum) + let item = {'lnum': a:lnum} + if a:lnum == 0 || a:lnum > line('$') + let item.type = 0 + return item + endif + + let matches = matchlist(getline(a:lnum), vimwiki#vars#get_syntaxlocal('rxListItem')) + if matches == [] || + \ (matches[1] == '' && matches[2] == '') || + \ (matches[1] != '' && matches[2] != '') + let item.type = 0 + return item + endif + + let item.cb = matches[3] + + if matches[1] != '' + let item.type = 1 + let item.mrkr = matches[1] + else + let item.type = 2 + let item.mrkr = matches[2] + endif + + return item +endfunction + + +function! s:empty_item() + return {'type': 0} +endfunction + + +"Returns: level of the line +"0 is the 'highest' level +function! s:get_level(lnum) + if getline(a:lnum) =~# '^\s*$' + return 0 + endif + if !vimwiki#vars#get_syntaxlocal('recurring_bullets') let level = indent(a:lnum) + else + let level = s:string_length(matchstr(getline(a:lnum), + \ vimwiki#vars#get_syntaxlocal(rx_bullet_chars)))-1 + if level < 0 + let level = (indent(a:lnum) == 0) ? 0 : 9999 + endif endif return level -endfunction "}}} +endfunction + + +"Returns: 1, a, i, A, I or '' +"If in doubt if alphanumeric character or romanian +"numeral, peek in the previous line +function! s:guess_kind_of_numbered_item(item) + if a:item.type != 2 | return '' | endif + let number_chars = a:item.mrkr[:-2] + let divisor = a:item.mrkr[-1:] + + let number_kinds = vimwiki#vars#get_syntaxlocal('number_kinds') + + if number_chars =~# '\d\+' + return '1' + endif + if number_chars =~# '\l\+' + if number_chars !~# '^[ivxlcdm]\+' || index(number_kinds, 'i') == -1 + return 'a' + else + + let item_above = s:get_prev_list_item(a:item, 0) + if item_above.type != 0 + if index(number_kinds, 'a') == -1 || + \ (item_above.mrkr[-1:] !=# divisor && number_chars =~# 'i\+') || + \ s:increment_i(item_above.mrkr[:-2]) ==# number_chars + return 'i' + else + return 'a' + endif + else + if number_chars =~# 'i\+' || index(number_kinds, 'a') == -1 + return 'i' + else + return 'a' + endif + endif -" Get previous list item. -" Returns: line number or 0. -function! s:prev_list_item(lnum) "{{{ - let c_lnum = a:lnum - 1 - while c_lnum >= 1 - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum endif - if line =~ '^\s*$' - return 0 + endif + if number_chars =~# '\u\+' + if number_chars !~# '^[IVXLCDM]\+' || index(number_kinds, 'I') == -1 + return 'A' + else + + let item_above = s:get_prev_list_item(a:item, 0) + if item_above.type != 0 + if index(number_kinds, 'A') == -1 || + \ (item_above.mrkr[-1:] !=# divisor && number_chars =~# 'I\+') || + \ s:increment_I(item_above.mrkr[:-2]) ==# number_chars + return 'I' + else + return 'A' + endif + else + if number_chars =~# 'I\+' || index(number_kinds, 'A') == -1 + return 'I' + else + return 'A' + endif + endif + endif - let c_lnum -= 1 + endif +endfunction + + +function! s:regexp_of_marker(item) + if a:item.type == 1 + return vimwiki#u#escape(a:item.mrkr) + elseif a:item.type == 2 + let number_divisors = vimwiki#vars#get_syntaxlocal('number_divisors') + for ki in ['d', 'u', 'l'] + let match = matchstr(a:item.mrkr, '\'.ki.'\+['.number_divisors.']') + if match != '' + return '\'.ki.'\+'.vimwiki#u#escape(match[-1:]) + endif + endfor + else + return '' + endif +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 +" --------------------------------------------------------- + +"Returns: the list item after a:item or an empty item +"If a:ignore_kind is 1, the markers can differ +function! s:get_next_list_item(item, ignore_kind) + let org_lvl = s:get_level(a:item.lnum) + if !a:ignore_kind + let org_regex = s:regexp_of_marker(a:item) + endif + + let cur_ln = s:get_next_line(a:item.lnum) + while cur_ln <= line('$') + let cur_lvl = s:get_level(cur_ln) + if cur_lvl <= org_lvl + if a:ignore_kind + return s:get_any_item_of_level(cur_ln, cur_lvl, org_lvl) + else + return s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex) + endif + endif + let cur_ln = s:get_next_line(cur_ln) endwhile - return 0 -endfunction "}}} - -" Get next list item in the list. -" Returns: line number or 0. -function! s:next_list_item(lnum) "{{{ - let c_lnum = a:lnum + 1 - while c_lnum <= line('$') - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum - endif - if line =~ '^\s*$' - return 0 - endif - let c_lnum += 1 + return s:empty_item() +endfunction + + +"Returns: the list item before a:item or an empty item +"If a:ignore_kind is 1, the markers can differ +function! s:get_prev_list_item(item, ignore_kind) + let org_lvl = s:get_level(a:item.lnum) + if !a:ignore_kind + let org_regex = s:regexp_of_marker(a:item) + endif + + let cur_ln = s:get_prev_line(a:item.lnum) + while cur_ln >= 1 + let cur_lvl = s:get_level(cur_ln) + if cur_lvl <= org_lvl + if a:ignore_kind + return s:get_any_item_of_level(cur_ln, cur_lvl, org_lvl) + else + return s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex) + endif + endif + let cur_ln = s:get_prev_line(cur_ln) + endwhile + return s:empty_item() +endfunction + + +function! s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex) + let cur_linecontent = getline(a:cur_ln) + if a:cur_lvl == a:org_lvl + if cur_linecontent =~# '^\s*'.a:org_regex.'\s' + return s:get_item(a:cur_ln) + else + return s:empty_item() + endif + elseif a:cur_lvl < a:org_lvl + return s:empty_item() + endif +endfunction + + +function! s:get_any_item_of_level(cur_ln, cur_lvl, org_lvl) + if a:cur_lvl == a:org_lvl + return s:get_item(a:cur_ln) + elseif a:cur_lvl < a:org_lvl + return s:empty_item() + endif +endfunction + + +function! s:get_first_item_in_list(item, ignore_kind) + let cur_item = a:item + while 1 + let prev_item = s:get_prev_list_item(cur_item, a:ignore_kind) + if prev_item.type == 0 + break + else + let cur_item = prev_item + endif endwhile - return 0 -endfunction "}}} - -" Find next list item in the buffer. -" Returns: line number or 0. -function! s:find_next_list_item(lnum) "{{{ - let c_lnum = a:lnum + 1 - while c_lnum <= line('$') - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum - endif - let c_lnum += 1 + return cur_item +endfunction + + +function! s:get_last_item_in_list(item, ignore_kind) + let cur_item = a:item + while 1 + let next_item = s:get_next_list_item(cur_item, a:ignore_kind) + if next_item.type == 0 + break + else + let cur_item = next_item + endif endwhile - return 0 -endfunction "}}} - -" Set state of the list item on line number "lnum" to [ ] or [x] -function! s:set_state(lnum, rate) "{{{ - let line = getline(a:lnum) - let state = s:rx_li_symbol(a:rate) - let line = substitute(line, s:rx_li_box, state, '') - call setline(a:lnum, line) -endfunction "}}} - -" Get state of the list item on line number "lnum" -function! s:get_state(lnum) "{{{ - let state = 0 - let line = getline(a:lnum) - let opt = matchstr(line, s:rx_cb_list_item()) - if opt =~ s:rx_li_symbol(100) - let state = 100 - elseif opt =~ s:rx_li_symbol(0) - let state = 0 - elseif opt =~ s:rx_li_symbol(25) - let state = 25 - elseif opt =~ s:rx_li_symbol(50) - let state = 50 - elseif opt =~ s:rx_li_symbol(75) - let state = 75 + return cur_item +endfunction + + +"Returns: lnum+1 in most cases, but skips blank lines and preformatted text, +"0 in case of nonvalid line. +"If there is no second argument, 0 is returned at a header, otherwise the +"header is skipped +function! s:get_next_line(lnum, ...) + if getline(a:lnum) =~# vimwiki#vars#get_syntaxlocal('rxPreStart') + let cur_ln = a:lnum + 1 + while cur_ln <= line('$') && getline(cur_ln) !~# vimwiki#vars#get_syntaxlocal('rxPreEnd') + let cur_ln += 1 + endwhile + let next_line = cur_ln + else + let next_line = nextnonblank(a:lnum+1) endif - return state -endfunction "}}} -" Returns 1 if there is checkbox on a list item, 0 otherwise. -function! s:is_cb_list_item(lnum) "{{{ - return getline(a:lnum) =~ s:rx_cb_list_item() -endfunction "}}} + if a:0 > 0 && getline(next_line) =~# vimwiki#vars#get_syntaxlocal('rxHeader') + let next_line = s:get_next_line(next_line, 1) + endif + + if next_line < 0 || next_line > line('$') || + \ (getline(next_line) =~# vimwiki#vars#get_syntaxlocal('rxHeader') && a:0 == 0) + return 0 + endif + + return next_line +endfunction -" Returns start line number of list item, 0 if it is not a list. -function! s:is_list_item(lnum) "{{{ - let c_lnum = a:lnum - while c_lnum >= 1 - let line = getline(c_lnum) - if line =~ s:rx_list_item() - return c_lnum + +"Returns: lnum-1 in most cases, but skips blank lines and preformatted text +"0 in case of nonvalid line and a header, because a header ends every list +function! s:get_prev_line(lnum) + let prev_line = prevnonblank(a:lnum-1) + + if getline(prev_line) =~# vimwiki#vars#get_syntaxlocal('rxPreEnd') + let cur_ln = a:lnum - 1 + while 1 + if cur_ln == 0 || getline(cur_ln) =~# vimwiki#vars#get_syntaxlocal('rxPreStart') + break + endif + let cur_ln -= 1 + endwhile + let prev_line = cur_ln + endif + + if prev_line < 0 || prev_line > line('$') || + \ getline(prev_line) =~# vimwiki#vars#get_syntaxlocal('rxHeader') + return 0 + endif + + return prev_line +endfunction + + +function! s:get_first_child(item) + if a:item.lnum >= line('$') + return s:empty_item() + endif + let org_lvl = s:get_level(a:item.lnum) + let cur_item = s:get_item(s:get_next_line(a:item.lnum)) + while 1 + if cur_item.type != 0 && s:get_level(cur_item.lnum) > org_lvl + return cur_item endif - if line =~ '^\s*$' - return 0 + if cur_item.lnum > line('$') || cur_item.lnum <= 0 || s:get_level(cur_item.lnum) <= org_lvl + return s:empty_item() endif - if indent(c_lnum) > indent(a:lnum) - return 0 + let cur_item = s:get_item(s:get_next_line(cur_item.lnum)) + endwhile +endfunction + + +"Returns: the next sibling of a:child, given the parent item +"Used for iterating over children +"Note: child items do not necessarily have the same indent, i.e. level +function! s:get_next_child_item(parent, child) + if a:parent.type == 0 | return s:empty_item() | endif + let parent_lvl = s:get_level(a:parent.lnum) + let cur_ln = s:get_last_line_of_item_incl_children(a:child) + while 1 + let next_line = s:get_next_line(cur_ln) + if next_line == 0 || s:get_level(next_line) <= parent_lvl + break + endif + let cur_ln = next_line + let cur_item = s:get_item(cur_ln) + if cur_item.type > 0 + return cur_item + endif + endwhile + return s:empty_item() +endfunction + + +function! s:get_parent(item) + let parent_line = 0 + + let cur_ln = prevnonblank(a:item.lnum) + let child_lvl = s:get_level(cur_ln) + if child_lvl == 0 + return s:empty_item() + endif + + while 1 + let cur_ln = s:get_prev_line(cur_ln) + if cur_ln == 0 | break | endif + let cur_lvl = s:get_level(cur_ln) + if cur_lvl < child_lvl + let cur_item = s:get_item(cur_ln) + if cur_item.type == 0 + let child_lvl = cur_lvl + continue + endif + let parent_line = cur_ln + break endif - let c_lnum -= 1 endwhile - return 0 -endfunction "}}} - -" Returns char column of checkbox. Used in parent/child checks. -function! s:get_li_pos(lnum) "{{{ - return stridx(getline(a:lnum), '[') -endfunction "}}} - -" Returns list of line numbers of parent and all its child items. -function! s:get_child_items(lnum) "{{{ - let result = [] - let lnum = a:lnum - let p_pos = s:get_level(lnum) - - " add parent - call add(result, lnum) - - let lnum = s:next_list_item(lnum) - while lnum != 0 && s:is_list_item(lnum) && s:get_level(lnum) > p_pos - call add(result, lnum) - let lnum = s:next_list_item(lnum) + return s:get_item(parent_line) +endfunction + + +"Returns: the item above or the item below or an empty item +function! s:get_a_neighbor_item(item) + let prev_item = s:get_prev_list_item(a:item, 1) + if prev_item.type != 0 + return prev_item + else + let next_item = s:get_next_list_item(a:item, 1) + if next_item.type != 0 + return next_item + endif + endif + return s:empty_item() +endfunction + + +function! s:get_a_neighbor_item_in_column(lnum, column) + let cur_ln = s:get_prev_line(a:lnum) + while cur_ln >= 1 + if s:get_level(cur_ln) <= a:column + return s:get_corresponding_item(cur_ln) + endif + let cur_ln = s:get_prev_line(cur_ln) endwhile - - return result -endfunction "}}} + return s:empty_item() +endfunction -" Returns list of line numbers of all items of the same level. -function! s:get_sibling_items(lnum) "{{{ - let result = [] - let lnum = a:lnum - let ind = s:get_level(lnum) - while lnum != 0 && s:get_level(lnum) >= ind - if s:get_level(lnum) == ind && s:is_cb_list_item(lnum) - call add(result, lnum) +"Returns: the item if there is one in a:lnum +"else the multiline item a:lnum belongs to +function! s:get_corresponding_item(lnum) + let item = s:get_item(a:lnum) + if item.type != 0 + return item + endif + let org_lvl = s:get_level(a:lnum) + let cur_ln = a:lnum + while cur_ln > 0 + let cur_lvl = s:get_level(cur_ln) + let cur_item = s:get_item(cur_ln) + if cur_lvl < org_lvl && cur_item.type != 0 + return cur_item endif - let lnum = s:next_list_item(lnum) + if cur_lvl < org_lvl + let org_lvl = cur_lvl + endif + let cur_ln = s:get_prev_line(cur_ln) endwhile + return s:empty_item() +endfunction + - let lnum = s:prev_list_item(a:lnum) - while lnum != 0 && s:get_level(lnum) >= ind - if s:get_level(lnum) == ind && s:is_cb_list_item(lnum) - call add(result, lnum) +"Returns: the last line of a (possibly multiline) item, including all children +function! s:get_last_line_of_item_incl_children(item) + let cur_ln = a:item.lnum + let org_lvl = s:get_level(a:item.lnum) + while 1 + let next_line = s:get_next_line(cur_ln) + if next_line == 0 || s:get_level(next_line) <= org_lvl + return cur_ln endif - let lnum = s:prev_list_item(lnum) + let cur_ln = next_line endwhile - - return result -endfunction "}}} - -" Returns line number of the parent of lnum item -function! s:get_parent_item(lnum) "{{{ - let lnum = a:lnum - let ind = s:get_level(lnum) - - let lnum = s:prev_list_item(lnum) - while lnum != 0 && s:is_list_item(lnum) && s:get_level(lnum) >= ind - let lnum = s:prev_list_item(lnum) +endfunction + + +"Returns: the last line of a (possibly multiline) item +"Note: there can be other list items between the first and last line +function! s:get_last_line_of_item(item) + if a:item.type == 0 | return 0 | endif + let org_lvl = s:get_level(a:item.lnum) + let last_corresponding_line = a:item.lnum + + let cur_ln = s:get_next_line(a:item.lnum) + while 1 + if cur_ln == 0 || s:get_level(cur_ln) <= org_lvl + break + endif + let cur_item = s:get_item(cur_ln) + if cur_item.type == 0 + let last_corresponding_line = cur_ln + let cur_ln = s:get_next_line(cur_ln) + else + let cur_ln = s:get_next_line(s:get_last_line_of_item_incl_children(cur_item)) + endif endwhile - if s:is_cb_list_item(lnum) - return lnum - else - return a:lnum + return last_corresponding_line +endfunction + + +" --------------------------------------------------------- +" renumber list items +" --------------------------------------------------------- + +"Renumbers the current list from a:item on downwards +"Returns: the last item that was adjusted +function! s:adjust_numbered_list_below(item, recursive) + if !(a:item.type == 2 || (a:item.type == 1 && a:recursive)) + return a:item endif -endfunction "}}} -" Creates checkbox in a list item. -function! s:create_cb_list_item(lnum) "{{{ - let line = getline(a: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 - call setline(a:lnum, line) + let kind = s:guess_kind_of_numbered_item(a:item) + + let cur_item = a:item + while 1 + if a:recursive + call s:adjust_items_recursively(cur_item) + endif + + let next_item = s:get_next_list_item(cur_item, 0) + if next_item.type == 0 + break + endif + + if cur_item.type == 2 + let new_val = s:increment_{kind}(cur_item.mrkr[:-2]) . cur_item.mrkr[-1:] + call s:substitute_string_in_line(next_item.lnum, next_item.mrkr, new_val) + let next_item.mrkr = new_val + endif + + let cur_item = next_item + endwhile + return cur_item +endfunction + + +function! s:adjust_items_recursively(parent) + if a:parent.type == 0 + return s:empty_item() + end + + let child_item = s:get_first_child(a:parent) + if child_item.type == 0 + return child_item endif -endfunction "}}} + while 1 + let last_item = s:adjust_numbered_list(child_item, 1, 1) + + let child_item = s:get_next_child_item(a:parent, last_item) + if child_item.type == 0 + return last_item + endif + endwhile +endfunction -" Tells if all of the sibling list items are checked or not. -function! s:all_siblings_checked(lnum) "{{{ - let result = 0 - let cnt = 0 - let siblings = s:get_sibling_items(a:lnum) - for lnum in siblings - let cnt += s:get_state(lnum) - endfor - let result = cnt/len(siblings) - return result -endfunction "}}} -" Creates checkbox on a list item if there is no one. -function! s:TLI_create_checkbox(lnum) "{{{ - if a:lnum && !s:is_cb_list_item(a:lnum) - if g:vimwiki_auto_checkbox - call s:create_cb_list_item(a:lnum) +"Renumbers the list a:item is in. +"If a:ignore_kind == 0, only the items which have the same kind of marker as +"a:item are considered, otherwise all items. +"Returns: the last item that was adjusted +function! s:adjust_numbered_list(item, ignore_kind, recursive) + if !(a:item.type == 2 || (a:item.type == 1 && (a:ignore_kind || a:recursive))) + return s:empty_item() + end + + let first_item = s:get_first_item_in_list(a:item, a:ignore_kind) + + while 1 + if first_item.type == 2 + let new_mrkr = s:guess_kind_of_numbered_item(first_item) . first_item.mrkr[-1:] + call s:substitute_string_in_line(first_item.lnum, first_item.mrkr, new_mrkr) + let first_item.mrkr = new_mrkr endif + + let last_item = s:adjust_numbered_list_below(first_item, a:recursive) + + let next_first_item = s:get_next_list_item(last_item, 1) + if a:ignore_kind == 0 || next_first_item.type == 0 + return last_item + endif + let first_item = next_first_item + endwhile +endfunction + + +"Renumbers the list the cursor is in +"also update its parents checkbox state +function! vimwiki#lst#adjust_numbered_list() + let cur_item = s:get_corresponding_item(line('.')) + if cur_item.type == 0 | return | endif + call s:adjust_numbered_list(cur_item, 1, 0) + call s:update_state(s:get_parent(cur_item)) +endfunction + + +"Renumbers all lists of the buffer +"of course, this might take some seconds +function! vimwiki#lst#adjust_whole_buffer() + let cur_ln = 1 + while 1 + let cur_item = s:get_item(cur_ln) + if cur_item.type != 0 + let cur_item = s:adjust_numbered_list(cur_item, 0, 1) + endif + let cur_ln = s:get_next_line(cur_item.lnum, 1) + if cur_ln <= 0 || cur_ln > line('$') + return + endif + endwhile +endfunction + + +" --------------------------------------------------------- +" checkbox stuff +" --------------------------------------------------------- + +"Returns: the rate of checkboxed list item in percent +function! s:get_rate(item) + if a:item.type == 0 || a:item.cb == '' + return -1 + endif + let state = a:item.cb + if state == vimwiki#vars#get_global('listsym_rejected') + return -1 + endif + let n = len(vimwiki#vars#get_syntaxlocal('listsyms_list')) + return index(vimwiki#vars#get_syntaxlocal('listsyms_list'), state) * 100/(n-1) +endfunction + + +"Set state of the list item to [ ] or [o] or whatever +"Returns: 1 if the state changed, 0 otherwise +function! s:set_state(item, new_rate) + let new_state = s:rate_to_state(a:new_rate) + let old_state = s:rate_to_state(s:get_rate(a:item)) + if new_state !=# old_state + call s:substitute_rx_in_line(a:item.lnum, '\[.]', '['.new_state.']') return 1 + else + return 0 endif - return 0 -endfunction "}}} +endfunction -" Switch state of the child list items. -function! s:TLI_switch_child_state(lnum) "{{{ - let current_state = s:get_state(a:lnum) - if current_state == 100 - let new_state = 0 + +" 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 new_state = 100 + let retain_closed_children = 1 endif - for lnum in s:get_child_items(a:lnum) - call s:set_state(lnum, new_state) - endfor -endfunction "}}} - -" Switch state of the parent list items. -function! s:TLI_switch_parent_state(lnum) "{{{ - let c_lnum = a:lnum - while s:is_cb_list_item(c_lnum) - let parent_lnum = s:get_parent_item(c_lnum) - if parent_lnum == c_lnum + + let child_item = s:get_first_child(a:item) + while 1 + if child_item.type == 0 break endif - call s:set_state(parent_lnum, s:all_siblings_checked(c_lnum)) + if child_item.cb != '' + 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 +endfunction + + +"Returns: the appropriate symbol for a given percent rate +function! s:rate_to_state(rate) + let listsyms_list = vimwiki#vars#get_syntaxlocal('listsyms_list') + let state = '' + let n = len(listsyms_list) + if a:rate == 100 + let state = listsyms_list[n-1] + elseif a:rate == 0 + let state = listsyms_list[0] + elseif a:rate == -1 + let state = vimwiki#vars#get_global('listsym_rejected') + else + let index = float2nr(ceil(a:rate/100.0*(n-2))) + let state = listsyms_list[index] + endif + return state +endfunction + + +"updates the symbol of a checkboxed item according to the symbols of its +"children +function! s:update_state(item) + if a:item.type == 0 || a:item.cb == '' + return + endif + + let sum_children_rate = 0 + let count_children_with_cb = 0 + let count_rejected_children = 0 - let c_lnum = parent_lnum + let child_item = s:get_first_child(a:item) + + while 1 + if child_item.type == 0 + break + endif + if child_item.cb != '' + let rate = s:get_rate(child_item) + 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 -endfunction "}}} -function! s:TLI_toggle(lnum) "{{{ - if !s:TLI_create_checkbox(a:lnum) - call s:TLI_switch_child_state(a:lnum) + if count_children_with_cb > 0 + 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) + if rate > 0 && rate < 100 + call s:set_state_recursively(a:item, 0) + endif endif - call s:TLI_switch_parent_state(a:lnum) -endfunction "}}} +endfunction -" Script functions }}} -" Toggle list item between [ ] and [X] -function! vimwiki#lst#ToggleListItem(line1, line2) "{{{ - let line1 = a:line1 - let line2 = a:line2 +function! s:set_state_recursively(item, new_rate) + let state_changed = s:set_state(a:item, a:new_rate) + if state_changed + call s:update_state(s:get_parent(a:item)) + endif +endfunction - if line1 != line2 && !s:is_list_item(line1) - let line1 = s:find_next_list_item(line1) + +"Creates checkbox in a list item. +"Returns: 1 if successful +function! s:create_cb(item, start_rate) + if a:item.type == 0 || a:item.cb != '' + return 0 endif - let c_lnum = line1 - while c_lnum != 0 && c_lnum <= line2 - let li_lnum = s:is_list_item(c_lnum) + let new_item = a:item + 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 . ']') + + call s:update_state(new_item) + return 1 +endfunction + - if li_lnum - let li_level = s:get_level(li_lnum) - if c_lnum == line1 - let start_li_level = li_level +function! s:remove_cb(item) + let item = a:item + if item.type != 0 && item.cb != '' + let item.cb = '' + call s:substitute_rx_in_line(item.lnum, '\s\+\[.\]', '') + endif + return item +endfunction + + +" 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 + return + endif + + let parent_items_of_lines = [] + + for cur_ln in range(from_item.lnum, a:to_line) + let cur_item = s:get_item(cur_ln) + if cur_item.type != 0 && cur_item.cb != '' + call s:set_state_plus_children(cur_item, a:new_rate) + let cur_parent_item = s:get_parent(cur_item) + if index(parent_items_of_lines, cur_parent_item) == -1 + call insert(parent_items_of_lines, cur_parent_item) endif + endif + endfor + + for parent_item in parent_items_of_lines + call s:update_state(parent_item) + endfor + +endfunction + + +" 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 + endif - if li_level <= start_li_level - call s:TLI_toggle(li_lnum) - let start_li_level = li_level + if from_item.cb == '' + + "if from_line has no CB, make a CB in every selected line + 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, a:start_rate) + + if success + let cur_parent_item = s:get_parent(cur_item) + if index(parent_items_of_lines, cur_parent_item) == -1 + call insert(parent_items_of_lines, cur_parent_item) + endif + endif + endfor + + for parent_item in parent_items_of_lines + call s:update_state(parent_item) + endfor + + else + + "if from_line has CB, toggle it and set all siblings to the same new state + let rate_first_line = s:get_rate(from_item) + let new_rate = rate_first_line == a:state1 ? a:state2 : a:state1 + + call s:change_cb(a:from_line, a:to_line, new_rate) + + endif + +endfunction + + +"Decrement checkbox between [ ] and [X] +"in the lines of the given range +function! vimwiki#lst#decrement_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, decrement 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 = max([rate_first_line - 100/(n-1)-1, 0]) + + call s:change_cb(a:from_line, a:to_line, new_rate) + +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, 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, -1) +endfunction + + +function! vimwiki#lst#remove_cb(first_line, last_line) + let first_item = s:get_corresponding_item(a:first_line) + let last_item = s:get_corresponding_item(a:last_line) + + if first_item.type == 0 || last_item.type == 0 + return + endif + + let parent_items_of_lines = [] + let cur_ln = first_item.lnum + while 1 + if cur_ln <= 0 || cur_ln > last_item.lnum | break | endif + let cur_item = s:get_item(cur_ln) + if cur_item.type != 0 + let cur_item = s:remove_cb(cur_item) + let cur_parent_item = s:get_parent(cur_item) + if index(parent_items_of_lines, cur_parent_item) == -1 + call insert(parent_items_of_lines, cur_parent_item) endif endif + let cur_ln = s:get_next_line(cur_ln) + endwhile + for parent_item in parent_items_of_lines + call s:update_state(parent_item) + endfor +endfunction + - let c_lnum = s:find_next_list_item(c_lnum) +function! vimwiki#lst#remove_cb_in_list() + let first_item = s:get_first_item_in_list(s:get_corresponding_item(line('.')), 0) + + let cur_item = first_item + while 1 + let next_item = s:get_next_list_item(cur_item, 0) + let cur_item = s:remove_cb(cur_item) + if next_item.type == 0 + break + else + let cur_item = next_item + endif endwhile -endfunction "}}} + call s:update_state(s:get_parent(first_item)) +endfunction + + -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 .= '[ ] ' +" --------------------------------------------------------- +" change the level of list items +" --------------------------------------------------------- + +function! s:set_indent(lnum, new_indent) + if &expandtab + let indentstring = repeat(' ', a:new_indent) + else + let indentstring = repeat('\t', a:new_indent / &tabstop) . repeat(' ', a:new_indent % &tabstop) endif - return cr -endfunction "}}} + call s:substitute_rx_in_line(a:lnum, '^\s*', indentstring) +endfunction -function! vimwiki#lst#kbd_oO(cmd) "{{{ - " cmd should be 'o' or 'O' - let l:count = v:count1 - while l:count > 0 +function! s:decrease_level(item) + let removed_indent = 0 + if vimwiki#vars#get_syntaxlocal('recurring_bullets') && a:item.type == 1 && + \ index(vimwiki#vars#get_syntaxlocal('multiple_bullet_chars'), + \ s:first_char(a:item.mrkr)) > -1 + if s:string_length(a:item.mrkr) >= 2 + call s:substitute_string_in_line(a:item.lnum, s:first_char(a:item.mrkr), '') + let removed_indent = -1 + endif + else + let old_indent = indent(a:item.lnum) + if &shiftround + let new_indent = (old_indent - 1) / vimwiki#u#sw() * vimwiki#u#sw() + else + let new_indent = old_indent - vimwiki#u#sw() + endif + call s:set_indent(a:item.lnum, new_indent) + let removed_indent = new_indent - old_indent + endif + return removed_indent +endfunction - let beg_lnum = foldclosed('.') - let end_lnum = foldclosedend('.') - if end_lnum != -1 && a:cmd ==# 'o' - let lnum = end_lnum - let line = getline(beg_lnum) + +function! s:increase_level(item) + let additional_indent = 0 + if vimwiki#vars#get_syntaxlocal('recurring_bullets') && a:item.type == 1 && + \ index(vimwiki#vars#get_syntaxlocal('multiple_bullet_chars'), + \ s:first_char(a:item.mrkr)) > -1 + call s:substitute_string_in_line(a:item.lnum, a:item.mrkr, a:item.mrkr . + \ s:first_char(a:item.mrkr)) + let additional_indent = 1 + else + let old_indent = indent(a:item.lnum) + if &shiftround + let new_indent = (old_indent / vimwiki#u#sw() + 1) * vimwiki#u#sw() else - let line = getline('.') - let lnum = line('.') + let new_indent = old_indent + vimwiki#u#sw() endif + call s:set_indent(a:item.lnum, new_indent) + let additional_indent = new_indent - old_indent + endif + return additional_indent +endfunction - " 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*$', ' ', '').'[ ] ' - elseif line =~ s:rx_list_item() - let res = substitute(m, '\s*$', ' ', '') - elseif &autoindent || &smartindent - let res = matchstr(line, '^\s*') + +"adds a:indent_by to the current indent +"a:indent_by can be negative +function! s:indent_line_by(lnum, indent_by) + let item = s:get_item(a:lnum) + if vimwiki#vars#get_syntaxlocal('recurring_bullets') && item.type == 1 && + \ index(vimwiki#vars#get_syntaxlocal('multiple_bullet_chars'), + \ s:first_char(item.mrkr)) > -1 + if a:indent_by > 0 + call s:substitute_string_in_line(a:lnum, item.mrkr, item.mrkr . s:first_char(item.mrkr)) + elseif a:indent_by < 0 + call s:substitute_string_in_line(a:lnum, s:first_char(item.mrkr), '') endif + else + call s:set_indent(a:lnum, indent(a:lnum) + a:indent_by) + endif +endfunction + - if a:cmd ==# 'o' - call append(lnum, res) - call cursor(lnum + 1, col('$')) +"changes lvl of lines in selection +function! s:change_level(from_line, to_line, direction, plus_children) + let from_item = s:get_corresponding_item(a:from_line) + if from_item.type == 0 + if a:direction ==# 'increase' && a:from_line == a:to_line && empty(getline(a:from_line)) + "that's because :> doesn't work on an empty line + normal! gi else - call append(lnum - 1, res) - call cursor(lnum, col('$')) + execute a:from_line.','.a:to_line.(a:direction ==# 'increase' ? '>' : '<') + endif + return + endif + + if a:direction ==# 'decrease' && s:get_level(from_item.lnum) == 0 + return + endif + + if a:from_line == a:to_line + if a:plus_children + let to_line = s:get_last_line_of_item_incl_children(from_item) + else + let to_line = s:get_last_line_of_item(from_item) + endif + else + let to_item = s:get_corresponding_item(a:to_line) + if to_item.type == 0 + let to_line = a:to_line + else + if a:plus_children + let to_line = s:get_last_line_of_item_incl_children(to_item) + else + let to_line = s:get_last_line_of_item(to_item) + endif + endif + endif + + if to_line == 0 + return + endif + + let to_be_adjusted = s:get_a_neighbor_item(from_item) + let old_parent = s:get_parent(from_item) + let first_line_level = s:get_level(from_item.lnum) + let more_than_one_level_concerned = 0 + + let first_line_indented_by = (a:direction ==# 'increase') ? + \ s:increase_level(from_item) : s:decrease_level(from_item) + + let cur_ln = s:get_next_line(from_item.lnum) + while cur_ln > 0 && cur_ln <= to_line + if !more_than_one_level_concerned && + \ s:get_level(cur_ln) != first_line_level && + \ s:get_item(cur_ln).type != 0 + let more_than_one_level_concerned = 1 + endif + call s:indent_line_by(cur_ln, first_line_indented_by) + let cur_ln = s:get_next_line(cur_ln, 1) + endwhile + + if a:from_line == a:to_line + call s:adjust_mrkr(from_item) + endif + call s:update_state(old_parent) + let from_item = s:get_item(from_item.lnum) + if from_item.cb != '' + call s:update_state(from_item) + call s:update_state(s:get_parent(from_item)) + endif + + if more_than_one_level_concerned + call vimwiki#lst#adjust_whole_buffer() + else + call s:adjust_numbered_list(from_item, 0, 0) + call s:adjust_numbered_list(to_be_adjusted, 0, 0) + endif +endfunction + + +function! vimwiki#lst#change_level(from_line, to_line, direction, plus_children) + let cur_col = col('$') - col('.') + call s:change_level(a:from_line, a:to_line, a:direction, a:plus_children) + call cursor('.', col('$') - cur_col) +endfunction + + +"indent line a:lnum to be the continuation of a:prev_item +function! s:indent_multiline(prev_item, lnum) + if a:prev_item.type != 0 + call s:set_indent(a:lnum, s:text_begin(a:prev_item.lnum)) + endif +endfunction + + +" --------------------------------------------------------- +" change markers of list items +" --------------------------------------------------------- + +"Returns: the position of a marker in g:vimwiki_list_markers +function! s:get_idx_list_markers(item) + if a:item.type == 1 + let m = s:first_char(a:item.mrkr) + else + let m = s:guess_kind_of_numbered_item(a:item) . a:item.mrkr[-1:] + endif + return index(vimwiki#vars#get_syntaxlocal('list_markers'), m) +endfunction + + +"changes the marker of the given item to the next in g:vimwiki_list_markers +function! s:get_next_mrkr(item) + let markers = vimwiki#vars#get_syntaxlocal('list_markers') + if a:item.type == 0 + let new_mrkr = markers[0] + else + let idx = s:get_idx_list_markers(a:item) + let new_mrkr = markers[(idx+1) % len(markers)] + endif + return new_mrkr +endfunction + + +"changes the marker of the given item to the previous in g:vimwiki_list_markers +function! s:get_prev_mrkr(item) + let markers = vimwiki#vars#get_syntaxlocal('list_markers') + if a:item.type == 0 + return markers[-1] + endif + let idx = s:get_idx_list_markers(a:item) + if idx == -1 + return markers[-1] + else + return markers[(idx - 1 + len(markers)) % len(markers)] + endif +endfunction + + +function! s:set_new_mrkr(item, new_mrkr) + if a:item.type == 0 + call s:substitute_rx_in_line(a:item.lnum, '^\s*\zs\ze', a:new_mrkr.' ') + if indent(a:item.lnum) == 0 && !vimwiki#vars#get_syntaxlocal('recurring_bullets') + call s:set_indent(a:item.lnum, vimwiki#lst#get_list_margin()) endif + else + call s:substitute_string_in_line(a:item.lnum, a:item.mrkr, a:new_mrkr) + endif +endfunction + + +function! vimwiki#lst#change_marker(from_line, to_line, new_mrkr, mode) + let cur_col_from_eol = col("$") - (a:mode ==# "i" ? col("'^") : col('.')) + let new_mrkr = a:new_mrkr + let cur_ln = a:from_line + while 1 + let cur_item = s:get_item(cur_ln) + + if new_mrkr ==# "next" + let new_mrkr = s:get_next_mrkr(cur_item) + elseif new_mrkr ==# "prev" + let new_mrkr = s:get_prev_mrkr(cur_item) + endif + + "handle markers like *** + if index(vimwiki#vars#get_syntaxlocal('multiple_bullet_chars'), s:first_char(new_mrkr)) > -1 + "use *** if the item above has *** too + let item_above = s:get_prev_list_item(cur_item, 1) + if item_above.type == 1 && s:first_char(item_above.mrkr) ==# s:first_char(new_mrkr) + let new_mrkr = item_above.mrkr + else + "use *** if the item below has *** too + let item_below = s:get_next_list_item(cur_item, 1) + if item_below.type == 1 && s:first_char(item_below.mrkr) ==# s:first_char(new_mrkr) + let new_mrkr = item_below.mrkr + else + "if the old is ### and the new is * use *** + if cur_item.type == 1 && + \ index(vimwiki#vars#get_syntaxlocal('multiple_bullet_chars'), + \ s:first_char(cur_item.mrkr))>-1 + let new_mrkr = repeat(new_mrkr, s:string_length(cur_item.mrkr)) + else + "use *** if the parent item has ** + let parent_item = s:get_parent(cur_item) + if parent_item.type == 1 && s:first_char(parent_item.mrkr) ==# s:first_char(new_mrkr) + let new_mrkr = repeat(s:first_char(parent_item.mrkr), + \ s:string_length(parent_item.mrkr)+1) + endif + endif + endif + endif + + endif + + call s:set_new_mrkr(cur_item, new_mrkr) + call s:adjust_numbered_list(s:get_item(cur_ln), 1, 0) + + if cur_ln >= a:to_line | break | endif + let cur_ln = s:get_next_line(cur_ln, 1) + endwhile + + call cursor('.', col('$') - cur_col_from_eol) +endfunction - let l:count -= 1 + +function! vimwiki#lst#change_marker_in_list(new_mrkr) + let cur_item = s:get_corresponding_item(line('.')) + let first_item = s:get_first_item_in_list(cur_item, 0) + let last_item = s:get_last_item_in_list(cur_item, 0) + if first_item.type == 0 || last_item.type == 0 | return | endif + let first_item_line = first_item.lnum + + let cur_item = first_item + while cur_item.type != 0 && cur_item.lnum <= last_item.lnum + call s:set_new_mrkr(cur_item, a:new_mrkr) + let cur_item = s:get_next_list_item(cur_item, 1) endwhile + call s:adjust_numbered_list(s:get_item(first_item_line), 0, 0) +endfunction + + +"sets kind of the item depending on neighbor items and the parent item +function! s:adjust_mrkr(item) + if a:item.type == 0 || vimwiki#vars#get_syntaxlocal('recurring_bullets') + return + endif + + let new_mrkr = a:item.mrkr + let neighbor_item = s:get_a_neighbor_item(a:item) + if neighbor_item.type != 0 + let new_mrkr = neighbor_item.mrkr + endif + + "if possible, set e.g. *** if parent has ** as marker + if neighbor_item.type == 0 && a:item.type == 1 && + \ index(vimwiki#vars#get_syntaxlocal('multiple_bullet_chars'), + \ s:first_char(a:item.mrkr)) > -1 + let parent_item = s:get_parent(a:item) + if parent_item.type == 1 && s:first_char(parent_item.mrkr) ==# s:first_char(a:item.mrkr) + let new_mrkr = repeat(s:first_char(parent_item.mrkr), s:string_length(parent_item.mrkr)+1) + endif + endif + + call s:substitute_string_in_line(a:item.lnum, a:item.mrkr, new_mrkr) + call s:adjust_numbered_list(a:item, 0, 1) +endfunction + + +function! s:clone_marker_from_to(from, to) + let item_from = s:get_item(a:from) + if item_from.type == 0 | return | endif + let new_mrkr = item_from.mrkr . ' ' + call s:substitute_rx_in_line(a:to, '^\s*', new_mrkr) + 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), 0) + call s:update_state(s:get_parent(s:get_item(a:to))) + endif + if item_from.type == 2 + let adjust_from = ( a:from < a:to ? a:from : a:to ) + call s:adjust_numbered_list_below(s:get_item(adjust_from), 0) + endif +endfunction + + +function! s:remove_mrkr(item) + let item = a:item + if item.cb != '' + let item = s:remove_cb(item) + let parent_item = s:get_parent(item) + else + let parent_item = s:empty_item() + endif + call s:substitute_rx_in_line(item.lnum, vimwiki#u#escape(item.mrkr).'\s*', '') + call remove(item, 'mrkr') + call remove(item, 'cb') + let item.type = 0 + call s:update_state(parent_item) + return item +endfunction + + +function! s:create_marker(lnum) + let new_sibling = s:get_corresponding_item(a:lnum) + if new_sibling.type == 0 + let new_sibling = s:get_a_neighbor_item_in_column(a:lnum, virtcol('.')) + endif + if new_sibling.type != 0 + call s:clone_marker_from_to(new_sibling.lnum, a:lnum) + else + let cur_item = s:get_item(a:lnum) + call s:set_new_mrkr(cur_item, vimwiki#vars#get_syntaxlocal('list_markers')[0]) + call s:adjust_numbered_list(cur_item, 0, 0) + endif +endfunction + + +" --------------------------------------------------------- +" handle keys +" --------------------------------------------------------- + +function! vimwiki#lst#kbd_o() + let fold_end = foldclosedend('.') + let lnum = (fold_end == -1) ? line('.') : fold_end + let cur_item = s:get_item(lnum) + "inserting and deleting the x is necessary + "because otherwise the indent is lost + normal! ox + if cur_item.lnum < s:get_last_line_of_item(cur_item) + call s:indent_multiline(cur_item, cur_item.lnum+1) + else + call s:clone_marker_from_to(cur_item.lnum, cur_item.lnum+1) + endif startinsert! +endfunction -endfunction "}}} + +function! vimwiki#lst#kbd_O() + normal! Ox + let cur_ln = line('.') + if getline(cur_ln+1) !~# '^\s*$' + call s:clone_marker_from_to(cur_ln+1, cur_ln) + else + call s:clone_marker_from_to(cur_ln-1, cur_ln) + endif + startinsert! +endfunction + + +function! s:cr_on_empty_list_item(lnum, behavior) + if a:behavior == 1 + "just make a new list item + normal! gi  + call s:clone_marker_from_to(a:lnum, a:lnum+1) + startinsert! + return + elseif a:behavior == 2 + "insert new marker but remove marker in old line + call append(a:lnum-1, '') + startinsert! + return + elseif a:behavior == 3 + "list is finished, but cursor stays in current line + let item = s:get_item(a:lnum) + let neighbor_item = s:get_a_neighbor_item(item) + let child_item = s:get_first_child(item) + let parent_item = (item.cb != '') ? s:get_parent(item) : s:empty_item() + normal! "_cc + call s:adjust_numbered_list(neighbor_item, 0, 0) + call s:adjust_numbered_list(child_item, 0, 0) + call s:update_state(parent_item) + startinsert + return + elseif a:behavior == 4 + "list is finished, but cursor goes to next line + let item = s:get_item(a:lnum) + let neighbor_item = s:get_a_neighbor_item(item) + let child_item = s:get_first_child(item) + let parent_item = (item.cb != '') ? s:get_parent(item) : s:empty_item() + normal! "_cc + call s:adjust_numbered_list(neighbor_item, 0, 0) + call s:adjust_numbered_list(child_item, 0, 0) + call s:update_state(parent_item) + startinsert + return + elseif a:behavior == 5 + "successively decrease level + if s:get_level(a:lnum) > 0 + call s:change_level(a:lnum, a:lnum, 'decrease', 0) + startinsert! + else + let item = s:get_item(a:lnum) + let neighbor_item = s:get_a_neighbor_item(item) + let child_item = s:get_first_child(item) + let parent_item = (item.cb != '') ? s:get_parent(item) : s:empty_item() + normal! "_cc + call s:adjust_numbered_list(neighbor_item, 0, 0) + call s:adjust_numbered_list(child_item, 0, 0) + call s:update_state(parent_item) + startinsert + endif + return + endif +endfunction + + +function! s:cr_on_empty_line(lnum, behavior) + "inserting and deleting the x is necessary + "because otherwise the indent is lost + normal! gi x + if a:behavior == 2 || a:behavior == 3 + call s:create_marker(a:lnum+1) + endif +endfunction + + +function! s:cr_on_list_item(lnum, insert_new_marker, not_at_eol) + if a:insert_new_marker + "the ultimate feature of this script: make new marker on + normal! gi  + call s:clone_marker_from_to(a:lnum, a:lnum+1) + "tiny sweet extra feature: indent next line if current line ends with : + if !a:not_at_eol && getline(a:lnum) =~# ':$' + call s:change_level(a:lnum+1, a:lnum+1, 'increase', 0) + endif + else + " || (cur_item.lnum < s:get_last_line_of_item(cur_item)) + "indent this line so that it becomes the continuation of the line above + normal! gi  + let prev_line = s:get_corresponding_item(s:get_prev_line(a:lnum+1)) + call s:indent_multiline(prev_line, a:lnum+1) + endif +endfunction + + +function! vimwiki#lst#kbd_cr(normal, just_mrkr) + let lnum = line('.') + let has_bp = s:line_has_marker(lnum) + + if has_bp != 0 && virtcol('.') < s:text_begin(lnum) + call append(lnum-1, '') + startinsert! + return + endif + + if has_bp == 1 + call s:cr_on_empty_list_item(lnum, a:just_mrkr) + return + endif + + let insert_new_marker = (a:normal == 1 || a:normal == 3) + if getline('.')[col("'^")-1:] =~# '^\s\+$' + let cur_col = 0 + else + let cur_col = col("$") - col("'^") + if getline('.')[col("'^")-1] =~# '\s' && exists("*strdisplaywidth") + let ws_behind_cursor = + \ strdisplaywidth(matchstr(getline('.')[col("'^")-1:], '\s\+'), + \ virtcol("'^")-1) + let cur_col -= ws_behind_cursor + endif + if insert_new_marker && cur_col == 0 && getline(lnum) =~# '\s$' + let insert_new_marker = 0 + endif + endif + + if has_bp == 0 + call s:cr_on_empty_line(lnum, a:normal) + endif + + if has_bp == 2 + call s:cr_on_list_item(lnum, insert_new_marker, cur_col) + endif + + call cursor(lnum+1, col("$") - cur_col) + if cur_col == 0 + startinsert! + else + startinsert + endif + +endfunction + + +"creates a list item in the current line or removes it +function! vimwiki#lst#toggle_list_item() + let cur_col_from_eol = col("$") - col("'^") + let cur_item = s:get_item(line('.')) + + if cur_item.type == 0 + call s:create_marker(cur_item.lnum) + else + let prev_item = s:get_prev_list_item(cur_item, 1) + if prev_item.type == 0 + let prev_item = s:get_corresponding_item(s:get_prev_line(cur_item.lnum)) + endif + let cur_item = s:remove_mrkr(cur_item) + let adjust_prev_item = (prev_item.type == 2 && + \ s:get_level(cur_item.lnum) <= s:get_level(prev_item.lnum)) ? 1 : 0 + call s:indent_multiline(prev_item, cur_item.lnum) + if adjust_prev_item + call s:adjust_numbered_list_below(prev_item, 0) + endif + endif + + "set cursor position s.t. it's on the same char as before + let new_cur_col = col("$") - cur_col_from_eol + call cursor(cur_item.lnum, new_cur_col >= 1 ? new_cur_col : 1) + + if cur_col_from_eol == 0 || getline(cur_item.lnum) =~# '^\s*$' + startinsert! + else + startinsert + endif +endfunction + + +" --------------------------------------------------------- +" misc stuff +" --------------------------------------------------------- + +function! vimwiki#lst#TO_list_item(inner, visual) + let lnum = prevnonblank('.') + let item = s:get_corresponding_item(lnum) + if item.type == 0 + return + endif + let from_line = item.lnum + if a:inner + let to_line = s:get_last_line_of_item(item) + else + let to_line = s:get_last_line_of_item_incl_children(item) + endif + normal! V + call cursor(to_line, 0) + normal! o + call cursor(from_line, 0) +endfunction + + +function! vimwiki#lst#fold_level(lnum) + let cur_item = s:get_item(a:lnum) + if cur_item.type != 0 + let parent_item = s:get_parent(cur_item) + let child_item = s:get_first_child(cur_item) + let next_item = s:get_next_child_item(parent_item, cur_item) + if child_item.type != 0 + return 'a1' + elseif next_item.type == 0 + return 's1' + endif + endif + return '=' +endfunction diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/markdown_base.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/markdown_base.vim new file mode 100644 index 0000000..f1ce091 --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/markdown_base.vim @@ -0,0 +1,150 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 +" Vimwiki autoload plugin file +" Description: Link functions for markdown syntax +" Home: https://github.com/vimwiki/vimwiki/ + + +function! s:safesubstitute(text, search, replace, mode) + " Substitute regexp but do not interpret replace + let escaped = escape(a:replace, '\&') + return substitute(a:text, a:search, escaped, a:mode) +endfunction + + +function! vimwiki#markdown_base#scan_reflinks() + let mkd_refs = {} + " construct list of references using vimgrep + try + " Why noautocmd? Because https://github.com/vimwiki/vimwiki/issues/121 + noautocmd execute 'vimgrep #'.vimwiki#vars#get_syntaxlocal('rxMkdRef').'#j %' + catch /^Vim\%((\a\+)\)\=:E480/ " No Match + "Ignore it, and move on to the next file + endtry + + for d in getqflist() + let matchline = join(getline(d.lnum, min([d.lnum+1, line('$')])), ' ') + let descr = matchstr(matchline, vimwiki#vars#get_syntaxlocal('rxMkdRefMatchDescr')) + let url = matchstr(matchline, vimwiki#vars#get_syntaxlocal('rxMkdRefMatchUrl')) + if descr != '' && url != '' + let mkd_refs[descr] = url + endif + endfor + call vimwiki#vars#set_bufferlocal('markdown_refs', mkd_refs) + return mkd_refs +endfunction + + +" try markdown reference links +function! vimwiki#markdown_base#open_reflink(link) + " echom "vimwiki#markdown_base#open_reflink" + let link = a:link + let mkd_refs = vimwiki#vars#get_bufferlocal('markdown_refs') + if has_key(mkd_refs, link) + let url = mkd_refs[link] + call vimwiki#base#system_open_link(url) + return 1 + else + return 0 + endif +endfunction + + +function! s:normalize_link_syntax_n() + let lnum = line('.') + + " try WikiIncl + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_global('rxWikiIncl')) + if !empty(lnk) + " NO-OP !! + return + endif + + " try WikiLink0: replace with WikiLink1 + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink0')) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl'), + \ vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchDescr'), + \ vimwiki#vars#get_syntaxlocal('WikiLink1Template2')) + call vimwiki#base#replacestr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink0'), sub) + return + endif + + " try WikiLink1: replace with WikiLink0 + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink1')) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl'), + \ vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchDescr'), + \ vimwiki#vars#get_global('WikiLinkTemplate2')) + call vimwiki#base#replacestr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink1'), sub) + return + endif + + " try Weblink + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWeblink')) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ vimwiki#vars#get_syntaxlocal('rxWeblinkMatchUrl'), + \ vimwiki#vars#get_syntaxlocal('rxWeblinkMatchDescr'), + \ vimwiki#vars#get_syntaxlocal('Weblink1Template')) + call vimwiki#base#replacestr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWeblink'), sub) + 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(vimwiki#vars#get_global('rxWord')) + if !empty(lnk) + let sub = vimwiki#base#normalize_link_helper(lnk, + \ vimwiki#vars#get_global('rxWord'), '', + \ vimwiki#vars#get_syntaxlocal('Weblink1Template')) + call vimwiki#base#replacestr_at_cursor('\V'.lnk, sub) + 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 link = s:safesubstitute(vimwiki#vars#get_syntaxlocal('Weblink1Template'), + \ '__LinkUrl__', visual_selection, '') + let link = s:safesubstitute(link, '__LinkDescription__', visual_selection, '') + + call setreg('"', substitute(link, '\n', '', ''), visualmode()) + + " paste result + norm! `>""pgvd + + finally + call setreg('"', rv, rt) + let &selection = sel_save + endtry + +endfunction + + +function! vimwiki#markdown_base#normalize_link(is_visual_mode) + if 0 + " Syntax-specific links + else + if !a:is_visual_mode + call s:normalize_link_syntax_n() + elseif line("'<") == line("'>") + " action undefined for multi-line visual mode selections + call s:normalize_link_syntax_v() + endif + endif +endfunction + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/path.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/path.vim new file mode 100644 index 0000000..367b1d7 --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/path.vim @@ -0,0 +1,183 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 +" Vimwiki autoload plugin file +" Description: Path manipulation functions +" Home: https://github.com/vimwiki/vimwiki/ + + +function! vimwiki#path#chomp_slash(str) + return substitute(a:str, '[/\\]\+$', '', '') +endfunction + + +" Define path-compare function, either case-sensitive or not, depending on OS. +if vimwiki#u#is_windows() + function! vimwiki#path#is_equal(p1, p2) + return a:p1 ==? a:p2 + endfunction +else + function! vimwiki#path#is_equal(p1, p2) + return a:p1 ==# a:p2 + endfunction +endif + + +" collapse sections like /a/b/../c to /a/c +function! vimwiki#path#normalize(path) + let path = a:path + while 1 + let result = substitute(path, '/[^/]\+/\.\.', '', '') + if result ==# path + break + endif + let path = result + endwhile + return result +endfunction + + +function! vimwiki#path#path_norm(path) + " /-slashes + if a:path !~# '^scp:' + 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) + else + return a:path + endif +endfunction + + +function! vimwiki#path#is_link_to_dir(link) + " Check if link is to a directory. + " It should be ended with \ or /. + return a:link =~# '\m[/\\]$' +endfunction + + +function! vimwiki#path#abs_path_of_link(link) + return vimwiki#path#normalize(expand("%:p:h").'/'.a:link) +endfunction + + +" return longest common path prefix of 2 given paths. +" '~/home/usrname/wiki', '~/home/usrname/wiki/shmiki' => '~/home/usrname/wiki' +function! vimwiki#path#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) && vimwiki#path#is_equal(p1[idx], p2[idx]) + let idx = idx + 1 + endwhile + if idx == 0 + return '' + else + return join(p1[: idx-1], '/') + endif +endfunction + + +function! vimwiki#path#wikify_path(path) + let result = resolve(fnamemodify(a:path, ':p')) + if vimwiki#u#is_windows() + let result = substitute(result, '\\', '/', 'g') + endif + let result = vimwiki#path#chomp_slash(result) + return result +endfunction + + +function! vimwiki#path#current_wiki_file() + return vimwiki#path#wikify_path(expand('%:p')) +endfunction + + +" Returns: the relative path from a:dir to a:file +function! vimwiki#path#relpath(dir, file) + let result = [] + let dir = split(a:dir, '/') + let file = split(a:file, '/') + while (len(dir) > 0 && len(file) > 0) && vimwiki#path#is_equal(dir[0], file[0]) + call remove(dir, 0) + call remove(file, 0) + endwhile + if empty(dir) && empty(file) + return './' + endif + for segment in dir + let result += ['..'] + endfor + for segment in file + let result += [segment] + endfor + let result_path = join(result, '/') + if a:file =~ '\m/$' + let result_path .= '/' + endif + return result_path +endfunction + + +" If the optional argument provided and nonzero, +" it will ask before creating a directory +" Returns: 1 iff directory exists or successfully created +function! vimwiki#path#mkdir(path, ...) + let path = expand(a:path) + + if path =~# '^scp:' + " we can not do much, so let's pretend everything is ok + return 1 + endif + + if isdirectory(path) + return 1 + else + if !exists("*mkdir") + return 0 + endif + + let path = vimwiki#path#chomp_slash(path) + if vimwiki#u#is_windows() && !empty(vimwiki#vars#get_global('w32_dir_enc')) + let path = iconv(path, &enc, vimwiki#vars#get_global('w32_dir_enc')) + endif + + if a:0 && a:1 && input("Vimwiki: Make new directory: ".path."\n [y]es/[N]o? ") !~? '^y' + return 0 + endif + + call mkdir(path, "p") + return 1 + endif +endfunction + + +function! vimwiki#path#is_absolute(path) + if vimwiki#u#is_windows() + return a:path =~? '\m^\a:' + else + return a:path =~# '\m^/\|\~/' + endif +endfunction + + +" Combine a directory and a file into one path, doesn't generate duplicate +" path separator in case the directory is also having an ending / or \. This +" is because on windows ~\vimwiki//.tags is invalid but ~\vimwiki/.tags is a +" valid path. +if vimwiki#u#is_windows() + function! vimwiki#path#join_path(directory, file) + let directory = vimwiki#path#chomp_slash(a:directory) + let file = substitute(a:file, '\m^[\\/]\+', '', '') + return directory . '/' . file + endfunction +else + function! vimwiki#path#join_path(directory, file) + let directory = substitute(a:directory, '\m/\+$', '', '') + let file = substitute(a:file, '\m^/\+', '', '') + return directory . '/' . file + endfunction +endif + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/style.css b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/style.css index f569a40..a5f11b9 100644 --- a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/style.css +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/style.css @@ -24,16 +24,60 @@ del {text-decoration: line-through; color: #777777;} .justright {text-align: right;} .justcenter {text-align: center;} .center {margin-left: auto; margin-right: auto;} +.tag {background-color: #eeeeee; font-family: monospace; padding: 2px;} +.header a {text-decoration: none; color: inherit;} + /* 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;} +.rejected { + /* list-style: none; */ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAAACXBIWXMAAADFAAAAxQEdzbqoAAAAB3RJTUUH4QgEFhAtuWgv9wAAAPZQTFRFmpqam5iYnJaWnJeXnpSUn5OTopCQpoqKpouLp4iIqIiIrYCAt3V1vW1tv2xsmZmZmpeXnpKS/x4e/x8f/yAg/yIi/yQk/yUl/yYm/ygo/ykp/yws/zAw/zIy/zMz/zQ0/zU1/zY2/zw8/0BA/0ZG/0pK/1FR/1JS/1NT/1RU/1VV/1ZW/1dX/1pa/15e/19f/2Zm/2lp/21t/25u/3R0/3p6/4CA/4GB/4SE/4iI/46O/4+P/52d/6am/6ur/66u/7Oz/7S0/7e3/87O/9fX/9zc/93d/+Dg/+vr/+3t/+/v//Dw//Ly//X1//f3//n5//z8////gzaKowAAAA90Uk5T/Pz8/Pz8/Pz8/Pz8/f39ppQKWQAAAAFiS0dEEnu8bAAAAACuSURBVAhbPY9ZF4FQFEZPSKbIMmWep4gMGTKLkIv6/3/GPbfF97b3w17rA0kQOPgvAeHW6uJ6+5h7HqLdwowgOzejXRXBdx6UdSru216xuOMBHHNU0clTzeSUA6EhF8V8kqroluMiU6HKcuf4phGPr1o2q9kYZWwNq1qfRRmTaXpqsyjj17KkWCxKBUBgXWueHIyiAIg18gsse4KHkLF5IKIY10WQgv7fOy4ST34BRiopZ8WLNrgAAAAASUVORK5CYII=); + background-repeat: no-repeat; + background-position: 0 .2em; + padding-left: 1.5em; +} +.done0 { + /* list-style: none; */ + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAA7SURBVCiR7dMxEgAgCANBI3yVRzF5KxNbW6wsuH7LQ2YKQK1mkswBVERYF5Os3UV3gwd/jF2SkXy66gAZkxS6BniubAAAAABJRU5ErkJggg==); + background-repeat: no-repeat; + background-position: 0 .2em; + padding-left: 1.5em; +} +.done1 { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABtSURBVCiR1ZO7DYAwDER9BDmTeZQMFXmUbGYpOjrEryA0wOvO8itOslFrJYAug5BMM4BeSkmjsrv3aVTa8p48Xw1JSkSsWVUFwD05IqS1tmYzk5zzae9jnVVVzGyXb8sALjse+euRkEzu/uirFomVIdDGOLjuAAAAAElFTkSuQmCC); + background-repeat: no-repeat; + background-position: 0 .15em; + 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; + padding-left: 1.5em; +} +.done3 { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABoSURBVCiR7dOxDcAgDATA/0DtUdiKoZC3YhLkHjkVKF3idJHiztKfvrHZWnOSE8Fx95RJzlprimJVnXktvXeY2S0SEZRSAAAbmxnGGKH2I5T+8VfxPhIReQSuuY3XyYWa3T2p6quvOgGrvSFGlewuUAAAAABJRU5ErkJggg==); + background-repeat: no-repeat; + background-position: 0 .15em; + 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; + 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/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/tags.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/tags.vim new file mode 100644 index 0000000..e802bce --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/tags.vim @@ -0,0 +1,342 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 +" Vimwiki autoload plugin file + + +let s:TAGS_METADATA_FILE_NAME = '.tags' + + + +" Tags metadata in-memory format: +" metadata := { 'pagename': [entries, ...] } +" entry := { 'tagname':..., 'lineno':..., 'link':... } + +" Tags metadata in-file format: +" +" Is based on CTags format (see |tags-file-format|). +" +" {tagaddress} is set to lineno. We'll let vim search by exact line number; we +" can afford that, we assume metadata file is always updated before use. +" +" Pagename and link are not saved in standard ctags fields, so we'll add +" an optional field, "vimwiki:". In this field, we encode tab-separated values +" of missing parameters -- "pagename" and "link". + + + +" Update tags metadata. +" a:full_rebuild == 1: re-scan entire wiki +" a:full_rebuild == 0: only re-scan current page +" a:all_files == '': only if the file is newer than .tags +function! vimwiki#tags#update_tags(full_rebuild, all_files) + let all_files = a:all_files != '' + if !a:full_rebuild + " Updating for one page (current) + let page_name = vimwiki#vars#get_bufferlocal('subdir') . expand('%:t:r') + " Collect tags in current file + let tags = s:scan_tags(getline(1, '$'), page_name) + " Load metadata file + let metadata = s:load_tags_metadata() + " Drop old tags + let metadata = s:remove_page_from_tags(metadata, page_name) + " Merge in the new ones + let metadata = s:merge_tags(metadata, page_name, tags) + " Save + call s:write_tags_metadata(metadata) + else " full rebuild + let files = vimwiki#base#find_files(vimwiki#vars#get_bufferlocal('wiki_nr'), 0) + let wiki_base_dir = vimwiki#vars#get_wikilocal('path') + let tags_file_last_modification = getftime(vimwiki#tags#metadata_file_path()) + let metadata = s:load_tags_metadata() + for file in files + if all_files || getftime(file) >= tags_file_last_modification + let subdir = vimwiki#base#subdir(wiki_base_dir, file) + let page_name = subdir . fnamemodify(file, ':t:r') + let tags = s:scan_tags(readfile(file), page_name) + let metadata = s:remove_page_from_tags(metadata, page_name) + let metadata = s:merge_tags(metadata, page_name, tags) + endif + endfor + call s:write_tags_metadata(metadata) + endif +endfunction + + +" Scans the list of text lines (argument) and produces tags metadata as a list of tag entries. +function! s:scan_tags(lines, page_name) + + let entries = [] + + " Code wireframe to scan for headers -- borrowed from + " vimwiki#base#get_anchors(), with minor modifications. + + let rxheader = vimwiki#vars#get_syntaxlocal('header_search') + let rxtag = vimwiki#vars#get_syntaxlocal('tag_search') + + let anchor_level = ['', '', '', '', '', '', ''] + let current_complete_anchor = '' + + let PROXIMITY_LINES_NR = 2 + let header_line_nr = - (2 * PROXIMITY_LINES_NR) + + for line_nr in range(1, len(a:lines)) + let line = a:lines[line_nr - 1] + + " process headers + let h_match = matchlist(line, rxheader) + if !empty(h_match) " got a header + let header_line_nr = line_nr + let header = vimwiki#u#trim(h_match[2]) + let level = len(h_match[1]) + let anchor_level[level-1] = header + for l in range(level, 6) + let anchor_level[l] = '' + endfor + if level == 1 + let current_complete_anchor = header + else + let current_complete_anchor = '' + for l in range(level-1) + if anchor_level[l] != '' + let current_complete_anchor .= anchor_level[l].'#' + endif + endfor + let current_complete_anchor .= header + endif + continue " tags are not allowed in headers + endif + + " TODO ignore verbatim blocks + + " Scan line for tags. There can be many of them. + let str = line + while 1 + let tag_group = matchstr(str, rxtag) + if tag_group == '' + break + endif + let tagend = matchend(str, rxtag) + let str = str[(tagend):] + for tag in split(tag_group, ':') + " Create metadata entry + let entry = {} + let entry.tagname = tag + let entry.lineno = line_nr + if line_nr <= PROXIMITY_LINES_NR && header_line_nr < 0 + " Tag appeared at the top of the file + let entry.link = a:page_name + elseif line_nr <= (header_line_nr + PROXIMITY_LINES_NR) + " Tag appeared right below a header + let entry.link = a:page_name . '#' . current_complete_anchor + else + " Tag stands on its own + let entry.link = a:page_name . '#' . tag + endif + call add(entries, entry) + endfor + endwhile + + endfor " loop over lines + return entries +endfunction + + +" Returns tags metadata file path +function! vimwiki#tags#metadata_file_path() abort + return fnamemodify(vimwiki#path#join_path(vimwiki#vars#get_wikilocal('path'), + \ s:TAGS_METADATA_FILE_NAME), ':p') +endfunction + + +" Loads tags metadata from file, returns a dictionary +function! s:load_tags_metadata() abort + let metadata_path = vimwiki#tags#metadata_file_path() + if !filereadable(metadata_path) + return {} + endif + let metadata = {} + for line in readfile(metadata_path) + if line =~ '^!_TAG_FILE_' + continue + endif + let parts = matchlist(line, '^\(.\{-}\);"\(.*\)$') + if parts[0] == '' || parts[1] == '' || parts[2] == '' + throw 'VimwikiTags1: Metadata file corrupted' + endif + let std_fields = split(parts[1], '\t') + if len(std_fields) != 3 + throw 'VimwikiTags2: Metadata file corrupted' + endif + let vw_part = parts[2] + if vw_part[0] != "\t" + throw 'VimwikiTags3: Metadata file corrupted' + endif + let vw_fields = split(vw_part[1:], "\t") + if len(vw_fields) != 1 || vw_fields[0] !~ '^vimwiki:' + throw 'VimwikiTags4: Metadata file corrupted' + endif + let vw_data = substitute(vw_fields[0], '^vimwiki:', '', '') + let vw_data = substitute(vw_data, '\\n', "\n", 'g') + let vw_data = substitute(vw_data, '\\r', "\r", 'g') + let vw_data = substitute(vw_data, '\\t', "\t", 'g') + let vw_data = substitute(vw_data, '\\\\', "\\", 'g') + let vw_fields = split(vw_data, "\t") + if len(vw_fields) != 2 + throw 'VimwikiTags5: Metadata file corrupted' + endif + let pagename = vw_fields[0] + let entry = {} + let entry.tagname = std_fields[0] + let entry.lineno = std_fields[2] + let entry.link = vw_fields[1] + if has_key(metadata, pagename) + call add(metadata[pagename], entry) + else + let metadata[pagename] = [entry] + endif + endfor + return metadata +endfunction + + +" Removes all entries for given page from metadata in-place. Returns updated +" metadata (just in case). +function! s:remove_page_from_tags(metadata, page_name) + if has_key(a:metadata, a:page_name) + call remove(a:metadata, a:page_name) + return a:metadata + else + return a:metadata + endif +endfunction + + +" Merges metadata of one file into a:metadata +function! s:merge_tags(metadata, pagename, file_metadata) + let metadata = a:metadata + let metadata[a:pagename] = a:file_metadata + return metadata +endfunction + + +" Compares two actual lines from tags file. Return value is in strcmp style. +" See help on sort() -- that's what this function is going to be used for. +" See also s:write_tags_metadata below -- that's where we compose these tags +" file lines. +" +" This function is needed for tags sorting, since plain sort() compares line +" numbers as strings, not integers, and so, for example, tag at line 14 +" preceeds the same tag on the same page at line 9. (Because string "14" is +" alphabetically 'less than' string "9".) +function! s:tags_entry_cmp(i1, i2) + let items = [] + for orig_item in [a:i1, a:i2] + let fields = split(orig_item, "\t") + let item = {} + let item.text = fields[0]."\t".fields[1] + let item.lineno = 0 + matchstr(fields[2], '\m\d\+') + call add(items, item) + endfor + if items[0].text ># items[1].text + return 1 + elseif items[0].text <# items[1].text + return -1 + elseif items[0].lineno > items[1].lineno + return 1 + elseif items[0].lineno < items[1].lineno + return -1 + else + return 0 + endif +endfunction + + +" Saves metadata object into a file. Throws exceptions in case of problems. +function! s:write_tags_metadata(metadata) + let metadata_path = vimwiki#tags#metadata_file_path() + let tags = [] + for pagename in keys(a:metadata) + for entry in a:metadata[pagename] + let entry_data = pagename . "\t" . entry.link + let entry_data = substitute(entry_data, "\\", '\\\\', 'g') + let entry_data = substitute(entry_data, "\t", '\\t', 'g') + let entry_data = substitute(entry_data, "\r", '\\r', 'g') + let entry_data = substitute(entry_data, "\n", '\\n', 'g') + call add(tags, + \ entry.tagname . "\t" + \ . pagename . vimwiki#vars#get_wikilocal('ext') . "\t" + \ . entry.lineno + \ . ';"' + \ . "\t" . "vimwiki:" . entry_data + \) + endfor + endfor + call sort(tags, "s:tags_entry_cmp") + call insert(tags, "!_TAG_FILE_SORTED\t1\t") + call writefile(tags, metadata_path) +endfunction + + +" Returns list of unique tags found in the .tags file +function! vimwiki#tags#get_tags() + let metadata = s:load_tags_metadata() + let tags = {} + for entries in values(metadata) + for entry in entries + let tags[entry.tagname] = 1 + endfor + endfor + return keys(tags) +endfunction + + +" Similar to vimwiki#base#generate_links. In the current buffer, appends +" tags and references to all their instances. If no arguments (tags) are +" specified, outputs all tags. +function! vimwiki#tags#generate_tags(...) abort + let need_all_tags = (a:0 == 0) + let specific_tags = a:000 + + let metadata = s:load_tags_metadata() + + " make a dictionary { tag_name: [tag_links, ...] } + let tags_entries = {} + for entries in values(metadata) + for entry in entries + if has_key(tags_entries, entry.tagname) + call add(tags_entries[entry.tagname], entry.link) + else + let tags_entries[entry.tagname] = [entry.link] + endif + endfor + endfor + + let lines = [] + let bullet = repeat(' ', vimwiki#lst#get_list_margin()).vimwiki#lst#default_symbol().' ' + for tagname in sort(keys(tags_entries)) + if need_all_tags || index(specific_tags, tagname) != -1 + call extend(lines, [ + \ '', + \ substitute(vimwiki#vars#get_syntaxlocal('rxH2_Template'), '__Header__', tagname, ''), + \ '' ]) + for taglink in sort(tags_entries[tagname]) + call add(lines, bullet . substitute(vimwiki#vars#get_global('WikiLinkTemplate1'), + \ '__LinkUrl__', taglink, '')) + endfor + endif + endfor + + let links_rx = '\m\%(^\s*$\)\|\%('.vimwiki#vars#get_syntaxlocal('rxH2').'\)\|\%(^\s*' + \ .vimwiki#u#escape(vimwiki#lst#default_symbol()).' ' + \ .vimwiki#vars#get_syntaxlocal('rxWikiLink').'$\)' + + call vimwiki#base#update_listing_in_buffer(lines, 'Generated Tags', links_rx, line('$')+1, 1) +endfunction + + +function! vimwiki#tags#complete_tags(ArgLead, CmdLine, CursorPos) abort + " We can safely ignore args if we use -custom=complete option, Vim engine + " will do the job of filtering. + let taglist = vimwiki#tags#get_tags() + return join(taglist, "\n") +endfunction + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/tbl.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/tbl.vim index 77d5397..1c049ce 100644 --- a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/tbl.vim +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/tbl.vim @@ -1,31 +1,36 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Desc: Tables +" Description: Tables " | Easily | manageable | text | tables | ! | -" |--------+------------+-------+--------+---------| +" |--------|------------|-------|--------|---------| " | Have | fun! | Drink | tea | Period. | " -" Author: Maxim Kim -" Home: http://code.google.com/p/vimwiki/ +" Home: https://github.com/vimwiki/vimwiki/ + + -" Load only once {{{ if exists("g:loaded_vimwiki_tbl_auto") || &cp finish endif let g:loaded_vimwiki_tbl_auto = 1 -"}}} + let s:textwidth = &tw -" Misc functions {{{ -function! s:wide_len(str) "{{{ + +function! s:rxSep() + return vimwiki#vars#get_syntaxlocal('rxTableSep') +endfunction + + +function! s:wide_len(str) " vim73 has new function that gives correct string width. if exists("*strdisplaywidth") return strdisplaywidth(a:str) endif " get str display width in vim ver < 7.2 - if !g:vimwiki_CJK_length + if !vimwiki#vars#get_global('CJK_length') let ret = strlen(substitute(a:str, '.', 'x', 'g')) else let savemodified = &modified @@ -38,26 +43,49 @@ function! s:wide_len(str) "{{{ let &modified = savemodified endif return ret -endfunction "}}} +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 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:rxSep().'\(--\+'.s:rxSep().'\)\+\s*$' +endfunction + -function! s:is_table(line) "{{{ - return a:line =~ '^\s*\%(|[^|]\+\)\+|\s*$' || s:is_separator(a:line) -endfunction "}}} +function! s:is_separator_tail(line) + return a:line =~# '^\{-1}\%(\s*\|-*\)\%('.s:rxSep().'-\+\)\+'.s:rxSep().'\s*$' +endfunction -function! s:is_separator(line) "{{{ - return a:line =~ '^\s*[|+]\s*--[-|+]\+' -endfunction "}}} -function! s:is_last_column(lnum, cnum) "{{{ - return strpart(getline(a:lnum), a:cnum - 1) =~ '^[^|]*|\s*$' -endfunction "}}} +function! s:is_last_column(lnum, cnum) + let line = strpart(getline(a:lnum), a:cnum - 1) + return line =~# s:rxSep().'\s*$' && line !~# s:rxSep().'.*'.s:rxSep().'\s*$' +endfunction -function! s:is_first_column(lnum, cnum) "{{{ + +function! s:is_first_column(lnum, cnum) let line = strpart(getline(a:lnum), 0, a:cnum - 1) - return line =~ '^\s*|[^|]*$' || line =~ '^\s*$' -endfunction "}}} + return line =~# '^\s*$' || + \ (line =~# '^\s*'.s:rxSep() && line !~# '^\s*'.s:rxSep().'.*'.s:rxSep()) +endfunction + -function! s:count_separators_up(lnum) "{{{ +function! s:count_separators_up(lnum) let lnum = a:lnum - 1 while lnum > 1 if !s:is_separator(getline(lnum)) @@ -67,9 +95,10 @@ function! s:count_separators_up(lnum) "{{{ endwhile return (a:lnum-lnum) -endfunction "}}} +endfunction -function! s:count_separators_down(lnum) "{{{ + +function! s:count_separators_down(lnum) let lnum = a:lnum + 1 while lnum < line('$') if !s:is_separator(getline(lnum)) @@ -79,54 +108,93 @@ function! s:count_separators_down(lnum) "{{{ endwhile return (lnum-a:lnum) -endfunction "}}} +endfunction + -function! s:create_empty_row(cols) "{{{ - let first_cell = "| |" - let cell = " |" - let row = first_cell +function! s:create_empty_row(cols) + 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 return row -endfunction "}}} +endfunction -function! s:create_row_sep(cols) "{{{ - let first_cell = "|---+" - let cell = "---+" - let last_cell = "---|" - if a:cols < 2 - return "|---|" - endif - - let row = first_cell +function! s:create_row_sep(cols) + let row = s:rxSep() + let cell = "---".s:rxSep() - 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] -endfunction "}}} +endfunction + + +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 -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)) + if cell.quote != '' + call add(result, vimwiki#u#trim(cell.quote, '|')) endif -endfunction "}}} + return result +endfunction -function! s:get_indent(lnum) "{{{ + +function! s:col_count(lnum) + return len(vimwiki#tbl#get_cells(getline(a:lnum))) +endfunction + + +function! s:get_indent(lnum) if !s:is_table(getline(a:lnum)) return endif @@ -144,9 +212,10 @@ function! s:get_indent(lnum) "{{{ endwhile return indent -endfunction " }}} +endfunction + -function! s:get_rows(lnum) "{{{ +function! s:get_rows(lnum) if !s:is_table(getline(a:lnum)) return endif @@ -155,7 +224,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]) @@ -178,15 +247,16 @@ function! s:get_rows(lnum) "{{{ endwhile return upper_rows + lower_rows -endfunction "}}} +endfunction + -function! s:get_cell_max_lens(lnum) "{{{ +function! s:get_cell_max_lens(lnum, ...) let max_lens = {} for [lnum, row] in s:get_rows(a:lnum) if s:is_separator(row) continue endif - let cells = s:get_values(row) + let cells = a:0 > 1 ? a:1[lnum - a:2] : vimwiki#tbl#get_cells(row) for idx in range(len(cells)) let value = cells[idx] if has_key(max_lens, idx) @@ -197,50 +267,52 @@ function! s:get_cell_max_lens(lnum) "{{{ endfor endfor return max_lens -endfunction "}}} +endfunction -function! s:get_aligned_rows(lnum, col1, col2) "{{{ - let max_lens = s:get_cell_max_lens(a:lnum) - let rows = [] - for [lnum, row] in s:get_rows(a:lnum) + +function! s:get_aligned_rows(lnum, col1, col2) + let rows = s:get_rows(a:lnum) + let startlnum = rows[0][0] + let cells = [] + for [lnum, row] in rows + call add(cells, vimwiki#tbl#get_cells(row)) + endfor + let max_lens = s:get_cell_max_lens(a:lnum, cells, startlnum) + let result = [] + for [lnum, row] in rows if s:is_separator(row) let new_row = s:fmt_sep(max_lens, a:col1, a:col2) else - let new_row = s:fmt_row(row, max_lens, a:col1, a:col2) + let new_row = s:fmt_row(cells[lnum - startlnum], max_lens, a:col1, a:col2) endif - call add(rows, [lnum, new_row]) + call add(result, [lnum, new_row]) endfor - return rows -endfunction "}}} + return result +endfunction + " Number of the current column. Starts from 0. -function! s:cur_column() "{{{ +function! s:cur_column() let line = getline('.') 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 endwhile return col -endfunction "}}} +endfunction -" }}} -" Format functions {{{ -function! s:fmt_cell(cell, max_len) "{{{ +function! s:fmt_cell(cell, max_len) let cell = ' '.a:cell.' ' let diff = a:max_len - s:wide_len(a:cell) @@ -250,139 +322,205 @@ function! s:fmt_cell(cell, max_len) "{{{ let cell .= repeat(' ', diff) return cell -endfunction "}}} +endfunction + -function! s:fmt_row(line, max_lens, col1, col2) "{{{ - let new_line = '|' - let cells = s:get_values(a:line) - for idx in range(len(cells)) +function! s:fmt_row(cells, max_lens, col1, col2) + let new_line = s:rxSep() + for idx in range(len(a:cells)) if idx == a:col1 let idx = a:col2 elseif idx == a:col2 let idx = a:col1 endif - let value = cells[idx] - let new_line .= s:fmt_cell(value, a:max_lens[idx]).'|' + let value = a:cells[idx] + let new_line .= s:fmt_cell(value, a:max_lens[idx]).s:rxSep() endfor - let idx = len(cells) + let idx = len(a: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 -endfunction "}}} +endfunction -function! s:fmt_cell_sep(max_len) "{{{ + +function! s:fmt_cell_sep(max_len) if a:max_len == 0 return repeat('-', 3) else return repeat('-', a:max_len+2) endif -endfunction "}}} +endfunction + -function! s:fmt_sep(max_lens, col1, col2) "{{{ - let sep = '|' +function! s:fmt_sep(max_lens, col1, col2) + 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 -endfunction "}}} -"}}} + return new_line +endfunction + -" Keyboard functions "{{{ -function! s:kbd_create_new_row(cols, goto_first) "{{{ +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 "}}} +endfunction -function! s:kbd_goto_next_row() "{{{ - let cmd = "\jt|T|a" + +function! s:kbd_goto_next_row() + 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 "}}} +endfunction + -function! s:kbd_goto_prev_row() "{{{ - let cmd = "\jt|T|a" +function! s:kbd_goto_prev_row() + 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 "}}} +endfunction + + +" 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 "}}} +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 + 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 "}}} +endfunction -"}}} -" Global functions {{{ -function! vimwiki#tbl#kbd_cr() "{{{ +function! vimwiki#tbl#kbd_cr() let lnum = line('.') if !s:is_table(getline(lnum)) - return "\" + return "" 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() endif -endfunction "}}} +endfunction + -function! vimwiki#tbl#kbd_tab() "{{{ +function! vimwiki#tbl#kbd_tab() let lnum = line('.') if !s:is_table(getline(lnum)) return "\" 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) -endfunction "}}} + return s:kbd_goto_next_col(is_sep || last) +endfunction + -function! vimwiki#tbl#kbd_shift_tab() "{{{ +function! vimwiki#tbl#kbd_shift_tab() let lnum = line('.') if !s:is_table(getline(lnum)) return "\" 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) -endfunction "}}} + return s:kbd_goto_prev_col(is_sep || first) +endfunction -function! vimwiki#tbl#format(lnum, ...) "{{{ + +function! vimwiki#tbl#format(lnum, ...) + if !(&filetype ==? 'vimwiki') + return + endif let line = getline(a:lnum) if !s:is_table(line) return @@ -397,16 +535,22 @@ function! vimwiki#tbl#format(lnum, ...) "{{{ endif let indent = s:get_indent(a:lnum) + if &expandtab + let indentstring = repeat(' ', indent) + else + let indentstring = repeat(' ', indent / &tabstop) . repeat(' ', indent % &tabstop) + endif for [lnum, row] in s:get_aligned_rows(a:lnum, col1, col2) - let row = repeat(' ', indent).row + let row = indentstring.row call setline(lnum, row) endfor - + let &tw = s:textwidth -endfunction "}}} +endfunction -function! vimwiki#tbl#create(...) "{{{ + +function! vimwiki#tbl#create(...) if a:0 > 1 let cols = a:1 let rows = a:2 @@ -437,32 +581,42 @@ function! vimwiki#tbl#create(...) "{{{ for r in range(rows - 1) call add(lines, row) endfor - + call append(line('.'), lines) -endfunction "}}} +endfunction -function! vimwiki#tbl#align_or_cmd(cmd) "{{{ + +function! vimwiki#tbl#align_or_cmd(cmd) if s:is_table(getline('.')) call vimwiki#tbl#format(line('.')) else exe 'normal! '.a:cmd endif -endfunction "}}} +endfunction + -function! vimwiki#tbl#reset_tw(lnum) "{{{ +function! vimwiki#tbl#reset_tw(lnum) + if !(&filetype ==? 'vimwiki') + return + endif let line = getline(a:lnum) if !s:is_table(line) return endif - + let s:textwidth = &tw let &tw = 0 -endfunction "}}} +endfunction + + +" TODO: move_column_left and move_column_right are good candidates to be refactored. +function! vimwiki#tbl#move_column_left() -" 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 @@ -472,18 +626,30 @@ function! vimwiki#tbl#move_column_left() "{{{ endif if cur_col > 0 - call vimwiki#tbl#format(line('.'), cur_col-1, cur_col) + 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 "}}} +endfunction + + +function! vimwiki#tbl#move_column_right() -function! vimwiki#tbl#move_column_right() "{{{ - if !s:is_table(getline('.')) + let line = getline('.') + + if !s:is_table(line) return endif @@ -493,18 +659,45 @@ function! vimwiki#tbl#move_column_right() "{{{ endif if cur_col < s:col_count(line('.'))-1 - call vimwiki#tbl#format(line('.'), cur_col, cur_col+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 "}}} +endfunction + -function! vimwiki#tbl#get_rows(lnum) "{{{ +function! vimwiki#tbl#get_rows(lnum) return s:get_rows(a:lnum) -endfunction "}}} +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/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/u.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/u.vim new file mode 100644 index 0000000..c8f62ee --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/u.vim @@ -0,0 +1,72 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 +" Vimwiki autoload plugin file +" Description: Utility functions +" Home: https://github.com/vimwiki/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#is_macos() + if has("mac") || has("macunix") || has("gui_mac") + return 1 + endif + " that still doesn't mean we are not on Mac OS + let os = substitute(system('uname'), '\n', '', '') + return os == 'Darwin' || os == 'Mac' +endfunction + + +function! vimwiki#u#count_first_sym(line) + let first_sym = matchstr(a:line, '\S') + return len(matchstr(a:line, first_sym.'\+')) +endfunction + + +function! vimwiki#u#escape(string) + return escape(a:string, '~.*[]\^$') +endfunction + + +" Load concrete Wiki syntax: sets regexes and templates for headers and links +function vimwiki#u#reload_regexes() + execute 'runtime! syntax/vimwiki_'.vimwiki#vars#get_wikilocal('syntax').'.vim' +endfunction + + +" Load syntax-specific functionality +function vimwiki#u#reload_regexes_custom() + execute 'runtime! syntax/vimwiki_'.vimwiki#vars#get_wikilocal('syntax').'_custom.vim' +endfunction + + +" Backward compatible version of the built-in function shiftwidth() +if exists('*shiftwidth') + func vimwiki#u#sw() + return shiftwidth() + endfunc +else + func vimwiki#u#sw() + return &sw + endfunc +endif + diff --git a/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/vars.vim b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/vars.vim new file mode 100644 index 0000000..d60a561 --- /dev/null +++ b/etc/soft/nvim/+plugins/vimwiki/autoload/vimwiki/vars.vim @@ -0,0 +1,850 @@ +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 +" Vimwiki autoload plugin file +" Home: https://github.com/vimwiki/vimwiki/ + + + +" ------------------------------------------------------------------------------------------------ +" This file provides functions to manage the various state variables which are needed during a +" Vimwiki session. +" They consist of: +" +" - global variables. These are stored in the dict g:vimwiki_global_vars. They consist mainly of +" 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 +" (used for temporary wikis). +" +" - syntax variables. Stored in the dict g:vimwiki_syntax_variables which holds all the regexes and +" other stuff which is needed for highlighting. +" +" - buffer-local variables. They are stored as buffer variables directly (b:foo) + +" As a developer, you should, if possible, only use the get_ and set_ functions for these types of +" variables, not the underlying dicts! +" ------------------------------------------------------------------------------------------------ + + +function! s:populate_global_variables() + + let g:vimwiki_global_vars = {} + + call s:read_global_settings_from_user() + call s:normalize_global_settings() + + " non-configurable global variables: + + " Scheme regexes must be defined even if syntax file is not loaded yet cause users should be + " able to ww without opening any vimwiki file first + let g:vimwiki_global_vars.schemes = join(['wiki\d\+', 'diary', 'local'], '\|') + let g:vimwiki_global_vars.web_schemes1 = join(['http', 'https', 'file', 'ftp', 'gopher', + \ 'telnet', 'nntp', 'ldap', 'rsync', 'imap', 'pop', 'irc', 'ircs', 'cvs', 'svn', 'svn+ssh', + \ 'git', 'ssh', 'fish', 'sftp'], '\|') + let web_schemes2 = + \ join(['mailto', 'news', 'xmpp', 'sip', 'sips', 'doi', 'urn', 'tel', 'data'], '\|') + + let g:vimwiki_global_vars.rxSchemes = '\%('. + \ g:vimwiki_global_vars.schemes . '\|'. + \ g:vimwiki_global_vars.web_schemes1 . '\|'. + \ web_schemes2 . + \ '\)' + + " match URL for common protocols; see http://en.wikipedia.org/wiki/URI_scheme + " http://tools.ietf.org/html/rfc3986 + let rxWebProtocols = + \ '\%('. + \ '\%('. + \ '\%('.g:vimwiki_global_vars.web_schemes1 . '\):'. + \ '\%(//\)'. + \ '\)'. + \ '\|'. + \ '\%('.web_schemes2.'\):'. + \ '\)' + + let g:vimwiki_global_vars.rxWeblinkUrl = rxWebProtocols . '\S\{-1,}'. '\%(([^ \t()]*)\)\=' + + let wikilink_prefix = '[[' + let wikilink_suffix = ']]' + let wikilink_separator = '|' + let g:vimwiki_global_vars.rx_wikilink_prefix = vimwiki#u#escape(wikilink_prefix) + let g:vimwiki_global_vars.rx_wikilink_suffix = vimwiki#u#escape(wikilink_suffix) + let g:vimwiki_global_vars.rx_wikilink_separator = vimwiki#u#escape(wikilink_separator) + + " templates for the creation of wiki links + " [[URL]] + let g:vimwiki_global_vars.WikiLinkTemplate1 = wikilink_prefix . '__LinkUrl__'. wikilink_suffix + " [[URL|DESCRIPTION]] + let g:vimwiki_global_vars.WikiLinkTemplate2 = wikilink_prefix . '__LinkUrl__'. wikilink_separator + \ . '__LinkDescription__' . wikilink_suffix + + let valid_chars = '[^\\\]]' + let g:vimwiki_global_vars.rxWikiLinkUrl = valid_chars.'\{-}' + let g:vimwiki_global_vars.rxWikiLinkDescr = valid_chars.'\{-}' + + " this regexp defines what can form a link when the user presses in the + " buffer (and not on a link) to create a link + " basically, it's Ascii alphanumeric characters plus #|./@-_~ plus all + " non-Ascii characters, except that . is not accepted as the last character + let g:vimwiki_global_vars.rxWord = '[^[:blank:]!"$%&''()*+,:;<=>?\[\]\\^`{}]*[^[:blank:]!"$%&''()*+.,:;<=>?\[\]\\^`{}]' + + let g:vimwiki_global_vars.rx_wikilink_prefix1 = g:vimwiki_global_vars.rx_wikilink_prefix . + \ g:vimwiki_global_vars.rxWikiLinkUrl . g:vimwiki_global_vars.rx_wikilink_separator + let g:vimwiki_global_vars.rx_wikilink_suffix1 = g:vimwiki_global_vars.rx_wikilink_suffix + + let g:vimwiki_global_vars.rxWikiInclPrefix = '{{' + let g:vimwiki_global_vars.rxWikiInclSuffix = '}}' + let g:vimwiki_global_vars.rxWikiInclSeparator = '|' + " '{{__LinkUrl__}}' + let g:vimwiki_global_vars.WikiInclTemplate1 = g:vimwiki_global_vars.rxWikiInclPrefix + \ .'__LinkUrl__'. g:vimwiki_global_vars.rxWikiInclSuffix + " '{{__LinkUrl____LinkDescription__}}' + let g:vimwiki_global_vars.WikiInclTemplate2 = g:vimwiki_global_vars.rxWikiInclPrefix + \ . '__LinkUrl__' . g:vimwiki_global_vars.rxWikiInclSeparator . '__LinkDescription__' + \ . g:vimwiki_global_vars.rxWikiInclSuffix + + let valid_chars = '[^\\\}]' + let g:vimwiki_global_vars.rxWikiInclUrl = valid_chars.'\{-}' + let g:vimwiki_global_vars.rxWikiInclArg = valid_chars.'\{-}' + let g:vimwiki_global_vars.rxWikiInclArgs = '\%('. g:vimwiki_global_vars.rxWikiInclSeparator. + \ g:vimwiki_global_vars.rxWikiInclArg. '\)'.'\{-}' + + " *. {{URL}[{...}]} - i.e. {{URL}}, {{URL|ARG1}}, {{URL|ARG1|ARG2}}, etc. + " *a) match {{URL}[{...}]} + let g:vimwiki_global_vars.rxWikiIncl = g:vimwiki_global_vars.rxWikiInclPrefix. + \ g:vimwiki_global_vars.rxWikiInclUrl. + \ g:vimwiki_global_vars.rxWikiInclArgs. g:vimwiki_global_vars.rxWikiInclSuffix + " *b) match URL within {{URL}[{...}]} + let g:vimwiki_global_vars.rxWikiInclMatchUrl = g:vimwiki_global_vars.rxWikiInclPrefix. + \ '\zs'. g:vimwiki_global_vars.rxWikiInclUrl . '\ze'. + \ g:vimwiki_global_vars.rxWikiInclArgs . g:vimwiki_global_vars.rxWikiInclSuffix + + let g:vimwiki_global_vars.rxWikiInclPrefix1 = g:vimwiki_global_vars.rxWikiInclPrefix. + \ g:vimwiki_global_vars.rxWikiInclUrl . g:vimwiki_global_vars.rxWikiInclSeparator + let g:vimwiki_global_vars.rxWikiInclSuffix1 = g:vimwiki_global_vars.rxWikiInclArgs. + \ g:vimwiki_global_vars.rxWikiInclSuffix + + let g:vimwiki_global_vars.rxTodo = '\C\<\%(TODO\|DONE\|STARTED\|FIXME\|FIXED\|XXX\)\>' + + " default colors when headers of different levels are highlighted differently + " not making it yet another option; needed by ColorScheme autocommand + let g:vimwiki_global_vars.hcolor_guifg_light = ['#aa5858', '#507030', '#1030a0', '#103040' + \ , '#505050', '#636363'] + let g:vimwiki_global_vars.hcolor_ctermfg_light = ['DarkRed', 'DarkGreen', 'DarkBlue', 'Black' + \ , 'Black', 'Black'] + let g:vimwiki_global_vars.hcolor_guifg_dark = ['#e08090', '#80e090', '#6090e0', '#c0c0f0' + \ , '#e0e0f0', '#f0f0f0'] + let g:vimwiki_global_vars.hcolor_ctermfg_dark = ['Red', 'Green', 'Blue', 'White', 'White' + \ , 'White'] +endfunction + + +function! s:read_global_settings_from_user() + let global_settings = { + \ 'CJK_length': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, + \ 'auto_chdir': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, + \ 'autowriteall': {'type': type(0), 'default': 1, 'min': 0, 'max': 1}, + \ 'conceallevel': {'type': type(0), 'default': 2, 'min': 0, 'max': 3}, + \ 'diary_months': {'type': type({}), 'default': + \ { + \ 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': {'type': type(''), 'default': ''}, + \ 'ext2syntax': {'type': type({}), 'default': {}}, + \ 'folding': {'type': type(''), 'default': '', 'possible_values': ['', 'expr', 'syntax', + \ 'list', 'custom', ':quick', 'expr:quick', 'syntax:quick', 'list:quick', + \ 'custom:quick']}, + \ 'global_ext': {'type': type(0), 'default': 1, 'min': 0, 'max': 1}, + \ 'hl_cb_checked': {'type': type(0), 'default': 0, 'min': 0, 'max': 2}, + \ 'hl_headers': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, + \ 'html_header_numbering': {'type': type(0), 'default': 0, 'min': 0, 'max': 6}, + \ 'html_header_numbering_sym': {'type': type(''), 'default': ''}, + \ 'list_ignore_newline': {'type': type(0), 'default': 1, 'min': 0, 'max': 1}, + \ 'text_ignore_newline': {'type': type(0), 'default': 1, 'min': 0, 'max': 1}, + \ 'listsyms': {'type': type(''), 'default': ' .oOX', 'min_length': 2}, + \ 'listsym_rejected': {'type': type(''), 'default': '-', 'length': 1}, + \ 'map_prefix': {'type': type(''), 'default': 'w'}, + \ 'menu': {'type': type(''), 'default': 'Vimwiki'}, + \ 'table_auto_fmt': {'type': type(0), 'default': 1, 'min': 0, 'max': 1}, + \ 'table_mappings': {'type': type(0), 'default': 1, 'min': 0, 'max': 1}, + \ 'toc_header': {'type': type(''), 'default': 'Contents', 'min_length': 1}, + \ 'url_maxsave': {'type': type(0), 'default': 15, 'min': 0}, + \ 'use_calendar': {'type': type(0), 'default': 1, 'min': 0, 'max': 1}, + \ 'use_mouse': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, + \ 'user_htmls': {'type': type(''), 'default': ''}, + \ 'valid_html_tags': {'type': type(''), 'default': + \ 'b,i,s,u,sub,sup,kbd,br,hr,div,center,strong,em'}, + \ 'w32_dir_enc': {'type': type(''), 'default': ''}, + \ } + + " copy the user's settings from variables of the form g:vimwiki_
    dance +Anchors~ + +A wikilink, interwiki link or diary link can be followed by a '#' and the name +of an anchor. When opening a link, the cursor jumps to the anchor. > + [[Todo List#Tomorrow|Tasks for tomorrow]] + +To jump inside the current wiki file you can omit the file: > + [[#Tomorrow]] + +See |vimwiki-anchors| for how to set an anchor. + +Raw URLs~ + +Raw URLs are also supported: > + https://github.com/vimwiki/vimwiki.git + mailto:habamax@gmail.com + ftp://vim.org + +External files~ + +The "file:" and "local:" schemes allow you to directly link to arbitrary +resources using absolute or relative paths: > + [[file:/home/somebody/a/b/c/music.mp3]] + [[file:C:/Users/somebody/d/e/f/music.mp3]] + [[file:~/a/b/c/music.mp3]] + [[file:../assets/data.csv|Important Data]] + [[local:C:/Users/somebody/d/e/f/music.mp3]] + [[file:/home/user/documents/|Link to a directory]] + +These links are opened with the system command, i.e. !xdg-open (Linux), !open +(Mac), or !start (Windows). To customize this behavior, see +|VimwikiLinkHandler|. + +In Vim, "file:" and "local:" behave the same, i.e. you can use them with both +relative and absolute links. When converted to HTML, however, "file:" links +will become absolute links, while "local:" links become relative to the HTML +output directory. The latter can be useful if you copy your HTML files to +another computer. +To customize the HTML conversion of links, see |VimwikiLinkConverter|. + +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: > + {{file:../../images/vimwiki_logo.png}} +or from a universal URL: > + {{http://vimwiki.googlecode.com/hg/images/vimwiki_logo.png}} -Double bracketed link to an image with alternate text: > - [[http://habamax.ru/blog/wp-content/uploads/2009/01/2740254sm.jpg|dance|]] +Transclude image with alternate text: > + {{http://vimwiki.googlecode.com/hg/images/vimwiki_logo.png|Vimwiki}} in HTML: > - dance + Vimwiki -Double bracketed link to an image with alternate text and some style: > - [[http://helloworld.com/blabla.jpg|cool stuff|width:150px; height: 120px;]] +Transclude image with alternate text and some style: > + {{http://.../vimwiki_logo.png|cool stuff|style="width:150px;height:120px;"}} in HTML: > - cool stuff + cool stuff -Double bracketed link to an image without alternate text and some style: > - [[http://helloworld.com/blabla.jpg||width:150px; height: 120px;]] +Transclude image _without_ alternate text and with a 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|. + +Thumbnail links~ +> +Thumbnail links are constructed like this: > + [[http://someaddr.com/bigpicture.jpg|{{http://someaddr.com/thumbnail.jpg}}]] -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: > - + + [Id]: URL + +then the URL is opened with the system default handler. Otherwise, Vimwiki +treats the reference-style link as a Wikilink, interpreting the Id field as a +wiki page name. + +Highlighting of existing links when |vimwiki-option-maxhi| is activated +identifies links whose Id field is not defined, either as a reference-link or +as a wiki page. + +To scan the page for new or changed definitions for reference-links, simply +re-open the page ":e". ------------------------------------------------------------------------------ 5.3. Headers *vimwiki-syntax-headers* @@ -625,72 +1098,75 @@ two lines. 5.5. Lists *vimwiki-syntax-lists* Unordered lists: > - * Bulleted list item 1 - * Bulleted list item 2 - * Bulleted list sub item 1 - * Bulleted list sub item 2 - * more ... - * and more ... - * ... - * Bulleted list sub item 3 - * etc. -or: > - Bulleted list item 1 - Bulleted list item 2 - - Bulleted list sub item 1 - - Bulleted list sub item 2 - - more ... - - and more ... - - ... - - Bulleted list sub item 3 - - etc. +or: > + * Bulleted list item 1 + * Bulleted list item 2 -or mix: > - - Bulleted list item 1 - - Bulleted list item 2 - * Bulleted list sub item 1 - * Bulleted list sub item 2 - * more ... - - and more ... - - ... - * Bulleted list sub item 3 - * etc. Ordered lists: > - # Numbered list item 1 - # Numbered list item 2 - # Numbered list sub item 1 - # Numbered list sub item 2 - # more ... - # and more ... - # ... - # Numbered list sub item 3 - # etc. - -It is possible to mix bulleted and numbered lists: > - * Bulleted list item 1 - * Bulleted list item 2 - # Numbered list sub item 1 - # Numbered list sub item 2 + 1. Numbered list item 1 + 2. Numbered list item 2 + 3. Numbered list item 3 +or: > + 1) Numbered list item 1 + 2) Numbered list item 2 + 3) Numbered list item 3 +or: > + a) Numbered list item 1 + b) Numbered list item 2 + c) Numbered list item 3 +or: > + A) Numbered list item 1 + B) Numbered list item 2 + C) Numbered list item 3 +or: > + i) Numbered list item 1 + ii) Numbered list item 2 + iii) Numbered list item 3 +or: > + I) Numbered list item 1 + II) Numbered list item 2 + III) Numbered list item 3 +or: > + # Bulleted list item 1 + # the # become numbers when converted to HTML -Note that a space after *, - or # is essential. +Note that a space after the list item symbols (-, *, 1. etc.) is essential. + +You can nest and mix the various types: > + - Bulleted list item 1 + - Bulleted list item 2 + a) Numbered list sub item 1 + b) more ... + * and more ... + * ... + c) Numbered list sub item 3 + 1. Numbered list sub sub item 1 + 2. Numbered list sub sub item 2 + d) etc. + - Bulleted list item 3 + +List items can span multiple lines: > + * Item 1 + Item 1 continued line. + Item 1 next continued line. + * Item 2 + - Sub item 1 + Sub item 1 continued line. + Sub item 1 next continued line. + - Sub item 2 + - etc. + Continuation of Item 2 + Next continuation of Item 2 -Multiline list items: > - * Bulleted list item 1 - List item 1 continued line. - List item 1 next continued line. - * Bulleted list item 2 - * Bulleted list sub item 1 - List sub item 1 continued line. - List sub item 1 next continued line. - * Bulleted list sub item 2 - * etc. Definition lists: > -Term 1:: Definition 1 -Term 2:: -:: Definition 2 -:: Definition 3 + Term 1:: Definition 1 + Term 2:: + :: Definition 2 + :: Definition 3 ------------------------------------------------------------------------------ @@ -702,7 +1178,7 @@ typeface formatting and links. For example: > | Year | Temperature (low) | Temperature (high) | - |------+-------------------+--------------------| + |------|-------------------|--------------------| | 1900 | -10 | 25 | | 1910 | -15 | 30 | | 1920 | -10 | 32 | @@ -712,14 +1188,14 @@ For example: > In HTML the following part > | Year | Temperature (low) | Temperature (high) | - |------+-------------------+--------------------| + |------|-------------------|--------------------| > -is higlighted as a table header. +is highlighted as a table header. If you indent a table then it will be centered in HTML. -If you set > in a cell, the cell spans the left column. -If you set \/ in a cell, the cell spans the above row. +If you put > in a cell, the cell spans the left column. +If you put \/ in a cell, the cell spans the above row. For example: > | a | b | c | d | @@ -730,9 +1206,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* @@ -750,7 +1223,7 @@ Use {{{ and }}} to define a block of preformatted text: }}} -You can add optional information to {{{ tag: > +You can add optional information after the {{{: > {{{class="brush: python" > def hello(world): for x in range(10): @@ -764,101 +1237,199 @@ Result of HTML export: > print("Hello {0} number {1}".format(world, x)) -This might be useful for coloring program code with external js tools -such as google's syntax highlighter. +This might be useful for coloring program code with external JS tools +such as Google's syntax highlighter. + +You can setup Vimwiki to highlight code snippets in preformatted text. +See |vimwiki-option-nested_syntaxes| and +|vimwiki-option-automatic_nested_syntaxes|. + + +------------------------------------------------------------------------------ +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. installing MathJax locally (Recommended: 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). + +2. Loading MathJax from a CDN-server (needs internet connection). +Add to your HTML template the following line: -You can setup vimwiki to highlight code snippets in preformatted text. -See |vimwiki-option-nested_syntaxes| + ------------------------------------------------------------------------------ -5.8. Blockquotes *vimwiki-syntax-blockquotes* +5.9. Blockquotes *vimwiki-syntax-blockquotes* -Text started with 4 or more spaces is a blockquote. +Text which starts with 4 or more spaces is a blockquote. - This would be a blockquote in vimwiki. It is not highlighted in vim but + This would be a blockquote in Vimwiki. It is not highlighted in Vim but could be styled by CSS in HTML. Blockquotes are usually used to quote a long piece of text from another source. ------------------------------------------------------------------------------ -5.9. Comments *vimwiki-syntax-comments* +5.10. Comments *vimwiki-syntax-comments* -Text line started with %% is a comment. +A line that starts with %% is a comment. E.g.: > %% this text would not be in HTML < - ------------------------------------------------------------------------------ -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' (
    ): > +4 or more dashes at the start of the line is a horizontal line (
    ): > ---- < +------------------------------------------------------------------------------ +5.12. Tags *vimwiki-syntax-tags* -============================================================================== -6. Folding/Outline *vimwiki-folding* +You can tag a wiki file, a header or an arbitrary place in a wiki file. Then, +you can use Vim's built-in tag search functionality (see |tagsrch.txt|) or +Vimwiki's tag related commands to quickly jump to all occurrences of the tag. -Vimwiki can fold or outline headers and list items. +A tag is a sequence of non-space characters between two colons: > + :tag-example: +< +It is allowed to concatenate multiple tags in one line: > + :tag-one:tag-two: +< +If placed in the first two lines of a file, the whole file is tagged. If +placed under a header, within the 2 lines below it, the header is then tagged +with this tag, and the tag search commands will jump to this specific header. +Otherwise, the tag stands of its own and the search command jumps directly to +it. -Example: -= My current task = - * [ ] Do stuff 1 - * [ ] Do substuff 1.1 - * [ ] Do substuff 1.2 - * [ ] Do substuff 1.2.1 - * [ ] Do substuff 1.2.2 - * [ ] Do substuff 1.3 - * [ ] Do stuff 2 - * [ ] Do stuff 3 +Typing tags can be simplified by using Vim's omni completion (see +|compl-omni|) like so: > + :ind +which opens up a popup menu with all tags defined in the wiki starting with +"ind". -Hit |zM| : -= My current task = [8] --------------------------------------~ +Tags are also treated as |vimwiki-anchors| (similar to bold text). -Hit |zr| : -= My current task =~ - * [ ] Do stuff 1 [5] --------------------------------------~ - * [ ] Do stuff 2~ - * [ ] Do stuff 3~ - -Hit |zr| one more time: -= My current task =~ - * [ ] Do stuff 1~ - * [ ] Do substuff 1.1~ - * [ ] Do substuff 1.2 [2] -------------------------------~ - * [ ] Do substuff 1.3~ - * [ ] Do stuff 2~ - * [ ] Do stuff 3~ - -NOTE:If you use default vimwiki syntax, folding on list items will work -properly only if all of them are indented using current |shiftwidth|. -For MediaWiki, * or # should be in the first column. + *vimwiki-build-tags* +Note that the tag search/jump/completion commands need certain metadata saved +in the wiki folder. This metadata file can be manually updated by running +|:VimwikiRebuildTags|. When the option |vimwiki-option-auto_tags| is enabled, +the tags metadata will be auto-updated on each page save. -To turn folding on/off check |g:vimwiki_folding|. + +Tags-related commands and options: + * |:VimwikiRebuildTags| + * |:VimwikiGenerateTags| + * |:VimwikiSearchTags| + * |vimwiki-option-auto_tags| ============================================================================== -7. Placeholders *vimwiki-placeholders* +6. Folding/Outline *vimwiki-folding* ------------------------------------------------------------------------------- -%toc Table of Contents *vimwiki-toc* *vimwiki-table-of-contents* +Vimwiki can fold or outline sections using headers and preformatted blocks. +Alternatively, one can fold list subitems instead. Folding is not enabled +by default, and requires the |g:vimwiki_folding| variable to be set. -You can add 'table of contents' to your HTML page generated from wiki one. -Just place > +Example for list folding with |g:vimwiki_folding| set to 'list': -%toc += My current task = +* [ ] Do stuff 1 + * [ ] Do substuff 1.1 + * [ ] Do substuff 1.2 + * [ ] Do substuff 1.2.1 + * [ ] Do substuff 1.2.2 + * [ ] Do substuff 1.3 +* [ ] Do stuff 2 +* [ ] Do stuff 3 -into your wiki page. -You can also add a caption to your 'toc': > +Hit |zM| : += My current task = +* [ ] Do stuff 1 [6] --------------------------------------~ +* [ ] Do stuff 2 +* [ ] Do stuff 3 -%toc Table of Contents +Hit |zr| : += My current task = +* [ ] Do stuff 1 + * [ ] Do substuff 1.1 + * [ ] Do substuff 1.2 [3] -------------------------------~ + * [ ] Do substuff 1.3 +* [ ] Do stuff 2 +* [ ] Do stuff 3 + +Hit |zr| one more time : += My current task = +* [ ] Do stuff 1 + * [ ] Do substuff 1.1 + * [ ] Do substuff 1.2 + * [ ] Do substuff 1.2.1 + * [ ] Do substuff 1.2.2 + * [ ] Do substuff 1.3 +* [ ] Do stuff 2 +* [ ] Do stuff 3 + +Note: If you use the default Vimwiki syntax, folding on list items will work +properly only if all of them are indented using the current 'shiftwidth'. +For Markdown and MediaWiki syntax, * or # should be in the first column. -or > +To turn folding on/off check |g:vimwiki_folding|. -%toc Whatever +============================================================================== +7. Placeholders *vimwiki-placeholders* ------------------------------------------------------------------------------ %title Title of the page *vimwiki-title* @@ -892,57 +1463,220 @@ into it. See |vimwiki-option-template_path| for details. +------------------------------------------------------------------------------ +%date *vimwiki-date* + +The date of the wiki page. The value can be used in the HTML template, see +|vimwiki-option-template_path| for details. + +%date 2017-07-08 +%date + +If you omit the date after the placeholder, the date of the HTML conversion is +used. + ============================================================================== -8. Todo lists *vimwiki-todo-lists* +8. Lists *vimwiki-lists* + +While writing lists, the keys , o and O insert new bullets or numbers as +you would expect it. A new bullet/number is inserted if and only if the cursor +is in a list item. To make a list item with more than one line, press +or press and . +Note that the mapping is not available in all terminals. + +Furthermore, and behave differently when the cursor is behind an +empty list item. See the table below. + +You can configure the behavior of and of like this: > + inoremap :VimwikiReturn 1 5 + inoremap :VimwikiReturn 2 2 + +The first argument of the command :VimwikiReturn is a number that specifies +when to insert a new bullet/number and when not, depending on whether the +cursor is in a list item or in a normal line: > + + Number │ Before │ After + ====================================== + 1 │ 1. item| │ 1. item + │ │ 2. | + │–––––––––––––––––––––––––––––– ← default for + │ 1. item │ 1. item + │ continue| │ continue + │ │ | + ====================================== + 2 │ 1. item| │ 1. item + │ │ | + │–––––––––––––––––––––––––––––– ← default for + │ 1. item │ 1. item + │ continue| │ continue + │ │ 2. | + ====================================== + 3 │ 1. item| │ 1. item + │ │ 2. | + │–––––––––––––––––––––––––––––– + │ 1. item │ 1. item + │ continue| │ continue + │ │ 2. | + ====================================== + 4 │ 1. item| │ 1. item + │ │ | + │–––––––––––––––––––––––––––––– + │ 1. item │ 1. item + │ continue| │ continue + │ │ | +< + +The second argument is a number that specifies what should happen when you +press or behind an empty list item. There are no less than five +possibilities: +> + Number │ Before │ After + ====================================== + 1 │ 1. | │ 1. + │ │ 2. | + ====================================== + 2 │ 1. | │ ← default for + │ │ 1. | + ====================================== + 3 │ 1. | │ | + │ │ + ====================================== + 4 │ 1. | │ + │ │ | + ====================================== + 5 │ 1. | │ 1. | + │ │ + │–––––––––––––––––––––––––––––– ← default for + │ 1. | │ | + │ │ +< + + + *vimwiki-list-manipulation* +The level of a list item is determined by its indentation (default and +Markdown syntax) or by the number of list symbols (MediaWiki syntax). + +Use gll and glh in normal mode to increase or decrease the level of a list +item. The symbols are adjusted automatically to the list items around it. +Use gLl and gLh to increase or decrease the level of a list item plus all +list items of lower level below it, that is, all child items. + +Use and to change the level of a list item in insert mode. + +See |vimwiki_gll|, |vimwiki_gLl|, |vimwiki_glh|, |vimwiki_gLh|, +|vimwiki_i_|, |vimwiki_i_| + + +Use gl followed by the desired symbol to change the symbol of a list item or +create one. Type gL and the symbol to change all items of the current list. +For default syntax, the following types are available: > + - hyphen + * asterisk + # hash + 1. number with period + 1) number with parenthesis + a) lower-case letter with parenthesis + A) upper-case letter with parenthesis + i) lower-case Roman numerals with parenthesis + I) upper-case Roman numerals with parenthesis + +Markdown syntax has the following types: > + - hyphen + * asterisk + + plus + 1. number with period + +MediaWiki syntax only has: > + * asterisk + # hash + +In insert mode, use the keys and to switch between +symbols. For convenience, only the commonly used symbols can be reached +through these keys for default syntax. + +Note that such a list: a) b) c) … only goes up to zz), to avoid confusion with +normal text followed by a parenthesis. +Roman numerals go up to MMMM) and numbers up to 2147483647. or +9223372036854775807. depending if your Vim is 32 or 64 bit. + +Also note that you can, of course, mix different list symbols in one list, but +if you have the strange idea of putting a list with Romanian numerals right +after a list using letters or vice versa, Vimwiki will get confused because +it cannot distinguish which is which (at least if the types are both upper +case or both lower case). + +See |vimwiki_glstar|, |vimwiki_gl#| |vimwiki_gl-|, |vimwiki_gl-|, +|vimwiki_gl1|, |vimwiki_gla|, |vimwiki_glA|, |vimwiki_gli|, |vimwiki_glI| + + +Use glr and gLr if the numbers of a numbered list are mixed up. See +|vimwiki_glr| and |vimwiki_gLr|. + + +------------------------------------------------------------------------------ +Todo lists *vimwiki-todo-lists* You can have todo lists -- lists of items you can check/uncheck. -Consider the following example: -= Toggleable list of todo items = - * [X] Toggle list item on/off. - * [X] Simple toggling between [ ] and [X]. - * [X] All list's subitems should be toggled on/off appropriately. - * [X] Toggle child subitems only if current line is list item - * [X] Parent list item should be toggled depending on it's child items. - * [X] Make numbered list items toggleable too - * [X] Add highlighting to list item boxes - * [X] Add [ ] to the next created with o, O and list item. +Consider the following example: > + = Toggleable list of todo items = + * [X] Toggle list item on/off. + * [X] Simple toggling between [ ] and [X]. + * [X] All list's subitems should be toggled on/off appropriately. + * [X] Toggle child subitems only if current line is list item + * [X] Parent list item should be toggled depending on it's child items. + * [X] Make numbered list items toggleable too + * [X] Add highlighting to list item boxes + * [X] Add [ ] to the next list item created with o, O and . Pressing on the first list item will toggle it and all of its child -items: -= Toggleable list of todo items = - * [ ] Toggle list item on/off. - * [ ] Simple toggling between [ ] and [X]. - * [ ] All of a list's subitems should be toggled on/off appropriately. - * [ ] Toggle child subitems only if the current line is a list item. - * [ ] Parent list item should be toggled depending on their child items. - * [X] Make numbered list items toggleable too. - * [X] Add highlighting to list item boxes. - * [X] Add [ ] to the next list item created using o, O or . +items: > + = Toggleable list of todo items = + * [ ] Toggle list item on/off. + * [ ] Simple toggling between [ ] and [X]. + * [ ] All of a list's subitems should be toggled on/off appropriately. + * [ ] Toggle child subitems only if the current line is a list item. + * [ ] Parent list item should be toggled depending on their child items. + * [X] Make numbered list items toggleable too. + * [X] Add highlighting to list item boxes. + * [X] Add [ ] to the next list item created using o, O or . Pressing on the third list item will toggle it and adjust all of its -parent items: -= Toggleable list of todo items = - * [.] Toggle list item on/off. - * [ ] Simple toggling between [ ] and [X]. - * [X] All of a list's subitems should be toggled on/off appropriately. - * [ ] Toggle child subitems only if current line is list item. - * [ ] Parent list item should be toggled depending on it's child items. - * [ ] Make numbered list items toggleable too. - * [ ] Add highlighting to list item boxes. - * [ ] Add [ ] to the next list item created using o, O or . - -Parent items could be changed when their child items change. The symbol -between [ ] depends on the percentage of toggled child items (see also -|g:vimwiki_listsyms|): > +parent items: > + = Toggleable list of todo items = + * [.] Toggle list item on/off. + * [ ] Simple toggling between [ ] and [X]. + * [X] All of a list's subitems should be toggled on/off appropriately. + * [ ] Toggle child subitems only if current line is list item. + * [ ] Parent list item should be toggled depending on it's child items. + * [ ] Make numbered list items toggleable too. + * [ ] Add highlighting to list item boxes. + * [ ] Add [ ] to the next list item created using o, O or . + +Parent items should change when their child items change. If not, use +|vimwiki_glr|. The symbol between [ ] depends on the percentage of toggled +child items (see also |g:vimwiki_listsyms|): > [ ] -- 0% [.] -- 1-33% [o] -- 34-66% [O] -- 67-99% [X] -- 100% -It is possible to toggle several list items using visual mode. +You can use |vimwiki_gln| and |vimwiki_glp| to change the "done" status of a +checkbox without a childitem. + +It is possible to toggle several list items using visual mode. But note that +instead of toggling every item individually, all items get checked if the +first item was unchecked and all items get unchecked if the first item was +checked. + +Use gl (see |vimwiki_gl|) to remove a single checkbox and +gL (see |vimwiki_gL|) to remove all checkboxes of the list the +cursor is in. + +You can mark an item as rejected ("won't do") with +|vimwiki_glx|. A rejected item will not influence the status of its parents. ============================================================================== @@ -950,23 +1684,23 @@ It is possible to toggle several list items using visual mode. Use the :VimwikiTable command to create a default table with 5 columns and 2 rows: > - + | | | | | | - |---+---+---+---+---| + |---|---|---|---|---| | | | | | | < Tables are auto-formattable. Let's add some text into first cell: > | First Name | | | | | - |---+---+---+---+---| + |---|---|---|---|---| | | | | | | < Whenever you press , or leave Insert mode, the table is formatted: > | First Name | | | | | - |------------+---+---+---+---| + |------------|---|---|---|---| | | | | | | < @@ -974,7 +1708,7 @@ You can easily create nice-looking text tables, just press and enter new values: > | First Name | Last Name | Age | City | e-mail | - |------------+------------+-----+----------+----------------------| + |------------|------------|-----|----------|----------------------| | Vladislav | Pokrishkin | 31 | Moscow | vlad_pok@smail.com | | James | Esfandiary | 27 | Istanbul | esfandiary@tmail.com | < @@ -986,39 +1720,30 @@ To indent table indent the first row. Then format it with 'gqq'. 10. Diary *vimwiki-diary* The diary helps you make daily notes. You can easily add information into -vimwiki that should be sorted out later. Just hit ww to create -new daily note with name based on current date. The link to this newly created -file is added to a diary wiki file. +Vimwiki that should be sorted out later. Just hit ww to create +a new note for today with a name based on the current date. -Usage example with default settings: > - Consider today is 2010-01-27. +To generate the diary section with all available links one can use +|:VimwikiDiaryGenerateLinks| or wi . - Hit \w\w . - ~/vimwiki/diary.wiki is created. +Note: it works only for diary index file. - 2 following lines are added to ~/vimwiki/diary/diary.wiki : - = Diary = - | [[2010-01-27]] | +Example of diary section: > + = Diary = - ~/vimwiki/diary/2010-01-27.wiki is created. - You are ready to add your information there. - ------------------------------------------- + == 2011 == - On the next day. - Hit \w\w . + === December === + * [[2011-12-09]] + * [[2011-12-08]] - The first line after = Diary = is changed in ~/vimwiki/diary/diary.wiki : - = Diary = - | [[2010-01-28]] | [[2010-01-27]] | - ~/vimwiki/diary/2010-01-28.wiki is created. - You are ready to add your information there. -> +See |g:vimwiki_diary_months| if you would like to rename months. -By default there are 4 links on the line. All links are sorted by their dates. -Calendar integration *vimwiki-calendar* ------------------------------------------------------------------------------ +Calendar integration *vimwiki-calendar* + If you have Calendar.vim installed you can use it to create diary notes. Just open calendar with :Calendar and tap on the date. A wiki file will be created in the default wiki's diary. @@ -1029,42 +1754,128 @@ See |g:vimwiki_use_calendar| option to turn it off/on. ============================================================================== -11. Options *vimwiki-options* +11. Anchors *vimwiki-anchors* + +Every header, tag, and bold text can be used as an anchor. To jump to it, use +a wikilink of the form > + [[file#anchor]] + +For example, consider the following file "Todo.wiki": > + = My tasks = + :todo-lists: + == Home == + - [ ] bathe my dog + == Work == + - [ ] beg for *pay rise* + == Knitting club == + === Knitting projects === + - [ ] a *funny pig* + - [ ] a *scary dog* + +Then, to jump from your index.wiki directly to your knitting projects, use: > + [[Todo#Knitting projects]] -There are global and per-wiki (local) options available to tune vimwiki. -All global options are set using the following pattern: > - let g:option_name=option_value +Or, to jump to an individual project, use this link: > + [[Todo#funny pig]] + +Or, to jump to a tag, use this link: > + [[Todo#todo-lists]] + +If there are multiple instances of an anchor, you can use the long form which +consists of the complete header hierarchy, separated by '#': > + [[Todo#My tasks#Knitting club#Knitting projects#scary dog]] + +If you don't feel like typing the whole stuff, type just [[Todo# and then +|i_CTRL-X_CTRL-O| to start the omni completion of anchors. + +For jumping inside a single file, you can omit the file in the link: > + [[#pay rise]] -All per-wiki options are dictionaries (see |Dictionary|) in a list of wikies. -See |g:vimwiki_list| option for more details. ------------------------------------------------------------------------------ -*g:vimwiki_list* *vimwiki-multiple-wikies* +Table of Contents *vimwiki-toc* *vimwiki-table-of-contents* -Each item in g:vimwiki_list is a |Dictionary| that holds all customization -available for a wiki represented by that item. It is in the form: > - {'option1': 'value1', 'option2: 'value2', ...} +You can create a "table of contents" at the top of your wiki file. +The commando |:VimwikiTOC| creates the magic header > + = Contents = +in the current file and below it a list of all the headers in this file as +links, so you can directly jump to specific parts of the file. -Consider the following example: > +For the indentation of the list, the value of |vimwiki-option-list_margin| is +used. + +If you don't want the TOC to sit in the very first line, e.g. because you have +a modeline there, put the magic header in the second or third line and run +:VimwikiTOC to update the TOC. + +If English is not your preferred language, set the option +|g:vimwiki_toc_header| to your favorite translation. + +If you want to keep the TOC up to date automatically, use the option +|vimwiki-option-auto_toc|. + + +------------------------------------------------------------------------------ +Tagbar integration *vimwiki-tagbar* + +As an alternative to the Table of Contents, you can use the Tagbar plugin +(http://majutsushi.github.io/tagbar/) to show the headers of your wiki files +in a side pane. +Download the Python script from +https://raw.githubusercontent.com/vimwiki/utils/master/vwtags.py and follow +the instructions in it. + + +============================================================================== +12. Options *vimwiki-options* + +There are global options and local (per-wiki) options available to tune +Vimwiki. + +Global options are configured via global variables. For a complete list of +them, see |vimwiki-global-options|. + +Local options for multiple independent wikis are stored in a single global +variable |g:vimwiki_list|. The per-wiki options can be registered in advance, +as described in |vimwiki-register-wiki|, or may be registered on the fly as +described in |vimwiki-temporary-wiki|. For a list of per-wiki options, see +|vimwiki-local-options|. + +A note for Vim power users: +If you have an elaborated Vim setup, where you e.g. load plugins +conditionally, make sure the settings are set before Vimwiki loads (that is, +before plugin/vimwiki.vim is sourced). If this is not possible, try this +command after the Vimwiki settings are (re-) set: > + :call vimwiki#vars#init() + +------------------------------------------------------------------------------ +12.1 Registered Wiki *g:vimwiki_list* *vimwiki-register-wiki* + +One or more wikis can be registered using the |g:vimwiki_list| variable. + +Each item in |g:vimwiki_list| is a |Dictionary| that holds all customizations +available for a distinct wiki. The options dictionary has the form: > + {'option1': 'value1', 'option2': 'value2', ...} + +Consider the following: > let g:vimwiki_list = [{'path': '~/my_site/', 'path_html': '~/public_html/'}] -It gives us one wiki located at ~/my_site/ that could be htmlized to -~/public_html/ +This defines one wiki located at ~/my_site/. When converted to HTML, the +produced HTML files go to ~/public_html/ . -The next example: > +Another example: > let g:vimwiki_list = [{'path': '~/my_site/', 'path_html': '~/public_html/'}, \ {'path': '~/my_docs/', 'ext': '.mdox'}] -gives us 2 wikies, the first wiki as in the previous example, and the second -one located in ~/my_docs/, with files that have the .mdox extension. + +defines two wikis: the first as before, and the second one located in +~/my_docs/, with files that have the .mdox extension. An empty |Dictionary| in g:vimwiki_list is the wiki with default options: > let g:vimwiki_list = [{}, \ {'path': '~/my_docs/', 'ext': '.mdox'}] -< - -You can also create wikis as separate |Dictionary|s. > - +For clarity, in your .vimrc file you can define wiki options using separate +|Dictionary| variables and subsequently compose them into |g:vimwiki_list|. > let wiki_1 = {} let wiki_1.path = '~/my_docs/' let wiki_1.html_template = '~/public_html/template.tpl' @@ -1075,10 +1886,37 @@ You can also create wikis as separate |Dictionary|s. > let wiki_2.index = 'main' let g:vimwiki_list = [wiki_1, wiki_2] - < -PER WIKI OPTIONS *viwmiki-local-options* + +------------------------------------------------------------------------------ +12.2 Temporary Wiki *vimwiki-temporary-wiki* + + +The creation of temporary wikis allows you to create a wiki on the fly. + +If a file with a registered wiki extension (see |vimwiki-register-extension|) +is opened in a directory that: 1) is not listed in |g:vimwiki_list|, and 2) is +not a subdirectory of any such directory, then a temporary wiki is created and +appended to the list of configured wikis in |g:vimwiki_list|. + +In addition to Vimwiki's editing functionality, the temporary wiki enables: 1) +wiki-linking to other files in the same subtree, 2) highlighting of existing +wiki pages when |vimwiki-option-maxhi| is activated, and 3) HTML generation to +|vimwiki-option-path_html|. + +Temporary wikis are configured using default |vimwiki-local-options|, except +for the path, extension, and syntax options. The path and extension are set +using the file's location and extension. The syntax is set to Vimwiki's +default unless another syntax is registered via |vimwiki-register-extension|. + +Use |g:vimwiki_global_ext| to turn off creation of temporary wikis. + +NOTE: Vimwiki assumes that the locations of distinct wikis do not overlap. + + +------------------------------------------------------------------------------ +12.3 Per-Wiki Options *vimwiki-local-options* *vimwiki-option-path* @@ -1094,19 +1932,20 @@ Wiki files location: > *vimwiki-option-path_html* ------------------------------------------------------------------------------ Key Default value~ -path_html ~/vimwiki_html/ +path_html '' Description~ Location of HTML files converted from wiki files: > let g:vimwiki_list = [{'path': '~/my_site/', - \ 'path_html': '~/my_site_html/'}] + \ 'path_html': '~/html_site/'}] -If you omit this option, the value of path_html would be set to the value of -path with the trailing slash ('/') removed and '_html' added; i.e. for: > +If path_html is an empty string, the location is derived from +|vimwiki-option-path| by adding '_html'; i.e. for: > let g:vimwiki_list = [{'path': '~/okidoki/'}] path_html will be set to '~/okidoki_html/'. + *vimwiki-option-auto_export* ------------------------------------------------------------------------------ Key Default value Values~ @@ -1119,6 +1958,18 @@ corresponding wiki page is saved: > This will keep your HTML files up to date. + +*vimwiki-option-auto_toc* +------------------------------------------------------------------------------ +Key Default value Values~ +auto_toc 0 0, 1 + +Description~ +Set this option to 1 to automatically update the table of contents when the +current wiki page is saved: > + let g:vimwiki_list = [{'path': '~/my_site/', 'auto_toc': 1}] + + *vimwiki-option-index* ------------------------------------------------------------------------------ Key Default value~ @@ -1145,15 +1996,16 @@ Extension of wiki files: > *vimwiki-option-syntax* ------------------------------------------------------------------------------ Key Default value Values~ -syntax default default, media +syntax default default, markdown, or media Description~ -Wiki syntax. -You can use different markup languages (currently default vimwiki and -MediaWiki), but only vimwiki's default markup will be converted to HTML at the -moment. -To use MediaWiki's wiki markup: > - let g:vimwiki_list = [{'path': '~/my_site/', 'syntax': 'media'}] +Wiki syntax. You can use different markup languages (currently: Vimwiki's +default, Markdown, and MediaWiki), but only Vimwiki's default markup will be +converted to HTML at the moment. + +To use Markdown's wiki markup: > + let g:vimwiki_list = [{'path': '~/my_site/', + \ 'syntax': 'markdown', 'ext': '.md'}] < *vimwiki-option-template_path* @@ -1186,15 +2038,17 @@ Each template could look like: >
    %content%
    +

    Page created on %date%

    -where +where %title% is replaced by a wiki page name or by a |vimwiki-title| + %date% is replaced with the current date or by |vimwiki-date| %root_path% is replaced by a count of ../ for pages buried in subdirs: if you have wikilink [[dir1/dir2/dir3/my page in a subdir]] then %root_path% is replaced by '../../../'. - + %content% is replaced by a wiki file content. @@ -1219,7 +2073,7 @@ See |vimwiki-option-template_path| for details. *vimwiki-option-template_ext* ------------------------------------------------------------------------------ Key Default value~ -template_ext .html +template_ext .tpl Description~ Setup template filename extension. @@ -1241,29 +2095,28 @@ or even > let g:vimwiki_list = [{'path': '~/my_pages/', \ 'css_name': 'css/main.css'}] < +Vimwiki comes with a default CSS file "style.css". *vimwiki-option-maxhi* ------------------------------------------------------------------------------ Key Default value Values~ -maxhi 1 0, 1 +maxhi 0 0, 1 Description~ -Non-existent wiki links highlighting can be quite slow. If you don't want it, -set maxhi to 0: > - let g:vimwiki_list = [{'path': '~/my_site/', 'maxhi': 0}] - -This disables filesystem checks for wiki links. +If on, wiki links to non-existent wiki files are highlighted. However, it can +be quite slow. If you still want it, set maxhi to 1: > + let g:vimwiki_list = [{'path': '~/my_site/', 'maxhi': 1}] *vimwiki-option-nested_syntaxes* ------------------------------------------------------------------------------ Key Default value Values~ -nested_syntaxes {} pairs of highlight keyword and vim filetype +nested_syntaxes {} pairs of highlight keyword and Vim filetype Description~ You can configure preformatted text to be highlighted with any syntax -available for vim. +available for Vim. For example the following setup in your vimrc: > let wiki = {} let wiki.path = '~/my_wiki/' @@ -1299,13 +2152,37 @@ or in: > }}} +*vimwiki-option-automatic_nested_syntaxes* +------------------------------------------------------------------------------ +Key Default value~ +automatic_nested_syntaxes 1 + +Description~ +If set, the nested syntaxes (|vimwiki-option-nested_syntaxes|) are +automatically derived when opening a buffer. +Just write your preformatted text in your file like this > + {{{xxx + my preformatted text + }}} + +where xxx is a filetype which is known to Vim. For example, for C++ +highlighting, use "cpp" (not "c++"). For a list of known filetypes, type +":setf " and hit Ctrl+d. + +Note that you may have to reload the file (|:edit|) to see the highlight. + +Since every file is scanned for the markers of preformatted text when it is +opened, it can be slow when you have huge files. In this case, set this option +to 0. + + *vimwiki-option-diary_rel_path* ------------------------------------------------------------------------------ Key Default value~ diary_rel_path diary/ Description~ -Related to |vimwiki-option-path| path for diary wiki-files. +The path to the diary wiki files, relative to |vimwiki-option-path|. *vimwiki-option-diary_index* @@ -1314,7 +2191,7 @@ Key Default value~ diary_index diary Description~ -Name of wiki-file that holds all links to dated wiki-files. +Name of wiki-file that holds all links to dated wiki files. *vimwiki-option-diary_header* @@ -1327,34 +2204,124 @@ Name of the header in |vimwiki-option-diary_index| where links to dated wiki-files are located. -*vimwiki-option-diary_link_count* +*vimwiki-option-diary_sort* +------------------------------------------------------------------------------ +Key Default value Values~ +diary_sort desc desc, asc + +Description~ +Sort links in a diary index page. + + +*vimwiki-option-custom_wiki2html* ------------------------------------------------------------------------------ Key Default value~ -diary_link_count 4 +custom_wiki2html '' Description~ -Number of maximum dated links placed on one line. -Ex: -= Diary = -| [[2010-01-30]] | [[2010-01-29]] | [[2010-01-28]] | [[2010-01-27]] | -| [[2010-01-26]] | [[2010-01-25]] | +The full path to an user-provided script that converts a wiki page to HTML. +Vimwiki calls the provided |vimwiki-option-custom_wiki2html| script from the +command-line, using |:!| invocation. + +The following arguments, in this order, are passed to the script: + +1. force : [0/1] overwrite an existing file +2. syntax : the syntax chosen for this wiki +3. extension : the file extension for this wiki +4. output_dir : the full path of the output directory +5. input_file : the full path of the wiki page +6. css_file : the full path of the css file for this wiki +7. template_path : the full path to the wiki's templates +8. template_default : the default template name +9. template_ext : the extension of template files +10. root_path : a count of ../ for pages buried in subdirs + For example, if you have wikilink [[dir1/dir2/dir3/my page in a subdir]] + then this argument is '../../../'. +11. custom_args : custom arguments that will be passed to the conversion + (can be defined in g:vimwiki_list as 'custom_wiki2html_args' parameter, + see |vimwiki-option-custom_wiki2html_args|) + script. + +Options 7-11 are experimental and may change in the future. If any of these +parameters is empty, a hyphen "-" is passed to the script in its place. +For an example and further instructions, refer to the following script: + $VIMHOME/autoload/vimwiki/customwiki2html.sh +An alternative converter was developed by Jason6Anderson, and can +be located at https://github.com/vimwiki-backup/vimwiki/issues/384 -GLOBAL OPTIONS *viwmiki-global-options* +To use the internal wiki2html converter, use an empty string (the default). -Use: > - let g:option_name=option_value -to set them. +*vimwiki-option-custom_wiki2html_args* ----------------------------------------------------------------------------- +Key Default value~ +custom_wiki2html_args '' + +Description~ +If a custom script is called with |vimwiki-option-custom_wiki2html|, additional +parameters can be passed using this option: > + let g:vimwiki_list = [{'path': '~/path/', 'custom_wiki2html_args': 'stuff'}] + + +*vimwiki-option-list_margin* +------------------------------------------------------------------------------ +Key Default value~ +list_margin -1 + +Description~ +Width of left-hand margin for lists. When negative, the current 'shiftwidth' +is used. This affects the appearance of the generated links (see +|:VimwikiGenerateLinks|), the Table of contents (|vimwiki-toc|) and the +behavior of the list manipulation commands |:VimwikiListChangeLevel| and the +local mappings |vimwiki_glstar|, |vimwiki_gl#| |vimwiki_gl-|, |vimwiki_gl-|, +|vimwiki_gl1|, |vimwiki_gla|, |vimwiki_glA|, |vimwiki_gli|, |vimwiki_glI| and +|vimwiki_i__|. + +Note: if you use Markdown or MediaWiki syntax, you probably would like to set +this option to 0, because every indented line is considered verbatim text. + + +*vimwiki-option-auto_tags* +------------------------------------------------------------------------------ +Key Default value Values~ +auto_tags 0 0, 1 + +Description~ +Set this option to 1 to automatically update the tags metadata when the +current wiki page is saved: > + let g:vimwiki_list = [{'path': '~/my_site/', 'auto_tags': 1}] + + +*vimwiki-option-auto_diary_index* +------------------------------------------------------------------------------ +Key Default value Values~ +auto_diary_index 0 0, 1 + +Description~ +Set this option to 1 to automatically update the diary index when opened. +See |:VimwikiDiaryGenerateLinks|: > + let g:vimwiki_list = [{'path': '~/my_site/', 'auto_diary_index': 1}] + + +------------------------------------------------------------------------------ +12.4 Global Options *vimwiki-global-options* + + +Global options are configured using the following pattern: > + + let g:option_name = option_value + + +------------------------------------------------------------------------------ *g:vimwiki_hl_headers* Highlight headers with =Reddish=, ==Greenish==, ===Blueish=== colors. Value Description~ -1 Use VimwikiHeader1-VimwikiHeader6 group colors to highlight +1 Use VimwikiHeader1 - VimwikiHeader6 group colors to highlight different header levels. 0 Use |hl-Title| color for headers. Default: 0 @@ -1363,72 +2330,73 @@ Default: 0 ------------------------------------------------------------------------------ *g:vimwiki_hl_cb_checked* -Checked list items can be highlighted with a color: +Highlight checked list items with a special color: * [X] the whole line can be highlighted with the option set to 1. - * [ ] I wish vim could use strikethru. + * this line is highlighted as well with the option set to 2 + * [ ] this line is never highlighted Value Description~ -1 Highlight checked [X] check box with |group-name| "Comment". -0 Don't. +0 Don't highlight anything. +1 Highlight only the first line of a checked [X] list item. +2 Highlight a complete checked list item and all its child items. Default: 0 +The |group-name| "Comment" is used for highlighting. + +Note: Option 2 does not work perfectly. Specifically, it might break if the +list item contains preformatted text or if you mix tabs and spaces for +indenting. Also, indented headers can be highlighted erroneously. +Furthermore, if your list is long, Vim's highlight can break. To solve this, +consider putting > + au BufEnter *.wiki :syntax sync fromstart +in your .vimrc ------------------------------------------------------------------------------ -*g:vimwiki_global_ext* *vimwiki-temporary-wiki* +*g:vimwiki_global_ext* + +Control the creation of |vimwiki-temporary-wiki|s. -If a file with a registered wiki extension is opened in a directory that is -not listed in |g:vimwiki_list| then: +If a file with a registered extension (see |vimwiki-register-extension|) is +opened in a directory that is: 1) not listed in |g:vimwiki_list|, and 2) not a +subdirectory of any such directory, then: Value Description~ -1 make a temporary wiki in that dir. +1 make temporary wiki and append it to |g:vimwiki_list|. 0 don't make temporary wiki in that dir. -A temporary wiki is created to scan the filesystem for available links to -highlight. - -Consider your wiki extension is .txt then you can > +If your preferred wiki extension is .txt then you can > let g:vimwiki_global_ext = 0 -to make it local to vimwiki paths listed in g:vimwiki_list. So other text -files wouldn't be treated as wiki pages. +to restrict Vimwiki's operation to only those paths listed in g:vimwiki_list. +Other text files wouldn't be treated as wiki pages. Default: 1 ------------------------------------------------------------------------------ -*g:vimwiki_upper* *g:vimwiki_lower* - -This affects WikiWord detection. -By default WikiWord detection uses English and Russian letters. -You can set up your own: > - let g:vimwiki_upper = "A-Z\u0410-\u042f" - let g:vimwiki_lower = "a-z\u0430-\u044f" - - ------------------------------------------------------------------------------- -*g:vimwiki_auto_checkbox* +*g:vimwiki_ext2syntax* *vimwiki-register-extension* -If on, creates checkbox while toggling list item. +A many-to-one mapping between file extensions and syntaxes whose purpose is to +register the extensions with Vimwiki. -Value Description~ -0 Do not create checkbox. -1 Create checkbox. +E.g.: > + let g:vimwiki_ext2syntax = {'.md': 'markdown', + \ '.mkd': 'markdown', + \ '.wiki': 'media'} -Default: 1 +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. -E.g.: -Press (|:VimwikiToggleListItem|) on a list item without checkbox to -create it: > - * List item -Result: > - * [ ] List item +Default: {} ------------------------------------------------------------------------------ *g:vimwiki_menu* -GUI menu of available wikies to select. +Create a menu in the menu bar of GVim, where you can open the available wikis. Value Description~ '' No menu @@ -1440,38 +2408,30 @@ 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_listsyms* ------------------------------------------------------------------------------- -*g:vimwiki_badsyms* +String of at least two symbols to show the progression of todo list items. +Default value is ' .oOX'. -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'. +The first char is for 0% done items. +The last is for 100% done items. -This option is a complement one to |g:vimwiki_stripsym|. +You can set it to some more fancy symbols like this: +> + let g:vimwiki_listsyms = '✗○◐●✓' ------------------------------------------------------------------------------ -*g:vimwiki_listsyms* +*g:vimwiki_listsym_rejected* -String of 5 symbols for list items with checkboxes. -Default value is ' .oOX'. +Character that is used to show that an item of a todo list will not be done. +Default value is '-'. -g:vimwiki_listsyms[0] is for 0% done items. -g:vimwiki_listsyms[4] is for 100% done items. +The character used here must not be part of |g:vimwiki_listsyms|. + +You can set it to a more fancy symbol like this: +> + let g:vimwiki_listsym_rejected = '✗' ------------------------------------------------------------------------------ @@ -1489,60 +2449,49 @@ Default: 0 ------------------------------------------------------------------------------ *g:vimwiki_folding* -Enable/disable vimwiki's folding/outline functionality. Folding in vimwiki -uses the 'expr' foldmethod which is very flexible but really slow. +Enable/disable Vimwiki's folding (outline) functionality. Folding in Vimwiki +can uses either the 'expr' or the 'syntax' |foldmethod| of Vim. Value Description~ -0 Disable folding. -1 Enable folding. +'' Disable folding +'expr' Folding based on expression (folds sections and code blocks) +'syntax' Folding based on syntax (folds sections; slower than 'expr') +'list' Folding based on expression (folds list subitems; much slower) +'custom' Leave the folding settings as they are (e.g. set by another + plugin) -Default: 0 - - ------------------------------------------------------------------------------- -*g:vimwiki_fold_lists* - -Enable/disable folding of list subitems. - -Value Description~ -0 Disable list subitem's folding. -1 Enable list subitem's folding. - -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: '' -Default: 0 +Limitations: + - Opening very large files may be slow when folding is enabled. + - 'list' folding is particularly slow with larger files. + - 'list' is intended to work with lists nicely indented with 'shiftwidth'. + - 'syntax' is only available for the default syntax so far. +The options above can be suffixed with ':quick' (e.g.: 'expr:quick') in order +to use some workarounds to make folds work faster. ------------------------------------------------------------------------------ -*g:vimwiki_camel_case* +*g:vimwiki_list_ignore_newline* -If you do not want WikiWord to be a link, this setting is just for you. +This is HTML related. +Convert newlines to
    s in multiline list items. Value Description~ -0 Do not make links from CamelCased words. -1 Make links from CamelCased words. +0 Newlines in a list item are converted to
    s. +1 Ignore newlines. Default: 1 ------------------------------------------------------------------------------ -*g:vimwiki_list_ignore_newline* +*g:vimwiki_text_ignore_newline* This is HTML related. -Convert newlines to
    s in multiline list items. +Convert newlines to
    s in text. Value Description~ -0 Newlines in a list item are converted to
    s. +0 Newlines in text are converted to
    s. 1 Ignore newlines. Default: 1 @@ -1562,34 +2511,134 @@ Default: 1 ------------------------------------------------------------------------------ -*g:vimwiki_browsers* *VimwikiWeblinkHandler* +*VimwikiLinkHandler* + +A customizable link handler can be defined to override Vimwiki's behavior when +opening 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 indicates success. + +If the link is not handled successfully, the behavior of Vimwiki depends on +the scheme. "wiki:", "diary:" or schemeless links are opened in Vim. "file:" +and "local:" links are opened with a system default handler. + +You can redefine the VimwikiLinkHandler function in your .vimrc to do +something else: > + + 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 a new scheme, "vfile:", which behaves similar to +"file:", but the files are always opened with Vim in a new tab: > + + function! VimwikiLinkHandler(link) + " Use Vim to open external files with the 'vfile:' scheme. E.g.: + " 1) [[vfile:~/Code/PythonProject/abc123.py]] + " 2) [[vfile:./|Wiki Home]] + let link = a:link + if link =~# '^vfile:' + let link = link[1:] + else + return 0 + endif + let link_infos = vimwiki#base#resolve_link(link) + if link_infos.filename == '' + echomsg 'Vimwiki Error: Unable to resolve link!' + return 0 + else + exe 'tabnew ' . fnameescape(link_infos.filename) + return 1 + endif + endfunction + +------------------------------------------------------------------------------ +*VimwikiLinkConverter* + +This function can be overridden in your .vimrc to specify what a link looks +like when converted to HTML. The parameters of the function are: + - the link as a string + - the full path to the wiki file where the link is in + - the full path to the output HTML file +It should return the HTML link if successful or an empty string '' otherwise. + +This example changes how relative links to external files using the "local:" +scheme look like in HTML. Per default, they would become links relative to +the HTML output directory. This function converts them to links relative to +the wiki file, i.e. a link [[local:../document.pdf]] becomes +
    . Also, this function will copy document.pdf to the +right place. > + + function! VimwikiLinkConverter(link, source_wiki_file, target_html_file) + if a:link =~# '^local:' + let link_infos = vimwiki#base#resolve_link(a:link) + let html_link = vimwiki#path#relpath( + \ fnamemodify(a:source_wiki_file, ':h'), link_infos.filename) + let relative_link = + \ fnamemodify(a:target_html_file, ':h') . '/' . html_link + call system('cp ' . fnameescape(link_infos.filename) . + \ ' ' . fnameescape(relative_link)) + return html_link + endif + return '' + endfunction -You can open external weblinks in a webbrowser. Webbrowsers are listed in -|g:vimwiki_browsers|. +------------------------------------------------------------------------------ +*VimwikiWikiIncludeHandler* -For win32 it is: chrome, opera, firefox and explorer. -For other OSes it is: opera, firefox and konqueror. +Vimwiki includes the content of a wiki-include URL as an image by default. -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'] +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: > -or redefine VimwikiWeblinkHandler function: > - function! VimwikiWeblinkHandler(weblink) - let browser = 'C:\Program Files\Firefox\firefox.exe' - execute '!start "'.browser.'" ' . a:weblink - endfunction + " 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 link_infos = vimwiki#base#resolve_link(url_0) + let arg1 = matchstr(str, VimwikiWikiInclMatchArg(1)) + let arg2 = matchstr(str, VimwikiWikiInclMatchArg(2)) + + if arg1 =~ '#' + return link_infos.filename.'#'.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 @@ -1597,7 +2646,7 @@ Default: 1 ------------------------------------------------------------------------------ *g:vimwiki_w32_dir_enc* -Convert directory name from current |encoding| into 'g:vimwiki_w32_dir_enc' +Convert directory name from current 'encoding' into 'g:vimwiki_w32_dir_enc' before it is created. If you have 'enc=utf-8' and set up > @@ -1614,8 +2663,8 @@ Default: '' ------------------------------------------------------------------------------ *g:vimwiki_CJK_length* -Use special method to calculate correct length of the strings with double-wide -characters (to align table cells properly). +Use a special method to calculate the correct length of the strings with +double-wide characters (to align table cells properly). Value Description~ 0 Do not use it. @@ -1623,18 +2672,18 @@ Value Description~ Default: 0 -Note: Vim73 has a new function |strdisplaywidth|, so for Vim73 users this -option is obsolete. +Note: Vim 7.3 has a new function |strdisplaywidth()|, so for users of an up to +date Vim, this option is obsolete. ------------------------------------------------------------------------------ *g:vimwiki_dir_link* -This option is about what to do with links to directories -- [[directory/]], -[[papers/]], etc. +This option is about what to do with links to directories, like +[[directory/]], [[papers/]], etc. Value Description~ -'' Open 'directory/' using standard netrw plugin. +'' Open 'directory/' using the standard netrw plugin. 'index' Open 'directory/index.wiki', create if needed. 'main' Open 'directory/main.wiki', create if needed. etc. @@ -1665,6 +2714,7 @@ Value Description~ 2 Header numbering is on. Headers are numbered starting from header level 2. etc. + Example when g:vimwiki_html_header_numbering = 2: > Header1 1 Header2 @@ -1683,15 +2733,15 @@ Default: 0 ------------------------------------------------------------------------------ *g:vimwiki_html_header_numbering_sym* -Ending symbol for |g:vimwiki_html_header_numbering|. +Ending symbol for |g:vimwiki_html_header_numbering|. Value Description~ '.' Dot will be added after a header's number. ')' Closing bracket will be added after a header's number. etc. -With - let g:vimwiki_html_header_numbering = '.' +With + let g:vimwiki_html_header_numbering_sym = '.' headers would look like: > 1. Header1 1.1. Header2 @@ -1707,23 +2757,11 @@ 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* -Comma-separated list of HTML tags that can be used in vimwiki. +Case-insensitive comma separated list of HTML tags that can be used in +Vimwiki. When converting to HTML, these tags are left as they are, while +every other tag is escaped. Default: 'b,i,s,u,sub,sup,kbd,br,hr' @@ -1737,7 +2775,7 @@ should not be deleted after |:VimwikiAll2HTML|. Default: '' Example: -Consider you have 404.html and search.html in your vimwiki 'path_html'. +Consider you have 404.html and search.html in your Vimwiki 'path_html'. With: > let g:vimwiki_user_htmls = '404.html,search.html' they would not be deleted after |:VimwikiAll2HTML|. @@ -1746,44 +2784,447 @@ they would not be deleted after |:VimwikiAll2HTML|. ------------------------------------------------------------------------------ *g:vimwiki_conceallevel* -In vim73 |conceallevel| is local to window, thus if you open viwmiki buffer in -a new tab or window, it would be set to default value. +In Vim 7.3 'conceallevel' is local to the current window, thus if you open a +Vimwiki buffer in a new tab or window, it would be set to the default value. + +Vimwiki sets 'conceallevel' to g:vimwiki_conceallevel every time a Vimwiki +buffer is entered. + +With default settings, Vimwiki conceals one-character markers, shortens long +URLs and hides markers and URL for links that have a description. + +Default: 2 + + +------------------------------------------------------------------------------ +*g:vimwiki_autowriteall* + +Automatically save a modified wiki buffer when switching wiki pages. Has the +same effect like setting the Vim option 'autowriteall', but it works for wiki +files only, while the Vim option is global. +Hint: if you're just annoyed that you have to save files manually to switch +wiki pages, consider setting the Vim option 'hidden' which makes that modified +files don't need to be saved. + +Value Description~ +0 autowriteall is off +1 autowriteall is on + +Default: 1 + + +------------------------------------------------------------------------------ +*g:vimwiki_url_maxsave* + +Setting the value of |g:vimwiki_url_maxsave| to 0 will prevent any link +shortening: you will see the full URL in all types of links, with no parts +being concealed. Concealing of one-character markers is not affected. + +When positive, the value determines the maximum number of characters that +are retained at the end after concealing the middle part of a long URL. +It could be less: in case one of the characters /,#,? is found near the end, +the URL will be concealed up to the last occurrence of that character. + +Note: + * The conceal feature works only with Vim >= 7.3. + * When using the default |wrap| option of Vim, the effect of concealed links + is not always pleasing, because the visible text on longer lines with + a lot of concealed parts may appear to be strangely broken across several + lines. This is a limitation of Vim's |conceal| feature. + * Many color schemes do not define an unobtrusive color for the Conceal + highlight group - this might be quite noticeable on shortened URLs. + + +Default: 15 -Vimwiki sets |conceallevel| to g:vimwiki_conceallevel everytime vimwiki buffer -is entered. -Default: 3 +------------------------------------------------------------------------------ +*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' + \ } + + +------------------------------------------------------------------------------ +*g:vimwiki_toc_header* + +A string with the magic header that tells Vimwiki where the Table of Contents +(see |vimwiki-toc|) is located in a file. You can change it to the +appropriate word in your mother tongue like this: > + let g:vimwiki_toc_header = 'Inhalt' +The default is 'Contents'. + + +------------------------------------------------------------------------------ +*g:vimwiki_map_prefix* + +A string which specifies the prefix for all global mappings (and some local +ones). Use it to avoid conflicts with other plugins. Note that it must be +defined before the plugin loads. > + let g:vimwiki_map_prefix = 'e' + +The default is 'w'. + + +------------------------------------------------------------------------------ +*g:vimwiki_auto_chdir* + +When set to 1, enables auto-cd feature. Whenever Vimwiki page is opened, +Vimwiki performs an |:lcd| to the Vimwiki folder to where the page belongs. + + +Value Description~ +0 Do not change directory. +1 Change directory to Vimwiki folder on opening page. + +Default: 0 ============================================================================== -12. Help *vimwiki-help* +13. Getting help *vimwiki-help* + +For questions, discussions, praise or rants there is a mailing list: +https://groups.google.com/forum/#!forum/vimwiki + +Also, there is the IRC channel #vimwiki on Freenode which can be accessed via +webchat: https://webchat.freenode.net/?channels=#vimwiki -Your help in making vimwiki better is really appreciated! +============================================================================== +14. Contributing & Bug reports *vimwiki-contributing* + +Your help in making Vimwiki better is really appreciated! Any help, whether it is a spelling correction or a code snippet to patch -- everything is welcomed. -Issues can be filed at http://code.google.com/p/vimwiki/issues . - +See CONTRIBUTING.md for info about how to file bugs etc. ============================================================================== -13. Developers *vimwiki-developers* - - - Maxim Kim as original author. - - See the http://code.google.com/p/vimwiki/people/list for the others. +15. Development *vimwiki-development* -Web: http://code.google.com/p/vimwiki/ -Mail-List: https://groups.google.com/forum/#!forum/vimwiki +Homepage: http://vimwiki.github.io/ +Github: https://github.com/vimwiki/vimwiki/ Vim plugins: http://www.vim.org/scripts/script.php?script_id=2226 +Old homepage: http://code.google.com/p/vimwiki/ + +Contributors and their Github usernames in roughly chronological order: + + - Maxim Kim (@habamax) as original author + - the people here: http://code.google.com/p/vimwiki/people/list + - Stuart Andrews (@tub78) + - Tomas Pospichal + - Daniel Schemala (@EinfachToll) as current maintainer + - Larry Hynes (@larryhynes) + - Hector Arciga (@harciga) + - Alexey Radkov (@lyokha) + - Aaron Franks (@af) + - Dan Bernier (@danbernier) + - Carl Helmertz (@chelmertz) + - Karl Yngve Lervåg (@lervag) + - Patrick Davey (@patrickdavey) + - Ivan Tishchenko (@t7ko) + - 修昊 (@Svtter) + - Marcelo D Montu (@mMontu) + - John Kaul + - Hongbo Liu (@hiberabyss) + - @Tomsod + - @wangzq + - Jinzhou Zhang (@lotabout) + - Michael Riley (@optik-aper) + - Irfan Sharif (@irfansharif) + - John Conroy (@jconroy77) + - Christian Rondeau (@christianrondeau) + - Alex Thorne (@thornecc) + - Shafqat Bhuiyan (@priomsrb) + - Bradley Cicenas (@bcicen) + - Michael Thessel (@MichaelThessel) + - Michael F. Schönitzer (@nudin) + - @sqlwwx + - Guilherme Salazar (@salazar) + - Daniel Trnka (@trnila) + - Yuchen Pei (@ycpei) + - @maqiv + - Dawid Ciężarkiewicz (@dpc) + - Drew Hays (@Dru89) + - Daniel Etrata (@danetrata) + - Keith Haber (@kjhaber) + - @beuerle + - Silvio Ricardo Cordeiro (@silvioricardoc) + - @blyoa + - Jonathan McElroy (@jonathanmcelroy) + - @PetrusZ + - Brian Gianforcaro (@bgianfo) + - Ben Burrill (@benburrill) + - Zhuang Ma (@mzlogin) + - Huy Le (@huynle) + - Nick Borden (@hcwndbyw) + - John Campbell (@johnmarcampbell) + - Petrus (@PetrusZ) + - Steven Stallion (@sstallion) + - Daniel Quomsieh (@DQuomsieh) + - Fredrik Arnerup (@farnerup) + - CUI Hao (@cuihaoleo) + - Benjamin Brandtner (@BenjaminBrandtner) + - @sreejith994 + - Raphael Feng (@raphaelfeng) + - Kasper Socha (@fte10kso) + - Nicolas Brailovsky (@nicolasbrailo) + - @BenMcH + - Stefan Huber (@shuber2) + - Hugo Hörnquist (@HugoNikanor) + - Rane Brown (@ranebrown) + - @monkinco ============================================================================== -14. Changelog *vimwiki-changelog* +16. Changelog *vimwiki-changelog* + + +Issue numbers starting with '#' are issues from +https://github.com/vimwiki/vimwiki/issues/, all others from +http://code.google.com/p/vimwiki/issues/list. They may be accessible from +https://github.com/vimwiki-backup/vimwiki/issues. + + +2.4.1 (2019-02-20)~ +Fixed: + * Fix VimwikiShowVersion function. + * strikethrough `~` characters were not hidden within tables + * Update and format README.md and update screen shots + +2.4 (2019-03-24)~ + +New:~ + * Add the option |g:vimwiki_text_ignore_newline|. + * |g:vimwiki_listsyms| can have fewer or more than 5 symbols. + * glx on a list item marks a checkbox as won't do, see |vimwiki_glx|. + * Add the option |g:vimwiki_listsym_rejected| to set the character used + for won't-do list items. + * gln and glp change the "done" status of a checkbox, see |vimwiki_gln|. + * |:VimwikiSplitLink| and |:VimwikiVSplitLink| can now reuse an existing + split window and not move the cursor. + * Add 'aH' and 'iH' text objects, see |vimwiki-text-objects|. + * Add the keys |vimwiki_[[|, |vimwiki_]]|, |vimwiki_[=|, |vimwiki_]=| and + |vimwiki_]u| for navigating between headers. + * Add the command |:VimwikiMakeTomorrowDiaryNote|. + * |g:vimwiki_folding| has a new option 'custom'. + * Add the ':quick' option for faster folding, see |g:vimwiki_folding|. + * Add the %date placeholder, see |vimwiki-date|. + * Add the option |vimwiki-option-custom_wiki2html_args|. + * Add support for HTML-style comments when using markdown syntax. + * Made headings link to themselves in HTML output. + * Add |:VimwikiShowVersion| to check the version + +Removed:~ + * Remove the undocumented and buggy command :VimwikiReadLocalOptions + which allowed to store Vimwiki related settings in a local file. + * Remove the undocumented command :VimwikiPrintWikiState. + * For complicated reasons, Vimwiki doesn't clean up its settings anymore + if you change the filetype of a wiki buffer. + +Fixed:~ + * Make |vimwiki-option-automatic_nested_syntaxes| work also for markdown. + * Issue #236: Highlight math blocks as TeX math, not TeX. + * Issue #264: Don't overwrite mappings to i_ from other plugins. + * Fix an error where sometimes didn't work under Windows. + * Issue #302: |:VimwikiDiaryGenerateLinks| had issues with markdown. + * Issue #445: Better handling of |'autowriteall'| and |'hidden'|. + * Improve 'ah' and 'ih' text objects, see |vimwiki-text-objects|. + * Allow opening of links using Powershell. + * Allow any visual mode to be used with |vimwiki_+|. + * Markdown syntax for |vimwiki-toc| is used, when appropriate. + * Wikis can now be in subfolders of other wikis. + * Issue #482: |:VimwikiMakeDiaryNote| now uses the diary of the current wiki. + * Opening the diary and wikis from the menu works correctly now. + * Issue #497: Make |:VimwikiMakeDiaryNote| work outside a wiki buffer. + * Use markdown syntax in the diary when appropriate. + * Improve handling of errors on opening files. + * Update links when renaming a page with |:VimwikiRenameLink|. + * Fix losing the highlighting in various situations. + * Improved link normalisation. + * Various other minor fixes. + + +2.3 (2016-03-31)~ + +New:~ + * Add |:VimwikiMakeYesterdayDiaryNote| command + * Issue #128: add option |vimwiki-option-automatic_nested_syntaxes| + * Issue #192: Sort links in the list generated by |:VimwikiGenerateTags| + +Fixed:~ + * Issue #176: Fix issue when the wiki path contains spaces + * Also look for tags in wiki files in subdirectories + * Locate the .tags file correctly on Windows + * Issue #183: Fix HTML conversion of headers containing links + * Issue #64: create correct Markdown links when pressing CR on a word + * Issue #191: ignore headers inside preformatted text when creating the TOC + * Create the standard CSS file also if only one file is converted to HTML + * Fix #188: |vimwiki_+| on a raw url surrounds it with brackets + * various minor fixes + + +2.2.1 (2015-12-10)~ + +Removed:~ + * Removed the option g:vimwiki_debug, which probably nobody used. If you + want it back, file an issue at Github. + +Fixed:~ + * Issue #175: Don't do random things when the user has remapped the z key + * Don't ask for confirmation when following an URL in MacOS + * Always jump to the first occurrence of a tag in a file + * Don't move the cursor when updating the TOC + * Fix some issues with the TOC when folding is enabled + + +2.2 (2015-11-25)~ + +New:~ + * Support for anchors, see |vimwiki-anchors| + * in this context, add support for TOC, see |vimwiki-toc| + * add omni completion of wiki links (files and anchors) + * new local option |vimwiki-option-auto_toc| + * new global option |g:vimwiki_toc_header| + * Support for tags, see |vimwiki-syntax-tags| + * List editing capabilities, see |vimwiki-lists|: + * support for auto incrementing numbered lists + * more key maps for list manipulation, see |vimwiki-list-manipulation| + * improved automatic adjustment of checkboxes + * text objects for list items, see |vimwiki-text-objects| + * New command |:VimwikiCheckLinks| to check for broken links + * New global option |g:vimwiki_auto_chdir| + * New global option |g:vimwiki_map_prefix| + * Support for wiki links absolute to the wiki root + * Added the |VimwikiLinkConverter| function + * Issue #24: Basic support for remote directories via netrw + * Issue #50: in HTML, tables can now be embedded in lists + * When converting to HTML, show a message with the output directory + * Add auto completion for |:VimwikiGoto| + * Add Chinese Readme file + +Changed:~ + * Wiki files must not contain # anymore, because # is used to separate the + file from an anchor in a link. + * replace the function vimwiki#base#resolve_scheme() by + vimwiki#base#resolve_link() (relevant if you have a custom + |VimwikiLinkHandler| which used this function) + * The semantic of "file:" and "local:" links changed slightly, see + |vimwiki-syntax-links| for what they mean now + * The meaning of a link like [[/some/directory/]] changed. It used to be + a link to the actual directory /some/directory/, now it's relative to + the root of the current wiki. Use [[file:/some/directory/]] for the old + behavior. + +Removed:~ + * the %toc placeholder is now useless, use |vimwiki-toc| instead + * the global option g:vimwiki_auto_checkbox is now useless and removed + +Fixed:~ + * Issue 415: Disable folding if g:vimwiki_folding is set to '' + * Fix slowdown in Vim 7.4 + * Issue #12: Separate diaries from different wikis + * Issue #13: Fix :VimwikiRenameLink on links containing a dot + * Always jump to previous link on , not to beginning of link + * Issue #27: Fix on a visual selection sometimes not working + * |VimwikiBackLinks| now recognizes much more valid links + * Issue 424: make external links with #, % work under Linux + * Issue #39: don't htmlize stuff inside pre tags + * Issue #44: faster formatting of large tables + * Issue #52: Recognize markdown links when renaming wiki file + * Issue #54: Disable 'shellslash' on Windows to avoid problems + * Issue #81: Don't get stuck when converting a read-only file + * Issue #66: Better normalizing of links in diary + * Fix the menu in GVim, which was sometimes not shown correctly + * |VimwikiGenerateLinks| now also generates links for subdirectories + * Issue #93: Don't process placeholders inside preformatted text + * Issue #102: Add default values to some options like the doc says + * Issue #144: Fix bug with folds shortening on multibyte characters + * Issue #158: Detect the OS correctly + * |VimwikiGenerateLinks| now replaces a potentially existing old list + * Fix uneven indentation of list items with checkboxes in HTML + * Various small fixes + * Corrected website links in documentation. code.google is dead, long live + Github! + +2.1~ + + * Concealing of links can be turned off - set |g:vimwiki_url_maxsave| to 0. + The option g:vimwiki_url_mingain was removed + * |g:vimwiki_folding| also accepts value 'list'; with 'expr' both sections + and code blocks folded, g:vimwiki_fold_lists option was removed + * Issue 261: Syntax folding is back. |g:vimwiki_folding| values are + changed to '', 'expr', 'syntax'. + * Issue 372: Ignore case in g:vimwiki_valid_html_tags + * Issue 374: Make autowriteall local to vimwiki. It is not 100% local + though. + * Issue 384: Custom_wiki2html script now receives templating arguments + * Issue 393: Custom_wiki2html script path can contain tilde character + * Issue 392: Custom_wiki2html arguments are quoted, e.g names with spaces + * Various small bug fixes. + +2.0.1 'stu'~ + + * Follow (i.e. open target of) markdown reference-style links. + * Bug fixes. + + +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 + * More link schemes + * Transclusions + * 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| converts only changed wiki files. - * Issue 117: |VimwikiDiaryIndex| command that opens diary index wiki page. + * Issue 117: |:VimwikiDiaryIndex| command that opens diary index wiki page. * Issue 120: Links in headers are not highlighted in vimwiki but are highlighted in HTML. * Issue 138: Added possibility to remap table-column move bindings. See @@ -1801,7 +3242,7 @@ Vim plugins: http://www.vim.org/scripts/script.php?script_id=2226 * Fix of g:vimwiki_stripsym = '' (i.e. an empty string) -- it removes bad symbols from filenames. * Issue 145: With modeline 'set ft=vimwiki' links are not correctly - highlighted when open wiki files. + highlighted when open wiki files. * Issue 146: Filetype difficulty with ".txt" as a vimwiki extension. * Issue 148: There are no mailto links. * Issue 151: Use location list instead of quickfix list for :VimwikiSearch @@ -1838,483 +3279,27 @@ Vim plugins: http://www.vim.org/scripts/script.php?script_id=2226 * Issue 210: HTML: para enclose header. * Issue 214: External links containing Chinese characters get trimmed. * Issue 218: Command to generate HTML file and open it in webbrowser. See - |:Vimwiki2HTMLBrowse|(bind to whh) + |:Vimwiki2HTMLBrowse|(bind to whh) * 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. - -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]] +... + +39 releases + +... 0.1~ * First public version. ============================================================================== -15. License *vimwiki-license* +17. License *vimwiki-license* -The MIT Licence +The MIT License http://www.opensource.org/licenses/mit-license.php Copyright (c) 2008-2010 Maxim Kim + 2013-2017 Daniel Schemala Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/etc/soft/nvim/+plugins/vimwiki/doc/wiki.png b/etc/soft/nvim/+plugins/vimwiki/doc/wiki.png new file mode 100644 index 0000000..bbcc463 Binary files /dev/null and b/etc/soft/nvim/+plugins/vimwiki/doc/wiki.png differ diff --git a/etc/soft/nvim/+plugins/vimwiki/ftplugin/vimwiki.vim b/etc/soft/nvim/+plugins/vimwiki/ftplugin/vimwiki.vim index 7ef05da..2d3688b 100644 --- a/etc/soft/nvim/+plugins/vimwiki/ftplugin/vimwiki.vim +++ b/etc/soft/nvim/+plugins/vimwiki/ftplugin/vimwiki.vim @@ -1,234 +1,307 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki filetype plugin file -" Author: Maxim Kim -" Home: http://code.google.com/p/vimwiki/ +" Home: https://github.com/vimwiki/vimwiki/ if exists("b:did_ftplugin") finish endif let b:did_ftplugin = 1 " Don't load another plugin for this buffer -" UNDO list {{{ -" Reset the following options to undo this plugin. -let b:undo_ftplugin = "setlocal ". - \ "suffixesadd< isfname< comments< ". - \ "autowriteall< ". - \ "formatoptions< foldtext< ". - \ "foldmethod< foldexpr< commentstring< " -" UNDO }}} -" MISC STUFF {{{ -setlocal autowriteall setlocal commentstring=%%%s -if g:vimwiki_conceallevel && exists("+conceallevel") - let &conceallevel = g:vimwiki_conceallevel +if vimwiki#vars#get_global('conceallevel') && exists("+conceallevel") + let &l:conceallevel = vimwiki#vars#get_global('conceallevel') endif -" MISC }}} - -" GOTO FILE: gf {{{ -execute 'setlocal suffixesadd='.VimwikiGet('ext') +" This is for GOTO FILE: gf +execute 'setlocal suffixesadd='.vimwiki#vars#get_wikilocal('ext') setlocal isfname-=[,] -" gf}}} - -" Autocreate list items {{{ -" for list items, and list items with checkboxes -if VimwikiGet('syntax') == 'default' - setl comments=b:*,b:#,b:- - setl formatlistpat=^\\s*[*#-]\\s* -else - setl comments=n:*,n:# -endif -setlocal formatoptions=tnro - -if !empty(&langmap) - " Valid only if langmap is a comma separated pairs of chars - let l_o = matchstr(&langmap, '\C,\zs.\zeo,') - if l_o - exe 'nnoremap '.l_o.' :call vimwiki#lst#kbd_oO("o")a' - endif - let l_O = matchstr(&langmap, '\C,\zs.\zeO,') - if l_O - exe 'nnoremap '.l_O.' :call vimwiki#lst#kbd_oO("O")a' - endif -endif +exe "setlocal tags+=" . escape(vimwiki#tags#metadata_file_path(), ' \|"') -" COMMENTS }}} -" FOLDING for headers and list items using expr fold method. {{{ -function! VimwikiFoldLevel(lnum) "{{{ - let line = getline(a:lnum) - " Header folding... - if line =~ g:vimwiki_rxHeader - let n = vimwiki#base#count_first_sym(line) - return '>'.n - endif +function! Complete_wikifiles(findstart, base) + if a:findstart == 1 + let column = col('.')-2 + let line = getline('.')[:column] + let startoflink = match(line, '\[\[\zs[^\\[\]]*$') + if startoflink != -1 + let s:line_context = '[' + return startoflink + endif + if vimwiki#vars#get_wikilocal('syntax') ==? 'markdown' + let startofinlinelink = match(line, '\[.*\](\zs[^)]*$') + if startofinlinelink != -1 + let s:line_context = '[' + return startofinlinelink + endif + endif + let startoftag = match(line, ':\zs[^:[:space:]]*$') + if startoftag != -1 + let s:line_context = ':' + return startoftag + endif + let s:line_context = '' + return -1 + else + " Completion works for wikilinks/anchors, and for tags. s:line_content + " tells us which string came before a:base. There seems to be no easier + " solution, because calling col('.') here returns garbage. + if s:line_context == '' + return [] + elseif s:line_context == ':' + " Tags completion + let tags = vimwiki#tags#get_tags() + if a:base != '' + call filter(tags, + \ "v:val[:" . (len(a:base)-1) . "] == '" . substitute(a:base, "'", "''", '') . "'" ) + endif + return tags + elseif a:base !~# '#' + " we look for wiki files + + if a:base =~# '\m^wiki\d\+:' + let wikinumber = eval(matchstr(a:base, '\m^wiki\zs\d\+')) + if wikinumber >= vimwiki#vars#number_of_wikis() + return [] + endif + let prefix = matchstr(a:base, '\m^wiki\d\+:\zs.*') + let scheme = matchstr(a:base, '\m^wiki\d\+:\ze') + elseif a:base =~# '^diary:' + let wikinumber = -1 + let prefix = matchstr(a:base, '^diary:\zs.*') + let scheme = matchstr(a:base, '^diary:\ze') + else " current wiki + let wikinumber = vimwiki#vars#get_bufferlocal('wiki_nr') + let prefix = a:base + let scheme = '' + 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 links = vimwiki#base#get_wikilinks(wikinumber, 1) + let result = [] + for wikifile in links + if wikifile =~ '^'.vimwiki#u#escape(prefix) + call add(result, scheme . wikifile) + endif + endfor + return result - " List item folding... - if g:vimwiki_fold_lists - let base_level = s:get_base_level(a:lnum) - - let rx_list_item = '\('. - \ g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber. - \ '\)' - - - if line =~ rx_list_item - let [nnum, nline] = s:find_forward(rx_list_item, a:lnum) - let level = s:get_li_level(a:lnum) - let leveln = s:get_li_level(nnum) - let adj = s:get_li_level(s:get_start_list(rx_list_item, a:lnum)) - - if leveln > level - return ">".(base_level+leveln-adj) - else - return (base_level+level-adj) - endif else - " 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) - 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) + " we look for anchors in the given wikifile + + let segments = split(a:base, '#', 1) + let given_wikifile = segments[0] == '' ? expand('%:t:r') : segments[0] + let link_infos = vimwiki#base#resolve_link(given_wikifile.'#') + let wikifile = link_infos.filename + let syntax = vimwiki#vars#get_wikilocal('syntax', link_infos.index) + let anchors = vimwiki#base#get_anchors(wikifile, syntax) + + let filtered_anchors = [] + let given_anchor = join(segments[1:], '#') + for anchor in anchors + if anchor =~# '^'.vimwiki#u#escape(given_anchor) + call add(filtered_anchors, segments[0].'#'.anchor) endif - endif + endfor + return filtered_anchors + endif + endif +endfunction + +setlocal omnifunc=Complete_wikifiles + + - return base_level +" settings necessary for the automatic formatting of lists +setlocal autoindent +setlocal nosmartindent +setlocal nocindent +setlocal comments="" +setlocal formatoptions-=c +setlocal formatoptions-=r +setlocal formatoptions-=o +setlocal formatoptions-=2 +setlocal formatoptions+=n + +let &formatlistpat = vimwiki#vars#get_syntaxlocal('rxListItem') + +if !empty(&langmap) + " Valid only if langmap is a comma separated pairs of chars + let s:l_o = matchstr(&langmap, '\C,\zs.\zeo,') + if s:l_o + exe 'nnoremap '.s:l_o.' :call vimwiki#lst#kbd_o()a' endif - return -1 -endfunction "}}} + let s:l_O = matchstr(&langmap, '\C,\zs.\zeO,') + if s:l_O + exe 'nnoremap '.s:l_O.' :call vimwiki#lst#kbd_O()a' + endif +endif -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)) - endif - let lnum -= 1 - endwhile - return 0 -endfunction "}}} - -function! s:find_forward(rx_item, lnum) "{{{ - let lnum = a:lnum + 1 - - while lnum <= line('$') - let line = getline(lnum) - if line =~ a:rx_item - \ || line =~ '^\S' - \ || line =~ g:vimwiki_rxHeader - break - endif - let lnum += 1 - endwhile - return [lnum, getline(lnum)] -endfunction "}}} -function! s:find_backward(rx_item, lnum) "{{{ - let lnum = a:lnum - 1 +" ------------------------------------------------ +" Folding stuff +" ------------------------------------------------ - while lnum > 1 - let line = getline(lnum) - if line =~ a:rx_item - \ || line =~ '^\S' - break - endif - let lnum -= 1 - endwhile +function! VimwikiFoldListLevel(lnum) + return vimwiki#lst#fold_level(a:lnum) +endfunction - return [lnum, getline(lnum)] -endfunction "}}} -function! s:get_li_level(lnum) "{{{ - if VimwikiGet('syntax') == 'media' - let level = vimwiki#base#count_first_sym(getline(a:lnum)) +function! VimwikiFoldLevel(lnum) + let line = getline(a:lnum) + + " Header/section folding... + if line =~# vimwiki#vars#get_syntaxlocal('rxHeader') + return '>'.vimwiki#u#count_first_sym(line) + " Code block folding... + elseif line =~# vimwiki#vars#get_syntaxlocal('rxPreStart') + return 'a1' + elseif line =~# vimwiki#vars#get_syntaxlocal('rxPreEnd') + return 's1' else - let level = (indent(a:lnum) / &sw) + return "=" + endif +endfunction + + +" Constants used by VimwikiFoldText +" use \u2026 and \u21b2 (or \u2424) if enc=utf-8 to save screen space +let s:ellipsis = (&enc ==? 'utf-8') ? "\u2026" : "..." +let s:ell_len = strlen(s:ellipsis) +let s:newline = (&enc ==? 'utf-8') ? "\u21b2 " : " " +let s:tolerance = 5 + + +" unused +function! s:shorten_text_simple(text, len) + let spare_len = a:len - len(a:text) + return (spare_len>=0) ? [a:text,spare_len] : [a:text[0:a:len].s:ellipsis, -1] +endfunction + + +" s:shorten_text(text, len) = [string, spare] with "spare" = len-strlen(string) +" for long enough "text", the string's length is within s:tolerance of "len" +" (so that -s:tolerance <= spare <= s:tolerance, "string" ends with s:ellipsis) +function! s:shorten_text(text, len) + " returns [string, spare] + " strlen() returns lenght in bytes, not in characters, so we'll have to do a + " trick here -- replace all non-spaces with dot, calculate lengths and + " indexes on it, then use original string to break at selected index. + let text_pattern = substitute(a:text, '\m\S', '.', 'g') + let spare_len = a:len - strlen(text_pattern) + if (spare_len + s:tolerance >= 0) + return [a:text, spare_len] endif - return level -endfunction "}}} - -function! s:get_start_list(rx_item, lnum) "{{{ - let lnum = a:lnum - while lnum >= 1 - let line = getline(lnum) - if line !~ a:rx_item && line =~ '^\S' - return nextnonblank(lnum + 1) + " try to break on a space; assumes a:len-s:ell_len >= s:tolerance + let newlen = a:len - s:ell_len + let idx = strridx(text_pattern, ' ', newlen + s:tolerance) + let break_idx = (idx + s:tolerance >= newlen) ? idx : newlen + return [matchstr(a:text, '\m^.\{'.break_idx.'\}').s:ellipsis, newlen - break_idx] +endfunction + + +function! VimwikiFoldText() + let line = getline(v:foldstart) + let main_text = substitute(line, '^\s*', repeat(' ',indent(v:foldstart)), '') + let fold_len = v:foldend - v:foldstart + 1 + let len_text = ' ['.fold_len.'] ' + if line !~# vimwiki#vars#get_syntaxlocal('rxPreStart') + let [main_text, spare_len] = s:shorten_text(main_text, 50) + return main_text.len_text + else + " fold-text for code blocks: use one or two of the starting lines + let [main_text, spare_len] = s:shorten_text(main_text, 24) + let line1 = substitute(getline(v:foldstart+1), '^\s*', ' ', '') + let [content_text, spare_len] = s:shorten_text(line1, spare_len+20) + if spare_len > s:tolerance && fold_len > 3 + let line2 = substitute(getline(v:foldstart+2), '^\s*', s:newline, '') + let [more_text, spare_len] = s:shorten_text(line2, spare_len+12) + let content_text .= more_text endif - let lnum -= 1 - endwhile - return 0 -endfunction "}}} + return main_text.len_text.content_text + endif +endfunction -function! VimwikiFoldText() "{{{ - let line = substitute(getline(v:foldstart), '\t', - \ repeat(' ', &tabstop), 'g') - return line.' ['.(v:foldend - v:foldstart).']' -endfunction "}}} -" FOLDING }}} -" COMMANDS {{{ +" ------------------------------------------------ +" Commands +" ------------------------------------------------ + command! -buffer Vimwiki2HTML - \ w call vimwiki#html#Wiki2HTML(expand(VimwikiGet('path_html')), + \ if filewritable(expand('%')) | silent noautocmd w | endif + \ + \ let res = vimwiki#html#Wiki2HTML(expand(vimwiki#vars#get_wikilocal('path_html')), \ expand('%')) + \ + \ if res != '' | echo 'Vimwiki: HTML conversion is done, output: ' + \ . expand(vimwiki#vars#get_wikilocal('path_html')) | endif command! -buffer Vimwiki2HTMLBrowse - \ w call VimwikiWeblinkHandler( - \ vimwiki#html#Wiki2HTML(expand(VimwikiGet('path_html')), - \ expand('%'))) + \ if filewritable(expand('%')) | silent noautocmd w | endif + \ + \ call vimwiki#base#system_open_link(vimwiki#html#Wiki2HTML( + \ expand(vimwiki#vars#get_wikilocal('path_html')), + \ expand('%'))) command! -buffer VimwikiAll2HTML - \ call vimwiki#html#WikiAll2HTML(expand(VimwikiGet('path_html'))) + \ call vimwiki#html#WikiAll2HTML(expand(vimwiki#vars#get_wikilocal('path_html'))) + +command! -buffer VimwikiTOC call vimwiki#base#table_of_contents(1) command! -buffer VimwikiNextLink call vimwiki#base#find_next_link() command! -buffer VimwikiPrevLink call vimwiki#base#find_prev_link() command! -buffer VimwikiDeleteLink call vimwiki#base#delete_link() command! -buffer VimwikiRenameLink call vimwiki#base#rename_link() -command! -buffer VimwikiFollowLink call vimwiki#base#follow_link('nosplit') +command! -buffer VimwikiFollowLink call vimwiki#base#follow_link('nosplit', 0, 1) 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=* VimwikiSplitLink call vimwiki#base#follow_link('hsplit', ) +command! -buffer -nargs=* VimwikiVSplitLink call vimwiki#base#follow_link('vsplit', ) -command! -buffer VimwikiTabnewLink call vimwiki#base#follow_link('tabnew') +command! -buffer -nargs=? VimwikiNormalizeLink call vimwiki#base#normalize_link() -command! -buffer -range VimwikiToggleListItem call vimwiki#lst#ToggleListItem(, ) +command! -buffer VimwikiTabnewLink call vimwiki#base#follow_link('tab', 0, 1) 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'), ' ') + \ escape(vimwiki#vars#get_wikilocal('path').'**/*'.vimwiki#vars#get_wikilocal('ext'), ' ') exe 'command! -buffer -nargs=* VWS lvimgrep '. - \ escape(VimwikiGet('path').'**/*'.VimwikiGet('ext'), ' ') - -command! -buffer -nargs=1 VimwikiGoto call vimwiki#base#goto("") + \ escape(vimwiki#vars#get_wikilocal('path').'**/*'.vimwiki#vars#get_wikilocal('ext'), ' ') + +command! -buffer -nargs=+ -complete=custom,vimwiki#base#complete_links_escaped + \ VimwikiGoto call vimwiki#base#goto() + +command! -buffer VimwikiCheckLinks call vimwiki#base#check_links() + +" list commands +command! -buffer -nargs=+ VimwikiReturn call CR() +command! -buffer -range -nargs=1 VimwikiChangeSymbolTo + \ call vimwiki#lst#change_marker(, , , 'n') +command! -buffer -range -nargs=1 VimwikiListChangeSymbolI + \ call vimwiki#lst#change_marker(, , , 'i') +command! -buffer -nargs=1 VimwikiChangeSymbolInListTo + \ call vimwiki#lst#change_marker_in_list() +command! -buffer -range VimwikiToggleListItem call vimwiki#lst#toggle_cb(, ) +command! -buffer -range VimwikiToggleRejectedListItem + \ call vimwiki#lst#toggle_rejected_cb(, ) +command! -buffer -range VimwikiIncrementListItem call vimwiki#lst#increment_cb(, ) +command! -buffer -range VimwikiDecrementListItem call vimwiki#lst#decrement_cb(, ) +command! -buffer -range -nargs=+ VimwikiListChangeLvl + \ call vimwiki#lst#change_level(, , ) +command! -buffer -range VimwikiRemoveSingleCB call vimwiki#lst#remove_cb(, ) +command! -buffer VimwikiRemoveCBInList call vimwiki#lst#remove_cb_in_list() +command! -buffer VimwikiRenumberList call vimwiki#lst#adjust_numbered_list() +command! -buffer VimwikiRenumberAllLists call vimwiki#lst#adjust_whole_buffer() +command! -buffer VimwikiListToggle call vimwiki#lst#toggle_list_item() " table commands command! -buffer -nargs=* VimwikiTable call vimwiki#tbl#create() @@ -241,13 +314,26 @@ command! -buffer VimwikiTableMoveColumnRight call vimwiki#tbl#move_column_right( command! -buffer VimwikiDiaryNextDay call vimwiki#diary#goto_next_day() command! -buffer VimwikiDiaryPrevDay call vimwiki#diary#goto_prev_day() -" COMMANDS }}} +" tags commands +command! -buffer -bang VimwikiRebuildTags call vimwiki#tags#update_tags(1, '') +command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags + \ VimwikiSearchTags VimwikiSearch /::/ +command! -buffer -nargs=* -complete=custom,vimwiki#tags#complete_tags + \ VimwikiGenerateTags call vimwiki#tags#generate_tags() + +command! -buffer VimwikiPasteUrl call vimwiki#html#PasteUrl(expand('%:p')) +command! -buffer VimwikiCatUrl call vimwiki#html#CatUrl(expand('%:p')) -" KEYBINDINGS {{{ -if g:vimwiki_use_mouse + +" ------------------------------------------------ +" Keybindings +" ------------------------------------------------ + +if vimwiki#vars#get_global('use_mouse') nmap nmap - nnoremap <2-LeftMouse> :VimwikiFollowLink + nnoremap <2-LeftMouse> + \ :call vimwiki#base#follow_link('nosplit', 0, 1, "\2-LeftMouse>") nnoremap :VimwikiSplitLink nnoremap :VimwikiVSplitLink nnoremap :VimwikiGoBackLink @@ -255,138 +341,276 @@ endif if !hasmapto('Vimwiki2HTML') - nmap wh Vimwiki2HTML + exe 'nmap '.vimwiki#vars#get_global('map_prefix').'h Vimwiki2HTML' endif -nnoremap