diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d791bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Local stuff +# This section is devoted to this project +############################## +doc/tags + +# Vim stuff +############################## +*.s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ + +# OS generated files +############################## +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5a03fae --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,55 @@ +# Filing a bug + +Before filing a bug or starting to write a patch, check the latest development version from +https://github.com/vimwiki/vimwiki/tree/dev to see if your problem is already fixed. + +Issues can be filed at https://github.com/vimwiki/vimwiki/issues/ . + +# Creating a pull request +If you want to provide a pull request on GitHub, please start from the `dev` branch, not from the +`master` branch. (Caution, GitHub shows `master` as the default branch from which to start a PR.) + + +# More info 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 compatiblility. 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/LICENSE b/LICENSE new file mode 100644 index 0000000..cdf8546 --- /dev/null +++ b/LICENSE @@ -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/README-cn.md b/README-cn.md new file mode 100644 index 0000000..5d1a064 --- /dev/null +++ b/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/README.md b/README.md index 3d6a564..dec2b9a 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,27 @@ -A Personal Wiki For Vim Plugin +A Personal Wiki For Vim ============================================================================== -This is a mirror of http://www.vim.org/scripts/script.php?script_id=2226 - -Screenshots are available on http://code.google.com/p/vimwiki/ -There are also zipped vimwiki files there in case you do not like vimball archives. - - -Prerequisites -============================================================================== - -Make sure you have these settings in your vimrc file: - - set nocompatible - filetype plugin on - syntax on - -Without them Vimwiki will not work properly. +[中文](README-cn.md) +![screenshot1](doc/screenshot_1.png) +![screenshot2](doc/screenshot_2.png) * Intro -============================================================================== +------------------------------------------------------------------------------ + Vimwiki is a personal wiki for Vim -- a number of linked text files that have their own syntax highlighting. -With vimwiki you can: +With Vimwiki you can: - * organize notes and ideas; - * manage todo-lists; - * write documentation. + * organize notes and ideas + * manage todo-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 +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: @@ -41,32 +30,35 @@ Feed it with the following example: * 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 +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: +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. -For the various options see `:h vimwiki-options`. - Basic Markup -============================================================================== -see `:h vimwiki-syntax` +------------------------------------------------------------------------------ - *bold* -- bold - _italic_ -- italic + = Header1 = + == Header2 == + === Header3 === + + + *bold* -- bold text + _italic_ -- italic text + + [[wiki link]] -- wiki link + [[wiki link|description]] -- wiki link with description - [[wiki link]] -- link with spaces - [[wiki link|description]] -- link with description Lists: @@ -85,45 +77,98 @@ Lists: a) numbered list item 3 b) numbered list item 4 - = Header1 = - == Header2 == - === Header3 === + +For other syntax elements, see `:h vimwiki-syntax` Key bindings -============================================================================== -see `:h vimwiki-mappings` +------------------------------------------------------------------------------ -normal mode: +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. - * `` -- Folow/Create wiki link - * `` -- Split and folow/create wiki link - * `` -- Vertical split and folow/create wiki link - * `` -- Go back to parent(previous) wiki link - * `` -- Find next wiki link - * `` -- Find previous wiki link + * `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 -============================================================================== +Commands +------------------------------------------------------------------------------ - * `:Vimwiki2HTML` -- Convert current wiki link to HTML - * `:VimwikiAll2HTML` -- Convert all your wiki links to HTML + * `:Vimwiki2HTML` -- Convert current wiki link to HTML + * `:VimwikiAll2HTML` -- Convert all your wiki links to HTML * `:help vimwiki-commands` -- list all commands - -Install details -============================================================================== + * `:help vimwiki` -- General vimwiki help docs -Using pathogen (http://www.vim.org/scripts/script.php?script_id=2332 ) + +Changing Wiki Syntax +------------------------------------------------------------------------------ + + Vimwiki currently ships with 3 syntaxes: Vimwiki (default), Markdown (markdown), and MediaWiki (media) + + +Prerequisites +------------------------------------------------------------------------------ + +Make sure you have these settings in your vimrc file: + + 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) +------------------------------------------------------------------------------ + + 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) +------------------------------------------------------------------------------ cd ~/.vim mkdir bundle cd bundle - git clone git://github.com/vim-scripts/vimwiki.git + git clone https://github.com/vimwiki/vimwiki.git -Then launch vim, run `:Helptags` and then `:help vimwiki` to verify it was installed. +Installation using [Vim-Plug](https://github.com/junegunn/vim-plug) +------------------------------------------------------------------------------ + +Add the following to the plugin-configuration in your vimrc: + + 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 + + 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. + + +Getting help +============================================================================== + +Have a question? Visit the IRC channel `#vimwiki` on Freenode ([webchat](https://webchat.freenode.net/?channels=#vimwiki)) +or post to the [mailing list](https://groups.google.com/forum/#!forum/vimwiki). + + +---- +\* Screenshots made with the [solarized colorscheme](https://github.com/altercation/vim-colors-solarized) +and [lightline](https://github.com/itchyny/lightline.vim) diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim index ec4ae0b..7986609 100644 --- a/autoload/vimwiki/base.vim +++ b/autoload/vimwiki/base.vim @@ -1,297 +1,50 @@ -" 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 -" MISC helper functions {{{ -" s:normalize_path -function! s:normalize_path(path) "{{{ - let g:VimwikiLog.normalize_path += 1 "XXX - " resolve doesn't work quite right with symlinks ended with / or \ - let path = substitute(a:path, '[/\\]\+$', '', '') - if path !~# '^scp:' - return resolve(expand(path)).'/' - else - return path.'/' - endif -endfunction "}}} +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 -" s:path_html -function! s:path_html(idx) "{{{ - let path_html = VimwikiGet('path_html', a:idx) - if !empty(path_html) - return path_html - else - let g:VimwikiLog.path_html += 1 "XXX - let path = VimwikiGet('path', a:idx) - return substitute(path, '[/\\]\+$', '', '').'_html/' - endif -endfunction "}}} -function! vimwiki#base#get_known_extensions() " {{{ - " Getting all extensions that different wikis could have - let extensions = {} - for wiki in g:vimwiki_list - if has_key(wiki, 'ext') - let extensions[wiki.ext] = 1 - else - let extensions['.wiki'] = 1 - endif - endfor - " append map g:vimwiki_ext2syntax - for ext in keys(g:vimwiki_ext2syntax) - let extensions[ext] = 1 - endfor - return keys(extensions) -endfunction " }}} - -function! vimwiki#base#get_known_syntaxes() " {{{ +function! s:vimwiki_get_known_syntaxes() " Getting all syntaxes that different wikis could have let syntaxes = {} let syntaxes['default'] = 1 - for wiki in g:vimwiki_list - if has_key(wiki, 'syntax') - let syntaxes[wiki.syntax] = 1 - endif + 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 - " append map g:vimwiki_ext2syntax - for syn in values(g:vimwiki_ext2syntax) + " 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 " }}} -" }}} +endfunction -" vimwiki#base#apply_wiki_options -function! vimwiki#base#apply_wiki_options(options) " {{{ Update the current - " wiki using the options dictionary - for kk in keys(a:options) - let g:vimwiki_list[g:vimwiki_current_idx][kk] = a:options[kk] - endfor - call vimwiki#base#validate_wiki_options(g:vimwiki_current_idx) - call vimwiki#base#setup_buffer_state(g:vimwiki_current_idx) -endfunction " }}} -" vimwiki#base#read_wiki_options -function! vimwiki#base#read_wiki_options(check) " {{{ Attempt to read wiki - " options from the current page's directory, or its ancesters. If a file - " named vimwiki.vimrc is found, which declares a wiki-options dictionary - " named g:local_wiki, a message alerts the user that an update has been - " found and may be applied. If the argument check=1, the user is queried - " before applying the update to the current wiki's option. - - " Save global vimwiki options ... after all, the global list is often - " initialized for the first time in vimrc files, and we don't want to - " overwrite !! (not to mention all the other globals ...) - let l:vimwiki_list = deepcopy(g:vimwiki_list, 1) - " - if a:check > 1 - call vimwiki#base#print_wiki_state() - echo " \n" - endif - " - let g:local_wiki = {} - let done = 0 - " ... start the wild-goose chase! - for invsubdir in ['.', '..', '../..', '../../..'] - " other names are possible, but most vimrc files will cause grief! - for nm in ['vimwiki.vimrc'] - " TODO: use an alternate strategy, instead of source, to read options - if done - continue - endif - " - let local_wiki_options_filename = expand('%:p:h').'/'.invsubdir.'/'.nm - if !filereadable(local_wiki_options_filename) - continue - endif - " - echo "\nFound file : ".local_wiki_options_filename - let query = "Vimwiki: Check for options in this file [Y]es/[n]o? " - if a:check > 0 && (tolower(input(query)) !~ "y") - continue - endif - " - try - execute 'source '.local_wiki_options_filename - catch - endtry - if empty(g:local_wiki) - continue - endif - " - if a:check > 0 - echo "\n\nFound wiki options\n g:local_wiki = ".string(g:local_wiki) - let query = "Vimwiki: Apply these options [Y]es/[n]o? " - if tolower(input(query)) !~ "y" - let g:local_wiki = {} - continue - endif - endif - " - " restore global list - " - this prevents corruption by g:vimwiki_list in options_file - let g:vimwiki_list = deepcopy(l:vimwiki_list, 1) - " - call vimwiki#base#apply_wiki_options(g:local_wiki) - let done = 1 - endfor - endfor - if !done - " - " restore global list, if no local options were found - " - this prevents corruption by g:vimwiki_list in options_file - let g:vimwiki_list = deepcopy(l:vimwiki_list, 1) - " - endif - if a:check > 1 - echo " \n " - if done - call vimwiki#base#print_wiki_state() - else - echo "Vimwiki: No options were applied." - endif - endif -endfunction " }}} - -" vimwiki#base#validate_wiki_options -function! vimwiki#base#validate_wiki_options(idx) " {{{ Validate wiki options - " Only call this function *before* opening a wiki page. - " - " XXX: It's too early to update global / buffer variables, because they are - " still needed in their existing state for s:setup_buffer_leave() - "" let g:vimwiki_current_idx = a:idx - - " update normalized path & path_html - call VimwikiSet('path', s:normalize_path(VimwikiGet('path', a:idx)), a:idx) - call VimwikiSet('path_html', s:normalize_path(s:path_html(a:idx)), a:idx) - call VimwikiSet('template_path', - \ s:normalize_path(VimwikiGet('template_path', a:idx)), a:idx) - call VimwikiSet('diary_rel_path', - \ s:normalize_path(VimwikiGet('diary_rel_path', a:idx)), a:idx) - - " XXX: It's too early to update global / buffer variables, because they are - " still needed in their existing state for s:setup_buffer_leave() - "" call vimwiki#base#cache_buffer_state() -endfunction " }}} - -" vimwiki#base#setup_buffer_state -function! vimwiki#base#setup_buffer_state(idx) " {{{ Init page-specific variables - " Only call this function *after* opening a wiki page. - if a:idx < 0 - return - endif - - let g:vimwiki_current_idx = a:idx - - " The following state depends on the current active wiki page - let subdir = vimwiki#base#current_subdir(a:idx) - call VimwikiSet('subdir', subdir, a:idx) - call VimwikiSet('invsubdir', vimwiki#base#invsubdir(subdir), a:idx) - call VimwikiSet('url', vimwiki#html#get_wikifile_url(expand('%:p')), a:idx) - - " update cache - call vimwiki#base#cache_buffer_state() -endfunction " }}} - -" vimwiki#base#cache_buffer_state -function! vimwiki#base#cache_buffer_state() "{{{ - if !exists('g:vimwiki_current_idx') && g:vimwiki_debug - echo "[Vimwiki Internal Error]: Missing global state variable: 'g:vimwiki_current_idx'" - endif - let b:vimwiki_idx = g:vimwiki_current_idx -endfunction "}}} - -" vimwiki#base#recall_buffer_state -function! vimwiki#base#recall_buffer_state() "{{{ - if !exists('b:vimwiki_idx') - if g:vimwiki_debug - echo "[Vimwiki Internal Error]: Missing buffer state variable: 'b:vimwiki_idx'" - endif - return 0 - else - let g:vimwiki_current_idx = b:vimwiki_idx - return 1 - endif -endfunction " }}} - -" vimwiki#base#print_wiki_state -function! vimwiki#base#print_wiki_state() "{{{ print wiki options - " and buffer state variables - let g_width = 18 - let b_width = 18 - echo "- Wiki Options (idx=".g:vimwiki_current_idx.") -" - for kk in VimwikiGetOptionNames() - echo " '".kk."': ".repeat(' ', g_width-len(kk)).string(VimwikiGet(kk)) - endfor - if !exists('b:vimwiki_list') - return - endif - echo "- Cached Variables -" - for kk in keys(b:vimwiki_list) - echo " '".kk."': ".repeat(' ', b_width-len(kk)).string(b:vimwiki_list[kk]) - endfor -endfunction "}}} - -" vimwiki#base#mkdir -" If the optional argument 'confirm' == 1 is provided, -" vimwiki#base#mkdir will ask before creating a directory -function! vimwiki#base#mkdir(path, ...) "{{{ - let path = expand(a:path) - if path !~# '^scp:' - if !isdirectory(path) && exists("*mkdir") - let path = vimwiki#u#chomp_slash(path) - if vimwiki#u#is_windows() && !empty(g:vimwiki_w32_dir_enc) - let path = iconv(path, &enc, g:vimwiki_w32_dir_enc) - endif - if a:0 && a:1 && tolower(input("Vimwiki: Make new directory: ".path."\n [Y]es/[n]o? ")) !~ "y" - return 0 - endif - call mkdir(path, "p") - endif - return 1 - else - return 1 - endif -endfunction " }}} - -" vimwiki#base#file_pattern -function! vimwiki#base#file_pattern(files) "{{{ Get search regex from glob() +function! vimwiki#base#file_pattern(files) + " Get search regex from glob() " string. Aim to support *all* special characters, forcing the user to choose " names that are compatible with any external restrictions that they " encounter (e.g. filesystem, wiki conventions, other syntaxes, ...). - " See: http://code.google.com/p/vimwiki/issues/detail?id=316 - " Change / to [/\\] to allow "Windows paths" - " TODO: boundary cases ... - " e.g. "File$", "^File", "Fi]le", "Fi[le", "Fi\le", "Fi/le" - " XXX: (remove my comment if agreed) Maxim: with \V (very nomagic) boundary - " cases works for 1 and 2. - " 3, 4, 5 is not highlighted as links thus wouldn't be highlighted. - " 6 is a regular vimwiki link with subdirectory... - " - let pattern = vimwiki#base#branched_pattern(a:files,"\n") - return '\V'.pattern.'\m' -endfunction "}}} + " See: https://github.com/vimwiki-backup/vimwiki/issues/316 + " Change / to [/\\] to allow "Windows paths" + return '\V\%('.join(a:files, '\|').'\)\m' +endfunction -" vimwiki#base#branched_pattern -function! vimwiki#base#branched_pattern(string,separator) "{{{ get search regex -" from a string-list; separators assumed at start and end as well - let pattern = substitute(a:string, a:separator, '\\|','g') - let pattern = substitute(pattern, '\%^\\|', '\\%(','') - let pattern = substitute(pattern,'\\|\%$', '\\)','') - return pattern -endfunction "}}} -" vimwiki#base#subdir "FIXME TODO slow and faulty -function! vimwiki#base#subdir(path, filename) "{{{ - let g:VimwikiLog.subdir += 1 "XXX +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? @@ -312,164 +65,197 @@ function! vimwiki#base#subdir(path, filename) "{{{ let res = res.'/' endif return res -endfunction "}}} +endfunction -" vimwiki#base#current_subdir -function! vimwiki#base#current_subdir(idx)"{{{ - return vimwiki#base#subdir(VimwikiGet('path', a:idx), expand('%:p')) -endfunction"}}} -" vimwiki#base#invsubdir -function! vimwiki#base#invsubdir(subdir) " {{{ +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 " }}} +endfunction -" vimwiki#base#resolve_scheme -function! vimwiki#base#resolve_scheme(lnk, as_html) " {{{ Resolve scheme - let lnk = a:lnk - " a link starting with # means current file with an anchor - if lnk =~ '^#' - let lnk = expand('%:t:r').lnk - endif - - " if link is schemeless add wikiN: scheme - let is_schemeless = lnk !~ g:vimwiki_rxSchemeUrl - let lnk = (is_schemeless ? 'wiki'.g:vimwiki_current_idx.':'.lnk : lnk) - - " Get scheme - let scheme = matchstr(lnk, g:vimwiki_rxSchemeUrlMatchScheme) - " Get link (without scheme) - let lnk = matchstr(lnk, g:vimwiki_rxSchemeUrlMatchUrl) - let path = '' - let subdir = '' - let ext = '' - let idx = -1 - let anchor = '' - - "extract anchor - if scheme =~ 'wiki' || scheme =~ 'diary' - let split_lnk = split(lnk, '#', 1) - let lnk = split_lnk[0] - if len(split_lnk) <= 1 || split_lnk[-1] == '' - let anchor = '' - else - let anchor = join(split_lnk[1:], '#') - endif - endif - - " do nothing if scheme is unknown to vimwiki - if !(scheme =~ 'wiki.*' || scheme =~ 'diary' || scheme =~ 'local' - \ || scheme =~ 'file') - return [idx, scheme, path, subdir, lnk, ext, scheme.':'.lnk, anchor] - endif - - " scheme behaviors - if scheme =~ 'wiki\d\+' - let idx = eval(matchstr(scheme, '\D\+\zs\d\+\ze')) - if idx < 0 || idx >= len(g:vimwiki_list) - echom 'Vimwiki Error: Numbered scheme refers to a non-existent wiki!' - return [idx,'','','','','','', ''] - else - if idx != g:vimwiki_current_idx - call vimwiki#base#validate_wiki_options(idx) +" 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 - if a:as_html - if idx == g:vimwiki_current_idx - let path = VimwikiGet('path_html') - else - let path = VimwikiGet('path_html', idx) - endif - else - if idx == g:vimwiki_current_idx - let path = VimwikiGet('path') - else - let path = VimwikiGet('path', idx) - endif - endif - - " For Issue 310. Otherwise current subdir is used for another wiki. - if idx == g:vimwiki_current_idx - let subdir = VimwikiGet('subdir') - else - let subdir = "" - endif - - if a:as_html - let ext = '.html' - else - if idx == g:vimwiki_current_idx - let ext = VimwikiGet('ext') - else - let ext = VimwikiGet('ext', idx) - endif - endif - - " default link for directories - if vimwiki#u#is_link_to_dir(lnk) - let ext = (g:vimwiki_dir_link != '' ? g:vimwiki_dir_link. ext : '') - endif - elseif scheme =~ 'diary' - if a:as_html - " use cached value (save time when converting diary index!) - let path = VimwikiGet('invsubdir') - let ext = '.html' - else - let path = VimwikiGet('path') - let ext = VimwikiGet('ext') - endif - let subdir = VimwikiGet('diary_rel_path') - elseif scheme =~ 'local' - " revisiting the 'lcd'-bug ... - let path = VimwikiGet('path') - let subdir = VimwikiGet('subdir') - if a:as_html - " prepend browser-specific file: scheme - let path = 'file://'.fnamemodify(path, ":p") - endif - elseif scheme =~ 'file' - " RM repeated leading "/"'s within a link - let lnk = substitute(lnk, '^/*', '/', '') - " convert "/~..." into "~..." for fnamemodify - let lnk = substitute(lnk, '^/\~', '\~', '') - " convert /C: to C: (or fnamemodify(...":p:h") interpret it as C:\C: - if vimwiki#u#is_windows() - let lnk = substitute(lnk, '^/\ze[[:alpha:]]:', '', '') - endif - if a:as_html - " prepend browser-specific file: scheme - let path = 'file://'.fnamemodify(lnk, ":p:h").'/' - else - let path = fnamemodify(lnk, ":p:h").'/' - endif - let lnk = fnamemodify(lnk, ":p:t") - let subdir = '' - endif + return bestmatch +endfunction - " construct url from parts - if is_schemeless && a:as_html - let scheme = '' - let url = lnk.ext +" 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 - let url = path.subdir.lnk.ext + let source_wiki = vimwiki#vars#get_bufferlocal('wiki_nr') + let source_file = vimwiki#path#current_wiki_file() endif - " result - return [idx, scheme, path, subdir, lnk, ext, url, anchor] -endfunction "}}} + let link_text = a:link_text -" vimwiki#base#system_open_link -function! vimwiki#base#system_open_link(url) "{{{ + + 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 + + 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) - "http://vim.wikia.com/wiki/Opening_current_Vim_file_in_your_Windows_browser - execute 'silent ! start "Title" /B ' . shellescape(a:url, 1) + "Disable shellslash for cmd and command.com, but enable for all other shells + "See Issue #560 + if (&shell =~? "cmd") || (&shell =~? "command.com") + + if exists('+shellslash') + let old_ssl = &shellslash + set noshellslash + let url = shellescape(a:url, 1) + let &shellslash = old_ssl + else + let url = shellescape(a:url, 1) + endif + execute 'silent ! start "Title" /B ' . url + + else + + if exists('+shellslash') + let old_ssl = &shellslash + set shellslash + let url = shellescape(a:url, 1) + let &shellslash = old_ssl + else + let url = shellescape(a:url, 1) + endif + execute 'silent ! start ' . url + + endif endfunction function! s:macunix_handler(url) - execute '!open ' . shellescape(a:url, 1) + call system('open ' . shellescape(a:url).' &') endfunction function! s:linux_handler(url) call system('xdg-open ' . shellescape(a:url).' &') @@ -478,7 +264,7 @@ function! vimwiki#base#system_open_link(url) "{{{ if vimwiki#u#is_windows() call s:win32_handler(a:url) return - elseif has("macunix") + elseif vimwiki#u#is_macos() call s:macunix_handler(a:url) return else @@ -486,256 +272,525 @@ function! vimwiki#base#system_open_link(url) "{{{ return endif endtry - echomsg 'Default Vimwiki link handler was unable to open the HTML file!' -endfunction "}}} + echomsg 'Vimwiki Error: Default Vimwiki link handler was unable to open the HTML file!' +endfunction -" vimwiki#base#open_link -function! vimwiki#base#open_link(cmd, link, ...) "{{{ - let [idx, scheme, path, subdir, lnk, ext, url, anchor] = - \ vimwiki#base#resolve_scheme(a:link, 0) - if url == '' - if g:vimwiki_debug - echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url.', anchor='.anchor +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 - echom 'Vimwiki Error: Unable to resolve link!' return endif - let update_prev_link = ( (scheme == '' || scheme =~ 'wiki' || scheme =~ 'diary') - \ && lnk != expand('%:t:r') - \ ? 1 : 0) + let is_wiki_link = link_infos.scheme =~# '\mwiki\d\+' || link_infos.scheme =~# 'diary' - let use_system_open = ( - \ scheme == '' || - \ scheme =~ 'wiki' || - \ scheme =~ 'diary' ? 0 : 1) + 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 = [expand('%:p'), getpos('.')] + elseif &ft ==# 'vimwiki' + let vimwiki_prev_link = [vimwiki#path#current_wiki_file(), getpos('.')] endif endif " open/edit - if g:vimwiki_debug - echom 'open_link: idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url.'anchor='.anchor - endif - - if use_system_open - call vimwiki#base#system_open_link(url) - else - call vimwiki#base#edit_file(a:cmd, url, anchor, + if is_wiki_link + call vimwiki#base#edit_file(a:cmd, link_infos.filename, link_infos.anchor, \ vimwiki_prev_link, update_prev_link) - if idx != g:vimwiki_current_idx - " this call to setup_buffer_state may not be necessary - call vimwiki#base#setup_buffer_state(idx) - endif + else + call vimwiki#base#system_open_link(link_infos.filename) endif -endfunction " }}} +endfunction -" vimwiki#base#generate_links -function! vimwiki#base#generate_links() "{{{only get links from the current dir + +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('*'.VimwikiGet('ext'),1)."\n" + " 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, '\'.VimwikiGet('ext').'\ze\n', '', 'g') + 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 - " We don't want link to itself. XXX Why ??? - " let cur_link = expand('%:t:r') - " call filter(links, 'v:val != cur_link') - let links = split(globlinks,"\n") - call append(line('$'), substitute(g:vimwiki_rxH1_Template, '__Header__', 'Generated Links', '')) +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().' ' + let bullet = repeat(' ', vimwiki#lst#get_list_margin()) . vimwiki#lst#default_symbol().' ' for link in links - call append(line('$'), bullet. - \ substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', '\='."'".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 " }}} -" vimwiki#base#goto -function! vimwiki#base#goto(...) "{{{ + 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! vimwiki#base#goto(...) let key = a:1 let anchor = a:0 > 1 ? a:2 : '' call vimwiki#base#edit_file(':e', - \ VimwikiGet('path'). - \ key. - \ VimwikiGet('ext'), + \ vimwiki#vars#get_wikilocal('path') . key . vimwiki#vars#get_wikilocal('ext'), \ anchor) -endfunction "}}} +endfunction -" vimwiki#base#backlinks -function! vimwiki#base#backlinks() "{{{ - let filename = expand("%:t:r") - let rx_wikilink = vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate1, - \ '\zs'.filename.'\ze\%(#.*\)\?', '.*', ''). - \ '\|'. vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate2, - \ '\zs'.filename.'\ze\%(#.*\)\?', '.*', '') - execute 'lvimgrep "\C'.rx_wikilink.'" '. - \ escape(VimwikiGet('path').'**/*'.VimwikiGet('ext'), ' ') -endfunction "}}} -" vimwiki#base#get_links -function! vimwiki#base#get_links(pat) "{{{ return string-list for files - " in the current wiki matching the pattern "pat" - " search all wiki files (or directories) in wiki 'path' and its subdirs. +function! 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 - let time1 = reltime() " start the clock + if empty(locations) + echomsg 'Vimwiki: No other file links to this file' + else + call setloclist(0, locations, 'r') + lopen + endif +endfunction - " XXX: - " if maxhi = 1 and ww before loading any vimwiki file - " cached 'subdir' is not set up - try - let subdir = VimwikiGet('subdir') - " FIXED: was previously converting './' to '../' - let invsubdir = VimwikiGet('invsubdir') - catch - let subdir = '' - let invsubdir = '' - endtry +" 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 = "\n".glob(VimwikiGet('path').search_dirs.a:pat,1)."\n" - - "save pwd, do lcd %:h, restore old pwd; getcwd() - " change to the directory of the current file - let orig_pwd = getcwd() - - " calling from other than vimwiki file - let path_base = vimwiki#u#path_norm(vimwiki#u#chomp_slash(VimwikiGet('path'))) - let path_file = vimwiki#u#path_norm(vimwiki#u#chomp_slash(expand('%:p:h'))) + return split(globpath(root_directory, pattern), '\n') +endfunction - if vimwiki#u#path_common_pfx(path_file, path_base) != path_base - exe 'lcd! '.path_base + +" 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 - lcd! %:p:h + let cwd = vimwiki#vars#get_wikilocal('path', a:wiki_nr) endif - - " all path are relative to the current file's location - let globlinks = "\n".glob(invsubdir.search_dirs.a:pat,1)."\n" - " remove extensions - let globlinks = substitute(globlinks,'\'.VimwikiGet('ext').'\ze\n', '', 'g') - " standardize path separators on Windows - let globlinks = substitute(globlinks,'\\', '/', 'g') - - " shortening those paths ../../dir1/dir2/ that can be shortened - " first for the current directory, then for parent etc. - let sp_rx = '\n\zs' . invsubdir . subdir . '\ze' - for i in range(len(invsubdir)/3) "XXX multibyte? - let globlinks = substitute(globlinks, sp_rx, '', 'g') - let sp_rx = substitute(sp_rx,'\\zs../','../\\zs','') - let sp_rx = substitute(sp_rx,'[^/]\+/\\ze','\\ze','') + 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 - " for directories: add ./ (instead of now empty) and invsubdir (if distinct) - if a:pat == '*/' - let globlinks = substitute(globlinks, "\n\n", "\n./\n",'') - if invsubdir != '' - let globlinks .= invsubdir."\n" - else - let globlinks .= "./\n" + 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 + + +" 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 + + +function! vimwiki#base#get_anchors(filename, syntax) + if !filereadable(a:filename) + return [] endif - " restore the original working directory - exe 'lcd! '.orig_pwd + 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 time2 = vimwiki#u#time(time1) - call VimwikiLog_extend('timing',['base:afterglob('.len(split(globlinks, '\n')).')',time2]) - return globlinks -endfunction "}}} + let anchor_level = ['', '', '', '', '', '', ''] + let anchors = [] + let current_complete_anchor = '' + for line in readfile(a:filename) -" s:jump_to_anchor -function! s:jump_to_anchor(anchor) "{{{ + " 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 = substitute( - \ g:vimwiki_{VimwikiGet('syntax')}_header_match, - \ '__Header__', "\\='".segment."'", '') - let anchor_bold = substitute(g:vimwiki_{VimwikiGet('syntax')}_bold_match, - \ '__Text__', "\\='".segment."'", '') + 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_header, 'W') && !search(anchor_bold, 'W') + if !search(anchor_tag, 'Wc') && !search(anchor_header, 'Wc') && !search(anchor_bold, 'Wc') call setpos('.', oldpos) break endif let oldpos = getpos('.') endfor -endfunction "}}} +endfunction -" vimwiki#base#edit_file -function! vimwiki#base#edit_file(command, filename, anchor, ...) "{{{ - " XXX: Should we allow * in filenames!? - " Maxim: It is allowed, escaping here is for vim to be able to open files - " which have that symbols. - " Try to remove * from escaping and open&save : - " [[testBLAfile]]... - " then - " [[test*file]]... - " you'll have E77: Too many file names - let fname = escape(a:filename, '% *|#') - let dir = fnamemodify(a:filename, ":p:h") - if vimwiki#base#mkdir(dir, 1) - " 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 ' && a:filename == expand('%:p')) - execute a:command.' '.fname + +" 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 + + 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#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 - if a:anchor != '' - call s:jump_to_anchor(a:anchor) + 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 - echom ' ' - echom 'Vimwiki: Unable to edit file in non-existent directory: '.dir + call setqflist(errors, 'r') + copen + endif +endfunction + + +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 - let b:vimwiki_prev_link = a:1 + call vimwiki#vars#set_bufferlocal('prev_link', a:1) endif -endfunction " }}} +endfunction -" vimwiki#base#search_word -function! vimwiki#base#search_word(wikiRx, cmd) "{{{ + +function! vimwiki#base#search_word(wikiRx, cmd) let match_line = search(a:wikiRx, 's'.a:cmd) if match_line == 0 - echomsg 'vimwiki: Wiki link not found.' + echomsg 'Vimwiki: Wiki link not found' endif -endfunction " }}} +endfunction + -" vimwiki#base#matchstr_at_cursor " Returns part of the line that matches wikiRX at cursor -function! vimwiki#base#matchstr_at_cursor(wikiRX) "{{{ +function! vimwiki#base#matchstr_at_cursor(wikiRX) let col = col('.') - 1 let line = getline('.') let ebeg = -1 @@ -755,10 +810,10 @@ function! vimwiki#base#matchstr_at_cursor(wikiRX) "{{{ else return "" endif -endf "}}} +endfunction -" vimwiki#base#replacestr_at_cursor -function! vimwiki#base#replacestr_at_cursor(wikiRX, sub) "{{{ + +function! vimwiki#base#replacestr_at_cursor(wikiRX, sub) let col = col('.') - 1 let line = getline('.') let ebeg = -1 @@ -778,27 +833,27 @@ function! vimwiki#base#replacestr_at_cursor(wikiRX, sub) "{{{ let newline = strpart(line, 0, ebeg).a:sub.strpart(line, ebeg+elen) call setline(line('.'), newline) endif -endf "}}} +endfunction -" s:print_wiki_list -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 " }}} +endfunction -" s:update_wiki_link -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 = [] @@ -815,40 +870,38 @@ function! s:update_wiki_link(fname, old, new) " {{{ call writefile(dest, a:fname) call delete(a:fname.'#vimwiki_upd#') endif -endfunction " }}} +endfunction -" s:update_wiki_links_dir -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 - let old_fname_r = vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate1, - \ '\zs'.old_fname.'\ze\%(#.*\)\?', '.*', ''). - \ '\|'. vimwiki#base#apply_template(g:vimwiki_WikiLinkTemplate2, - \ '\zs'.old_fname.'\ze\%(#.*\)\?', '.*', '') + let old_fname_r = vimwiki#base#apply_template( + \ vimwiki#vars#get_syntaxlocal('WikiLinkMatchUrlTemplate', + \ vimwiki#vars#get_wikilocal('syntax', a:wiki_nr)), old_fname, '', '') - 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 " }}} +endfunction -" s:tail_name -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 -" s:update_wiki_links -function! s:update_wiki_links(old_fname, new_fname) " {{{ + +function! s:update_wiki_links(wiki_nr, old_fname, new_fname,old_fname_relpath) let old_fname = a:old_fname let new_fname = a:new_fname - let subdirs = split(a:old_fname, '[/\\]')[: -2] + let subdirs = split(a:old_fname_relpath, '[/\\]')[: -2] " TODO: Use Dictionary here... let dirs_keys = [''] @@ -870,39 +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 -" s:get_wiki_buffers -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 " }}} +endfunction -" s:open_wiki_buffer -function! s:open_wiki_buffer(item) "{{{ + +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]) + call vimwiki#vars#set_bufferlocal('prev_link', a:item[1], a:item[0]) endif -endfunction " }}} +endfunction -" vimwiki#base#nested_syntax -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 @@ -932,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.'"'. @@ -941,104 +1003,231 @@ 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 "}}} +endfunction -" WIKI link following functions {{{ -" vimwiki#base#find_next_link -function! vimwiki#base#find_next_link() "{{{ - call vimwiki#base#search_word(g:vimwiki_rxAnyLink, '') -endfunction " }}} -" vimwiki#base#find_prev_link -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(g:vimwiki_rxAnyLink, 'b') +" 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 - call vimwiki#base#search_word(g:vimwiki_rxAnyLink, 'b') -endfunction " }}} -" vimwiki#base#follow_link -function! vimwiki#base#follow_link(split, ...) "{{{ Parse link at cursor and pass - " to VimwikiLinkHandler, or failing that, the default open_link handler - if exists('*vimwiki#'.VimwikiGet('syntax').'_base#follow_link') - " Syntax-specific links - " XXX: @Stuart: do we still need it? - " XXX: @Maxim: most likely! I am still working on a seemless way to - " integrate regexp's without complicating syntax/vimwiki.vim - if a:0 - call vimwiki#{VimwikiGet('syntax')}_base#follow_link(a:split, a:1) - else - call vimwiki#{VimwikiGet('syntax')}_base#follow_link(a:split) + " 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 - if a:split == "split" + 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 + + if is_cursor_after_listing + let winview_save.lnum += lines_diff + endif + call winrestview(winview_save) +endfunction + + +function! vimwiki#base#find_next_link() + call vimwiki#base#search_word(vimwiki#vars#get_syntaxlocal('rxAnyLink'), '') +endfunction + + +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, ...) + 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 + + 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" + elseif a:split ==# "vsplit" let cmd = ":vsplit " - elseif a:split == "tabnew" + elseif a:split ==# "tab" let cmd = ":tabnew " else let cmd = ":e " endif - " try WikiLink - let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiLink), - \ g:vimwiki_rxWikiLinkMatchUrl) - " try WikiIncl - if lnk == "" - let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiIncl), - \ g:vimwiki_rxWikiInclMatchUrl) - endif - " try Weblink - if lnk == "" - let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWeblink), - \ g:vimwiki_rxWeblinkMatchUrl) - endif - - if lnk != "" - if !VimwikiLinkHandler(lnk) - call vimwiki#base#open_link(cmd, lnk) + " 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 - return endif - if a:0 > 0 - execute "normal! ".a:1 - else + + 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 endif +endfunction -endfunction " }}} -" vimwiki#base#go_back_link -function! vimwiki#base#go_back_link() "{{{ - if exists("b:vimwiki_prev_link") +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 - let prev_word = b:vimwiki_prev_link - execute ":e ".substitute(prev_word[0], '\s', '\\\0', 'g') - call setpos('.', prev_word[1]) + 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 " }}} +endfunction -" vimwiki#base#goto_index -function! vimwiki#base#goto_index(wnum, ...) "{{{ - if a:wnum > len(g:vimwiki_list) - echom "vimwiki: Wiki ".a:wnum." is not registered in g:vimwiki_list!" + +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 "exe 'VimwikiIndex' | echo g:vimwiki_current_idx" + " vim -n -c ":VimwikiIndex" if a:wnum > 0 let idx = a:wnum - 1 else @@ -1046,36 +1235,36 @@ function! vimwiki#base#goto_index(wnum, ...) "{{{ endif if a:0 - let cmd = 'tabedit' + 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 - if g:vimwiki_debug == 3 - echom "--- Goto_index g:curr_idx=".g:vimwiki_current_idx." ww_idx=".idx."" - endif + let index_file = vimwiki#vars#get_wikilocal('path', idx). + \ vimwiki#vars#get_wikilocal('index', idx). + \ vimwiki#vars#get_wikilocal('ext', idx) - call vimwiki#base#validate_wiki_options(idx) - call vimwiki#base#edit_file(cmd, - \ VimwikiGet('path', idx).VimwikiGet('index', idx). - \ VimwikiGet('ext', idx), - \ '') - call vimwiki#base#setup_buffer_state(idx) -endfunction "}}} + call vimwiki#base#edit_file(cmd, index_file, '') +endfunction -" vimwiki#base#delete_link -function! vimwiki#base#delete_link() "{{{ - "" file system funcs - "" Delete wiki link 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 @@ -1086,71 +1275,68 @@ function! vimwiki#base#delete_link() "{{{ if expand('%:p') != "" execute "e" endif -endfunction "}}} +endfunction -" vimwiki#base#rename_link -function! vimwiki#base#rename_link() "{{{ - "" Rename wiki link, update all links to renamed WikiWord - let subdir = VimwikiGet('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 - let url = matchstr(new_link, g:vimwiki_rxWikiLinkMatchUrl) + 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_fname = VimwikiGet('path').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 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 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() @@ -1171,82 +1357,88 @@ function! vimwiki#base#rename_link() "{{{ setlocal nomore " update links - call s:update_wiki_links(s:tail_name(old_fname), new_link) + call s:update_wiki_links(wiki_nr, s:tail_name(old_fname), s:tail_name(new_link),old_fname) " restore wiki buffers for bitem in blist - 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 -" vimwiki#base#ui_select -function! vimwiki#base#ui_select() "{{{ + +function! vimwiki#base#ui_select() call s:print_wiki_list() let idx = input("Select Wiki (specify number): ") if idx == "" return endif call vimwiki#base#goto_index(idx) -endfunction "}}} -" }}} +endfunction -" TEXT OBJECTS functions {{{ -" vimwiki#base#TO_header -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#u#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 - - if a:visual && is_header_selected - call cursor(sel_end + advance, 0) - endif - - if search('^\(=\{1,'.level.'}\).\+\1\s*$', 'W') - call cursor(line('.') - 1, 0) + " 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 - call cursor(line('$'), 0) + 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 + + 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 a:inner && getline(line('.')) =~ '^\s*$' - let lnum = prevnonblank(line('.') - 1) - call cursor(lnum, 0) + if a:inner + let first_line += 1 + let last_line = prevnonblank(last_line) endif -endfunction "}}} -" vimwiki#base#TO_table_cell -function! vimwiki#base#TO_table_cell(inner, visual) "{{{ + 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) if col('.') == col('$')-1 return endif @@ -1290,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 @@ -1308,10 +1500,10 @@ function! vimwiki#base#TO_table_cell(inner, visual) "{{{ normal! 2h endif endif -endfunction "}}} +endfunction -" vimwiki#base#TO_table_col -function! vimwiki#base#TO_table_col(inner, visual) "{{{ + +function! vimwiki#base#TO_table_col(inner, visual) let t_rows = vimwiki#tbl#get_rows(line('.')) if empty(t_rows) return @@ -1335,7 +1527,7 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ " | 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' @@ -1358,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 @@ -1389,7 +1581,7 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ " | 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' @@ -1423,23 +1615,21 @@ function! vimwiki#base#TO_table_col(inner, visual) "{{{ " expand selection to the bottom line of the table call vimwiki#u#cursor(t_rows[-1][0], virtcol('.')) endif -endfunction "}}} -" }}} +endfunction -" HEADER functions {{{ -" vimwiki#base#AddHeaderLevel -function! vimwiki#base#AddHeaderLevel() "{{{ + +function! vimwiki#base#AddHeaderLevel() let lnum = line('.') let line = getline(lnum) - let rxHdr = g:vimwiki_rxH - if line =~ '^\s*$' + let rxHdr = vimwiki#vars#get_syntaxlocal('rxH') + if line =~# '^\s*$' return endif - if line =~ g:vimwiki_rxHeader + if line =~# vimwiki#vars#get_syntaxlocal('rxHeader') let level = vimwiki#u#count_first_sym(line) if level < 6 - if g:vimwiki_symH + if vimwiki#vars#get_syntaxlocal('symH') let line = substitute(line, '\('.rxHdr.'\+\).\+\1', rxHdr.'&'.rxHdr, '') else let line = substitute(line, '\('.rxHdr.'\+\).\+', rxHdr.'&', '') @@ -1447,31 +1637,31 @@ function! vimwiki#base#AddHeaderLevel() "{{{ call setline(lnum, line) endif else - let line = substitute(line, '^\s*', '&'.rxHdr.' ', '') - if g:vimwiki_symH + 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 "}}} +endfunction -" vimwiki#base#RemoveHeaderLevel -function! vimwiki#base#RemoveHeaderLevel() "{{{ + +function! vimwiki#base#RemoveHeaderLevel() let lnum = line('.') let line = getline(lnum) - let rxHdr = g:vimwiki_rxH - if line =~ '^\s*$' + let rxHdr = vimwiki#vars#get_syntaxlocal('rxH') + if line =~# '^\s*$' return endif - if line =~ g:vimwiki_rxHeader + 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 =~ rxHdr.'\s' + let chomp = line =~# rxHdr.'\s' - if g:vimwiki_symH + if vimwiki#vars#get_syntaxlocal('symH') let line = substitute(line, old, new, 'g') else let line = substitute(line, old, new, '') @@ -1486,55 +1676,167 @@ function! vimwiki#base#RemoveHeaderLevel() "{{{ call setline(lnum, line) endif -endfunction " }}} +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') - " look for existing TOC - let toc_header = '^\s*'.substitute(g:vimwiki_rxH1_Template, '__Header__', - \ '\='."'".g:vimwiki_toc_header."'", '').'\s*$' - let toc_line = 0 - let lnum = 1 - while lnum <= &modelines + 2 && lnum <= line('$') - if getline(lnum) =~# toc_header - let toc_line = lnum - break + 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 - let lnum += 1 - endwhile - - if !a:create && toc_line <= 0 - return endif - let old_cursor_pos = getpos('.') - let bullet = vimwiki#lst#default_symbol().' ' - let rx_bullet = vimwiki#u#escape(bullet) - let whitespaces = matchstr(getline(toc_line), '^\s*') - - " delete old TOC - if toc_line > 0 - let endoftoc = toc_line+1 - while endoftoc <= line('$') && getline(endoftoc) =~ '^\s*'.rx_bullet.g:vimwiki_rxWikiLink.'\s*$' - let endoftoc += 1 - endwhile - silent exe toc_line.','.string(endoftoc-1).'delete _' - else - let toc_line = 1 - endif - - " collect new headers - let headers = [] + let numbering = vimwiki#vars#get_global('html_header_numbering') let headers_levels = [['', 0], ['', 0], ['', 0], ['', 0], ['', 0], ['', 0]] - for lnum in range(1, line('$')) - let line_content = getline(lnum) - if line_content !~ g:vimwiki_rxHeader + 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 h_level = vimwiki#u#count_first_sym(line_content) - let h_text = vimwiki#u#trim(matchstr(line_content, g:vimwiki_rxHeader)) 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 @@ -1546,187 +1848,249 @@ function! vimwiki#base#table_of_contents(create) endfor let h_complete_id .= headers_levels[h_level-1][0] - if g:vimwiki_html_header_numbering > 0 - \ && g:vimwiki_html_header_numbering <= h_level - let h_number = join(map(copy(headers_levels[ - \ g:vimwiki_html_header_numbering-1 : h_level-1]), 'v:val[1]'), '.') - let h_number .= g:vimwiki_html_header_numbering_sym + 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(headers, [h_level, h_complete_id, h_text]) + call add(complete_header_infos, [h_level, h_complete_id, h_text]) endfor - " write new TOC - call append(toc_line-1, whitespaces . substitute(g:vimwiki_rxH1_Template, - \ '__Header__', '\='."'".g:vimwiki_toc_header."'", '')) - + let lines = [] let startindent = repeat(' ', vimwiki#lst#get_list_margin()) - let indentstring = repeat(' ', &shiftwidth) - for [lvl, link, desc] in headers - let esc_link = substitute(link, "'", "''", 'g') - let esc_desc = substitute(desc, "'", "''", 'g') - let link = substitute(g:vimwiki_WikiLinkTemplate2, '__LinkUrl__', - \ '\='."'".'#'.esc_link."'", '') - let link = substitute(link, '__LinkDescription__', '\='."'".esc_desc."'", '') - call append(toc_line, startindent.repeat(indentstring, lvl-1).bullet.link) - let toc_line += 1 + 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 - if getline(toc_line+1) !~ '^\s*$' - call append(toc_line, '') - endif - call setpos('.', old_cursor_pos) -endfunction -"}}} -" LINK functions {{{ -" vimwiki#base#apply_template + 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 = vimwiki#u#escape(a:template) +function! vimwiki#base#apply_template(template, rxUrl, rxDesc, rxStyle) + let lnk = a:template if a:rxUrl != "" - let lnk = substitute(lnk, '__LinkUrl__', '\='."'".a:rxUrl."'", '') + let lnk = s:safesubstitute(lnk, '__LinkUrl__', a:rxUrl, 'g') endif if a:rxDesc != "" - let lnk = substitute(lnk, '__LinkDescription__', '\='."'".a:rxDesc."'", '') + let lnk = s:safesubstitute(lnk, '__LinkDescription__', a:rxDesc, 'g') endif if a:rxStyle != "" - let lnk = substitute(lnk, '__LinkStyle__', '\='."'".a:rxStyle."'", '') + let lnk = s:safesubstitute(lnk, '__LinkStyle__', a:rxStyle, 'g') endif return lnk -endfunction " }}} +endfunction -" s:clean_url -function! s:clean_url(url) " {{{ - let url = split(a:url, '/\|=\|-\|&\|?\|\.') - let url = filter(url, 'v:val != ""') - let url = filter(url, 'v:val != "www"') - let url = filter(url, 'v:val != "com"') - let url = filter(url, 'v:val != "org"') - let url = filter(url, 'v:val != "net"') - let url = filter(url, 'v:val != "edu"') - let url = filter(url, 'v:val != "http\:"') - let url = filter(url, 'v:val != "https\:"') - let url = filter(url, 'v:val != "file\:"') - let url = filter(url, 'v:val != "xml\:"') + +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 " }}} +endfunction -" vimwiki#base#normalize_link_helper -function! vimwiki#base#normalize_link_helper(str, rxUrl, rxDesc, template) " {{{ - let str = a:str - let url = matchstr(str, a:rxUrl) - let descr = matchstr(str, a:rxDesc) - let template = a:template + +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 = substitute(template, '__LinkDescription__', '\="'.descr.'"', '') - let lnk = substitute(lnk, '__LinkUrl__', '\="'.url.'"', '') + let lnk = s:safesubstitute(a:template, '__LinkDescription__', descr, '') + let lnk = s:safesubstitute(lnk, '__LinkUrl__', url, '') return lnk -endfunction " }}} +endfunction -" vimwiki#base#normalize_imagelink_helper -function! vimwiki#base#normalize_imagelink_helper(str, rxUrl, rxDesc, rxStyle, template) "{{{ + +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 = substitute(lnk, '__LinkStyle__', '\="'.style.'"', '') + let lnk = s:safesubstitute(lnk, '__LinkStyle__', style, '') return lnk -endfunction " }}} +endfunction -" s:normalize_link_syntax_n -function! s:normalize_link_syntax_n() " {{{ + +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(g:vimwiki_rxWikiLink) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink')) if !empty(lnk) let sub = vimwiki#base#normalize_link_helper(lnk, - \ g:vimwiki_rxWikiLinkMatchUrl, g:vimwiki_rxWikiLinkMatchDescr, - \ g:vimwiki_WikiLinkTemplate2) - call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWikiLink, sub) - if g:vimwiki_debug > 1 - echomsg "WikiLink: ".lnk." Sub: ".sub - endif + \ 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(g:vimwiki_rxWikiIncl) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_global('rxWikiIncl')) if !empty(lnk) " NO-OP !! - if g:vimwiki_debug > 1 - echomsg "WikiIncl: ".lnk." Sub: ".lnk - endif + 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(g:vimwiki_rxWord) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_global('rxWord')) if !empty(lnk) - let sub = vimwiki#base#normalize_link_helper(lnk, - \ g:vimwiki_rxWord, '', - \ g:vimwiki_WikiLinkTemplate1) - call vimwiki#base#replacestr_at_cursor('\V'.lnk, sub) - if g:vimwiki_debug > 1 - echomsg "Word: ".lnk." Sub: ".sub + 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 " }}} +endfunction -" s:normalize_link_syntax_v -function! s:normalize_link_syntax_v() " {{{ + +function! s:normalize_link_syntax_v() let sel_save = &selection let &selection = "old" - let rv = @" - let rt = getregtype('"') + let default_register_save = @" + let registertype_save = getregtype('"') try - norm! gv""y - let visual_selection = @" - let visual_selection = substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', '\='."'".visual_selection."'", '') + " Save selected text to register " + normal! gv""y - call setreg('"', visual_selection, 'v') - - " paste result - norm! `>""pgvd + " 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('"', rv, rt) + call setreg('"', default_register_save, registertype_save) let &selection = sel_save endtry +endfunction -endfunction " }}} -" vimwiki#base#normalize_link -function! vimwiki#base#normalize_link(is_visual_mode) "{{{ - if exists('*vimwiki#'.VimwikiGet('syntax').'_base#normalize_link') +function! vimwiki#base#normalize_link(is_visual_mode) + if exists('*vimwiki#'.vimwiki#vars#get_wikilocal('syntax').'_base#normalize_link') " Syntax-specific links - call vimwiki#{VimwikiGet('syntax')}_base#normalize_link(a:is_visual_mode) + 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 visualmode() ==# 'v' && line("'<") == line("'>") - " action undefined for 'line-wise' or 'multi-line' visual mode selections + elseif line("'<") == line("'>") + " action undefined for multi-line visual mode selections call s:normalize_link_syntax_v() endif endif -endfunction "}}} +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 vimwiki#base#get_known_syntaxes() +for s:syn in s:vimwiki_get_known_syntaxes() execute 'runtime! autoload/vimwiki/'.s:syn.'_base.vim' -endfor +endfor " ------------------------------------------------------------------------- - diff --git a/autoload/vimwiki/customwiki2html.sh b/autoload/vimwiki/customwiki2html.sh index c5960b1..6b0c17a 100755 --- a/autoload/vimwiki/customwiki2html.sh +++ b/autoload/vimwiki/customwiki2html.sh @@ -6,7 +6,7 @@ # commenting / uncommenting the relevant lines below. # # NEW! An alternative converter was developed by Jason6Anderson, and can -# be located at http://code.google.com/p/vimwiki/issues/detail?id=384 +# be located at https://github.com/vimwiki-backup/vimwiki/issues/384 # # # To use this script, you must have the Discount converter installed. diff --git a/autoload/vimwiki/default.tpl b/autoload/vimwiki/default.tpl index 3e31d99..3a4045f 100644 --- a/autoload/vimwiki/default.tpl +++ b/autoload/vimwiki/default.tpl @@ -1,4 +1,4 @@ - + diff --git a/autoload/vimwiki/diary.vim b/autoload/vimwiki/diary.vim index 36d59de..37f6d5c 100644 --- a/autoload/vimwiki/diary.vim +++ b/autoload/vimwiki/diary.vim @@ -1,88 +1,80 @@ -" 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 -"}}} + let s:vimwiki_max_scan_for_caption = 5 -" Helpers {{{ -function! s:prefix_zero(num) "{{{ + +function! s:prefix_zero(num) if a:num < 10 return '0'.a:num endif return a:num -endfunction "}}} +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(...) + 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:diary_path(...) "{{{ - let idx = a:0 == 0 ? g:vimwiki_current_idx : a:1 - return VimwikiGet('path', idx).VimwikiGet('diary_rel_path', idx) -endfunction "}}} -function! s:diary_index(...) "{{{ - let idx = a:0 == 0 ? g:vimwiki_current_idx : a:1 - return s:diary_path(idx).VimwikiGet('diary_index', idx).VimwikiGet('ext', idx) -endfunction "}}} +function! s: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 -function! s:diary_date_link(...) "{{{ - let idx = a:0 == 0 ? g:vimwiki_current_idx : a:1 - return s:get_date_link(VimwikiGet('diary_link_fmt', idx)) -endfunction "}}} -function! s:get_position_links(link) "{{{ +function! vimwiki#diary#diary_date_link(...) + if a:0 + return strftime('%Y-%m-%d', a:1) + else + return strftime('%Y-%m-%d') + endif +endfunction + + +function! s:get_position_links(link) let idx = -1 let links = [] - if a:link =~ '^\d\{4}-\d\d-\d\d' - let links = keys(s:get_diary_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 "}}} +endfunction -fun! s:get_month_name(month) "{{{ - return g:vimwiki_diary_months[str2nr(a:month)] -endfun "}}} -" Helpers }}} +function! s:get_month_name(month) + return vimwiki#vars#get_global('diary_months')[str2nr(a:month)] +endfunction -" Diary index stuff {{{ -fun! s:read_captions(files) "{{{ + +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 = fnamemodify(fl, ':t:r') + let fl_key = substitute(fnamemodify(fl, ':t'), vimwiki#vars#get_wikilocal('ext').'$', '', '') if filereadable(fl) for line in readfile(fl, '', s:vimwiki_max_scan_for_caption) - if line =~ g:vimwiki_rxHeader && !has_key(result, fl_key) - let result[fl_key] = vimwiki#u#trim(matchstr(line, g:vimwiki_rxHeader)) + if line =~# rx_header && !has_key(result, fl_key) + let result[fl_key] = vimwiki#u#trim(matchstr(line, rx_header)) endif endfor endif @@ -93,26 +85,24 @@ fun! s:read_captions(files) "{{{ endfor return result -endfun "}}} +endfunction -fun! s:get_diary_links(...) "{{{ + +function! s:get_diary_files() let rx = '^\d\{4}-\d\d-\d\d' - let s_files = glob(VimwikiGet('path').VimwikiGet('diary_rel_path').'*'.VimwikiGet('ext')) + 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, '\').'"') + call filter(files, 'fnamemodify(v:val, ":t") =~# "'.escape(rx, '\').'"') " remove backup files (.wiki~) - call filter(files, 'v:val !~ ''.*\~$''') + call filter(files, 'v:val !~# ''.*\~$''') - if a:0 - call add(files, a:1) - endif - let links_with_captions = s:read_captions(files) + return files +endfunction - return links_with_captions -endfun "}}} -fun! s:group_links(links) "{{{ +function! s:group_links(links) let result = {} let p_year = 0 let p_month = 0 @@ -131,130 +121,105 @@ fun! s:group_links(links) "{{{ let p_month = month endfor return result -endfun "}}} +endfunction -fun! s:sort(lst) "{{{ - if VimwikiGet("diary_sort") == 'desc' + +function! s:sort(lst) + if vimwiki#vars#get_wikilocal('diary_sort') ==? 'desc' return reverse(sort(a:lst)) else return sort(a:lst) endif -endfun "}}} +endfunction -fun! s:format_diary(...) "{{{ + +function! s:format_diary() let result = [] - call add(result, substitute(g:vimwiki_rxH1_Template, '__Header__', VimwikiGet('diary_header'), '')) + let links_with_captions = s:read_captions(s:get_diary_files()) + let g_files = s:group_links(links_with_captions) - if a:0 - let g_files = s:group_links(s:get_diary_links(a:1)) - else - let g_files = s:group_links(s:get_diary_links()) - endif - - " for year in s:rev(sort(keys(g_files))) for year in s:sort(keys(g_files)) call add(result, '') - call add(result, substitute(g:vimwiki_rxH2_Template, '__Header__', year , '')) + call add(result, + \ substitute(vimwiki#vars#get_syntaxlocal('rxH2_Template'), '__Header__', year , '')) - " for month in s:rev(sort(keys(g_files[year]))) for month in s:sort(keys(g_files[year])) call add(result, '') - call add(result, substitute(g:vimwiki_rxH3_Template, '__Header__', s:get_month_name(month), '')) + call add(result, substitute(vimwiki#vars#get_syntaxlocal('rxH3_Template'), + \ '__Header__', s:get_month_name(month), '')) - " for [fl, cap] in s:rev(sort(items(g_files[year][month]))) for [fl, cap] in s:sort(items(g_files[year][month])) - if empty(cap) - let entry = substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', fl, '') - let entry = substitute(entry, '__LinkDescription__', cap, '') - call add(result, repeat(' ', &sw).'* '.entry) - else - let entry = substitute(g:vimwiki_WikiLinkTemplate2, '__LinkUrl__', fl, '') - let entry = substitute(entry, '__LinkDescription__', cap, '') - call add(result, repeat(' ', &sw).'* '.entry) + 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 - call add(result, '') return result -endfun "}}} +endfunction -function! s:delete_diary_section() "{{{ - " remove diary section - let old_pos = getpos('.') - let ln_start = -1 - let ln_end = -1 - call cursor(1, 1) - if search(substitute(g:vimwiki_rxH1_Template, '__Header__', VimwikiGet('diary_header'), ''), 'Wc') - let ln_start = line('.') - if search(g:vimwiki_rxH1, 'W') - let ln_end = line('.') - 1 - else - let ln_end = line('$') + +" 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 wiki_nr = a:wnum - 1 endif - if ln_start < 0 || ln_end < 0 - call setpos('.', old_pos) - return - endif - - if !&readonly - exe ln_start.",".ln_end."delete _" - endif - - call setpos('.', old_pos) -endfunction "}}} - -function! s:insert_diary_section() "{{{ - if !&readonly - let ln = line('.') - call append(ln, s:format_diary()) - if ln == 1 && getline(ln) == '' - 1,1delete - endif - endif -endfunction "}}} - -" Diary index stuff }}} - -function! vimwiki#diary#make_note(wnum, ...) "{{{ - if a:wnum > len(g:vimwiki_list) - echom "vimwiki: Wiki ".a:wnum." is not registered in g:vimwiki_list!" + if wiki_nr >= vimwiki#vars#number_of_wikis() + echomsg 'Vimwiki Error: Wiki '.wiki_nr.' is not registered in g:vimwiki_list!' return endif " TODO: refactor it. base#goto_index uses the same - if a:wnum > 0 - let idx = a:wnum - 1 - else - let idx = 0 - endif - call vimwiki#base#validate_wiki_options(idx) - call vimwiki#base#mkdir(VimwikiGet('path', idx).VimwikiGet('diary_rel_path', idx)) + call vimwiki#path#mkdir(vimwiki#vars#get_wikilocal('path', wiki_nr). + \ vimwiki#vars#get_wikilocal('diary_rel_path', wiki_nr)) - if a:0 && a:1 == 1 - let cmd = 'tabedit' - else - let cmd = 'edit' + let cmd = 'edit' + 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 endif if a:0>1 let link = 'diary:'.a:2 else - let link = 'diary:'.s:diary_date_link(idx) + let link = 'diary:'.vimwiki#diary#diary_date_link() endif - call vimwiki#base#open_link(cmd, link, s:diary_index(idx)) - call vimwiki#base#setup_buffer_state(idx) -endfunction "}}} + call vimwiki#base#open_link(cmd, link, s:diary_index(wiki_nr)) +endfunction -function! vimwiki#diary#goto_diary_index(wnum) "{{{ - if a:wnum > len(g:vimwiki_list) - echom "vimwiki: Wiki ".a:wnum." is not registered in g:vimwiki_list!" + +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 @@ -265,12 +230,16 @@ function! vimwiki#diary#goto_diary_index(wnum) "{{{ let idx = 0 endif - call vimwiki#base#validate_wiki_options(idx) call vimwiki#base#edit_file('e', s:diary_index(idx), '') - call vimwiki#base#setup_buffer_state(idx) -endfunction "}}} -function! vimwiki#diary#goto_next_day() "{{{ + if vimwiki#vars#get_wikilocal('auto_diary_index') + call vimwiki#diary#generate_diary_section() + write! " save changes + endif +endfunction + + +function! vimwiki#diary#goto_next_day() let link = '' let [idx, links] = s:get_position_links(expand('%:t:r')) @@ -282,15 +251,16 @@ function! vimwiki#diary#goto_next_day() "{{{ let link = 'diary:'.links[idx+1] else " goto today - let link = 'diary:'.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')) @@ -302,34 +272,36 @@ function! vimwiki#diary#goto_prev_day() "{{{ let link = 'diary:'.links[idx-1] else " goto today - let link = 'diary:'.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#u#path_norm(expand("%:p")) - let diary_file = vimwiki#u#path_norm(s:diary_index()) - if current_file == diary_file - call s:delete_diary_section() - call s:insert_diary_section() + +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 - echom "vimwiki: You can generate diary links only in a diary index page!" + echomsg 'Vimwiki Error: You can generate diary links only in a diary index page!' endif -endfunction "}}} +endfunction -" Calendar.vim {{{ -" Callback function. -function! vimwiki#diary#calendar_action(day, month, year, week, dir) "{{{ + +" 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' + if a:dir ==? 'V' vsplit else split @@ -341,18 +313,15 @@ function! vimwiki#diary#calendar_action(day, month, year, week, dir) "{{{ endif endif - " XXX: Well, +1 is for inconsistent index basing... - call vimwiki#diary#make_note(g:vimwiki_current_idx+1, 0, link) -endfunction "}}} + call vimwiki#diary#make_note(0, 0, link) +endfunction -" Sign function. -function vimwiki#diary#calendar_sign(day, month, year) "{{{ + +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') + 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 "}}} - -" Calendar.vim }}} +endfunction diff --git a/autoload/vimwiki/html.vim b/autoload/vimwiki/html.vim index 71bd126..ba2cc4c 100644 --- a/autoload/vimwiki/html.vim +++ b/autoload/vimwiki/html.vim @@ -1,63 +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/ -" TODO: We need vimwiki abstract syntax tree. If properly designed it wourld -" greatly symplify different syntax to HTML generation. -" -" vimwiki -- --> PDF -" \ / -" markdown -----> AST -----> HTML -" / \ -" mediawiki -- --> Latex -" -" 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 VimwikiGet('syntax') == "default" -endfunction " }}} -function! s:remove_blank_lines(lines) " {{{ - while !empty(a:lines) && a:lines[-1] =~ '^\s*$' +function! s:syntax_supported() + return vimwiki#vars#get_wikilocal('syntax') ==? "default" +endfunction + + +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 tolower(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) != '' @@ -65,45 +59,50 @@ function! s:find_autoload_file(name) " {{{ endif endfor return '' -endfunction " }}} +endfunction -function! s:default_CSS_full_name(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 "}}} +endfunction -function! s:create_default_CSS(path) " {{{ + +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=[] @@ -113,8 +112,7 @@ function! s:get_html_template(wikifile, template) "{{{ 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 @@ -126,23 +124,22 @@ function! s:get_html_template(wikifile, template) "{{{ let lines = readfile(default_tpl) return lines -endfunction "}}} +endfunction -function! s:safe_html_preformatted(line) "{{{ + +function! s:safe_html_preformatted(line) let line = substitute(a:line,'<','\<', 'g') let line = substitute(line,'>','\>', 'g') return line -endfunction "}}} +endfunction -function! s:safe_html_anchor(string) "{{{ - let string = substitute(a:string, '"', '\"', 'g') - let string = substitute(string, "'", '\'', 'g') - let string = substitute(string, '/', '\/', 'g') - let string = substitute(string, '\t', ' ', 'g') " doesn't work - return string -endfunction "}}} -function! s:safe_html_line(line) "{{{ +function! s:escape_html_attribute(string) + return substitute(a:string, '"', '\"', 'g') +endfunction + + +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() @@ -151,20 +148,21 @@ function! s:safe_html_line(line) "{{{ let line = substitute(line,s:gt_pattern,'\>', '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 @@ -172,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. @@ -201,28 +201,36 @@ function! s:subst_func(line, regexp, func, ...) " {{{ 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 "}}} -" get title. -function! s:process_title(placeholders, default_title) "{{{ +function! s:process_date(placeholders, default_date) if !empty(a:placeholders) for [placeholder, row, idx] in a:placeholders let [type, param] = placeholder - if type == 'title' && !empty(param) + if type ==# 'date' && !empty(param) + return param + endif + endfor + endif + return a:default_date +endfunction + + +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) 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('') @@ -231,19 +239,20 @@ function! s:is_html_uptodate(wikifile) "{{{ endif let wikifile = fnamemodify(a:wikifile, ":p") - let htmlfile = expand(VimwikiGet('path_html').VimwikiGet('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) @@ -260,22 +269,23 @@ function! s:html_insert_contents(html_lines, content) "{{{ endif endfor return lines -endfunction "}}} -"}}} +endfunction -" INLINE TAGS "{{{ -function! s:tag_eqin(value) "{{{ + +function! s:tag_eqin(value) " mathJAX wants \( \) for inline maths return '\('.s:mid(a:value, 1).'\)' -endfunction "}}} +endfunction -function! s:tag_em(value) "{{{ + +function! s:tag_em(value) return ''.s:mid(a:value, 1).'' -endfunction "}}} +endfunction -function! s:tag_strong(value, header_ids) "{{{ + +function! s:tag_strong(value, header_ids) let text = s:mid(a:value, 1) - let id = s:safe_html_anchor(text) + let id = s:escape_html_attribute(text) let complete_id = '' for l in range(6) if a:header_ids[l][0] != '' @@ -286,81 +296,104 @@ function! s:tag_strong(value, header_ids) "{{{ let complete_id = complete_id[:-2] endif let complete_id .= '-'.id - return '
'.text.'' -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_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 "}}} - -"function! s:tag_pre(value) "{{{ -" return ''.s:mid(a:value, 3).'' -"endfunction "}}} - -"FIXME dead code? -"function! s:tag_math(value) "{{{ -" return '\['.s:mid(a:value, 3).'\]' -"endfunction "}}} +endfunction -"{{{ v2.0 links -" match n-th ARG within {{URL[|ARG1|ARG2|...]}} " {{{ -" *c,d,e),... -function! vimwiki#html#incl_match_arg(nn_index) - let rx = g:vimwiki_rxWikiInclPrefix. g:vimwiki_rxWikiInclUrl - let rx = rx. repeat(g:vimwiki_rxWikiInclSeparator. g:vimwiki_rxWikiInclArg, a:nn_index-1) - if a:nn_index > 0 - let rx = rx. g:vimwiki_rxWikiInclSeparator. '\zs'. g:vimwiki_rxWikiInclArg. '\ze' +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 rx = rx. g:vimwiki_rxWikiInclArgs. g:vimwiki_rxWikiInclSuffix + 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 + + +function! s:tag_todo(value) + return ''.a:value.'' +endfunction + + +function! s:tag_strike(value) + return ''.s:mid(a:value, 2).'' +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: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! vimwiki#html#linkify_link(src, descr) "{{{ - let src_str = ' href="'.s:safe_html_anchor(a:src).'"' - let descr = substitute(a:descr,'^\s*\(.*\)\s*$','\1','') + +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 =~ g:vimwiki_rxWikiIncl - \ ? s:tag_wikiincl(descr) + let descr_str = (descr =~# vimwiki#vars#get_global('rxWikiIncl') + \ ? s:tag_wikiincl(descr) \ : descr) return ''.descr_str.'' -endfunction "}}} +endfunction -function! vimwiki#html#linkify_image(src, descr, verbatim_str) "{{{ + +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 "}}} +endfunction -function! s:tag_weblink(value) "{{{ + +function! s:tag_weblink(value) " Weblink Template -> descr let str = a:value - let url = matchstr(str, g:vimwiki_rxWeblinkMatchUrl) - let descr = matchstr(str, g:vimwiki_rxWeblinkMatchDescr) - let line = vimwiki#html#linkify_link(url, descr) + 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 "}}} +endfunction -function! s:tag_wikiincl(value) "{{{ + +function! s:tag_wikiincl(value) " {{imgurl|arg1|arg2}} -> ??? " {{imgurl}} -> " {{imgurl|descr|style="A"}} -> descr @@ -370,68 +403,83 @@ function! s:tag_wikiincl(value) "{{{ let line = VimwikiWikiIncludeHandler(str) " otherwise, assume image transclusion if line == '' - let url_0 = matchstr(str, g:vimwiki_rxWikiInclMatchUrl) - let descr = matchstr(str, vimwiki#html#incl_match_arg(1)) - let verbatim_str = matchstr(str, vimwiki#html#incl_match_arg(2)) - " resolve url - let [idx, scheme, path, subdir, lnk, ext, url, anchor] = - \ vimwiki#base#resolve_scheme(url_0, 1) - " generate html output - " TODO: migrate non-essential debugging messages into g:VimwikiLog - if g:vimwiki_debug > 1 - echom '{{idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.'}}' - endif + 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)) - " Issue 343: Image transclusions: schemeless links have .html appended. - " If link is schemeless pass it as it is - if scheme == '' - let url = lnk + 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 url = link_infos.filename endif let url = escape(url, '#') - let line = vimwiki#html#linkify_image(url, descr, verbatim_str) - return line + let line = s:linkify_image(url, descr, verbatim_str) endif return line -endfunction "}}} +endfunction -function! s:tag_wikilink(value) "{{{ + +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 + " [[#a1#a2]] -> #a1#a2 let str = a:value - let url = matchstr(str, g:vimwiki_rxWikiLinkMatchUrl) - let descr = matchstr(str, g:vimwiki_rxWikiLinkMatchDescr) - let descr = (substitute(descr,'^\s*\(.*\)\s*$','\1','') != '' ? descr : url) + 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) - " resolve url - let [idx, scheme, path, subdir, lnk, ext, url, anchor] = - \ vimwiki#base#resolve_scheme(url, 1) + 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) - " generate html output - " TODO: migrate non-essential debugging messages into g:VimwikiLog - if g:vimwiki_debug > 1 - echom '[[idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.']]' + 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 link_infos.anchor != '' + let anchor = substitute(link_infos.anchor, '#', '-', 'g') + let html_link .= '#'.anchor + endif + let line = html_link endif - if anchor != '' - let anchor = substitute(anchor, '#', '-', 'g') - let url .= '#'.anchor - endif - let line = vimwiki#html#linkify_link(url, descr) + + let line = s:linkify_link(line, descr) return line -endfunction "}}} -"}}} +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) @@ -448,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 = '' @@ -458,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) @@ -470,22 +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. - " FIXME + " FIXME let patt_splitter = '\(`[^`]\+`\)\|'. - \ '\('.g:vimwiki_rxPreStart.'.\+'.g:vimwiki_rxPreEnd.'\)\|'. + \ '\('.vimwiki#vars#get_syntaxlocal('rxPreStart').'.\+'. + \ vimwiki#vars#get_syntaxlocal('rxPreEnd').'\)\|'. \ '\(\)\|'. \ '\(\)\|'. \ '\(\)\|'. - \ '\('.g:vimwiki_rxEqIn.'\)' + \ '\('.vimwiki#vars#get_syntaxlocal('rxEqIn').'\)' "FIXME FIXME !!! these can easily occur on the same line! "XXX {{{ }}} ??? obsolete - if '`[^`]\+`' == a:regexp || '{{{.\+}}}' == a:regexp || g:vimwiki_rxEqIn == a:regexp + 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 @@ -508,91 +560,99 @@ function! s:make_tag(line, regexp, func, ...) "{{{ 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, header_ids) "{{{ + +function! s:process_tags_typefaces(line, header_ids) let line = a:line - let line = s:make_tag(line, g:vimwiki_rxItalic, 's:tag_em') - let line = s:make_tag(line, g:vimwiki_rxBold, 's:tag_strong', a:header_ids) - 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, g:vimwiki_rxEqIn, 's:tag_eqin') + 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, g:vimwiki_rxWikiLink, 's:tag_wikilink') - let line = s:make_tag(line, g:vimwiki_rxWikiIncl, 's:tag_wikiincl') - let line = s:make_tag(line, g:vimwiki_rxWeblink, 's:tag_weblink') + 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, header_ids) "{{{ + +function! s:process_inline_tags(line, header_ids) let line = s:process_tags_links(a: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) "{{{ + +function! s:close_tag_math(math, ldest) if a:math[0] call insert(a:ldest, "\\\]") return 0 endif return a:math -endfunction "}}} +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, header_ids) "{{{ + +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 @@ -618,9 +678,9 @@ function! s:close_tag_table(table, ldest, header_ids) "{{{ endif endfor endfor - endfunction "}}} + endfunction - function! s:sum_colspan(table) "{{{ + function! s:sum_colspan(table) for row in a:table[1:] let cols = 1 @@ -633,19 +693,19 @@ function! s:close_tag_table(table, ldest, header_ids) "{{{ endif endfor endfor - endfunction "}}} + endfunction - function! s:close_tag_row(row, header, ldest, header_ids) "{{{ + 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 @@ -668,7 +728,7 @@ function! s:close_tag_table(table, ldest, header_ids) "{{{ endfor call add(a:ldest, '') - endfunction "}}} + endfunction let table = a:table let ldest = a:ldest @@ -676,7 +736,7 @@ function! s:close_tag_table(table, ldest, header_ids) "{{{ 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,32 +771,35 @@ function! s:close_tag_table(table, ldest, header_ids) "{{{ 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 "XXX huh? - "if !pre[0] && a:line =~ '^\s*{{{[^\(}}}\)]*\s*$' - if !pre[0] && a:line =~ '^\s*{{{' + "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') @@ -747,7 +810,7 @@ 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 @@ -758,21 +821,23 @@ function! s:process_tag_pre(line, pre) "{{{ call add(lines, s:safe_html_preformatted(a:line)) endif return [processed, lines, pre] -endfunction "}}} +endfunction -function! s:process_tag_math(line, math) "{{{ + +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*$' + if !math[0] && a:line =~# '^\s*{{\$[^\(}}$\)]*\s*$' let class = matchstr(a:line, '{{$\zs.*$') "FIXME class cannot be any string! let class = substitute(class, '\s\+$', '', 'g') - " Check the math placeholder (default: displaymath) - let b:vimwiki_mathEnv = matchstr(class, '^%\zs\S\+\ze%') - if b:vimwiki_mathEnv != "" - call add(lines, substitute(class, '^%\(\S\+\)%','\\begin{\1}', '')) + " 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 @@ -780,10 +845,10 @@ function! s:process_tag_math(line, math) "{{{ endif let math = [1, len(matchstr(a:line, '^\s*\ze{{\$'))] let processed = 1 - elseif math[0] && a:line =~ '^\s*}}\$\s*$' + elseif math[0] && a:line =~# '^\s*}}\$\s*$' let math = [0, 0] - if b:vimwiki_mathEnv != "" - call add(lines, "\\end{".b:vimwiki_mathEnv."}") + if s:current_math_env != "" + call add(lines, "\\end{".s:current_math_env."}") else call add(lines, "\\\]") endif @@ -793,13 +858,14 @@ function! s:process_tag_math(line, math) "{{{ call add(lines, substitute(a:line, '^\s\{'.math[1].'}', '', '')) endif return [processed, lines, math] -endfunction "}}} +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 @@ -811,21 +877,29 @@ 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) "{{{ +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 !empty(chk) && len(chk[1]) > 0 - let completion = index(g:vimwiki_listsyms_list, chk[1]) - if completion >= 0 && completion <=4 + 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, ''] - endfunction "}}} + endfunction + let in_list = (len(a:lists) > 0) @@ -833,7 +907,7 @@ function! s:process_tag_list(line, lists) "{{{ " text. " XXX necessary? in *bold* text, no space must follow the first * if !in_list - let pos = match(a:line, '^\s*'.g:vimwiki_rxBold) + let pos = match(a:line, '^\s*'.vimwiki#vars#get_syntaxlocal('rxBold')) if pos != -1 return [0, []] endif @@ -842,12 +916,12 @@ function! s:process_tag_list(line, lists) "{{{ let lines = [] let processed = 0 - if a:line =~ '^\s*'.s:bullets.'\s' + if a:line =~# '^\s*'.s:bullets.'\s' let lstSym = matchstr(a:line, s:bullets) let lstTagOpen = '
      ' let lstTagClose = '
    ' let lstRegExp = '^\s*'.s:bullets.'\s' - elseif a:line =~ '^\s*'.s:numbers.'\s' + elseif a:line =~# '^\s*'.s:numbers.'\s' let lstSym = matchstr(a:line, s:numbers) let lstTagOpen = '
      ' let lstTagClose = '
    ' @@ -889,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 && 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) @@ -903,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 @@ -927,45 +1001,51 @@ 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_rxHeader + if a:line =~# vimwiki#vars#get_syntaxlocal('rxHeader') let h_level = vimwiki#u#count_first_sym(a:line) endif if h_level > 0 - let h_text = vimwiki#u#trim(matchstr(line, g:vimwiki_rxHeader)) + let h_text = vimwiki#u#trim(matchstr(line, vimwiki#vars#get_syntaxlocal('rxHeader'))) let h_number = '' let h_complete_id = '' - let h_id = s:safe_html_anchor(h_text) - let centered = (a:line =~ '^\s') + let h_id = s:escape_html_attribute(h_text) + let centered = (a:line =~# '^\s') - if h_text != g:vimwiki_toc_header + if h_text !=# vimwiki#vars#get_global('toc_header') let a:id[h_level-1] = [h_text, a:id[h_level-1][1]+1] @@ -983,16 +1063,18 @@ function! s:process_tag_h(line, id) "{{{ let h_number .= a:id[h_level-1][1] let h_complete_id .= a:id[h_level-1][0] - if g:vimwiki_html_header_numbering + if vimwiki#vars#get_global('html_header_numbering') let num = matchstr(h_number, - \ '^\(\d.\)\{'.(g:vimwiki_html_header_numbering-1).'}\zs.*') + \ '^\(\d.\)\{'.(vimwiki#vars#get_global('html_header_numbering')-1).'}\zs.*') if !empty(num) - let num .= g:vimwiki_html_header_numbering_sym + let num .= vimwiki#vars#get_global('html_header_numbering_sym') endif let h_text = num.' '.h_text endif - let h_complete_id = s:safe_html_anchor(h_complete_id) - let h_part = '
    ' + let h_part .= '' + let h_part .= '
    ' + let h_text = s:process_inline_tags(h_text, a:id) + + let line = h_part.h_text.'' let processed = 1 endif return [processed, line] -endfunction "}}} +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, header_ids) "{{{ - 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 @@ -1047,11 +1132,11 @@ function! s:process_tag_table(line, table, header_ids) "{{{ 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', []] @@ -1060,7 +1145,7 @@ function! s:process_tag_table(line, table, header_ids) "{{{ let row = [[]] endif return row - endfunction "}}} + endfunction let table = a:table let lines = [] @@ -1081,14 +1166,10 @@ function! s:process_tag_table(line, table, header_ids) "{{{ 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 @@ -1106,40 +1187,7 @@ function! s:parse_line(line, state) " {{{ let processed = 0 - if !processed - if line =~ g:vimwiki_rxComment - let processed = 1 - endif - endif - - " nohtml -- placeholder - if !processed - if line =~ '^\s*%nohtml' - let processed = 1 - let state.placeholder = ['nohtml'] - endif - endif - - " title -- placeholder - if !processed - if line =~ '^\s*%title' - let processed = 1 - let param = matchstr(line, '^\s*%title\s\zs.*') - let state.placeholder = ['title', param] - endif - endif - - " html template -- placeholder "{{{ - if !processed - if line =~ '^\s*%template' - let processed = 1 - let param = matchstr(line, '^\s*%template\s\zs.*') - let state.placeholder = ['template', param] - endif - endif - "}}} - - " pres "{{{ + " 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. @@ -1163,9 +1211,58 @@ function! s:parse_line(line, state) " {{{ endif call extend(res_lines, lines) endif - "}}} - " lists "{{{ + + if !processed + if line =~# vimwiki#vars#get_syntaxlocal('rxComment') + let processed = 1 + endif + endif + + " nohtml -- placeholder + if !processed + if line =~# '\m^\s*%nohtml\s*$' + let processed = 1 + let state.placeholder = ['nohtml'] + endif + endif + + " title -- placeholder + if !processed + if line =~# '\m^\s*%title\%(\s.*\)\?$' + let processed = 1 + let param = matchstr(line, '\m^\s*%title\s\+\zs.*') + let state.placeholder = ['title', param] + endif + endif + + " date -- placeholder + if !processed + if line =~# '\m^\s*%date\%(\s.*\)\?$' + let processed = 1 + let param = matchstr(line, '\m^\s*%date\s\+\zs.*') + let state.placeholder = ['date', param] + endif + endif + + " html template -- placeholder + if !processed + if line =~# '\m^\s*%template\%(\s.*\)\?$' + let processed = 1 + let param = matchstr(line, '\m^\s*%template\s\+\zs.*') + let state.placeholder = ['template', param] + endif + endif + + + " tables + if !processed + let [processed, lines, state.table] = s:process_tag_table(line, state.table, state.header_ids) + call extend(res_lines, lines) + endif + + + " lists if !processed let [processed, lines] = s:process_tag_list(line, state.lists) if processed && state.quote @@ -1191,36 +1288,25 @@ function! s:parse_line(line, state) " {{{ call extend(res_lines, lines) endif - "}}} - " headers "{{{ + + " headers if !processed 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, - \ state.header_ids) + 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, state.header_ids) - call add(res_lines, line) endif endif - "}}} - " tables "{{{ - if !processed - let [processed, lines, state.table] = s:process_tag_table(line, - \ state.table, state.header_ids) - 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) @@ -1246,23 +1332,22 @@ function! s:parse_line(line, state) " {{{ 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, - \ state.header_ids) + 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) @@ -1270,9 +1355,9 @@ function! s:parse_line(line, state) " {{{ 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) @@ -1288,15 +1373,14 @@ function! s:parse_line(line, state) " {{{ 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, - \ state.header_ids) + let state.table = s:close_tag_table(state.table, res_lines, state.header_ids) endif call map(lines, 's:process_inline_tags(v:val, state.header_ids)') call extend(res_lines, lines) endif - "}}} + "" add the rest if !processed @@ -1305,44 +1389,51 @@ function! s:parse_line(line, state) " {{{ return [res_lines, state] -endfunction " }}} +endfunction -function! s:use_custom_wiki2html() "{{{ - let custom_wiki2html = VimwikiGet('custom_wiki2html') - return !empty(custom_wiki2html) && s:file_exists(custom_wiki2html) -endfunction " }}} -function! vimwiki#html#CustomWiki2HTML(path, wikifile, force) "{{{ - call vimwiki#base#mkdir(a:path) - echomsg system(VimwikiGet('custom_wiki2html'). ' '. +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. ' '. - \ VimwikiGet('syntax'). ' '. - \ strpart(VimwikiGet('ext'), 1). ' '. + \ 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(VimwikiGet('template_path')) > 1 ? shellescape(expand(VimwikiGet('template_path'))) : '-'). ' '. - \ (len(VimwikiGet('template_default')) > 0 ? VimwikiGet('template_default') : '-'). ' '. - \ (len(VimwikiGet('template_ext')) > 0 ? VimwikiGet('template_ext') : '-'). ' '. - \ (len(VimwikiGet('subdir')) > 0 ? shellescape(s:root_path(VimwikiGet('subdir'))) : '-')) -endfunction " }}} + \ (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! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ - - if VimwikiGet('auto_toc') >= 1 - call vimwiki#base#table_of_contents(0) - noautocmd update - endif - - let starttime = reltime() " start the clock +function! s:convert_file(path_html, wikifile) let done = 0 let wikifile = fnamemodify(a:wikifile, ":p") - let path_html = expand(a:path_html).VimwikiGet('subdir') + let path_html = expand(a:path_html).vimwiki#vars#get_bufferlocal('subdir') let htmlfile = fnamemodify(wikifile, ":t:r").'.html' + " 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 + if s:use_custom_wiki2html() let force = 1 call vimwiki#html#CustomWiki2HTML(path_html, wikifile, force) @@ -1353,11 +1444,7 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ let lsource = readfile(wikifile) let ldest = [] - "if g:vimwiki_debug - " echo 'Generating HTML ... ' - "endif - - call vimwiki#base#mkdir(path_html) + call vimwiki#path#mkdir(path_html) " nohtml placeholder -- to skip html generation. let nohtml = 0 @@ -1384,16 +1471,15 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ " prepare constants for s:safe_html_line() let s:lt_pattern = '<' let s:gt_pattern = '>' - if g:vimwiki_valid_html_tags != '' - let tags = join(split(g:vimwiki_valid_html_tags, '\s*,\s*'), '\|') - let s:lt_pattern = '\c<\%(/\?\%('.tags.'\)\%(\s\{-1}\S\{-}\)\{-}/\?>\)\@!' + 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 " prepare regexps for lists - let s:bullets = '[*•-]' - let s:numbers = - \'\C\%(#\|\d\+)\|\d\+\.\|[ivxlcdm]\+)\|[IVXLCDM]\+)\|\l\{1,2})\|\u\{1,2})\)' + let s:bullets = '[*-]' + let s:numbers = '\C\%(#\|\d\+)\|\d\+\.\|[ivxlcdm]\+)\|[IVXLCDM]\+)\|\l\{1,2})\|\u\{1,2})\)' for line in lsource let oldquote = state.quote @@ -1407,10 +1493,10 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ endif if !empty(state.placeholder) - if state.placeholder[0] == 'nohtml' + if state.placeholder[0] ==# 'nohtml' let nohtml = 1 break - elseif state.placeholder[0] == 'template' + elseif state.placeholder[0] ==# 'template' let template_name = state.placeholder[1] else call add(placeholders, [state.placeholder, len(ldest), len(placeholders)]) @@ -1424,13 +1510,13 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ if nohtml echon "\r"."%nohtml placeholder found" - return + return '' endif call s:remove_blank_lines(ldest) - "" process end of file - "" close opened tags if any + " 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) @@ -1442,15 +1528,17 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ call extend(ldest, lines) let title = s:process_title(placeholders, fnamemodify(a:wikifile, ":t:r")) + let date = s:process_date(placeholders, strftime('%Y-%m-%d')) - let html_lines = s:get_html_template(a:wikifile, template_name) + let html_lines = s:get_html_template(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, "%date%", "'. date .'", "g")') call map(html_lines, 'substitute(v:val, "%root_path%", "'. - \ s:root_path(VimwikiGet('subdir')) .'", "g")') + \ s:root_path(vimwiki#vars#get_bufferlocal('subdir')) .'", "g")') - let css_name = expand(VimwikiGet('css_name')) + 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")') @@ -1461,100 +1549,116 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{ call map(html_lines, 'substitute(v:val, "%encoding%", "'. enc .'", "g")') let html_lines = s:html_insert_contents(html_lines, ldest) " %contents% - - "" make html file. + call writefile(html_lines, path_html.htmlfile) let done = 1 endif if done == 0 - echomsg 'vimwiki: conversion to HTML is not supported for this syntax!!!' - return + echomsg 'Vimwiki Error: Conversion to HTML is not supported for this syntax' + return '' endif - " measure the elapsed time - let time1 = vimwiki#u#time(starttime) "XXX - call VimwikiLog_extend('html',[htmlfile,time1]) - "if g:vimwiki_debug - " echon "\r".htmlfile.' written (time: '.time1.'s)' - "endif - return path_html.htmlfile -endfunction "}}} +endfunction -function! vimwiki#html#WikiAll2HTML(path_html) "{{{ +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_html) if !s:syntax_supported() && !s:use_custom_wiki2html() - echomsg 'vimwiki: conversion to HTML is not supported for this syntax!!!' + 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_html = expand(a:path_html) - call vimwiki#base#mkdir(path_html) + call vimwiki#path#mkdir(path_html) - echomsg 'Deleting non-wiki html files...' + 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 " temporarily adjust current_subdir global state variable - let current_subdir = VimwikiGet('subdir') - let current_invsubdir = VimwikiGet('invsubdir') + let current_subdir = vimwiki#vars#get_bufferlocal('subdir') + let current_invsubdir = vimwiki#vars#get_bufferlocal('invsubdir') - let wikifiles = split(glob(VimwikiGet('path').'**/*'.VimwikiGet('ext')), '\n') + 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(VimwikiGet('path'), wikifile) - call VimwikiSet('subdir', subdir) - call VimwikiSet('invsubdir', vimwiki#base#invsubdir(subdir)) + 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 + echomsg 'Vimwiki: Processing '.wikifile - call vimwiki#html#Wiki2HTML(path_html, wikifile) + call s:convert_file(path_html, wikifile) else - echomsg 'Skipping '.wikifile + echomsg 'Vimwiki: Skipping '.wikifile endif endfor " reset 'subdir' state variable - call VimwikiSet('subdir', current_subdir) - call VimwikiSet('invsubdir', current_invsubdir) + call vimwiki#vars#set_bufferlocal('subdir', current_subdir) + call vimwiki#vars#set_bufferlocal('invsubdir', current_invsubdir) - call s:create_default_CSS(path_html) - echomsg 'Done!' + 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) "{{{ + +function! s:file_exists(fname) return !empty(getftype(expand(a:fname))) -endfunction "}}} +endfunction -" uses VimwikiGet('path') -function! vimwiki#html#get_wikifile_url(wikifile) "{{{ - return VimwikiGet('path_html'). - \ vimwiki#base#subdir(VimwikiGet('path'), a:wikifile). + +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 "}}} +endfunction -function! vimwiki#html#PasteUrl(wikifile) "{{{ - execute 'r !echo file://'.vimwiki#html#get_wikifile_url(a:wikifile) -endfunction "}}} -function! vimwiki#html#CatUrl(wikifile) "{{{ - execute '!echo file://'.vimwiki#html#get_wikifile_url(a:wikifile) -endfunction "}}} -"}}} +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/autoload/vimwiki/lst.vim b/autoload/vimwiki/lst.vim index 86c9d74..201a658 100644 --- a/autoload/vimwiki/lst.vim +++ b/autoload/vimwiki/lst.vim @@ -1,21 +1,25 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Everything concerning bulleted and numbered lists and checkboxes -" Author: Daniel Schemala -" 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_list_auto = 1 -"incrementation functions for the various kinds of numbers {{{ -function! s:increment_1(value) "{{{ +" --------------------------------------------------------- +" incrementation functions for the various kinds of numbers +" --------------------------------------------------------- + +function! s:increment_1(value) return eval(a:value) + 1 -endfunction "}}} +endfunction -function! s:increment_A(value) "{{{ + +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))) @@ -32,9 +36,10 @@ function! s:increment_A(value) "{{{ call insert(list_of_chars, 'A') endif return join(list_of_chars, '') -endfunction "}}} +endfunction -function! s:increment_a(value) "{{{ + +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))) @@ -51,9 +56,10 @@ function! s:increment_a(value) "{{{ call insert(list_of_chars, 'a') endif return join(list_of_chars, '') -endfunction "}}} +endfunction -function! s:increment_I(value) "{{{ + +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'], @@ -65,9 +71,10 @@ function! s:increment_I(value) "{{{ endif endfor return '' -endfunction "}}} +endfunction -function! s:increment_i(value) "{{{ + +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'], @@ -79,27 +86,29 @@ function! s:increment_i(value) "{{{ endif endfor return '' -endfunction "}}} +endfunction -"incrementation functions for the various kinds of numbers }}} -"utility functions {{{ +" --------------------------------------------------------- +" 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_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) "{{{ +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 "}}} +endfunction -if exists("*strdisplaywidth") "{{{ + +if exists("*strdisplaywidth") function! s:string_length(str) return strdisplaywidth(a:str) endfunction @@ -107,42 +116,48 @@ else function! s:string_length(str) return strlen(substitute(a:str, '.', 'x', 'g')) endfunction -endif "}}} +endif -function! vimwiki#lst#default_symbol() "{{{ - return g:vimwiki_list_markers[0] -endfunction "}}} -function! vimwiki#lst#get_list_margin() "{{{ - if VimwikiGet('list_margin') < 0 +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 - return VimwikiGet('list_margin') + return list_margin endif -endfunction "}}} +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), g:vimwiki_rxListItem)) -endfunction "}}} +function! s:text_begin(lnum) + return s:string_length(matchstr(getline(a:lnum), vimwiki#vars#get_syntaxlocal('rxListItem'))) +endfunction + "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) =~# g:vimwiki_rxListItem.'\s*$' +function! s:line_has_marker(lnum) + if getline(a:lnum) =~# vimwiki#vars#get_syntaxlocal('rxListItem').'\s*$' return 1 - elseif getline(a:lnum) =~# g:vimwiki_rxListItem.'\s*\S' + elseif getline(a:lnum) =~# vimwiki#vars#get_syntaxlocal('rxListItem').'\s*\S' return 2 else return 0 endif -endfunction "}}} +endfunction -"utility functions }}} -"get properties of an item {{{ +" --------------------------------------------------------- +" 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 @@ -150,14 +165,14 @@ endfunction "}}} "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) "{{{ +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), g:vimwiki_rxListItem) + let matches = matchlist(getline(a:lnum), vimwiki#vars#get_syntaxlocal('rxListItem')) if matches == [] || \ (matches[1] == '' && matches[2] == '') || \ (matches[1] != '' && matches[2] != '') @@ -176,48 +191,54 @@ function! s:get_item(lnum) "{{{ endif return item -endfunction "}}} +endfunction -function! s:empty_item() "{{{ + +function! s:empty_item() return {'type': 0} -endfunction "}}} +endfunction + "Returns: level of the line "0 is the 'highest' level -function! s:get_level(lnum) "{{{ - if getline(a:lnum) =~ '^\s*$' +function! s:get_level(lnum) + if getline(a:lnum) =~# '^\s*$' return 0 endif - if VimwikiGet('syntax') != 'media' + if !vimwiki#vars#get_syntaxlocal('recurring_bullets') let level = indent(a:lnum) else - let level = s:string_length(matchstr(getline(a:lnum), s:rx_bullet_chars))-1 + 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) "{{{ +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:] - if number_chars =~ '\d\+' + 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(s:number_kinds, 'i') == -1 + 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(s:number_kinds, 'a') == -1 || + 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' @@ -225,7 +246,7 @@ function! s:guess_kind_of_numbered_item(item) "{{{ return 'a' endif else - if number_chars =~# 'i\+' || index(s:number_kinds, 'a') == -1 + if number_chars =~# 'i\+' || index(number_kinds, 'a') == -1 return 'i' else return 'a' @@ -235,13 +256,13 @@ function! s:guess_kind_of_numbered_item(item) "{{{ endif endif if number_chars =~# '\u\+' - if number_chars !~# '^[IVXLCDM]\+' || index(s:number_kinds, 'I') == -1 + 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(s:number_kinds, 'A') == -1 || + 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' @@ -249,7 +270,7 @@ function! s:guess_kind_of_numbered_item(item) "{{{ return 'A' endif else - if number_chars =~# 'I\+' || index(s:number_kinds, 'A') == -1 + if number_chars =~# 'I\+' || index(number_kinds, 'A') == -1 return 'I' else return 'A' @@ -258,14 +279,16 @@ function! s:guess_kind_of_numbered_item(item) "{{{ endif endif -endfunction "}}} +endfunction -function! s:regexp_of_marker(item) "{{{ + +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.'\+['.s:number_divisors.']') + let match = matchstr(a:item.mrkr, '\'.ki.'\+['.number_divisors.']') if match != '' return '\'.ki.'\+'.vimwiki#u#escape(match[-1:]) endif @@ -273,15 +296,23 @@ function! s:regexp_of_marker(item) "{{{ else return '' endif -endfunction "}}} +endfunction -"get properties of an item }}} -"functions for navigating between items {{{ +" 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) "{{{ +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) @@ -300,11 +331,12 @@ function! s:get_next_list_item(item, ignore_kind) "{{{ let cur_ln = s:get_next_line(cur_ln) endwhile return s:empty_item() -endfunction "}}} +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) "{{{ +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) @@ -323,9 +355,10 @@ function! s:get_prev_list_item(item, ignore_kind) "{{{ let cur_ln = s:get_prev_line(cur_ln) endwhile return s:empty_item() -endfunction "}}} +endfunction -function! s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex) "{{{ + +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' @@ -336,17 +369,19 @@ function! s:get_item_of_level(cur_ln, cur_lvl, org_lvl, org_regex) "{{{ elseif a:cur_lvl < a:org_lvl return s:empty_item() endif -endfunction "}}} +endfunction -function! s:get_any_item_of_level(cur_ln, cur_lvl, org_lvl) "{{{ + +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 "}}} +endfunction -function! s:get_first_item_in_list(item, ignore_kind) "{{{ + +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) @@ -357,9 +392,10 @@ function! s:get_first_item_in_list(item, ignore_kind) "{{{ endif endwhile return cur_item -endfunction "}}} +endfunction -function! s:get_last_item_in_list(item, ignore_kind) "{{{ + +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) @@ -370,17 +406,17 @@ function! s:get_last_item_in_list(item, ignore_kind) "{{{ endif endwhile return cur_item -endfunction "}}} +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) =~# '^\s*'.g:vimwiki_rxPreStart +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) !~# '^\s*'.g:vimwiki_rxPreEnd.'\s*$' + while cur_ln <= line('$') && getline(cur_ln) !~# vimwiki#vars#get_syntaxlocal('rxPreEnd') let cur_ln += 1 endwhile let next_line = cur_ln @@ -388,27 +424,28 @@ function! s:get_next_line(lnum, ...) "{{{ let next_line = nextnonblank(a:lnum+1) endif - if a:0 > 0 && getline(next_line) =~# g:vimwiki_rxHeader + 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) =~# g:vimwiki_rxHeader && a:0 == 0) + \ (getline(next_line) =~# vimwiki#vars#get_syntaxlocal('rxHeader') && a:0 == 0) return 0 endif return next_line -endfunction "}}} +endfunction + "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) "{{{ +function! s:get_prev_line(lnum) let prev_line = prevnonblank(a:lnum-1) - if getline(prev_line) =~# '^\s*'.g:vimwiki_rxPreEnd.'\s*$' + if getline(prev_line) =~# vimwiki#vars#get_syntaxlocal('rxPreEnd') let cur_ln = a:lnum - 1 while 1 - if cur_ln == 0 || getline(cur_ln) =~# '^\s*'.g:vimwiki_rxPreStart + if cur_ln == 0 || getline(cur_ln) =~# vimwiki#vars#get_syntaxlocal('rxPreStart') break endif let cur_ln -= 1 @@ -417,14 +454,15 @@ function! s:get_prev_line(lnum) "{{{ endif if prev_line < 0 || prev_line > line('$') || - \ getline(prev_line) =~# g:vimwiki_rxHeader + \ getline(prev_line) =~# vimwiki#vars#get_syntaxlocal('rxHeader') return 0 endif return prev_line -endfunction "}}} +endfunction -function! s:get_first_child(item) "{{{ + +function! s:get_first_child(item) if a:item.lnum >= line('$') return s:empty_item() endif @@ -434,19 +472,18 @@ function! s:get_first_child(item) "{{{ if cur_item.type != 0 && s:get_level(cur_item.lnum) > org_lvl return cur_item endif - if cur_item.lnum > line('$') || cur_item.lnum <= 0 || - \ s:get_level(cur_item.lnum) <= org_lvl + if cur_item.lnum > line('$') || cur_item.lnum <= 0 || s:get_level(cur_item.lnum) <= org_lvl return s:empty_item() endif let cur_item = s:get_item(s:get_next_line(cur_item.lnum)) endwhile -endfunction "}}} +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) "{{{ +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) @@ -462,9 +499,10 @@ function! s:get_next_child_item(parent, child) "{{{ endif endwhile return s:empty_item() -endfunction "}}} +endfunction -function! s:get_parent(item) "{{{ + +function! s:get_parent(item) let parent_line = 0 let cur_ln = prevnonblank(a:item.lnum) @@ -488,10 +526,11 @@ function! s:get_parent(item) "{{{ endif endwhile return s:get_item(parent_line) -endfunction "}}} +endfunction + "Returns: the item above or the item below or an empty item -function! s:get_a_neighbor_item(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 @@ -502,9 +541,10 @@ function! s:get_a_neighbor_item(item) "{{{ endif endif return s:empty_item() -endfunction "}}} +endfunction -function! s:get_a_neighbor_item_in_column(lnum, column) "{{{ + +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 @@ -513,11 +553,12 @@ function! s:get_a_neighbor_item_in_column(lnum, column) "{{{ let cur_ln = s:get_prev_line(cur_ln) endwhile return s:empty_item() -endfunction "}}} +endfunction + "Returns: the item if there is one in a:lnum "else the multiline item a:lnum belongs to -function! s:get_corresponding_item(lnum) "{{{ +function! s:get_corresponding_item(lnum) let item = s:get_item(a:lnum) if item.type != 0 return item @@ -536,10 +577,11 @@ function! s:get_corresponding_item(lnum) "{{{ let cur_ln = s:get_prev_line(cur_ln) endwhile return s:empty_item() -endfunction "}}} +endfunction + "Returns: the last line of a (possibly multiline) item, including all children -function! s:get_last_line_of_item_incl_children(item) "{{{ +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 @@ -549,11 +591,12 @@ function! s:get_last_line_of_item_incl_children(item) "{{{ endif let cur_ln = next_line endwhile -endfunction "}}} +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) "{{{ +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 @@ -568,20 +611,21 @@ function! s:get_last_line_of_item(item) "{{{ 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)) + let cur_ln = s:get_next_line(s:get_last_line_of_item_incl_children(cur_item)) endif endwhile return last_corresponding_line -endfunction "}}} +endfunction -"functions for navigating between items }}} -"renumber list items {{{ +" --------------------------------------------------------- +" 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) "{{{ +function! s:adjust_numbered_list_below(item, recursive) if !(a:item.type == 2 || (a:item.type == 1 && a:recursive)) return a:item endif @@ -608,9 +652,10 @@ function! s:adjust_numbered_list_below(item, recursive) "{{{ let cur_item = next_item endwhile return cur_item -endfunction "}}} +endfunction -function! s:adjust_items_recursively(parent) "{{{ + +function! s:adjust_items_recursively(parent) if a:parent.type == 0 return s:empty_item() end @@ -627,13 +672,14 @@ function! s:adjust_items_recursively(parent) "{{{ return last_item endif endwhile -endfunction "}}} +endfunction + "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) "{{{ +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 @@ -642,10 +688,8 @@ function! s:adjust_numbered_list(item, ignore_kind, recursive) "{{{ 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 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 @@ -657,20 +701,22 @@ function! s:adjust_numbered_list(item, ignore_kind, recursive) "{{{ endif let first_item = next_first_item endwhile -endfunction "}}} +endfunction + "Renumbers the list the cursor is in "also update its parents checkbox state -function! vimwiki#lst#adjust_numbered_list() "{{{ +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 "}}} +endfunction + "Renumbers all lists of the buffer "of course, this might take some seconds -function! vimwiki#lst#adjust_whole_buffer() "{{{ +function! vimwiki#lst#adjust_whole_buffer() let cur_ln = 1 while 1 let cur_item = s:get_item(cur_ln) @@ -682,24 +728,30 @@ function! vimwiki#lst#adjust_whole_buffer() "{{{ return endif endwhile -endfunction "}}} +endfunction -"renumber list items }}} -"checkbox stuff {{{ +" --------------------------------------------------------- +" checkbox stuff +" --------------------------------------------------------- "Returns: the rate of checkboxed list item in percent -function! s:get_rate(item) "{{{ +function! s:get_rate(item) if a:item.type == 0 || a:item.cb == '' return -1 endif let state = a:item.cb - return index(g:vimwiki_listsyms_list, state) * 25 -endfunction "}}} + 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) "{{{ +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 @@ -708,12 +760,50 @@ function! s:set_state(item, new_rate) "{{{ else return 0 endif -endfunction "}}} +endfunction -"Set state of the list item to [ ] or [o] or whatever -"Updates the states of its child items -function! s:set_state_plus_children(item, new_rate) "{{{ - call s:set_state(a:item, a:new_rate) + +" Sets the state of the list item to [ ] or [o] or whatever. Updates the states of its child items. +" If the new state should be [X] or [-], the state of the current list item is changed to this +" state, but if a child item already has [X] or [-] it is left alone. +function! s:set_state_plus_children(item, new_rate, ...) + let retain_state_if_closed = a:0 > 0 && a:1 > 0 + + if !(retain_state_if_closed && (a:new_rate == 100 || a:new_rate == -1) && s:is_closed(a:item)) + call s:set_state(a:item, a:new_rate) + endif + + let all_children_are_done = 1 + let all_children_are_rejected = 1 + + let child_item = s:get_first_child(a:item) + while 1 + if child_item.type == 0 + break + endif + if child_item.cb != vimwiki#vars#get_global('listsym_rejected') + let all_children_are_rejected = 0 + endif + if child_item.cb != vimwiki#vars#get_syntaxlocal('listsyms_list')[-1] + let all_children_are_done = 0 + endif + if !all_children_are_done && !all_children_are_rejected + break + endif + let child_item = s:get_next_child_item(a:item, child_item) + endwhile + + if (a:new_rate == 100 && all_children_are_done) || + \ (a:new_rate == -1) && all_children_are_rejected + return + endif + + if (a:new_rate == -1 && all_children_are_done) || + \ (a:new_rate == 100 && all_children_are_rejected) + let retain_closed_children = 0 + else + let retain_closed_children = 1 + endif let child_item = s:get_first_child(a:item) while 1 @@ -721,38 +811,42 @@ function! s:set_state_plus_children(item, new_rate) "{{{ break endif if child_item.cb != '' - call s:set_state_plus_children(child_item, a:new_rate) + call s:set_state_plus_children(child_item, a:new_rate, retain_closed_children) endif let child_item = s:get_next_child_item(a:item, child_item) endwhile -endfunction "}}} +endfunction + "Returns: the appropriate symbol for a given percent rate -function! s:rate_to_state(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 = g:vimwiki_listsyms_list[4] + let state = listsyms_list[n-1] elseif a:rate == 0 - let state = g:vimwiki_listsyms_list[0] - elseif a:rate >= 67 - let state = g:vimwiki_listsyms_list[3] - elseif a:rate >= 34 - let state = g:vimwiki_listsyms_list[2] + let state = listsyms_list[0] + elseif a:rate == -1 + let state = vimwiki#vars#get_global('listsym_rejected') else - let state = g:vimwiki_listsyms_list[1] + let index = float2nr(ceil(a:rate/100.0*(n-2))) + let state = listsyms_list[index] endif return state -endfunction "}}} +endfunction + "updates the symbol of a checkboxed item according to the symbols of its "children -function! s:update_state(item) "{{{ +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 child_item = s:get_first_child(a:item) @@ -761,14 +855,25 @@ function! s:update_state(item) "{{{ 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 += s:get_rate(child_item) + let sum_children_rate += rate endif let child_item = s:get_next_child_item(a:item, child_item) endwhile if count_children_with_cb > 0 - let new_rate = sum_children_rate / count_children_with_cb + if count_rejected_children == count_children_with_cb + let new_rate = -1 + else + let new_rate = sum_children_rate / count_children_with_cb + endif call s:set_state_recursively(a:item, new_rate) else let rate = s:get_rate(a:item) @@ -776,43 +881,46 @@ function! s:update_state(item) "{{{ call s:set_state_recursively(a:item, 0) endif endif -endfunction "}}} +endfunction -function! s:set_state_recursively(item, new_rate) "{{{ + +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 "}}} +endfunction + "Creates checkbox in a list item. "Returns: 1 if successful -function! s:create_cb(item) "{{{ +function! s:create_cb(item, start_rate) if a:item.type == 0 || a:item.cb != '' return 0 endif let new_item = a:item - let new_item.cb = g:vimwiki_listsyms_list[0] + let new_item.cb = s:rate_to_state(a:start_rate) call s:substitute_rx_in_line(new_item.lnum, \ vimwiki#u#escape(new_item.mrkr) . '\zs\ze', ' [' . new_item.cb . ']') call s:update_state(new_item) return 1 -endfunction "}}} +endfunction -function! s:remove_cb(item) "{{{ + +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 "}}} +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) "{{{ + +" 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 @@ -820,13 +928,39 @@ function! vimwiki#lst#toggle_cb(from_line, to_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) + 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 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) + let success = s:create_cb(cur_item, a:start_rate) if success let cur_parent_item = s:get_parent(cur_item) @@ -836,32 +970,74 @@ function! vimwiki#lst#toggle_cb(from_line, to_line) "{{{ 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==100 ? 0 : 100 + let new_rate = rate_first_line == a:state1 ? a:state2 : a:state1 - 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, 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 + call s:change_cb(a:from_line, a:to_line, new_rate) endif - for parent_item in parent_items_of_lines - call s:update_state(parent_item) - endfor +endfunction -endfunction "}}} -function! vimwiki#lst#remove_cb(first_line, last_line) "{{{ +"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) @@ -886,11 +1062,11 @@ function! vimwiki#lst#remove_cb(first_line, last_line) "{{{ for parent_item in parent_items_of_lines call s:update_state(parent_item) endfor -endfunction "}}} +endfunction -function! vimwiki#lst#remove_cb_in_list() "{{{ - let first_item = s:get_first_item_in_list( - \ s:get_corresponding_item(line('.')), 0) + +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 @@ -904,96 +1080,101 @@ function! vimwiki#lst#remove_cb_in_list() "{{{ endwhile call s:update_state(s:get_parent(first_item)) -endfunction "}}} +endfunction -"checkbox stuff }}} -"change the level of list items {{{ -function! s:set_indent(lnum, new_indent) "{{{ +" --------------------------------------------------------- +" 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) + let indentstring = repeat('\t', a:new_indent / &tabstop) . repeat(' ', a:new_indent % &tabstop) endif call s:substitute_rx_in_line(a:lnum, '^\s*', indentstring) -endfunction "}}} +endfunction -function! s:decrease_level(item) "{{{ + +function! s:decrease_level(item) let removed_indent = 0 - if VimwikiGet('syntax') == 'media' && a:item.type == 1 && - \ index(s:multiple_bullet_chars, s:first_char(a:item.mrkr)) > -1 + 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), '') + 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) / &shiftwidth * &shiftwidth + let new_indent = (old_indent - 1) / vimwiki#u#sw() * vimwiki#u#sw() else - let new_indent = old_indent - &shiftwidth + 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 "}}} +endfunction -function! s:increase_level(item) "{{{ + +function! s:increase_level(item) let additional_indent = 0 - if VimwikiGet('syntax') == 'media' && a:item.type == 1 && - \ index(s:multiple_bullet_chars, s:first_char(a:item.mrkr)) > -1 + 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 / &shiftwidth + 1) * &shiftwidth + let new_indent = (old_indent / vimwiki#u#sw() + 1) * vimwiki#u#sw() else - let new_indent = old_indent + &shiftwidth + 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 "}}} +endfunction + "adds a:indent_by to the current indent "a:indent_by can be negative -function! s:indent_line_by(lnum, indent_by) "{{{ +function! s:indent_line_by(lnum, indent_by) let item = s:get_item(a:lnum) - if VimwikiGet('syntax') == 'media' && item.type == 1 && - \ index(s:multiple_bullet_chars, s:first_char(item.mrkr)) > -1 + 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)) + 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 "}}} +endfunction + "changes lvl of lines in selection -function! s:change_level(from_line, to_line, direction, plus_children) "{{{ +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)) + 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 - execute a:from_line.','.a:to_line.(a:direction == 'increase' ? '>' : '<') + execute a:from_line.','.a:to_line.(a:direction ==# 'increase' ? '>' : '<') endif return endif - if a:direction == 'decrease' && s:get_level(from_item.lnum) == 0 + if a:direction ==# 'decrease' && s:get_level(from_item.lnum) == 0 return endif @@ -1025,8 +1206,7 @@ function! s:change_level(from_line, to_line, direction, plus_children) "{{{ 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') ? + 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) @@ -1056,72 +1236,81 @@ function! s:change_level(from_line, to_line, direction, plus_children) "{{{ call s:adjust_numbered_list(from_item, 0, 0) call s:adjust_numbered_list(to_be_adjusted, 0, 0) endif -endfunction "}}} +endfunction -function! vimwiki#lst#change_level(from_line, to_line, direction, plus_children) "{{{ + +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 "}}} +endfunction + "indent line a:lnum to be the continuation of a:prev_item -function! s:indent_multiline(prev_item, lnum) "{{{ +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 "}}} +endfunction -"change the level of list items }}} -"change markers of list items {{{ +" --------------------------------------------------------- +" change markers of list items +" --------------------------------------------------------- + "Returns: the position of a marker in g:vimwiki_list_markers -function! s:get_idx_list_markers(item) "{{{ +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(g:vimwiki_list_markers, m) -endfunction "}}} + 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) "{{{ +function! s:get_next_mrkr(item) + let markers = vimwiki#vars#get_syntaxlocal('list_markers') if a:item.type == 0 - let new_mrkr = g:vimwiki_list_markers[0] + let new_mrkr = markers[0] else let idx = s:get_idx_list_markers(a:item) - let new_mrkr = g:vimwiki_list_markers[(idx+1) % len(g:vimwiki_list_markers)] + let new_mrkr = markers[(idx+1) % len(markers)] endif return new_mrkr -endfunction "}}} +endfunction + "changes the marker of the given item to the previous in g:vimwiki_list_markers -function! s:get_prev_mrkr(item) "{{{ +function! s:get_prev_mrkr(item) + let markers = vimwiki#vars#get_syntaxlocal('list_markers') if a:item.type == 0 - return g:vimwiki_list_markers[-1] + return markers[-1] endif let idx = s:get_idx_list_markers(a:item) if idx == -1 - return g:vimwiki_list_markers[-1] + return markers[-1] else - return g:vimwiki_list_markers[(idx - 1 + len(g:vimwiki_list_markers)) % - \ len(g:vimwiki_list_markers)] + return markers[(idx - 1 + len(markers)) % len(markers)] endif -endfunction "}}} +endfunction -function! s:set_new_mrkr(item, new_mrkr) "{{{ + +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 && VimwikiGet('syntax') != 'media' + 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 "}}} +endfunction -function! vimwiki#lst#change_marker(from_line, to_line, new_mrkr, mode) "{{{ - let cur_col_from_eol = col("$") - (a:mode == "i" ? col("'^") : col('.')) + +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 @@ -1134,28 +1323,26 @@ function! vimwiki#lst#change_marker(from_line, to_line, new_mrkr, mode) "{{{ endif "handle markers like *** - if index(s:multiple_bullet_chars, s:first_char(new_mrkr)) > -1 + 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) + 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) + 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(s:multiple_bullet_chars,s:first_char(cur_item.mrkr))>-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) + 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 @@ -1173,9 +1360,10 @@ function! vimwiki#lst#change_marker(from_line, to_line, new_mrkr, mode) "{{{ endwhile call cursor('.', col('$') - cur_col_from_eol) -endfunction "}}} +endfunction -function! vimwiki#lst#change_marker_in_list(new_mrkr) "{{{ + +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) @@ -1189,11 +1377,12 @@ function! vimwiki#lst#change_marker_in_list(new_mrkr) "{{{ endwhile call s:adjust_numbered_list(s:get_item(first_item_line), 0, 0) -endfunction "}}} +endfunction + "sets kind of the item depending on neighbor items and the parent item -function! s:adjust_mrkr(item) "{{{ - if a:item.type == 0 || VimwikiGet('syntax') == 'media' +function! s:adjust_mrkr(item) + if a:item.type == 0 || vimwiki#vars#get_syntaxlocal('recurring_bullets') return endif @@ -1205,37 +1394,38 @@ function! s:adjust_mrkr(item) "{{{ "if possible, set e.g. *** if parent has ** as marker if neighbor_item.type == 0 && a:item.type == 1 && - \ index(s:multiple_bullet_chars, s:first_char(a:item.mrkr)) > -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) + 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 "}}} +endfunction -function! s:clone_marker_from_to(from, to) "{{{ + +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 = ( VimwikiGet('syntax') != 'media' ? indent(a:from) : 0 ) + let new_indent = ( vimwiki#vars#get_syntaxlocal('recurring_bullets') ? 0 : indent(a:from) ) call s:set_indent(a:to, new_indent) if item_from.cb != '' - call s:create_cb(s:get_item(a:to)) + call s:create_cb(s:get_item(a:to), 0) call s:update_state(s:get_parent(s:get_item(a:to))) endif if item_from.type == 2 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 "}}} +endfunction -function! s:remove_mrkr(item) "{{{ + +function! s:remove_mrkr(item) let item = a:item if item.cb != '' let item = s:remove_cb(item) @@ -1249,9 +1439,10 @@ function! s:remove_mrkr(item) "{{{ let item.type = 0 call s:update_state(parent_item) return item -endfunction "}}} +endfunction -function! s:create_marker(lnum) "{{{ + +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('.')) @@ -1260,15 +1451,17 @@ function! s:create_marker(lnum) "{{{ 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, g:vimwiki_list_markers[0]) + 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 "}}} +endfunction -"change markers of list items }}} -"handle keys {{{ -function! vimwiki#lst#kbd_o() "{{{ +" --------------------------------------------------------- +" 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) @@ -1281,20 +1474,22 @@ function! vimwiki#lst#kbd_o() "{{{ call s:clone_marker_from_to(cur_item.lnum, cur_item.lnum+1) endif startinsert! -endfunction "}}} +endfunction -function! vimwiki#lst#kbd_O() "{{{ + +function! vimwiki#lst#kbd_O() normal! Ox let cur_ln = line('.') - if getline(cur_ln+1) !~ '^\s*$' + 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 "}}} +endfunction -function! s:cr_on_empty_list_item(lnum, behavior) "{{{ + +function! s:cr_on_empty_list_item(lnum, behavior) if a:behavior == 1 "just make a new list item normal! gi  @@ -1348,24 +1543,26 @@ function! s:cr_on_empty_list_item(lnum, behavior) "{{{ endif return endif -endfunction "}}} +endfunction -function! s:cr_on_empty_line(lnum, behavior) "{{{ + +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 "}}} +endfunction -function! s:cr_on_list_item(lnum, insert_new_marker, not_at_eol) "{{{ + +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) =~ ':$' + if !a:not_at_eol && getline(a:lnum) =~# ':$' call s:change_level(a:lnum+1, a:lnum+1, 'increase', 0) endif else @@ -1375,9 +1572,10 @@ function! s:cr_on_list_item(lnum, insert_new_marker, not_at_eol) "{{{ 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 "}}} +endfunction -function! vimwiki#lst#kbd_cr(normal, just_mrkr) "{{{ + +function! vimwiki#lst#kbd_cr(normal, just_mrkr) let lnum = line('.') let has_bp = s:line_has_marker(lnum) @@ -1393,17 +1591,17 @@ function! vimwiki#lst#kbd_cr(normal, just_mrkr) "{{{ endif let insert_new_marker = (a:normal == 1 || a:normal == 3) - if getline('.')[col("'^")-1:] =~ '^\s\+$' + if getline('.')[col("'^")-1:] =~# '^\s\+$' let cur_col = 0 else let cur_col = col("$") - col("'^") - if getline('.')[col("'^")-1] =~ '\s' && exists("*strdisplaywidth") + 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$' + if insert_new_marker && cur_col == 0 && getline(lnum) =~# '\s$' let insert_new_marker = 0 endif endif @@ -1423,10 +1621,11 @@ function! vimwiki#lst#kbd_cr(normal, just_mrkr) "{{{ startinsert endif -endfunction "}}} +endfunction + "creates a list item in the current line or removes it -function! vimwiki#lst#toggle_list_item() "{{{ +function! vimwiki#lst#toggle_list_item() let cur_col_from_eol = col("$") - col("'^") let cur_item = s:get_item(line('.')) @@ -1450,60 +1649,19 @@ function! vimwiki#lst#toggle_list_item() "{{{ 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*$' + if cur_col_from_eol == 0 || getline(cur_item.lnum) =~# '^\s*$' startinsert! else startinsert endif -endfunction "}}} +endfunction -"handle keys }}} -"misc stuff {{{ -function! vimwiki#lst#setup_marker_infos() "{{{ - let s:rx_bullet_chars = '['.join(keys(g:vimwiki_bullet_types), '').']\+' +" --------------------------------------------------------- +" misc stuff +" --------------------------------------------------------- - let s:multiple_bullet_chars = [] - for i in keys(g:vimwiki_bullet_types) - if g:vimwiki_bullet_types[i] == 1 - call add(s:multiple_bullet_chars, i) - endif - endfor - - let s:number_kinds = [] - let s:number_divisors = "" - for i in g:vimwiki_number_types - call add(s:number_kinds, i[0]) - let s:number_divisors .= vimwiki#u#escape(i[1]) - endfor - - let s:char_to_rx = {'1': '\d\+', 'i': '[ivxlcdm]\+', 'I': '[IVXLCDM]\+', - \ 'a': '\l\{1,2}', 'A': '\u\{1,2}'} - - "create regexp for bulleted list items - let g:vimwiki_rxListBullet = join( map(keys(g:vimwiki_bullet_types), - \'vimwiki#u#escape(v:val).repeat("\\+", g:vimwiki_bullet_types[v:val])' - \ ) , '\|') - - "create regex for numbered list items - if !empty(g:vimwiki_number_types) - let g:vimwiki_rxListNumber = '\C\%(' - for type in g:vimwiki_number_types[:-2] - let g:vimwiki_rxListNumber .= s:char_to_rx[type[0]] . - \ vimwiki#u#escape(type[1]) . '\|' - endfor - let g:vimwiki_rxListNumber .= s:char_to_rx[g:vimwiki_number_types[-1][0]]. - \ vimwiki#u#escape(g:vimwiki_number_types[-1][1]) . '\)' - else - "regex that matches nothing - let g:vimwiki_rxListNumber = '$^' - endif - - "the user can set the listsyms as string, but vimwiki needs a list - let g:vimwiki_listsyms_list = split(g:vimwiki_listsyms, '\zs') -endfunction "}}} - -function! vimwiki#lst#TO_list_item(inner, visual) "{{{ +function! vimwiki#lst#TO_list_item(inner, visual) let lnum = prevnonblank('.') let item = s:get_corresponding_item(lnum) if item.type == 0 @@ -1519,9 +1677,10 @@ function! vimwiki#lst#TO_list_item(inner, visual) "{{{ call cursor(to_line, 0) normal! o call cursor(from_line, 0) -endfunction "}}} +endfunction -fun! vimwiki#lst#fold_level(lnum) "{{{ + +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) @@ -1534,6 +1693,5 @@ fun! vimwiki#lst#fold_level(lnum) "{{{ endif endif return '=' -endf "}}} +endfunction -"misc stuff }}} diff --git a/autoload/vimwiki/markdown_base.vim b/autoload/vimwiki/markdown_base.vim index d79c09b..f1ce091 100644 --- a/autoload/vimwiki/markdown_base.vim +++ b/autoload/vimwiki/markdown_base.vim @@ -1,63 +1,44 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Desc: Link functions for markdown syntax -" Author: Stuart Andrews (.. i.e. don't blame Maxim!) -" Home: http://code.google.com/p/vimwiki/ +" Description: Link functions for markdown syntax +" Home: https://github.com/vimwiki/vimwiki/ -" MISC helper functions {{{ +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 -" vimwiki#markdown_base#reset_mkd_refs -function! vimwiki#markdown_base#reset_mkd_refs() "{{{ - call VimwikiClear('markdown_refs') -endfunction "}}} -" vimwiki#markdown_base#scan_reflinks -function! vimwiki#markdown_base#scan_reflinks() " {{{ +function! vimwiki#markdown_base#scan_reflinks() let mkd_refs = {} " construct list of references using vimgrep try - execute 'vimgrep #'.g:vimwiki_rxMkdRef.'#j %' + " 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, g:vimwiki_rxMkdRefMatchDescr) - let url = matchstr(matchline, g:vimwiki_rxMkdRefMatchUrl) + 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 VimwikiSet('markdown_refs', mkd_refs) + call vimwiki#vars#set_bufferlocal('markdown_refs', mkd_refs) return mkd_refs -endfunction "}}} +endfunction -" vimwiki#markdown_base#get_reflinks -function! vimwiki#markdown_base#get_reflinks() " {{{ - let done = 1 - try - let mkd_refs = VimwikiGet('markdown_refs') - catch - " work-around hack - let done = 0 - " ... the following command does not work inside catch block !? - " > let mkd_refs = vimwiki#markdown_base#scan_reflinks() - endtry - if !done - let mkd_refs = vimwiki#markdown_base#scan_reflinks() - endif - return mkd_refs -endfunction "}}} - -" vimwiki#markdown_base#open_reflink " try markdown reference links -function! vimwiki#markdown_base#open_reflink(link) " {{{ +function! vimwiki#markdown_base#open_reflink(link) " echom "vimwiki#markdown_base#open_reflink" let link = a:link - let mkd_refs = vimwiki#markdown_base#get_reflinks() + 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) @@ -65,197 +46,68 @@ function! vimwiki#markdown_base#open_reflink(link) " {{{ else return 0 endif -endfunction " }}} +endfunction -" s:normalize_path -" s:path_html -" vimwiki#base#apply_wiki_options -" vimwiki#base#read_wiki_options -" vimwiki#base#validate_wiki_options -" vimwiki#base#setup_buffer_state -" vimwiki#base#cache_buffer_state -" vimwiki#base#recall_buffer_state -" vimwiki#base#print_wiki_state -" vimwiki#base#mkdir -" vimwiki#base#file_pattern -" vimwiki#base#branched_pattern -" vimwiki#base#subdir -" vimwiki#base#current_subdir -" vimwiki#base#invsubdir -" vimwiki#base#resolve_scheme -" vimwiki#base#system_open_link -" vimwiki#base#open_link -" vimwiki#base#generate_links -" vimwiki#base#goto -" vimwiki#base#backlinks -" vimwiki#base#get_links -" vimwiki#base#edit_file -" vimwiki#base#search_word -" vimwiki#base#matchstr_at_cursor -" vimwiki#base#replacestr_at_cursor -" s:print_wiki_list -" s:update_wiki_link -" s:update_wiki_links_dir -" s:tail_name -" s:update_wiki_links -" s:get_wiki_buffers -" s:open_wiki_buffer -" vimwiki#base#nested_syntax -" }}} -" WIKI link following functions {{{ -" vimwiki#base#find_next_link -" vimwiki#base#find_prev_link - -" vimwiki#base#follow_link -function! vimwiki#markdown_base#follow_link(split, ...) "{{{ Parse link at cursor and pass - " to VimwikiLinkHandler, or failing that, the default open_link handler - " echom "markdown_base#follow_link" - - if 0 - " Syntax-specific links - " XXX: @Stuart: do we still need it? - " XXX: @Maxim: most likely! I am still working on a seemless way to - " integrate regexp's without complicating syntax/vimwiki.vim - else - if a:split == "split" - let cmd = ":split " - elseif a:split == "vsplit" - let cmd = ":vsplit " - elseif a:split == "tabnew" - let cmd = ":tabnew " - else - let cmd = ":e " - endif - - " try WikiLink - let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiLink), - \ g:vimwiki_rxWikiLinkMatchUrl) - " try WikiIncl - if lnk == "" - let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiIncl), - \ g:vimwiki_rxWikiInclMatchUrl) - endif - " try Weblink - if lnk == "" - let lnk = matchstr(vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWeblink), - \ g:vimwiki_rxWeblinkMatchUrl) - endif - - if lnk != "" - if !VimwikiLinkHandler(lnk) - if !vimwiki#markdown_base#open_reflink(lnk) - call vimwiki#base#open_link(cmd, lnk) - endif - endif - return - endif - - if a:0 > 0 - execute "normal! ".a:1 - else - call vimwiki#base#normalize_link(0) - endif - endif - -endfunction " }}} - -" vimwiki#base#go_back_link -" vimwiki#base#goto_index -" vimwiki#base#delete_link -" vimwiki#base#rename_link -" vimwiki#base#ui_select - -" TEXT OBJECTS functions {{{ -" vimwiki#base#TO_header -" vimwiki#base#TO_table_cell -" vimwiki#base#TO_table_col -" }}} - -" HEADER functions {{{ -" vimwiki#base#AddHeaderLevel -" vimwiki#base#RemoveHeaderLevel -"}}} - -" LINK functions {{{ -" vimwiki#base#apply_template - -" s:clean_url -" vimwiki#base#normalize_link_helper -" vimwiki#base#normalize_imagelink_helper - -" s:normalize_link_syntax_n -function! s:normalize_link_syntax_n() " {{{ +function! s:normalize_link_syntax_n() let lnum = line('.') " try WikiIncl - let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiIncl) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_global('rxWikiIncl')) if !empty(lnk) " NO-OP !! - if g:vimwiki_debug > 1 - echomsg "WikiIncl: ".lnk." Sub: ".lnk - endif return endif " try WikiLink0: replace with WikiLink1 - let lnk = vimwiki#base#matchstr_at_cursor(g:vimwiki_rxWikiLink0) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink0')) if !empty(lnk) let sub = vimwiki#base#normalize_link_helper(lnk, - \ g:vimwiki_rxWikiLinkMatchUrl, g:vimwiki_rxWikiLinkMatchDescr, - \ g:vimwiki_WikiLink1Template2) - call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWikiLink0, sub) - if g:vimwiki_debug > 1 - echomsg "WikiLink: ".lnk." Sub: ".sub - endif + \ 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(g:vimwiki_rxWikiLink1) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWikiLink1')) if !empty(lnk) let sub = vimwiki#base#normalize_link_helper(lnk, - \ g:vimwiki_rxWikiLinkMatchUrl, g:vimwiki_rxWikiLinkMatchDescr, - \ g:vimwiki_WikiLinkTemplate2) - call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWikiLink1, sub) - if g:vimwiki_debug > 1 - echomsg "WikiLink: ".lnk." Sub: ".sub - endif + \ 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(g:vimwiki_rxWeblink) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_syntaxlocal('rxWeblink')) if !empty(lnk) let sub = vimwiki#base#normalize_link_helper(lnk, - \ g:vimwiki_rxWeblinkMatchUrl, g:vimwiki_rxWeblinkMatchDescr, - \ g:vimwiki_Weblink1Template) - call vimwiki#base#replacestr_at_cursor(g:vimwiki_rxWeblink, sub) - if g:vimwiki_debug > 1 - echomsg "WebLink: ".lnk." Sub: ".sub - endif + \ 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(g:vimwiki_rxWord) + let lnk = vimwiki#base#matchstr_at_cursor(vimwiki#vars#get_global('rxWord')) if !empty(lnk) let sub = vimwiki#base#normalize_link_helper(lnk, - \ g:vimwiki_rxWord, '', - \ g:vimwiki_WikiLinkTemplate1) + \ vimwiki#vars#get_global('rxWord'), '', + \ vimwiki#vars#get_syntaxlocal('Weblink1Template')) call vimwiki#base#replacestr_at_cursor('\V'.lnk, sub) - if g:vimwiki_debug > 1 - echomsg "Word: ".lnk." Sub: ".sub - endif return endif -endfunction " }}} +endfunction -" s:normalize_link_syntax_v -function! s:normalize_link_syntax_v() " {{{ + +function! s:normalize_link_syntax_v() let lnum = line('.') let sel_save = &selection let &selection = "old" @@ -266,37 +118,33 @@ function! s:normalize_link_syntax_v() " {{{ try norm! gvy let visual_selection = @" - let visual_selection = substitute(g:vimwiki_WikiLinkTemplate1, '__LinkUrl__', '\='."'".visual_selection."'", '') + let link = s:safesubstitute(vimwiki#vars#get_syntaxlocal('Weblink1Template'), + \ '__LinkUrl__', visual_selection, '') + let link = s:safesubstitute(link, '__LinkDescription__', visual_selection, '') - call setreg('"', visual_selection, 'v') + call setreg('"', substitute(link, '\n', '', ''), visualmode()) " paste result - norm! `>pgvd + norm! `>""pgvd finally call setreg('"', rv, rt) let &selection = sel_save endtry -endfunction " }}} +endfunction -" vimwiki#base#normalize_link -function! vimwiki#markdown_base#normalize_link(is_visual_mode) "{{{ + +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 visualmode() ==# 'v' && line("'<") == line("'>") - " action undefined for 'line-wise' or 'multi-line' visual mode selections + elseif line("'<") == line("'>") + " action undefined for multi-line visual mode selections call s:normalize_link_syntax_v() endif endif -endfunction "}}} - -" }}} - -" ------------------------------------------------------------------------- -" Load syntax-specific Wiki functionality -" ------------------------------------------------------------------------- +endfunction diff --git a/autoload/vimwiki/path.vim b/autoload/vimwiki/path.vim new file mode 100644 index 0000000..367b1d7 --- /dev/null +++ b/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/autoload/vimwiki/style.css b/autoload/vimwiki/style.css index 752867b..a5f11b9 100644 --- a/autoload/vimwiki/style.css +++ b/autoload/vimwiki/style.css @@ -24,42 +24,46 @@ 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 */ +.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; - margin-left: -2em; padding-left: 1.5em; } .done1 { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABtSURBVCiR1ZO7DYAwDER9BDmTeZQMFXmUbGYpOjrEryA0wOvO8itOslFrJYAug5BMM4BeSkmjsrv3aVTa8p48Xw1JSkSsWVUFwD05IqS1tmYzk5zzae9jnVVVzGyXb8sALjse+euRkEzu/uirFomVIdDGOLjuAAAAAElFTkSuQmCC); background-repeat: no-repeat; background-position: 0 .15em; - margin-left: -2em; padding-left: 1.5em; } .done2 { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAB1SURBVCiRzdO5DcAgDAVQGxjAYgTvxlDIu1FTIRYAp8qlFISkSH7l5kk+ZIwxKiI2mIyqWoeILYRgZ7GINDOLjnmF3VqklKCUMgTee2DmM661Qs55iI3Zm/1u5h9sm4ig9z4ERHTFzLyd4G4+nFlVrYg8+qoF/c0kdpeMsmcAAAAASUVORK5CYII=); background-repeat: no-repeat; background-position: 0 .15em; - margin-left: -2em; padding-left: 1.5em; } .done3 { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAxQAAAMUBHc26qAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABoSURBVCiR7dOxDcAgDATA/0DtUdiKoZC3YhLkHjkVKF3idJHiztKfvrHZWnOSE8Fx95RJzlprimJVnXktvXeY2S0SEZRSAAAbmxnGGKH2I5T+8VfxPhIReQSuuY3XyYWa3T2p6quvOgGrvSFGlewuUAAAAABJRU5ErkJggg==); background-repeat: no-repeat; background-position: 0 .15em; - margin-left: -2em; padding-left: 1.5em; } .done4 { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAzgAAAM4BlP6ToAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIISURBVDiNnZQ9SFtRFMd/773kpTaGJoQk1im4VDpWQcTNODhkFBcVTCNCF0NWyeDiIIiCm82QoIMIUkHUxcFBg1SEQoZszSat6cdTn1qNue92CMbEr9Sey+XC/Z/zu+f8h6ukUil3sVg0+M+4cFxk42/jH2wAqqqKSCSiPQdwcHHAnDHH9s/tN1h8V28ETdP+eU8fT9Nt62ancYdIPvJNtsu87bmjrJlrTDVM4RROJs1JrHPrD4Bar7A6cpc54iKOaTdJXCUI2UMVrQZ0Js7YPN18ECKkYNQcJe/OE/4dZsw7VqNXQMvHy3QZXQypQ6ycrtwDjf8aJ+PNEDSCzLpn7+m2pD8ZKHlKarYhy6XjEoCYGcN95qansQeA3fNdki+SaJZGTMQIOoL3W/Z89rxv+tokubNajlvk/vm+LFpF2XnUKZHI0I+QrI7Dw0OZTqdzUkpsM7mZTyfy5OPGyw1tK7AFSvmB/Ks8w8YwbUYbe6/3QEKv0vugfxWPnMLJun+d/kI/WLdizpNjMbAIKrhMF4OuwadBALqqs+RfInwUvuNi+fBd+wjogfogAFVRmffO02q01mZZ0HHdgXIzdz0QQLPezIQygX6llxNKKgOFARYCC49CqhoHIUTlss/Vx2phlYwjw8j1CAlfAiwQiJpiy7o1VHnsG5FISkoJu7Q/2YmmaV+i0ei7v38L2CBguSi5AAAAAElFTkSuQmCC); background-repeat: no-repeat; background-position: 0 .15em; - margin-left: -2em; padding-left: 1.5em; } diff --git a/autoload/vimwiki/tags.vim b/autoload/vimwiki/tags.vim new file mode 100644 index 0000000..e802bce --- /dev/null +++ b/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/autoload/vimwiki/u.vim b/autoload/vimwiki/u.vim index f838988..c8f62ee 100644 --- a/autoload/vimwiki/u.vim +++ b/autoload/vimwiki/u.vim @@ -1,10 +1,9 @@ -" vim:tabstop=2:shiftwidth=2:expandtab:foldmethod=marker:textwidth=79 +" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99 " Vimwiki autoload plugin file -" Utility functions -" Author: Maxim Kim -" Home: http://code.google.com/p/vimwiki/ +" Description: Utility functions +" Home: https://github.com/vimwiki/vimwiki/ -function! vimwiki#u#trim(string, ...) "{{{ +function! vimwiki#u#trim(string, ...) let chars = '' if a:0 > 0 let chars = a:1 @@ -12,83 +11,62 @@ function! vimwiki#u#trim(string, ...) "{{{ let res = substitute(a:string, '^[[:space:]'.chars.']\+', '', '') let res = substitute(res, '[[:space:]'.chars.']\+$', '', '') return res -endfunction "}}} +endfunction " Builtin cursor doesn't work right with unicode characters. -function! vimwiki#u#cursor(lnum, cnum) "{{{ +function! vimwiki#u#cursor(lnum, cnum) exe a:lnum exe 'normal! 0'.a:cnum.'|' -endfunction "}}} +endfunction -function! vimwiki#u#is_windows() "{{{ + +function! vimwiki#u#is_windows() return has("win32") || has("win64") || has("win95") || has("win16") -endfunction "}}} +endfunction -function! vimwiki#u#chomp_slash(str) "{{{ - return substitute(a:str, '[/\\]\+$', '', '') -endfunction "}}} -function! vimwiki#u#time(starttime) "{{{ - " measure the elapsed time and cut away miliseconds and smaller - return matchstr(reltimestr(reltime(a:starttime)),'\d\+\(\.\d\d\)\=') -endfunction "}}} - -function! vimwiki#u#path_norm(path) "{{{ - " /-slashes - 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#u#is_link_to_dir(link) "{{{ - " Check if link is to a directory. - " It should be ended with \ or /. - if a:link =~ '.\+[/\\]$' +function! vimwiki#u#is_macos() + if has("mac") || has("macunix") || has("gui_mac") return 1 endif - return 0 -endfunction " }}} + " 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) "{{{ + +function! vimwiki#u#count_first_sym(line) let first_sym = matchstr(a:line, '\S') return len(matchstr(a:line, first_sym.'\+')) -endfunction "}}} +endfunction -" return longest common path prefix of 2 given paths. -" '~/home/usrname/wiki', '~/home/usrname/wiki/shmiki' => '~/home/usrname/wiki' -function! vimwiki#u#path_common_pfx(path1, path2) "{{{ - let p1 = split(a:path1, '[/\\]', 1) - let p2 = split(a:path2, '[/\\]', 1) - let idx = 0 - let minlen = min([len(p1), len(p2)]) - while (idx < minlen) && (p1[idx] ==? p2[idx]) - let idx = idx + 1 - endwhile - if idx == 0 - return '' - else - return join(p1[: idx-1], '/') - endif -endfunction "}}} +function! vimwiki#u#escape(string) + return escape(a:string, '~.*[]\^$') +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_'.VimwikiGet('syntax').'.vim' -endfunction "}}} +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_'.VimwikiGet('syntax').'_custom.vim' -endfunction "}}} +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/autoload/vimwiki/vars.vim b/autoload/vimwiki/vars.vim new file mode 100644 index 0000000..d60a561 --- /dev/null +++ b/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_
  • '] - let spaninfo = s:makespaninfolist(len(matrix_body[0])) - for line in matrix_body - let old_spaninfo = spaninfo - let spaninfo = s:makespaninfolist(len(line)) - for idx in range(len(spaninfo)) - let spaninfo[idx][0] = len(old_spaninfo) > idx ? old_spaninfo[idx][0] : 1 - endfor - - call add(result, '') - for idx in range(len(line)-1, 0, -1) - let cell = line[idx] - if cell =~ '^\s*>\s*' - if idx > 0 - let spaninfo[idx-1][1] = spaninfo[idx][1] + 1 - else - call add(result, '') - endif - elseif cell =~ '^\s*\\\/\s*' - let spaninfo[idx][0] += 1 - else - let htmlspaninfo = '' - if spaninfo[idx][1] > 1 - let htmlspaninfo .= ' colspan="' . spaninfo[idx][1] . '"' - endif - if spaninfo[idx][0] > 1 - let htmlspaninfo .= ' rowspan="' . spaninfo[idx][0] . '"' - let spaninfo[idx][0] = 1 - endif - call add(result, ''.vimwiki#vw2html#process_line(cell).'') - endif - endfor - call add(result, '') - endfor - call add(result, '') - return join(reverse(result), '') -endf - -unlet! s:grammar -let s:grammar = ' - \ file = ((emptyline | header | hline | paragraph.tag("p"))°).applytemplate() - \ emptyline = /\s*\r/.skip() - \ header = /\s*\(=\{1,6}\)[^=][^\r]\{-}[^=]\1\s*\r/.header() - \ hline = /-----*\r/.replace("
    ") - \ paragraph = (table | list | preformatted_text | math_block | deflist | commentline | placeholder | ordinarytextline)+ - \ ordinarytextline = !emptyline !header !hline &> text - \ placeholder = /%\(toc\|title\|nohtml\|template\)[^\r]*\r/.processplaceholder() - \ commentline = /%%[^\r]*\r/.skip() - \ text = /[^\r]*/.process_line() /\r/.breakorspace() - \ - \ table = &> &bar (table_header? , table_block).make_table() { [''/[string,…], block] -> string } - \ table_header = (table_header_line , (/\r/ table_div /\r/).skip()).take("0") { [string, …] } - \ table_block = (table_line , (/\r/.skip() , table_line).take("1")*).insertfirst() { [[string, …], … ] } - \ table_div = /|[-|]\+|/ { string } - \ table_header_line = (bar , (header_cell bar)#).take("1") { [string, …] } - \ table_line = (bar , (body_cell bar)#).take("1") { [string, …] } - \ body_cell = /[^\r|]\+/.strip() { string } - \ header_cell = /[^\r|]\+/.strip() { string } - \ bar = /|/.skip() { string } - \ - \ list = &liststart (blist | rlist | Rlist | alist | Alist | nlist) - \ blist = &bullet ((&> blist_item)+).tag("ul") - \ rlist = &rstartnumber ((&> rlist_item)+).tag("ol") - \ Rlist = &Rstartnumber ((&> Rlist_item)+).tag("ol") - \ alist = &alphanumber ((&> alist_item)+).tag("ol") - \ Alist = &Alphanumber ((&> Alist_item)+).tag("ol") - \ nlist = &number ((&> nlist_item)+).tag("ol") - \ blist_item^ = (bullet , checkbox?).checkbox("-") list_item_content - \ rlist_item^ = (rnumber , checkbox?).checkbox("i") list_item_content - \ Rlist_item^ = (Rnumber , checkbox?).checkbox("I") list_item_content - \ alist_item^ = (alphanumber , checkbox?).checkbox("a") list_item_content - \ Alist_item^ = (Alphanumber , checkbox?).checkbox("A") list_item_content - \ nlist_item^ = (number , checkbox?).checkbox("1") list_item_content - \ bullet = /\s*[-*#•]\s\+/ - \ rstartnumber = /\s*i\{1,3})\s\+/ - \ Rstartnumber = /\s*I\{1,3})\s\+/ - \ rnumber = /\s*[ivxlcdm]\+)\s\+/ - \ Rnumber = /\s*[IVXLCDM]\+)\s\+/ - \ alphanumber = /\s*\l\{1,2})\s\+/ - \ Alphanumber = /\s*\u\{1,2})\s\+/ - \ number = /\s*\d\+[.)]\s\+/ - \ liststart = /\s*\([-*#•]\|\d\+\.\|\d\+)\|[ivxlcdm]\+)\|[IVXLCDM]\+)\|\l\{1,2})\|\u\{1,2})\)\s\+/ - \ checkbox = "[".skip() /[ .oOX]/ /\]\s\+/.skip() - \ list_item_content = text (&> paragraph)? (emptyline paragraph.tag("p"))° - \ - \ preformatted_text = &> "{{{".saveindent() /[^\r]*/.startpre() /\r/.skip() /\_.\{-}\r\s*}}}\s*\r/.endpre() - \ math_block = &> "{{$".skip() /[^\r]*/.startmathblock() /\r/.skip() /\_.\{-}\r\s*}}\$\s*\r/.endmathblock() - \ - \ deflist = (&> deflist_item+).tag("dl") - \ deflist_item^ = term (/\s\+/ short_definition)? /\r/.skip() (&>= long_definition)° - \ term = /[^\r:]*[[:alnum:]][^\r:]*/.tag("dt") "::".skip() - \ short_definition = /[^\r]\+/.tag("dd") - \ long_definition^ = /::\s\+/.skip() list_item_content.tag("dd") - \ - \' - - - -fu! s:start(input_file, output_dir) - call vimwiki#base#mkdir(a:output_dir) - let s:filename_without_ext = fnamemodify(a:input_file, ':t:r') - let output_path = a:output_dir . '/' . s:filename_without_ext .'.html' - - let g:peggi_debug = 0 - let g:peggi_transformation_prefix = 'vimwiki#vw2html#' - let s:title = s:filename_without_ext - let s:toc = 0 - let s:template = '' - call writefile(split(peggi#peggi#parse_file(s:grammar, a:input_file, 'file'), '\\n'), output_path) -endf - - -function! s:use_custom_wiki2html() "{{{ - let custom_wiki2html = VimwikiGet('custom_wiki2html') - return !empty(custom_wiki2html) && s:file_exists(custom_wiki2html) -endfunction " }}} - - -function! vimwiki#vw2html#CustomWiki2HTML(path, wikifile, force) "{{{ - call vimwiki#base#mkdir(a:path) - echomsg system(VimwikiGet('custom_wiki2html'). ' '. - \ a:force. ' '. - \ VimwikiGet('syntax'). ' '. - \ strpart(VimwikiGet('ext'), 1). ' '. - \ shellescape(a:path, 1). ' '. - \ shellescape(a:wikifile, 1). ' '. - \ shellescape(s:default_CSS_full_name(a:path), 1). ' '. - \ (len(VimwikiGet('template_path')) > 1 ? shellescape(expand(VimwikiGet('template_path')), 1) : '-'). ' '. - \ (len(VimwikiGet('template_default')) > 0 ? VimwikiGet('template_default') : '-'). ' '. - \ (len(VimwikiGet('template_ext')) > 0 ? VimwikiGet('template_ext') : '-'). ' '. - \ (len(VimwikiGet('subdir')) > 0 ? shellescape(s:root_path(VimwikiGet('subdir')), 1) : '-')) -endfunction " }}} - - - -function! vimwiki#vw2html#Wiki2HTML(path_html, wikifile) "{{{ - if VimwikiGet('syntax') != "default" - echomsg 'vimwiki: conversion to HTML is not supported for this syntax!' - return - endif - let starttime = reltime() - let path_html = expand(a:path_html).VimwikiGet('subdir') - let wikifile = fnamemodify(a:wikifile, ":p") - if s:use_custom_wiki2html() - let force = 1 - call vimwiki#html#CustomWiki2HTML(path_html, wikifile, force) - else - call s:start(wikifile, path_html) - endif - let time1 = vimwiki#u#time(starttime) -endfunction "}}} - - -function! s:save_vimwiki_buffer() "{{{ - if &filetype == 'vimwiki' - silent update - endif -endfunction "}}} - -function! s:syntax_supported() " {{{ - return VimwikiGet('syntax') == "default" -endfunction " }}} - -function! vimwiki#vw2html#WikiAll2HTML(path_html) "{{{ - if !s:syntax_supported() && !s:use_custom_wiki2html() - echomsg 'vimwiki: conversion to HTML is not supported for this syntax!' - return - endif - let starttime = reltime() - - echomsg 'Saving vimwiki files...' - let save_eventignore = &eventignore - let &eventignore = "all" - let cur_buf = bufname('%') - bufdo call s:save_vimwiki_buffer() - exe 'buffer '.cur_buf - let &eventignore = save_eventignore - - let path_html = expand(a:path_html) - call vimwiki#base#mkdir(path_html) - - echomsg 'Deleting non-wiki html files...' - call s:delete_html_files(path_html) - - echomsg 'Converting wiki to html files...' - let setting_more = &more - setlocal nomore - - let wikifiles = split(glob(VimwikiGet('path').'**/*'.VimwikiGet('ext')), '\n') - for wikifile in wikifiles - let wikifile = fnamemodify(wikifile, ":p") - - let subdir = vimwiki#base#subdir(VimwikiGet('path'), wikifile) - echom subdir - let wikifile = wikifile . subdir - - if !s:is_html_uptodate(wikifile) - echomsg 'Processing '.wikifile - call s:start(wikifile, path_html) - else - echomsg 'Skipping '.wikifile - endif - endfor - - call s:create_default_CSS(path_html) - echomsg 'Done!' - - let &more = setting_more - let time1 = vimwiki#u#time(starttime) - call VimwikiLog_extend('html',[htmlfile,time1]) -endfunction "}}} - -function! s:default_CSS_full_name(path) " {{{ - let path = expand(a:path) - let css_full_name = path.'/'.VimwikiGet('css_name') - return css_full_name -endfunction "}}} - -function! s:create_default_CSS(path) " {{{ - let css_full_name = s:default_CSS_full_name(a:path) - if glob(css_full_name) == "" - call vimwiki#base#mkdir(fnamemodify(css_full_name, ':p:h')) - let default_css = s:find_autoload_file('style.css') - if default_css != '' - let lines = readfile(default_css) - call writefile(lines, css_full_name) - echomsg "Default style.css has been created." - endif - endif -endfunction "}}} - - -function! s:find_autoload_file(name) " {{{ - for path in split(&runtimepath, ',') - let fname = path.'/autoload/vimwiki/'.a:name - if glob(fname) != '' - return fname - endif - endfor - return '' -endfunction " }}} - - -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 - 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') - if filereadable(wikifile) - continue - endif - - try - call delete(fname) - catch - echomsg 'vimwiki: Cannot delete '.fname - endtry - endfor -endfunction "}}} - -function! s:is_html_uptodate(wikifile) "{{{ - let tpl_time = -1 - - let tpl_file = s:get_template('') - if tpl_file != '' - let tpl_time = getftime(tpl_file) - endif - - let wikifile = fnamemodify(a:wikifile, ":p") - let htmlfile = expand(VimwikiGet('path_html').VimwikiGet('subdir'). - \fnamemodify(wikifile, ":t:r").".html") - - if getftime(wikifile) <= getftime(htmlfile) && tpl_time <= getftime(htmlfile) - return 1 - endif - return 0 -endfunction "}}} - -function s:get_template(tpl_from_placeholder) "{{{ - let tpl_in_tplpath = - \ expand(VimwikiGet('template_path') . - \ (a:tpl_from_placeholder != '' ? a:tpl_from_placeholder : VimwikiGet('template_default')) . - \ VimwikiGet('template_ext')) - - return filereadable(tpl_in_tplpath) ? tpl_in_tplpath : s:find_autoload_file('default.tpl') -endfunction "}}} - -function! s:root_path(subdir) "{{{ - return repeat('../', len(split(a:subdir, '[/\\]'))) -endfunction "}}} - diff --git a/doc/screenshot_1.png b/doc/screenshot_1.png new file mode 100644 index 0000000..8c875c2 Binary files /dev/null and b/doc/screenshot_1.png differ diff --git a/doc/screenshot_2.png b/doc/screenshot_2.png new file mode 100644 index 0000000..a4a1fc2 Binary files /dev/null and b/doc/screenshot_2.png differ diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index aebe321..4f935e5 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -9,12 +9,12 @@ |___| |___| |_| |_||__| |__||___| |___| |_||___| ~ - Version: 2.1 + Version: 2.4 ============================================================================== -CONTENTS *vimwiki-contents* +CONTENTS *vimwiki* - 1. Intro |vimwiki| + 1. Intro |vimwiki-intro| 2. Prerequisites |vimwiki-prerequisites| 3. Mappings |vimwiki-mappings| 3.1. Global mappings |vimwiki-global-mappings| @@ -35,9 +35,7 @@ CONTENTS *vimwiki-contents* 5.9. Blockquotes |vimwiki-syntax-blockquotes| 5.10. Comments |vimwiki-syntax-comments| 5.11. Horizontal line |vimwiki-syntax-hr| - 5.12. Schemes |vimwiki-syntax-schemes| - 5.13. Transclusions |vimwiki-syntax-transclude| - 5.14. Thumbnails |vimwiki-syntax-thumbnails| + 5.12. Tags |vimwiki-syntax-tags| 6. Folding/Outline |vimwiki-folding| 7. Placeholders |vimwiki-placeholders| 8. Lists |vimwiki-lists| @@ -49,26 +47,28 @@ CONTENTS *vimwiki-contents* 12.2. Temporary Wiki |vimwiki-temporary-wiki| 12.3. Per-Wiki Options |vimwiki-local-options| 12.4. Global Options |vimwiki-global-options| - 13. Help |vimwiki-help| - 14. Developers |vimwiki-developers| - 15. Changelog |vimwiki-changelog| - 16. License |vimwiki-license| + 13. Getting help |vimwiki-help| + 14. Contributing & Bug reports |vimwiki-contributing| + 15. Development |vimwiki-development| + 16. Changelog |vimwiki-changelog| + 17. License |vimwiki-license| ============================================================================== -1. Intro *vimwiki* +1. Intro *vimwiki-intro* Vimwiki is a personal wiki for Vim -- a number of linked text files that have their own syntax highlighting. -With vimwiki you can: - - organize notes and ideas; - - manage todo-lists; - - write documentation. +With Vimwiki you can: + - organize notes and ideas + - manage todo-lists + - write documentation + - 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 +wiki file. By default it is located in ~/vimwiki/index.wiki Feed it with the following example: @@ -78,11 +78,11 @@ Feed it with the following example: * 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. +'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 +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: @@ -105,7 +105,7 @@ Without them Vimwiki will not work properly. ============================================================================== 3. Mappings *vimwiki-mappings* -There are global and local mappings in vimwiki. +There are global and local mappings in Vimwiki. ------------------------------------------------------------------------------ 3.1. Global mappings *vimwiki-global-mappings* @@ -139,7 +139,7 @@ See also |:VimwikiTabIndex| ws or VimwikiUISelect - List and select available wikies. + List and select available wikis. To remap: > :nmap wq VimwikiUISelect < @@ -197,6 +197,40 @@ See also |:VimwikiMakeDiaryNote| See also |:VimwikiTabMakeDiaryNote| +[count]wy or VimwikiMakeYesterdayDiaryNote + Open diary wiki-file for yesterday of the [count]'s wiki. + + wy opens diary wiki-file for yesterday in the first + wiki from |g:vimwiki_list|. + 1wy as above opens diary wiki-file for yesterday in + the first wiki from |g:vimwiki_list|. + 2wy opens diary wiki-file for yesterday in the second + wiki from |g:vimwiki_list|. + 3wy opens diary wiki-file for yesterday in the third + wiki from |g:vimwiki_list|. + etc. + To remap: > + :nmap dy VimwikiMakeYesterdayDiaryNote +< +See also |:VimwikiMakeYesterdayDiaryNote| + +[count]wm or VimwikiMakeTomorrowDiaryNote + Open diary wiki-file for tomorrow of the [count]'s wiki. + + wm opens diary wiki-file for tomorrow in the first + wiki from |g:vimwiki_list|. + 1wm as above opens diary wiki-file for tomorrow in + the first wiki from |g:vimwiki_list|. + 2wm opens diary wiki-file for tomorrow in the second + wiki from |g:vimwiki_list|. + 3wm opens diary wiki-file for tomorrow in the third + wiki from |g:vimwiki_list|. + etc. + To remap: > + :nmap dm VimwikiMakeTomorrowDiaryNote +< +See also |:VimwikiMakeTomorrowDiaryNote| + ------------------------------------------------------------------------------ 3.2. Local mappings @@ -205,7 +239,7 @@ To remap one of these keys, either put it in your .vimrc like this > or, the better way, put it in a file .vim/ftplugin/vimwiki.vim like this > :nmap wc Vimwiki2HTML -The latter has the advantage that the mapping is local to viwiki buffers in +The latter has the advantage that the mapping is local to Vimwiki buffers in every case. Also note that some keys work in normal mode as well as in visual mode. If you @@ -223,7 +257,7 @@ NORMAL MODE *vimwiki-local-mappings* :nmap wc Vimwiki2HTML < *vimwiki_whh* -whh Convert current wiki page to HTML and open it in +whh Convert current wiki page to HTML and open it in the webbrowser. Maps to |:Vimwiki2HTMLBrowse| To remap: > @@ -267,19 +301,19 @@ NORMAL MODE *vimwiki-local-mappings* :nmap wt VimwikiTabnewLink < *vimwiki_* - Go back to previous wiki page. + Go back to previously visited wiki page. Maps to |:VimwikiGoBackLink|. To remap: > :nmap wb VimwikiGoBackLink < *vimwiki_* - Find next link on the current page. + Find next link in the current page. Maps to |:VimwikiNextLink|. To remap: > :nmap wn VimwikiNextLink < *vimwiki_* - Find previous link on the current page. + Find previous link in the current page. Maps to |:VimwikiPrevLink|. To remap: > :nmap wp VimwikiPrevLink @@ -299,7 +333,7 @@ NORMAL MODE *vimwiki-local-mappings* *vimwiki_=* = Add header level. Create if needed. There is nothing to indent with '==' command in - vimwiki, so it should be ok to use '=' here. + Vimwiki, so it should be ok to use '=' here. To remap: > :nmap == VimwikiAddHeaderLevel < @@ -307,21 +341,49 @@ NORMAL MODE *vimwiki-local-mappings* - Remove header level. To remap: > :nmap -- VimwikiRemoveHeaderLevel +< + *vimwiki_[[* +[[ Go to the previous header in the buffer. + To remap: > + :nmap <- VimwikiGoToPrevHeader +< + *vimwiki_]]* +]] Go to the next header in the buffer. + To remap: > + :nmap -> VimwikiGoToNextHeader +< + *vimwiki_[=* +[= Go to the previous header which has the same level as + the header the cursor is currently under. + To remap: > + :nmap <= VimwikiGoToPrevSiblingHeader +< + *vimwiki_]=* +]= Go to the next header which has the same level as the + header the cursor is currently under. + To remap: > + :nmap => VimwikiGoToNextSiblingHeader +< + *vimwiki_]u* *vimwiki_[u* +]u [u Go one level up -- that is, to the parent header of + the header the cursor is currently under. + To remap: > + :nmap -^ VimwikiGoToParentHeader < *vimwiki_+* + Create and/or decorate links. Depending on the context, this command will: convert words into - Wikilinks; convert raw URLs into Wikilinks; and add - placeholder text to Wiki- or Weblinks that are missing - descriptions. Can be activated in normal mode with - the cursor over a word or link, or in visual mode with - the selected text. + wikilinks; convert raw URLs into wikilinks; and add + placeholder description text to wiki- or weblinks that + are missing descriptions. Can be activated in normal + mode with the cursor over a word or link, or in visual + mode with the selected text. To remap: > :nmap ++ VimwikiNormalizeLink :vmap ++ VimwikiNormalizeLinkVisual < *vimwiki_* - Toggle checkbox of a list item on/off + Toggle checkbox of a list item on/off. Maps to |:VimwikiToggleListItem|. See |vimwiki-todo-lists|. To remap: > @@ -334,6 +396,16 @@ gL Remove checkboxes from all sibling list items. :map VimwikiRemoveSingleCB :map VimwikiRemoveCBInList < + *vimwiki_gln* *vimwiki_glp* +gln Increase the "done" status of a list checkbox, i.e. + from [ ] to [.] to [o] etc. See |vimwiki-todo-lists|. +glp Decrease the "done" status. + To remap: > + :nmap VimwikiIncrementListItem + :vmap VimwikiIncrementListItem + :nmap VimwikiDecrementListItem + :vmap VimwikiDecrementListItem + *vimwiki_gll* *vimwiki_gLl* gll Increase the level of a list item. gLl Increase the level of a list item and all child items. @@ -346,92 +418,95 @@ glh Decrease the level of a list item. gLh Decrease the level of a list item and all child items. To remap: > :map << VimwikiDecreaseLvlSingleItem - :map >>> VimwikiDecreaseLvlWholeItem + :map <<< VimwikiDecreaseLvlWholeItem < *vimwiki_glr* *vimwiki_gLr* -glr Renumber list items in the current list. -gLr Renumber list items in the whole buffer. +glr Renumber list items if the cursor is on a numbered + list item. +gLr Renumber list items in all numbered lists in the whole + file. Also readjust checkboxes. To remap: > :nmap VimwikiRenumberList :nmap VimwikiRenumberAllLists < *vimwiki_glstar* *vimwiki_gLstar* -gl* Make a list item out of normal line or change the symbol - of the current item to *. +gl* Make a list item out of a normal line or change the + symbol of the current item to *. gL* Change the symbol of the current list to *. To remap: > noremap glo :VimwikiChangeSymbolTo * noremap glO :VimwikiChangeSymbolInListTo * < *vimwiki_gl#* *vimwiki_gL#* -gl# Make a list item out of normal line or change the symbol - of the current item to #. +gl# Make a list item out of a normal line or change the + symbol of the current item to #. gL# Change the symbol of the current list to #. To remap: > noremap glo :VimwikiChangeSymbolTo # noremap glO :VimwikiChangeSymbolInListTo # < *vimwiki_gl-* *vimwiki_gL-* -gl- Make a list item out of normal line or change the symbol - of the current item to -. +gl- Make a list item out of a normal line or change the + symbol of the current item to -. gL- Change the symbol of the current list to -. To remap: > noremap glo :VimwikiChangeSymbolTo - noremap glO :VimwikiChangeSymbolInListTo - -< - *vimwiki_gl.* *vimwiki_gL.* -gl. Make a list item out of normal line or change the symbol - of the current item to •. -gL. Change the symbol of the current list to •. - To remap: > - noremap glo :VimwikiChangeSymbolTo • - noremap glO :VimwikiChangeSymbolInListTo • < *vimwiki_gl1* *vimwiki_gL1* -gl1 Make a list item out of normal line or change the symbol - of the current item to 1., the numbering is adjusted - according to the surrounding list items. +gl1 Make a list item out of a normal line or change the + symbol of the current item to 1., the numbering is + adjusted according to the surrounding list items. gL1 Change the symbol of the current list to 1. 2. 3. ... To remap: > noremap glo :VimwikiChangeSymbolTo 1. noremap glO :VimwikiChangeSymbolInListTo 1. < *vimwiki_gla* *vimwiki_gLa* -gla Make a list item out of normal line or change the symbol - of the current item to a), the numbering is adjusted - according to the surrounding list items. +gla Make a list item out of a normal line or change the + symbol of the current item to a), the numbering is + adjusted according to the surrounding list items. gLa Change the symbol of the current list to a) b) c) ... To remap: > noremap glo :VimwikiChangeSymbolTo a) noremap glO :VimwikiChangeSymbolInListTo a) < *vimwiki_glA* *vimwiki_gLA* -glA Make a list item out of normal line or change the symbol - of the current item to A), the numbering is adjusted - according to the surrounding list items. +glA Make a list item out of a normal line or change the + symbol of the current item to A), the numbering is + adjusted according to the surrounding list items. gLA Change the symbol of the current list to A) B) C) ... To remap: > noremap glo :VimwikiChangeSymbolTo A) noremap glO :VimwikiChangeSymbolInListTo A) < *vimwiki_gli* *vimwiki_gLi* -gli Make a list item out of normal line or change the symbol - of the current item to i), the numbering is adjusted - according to the surrounding list items. -gLi Change the symbol of the current list to i) ii) iii) ... +gli Make a list item out of a normal line or change the + symbol of the current item to i), the numbering is + adjusted according to the surrounding list items. +gLi Change the symbol of the current list to + i) ii) iii) ... To remap: > noremap glo :VimwikiChangeSymbolTo i) noremap glO :VimwikiChangeSymbolInListTo i) < *vimwiki_glI* *vimwiki_gLI* -glI Make a list item out of normal line or change the symbol - of the current item to I), the numbering is adjusted - according to the surrounding list items. -gLI Change the symbol of the current list to I) II) III) ... +glI Make a list item out of a normal line or change the + symbol of the current item to I), the numbering is + adjusted according to the surrounding list items. +gLI Change the symbol of the current list to + I) II) III) ... To remap: > noremap glo :VimwikiChangeSymbolTo I) noremap glO :VimwikiChangeSymbolInListTo I) +< + *vimwiki_glx* +glx Toggle checkbox of a list item disabled/off. + Maps to |:VimwikiToggleRejectedListItem|. + See |vimwiki-todo-lists|. + To remap: > + :map tx VimwikiToggleRejectedListItem < *vimwiki_gqq* *vimwiki_gww* gqq Format table. If you made some changes to a table @@ -515,13 +590,13 @@ INSERT MODE *vimwiki-list-mappings* < *vimwiki_i__* Change the symbol of the current list item to the next - available. From - to • to 1. to * to I) to a). + available. From - to 1. to * to I) to a). To remap: > :imap VimwikiListNextSymbol < *vimwiki_i__* Change the symbol of the current list item to the prev - available. From - to a) to I) to * to 1. to •. + available. From - to a) to I) to * to 1. To remap: > :imap VimwikiListPrevSymbol < @@ -534,19 +609,29 @@ INSERT MODE *vimwiki-list-mappings* ------------------------------------------------------------------------------ 3.3. Text objects *vimwiki-text-objects* -ah A section segment (the area between two consecutive - headings) including trailing empty lines. -ih A section segment without trailing empty lines. +ah A header including its content up to the next header. +ih The content under a header (like 'ah', but excluding + the header itself and trailing empty lines). -You can 'vah' to select a section segment with its contents or 'dah' to delete -it or 'yah' to yank it or 'cah' to change it. +aH A header including all of its subheaders. When [count] + is 2, include the parent header, when [count] is 3, + the grandparent and so on. +iH Like 'aH', but excluding the header itself and + trailing empty lines. + +Examples: +- type 'cih' to change the content under the current header +- 'daH' deletes an entire header plus its content including the content of all + of its subheaders +- 'v2aH' selects the parent header of the header the cursor is under plus all + of the content of all of its subheaders a\ A cell in a table. i\ An inner cell in a table. ac A column in a table. ic An inner column in a table. -al A list item plus it's children. +al A list item plus its children. il A single list item. @@ -574,22 +659,42 @@ il A single list item. *:VimwikiTabMakeDiaryNote* Open diary wiki-file for today of the current wiki in a new tab. +*:VimwikiMakeYesterdayDiaryNote* + Open diary wiki-file for yesterday of the current wiki. + +*:VimwikiMakeTomorrowDiaryNote* + Open diary wiki-file for tomorrow of the current wiki. ------------------------------------------------------------------------------ 4.2. Local commands *vimwiki-local-commands* +These commands are only available (and meaningful) when you are currently in a +Vimwiki file. + *:VimwikiFollowLink* - Follow wiki link (create target wiki page if needed). + Follow wiki link (or create target wiki page if needed). *:VimwikiGoBackLink* Go back to the wiki page you came from. -*:VimwikiSplitLink* +*:VimwikiSplitLink* [reuse] [move_cursor] Split and follow wiki link (create target wiki page if needed). -*:VimwikiVSplitLink* + If the argument 'reuse' is given and nonzero, the link is opened in a + possibly existing split window instead of making a new split. + + If 'move_cursor' is given and nonzero, the cursor moves to the window with + the opened link, otherwise, it stays in the window with the link. + +*:VimwikiVSplitLink* [reuse] [move_cursor] Vertical split and follow wiki link (create target wiki page if needed). + If the argument 'reuse' is given and nonzero, the link is opened in a + possibly existing split window instead of making a new split. + + If 'move_cursor' is given and nonzero, the cursor moves to the window with + the opened link, otherwise, it stays in the window with the link. + *:VimwikiTabnewLink* Follow wiki link in a new tab (create target wiki page if needed). @@ -602,27 +707,33 @@ il A single list item. *:VimwikiGoto* Goto link provided by an argument. For example: > :VimwikiGoto HelloWorld -< opens opens/creates HelloWorld wiki page. +< opens/creates HelloWorld wiki page. + + Supports |cmdline-completion| for link name. *:VimwikiDeleteLink* - Delete the wiki page that you are in. + Delete the wiki page you are in. *:VimwikiRenameLink* - Rename the wiki page that you are in. + Rename the wiki page you are in. *:Vimwiki2HTML* - Convert current wiki page to HTML using vimwiki's own converter or a + Convert current wiki page to HTML using Vimwiki's own converter or a user-supplied script (see |vimwiki-option-custom_wiki2html|). *:Vimwiki2HTMLBrowse* - Convert current wiki page to HTML and open it in webbrowser. + Convert current wiki page to HTML and open it in the webbrowser. *:VimwikiAll2HTML* Convert all wiki pages to HTML. - Default css file (style.css) is created if there is no one. + Default CSS file (style.css) is created if there is no one. *:VimwikiToggleListItem* - Toggle checkbox of a list item on/off + Toggle checkbox of a list item on/off. + See |vimwiki-todo-lists|. + +*:VimwikiToggleRejectedListItem* + Toggle checkbox of a list item disabled/off. See |vimwiki-todo-lists|. *:VimwikiListChangeLevel* CMD @@ -638,10 +749,15 @@ il A single list item. To display next match use |:lnext| command. To display previous match use |:lprevious| command. + Hint: this feature is simply a wrapper around |:lvimgrep|. For a + description of how the pattern can look like, see |:vimgrep|. For example, + to do a case insensitive search, use > + :VWS /\cpattern/ + *:VimwikiBacklinks* *:VWB* - Search for wikilinks to the [[current wiki page]] - in all files of current wiki. + Search for wikilinks to the current wiki page in all files of current + wiki. To display all matches use |:lopen| command. To display next match use |:lnext| command. To display previous match use |:lprevious| command. @@ -685,7 +801,7 @@ il A single list item. *:VimwikiGenerateLinks* - Insert all available links into current buffer. + Insert the links of all available wiki files into the current buffer. *:VimwikiDiaryGenerateLinks* Delete old, insert new diary section into diary index file. @@ -700,16 +816,40 @@ il A single list item. *:VimwikiTOC* Create or update the Table of Contents for the current wiki file. - See |vimwiki-toc| + See |vimwiki-toc|. + +*:VimwikiCheckLinks* + Search through all wiki files and check if the targets of all wiki links + and links to external files actually exist. Check also if all wiki files + are reachable from the index file. The results are shown in the quickfix + window. + +*:VimwikiRebuildTags* + Rebuilds the tags metadata file for all wiki files newer than the metadata + file. + Necessary for all tags related commands: |vimwiki-syntax-tags|. + + :VimwikiRebuildTags! does the same for all files. + +*:VimwikiSearchTags* + Searches over the pages in current wiki and finds all locations of a given + tag. Supports |cmdline-completion|. + +*:VimwikiGenerateTags* tagname1 tagname2 ... + Creates or updates an overview on all tags of the wiki with links to all + their instances. Supports |cmdline-completion|. If no arguments (tags) + are specified, outputs all tags. To make this command work properly, make + sure the tags have been built (see |vimwiki-build-tags|). + ============================================================================== 5. Wiki syntax *vimwiki-syntax* -There are a lot of different wikies out there. Most of them have their own -syntax and vimwiki's default syntax is not an exception here. +There are a lot of different wikis out there. Most of them have their own +syntax and Vimwiki is not an exception here. -Vimwiki has evolved its own syntax that closely resembles google's wiki +Vimwiki has evolved its own syntax that closely resembles Google's wiki markup. This syntax is described in detail below. Vimwiki also supports alternative syntaxes, like Markdown and MediaWiki, to @@ -717,7 +857,7 @@ varying degrees; see |vimwiki-option-syntax|. Static elements like headers, quotations, and lists are customized in syntax/vimwiki_xxx.vim, where xxx stands for the chosen syntax. -Interactive elements such as links and vimwiki commands are supported by +Interactive elements such as links and Vimwiki commands are supported by definitions and routines in syntax/vimwiki_xxx_custom.vim and autoload/vimwiki/xxx_base.vim. Currently, only Markdown includes this level of support. @@ -727,8 +867,9 @@ Vimwiki2HTML is currently functional only for the default syntax. ------------------------------------------------------------------------------ 5.1. Typefaces *vimwiki-syntax-typefaces* -There are a few typefaces that gives you a bit of control over how your -text should be decorated: > +There are a few typefaces that give you a bit of control over how your text +is decorated: > + *bold text* _italic text_ ~~strikeout text~~ @@ -736,39 +877,144 @@ text should be decorated: > super^script^ sub,,script,, +Furthermore, there are a number of words which are highlighted extra flashy: +TODO, DONE, STARTED, FIXME, FIXED, XXX. ------------------------------------------------------------------------------ 5.2. Links *vimwiki-syntax-links* Wikilinks~ -Link with spaces in it: > +Plain link: > [[This is a link]] -or: > +With description: > [[This is a link source|Description of the link]] -Links to directories (ending with a "/") are also supported: > - [[/home/somebody/|Home Directory]] +Wiki files don't need to be in the root directory of your wiki, you can put +them in subdirectories as well: > + [[projects/Important Project 1]] +To jump from that file back to the index file, use this link: > + [[../index]] +or: > + [[/index]] +The latter works because wiki links starting with "/" are considered to be +absolute to the wiki root directory, that is, the link [[/index]] always opens +the file /path/to/your/wiki/index.wiki, no matter in which subdirectory you +are currently in. +Links to subdirectories inside the wiki directory are also supported. They +end with a "/": > + [[a subdirectory/|Other files]] Use |g:vimwiki_dir_link| to control the behavior when opening directories. -Raw URLs~ +Typing wikilinks can be simplified by using Vim's omni completion (see +|compl-omni|) like so: > + [[ind +which opens up a popup menu with all the wiki files starting with "ind". -Raw URLs are also supported: > - http://code.google.com/p/vimwiki - mailto:habamax@gmail.com - ftp://vim.org +When |vimwiki-option-maxhi| equals 1, a distinct highlighting style is used to +identify wikilinks whose targets are not found. + +Interwiki~ + +If you maintain more than one wiki, you can create interwiki links between +them by adding a numbered prefix "wikiX:" in front of a link: > + [[wiki1:This is a link]] +or: > + [[wiki1:This is a link source|Description of the link]] + +The number behind "wiki" is in the range 0..N-1 and identifies the destination +wiki in |g:vimwiki_list|. + +Diary~ + +The "diary:" scheme is used to link to diary entries: > + [[diary:2012-03-05]] Anchors~ -A URL can be followed by a '#' and the name of an anchor. When opening a -link, Vimwiki then jumps to the anchor. > +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|. +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}} + +Transclude image with alternate text: > + {{http://vimwiki.googlecode.com/hg/images/vimwiki_logo.png|Vimwiki}} +in HTML: > + Vimwiki + +Transclude image with alternate text and some style: > + {{http://.../vimwiki_logo.png|cool stuff|style="width:150px;height:120px;"}} +in HTML: > + cool stuff + +Transclude image _without_ alternate text and with 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}}]] + +in HTML: > + + ". -Typing wikilinks can be simplified by using Vim's omni completion (see -|compl-omni|) like so: > - [[ind -which opens up a popup menu with all the wiki files starting with "ind". - ------------------------------------------------------------------------------ 5.3. Headers *vimwiki-syntax-headers* @@ -859,9 +1100,6 @@ two lines. Unordered lists: > - Bulleted list item 1 - Bulleted list item 2 -or: > - • Bulleted list item 1 - • Bulleted list item 2 or: > * Bulleted list item 1 * Bulleted list item 2 @@ -892,8 +1130,8 @@ or: > II) Numbered list item 2 III) Numbered list item 3 or: > - # Bulleted list item 1 ← will be converted to numbers in HTML - # Bulleted list item 2 + # Bulleted list item 1 + # the # become numbers when converted to HTML Note that a space after the list item symbols (-, *, 1. etc.) is essential. @@ -902,8 +1140,8 @@ You can nest and mix the various types: > - Bulleted list item 2 a) Numbered list sub item 1 b) more ... - • and more ... - • ... + * and more ... + * ... c) Numbered list sub item 3 1. Numbered list sub sub item 1 2. Numbered list sub sub item 2 @@ -952,12 +1190,12 @@ 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 | @@ -985,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): @@ -999,11 +1237,12 @@ 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| +You can setup Vimwiki to highlight code snippets in preformatted text. +See |vimwiki-option-nested_syntaxes| and +|vimwiki-option-automatic_nested_syntaxes|. ------------------------------------------------------------------------------ @@ -1031,7 +1270,7 @@ E.g.: }}$ Note: no matter how many lines are used in the text file, the HTML will -compress it to *one* line only. +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 @@ -1045,17 +1284,12 @@ E.g.: 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: +Note: the highlighting in Vim is automatic. For the rendering in HTML, you +have two alternative options: -1. using the MathJax server for rendering (needs an internet connection). -Add to your HTML template the following line: - - - -2. installing MathJax locally (faster, no internet required). Choose a -folder on your hard drive and save MathJax in it. Then add to your HTML -template the following line: +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: @@ -1070,188 +1304,126 @@ template folder. For instance, a sensible folder structure could be: 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: + + + ------------------------------------------------------------------------------ 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.10. 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.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. Schemes *vimwiki-syntax-schemes* +5.12. Tags *vimwiki-syntax-tags* -In addition to standard web schemes (e.g. `http:`, `https:`, `ftp:`, etc.) a -number of special schemes are supported: "wiki#:", "local:", "diary:", -"file:", and schemeless. +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. -While "wiki:#", "diary" and schemeless links are automatically opened in Vi, -all other links are opened with the system command. To customize this -behavior, see |VimwikiLinkHandler|. +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. -Interwiki:~ +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". -If you maintain more than one wiki, you can create interwiki links between them -by adding a numbered prefix "wiki#:" in front of a link: > - [[wiki#:This is a link]] -or: > - [[wiki#:This is a link source|Description of the link]] +Tags are also treated as |vimwiki-anchors| (similar to bold text). -The number "#", in the range 0..N-1, identifies the destination wiki in -|g:vimwiki_list|. - -Diary:~ - -The diary scheme is used to concisely link to diary entries: > - [[diary:2012-03-05]] - -This scheme precludes explicit inclusion of |vimwiki-option-diary_rel_path|, -and is most useful on subwiki pages to avoid links such as: > - [[../../diary/2012-03-05]] - -Local:~ - -A local resource that is not a wiki page may be specified with a path relative -to the current page: > - [[local:../assets/data.csv|data (CSV)]] - -When followed or converted to HTML, extensions of local-scheme links are not -modified. - -File:~ - -The file scheme allows you to directly link to arbitray resources using -absolute paths and extensions: > - [[file:///home/somebody/a/b/c/music.mp3]] - -Schemeless:~ - -Schemeless URLs, which are the default, are treated internally as "wiki#:" -URLs in all respects except when converted to Html. - -Schemeless links convert to plain relative path URLs, nearly verbatim: > - relpath/wikipage.html - -The "wiki#:", "local:", and "diary:" schemes use absolute paths as URLs: > - file:///abs_path_to_html#/relpath/wikipage.html - -When |vimwiki-option-maxhi| equals 1, a distinct highlighting style is used to -identify schemeless links whose targets are not found. All other links appear -as regular links even if the files to which they refer do not exist. - - ------------------------------------------------------------------------------- -5.13. Transclusions *vimwiki-syntax-transclude* - -Transclusion (Wiki-Include) Links~ - -Links that use "{{" and "}}" delimiters signify content that is to be -included into the Html output, rather than referenced via hyperlink. - -Wiki-include URLs may use any of the supported schemes, may be absolute or -relative, and need not end with an extension. - -The primary purpose for wiki-include links is to include images. - -Transclude from a local URL: > - {{local:../../images/vimwiki_logo.png}} -or from a universal URL: > - {{http://vimwiki.googlecode.com/hg/images/vimwiki_logo.png}} - -Transclude image with alternate text: > - {{http://vimwiki.googlecode.com/hg/images/vimwiki_logo.png|Vimwiki}} -in HTML: > - Vimwiki - -Transclude image with alternate text and some style: > - {{http://.../vimwiki_logo.png|cool stuff|style="width:150px; height: 120px;"}} -in HTML: > - cool stuff - -Transclude image _without_ alternate text and with css class: > - {{http://.../vimwiki_logo.png||class="center flow blabla"}} -in HTML: > - - -A trial feature allows you to supply your own handler for wiki-include links. -See |VimwikiWikiIncludeHandler|. - - ------------------------------------------------------------------------------- -5.14. Thumbnails *vimwiki-syntax-thumbnails* - -Thumbnail links~ -> -Thumbnail links are constructed like this: > - [[http://someaddr.com/bigpicture.jpg|{{http://someaddr.com/thumbnail.jpg}}]] - -in HTML: > -
    - (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. + ============================================================================== 9. Tables *vimwiki-tables* @@ -1532,10 +1720,10 @@ 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. +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. -To generate diary section with all available links one can use +To generate the diary section with all available links one can use |:VimwikiDiaryGenerateLinks| or wi . Note: it works only for diary index file. @@ -1553,9 +1741,9 @@ Example of diary section: > See |g:vimwiki_diary_months| if you would like to rename months. - -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. @@ -1566,32 +1754,36 @@ See |g:vimwiki_use_calendar| option to turn it off/on. ============================================================================== -12. Anchors *vimwiki-anchors* +11. Anchors *vimwiki-anchors* -Every header and every bold text is an anchor. To jump to it, use a wikilink -of the form > +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* + - [ ] a *funny pig* + - [ ] a *scary dog* Then, to jump from your index.wiki directly to your knitting projects, use: > [[Todo#Knitting projects]] Or, to jump to an individual project, use this link: > - [[Todo#pig]] + [[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#dog]] + [[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. @@ -1603,30 +1795,42 @@ For jumping inside a single file, you can omit the file in the link: > ------------------------------------------------------------------------------ Table of Contents *vimwiki-toc* *vimwiki-table-of-contents* -You can add a 'table of contents' to your wiki file. -Use the commando |:VimwikiTOC| to create the magic header > +You can create a "table of contents" at the top of your wiki file. +The commando |:VimwikiTOC| creates the magic header > = Contents = -at the top of your file and create a list of all the headers in the current -file as links, so you can directly jump to specific parts of the file. +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. -For the indentation, the value of |vimwiki-option-list_margin| is used. +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. if you have a -modeline there, put the magic header in the second or third line and run +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 your language is not english, set the option |g:vimwiki_toc_header| to your -favorite translation. +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. +Vimwiki. Global options are configured via global variables. For a complete list of them, see |vimwiki-global-options|. @@ -1637,21 +1841,27 @@ 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* +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', ...} + {'option1': 'value1', 'option2': 'value2', ...} Consider the following: > let g:vimwiki_list = [{'path': '~/my_site/', 'path_html': '~/public_html/'}] -This defines 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/ . Another example: > let g:vimwiki_list = [{'path': '~/my_site/', 'path_html': '~/public_html/'}, @@ -1680,25 +1890,24 @@ For clarity, in your .vimrc file you can define wiki options using separate ------------------------------------------------------------------------------ -12.2 Temporary Wiki *vimwiki-temporary-wiki* +12.2 Temporary Wiki *vimwiki-temporary-wiki* -The creation of temporary wikis allows you to open files that would not -normally be recognized by vimwiki. +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 may be created -and appended to the list of configured wikis in |g:vimwiki_list|. +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) +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 +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 +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. @@ -1752,17 +1961,14 @@ This will keep your HTML files up to date. *vimwiki-option-auto_toc* ------------------------------------------------------------------------------ -Set this option to a value greater than 0 to automatically update the Table of -Contents: > +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}] -Value Description~ -0 Don't update it automatically. -1 Update when the wiki file is converted to HTML. -2 Update when the wiki file is saved. - -Default: 0 - *vimwiki-option-index* ------------------------------------------------------------------------------ @@ -1793,8 +1999,8 @@ Key Default value Values~ syntax default default, markdown, or media Description~ -Wiki syntax. You can use different markup languages (currently: vimwiki's -default, Markdown, and MediaWiki), but only vimwiki's default markup will be +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: > @@ -1832,11 +2038,13 @@ Each template could look like: >
    %content%
    +

    Page created on %date%

    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 '../../../'. @@ -1865,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. @@ -1887,6 +2095,7 @@ 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* @@ -1895,21 +2104,19 @@ Key Default value Values~ maxhi 0 0, 1 Description~ -Non-existent wiki links highlighting can be quite slow. If you still want it, -set maxhi to 1: > +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}] -This disables filesystem checks for wiki links. - *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/' @@ -1945,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* @@ -1960,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* @@ -1990,53 +2221,91 @@ custom_wiki2html '' Description~ 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. +command-line, using |:!| invocation. -The following arguments, in this order, are passed to the -|vimwiki-option-custom_wiki2html| script: +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, i.e. 'path_html' +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 - if you have wikilink [[dir1/dir2/dir3/my page in a subdir]] then - %root_path% is replaced by '../../../'. + 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-10 are experimental and may change in the future. If any of these -parameters is empty, then a hyphen "-" is passed to the script in its place. +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 http://code.google.com/p/vimwiki/issues/detail?id=384 +be located at https://github.com/vimwiki-backup/vimwiki/issues/384 To use the internal wiki2html converter, use an empty string (the default). + +*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| +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_gl-|, |vimwiki_gl1|, |vimwiki_gla|, |vimwiki_glA|, |vimwiki_gli|, -|vimwiki_glI| and |vimwiki_i__|. +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 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* @@ -2052,7 +2321,7 @@ Global options are configured using the following pattern: > 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 @@ -2061,22 +2330,24 @@ 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. * this line is highlighted as well with the option set to 2 - * [ ] I wish vim could use strikethru. + * [ ] this line is never highlighted Value Description~ 0 Don't highlight anything. -1 Highlight checked [X] list item with |group-name| "Comment". -2 Highlight checked [X] list item and all its child items. +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 -Note: Option 2 does not work perfectly. Specifically, it might break on -preformatted text or if you mix tabs and spaces for indenting, and indented -headers can be highlighted erroneously. +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 @@ -2097,7 +2368,7 @@ Value Description~ If your preferred wiki extension is .txt then you can > let g:vimwiki_global_ext = 0 -to restrict vimwiki's operation to only those paths listed in g:vimwiki_list. +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 @@ -2106,17 +2377,17 @@ Default: 1 ------------------------------------------------------------------------------ *g:vimwiki_ext2syntax* *vimwiki-register-extension* -A many-to-one map between file extensions and syntaxes whose purpose is to -register the extensions with vimwiki. +A many-to-one mapping between file extensions and syntaxes whose purpose is to +register the extensions with Vimwiki. E.g.: > let g:vimwiki_ext2syntax = {'.md': 'markdown', \ '.mkd': 'markdown', \ '.wiki': 'media'} -An extension that is registered with vimwiki can trigger creation of a +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 +|g:vimwiki_list| are automatically registered with Vimwiki using the default syntax. Default: {} @@ -2125,7 +2396,7 @@ 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 @@ -2139,16 +2410,30 @@ Default: 'Vimwiki' ------------------------------------------------------------------------------ *g:vimwiki_listsyms* -String of 5 symbols for list items with checkboxes. +String of at least two symbols to show the progression of todo list items. Default value is ' .oOX'. The first char is for 0% done items. -The fifth is for 100% done items. +The last is for 100% done items. You can set it to some more fancy symbols like this: > let g:vimwiki_listsyms = '✗○◐●✓' + +------------------------------------------------------------------------------ +*g:vimwiki_listsym_rejected* + +Character that is used to show that an item of a todo list will not be done. +Default value is '-'. + +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 = '✗' + + ------------------------------------------------------------------------------ *g:vimwiki_use_mouse* @@ -2164,14 +2449,16 @@ Default: 0 ------------------------------------------------------------------------------ *g:vimwiki_folding* -Enable/disable vimwiki's folding (outline) functionality. Folding in vimwiki +Enable/disable Vimwiki's folding (outline) functionality. Folding in Vimwiki can uses either the 'expr' or the 'syntax' |foldmethod| of Vim. Value Description~ -'' 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). +'' 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: '' @@ -2181,6 +2468,8 @@ Limitations: - '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_list_ignore_newline* @@ -2195,6 +2484,19 @@ Value Description~ Default: 1 +------------------------------------------------------------------------------ +*g:vimwiki_text_ignore_newline* + +This is HTML related. +Convert newlines to
    s in text. + +Value Description~ +0 Newlines in text are converted to
    s. +1 Ignore newlines. + +Default: 1 + + ------------------------------------------------------------------------------ *g:vimwiki_use_calendar* @@ -2211,17 +2513,17 @@ Default: 1 ------------------------------------------------------------------------------ *VimwikiLinkHandler* -A customizable link handler, |VimwikiLinkHandler|, can be defined to override -Vimwiki's opening of links. Each recognized link, whether it is a wikilink, -wiki-include link or a weblink, is first passed to |VimwikiLinkHandler| to see -if it can be handled. The return value 1/0 indicates success. +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. All others, -including local: and file: schemes, are opened with a system default handler; -i.e. Linux (!xdg-open), Mac (!open), and Windows (!start). +the scheme. "wiki:", "diary:" or schemeless links are opened in Vim. "file:" +and "local:" links are opened with a system default handler. -You can redefine |VimwikiLinkHandler| function to do something else: > +You can redefine the VimwikiLinkHandler function in your .vimrc to do +something else: > function! VimwikiLinkHandler(link) try @@ -2234,64 +2536,87 @@ You can redefine |VimwikiLinkHandler| function to do something else: > return 0 endfunction -A second example handles two new schemes, 'vlocal:' and 'vfile:', which behave -similar to 'local:' and 'file:' schemes, but are always opened with Vim: > +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 links with the - " 'vlocal:' or 'vfile:' schemes. E.g.: - " 1) [[vfile:///~/Code/PythonProject/abc123.py]], and - " 2) [[vlocal:./|Wiki Home]] + 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 =~ "vlocal:" || link =~ "vfile:" + if link =~# '^vfile:' let link = link[1:] else return 0 endif - let [idx, scheme, path, subdir, lnk, ext, url, anchor] = - \ vimwiki#base#resolve_scheme(link, 0) - if g:vimwiki_debug - echom 'LinkHandler: idx='.idx.', scheme=[v]'.scheme.', path='.path. - \ ', subdir='.subdir.', lnk='.lnk.', ext='.ext.', url='.url. - \ ', anchor='.anchor - endif - if url == '' - echom 'Vimwiki Error: Unable to resolve link!' + let link_infos = vimwiki#base#resolve_link(link) + if link_infos.filename == '' + echomsg 'Vimwiki Error: Unable to resolve link!' return 0 else - call vimwiki#base#edit_file('tabnew', url, '', [], 0) + exe 'tabnew ' . fnameescape(link_infos.filename) return 1 endif - endfunction " }}} + 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 ------------------------------------------------------------------------------ *VimwikiWikiIncludeHandler* -Vimwiki includes the contents of a wiki-include URL as an image by default. +Vimwiki includes the content of a wiki-include URL as an image by default. A trial feature allows you to supply your own handler for wiki-include links. The handler should return the empty string when it does not recognize or cannot otherwise convert the link. A customized handler might look like this: > " Convert {{URL|#|ID}} -> URL#ID - function! VimwikiWikiIncludeHandler(value) "{{{ + function! VimwikiWikiIncludeHandler(value) let str = a:value " complete URL let url_0 = matchstr(str, g:vimwiki_rxWikiInclMatchUrl) " URL parts - let [scheme, path, subdir, lnk, ext, url, anchor] = - \ vimwiki#base#resolve_scheme(url_0, VimwikiGet('ext')) + let link_infos = vimwiki#base#resolve_link(url_0) let arg1 = matchstr(str, VimwikiWikiInclMatchArg(1)) let arg2 = matchstr(str, VimwikiWikiInclMatchArg(2)) if arg1 =~ '#' - return url.'#'.arg2 + return link_infos.filename.'#'.arg2 endif " Return the empty string when unable to process link return '' - endfunction "}}} + endfunction < ------------------------------------------------------------------------------ @@ -2321,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 > @@ -2338,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. @@ -2347,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. @@ -2389,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 @@ -2433,7 +2759,9 @@ Default: '' (empty) ------------------------------------------------------------------------------ *g:vimwiki_valid_html_tags* -Case-insensitive 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' @@ -2447,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|. @@ -2456,11 +2784,11 @@ they would not be deleted after |:VimwikiAll2HTML|. ------------------------------------------------------------------------------ *g:vimwiki_conceallevel* -In vim73 |conceallevel| is local to window, thus if you open vimwiki 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 everytime vimwiki buffer -is entered. +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. @@ -2471,8 +2799,12 @@ Default: 2 ------------------------------------------------------------------------------ *g:vimwiki_autowriteall* -In vim |autowriteall| is a global setting. With g:vimwiki_autowriteall vimwiki -makes it local to its buffers. +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 @@ -2506,19 +2838,6 @@ Note: Default: 15 ------------------------------------------------------------------------------- -*g:vimwiki_debug* - -Controls verbosity of debugging output, for example, the diagnostic -information about HTML conversion. - -Value Description~ -0 Do not show debug messages. -1 Show debug messages. - -Default: 0 - - ------------------------------------------------------------------------------ *g:vimwiki_diary_months* @@ -2541,66 +2860,279 @@ let g:vimwiki_diary_months = { \ 10: 'October', 11: 'November', 12: 'December' \ } + ------------------------------------------------------------------------------ *g:vimwiki_toc_header* -A string with the magic header that tells vimwiki where the Table of Contents -is located in the file. You can change it to the appropriate word in your -mother tongue like this: > +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'. -============================================================================== -13. Help *vimwiki-help* -Your help in making vimwiki better is really appreciated! +------------------------------------------------------------------------------ +*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 + +============================================================================== +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 + +============================================================================== +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. ============================================================================== -14. Developers *vimwiki-developers* +15. Development *vimwiki-development* - - Maxim Kim as original author. - - Stuart Andrews - - Tomas Pospichal - - See the http://code.google.com/p/vimwiki/people/list for the others. - -Web: http://code.google.com/p/vimwiki/ -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 + - @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) ============================================================================== -15. 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 (not yet released)~ + +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. + +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. + * 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| - * remove the now useless %toc placeholder * add omni completion of wiki links (files and anchors) - * the function base#resolve_scheme() now also returns the anchor - (important for custom VimwikiLinkHandlers) * 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| - * g:vimwiki_auto_checkbox is now useless and removed + * 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 - * Issue #24: Basic support for remote directories via netrw * 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~ @@ -2638,9 +3170,9 @@ Summary ~ * No more [http://link description] links. * No more plain image links. Use transclusions. * No more image links identified by extension. Use transclusions. - * Interwiki links. See |vimwiki-syntax-schemes|. - * Link schemes. See |vimwiki-syntax-schemes|. - * Transclusions. See |vimwiki-syntax-transclude|. + * 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|. @@ -2719,7 +3251,7 @@ http://code.google.com/p/vimwiki/issues/list * 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| @@ -2733,12 +3265,13 @@ http://code.google.com/p/vimwiki/issues/list * First public version. ============================================================================== -16. 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/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim index 06e7a9f..217359f 100644 --- a/ftplugin/vimwiki.vim +++ b/ftplugin/vimwiki.vim @@ -1,97 +1,90 @@ -" 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 -call vimwiki#u#reload_regexes() -" UNDO list {{{ -" Reset the following options to undo this plugin. -let b:undo_ftplugin = "setlocal ". - \ "suffixesadd< isfname< formatlistpat< ". - \ "formatoptions< foldtext< ". - \ "foldmethod< foldexpr< commentstring< " -" UNDO }}} - -" MISC STUFF {{{ setlocal commentstring=%%%s -if g:vimwiki_conceallevel && exists("+conceallevel") - let &l:conceallevel = g:vimwiki_conceallevel +if vimwiki#vars#get_global('conceallevel') && exists("+conceallevel") + let &l:conceallevel = vimwiki#vars#get_global('conceallevel') endif -" 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}}} -" omnicomplete function for wiki files and anchors {{{ +exe "setlocal tags+=" . escape(vimwiki#tags#metadata_file_path(), ' \|"') -let g:vimwiki_default_header_search = '^\s*\(=\{1,6}\)\([^=].*[^=]\)\1\s*$' -let g:vimwiki_default_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\s*$' -let g:vimwiki_markdown_header_search = '^\s*\(#\{1,6}\)\([^#].*\)$' -let g:vimwiki_markdown_header_match = '^\s*\(#\{1,6}\)#\@!\s*__Header__\s*$' -let g:vimwiki_media_header_search = '^\s*\(=\{1,6}\)\([^=].*[^=]\)\1\s*$' -let g:vimwiki_media_header_match = '^\s*\(=\{1,6}\)=\@!\s*__Header__\s*\1=\@!\s*$' -let g:vimwiki_default_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@=' -let g:vimwiki_default_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' -let g:vimwiki_markdown_bold_search = '\%(^\|\s\|[[:punct:]]\)\@<=\*\zs\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)\ze\*\%([[:punct:]]\|\s\|$\)\@=' -let g:vimwiki_markdown_bold_match = '\%(^\|\s\|[[:punct:]]\)\@<=\*__Text__\*\%([[:punct:]]\|\s\|$\)\@=' -let g:vimwiki_media_bold_search = "'''\\zs[^']\\+\\ze'''" -let g:vimwiki_media_bold_match = '''''''__Text__''''''' -" ^- looks strange, but is equivalent to "'''__Text__'''" but since we later -" want to call escape() on this string, we must keep it in single quotes -function! g:complete_wikifiles(findstart, base) + +function! Complete_wikifiles(findstart, base) if a:findstart == 1 - let column = col('.')-1 + let column = col('.')-2 let line = getline('.')[:column] - let startoflink = match(line, '\[\[\zs[^\\[]*$') + let startoflink = match(line, '\[\[\zs[^\\[\]]*$') if startoflink != -1 + let s:line_context = '[' return startoflink endif - if VimwikiGet('syntax') == 'markdown' - let startofinlinelink = match(line, '\[.*\](\zs.*$') + 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 - if a:base !~ '#' + " 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 =~# '^wiki\d:' - let wikinumber = eval(matchstr(a:base, '^wiki\zs\d')) - let directory = VimwikiGet('path', wikinumber) - let ext = VimwikiGet('ext', wikinumber) - let prefix = matchstr(a:base, '^wiki\d:\zs.*') - let scheme = matchstr(a:base, '^wiki\d:\ze') + 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 directory = VimwikiGet('path').'/'.VimwikiGet('diary_rel_path') - let ext = VimwikiGet('ext') + let wikinumber = -1 let prefix = matchstr(a:base, '^diary:\zs.*') let scheme = matchstr(a:base, '^diary:\ze') - else - let directory = VimwikiGet('path') - let ext = VimwikiGet('ext') + else " current wiki + let wikinumber = vimwiki#vars#get_bufferlocal('wiki_nr') let prefix = a:base let scheme = '' endif + let links = vimwiki#base#get_wikilinks(wikinumber, 1) let result = [] - for wikifile in split(globpath(directory, '**/*'.ext), '\n') - " get the filename relative to the wiki path: - let subdir_filename = substitute(fnamemodify(wikifile, ':p:r'), - \ '\V'.fnamemodify(directory, ':p'), '', '') - if subdir_filename =~ '^'.prefix - call add(result, scheme . subdir_filename) + for wikifile in links + if wikifile =~ '^'.vimwiki#u#escape(prefix) + call add(result, scheme . wikifile) endif endfor return result @@ -100,82 +93,29 @@ function! g:complete_wikifiles(findstart, base) " we look for anchors in the given wikifile let segments = split(a:base, '#', 1) - let link_infos = vimwiki#base#resolve_scheme(segments[0].'#', 0) - let wikifile = link_infos[6] - let syntax = VimwikiGet('syntax', link_infos[0]) - let rxheader = g:vimwiki_{syntax}_header_search - let rxbold = g:vimwiki_{syntax}_bold_search - if !filereadable(wikifile) - return [] - endif - let filecontent = readfile(wikifile) - let anchor_level = ['', '', '', '', '', '', ''] - let anchors = [] - - for line in filecontent - - " 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]) - let anchor_level[level-1] = header - for l in range(level, 6) - let anchor_level[l] = '' - endfor - call add(anchors, header) - let complete_anchor = '' - for l in range(level-1) - if anchor_level[l] != '' - let complete_anchor .= anchor_level[l].'#' - endif - endfor - let complete_anchor .= header - call add(anchors, complete_anchor) - endif - - " collect bold text (there can be several in one line) - let bold_count = 0 - let bold_end = 0 - while 1 - let bold_text = matchstr(line, rxbold, bold_end, bold_count) - let bold_end = matchend(line, rxbold, bold_end, bold_count) + 1 - if bold_text == "" - break - endif - let anchor_level[6] = bold_text - call add(anchors, bold_text) - let complete_anchor = '' - for l in range(6) - if anchor_level[l] != '' - let complete_anchor .= anchor_level[l].'#' - endif - endfor - let complete_anchor .= bold_text - call add(anchors, complete_anchor) - let bold_count += 1 - endwhile - - endfor + 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 =~# '^'.given_anchor + if anchor =~# '^'.vimwiki#u#escape(given_anchor) call add(filtered_anchors, segments[0].'#'.anchor) endif endfor - return filtered_anchors + endif endif endfunction -setlocal omnifunc=g:complete_wikifiles -" omnicomplete }}} -" MISC }}} +setlocal omnifunc=Complete_wikifiles + + -" LIST STUFF {{{ " settings necessary for the automatic formatting of lists setlocal autoindent setlocal nosmartindent @@ -187,8 +127,7 @@ setlocal formatoptions-=o setlocal formatoptions-=2 setlocal formatoptions+=n -"Create 'formatlistpat' -let &formatlistpat = g:vimwiki_rxListItem +let &formatlistpat = vimwiki#vars#get_syntaxlocal('rxListItem') if !empty(&langmap) " Valid only if langmap is a comma separated pairs of chars @@ -203,67 +142,76 @@ if !empty(&langmap) endif endif -" LIST STUFF }}} -" FOLDING {{{ -" Folding list items {{{ -function! VimwikiFoldListLevel(lnum) "{{{ + +" ------------------------------------------------ +" Folding stuff +" ------------------------------------------------ + +function! VimwikiFoldListLevel(lnum) return vimwiki#lst#fold_level(a:lnum) -endfunction "}}} -" Folding list items }}} +endfunction -" Folding sections and code blocks {{{ -function! VimwikiFoldLevel(lnum) "{{{ + +function! VimwikiFoldLevel(lnum) let line = getline(a:lnum) " Header/section folding... - if line =~ g:vimwiki_rxHeader + if line =~# vimwiki#vars#get_syntaxlocal('rxHeader') return '>'.vimwiki#u#count_first_sym(line) " Code block folding... - elseif line =~ '^\s*'.g:vimwiki_rxPreStart + elseif line =~# vimwiki#vars#get_syntaxlocal('rxPreStart') return 'a1' - elseif line =~ '^\s*'.g:vimwiki_rxPreEnd.'\s*$' + elseif line =~# vimwiki#vars#get_syntaxlocal('rxPreEnd') return 's1' else return "=" endif +endfunction -endfunction "}}} -" Constants used by VimwikiFoldText {{{ +" 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 -" }}} -function! s:shorten_text_simple(text, len) "{{{ unused + +" 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 "}}} +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] - let spare_len = a:len - strlen(a:text) +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 " try to break on a space; assumes a:len-s:ell_len >= s:tolerance let newlen = a:len - s:ell_len - let idx = strridx(a:text, ' ', newlen + s:tolerance) + let idx = strridx(text_pattern, ' ', newlen + s:tolerance) let break_idx = (idx + s:tolerance >= newlen) ? idx : newlen - return [a:text[0:break_idx].s:ellipsis, newlen - break_idx] -endfunction "}}} + return [matchstr(a:text, '\m^.\{'.break_idx.'\}').s:ellipsis, newlen - break_idx] +endfunction -function! VimwikiFoldText() "{{{ + +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 !~ '^\s*'.g:vimwiki_rxPreStart + if line !~# vimwiki#vars#get_syntaxlocal('rxPreStart') let [main_text, spare_len] = s:shorten_text(main_text, 50) return main_text.len_text else @@ -278,25 +226,30 @@ function! VimwikiFoldText() "{{{ endif return main_text.len_text.content_text endif -endfunction "}}} +endfunction -" Folding sections and code blocks }}} -" FOLDING }}} -" COMMANDS {{{ + +" ------------------------------------------------ +" Commands +" ------------------------------------------------ + command! -buffer Vimwiki2HTML - \ silent noautocmd w - \ let res = 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.' | endif + \ + \ if res != '' | echo 'Vimwiki: HTML conversion is done, output: ' + \ . expand(vimwiki#vars#get_wikilocal('path_html')) | endif command! -buffer Vimwiki2HTMLBrowse - \ silent noautocmd w + \ if filewritable(expand('%')) | silent noautocmd w | endif + \ \ call vimwiki#base#system_open_link(vimwiki#html#Wiki2HTML( - \ expand(VimwikiGet('path_html')), + \ 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) @@ -304,14 +257,14 @@ 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 -nargs=? VimwikiNormalizeLink call vimwiki#base#normalize_link() -command! -buffer VimwikiTabnewLink call vimwiki#base#follow_link('tabnew') +command! -buffer VimwikiTabnewLink call vimwiki#base#follow_link('tab', 0, 1) command! -buffer VimwikiGenerateLinks call vimwiki#base#generate_links() @@ -319,21 +272,31 @@ 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'), ' ') + \ escape(vimwiki#vars#get_wikilocal('path').'**/*'.vimwiki#vars#get_wikilocal('ext'), ' ') -command! -buffer -nargs=+ VimwikiGoto call vimwiki#base#goto() +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 -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 -nargs=+ VimwikiListChangeLvl call vimwiki#lst#change_level(, , ) +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() @@ -351,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() -" KEYBINDINGS {{{ -if g:vimwiki_use_mouse +command! -buffer VimwikiPasteUrl call vimwiki#html#PasteUrl(expand('%:p')) +command! -buffer VimwikiCatUrl call vimwiki#html#CatUrl(expand('%:p')) + + +" ------------------------------------------------ +" Keybindings +" ------------------------------------------------ + +if vimwiki#vars#get_global('use_mouse') nmap nmap - nnoremap <2-LeftMouse> :call vimwiki#base#follow_link("nosplit", "\2-LeftMouse>") + nnoremap <2-LeftMouse> + \ :call vimwiki#base#follow_link('nosplit', 0, 1, "\2-LeftMouse>") nnoremap :VimwikiSplitLink nnoremap :VimwikiVSplitLink nnoremap :VimwikiGoBackLink @@ -365,46 +341,39 @@ endif if !hasmapto('Vimwiki2HTML') - nmap wh Vimwiki2HTML + exe 'nmap '.vimwiki#vars#get_global('map_prefix').'h Vimwiki2HTML' endif -nnoremap