用vimwiki搭建你自己的维基世界

原文: http://wiki.ktmud.com/tips/vim/vimwiki-guide.html

Vim 里有个 [http://code.google.com/p/vimwiki/ vimwiki] 插件,正在使用 Vim 的同学一定有所耳闻。有了vimwiki, 搭配Vim本身强大的编辑功能,你就拥有了一个快速、轻巧、功能强大的个人笔记本。通过 vimwiki 输出HTML页面,你还能方便地和别人分享自己的知识积累。您现在看到的这个[http://wiki.ktmud.com 丘迟的维基世界]即是通过 vimwiki 搭建。为什么要叫做“维基世界”?因为只要你懂一点前端知识,它可以不仅仅是一个简单的知识管理系统,还能成为一个 playground ,任你自由发挥。

为什么要使用 vimwiki

众所周知,维基语法的作用有三点。1. 使条目更规范。通过一定转换,wiki 能输出为拥有约定俗成格式的HTML;2. 节约编辑时间。 显然,你不用写出完整的HTML标签,也不用在可视化编辑器中点来点去;3. 充分的可读性。使用维基语法书写的文档,即使未被转为HTML,内容的语义也是一目了然,甚至表格也能清晰地阅读。相较而言,UBB什么的简直就是扯淡嘛。

使用 vimwiki ,当然是为了享受维基语法的这些优点。但 vimwiki 提供的不仅这些,它还可以帮你维护 TODO-LIST 和个人日记。它生成的HTML文件可以轻松自定义,只要你愿意,你完全能把它打造成个人网站,甚至是拥有评论系统的博客。正如[http://wiki.ktmud.com 我]和[http://hotoo.github.com/blog/index.html 闲耘]这样。

安装 vimwiki

vimwiki 的安装同其他vim插件一样,把[http://code.google.com/p/vimwiki/downloads/list 下载回来的东西]解压到 vimfiles 里就好了。有 zip 包和 vba 包两种格式。其中 vba 是 Vim 独有的插件安装包。推荐使用 vba 安装,因为它能保存你的安装信息,不高兴了还可以卸载(详细说明请:h vba)。要使用这种安装方式,需要有 vimball 插件。Windows 下的 gvim 已经自带。如果你还没有这东西,可以先到 [http://www.vim.org vim.org] [http://www.vim.org/scripts/script.php?script_id=1502 自行下载]。

使用 Vim 打开 vimwiki.vba ,然后执行 :so % ,就这么简单。

如果你选择了 zip 包,解压完成后你可能还需要重建帮助文件索引。请执行 :helptags $VIMFILES/doc 。其中 \(VIMFILES 就是您的 vimfiles 目录。这是需要在 vimrc 中定义的系统变量, Windows 下应该是 \)VIM/vimfiles , Linux 下是 ~/.vim/ 。请检查您的 vimrc 里是否有这样的代码:

if has("win32")
  let $VIMFILES = $VIM.'/vimfiles'
else
  let $VIMFILES = $HOME.'/.vim'
endif

如果还没有,就赶快加上吧。

如果你正在使用 [http://www.vim.org/scripts/script.php?script_id=521 MRU] ,并且设置了 MRU_Include_Files ,记得把 .wiki 也包括进去。

装好之后,您可以马上使用 :h vimwiki 查看帮助。相信我,查看帮助文档绝对是最管用的学习方式(虽然耗时更久,但学得更全面,省去许多将来求助搜索引擎的时间)。当然,如果你英文不好,看不太懂,本文的存在就是为了帮助你,别急,慢慢来。

开始使用 vimwiki

使用快捷键 <leader>ww 开始编辑您的第一个 vimwiki 吧! 首次使用 vimwiki 时, 它默认会在操作系统用户目录(即 ~/ )建立一个 vimwiki 文件夹,保存所有你的 wiki 条目。如果你调用 :!Vimwiki2HTML 命令把 wiki 条目转为 html 页面,它会创建一个名为 vimwiki_html 的文件夹保存所有生成的 html 文件。

基本的 Wiki 语法

= 一级标题 =  
== 二级标题 ==
=== 三级标题 ===
此次类推。

当标题前面有空白时,标题文本居中对齐。
       = 我是居中的标题 =

*<b>粗体</b>*  _<i>斜体</i>_  ~~<del>删除线</del>~~   `<code>Some Code 代码</code>` 

<b>注意</b> 这几个针对文本格式的标签,都要求左右留有空白。
请注意你的代码高亮,一般来说,有了相应的高亮,你用的wiki标签才生效。

^<sup>上</sup>^标  ,,<sub>下</sub>,,标

    四个空格缩进的内容会被转成blockquote
    
`{{{` class="brush:php"
这中间的内容会被放到一个 pre 里,适合贴代码。
上面的 class 是可选的,一般用来安排代码高亮。
事实上,这一块代码展示就是放在了一个 pre 里。
请无视下面一行的反斜杠
`}}}`

WikiItem  大写开头的驼峰英文会被自动当作一个维基词条,并添加链接
[[Wiki Item]]  这是手动建立维基词条的方式
[[wiki item|description]]  输出HTML时显示description,链到 wiki item
http://ktmud.com/  外部URL会被自动转换成链接
[http://ktmud.com Ktmud]  带文字的外链
[images/hello.jpg] 输出 <img src="images/hello.jpg" />
[[images/hello.jpg]] 输出图片,并链向图片地址

* 无序列表 条目一
* 无序列表 条目二 
  - 子列表 条目一
  - 自列表 条目二

# 有序列表 条目一
# 有序列表 条目二

* 和 - 是等价的,后面必须跟一个空格

您可以查看[http://wiki.ktmud.com/tips/vim/vimwiki-guide.wiki 本文的wiki源文件]加深理解。

参考 :h vimwiki-syntax

特殊占位符

在wiki条目中使用以下占位符,能对生成的HTML文件做一些特殊的处理。

生成HTML

使用 :Vimwiki2HTML 可以为当前维基条目生成HTML文件,使用 :VimwikiAll2HTML 可以为所有条目生成HTML。您可以为每个维基项目指定 auto_export 选项,这样在wiki文件保存时就会自动生成HTML。个人不建议这样做,因为当条目很大,保存就相当费时。

定义下面的快捷键映射即可:

map <S-F4> :!VimwikiAll2HTML<cr>
map <F4> :!Vimwiki2HTML<cr>

键操作

快捷键总览

  1. <leader>ww 在当前窗口打开维基首页
  2. <leader>wt 在新tab打开维基首页
  3. <leader>w<leader>w 打开/新建当天日记
  4. <leader>w<keader>t 在新tab打开/新建当天日记
  5. <leader>ws 选择维基项目(详见下面的“多个维基项目”一节)

编辑时的按键

  1. 尚未建立的词条会被显示为红色(或其他你的 Vim 语法高亮定义的错误颜色),在词条上敲回车键,可以编辑这个词条。点击 Shift-回车,在新的分割窗口编辑该词条。编辑好以后点击退格(Backspace)键,可以返回链入页
  2. 使用 Tab 键,可以跳到下一个维基词条或链接,使用 Shift-Tab 跳到上一个
  3. 插入模式下使用Shift-Enter,插入 \<br\> 并换行

另有条目管理相关的快捷键 <leader>wd<leader>wr ,分表代表删除和重命名当前条目。其中重命名条目很强大,还能更改所有其他条目内引用了该条目的链接。 重命名之后别忘了重新生成所有条目的HTML。


进阶操作

日记功能

使用快捷键 <leader>w<leader>w 可以快速编辑当天的日记。还可以配合 [http://www.vim.org/scripts/script.php?script_id=52 Calendar 插件] 轻松管理你的日记。

请马上下载并安装 [http://www.vim.org/scripts/download_script.php?src_id=12959 calendar.vim]。 安装后,定义一下快捷键吧:

" calendar
map <F8> :Calendar<cr>

F8 调出日历窗口,按 q 退出。

在日期上点回车,就可以编辑当天的日记了!

PS: 按左右键在前后一个月里跳转,按上下键在前后一年跳转。按 t 回到当天。当然,Vim 默认的上下左右 hjkl 也是能用的。

多个维基项目

您可以配置 g:vimwiki_list,指定多个维基项目,它们各自拥有单独的文件夹。这就允许你把工作维基和生活的琐事记录完全分开。

请打开 vimrc ,加入以下内容:

let g:vimwiki_list = [{'path': 'E:/path/to/vimwiki-1/vimwiki/',  
  \ 'path_html': 'E:/My Dropbox/vimwiki_html/'
  \ 'html_header': 'E:/My Dropbox/Public/vimwiki_template/header.htm',
  \ 'html_footer': 'E:/My Dropbox/Public/vimwiki_template/footer.htm',
  \ 'diary_link_count': 5},
  \{'path': 'Z:/path/to/vimwiki-2/vimwiki/'}]

这里其实定义了两个维基项目。 path 是必须的,说明你想要把 wiki 条目存在哪个目录。其他选项各有默认值。生成的HTML存放在 path_html 下默认是与 path 同目录下的 WIKIFOLDER_html ,其中 WIKIFOLER 是你存放维基条目的文件夹名。你可以分别为每个 wiki 项目指定 html 头部和尾部模板,建议把模板文件后缀采用 htm ,既和生成的 html 有所区分,又能保证语法高亮和各种 ftplugin 可用。 diary_link_count 是指 diary.wiki 里每行放多少个日志链接。

定义好之后,你可以使用 <leader>ws 选择当前活动的维基项目。使用 <leader>ws 会弹出一个维基项目的列表,并带有编号,使用这个编号加上“快捷键总览”部分的快捷键,就可以打开相应项目的首页、日记等。如 2<leader>w<leader>w 就是在当前窗口打开列表中第二个项目的日记。

更多选项请参考 :h viwmiki-local-options

任务管理 TODO-list

Loading...

编辑表格

Loading...


调教你的 vimwiki

<b>警告!</b> 以下为高级内容,虽然我手把手在教,但毕竟折腾耗时。
而且您的操作可能因为 vimwiki 将来的版本升级而失效。
请评估自己的时间成本!

做一个你自己的模板

vimwiki 生成的HTML会都会链接相应vimwiki_html目录下的style.css。如果你不自己指定,它会自动生成一个默认的。CSS禅意花园的境界是什么来着,仅仅修改 style.css 就能拥有风格完全不同的页面。通过简单修改 style.css ,你完全可以创造自己风格的维基站。加上自定义文档头部和尾部的功能,折腾出一个个人网站来绰绰有余。当然,如果你还在想新闻列表,feed订阅什么的,请赶快走开。毕竟, vimwiki 不是 CMS 。

可惜的是,并不能指定一个 style.css 的模板,如果你还折腾了一些 !JavaScript 增强,就更麻烦了。需要的话请自行把相关文件复制过去吧。当然,你也可以直接把本页面另存为,使用我的模板!具体实现请自己折腾。

HTML 模板增强

使footer也可以引用 %root_path%

修改 $VIMFILES/autoload/vimwiki_html.vim ,第 1169 行

call extend(ldest, s:get_html_footer())

换为

call extend(ldest, s:get_html_footer(subdir))

相应的, s:get_html_footer 这个函数也要改一下。第 136 行,函数定义的部分:

function! s:get_html_footer()

改为

function! s:get_html_footer(subdir)

再从 s:get_html_header 里把处理 %root_path% 的部分拷过去。第 104 行:

call map(lines, 'substitute(v:val, "%root_path%", "'. \ s:root_path(a:subdir) .'", "g")')

复制到第 141 行 let lines = readfile(expand(VimwikiGet('html_footer'))) 之后

在wiki里使用更多的HTML标签

vimwiki 有一个 g:vimwiki_valid_html_tags 值,可以指定允许写在 wiki 中的HTML标签。 g:vimwiki_valid_html_tags 的默认值是 'b,i,s,u,sub,sup,kbd,br,hr' ,也就是说,当你在 wiki 中输入:

\<b\>Hello\</b\> <strong>Hello</stong>

输出的HTML会显示为:

Hello <strong>Hello</stong>

标签 b 被当作可用的HTML标签,而 strong 则输出为文本。

但有时候我们需要建立更强大的维基页面,不只用到这几个标签。比如[http://wiki.ktmud.com 本站首页]的“[http://wiki.ktmud.com/index.html#whats-special 有什么特别的]”部分,就是一个有特定 classiddiv。于是在 vimrc 中定义:

let g:vimwiki_valid_html_tags='b,i,s,u,sub,sup,kbd,br,hr,div,del,code'

在这里我添加了 div, del, code 三个标签。

但是,非常不幸,当我们需要在维基里贴HTML代码,即使我们把代码放到了 \{\{\{ \}\}\} 包裹的 pre 里,这几个标签还是会被输出为实际的HTML标签,而不是文本。

解决办法还是修改 vimwiki_html.vim 这个文件。

找到 " WIKI2HTML "\{\{\{ 所在行,也就是开始转换HTML的地方。

在前面添加一个函数:

function s:parse_tag_keeper(line)
  let line = substitute(a:line,'\\&lt;',
        \'\&lt;', 'g')
  let line = substitute(line,'\\&gt;',
        \'\&gt;', 'g')
  return line
endfunction

然后在之后的 s:parse_line(line, state) 函数内,插入这个函数的调用:

    ...

    let line = s:safe_html(a:line)
    <b>let line = s:parse_tag_keeper(line)</b>

这样如果我们用 \<tag\> 的形式输入 valid_html_tags 包括的标签,输出的HTML就会把它们当成文本处理了。

在写本文时,我需要输出 \{\{\{ \}\}\} ,而这对标记被作为了 wiki 里 pre 区块的 pattern 。于是就还要再写一个函数:

function s:parse_pre_keeper(line)
  let line = substitute(a:line,'\\{\\{\\{',
        \'\{\{\{', 'g')
  let line = substitute(line,'\\}\\}\\}',
        \'\}\}\}', 'g')
  return line
endfunction

就把它定义在 s:parse_tag_keeper 之后吧。但调用的时候怎么办呢?肯定要放在 vimwiki_html.vim 处理了 pre 区块之后。思来想去,只能放在刚好要输出HTML文件的时候。但是 vim 的 writefile 函数,接受的参数是一个 list (相当于数组),而不是字串。既然如此,我们就把输出结果给合并了再替换,然后再包装成 list 。

找到这句:

call writefile(ldest, path.wwFileNameOnly.'.html')

稍微修改一下:

let output = join(ldest, "\n\r")
let output = s:parse_pre_keeper(output)
let outputlist = split(output, "\n\r")
call writefile(outputlist, path.wwFileNameOnly.'.html')

之所以还要再split,是因为writefile写入的 NL 是无法用字符模拟的。这样当然会造成性能问题,如果有知道更好解决方案的,请留言告诉我。