首先,是要能快速调用gvim来编辑浏览器上文本框。我使用的 firefox + pentadactyl, 默认可以在文本框里按 <C-i> 来调用 gvim 来编辑帖子。firefox 也有相关的插件专门做这事的,It's All Text 插件
其次,将ubuntu论坛的文本框识别为 定文件类型,好进行个别设置。例如,我的是
[vim]
au BufRead /tmp/pentadactyl-forum.ubuntu* setf bbcode
[/vim]
这样可以把ubuntu论坛的文本框设置成bbcode文件类型。因为ubuntu论坛是支持使用bbcode来发帖的。
然后,是语法高bbcode syntax hilight plugin
上面是vim.org上下载的bbcode的语法高亮脚本,我作了如下修改,以主要是使被引用的的文字与自己本次写的文字能区分开来,发帖时看得清楚。
[diff]
--- a/bbcode.vim
+++ b/bbcode.vim
@@ -17,6 +17,7 @@
syn region bbcodeTag start="\[/\{0,1}" end="\]" contains=@NoSpell,bbcodeItem,bbcodeArgument,bbcodeValue
syn region bbcodeBold start="\[b\]" end="\[/b\]"me=e-4 contains=bbcodeTag,bbcodeBoldItalic,bbcodeBoldUnderline
+syn region bbcodeQuote start="\[quote\(=\"[^]\"]\+\"\)\?\]" end="\[/quote\]" keepend extend contains=bbcodeQuote,bbcodeTag,bbcodeBoldItalic,bbcodeBoldUnderline
syn region bbcodeBoldItalic contained start="\[i\]" end="\[/i\]"me=e-4 contains=bbcodeTag,bbcodeBoldItalicUnderline
syn region bbcodeBoldItalicUnderline contained start="\[u\]" end="\[/u\]"me=e-4 contains=bbcodeTag
syn region bbcodeBoldUnderline contained start="\[u\]" end="\[/u\]"me=e-4 contains=bbcodeTag,bbcodeBoldUnderlineItalic
@@ -41,6 +42,7 @@
hi link bbcodeArgument Type
hi link bbcodeValue Constant
hi link bbcodeUrl Underlined
+hi link bbcodeQuote Comment
hi link bbcodeBoldUnderlineItalic bbcodeBoldItalicUnderline
hi link bbcodeItalicBold bbcodeBoldItalic
[/diff]
完成了语法高亮,接下来就到编辑帖子了。论坛帖子,默认是长行,所以,我做了个设置在长行,jk是移动屏幕上的一行
[vim]
function MapFlow()
noremap <buffer> j gj
noremap <buffer> k gk
noremap <buffer> 0 g0
noremap <buffer> ^ g^
noremap <buffer> $ g$
let b:old_textwidth=&l:tw
setl tw=0
endfunction
function UnMapFlow()
unmap <buffer> <silent> j
unmap <buffer> <silent> k
unmap <buffer> <silent> 0
unmap <buffer> <silent> ^
unmap <buffer> <silent> $
if exists('b:old_textwidth')
exec 'setl tw=' . b:old_textwidth
endif
endfunction
[/vim]
再在 ftplugin/bbcode.vim 里面写上
[vim]
if exists("*MapFlow()")
call MapFlow()
endif
[/vim]
快速输入文字,当然少不了snippets功能,上 snipMate, 以下是我的snippets
[vim]
snippet list
[list${1:=1}]
${2}
[/list]
snippet code
[${1:code}]
${2}
[/$1]
${0}
snippet quote
snippet /quote${1}
[/quote]
${1}
snippet *
[*]
snippet ×
[*]
snippet python
[python]
${1}
[/python]
${2}
snippet bash
[bash]
${1}
[/bash]
${2}
snippet vim
[vim]
${1}
[/vim]
${2}
snippet c
[c]
${1}
[/c]
${2}
snippet fortran
[fortran]
${1}
[/fortran]
${2}
snippet url
$2 $0
[/vim]
这些snippte的用处,主要是快速插件一些标签,可用于输入vim或者它代码等。另 /quote<Tab> 可以在引用别人的话中迅速开始自己的话。
最后上一个我写的针对于bbcode text object支持的插件。text-object 是 vim 中我最喜欢的功能之一了。如光标在小括号中时,按 ci( 可以清除双引号中所有字符并立即开始编辑. bbcode 使用了与 html 标签类似标签,但把尖括号换成了方括号。对于 html 的标签,vim内建有不错的支持,如 cit 可以清除如 <td> foo </ts> 之内的文字,并开始插入。对于 bbcode 的方括号,vim 就没有内建支持了。但这个插件提供 bbcode 中与 html 的 tag 类似的 text object 支持,并且绑定在相同的按键上。
举例说明下此插件的典型用法。论坛中相互引用回帖,次数较多时,单个帖子就会迅速变得很长,手动删除又显得麻烦。利用这个插件,可以在一个 quote 上按 dat, 插件会找到对应的 /quote, 并且把此 quote 整个删除。
[vim]
" bbcode_textobject.vim: bbcode text object
" bbcode style *tag* text object.
" just like how <head> </head> tags is supported in html.
" Last Change: 2011-12-17
" Maintainer: Fermat <[email protected]>
" Licence: This script is released under the Vim License.
" Install: This is an filetype plugin, put in it some path like
" ~/.vim/ftplugin
" and make sure
" filetype plugin on
" is in you .vimrc file.
" Mappings:
" it inner tag
" at an tag
" vit put inner tag in visual mode
" dat delete a tag
" cit delete inner tag and start insert mode
" etc.
" Tips:
" press '' can return to where you start the visual mode,
" useful when you accidentally select a large region.
function! s:VisualSelectRegion(region, ...) "{{{
let vmode = ''
let maxlines = line("$")
if a:0 > 1
echoerr "Too many arguments!"
return
elseif a:0 == 1
if a:1 !=# 'v' && a:1 !=# 'V' && a:1 !=# ''
echoerr "Wrong region is given!"
return
else
let vmode = (a:1 ==? 'v' ? a:1 : '')
endif
endif
if type(a:region) == 3 && len(a:region) == 2
\ && type(a:region[0]) == 3 && len(a:region[0]) == 2
\ && type(a:region[1]) == 3 && len(a:region[1]) == 2
let region_b = a:region[0]
let region_e = a:region[1]
" check position b
if region_b[0] <= 0
let region_b = [1,1]
elseif region_b[0] > maxlines + 1 ||
\ (region_b[0] == maxlines + 1 && region_b[1] > 1)
let region_b = [maxlines + 1, 1]
endif
if region_b[1] < 1
let region_b[1] = 1
else
let ncol = len(getline(region_b[0]))
if region_b[1] > ncol + 2
let region_b[1] = ncol + 2
endif
if region_b[1] == ncol + 2
let region_b[1] = ncol + 1
let region_b[0] = region_b[0] + 1
endif
endif
" check position e
if region_e[0] <= 0
let region_e = [1,1]
elseif region_e[0] > maxlines + 1 ||
\ (region_e[0] == maxlines + 1 && region_e[1] > 1)
let region_e = [maxlines + 1, 1]
endif
if region_e[1] < 1
let region_e[1] = 1
else
let ncol = len(getline(region_e[0]))
if region_e[1] > ncol + 2
let region_e[1] = ncol + 2
endif
if region_e[1] == ncol + 2
let region_e[1] = ncol + 1
let region_e[0] = region_e[0] + 1
endif
endif
if region_b == region_e
echoerr "Nothing in region!"
endif
if region_b[0] > region_e[0] || (region_b[0]==region_e[0]
\ && region_b[1] > region_e[1])
let ltmp = region_b
let region_b = region_e
let region_e = ltmp
unlet ltmp
endif
else
echoerr "Wrong region is given!"
return
endif
if mode() != 'no'
exec "normal! \<Esc>"
endif
if region_b[1] == 1 && region_e[1] == 1
let vmode = (vmode ==? 'v' ? vmode : 'V')
else
let vmode = (vmode ==? 'v' ? vmode : 'v')
endif
if &selection !=# 'exclusive' ||
\ (&selection ==# 'exclusive' && vmode ==# 'V'
\ && region_e[1] == 1)
let region_e[1] = region_e[1] - 1
if region_e[1] == 0
let region_e[0] = region_e[0] - 1
let region_e[1] = 1 + len(getline(region_e[0]))
endif
endif
call setpos("''", getpos("."))
call cursor(region_b)
exec 'normal! ' . vmode
call cursor(region_e)
normal! o
endfunction " }}}
function! s:BbcodeTagsTextObject(mode) " {{{
if a:mode !=# 'a' && a:mode !=# 'i'
echoerr 'Bad argument!'
endif
let sflags = 'Wn'
let oldpos = getpos(".")
let region_b = searchpairpos('\[\w\+\%(=[^]]\+\)\?\]', '',
\ '\[/\w\+\zs\]', sflags . 'bc')
let region_e = searchpairpos('\[\w\+\%(=[^]]\+\)\?\]', '',
\ '\[/\w\+\zs\]', sflags)
if region_b == [0,0] || region_e == [0,0]
return 0
endif
call cursor(region_e)
let region_e = searchpos('\[/\w\+\]', sflags . 'b')
if region_e == [0,0]
echoerr "This shouldn't appear, you can consider to report a bug."
return 0
endif
call setpos(".", oldpos)
if matchlist(getline(region_b[0]), '\[\(\w\+\)\%(=[^]]\+\)\?\]', region_b[1]-1)[1]
\ != matchlist(getline(region_e[0]),'\[/\(\w\+\)\]', region_e[1]-1)[1]
echoerr "start and end tag do not match."
return 0
endif
if a:mode ==# 'i'
let region_b[1] = matchend(getline(region_b[0]),
\ '\[\(\w\+\)\%(=[^]]\+\)\?\]\s*', region_b[1]-1) + 1
if region_b[1] > len(getline(region_b[0]))
let region_b[1] = 1
let region_b[0] = region_b[0] + 1
endif
if strpart(getline(region_e[0]),0,region_e[1]-1) =~ '^\s\+$'
let region_e[1] = 1
endif
else
if strpart(getline(region_b[0]),0,region_b[1]-1) =~ '^\s\+$'
let region_b[1] = 1
endif
let region_e[1] = matchend(getline(region_e[0]),
\ '\[/\(\w\+\)\]\s*', region_e[1]-1) + 1
if region_e[1] > len(getline(region_e[0]))
let region_e[0] = region_e[0] + 1
let region_e[1] = 1
endif
endif
if region_b[1] == -1 || region_e[1] == -1
return 0
endif
return s:VisualSelectRegion([region_b, region_e])
endfunction " }}}
" key mappings {{{
onoremap <silent> <buffer> it :<C-u>call <SID>BbcodeTagsTextObject('i')<CR>
onoremap <silent> <buffer> at :<C-u>call <SID>BbcodeTagsTextObject('a')<CR>
vnoremap <silent> <buffer> it :<C-u>call <SID>BbcodeTagsTextObject('i')<CR>
vnoremap <silent> <buffer> at :<C-u>call <SID>BbcodeTagsTextObject('a')<CR>
" }}}
" vim:set fdm=marker sw=4 ts=8:
[/vim]
把我修改过的 bbcode 语法高亮插件也传一份吧,省得需要手动改了
[vim]
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
syn case ignore
syn spell toplevel
syn match bbcodeItem contained "\[\s*[-a-zA-Z0-9]\+"hs=s+1 contains=@NoSpell
syn match bbcodeItem contained "\[/\s*[-a-zA-Z0-9]\+"hs=s+2 contains=@NoSpell
syn match bbcodeItem contained "\[\s*\*\s*\]"hs=s+1,he=e-1 contains=@NoSpell
syn match bbcodeArgument contained "\s[-a-zA-Z0-9]\+\s*="ms=s+1,me=e-1 contains=@NoSpell
syn region bbcodeValue contained start="\"" end="\"" contains=@NoSpell
syn region bbcodeValue contained start="'" end="'" contains=@NoSpell
syn match bbcodeValue contained "=[\t ]*[^'" \t\]][^ \t\]]*"hs=s+1 contains=@NoSpell
syn region bbcodeTag start="\[/\{0,1}" end="\]" contains=@NoSpell,bbcodeItem,bbcodeArgument,bbcodeValue
syn region bbcodeBold start="\[b\]" end="\[/b\]"me=e-4 contains=bbcodeTag,bbcodeBoldItalic,bbcodeBoldUnderline
syn region bbcodeQuote start="\[quote\(=\"[^]\"]\+\"\)\?\]" end="\[/quote\]" keepend extend contains=bbcodeQuote,bbcodeTag,bbcodeBoldItalic,bbcodeBoldUnderline
syn region bbcodeBoldItalic contained start="\[i\]" end="\[/i\]"me=e-4 contains=bbcodeTag,bbcodeBoldItalicUnderline
syn region bbcodeBoldItalicUnderline contained start="\[u\]" end="\[/u\]"me=e-4 contains=bbcodeTag
syn region bbcodeBoldUnderline contained start="\[u\]" end="\[/u\]"me=e-4 contains=bbcodeTag,bbcodeBoldUnderlineItalic
syn region bbcodeBoldUnderlineItalic contained start="\[i\]" end="\[/i\]"me=e-4 contains=bbcodeTag
syn region bbcodeItalic start="\[i\]" end="\[/i\]"me=e-4 contains=bbcodeTag,bbcodeItalicBold,bbcodeItalicUnderline
syn region bbcodeItalicBold contained start="\[b\]" end="\[/b\]"me=e-4 contains=bbcodeTag,bbcodeItalicBoldUnderline
syn region bbcodeItalicBoldUnderline contained start="\[u\]" end="\[/u\]"me=e-4 contains=bbcodeTag
syn region bbcodeItalicUnderline contained start="\[u\]" end="\[/u\]"me=e-4 contains=bbcodeTag,bbcodeItalicUnderlineBold
syn region bbcodeItalicUnderlineBold contained start="\[b\]" end="\[/b\]"me=e-4 contains=bbcodeTag
syn region bbcodeUnderline start="\[u\]" end="\[/u\]"me=e-4 contains=bbcodeTag,bbcodeUnderlineBold,bbcodeUnderlineItalic
syn region bbcodeUnderlineBold contained start="\[b\]" end="\[/b\]"me=e-4 contains=bbcodeTag,bbcodeUnderlineBoldItalic
syn region bbcodeUnderlineBoldItalic contained start="\[i\]" end="\[/i\]"me=e-4 contains=bbcodeTag
syn region bbcodeUnderlineItalic contained start="\[i\]" end="\[/i\]"me=e-4 contains=bbcodeTag,bbcodeUnderlineItalicBold
syn region bbcodeUnderlineItalicBold contained start="\[b\]" end="\[/b\]"me=e-4 contains=bbcodeTag
syn region bbcodeUrl start="\[url\s*[=\]]" end="\[/url\]"me=e-6 contains=@NoSpell,bbcodeTag
hi link bbcodeTag Identifier
hi link bbcodeItem Statement
hi link bbcodeArgument Type
hi link bbcodeValue Constant
hi link bbcodeUrl Underlined
hi link bbcodeQuote Comment
hi link bbcodeBoldUnderlineItalic bbcodeBoldItalicUnderline
hi link bbcodeItalicBold bbcodeBoldItalic
hi link bbcodeItalicBoldUnderline bbcodeBoldItalicUnderline
hi link bbcodeItalicUnderlineBold bbcodeBoldItalicUnderline
hi link bbcodeUnderlineBold bbcodeBoldUnderline
hi link bbcodeUnderlineBoldItalic bbcodeBoldItalicUnderline
hi link bbcodeUnderlineItalic bbcodeItalicUnderline
hi link bbcodeUnderlineItalicBold bbcodeBoldItalicUnderline
hi def bbcodeBold term=bold cterm=bold gui=bold
hi def bbcodeBoldItalic term=bold,italic cterm=bold,italic gui=bold,italic
hi def bbcodeBoldItalicUnderline term=bold,italic,underline cterm=bold,italic,underline gui=bold,italic,underline
hi def bbcodeBoldUnderline term=bold,underline cterm=bold,underline gui=bold,underline
hi def bbcodeItalic term=italic cterm=italic gui=italic
hi def bbcodeItalicUnderline term=italic,underline cterm=italic,underline gui=italic,underline
hi def bbcodeUnderline term=underline cterm=underline gui=underline
let b:current_syntax = "bbcode"
[/vim]