removed packages

pull/1/head
Adam Veldhousen 10 years ago
parent 651c2f8a32
commit 0eb3233412

@ -1,84 +0,0 @@
This is a mirror of http://www.vim.org/scripts/script.php?script_id=2423
This is vimscript for gist (http://gist.github.com)
Usage:
:Gist
post whole text to gist.
:'<,'>Gist
post selected text to gist.
:Gist -p
post whole text to gist with private.
if you got empty gist list, try :Gist --abandon
:Gist -a
post whole text to gist with anonymous.
:Gist -m
post multi buffer to gist.
:Gist -e
edit the gist. (shoud be work on gist buffer)
you can update the gist with :w command on gist buffer.
:Gist -e foo.js
edit the gist with name 'foo.js'. (shoud be work on gist buffer)
:Gist -d
delete the gist. (should be work on gist buffer)
password authentication is needed.
:Gist -f
fork the gist. (should be work on gist buffer)
password authentication is needed.
:Gist XXXXX
get gist XXXXX.
:Gist -c XXXXX.
get gist XXXXX and put to clipboard.
:Gist -l
list gists from mine.
:Gist -la
list gists from all.
Tips:
if set g:gist_clip_command, gist.vim will copy the gist code
with option '-c'.
# mac
let g:gist_clip_command = 'pbcopy'
# linux
let g:gist_clip_command = 'xclip -selection clipboard'
# others(cygwin?)
let g:gist_clip_command = 'putclip'
if you want to detect filetype from filename...
let g:gist_detect_filetype = 1
if you want to open browser after the post...
let g:gist_open_browser_after_post = 1
if you want to change the browser...
let g:gist_browser_command = 'w3m %URL%'
or
let g:gist_browser_command = 'opera %URL% &'
on windows, should work with original setting.
Require:
curl command (http://curl.haxx.se/)
and if you want to use profile of git, it require git command.

@ -1,203 +0,0 @@
### Gist.vim
This is a vimscript for creating gists (http://gist.github.com).
For the latest version please see https://github.com/mattn/gist-vim.
## Usage:
- Post current buffer to gist, using default privacy option.
:Gist
- Post selected text to gist, using default privacy option.
This applies to all permutations listed below (except multi).
:'<,'>Gist
- Create a private gist.
:Gist -p
- Create a public gist.
(Only relevant if you've set gists to be private by default.)
:Gist -P
> This is only relevant if you've set gists to be private by default;
> if you get an empty gist list, try ":Gist --abandon".
- Create a gist anonymously.
:Gist -a
- Create a gist with all open buffers.
:Gist -m
- Edit the gist (you need to have opened the gist buffer first).
You can update the gist with the ":w" command within the gist buffer.
:Gist -e
- Edit the gist with name 'foo.js' (you need to have opened the gist buffer
first).
:Gist -e foo.js
- Post/Edit with the description " (you need to have opened the gist buffer
first). >
:Gist -s something
:Gist -e -s something
- Delete the gist (you need to have opened the gist buffer first).
Password authentication is needed.
:Gist -d
- Fork the gist (you need to have opened the gist buffer first).
Password authentication is needed.
:Gist -f
- Star the gist (you need to have opened the gist buffer first).
Password authentication is needed.
:Gist +1
- Unstar the gist (you need to have opened the gist buffer first).
Password authentication is needed.
:Gist -1
- Get gist XXXXX.
:Gist XXXXX
- Get gist XXXXX and add to clipboard.
:Gist -c XXXXX
- List your public gists.
:Gist -l
- List gists from user "mattn".
:Gist -l mattn
- List everyone's gists.
:Gist -la
- List gists from your starred gists.
:Gist -ls
## Tips:
If you set g:gist_clip_command, gist.vim will copy the gist code with option
'-c'.
- Mac:
let g:gist_clip_command = 'pbcopy'
- Linux:
let g:gist_clip_command = 'xclip -selection clipboard'
- Others (cygwin?):
let g:gist_clip_command = 'putclip'
If you want to detect filetype from the filename:
let g:gist_detect_filetype = 1
If you want to open browser after the post:
let g:gist_open_browser_after_post = 1
If you want to change the browser:
let g:gist_browser_command = 'w3m %URL%'
or:
let g:gist_browser_command = 'opera %URL% &'
On windows, this should work with your user settings.
If you want to show your private gists with ":Gist -l":
let g:gist_show_privates = 1
If you want your gist to be private by default:
let g:gist_post_private = 1
If you want to manipulate multiple files in a gist:
let g:gist_get_multiplefile = 1
You need to either set global git config:
$ git config --global github.user Username
## Requirements:
- curl command (http://curl.haxx.se/)
- webapi-vim (https://github.com/mattn/webapi-vim)
- and if you want to use your git profile, the git command-line client.
## License:
Copyright 2010 by Yasuhiro Matsumoto
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
## Install:
Copy it to your plugin directory.
gist.vim will create a curl cookie-jar file in your runtimepath.
- rtp:
- plugin/gist.vim
- cookies/github
If you want to uninstall gist.vim, remember to also remove `~/.gist-vim`.
## Setup:
This plugin uses github API v3. Setting value is stored in `~/.gist-vim`.
gist-vim have two ways to access APIs.
First, you need to set your Github username in global git config:
$ git config --global github.user Username
Then, gist.vim will ask for your password to create an authorization when you
first use it. The password is not stored and only the OAuth access token will
be kept for later use. You can revoke the token at any time from the list of
["Authorized applications" on Github's "Account Settings" page](https://github.com/settings/applications).

@ -1,894 +0,0 @@
"=============================================================================
" File: gist.vim
" Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
" Last Change: 27-Sep-2012.
" Version: 7.0
" WebPage: http://github.com/mattn/gist-vim
" License: BSD
let s:save_cpo = &cpo
set cpo&vim
let s:configfile = expand('~/.gist-vim')
if !exists('g:github_user')
let s:system = function(get(g:, 'webapi#system_function', 'system'))
let g:github_user = substitute(s:system('git config --get github.user'), "\n", '', '')
if strlen(g:github_user) == 0
let g:github_user = $GITHUB_USER
end
endif
function! s:get_browser_command()
let gist_browser_command = get(g:, 'gist_browser_command', '')
if gist_browser_command == ''
if has('win32') || has('win64')
let gist_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'
elseif has('mac') || has('macunix') || has('gui_macvim') || system('uname') =~? '^darwin'
let gist_browser_command = 'open %URL%'
elseif executable('xdg-open')
let gist_browser_command = 'xdg-open %URL%'
elseif executable('firefox')
let gist_browser_command = 'firefox %URL% &'
else
let gist_browser_command = ''
endif
endif
return gist_browser_command
endfunction
function! s:open_browser(url)
let cmd = s:get_browser_command()
if len(cmd) == 0
redraw
echohl WarningMsg
echo "It seems that you don't have general web browser. Open URL below."
echohl None
echo a:url
return
endif
if cmd =~ '^!'
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
silent! exec cmd
elseif cmd =~ '^:[A-Z]'
let cmd = substitute(cmd, '%URL%', '\=a:url', 'g')
exec cmd
else
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
call system(cmd)
endif
endfunction
function! s:shellwords(str)
let words = split(a:str, '\%(\([^ \t\''"]\+\)\|''\([^\'']*\)''\|"\(\%([^\"\\]\|\\.\)*\)"\)\zs\s*\ze')
let words = map(words, 'substitute(v:val, ''\\\([\\ ]\)'', ''\1'', "g")')
let words = map(words, 'matchstr(v:val, ''^\%\("\zs\(.*\)\ze"\|''''\zs\(.*\)\ze''''\|.*\)$'')')
return words
endfunction
function! s:format_gist(gist)
let files = sort(keys(a:gist.files))
if empty(files)
return ""
endif
let file = a:gist.files[files[0]]
if has_key(file, "content")
let code = file.content
let code = "\n".join(map(split(code, "\n"), '" ".v:val'), "\n")
else
let code = ""
endif
return printf("gist: %s %s%s", a:gist.id, type(a:gist.description)==0?"": a:gist.description, code)
endfunction
" Note: A colon in the file name has side effects on Windows due to NTFS Alternate Data Streams; avoid it.
let s:bufprefix = 'gist' . (has('unix') ? ':' : '_')
function! s:GistList(gistls, page)
if a:gistls == '-all'
let url = 'https://api.github.com/gists/public'
elseif get(g:, 'gist_show_privates', 0) && a:gistls == 'starred'
let url = 'https://api.github.com/gists/starred'
elseif get(g:, 'gist_show_privates') && a:gistls == 'mine'
let url = 'https://api.github.com/gists'
else
let url = 'https://api.github.com/users/'.a:gistls.'/gists'
endif
let winnum = bufwinnr(bufnr(s:bufprefix.a:gistls))
if winnum != -1
if winnum != bufwinnr('%')
exe winnum 'wincmd w'
endif
setlocal modifiable
else
exec 'silent noautocmd split' s:bufprefix.a:gistls
endif
if a:page > 1
let oldlines = getline(0, line('$'))
let url = url . '?page=' . a:page
endif
setlocal modifiable
let old_undolevels = &undolevels
let oldlines = []
silent %d _
redraw | echon 'Listing gists... '
let auth = s:GistGetAuthHeader()
if len(auth) == 0
bw!
redraw
echohl ErrorMsg | echomsg 'Canceled' | echohl None
return
endif
let res = webapi#http#get(url, '', { "Authorization": auth })
if v:shell_error != 0
bw!
redraw
echohl ErrorMsg | echomsg 'Gists not found' | echohl None
return
endif
let content = webapi#json#decode(res.content)
if type(content) == 4 && has_key(content, 'message') && len(content.message)
bw!
redraw
echohl ErrorMsg | echomsg content.message | echohl None
if content.message == 'Bad credentials'
call delete(s:configfile)
endif
return
endif
let lines = map(filter(content, '!empty(v:val.files)'), 's:format_gist(v:val)')
call setline(1, split(join(lines, "\n"), "\n"))
$put='more...'
let b:gistls = a:gistls
let b:page = a:page
setlocal buftype=nofile bufhidden=hide noswapfile
setlocal nomodified
setlocal nomodifiable
syntax match SpecialKey /^gist:/he=e-1
nnoremap <silent> <buffer> <cr> :call <SID>GistListAction(0)<cr>
nnoremap <silent> <buffer> <s-cr> :call <SID>GistListAction(1)<cr>
cal cursor(1+len(oldlines),1)
nohlsearch
redraw | echo ''
endfunction
function! gist#list(user, ...)
let page = get(a:000, 0, 0)
if a:user == '-all'
let url = 'https://api.github.com/gists/public'
elseif get(g:, 'gist_show_privates', 0) && a:user == 'starred'
let url = 'https://api.github.com/gists/starred'
elseif get(g:, 'gist_show_privates') && a:user == 'mine'
let url = 'https://api.github.com/gists'
else
let url = 'https://api.github.com/users/'.a:user.'/gists'
endif
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return []
endif
let res = webapi#http#get(url, '', { "Authorization": auth })
return webapi#json#decode(res.content)
endfunction
function! s:GistGetFileName(gistid)
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return ''
endif
let res = webapi#http#get('https://api.github.com/gists/'.a:gistid, '', { "Authorization": auth })
let gist = webapi#json#decode(res.content)
if has_key(gist, 'files')
return sort(keys(gist.files))[0]
endif
return ''
endfunction
function! s:GistDetectFiletype(gistid)
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return ''
endif
let res = webapi#http#get('https://api.github.com/gists/'.a:gistid, '', { "Authorization": auth })
let gist = webapi#json#decode(res.content)
let filename = sort(keys(gist.files))[0]
let ext = fnamemodify(filename, ':e')
if has_key(s:extmap, ext)
let type = s:extmap[ext]
else
let type = get(gist.files[filename], "type", "text")
endif
silent! exec "setlocal ft=".tolower(type)
endfunction
function! s:GistWrite(fname)
if substitute(a:fname, '\\', '/', 'g') == expand("%:p:gs@\\@/@")
Gist -e
else
exe "w".(v:cmdbang ? "!" : "") fnameescape(v:cmdarg) fnameescape(a:fname)
silent! exe "file" fnameescape(a:fname)
silent! au! BufWriteCmd <buffer>
endif
endfunction
function! s:GistGet(gistid, clipboard)
redraw | echon 'Getting gist... '
let res = webapi#http#get('https://api.github.com/gists/'.a:gistid, '', { "Authorization": s:GistGetAuthHeader() })
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
let gist = webapi#json#decode(res.content)
if get(g:, 'gist_get_multiplefile', 0) != 0
let num_file = len(keys(gist.files))
else
let num_file = 1
endif
redraw
if num_file > len(keys(gist.files))
echohl ErrorMsg | echomsg 'Gist not found' | echohl None
return
endif
for n in range(num_file)
try
let old_undolevels = &undolevels
let filename = sort(keys(gist.files))[n]
let winnum = bufwinnr(bufnr(s:bufprefix.a:gistid."/".filename))
if winnum != -1
if winnum != bufwinnr('%')
exe winnum 'wincmd w'
endif
setlocal modifiable
else
exec 'silent noautocmd new'
setlocal noswapfile
exec 'noautocmd file' s:bufprefix.a:gistid."/".fnameescape(filename)
endif
set undolevels=-1
filetype detect
silent %d _
let content = gist.files[filename].content
call setline(1, split(content, "\n"))
let b:gist = {
\ "filename": filename,
\ "id": gist.id,
\ "description": gist.description,
\ "private": gist.public =~ 'true',
\}
catch
let &undolevels = old_undolevels
bw!
redraw
echohl ErrorMsg | echomsg 'Gist contains binary' | echohl None
return
endtry
let &undolevels = old_undolevels
setlocal buftype=acwrite bufhidden=delete noswapfile
setlocal nomodified
doau StdinReadPost,BufRead,BufReadPost
let gist_detect_filetype = get(g:, 'gist_detect_filetype', 0)
if (&ft == '' && gist_detect_filetype == 1) || gist_detect_filetype == 2
call s:GistDetectFiletype(a:gistid)
endif
if a:clipboard
if exists('g:gist_clip_command')
exec 'silent w !'.g:gist_clip_command
elseif has('clipboard')
silent! %yank +
else
%yank
endif
endif
1
au! BufWriteCmd <buffer> call s:GistWrite(expand("<amatch>"))
endfor
else
bw!
redraw
echohl ErrorMsg | echomsg 'Gist not found' | echohl None
return
endif
endfunction
function! s:GistListAction(shift)
let line = getline('.')
let mx = '^gist:\s*\zs\(\w\+\)\ze.*'
if line =~# mx
let gistid = matchstr(line, mx)
if a:shift
call s:open_browser("https://gist.github.com/" . gistid)
else
call s:GistGet(gistid, 0)
endif
return
endif
if line =~# '^more\.\.\.$'
call s:GistList(b:gistls, b:page+1)
return
endif
endfunction
function! s:GistUpdate(content, gistid, gistnm, desc)
let gist = { "id": a:gistid, "files" : {}, "description": "","public": function('webapi#json#true') }
if exists('b:gist')
if has_key(b:gist, 'private') && b:gist.private | let gist["public"] = function('webapi#json#false') | endif
if has_key(b:gist, 'description') | let gist["description"] = b:gist.description | endif
if has_key(b:gist, 'filename') | let filename = b:gist.filename | endif
else
let filename = a:gistnm
if len(filename) == 0 | let filename = s:GistGetFileName(a:gistid) | endif
if len(filename) == 0 | let filename = s:get_current_filename(1) | endif
endif
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg 'Canceled' | echohl None
return
endif
" Update description
" If no new description specified, keep the old description
if a:desc != ' '
let gist["description"] = a:desc
else
let res = webapi#http#get('https://api.github.com/gists/'.a:gistid, '', { "Authorization": auth })
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
let old_gist = webapi#json#decode(res.content)
let gist["description"] = old_gist.description
endif
endif
let gist.files[filename] = { "content": a:content, "filename": filename }
redraw | echon 'Updating gist... '
let res = webapi#http#post('https://api.github.com/gists/' . a:gistid,
\ webapi#json#encode(gist), {
\ "Authorization": auth,
\ "Content-Type": "application/json",
\})
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
let obj = webapi#json#decode(res.content)
let loc = obj["html_url"]
redraw | echomsg 'Done: '.loc
let b:gist = {"id": a:gistid, "filename": filename}
setlocal nomodified
else
let loc = ''
let status = matchstr(status, '^\d\+\s*\zs.*')
echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
endif
return loc
endfunction
function! s:GistDelete(gistid)
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg 'Canceled' | echohl None
return
endif
redraw | echon 'Deleting gist... '
let res = webapi#http#post('https://api.github.com/gists/'.a:gistid, '', {
\ "Authorization": auth,
\ "Content-Type": "application/json",
\}, 'DELETE')
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
redraw | echomsg 'Done: '
if exists('b:gist')
unlet b:gist
endif
else
let status = matchstr(status, '^\d\+\s*\zs.*')
echohl ErrorMsg | echomsg 'Delete failed: '.status | echohl None
endif
endfunction
function! s:get_current_filename(no)
let filename = expand('%:t')
if len(filename) == 0 && &ft != ''
let pair = filter(items(s:extmap), 'v:val[1] == &ft')
if len(pair) > 0
let filename = printf('gistfile%d%s', a:no, pair[0][0])
endif
endif
if filename == ''
let filename = printf('gistfile%d.txt', a:no)
endif
return filename
endfunction
" GistPost function:
" Post new gist to github
"
" if there is an embedded gist url or gist id in your file,
" it will just update it.
" -- by c9s
"
" embedded gist url format:
"
" Gist: https://gist.github.com/123123
"
" embedded gist id format:
"
" GistID: 123123
"
function! s:GistPost(content, private, desc, anonymous)
let gist = { "files" : {}, "description": "","public": function('webapi#json#true') }
if a:desc != ' ' | let gist["description"] = a:desc | endif
if a:private | let gist["public"] = function('webapi#json#false') | endif
let filename = s:get_current_filename(1)
let gist.files[filename] = { "content": a:content, "filename": filename }
let header = {"Content-Type": "application/json"}
if !a:anonymous
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg 'Canceled' | echohl None
return
endif
let header["Authorization"] = auth
endif
redraw | echon 'Posting it to gist... '
let res = webapi#http#post('https://api.github.com/gists', webapi#json#encode(gist), header)
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
let obj = webapi#json#decode(res.content)
let loc = obj["html_url"]
redraw | echomsg 'Done: '.loc
let b:gist = {
\ "filename": filename,
\ "id": matchstr(loc, '[^/]\+$'),
\ "description": gist['description'],
\ "private": a:private,
\}
else
let loc = ''
let status = matchstr(status, '^\d\+\s*\zs.*')
echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
endif
return loc
endfunction
function! s:GistPostBuffers(private, desc, anonymous)
let bufnrs = range(1, bufnr("$"))
let bn = bufnr('%')
let query = []
let gist = { "files" : {}, "description": "","public": function('webapi#json#true') }
if a:desc != ' ' | let gist["description"] = a:desc | endif
if a:private | let gist["public"] = function('webapi#json#false') | endif
let index = 1
for bufnr in bufnrs
if !bufexists(bufnr) || buflisted(bufnr) == 0
continue
endif
echo "Creating gist content".index."... "
silent! exec "buffer!" bufnr
let content = join(getline(1, line('$')), "\n")
let filename = s:get_current_filename(index)
let gist.files[filename] = { "content": content, "filename": filename }
let index = index + 1
endfor
silent! exec "buffer!" bn
let header = {"Content-Type": "application/json"}
if !a:anonymous
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg 'Canceled' | echohl None
return
endif
let header["Authorization"] = auth
endif
redraw | echon 'Posting it to gist... '
let res = webapi#http#post('https://api.github.com/gists', webapi#json#encode(gist), header)
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
let obj = webapi#json#decode(res.content)
let loc = obj["html_url"]
redraw | echomsg 'Done: '.loc
let b:gist = {"id": matchstr(loc, '[^/]\+$'), "filename": filename, "private": a:private}
else
let loc = ''
let status = matchstr(status, '^\d\+\s*\zs.*')
echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
endif
return loc
endfunction
function! gist#Gist(count, line1, line2, ...)
redraw
if strlen(g:github_user) == 0
echohl ErrorMsg | echomsg "You don't have github account. read ':help gist-vim-setup'." | echohl None
return
endif
let bufname = bufname("%")
" find GistID: in content , then we should just update
let gistid = ''
let gistls = ''
let gistnm = ''
let gistdesc = ' '
let private = get(g:, 'gist_post_private', 0)
let multibuffer = 0
let clipboard = 0
let deletepost = 0
let editpost = 0
let anonymous = 0
let listmx = '^\%(-l\|--list\)\s*\([^\s]\+\)\?$'
let bufnamemx = '^' . s:bufprefix .'\(\zs[0-9a-f]\+\ze\|\zs[0-9a-f]\+\ze[/\\].*\)$'
if bufname =~ bufnamemx
let gistidbuf = matchstr(bufname, bufnamemx)
else
let gistidbuf = matchstr(join(getline(a:line1, a:line2), "\n"), 'GistID:\s*\zs\w\+')
endif
let args = (a:0 > 0) ? s:shellwords(a:1) : []
for arg in args
if arg =~ '^\(-h\|--help\)$\C'
help :Gist
return
elseif arg =~ '^\(-la\|--listall\)$\C'
let gistls = '-all'
elseif arg =~ '^\(-ls\|--liststar\)$\C'
let gistls = 'starred'
elseif arg =~ '^\(-l\|--list\)$\C'
if get(g:, 'gist_show_privates')
let gistls = 'mine'
else
let gistls = g:github_user
endif
elseif arg =~ '^\(-m\|--multibuffer\)$\C'
let multibuffer = 1
elseif arg =~ '^\(-p\|--private\)$\C'
let private = 1
elseif arg =~ '^\(-P\|--public\)$\C'
let private = 0
elseif arg =~ '^\(-a\|--anonymous\)$\C'
let anonymous = 1
elseif arg =~ '^\(-s\|--description\)$\C'
let gistdesc = ''
elseif arg =~ '^\(-c\|--clipboard\)$\C'
let clipboard = 1
elseif arg =~ '^\(-d\|--delete\)$\C' && gistidbuf != ''
let gistid = gistidbuf
let deletepost = 1
elseif arg =~ '^\(-e\|--edit\)$\C' && gistidbuf != ''
let gistid = gistidbuf
let editpost = 1
elseif arg =~ '^\(+1\|--star\)$\C' && gistidbuf != ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
echohl ErrorMsg | echomsg 'Canceled' | echohl None
else
let gistid = gistidbuf
let res = webapi#http#post('https://api.github.com/gists/'.gistid.'/star', '', { "Authorization": auth }, 'PUT')
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
echomsg "Stared" gistid
else
echohl ErrorMsg | echomsg 'Star failed' | echohl None
endif
endif
return
elseif arg =~ '^\(-1\|--unstar\)$\C' && gistidbuf != ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
echohl ErrorMsg | echomsg 'Canceled' | echohl None
else
let gistid = gistidbuf
let res = webapi#http#post('https://api.github.com/gists/'.gistid.'/star', '', { "Authorization": auth }, 'DELETE')
if status =~ '^2'
echomsg "Unstared" gistid
else
echohl ErrorMsg | echomsg 'Unstar failed' | echohl None
endif
endif
return
elseif arg =~ '^\(-f\|--fork\)$\C' && gistidbuf != ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
echohl ErrorMsg | echomsg 'Canceled' | echohl None
return
else
let gistid = gistidbuf
let res = webapi#http#post('https://api.github.com/gists/'.gistid.'/fork', '', { "Authorization": auth })
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
if status =~ '^2'
let obj = webapi#json#decode(res.content)
let gistid = obj["id"]
else
echohl ErrorMsg | echomsg 'Fork failed' | echohl None
return
endif
endif
elseif arg !~ '^-' && len(gistnm) == 0
if gistdesc != ' '
let gistdesc = matchstr(arg, '^\s*\zs.*\ze\s*$')
elseif editpost == 1 || deletepost == 1
let gistnm = arg
elseif len(gistls) > 0 && arg != '^\w\+$\C'
let gistls = arg
elseif arg =~ '^[0-9a-z]\+$\C'
let gistid = arg
else
echohl ErrorMsg | echomsg 'Invalid arguments: '.arg | echohl None
unlet args
return 0
endif
elseif len(arg) > 0
echohl ErrorMsg | echomsg 'Invalid arguments: '.arg | echohl None
unlet args
return 0
endif
endfor
unlet args
"echo "gistid=".gistid
"echo "gistls=".gistls
"echo "gistnm=".gistnm
"echo "gistdesc=".gistdesc
"echo "private=".private
"echo "clipboard=".clipboard
"echo "editpost=".editpost
"echo "deletepost=".deletepost
if gistidbuf != '' && gistid == '' && editpost == 0 && deletepost == 0
let editpost = 1
let gistid = gistidbuf
endif
if len(gistls) > 0
call s:GistList(gistls, 1)
elseif len(gistid) > 0 && editpost == 0 && deletepost == 0
call s:GistGet(gistid, clipboard)
else
let url = ''
if multibuffer == 1
let url = s:GistPostBuffers(private, gistdesc, anonymous)
else
if a:count < 1
let content = join(getline(a:line1, a:line2), "\n")
else
let save_regcont = @"
let save_regtype = getregtype('"')
silent! normal! gvy
let content = @"
call setreg('"', save_regcont, save_regtype)
endif
if editpost == 1
let url = s:GistUpdate(content, gistid, gistnm, gistdesc)
elseif deletepost == 1
call s:GistDelete(gistid)
else
let url = s:GistPost(content, private, gistdesc, anonymous)
endif
if a:count >= 1 && get(g:, 'gist_keep_selection', 0) == 1
silent! normal! gv
endif
endif
if len(url) > 0
if get(g:, 'gist_open_browser_after_post', 0) == 1
call s:open_browser(url)
endif
let gist_put_url_to_clipboard_after_post = get(g:, 'gist_put_url_to_clipboard_after_post', 1)
if gist_put_url_to_clipboard_after_post > 0
if gist_put_url_to_clipboard_after_post == 2
let url = url . "\n"
endif
if exists('g:gist_clip_command')
call system(g:gist_clip_command, url)
elseif has('unix') && !has('xterm_clipboard')
let @" = url
else
let @+ = url
endif
endif
endif
endif
return 1
endfunction
function! s:GistGetAuthHeader()
if get(g:, 'gist_use_password_in_gitconfig', 0) != 0
let password = substitute(system('git config --get github.password'), "\n", '', '')
if password =~ '^!' | let password = system(password[1:]) | endif
return printf("basic %s", webapi#base64#b64encode(g:github_user.":".password))
endif
let auth = ""
if filereadable(s:configfile)
let str = join(readfile(s:configfile), "")
if type(str) == 1
let auth = str
endif
endif
if len(auth) > 0
return auth
endif
redraw
echohl WarningMsg
echo 'Gist.vim requires authorization to use the Github API. These settings are stored in "~/.gist-vim". If you want to revoke, do "rm ~/.gist-vim".'
echohl None
let password = inputsecret("Github Password for ".g:github_user.":")
if len(password) > 0
let insecureSecret = printf("basic %s", webapi#base64#b64encode(g:github_user.":".password))
let res = webapi#http#post('https://api.github.com/authorizations', webapi#json#encode({
\ "scopes" : ["gist"],
\ "note" : "Gist.vim on ".hostname(),
\ "note_url" : "http://www.vim.org/scripts/script.php?script_id=2423"
\}), {
\ "Content-Type" : "application/json",
\ "Authorization" : insecureSecret,
\})
let authorization = webapi#json#decode(res.content)
if has_key(authorization, 'token')
let secret = printf("token %s", authorization.token)
call writefile([secret], s:configfile)
if !(has('win32') || has('win64'))
call system("chmod go= ".s:configfile)
endif
elseif has_key(authorization, 'message')
echohl WarningMsg
echo authorization.message
echohl None
let secret = ''
endif
else
let secret = ''
endif
return secret
endfunction
let s:extmap = {
\".adb": "ada",
\".ahk": "ahk",
\".arc": "arc",
\".as": "actionscript",
\".asm": "asm",
\".asp": "asp",
\".aw": "php",
\".b": "b",
\".bat": "bat",
\".befunge": "befunge",
\".bmx": "bmx",
\".boo": "boo",
\".c-objdump": "c-objdump",
\".c": "c",
\".cfg": "cfg",
\".cfm": "cfm",
\".ck": "ck",
\".cl": "cl",
\".clj": "clj",
\".cmake": "cmake",
\".coffee": "coffee",
\".cpp": "cpp",
\".cppobjdump": "cppobjdump",
\".cs": "csharp",
\".css": "css",
\".cw": "cw",
\".d-objdump": "d-objdump",
\".d": "d",
\".darcspatch": "darcspatch",
\".diff": "diff",
\".duby": "duby",
\".dylan": "dylan",
\".e": "e",
\".ebuild": "ebuild",
\".eclass": "eclass",
\".el": "lisp",
\".erb": "erb",
\".erl": "erlang",
\".f90": "f90",
\".factor": "factor",
\".feature": "feature",
\".fs": "fs",
\".fy": "fy",
\".go": "go",
\".groovy": "groovy",
\".gs": "gs",
\".gsp": "gsp",
\".haml": "haml",
\".hs": "haskell",
\".html": "html",
\".hx": "hx",
\".ik": "ik",
\".ino": "ino",
\".io": "io",
\".j": "j",
\".java": "java",
\".js": "javascript",
\".json": "json",
\".jsp": "jsp",
\".kid": "kid",
\".lhs": "lhs",
\".lisp": "lisp",
\".ll": "ll",
\".lua": "lua",
\".ly": "ly",
\".m": "objc",
\".mak": "mak",
\".man": "man",
\".mao": "mao",
\".matlab": "matlab",
\".md": "markdown",
\".minid": "minid",
\".ml": "ml",
\".moo": "moo",
\".mu": "mu",
\".mustache": "mustache",
\".mxt": "mxt",
\".myt": "myt",
\".n": "n",
\".nim": "nim",
\".nu": "nu",
\".numpy": "numpy",
\".objdump": "objdump",
\".ooc": "ooc",
\".parrot": "parrot",
\".pas": "pas",
\".pasm": "pasm",
\".pd": "pd",
\".phtml": "phtml",
\".pir": "pir",
\".pl": "perl",
\".po": "po",
\".py": "python",
\".pytb": "pytb",
\".pyx": "pyx",
\".r": "r",
\".raw": "raw",
\".rb": "ruby",
\".rhtml": "rhtml",
\".rkt": "rkt",
\".rs": "rs",
\".rst": "rst",
\".s": "s",
\".sass": "sass",
\".sc": "sc",
\".scala": "scala",
\".scm": "scheme",
\".scpt": "scpt",
\".scss": "scss",
\".self": "self",
\".sh": "sh",
\".sml": "sml",
\".sql": "sql",
\".st": "smalltalk",
\".tcl": "tcl",
\".tcsh": "tcsh",
\".tex": "tex",
\".textile": "textile",
\".tpl": "smarty",
\".twig": "twig",
\".txt" : "text",
\".v": "verilog",
\".vala": "vala",
\".vb": "vbnet",
\".vhd": "vhdl",
\".vim": "vim",
\".weechatlog": "weechatlog",
\".xml": "xml",
\".xq": "xquery",
\".xs": "xs",
\".yml": "yaml",
\}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et:

@ -1,251 +0,0 @@
*Gist.vim* Vimscript for creating gists (http://gist.github.com)
Usage |gist-vim-usage|
Tips |gist-vim-tips|
Requirements |gist-vim-requirements|
License |gist-vim-license|
Install |gist-vim-install|
Setup |gist-vim-setup|
This is a vimscript for creating gists (http://gist.github.com)
For the latest version please see https://github.com/mattn/gist-vim.
==============================================================================
USAGE *:Gist* *gist-vim-usage*
- Post current buffer to gist, using default privacy option. >
:Gist
<
- Post selected text to gist, using defualt privacy option.
This applies to all permutations listed below (except multi). >
:'<,'>Gist
<
- Create a private gist. >
:Gist -p
<
- Create a public gist.
(Only relevant if you've set gists to be private by default.) >
:Gist -P
<
- Post whole text to gist as public.
This is only relevant if you've set gists to be private by default.
>
:Gist -P
<
- Create a gist anonymously. >
:Gist -a
<
- Create a gist with all open buffers. >
:Gist -m
<
- Edit the gist (you need to have opened the gist buffer first).
You can update the gist with the {:w} command within the gist buffer. >
:Gist -e
<
- Edit the gist with name "foo.js" (you need to have opened the gist buffer
first). >
:Gist -e foo.js
<
- Post/Edit with the description " (you need to have opened the gist buffer
first). >
:Gist -s something
:Gist -e -s something
<
- Delete the gist (you need to have opened the gist buffer first).
Password authentication is needed. >
:Gist -d
<
- Fork the gist (you need to have opened the gist buffer first).
Password authentication is needed. >
:Gist -f
<
- Star the gist (you need to have opened the gist buffer first).
Password authentication is needed.
>
:Gist +1
<
- Unstar the gist (you need to have opened the gist buffer first).
Password authentication is needed.
>
:Gist -1
<
- Get gist XXXXX. >
:Gist XXXXX
<
- Get gist XXXXX and add to clipboard. >
:Gist -c XXXXX
<
- List your public gists. >
:Gist -l
<
- List gists from user "mattn". >
:Gist -l mattn
<
- List everyone's gists. >
:Gist -la
<
- List gists from your starred gists.
>
:Gist -ls
<
==============================================================================
TIPS *gist-vim-tips*
If you set "g:gist_clip_command", gist.vim will copy the gist code with option
"-c".
- Mac: >
let g:gist_clip_command = 'pbcopy'
<
- Linux: >
let g:gist_clip_command = 'xclip -selection clipboard'
<
- Others (cygwin?): >
let g:gist_clip_command = 'putclip'
<
If you want to detect filetype from the filename: >
let g:gist_detect_filetype = 1
<
If you want to open the browser after the post: >
let g:gist_open_browser_after_post = 1
<
If you want to change the browser: >
let g:gist_browser_command = 'w3m %URL%'
<
or: >
let g:gist_browser_command = 'opera %URL% &'
<
On windows, this should work with your user settings.
If you want to show your private gists with ":Gist -l": >
let g:gist_show_privates = 1
<
If you want to edit all files for gists containing more than one: >
let g:gist_get_multiplefile = 1
<
If you want to update a gist, embed >
GistID: xxxxx
>
in your local file, then call >
:Gist
>
==============================================================================
REQUIREMENTS *gist-vim-requirements*
- curl command (http://curl.haxx.se/)
- webapi-vim (https://github.com/mattn/webapi-vim)
- and, if you want to use your git profile, the git command-line client.
==============================================================================
LICENSE *gist-vim-license*
Copyright 2010 by Yasuhiro Matsumoto
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
==============================================================================
INSTALL *gist-vim-install*
Copy gist.vim to your plugin directory.
gist.vim will create a curl cookie-jar file in your runtimepath.
rtp:
- plugin/gist.vim
- cookies/github
If you want to uninstall gist.vim, remember to also remove "cookies/github".
==============================================================================
SETUP *gist-vim-setup*
This plugin uses github API v3. Setting value is stored in `~/.gist.vim`.
gist-vim have two ways to access APIs.
First, you need to set your Github username in global git config:
>
$ git config --global github.user Username
<
Then, gist.vim will ask for your password to create an authorization when you
first use it. The password is not stored and only the OAuth access token will
be kept for later use. You can revoke the token at any time from the list of
"Authorized applications" on Github's "Account Settings" page.
(https://github.com/settings/applications)
If you happen to have your password already written in ~/.gitconfig like
below:
>
[github]
password = xxxxx
<
Then, add following into your ~/.vimrc
>
let g:gist_use_password_in_gitconfig = 1
<
This is not secure at all, so strongly discouraged.
==============================================================================
THANKS *gist-vim-thanks*
AD7six
Bruno Bigras
c9s
Daniel Bretoi
Jeremy Michael Cantrell
Kien N
kongo2002
MATSUU Takuto
Matthew Weier O'Phinney
ornicar
Roland Schilter
steve
tyru
Will Gray
netj
vim:tw=78:ts=8:ft=help:norl:

@ -1,9 +0,0 @@
:Gist gist-vim.txt /*:Gist*
Gist.vim gist-vim.txt /*Gist.vim*
gist-vim-install gist-vim.txt /*gist-vim-install*
gist-vim-license gist-vim.txt /*gist-vim-license*
gist-vim-requirements gist-vim.txt /*gist-vim-requirements*
gist-vim-setup gist-vim.txt /*gist-vim-setup*
gist-vim-thanks gist-vim.txt /*gist-vim-thanks*
gist-vim-tips gist-vim.txt /*gist-vim-tips*
gist-vim-usage gist-vim.txt /*gist-vim-usage*

@ -1,26 +0,0 @@
"=============================================================================
" File: gist.vim
" Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
" WebPage: http://github.com/mattn/gist-vim
" License: BSD
" GetLatestVimScripts: 2423 1 :AutoInstall: gist.vim
" script type: plugin
if &cp || (exists('g:loaded_gist_vim') && g:loaded_gist_vim)
finish
endif
let g:loaded_gist_vim = 1
if !exists('g:github_user') && !executable('git')
echohl ErrorMsg | echomsg "Gist: require 'git' command" | echohl None
finish
endif
if !executable('curl')
echohl ErrorMsg | echomsg "Gist: require 'curl' command" | echohl None
finish
endif
command! -nargs=? -range=% Gist :call gist#Gist(<count>, <line1>, <line2>, <f-args>)
" vim:set et:

@ -1,16 +0,0 @@
post.pl
vim_passfile
doc/tags
.*.un~
.*.sw*
# ignore csv files for tests
*.csv
# ignore vimballs
*.vba
*.vmb
# ignore *.orig files
*.orig
*.*~
# various testfiles
file*.*
testfile*

@ -1,41 +0,0 @@
SCRIPT=ftplugin/csv.vim
DOC=doc/ft-csv.txt
PLUGIN=csv
VERSION=$(shell sed -n '/Version:/{s/^.*\(\S\.\S\+\)$$/\1/;p}' $(SCRIPT))
.PHONY : csv.vmb csv
all: vimball
release: $(PLUGIN) $(PLUGIN).vmb
clean:
find . -type f \( -name "*.vba" -o -name "*.vmb" -o -name "*.orig" \
-o -name "*.~*" -o -name ".VimballRecord" -o -name ".*.un~" \
-o -name "*.sw*" -o -name tags \) -delete
dist-clean: clean
vimball: $(PLUGIN).vmb install
install:
vim -N -c 'ru! vimballPlugin.vim' -c':so %' -c':q!' ${PLUGIN}.vmb
uninstall:
vim -N -c 'ru! vimballPlugin.vim' -c':RmVimball ${PLUGIN}.vmb'
undo:
for i in */*.orig; do mv -f "$$i" "$${i%.*}"; done
csv.vmb:
vim -N -c 'ru! vimballPlugin.vim' -c ':let g:vimball_home=getcwd()' -c ':call append("0", ["ftplugin/csv.vim", "doc/ft-csv.txt", "syntax/csv.vim", "ftdetect/csv.vim", "plugin/csv.vim"])' -c '$$d' -c ':%MkVimball! ${PLUGIN}' -c':q!'
ln -f $(PLUGIN).vmb $(PLUGIN)-$(VERSION).vmb
csv:
rm -f ${PLUGIN}.vmb
perl -i.orig -pne 'if (/Version:/) {s/\.(\d+)*/sprintf(".%d", 1+$$1)/e}' ${SCRIPT}
perl -i -pne 'if (/GetLatestVimScripts:/) {s/(\d+)\s+:AutoInstall:/sprintf("%d :AutoInstall:", 1+$$1)/e}' ${SCRIPT}
perl -i -pne 'if (/Last Change:/) {s/(:\s+).*\n$$/sprintf(": %s", `date -R`)/e}' ${SCRIPT}
perl -i -pne 'if (/Last Change:/) {s/(:\s+).*\n$$/sprintf(": %s", `LC_TIME=C date +"%a, %d %b %Y"`)/e}' ${DOC}
perl -i.orig -pne 'if (/Version:/) {s/\.(\d+).*/sprintf(".%d", 1+$$1)/e}' ${DOC}
cp -f $(DOC) README

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,3 +0,0 @@
" Install Filetype detection for CSV files
au BufRead,BufNewFile *.csv,*.dat,*.tsv,*.tab set filetype=csv

File diff suppressed because it is too large Load Diff

@ -1,79 +0,0 @@
if exists('g:loaded_csv') && g:loaded_csv
finish
endif
let g:loaded_csv = 1
let s:cpo_save = &cpo
set cpo&vim
if exists("g:csv_autocmd_arrange") &&
\ !exists("#CSV_Edit#BufReadPost")
aug CSV_Editing
au!
au BufReadPost,BufWritePost *.csv,*.dat,*.tsv,*.tab :ru! ftplugin/csv.vim | exe ":sil! InitCSV" | exe ":sil! %ArrangeCol" | setl noro
au BufWritePre *.csv,*.dat,*.tsv,*.tab :%UnArrangeCol
aug end
elseif exists("#CSV_Edit#BufReadPost")
aug CSV_Edit
au!
aug end
aug! CSV_Edit
endif
com! -range -bang CSVTable call <sid>Table(<bang>0, <line1>, <line2>)
fu! <sid>Table(bang, line1, line2)
" save and restore some options
if has("conceal")
let _a = [ &l:lz, &l:syntax, &l:ft, &l:sol, &l:tw, &l:wrap, &l:cole, &l:cocu, &l:fen, &l:fdm, &l:fdl, &l:fdc, &l:fml, &l:fdt, &l:ma, &l:ml]
else
let _a = [ &l:lz, &l:syntax, &l:ft, &l:sol, &l:tw, &l:wrap, &l:fen, &l:fdm, &l:fdl, &l:fdc, &l:fml, &l:fdt, &l:ma, &l:ml]
endif
let _b = winsaveview()
let line1 = a:line1
let line2 = a:line2
if line1 == line2
" use the current paragraph
let line1 = line("'{") + 1
let line2 = line("'}") - 1
endif
" try to guess the delimiter from the specified region, therefore, we need
" to initialize the plugin to inspect only those lines
let [ b:csv_start, b:csv_end ] = [ line1, line2 ]
" Reset b:did_ftplugin just to be sure
unlet! b:did_ftplugin
setl noml ft=csv lz ma
" get indent
let indent = matchstr(getline(a:line1), '^\s\+')
exe printf(':sil %d,%ds/^\s\+//e', line1, line2)
let last = line('$')
try
let b:csv_list=getline(line1, line2)
call filter(b:csv_list, '!empty(v:val)')
call map(b:csv_list, 'split(v:val, b:col.''\zs'')')
if exists(":CSVTabularize")
exe printf("%d,%dCSVTabularize%s", line1, line2, empty(a:bang) ? '' : '!')
else
echoerr "Not possible to call :CSVTabularize"
endif
unlet! b:col_width b:csv_list
catch
finally
if !empty(indent)
" Added one line above a:line1 and several lines below, so need to
" correct the range
exe printf(':sil %d,%ds/^/%s/e', (line1 - 1), (line2 + line('$') - last), indent)
endif
if has("conceal")
let [ &l:lz, &l:syntax, &l:ft, &l:sol, &l:tw, &l:wrap, &l:cole, &l:cocu, &l:fen, &l:fdm, &l:fdl, &l:fdc, &l:fml, &l:fdt, &l:ma, &l:ml] = _a
else
let [ &l:lz, &l:syntax, &l:ft, &l:sol, &l:tw, &l:wrap, &l:fen, &l:fdm, &l:fdl, &l:fdc, &l:fml, &l:fdt, &l:ma, &l:ml] = _a
endif
call winrestview(_b)
endtry
endfu
let &cpo = s:cpo_save
unlet s:cpo_save

@ -1,188 +0,0 @@
" A simple syntax highlighting, simply alternate colors between two
" adjacent columns
" Init {{{2
let s:cpo_save = &cpo
set cpo&vim
scriptencoding utf8
if version < 600
syn clear
elseif exists("b:current_syntax")
finish
endif
" Helper functions "{{{2
fu! <sid>Warning(msg) "{{{3
" Don't redraw, so we are not overwriting messages from the ftplugin
" script
"redraw!
echohl WarningMsg
echomsg "CSV Syntax:" . a:msg
echohl Normal
endfu
fu! <sid>Esc(val, char) "{{2
return '\V'.escape(a:val, '\\'.a:char).'\m'
endfu
fu! <sid>CheckSaneSearchPattern() "{{{3
let s:del_def = ','
let s:col_def = '\%([^' . s:del_def . ']*' . s:del_def . '\|$\)'
let s:col_def_end = '\%([^' . s:del_def . ']*' . s:del_def . '\)'
" First:
" Check for filetype plugin. This syntax script relies on the filetype
" plugin, else, it won't work properly.
redir => s:a |sil filetype | redir end
let s:a=split(s:a, "\n")[0]
if match(s:a, '\cplugin:off') > 0
call <sid>Warning("No filetype support, only simple highlighting using"
\ . s:del_def . " as delimiter! See :h csv-installation")
endif
" Check Comment setting
if !exists("g:csv_comment")
let b:csv_cmt = split(&cms, '%s')
else
let b:csv_cmt = split(g:csv_comment, '%s')
endif
" Second: Check for sane defaults for the column pattern
" Not necessary to check for fixed width columns
if exists("b:csv_fixed_width_cols")
return
endif
" Try a simple highlighting, if the defaults from the ftplugin
" don't exist
let s:col = exists("b:col") && !empty(b:col) ? b:col
\ : s:col_def
let s:col_end = exists("b:col_end") && !empty(b:col_end) ? b:col_end
\ : s:col_def_end
let s:del = exists("b:delimiter") && !empty(b:delimiter) ? b:delimiter
\ : s:del_def
let s:cmts = exists("b:csv_cmt") ? b:csv_cmt[0] : split(&cms, '&s')[0]
let s:cmte = exists("b:csv_cmt") && len(b:csv_cmt) == 2 ? b:csv_cmt[1]
\ : ''
if line('$') > 1 && (!exists("b:col") || empty(b:col))
" check for invalid pattern, ftplugin hasn't been loaded yet
call <sid>Warning("Invalid column pattern, using default pattern " . s:col_def)
endif
endfu
" Syntax rules {{{2
fu! <sid>DoHighlight() "{{{3
if has("conceal") && !exists("g:csv_no_conceal") &&
\ !exists("b:csv_fixed_width_cols")
" old val
"\ '\%(.\)\@=/ms=e,me=e contained conceal cchar=' .
" Has a problem with the last line!
exe "syn match CSVDelimiter /" . s:col_end .
\ '/ms=e,me=e contained conceal cchar=' .
\ (&enc == "utf-8" ? "│" : '|')
"exe "syn match CSVDelimiterEOL /" . s:del .
" \ '\?$/ contained conceal cchar=' .
" \ (&enc == "utf-8" ? "│" : '|')
hi def link CSVDelimiter Conceal
elseif !exists("b:csv_fixed_width_cols")
" The \%(.\)\@<= makes sure, the last char won't be concealed,
" if it isn't a delimiter
"exe "syn match CSVDelimiter /" . s:col . '\%(.\)\@<=/ms=e,me=e contained'
exe "syn match CSVDelimiter /" . s:col_end . '/ms=e,me=e contained'
"exe "syn match CSVDelimiterEOL /" . s:del . '\?$/ contained'
if has("conceal")
hi def link CSVDelimiter Conceal
else
hi def link CSVDelimiter Ignore
endif
endif " There is no delimiter for csv fixed width columns
if !exists("b:csv_fixed_width_cols")
exe 'syn match CSVColumnEven nextgroup=CSVColumnOdd /'
\ . s:col . '/ contains=CSVDelimiter'
exe 'syn match CSVColumnOdd nextgroup=CSVColumnEven /'
\ . s:col . '/ contains=CSVDelimiter'
exe 'syn match CSVColumnHeaderEven nextgroup=CSVColumnHeaderOdd /\%1l'
\. s:col . '/ contains=CSVDelimiter'
exe 'syn match CSVColumnHeaderOdd nextgroup=CSVColumnHeaderEven /\%1l'
\. s:col . '/ contains=CSVDelimiter'
else
for i in range(len(b:csv_fixed_width_cols))
let pat = '/\%' . b:csv_fixed_width_cols[i] . 'c.*' .
\ ((i == len(b:csv_fixed_width_cols)-1) ? '/' :
\ '\%' . b:csv_fixed_width_cols[i+1] . 'c/')
let group = "CSVColumn" . (i%2 ? "Odd" : "Even" )
let ngroup = "CSVColumn" . (i%2 ? "Even" : "Odd" )
exe "syn match " group pat " nextgroup=" . ngroup
endfor
endif
" Comment regions
exe 'syn match CSVComment /'. <sid>Esc(s:cmts, '/'). '.*'.
\ (!empty(s:cmte) ? '\%('. <sid>Esc(s:cmte, '/'). '\)\?'
\: ''). '/'
hi def link CSVComment Comment
endfun
fu! <sid>DoSyntaxDefinitions() "{{{3
syn spell toplevel
" Not really needed
syn case ignore
hi def link CSVColumnHeaderOdd WarningMsg
hi def link CSVColumnHeaderEven WarningMsg
hi def link CSVColumnOdd DiffAdd
hi def link CSVColumnEven DiffChange
" Old Version
if 0
if &t_Co < 88
if !exists("b:csv_fixed_width_cols")
hi default CSVColumnHeaderOdd ctermfg=DarkRed ctermbg=15
\ guibg=grey80 guifg=black term=underline cterm=standout,bold
\ gui=bold,underline
endif
hi default CSVColumnOdd ctermfg=DarkRed ctermbg=15 guibg=grey80
\ guifg=black term=underline cterm=bold gui=underline
else
if !exists("b:csv_fixed_width_cols")
hi default CSVColumnHeaderOdd ctermfg=darkblue ctermbg=white
\ guibg=grey80 guifg=black cterm=standout,underline
\ gui=bold,underline
endif
hi default CSVColumnOdd ctermfg=darkblue ctermbg=white guibg=grey80
\ guifg=black cterm=reverse,underline gui=underline
endif
" ctermbg=8 should be safe, even in 8 color terms
if !exists("b:csv_fixed_width_cols")
hi default CSVColumnHeaderEven ctermfg=white ctermbg=darkgrey
\ guibg=grey50 guifg=black term=bold cterm=standout,underline
\ gui=bold,underline
endif
hi default CSVColumnEven ctermfg=white ctermbg=darkgrey guibg=grey50
\ guifg=black term=bold cterm=underline gui=bold,underline
endif
endfun
" Main: {{{2
" Make sure, we are using a sane, valid pattern for syntax
" highlighting
call <sid>CheckSaneSearchPattern()
" Define all necessary syntax groups
call <sid>DoSyntaxDefinitions()
" Highlight the file
call <sid>DoHighlight()
" Set the syntax variable {{{2
let b:current_syntax="csv"
let &cpo = s:cpo_save
unlet s:cpo_save

@ -1,76 +0,0 @@
## Open items ##
----------------
- when using :VHeader, comments are not copied over
- wrap/shorten long fields (scopus.csv). Is this even possible with Vim?
(maybe conceal trailing and leading whitespace?)
This should work:
1) set a max width per column
2) for each column issue something like this:
:exe 'syn match CSVConcealed /\%'.line.'l\%>'.width. 'c.*/ conceal cchar=…'
- Allow to set only a range of the file to filetype csv
(helps when writing text and one wants to insert some csv data)
- Add more scripting functions? (which ones?)
- Better support for newlines within a column (Is this worth the
effort?)
- add vertical folding (concealing columns)
(works partly, can't conceal single columns?)
- make plugin autoloadable (shouldn't be necessary, as the code is only
loaded for file with &ft=csv)
## Fixed items ##
-----------------
- Better syntax highlighting (last char in last line is concealed)
- Convert to a visual table, something like this:
a,header,line
foo,bar,10
baz,bum,5
:VisualTable results in:
-------------------
|a |header| line|
-----|------|-----|
|foo |bar | 10|
|baz |bum | 5|
-------------------
(works using :Tabularize command)
- Header/VHeader command should be more robust. May be use the preview
window to display the header? Does scrollbinding then still work?
(should work now)
- Transposing columns (should work now)
- add a wizard, for defining fixed-width columns
(should work now)
- Reapply Filter, in case Search register changed
(use :Filters!, should work now)
- Sum should account for different number formats
(e.g. 10 000.01 should be counted as 10,000.01 in Australia,
10.000 should be counted as 10,000 in Germany.
How can the user configure how to handle certain delimiters?
:SumCol 3 /.:,/ should use the ',' as decimal separator?
:SumCol 3 /,: / should use the ' ' as thousands separator?
:SumCol 3 /,: / /.:,/ treats ' ' as thousands separator and
, as decimal separator?
(should work now)
- When filtering, move all folded values together, so your file needs to
be reorded (and changed), but will leave all non-folded items
together. Make this configurable and only possible, when the file is
!read-only and modifiable)
(should work now)
- apply Filter negatively, e.g. pressing enter on a value, hides all
values, that don't have this value. (Maybe use <Space>, on the value?)
(should work now)
- document how to "substitute in column" command, may be even provide a
command for that?
- new command: AddColumn adds an empty column after cursor or after
specified column number (possibly followed by number of columns to
add)
vim:tw=72

@ -1,16 +0,0 @@
This is a mirror of http://www.vim.org/scripts/script.php?script_id=39
The matchit.vim script allows you to configure % to match more than just
single characters. You can match words and even regular expressions.
Also, matching treats strings and comments (as recognized by the
syntax highlighting mechanism) intelligently.
The default ftplugins include settings for several languages:
Ada, ASP with VBS, Csh, DTD, Essbase, Fortran, HTML, JSP
(same as HTML), LaTeX, Lua, Pascal, SGML, Shell, Tcsh, Vim, XML.
(I no longer keep track, so there may be others.)
The documentation (included in the zip file) explains how to configure
the script for a new language and how to modify the defaults.
Since vim 6.0, matchit.vim has been included in the standard vim distribution,
under the macros/ directory; the version here may be more recent.

@ -1,406 +0,0 @@
*matchit.txt* Extended "%" matching
For instructions on installing this file, type
:help matchit-install
inside Vim.
For Vim version 6.3. Last change: 2007 Aug 29
VIM REFERENCE MANUAL by Benji Fisher
*matchit* *matchit.vim*
1. Extended matching with "%" |matchit-intro|
2. Activation |matchit-activate|
3. Configuration |matchit-configure|
4. Supporting a New Language |matchit-newlang|
5. Known Bugs and Limitations |matchit-bugs|
The functionality mentioned here is a plugin, see |add-plugin|.
This plugin is only available if 'compatible' is not set.
You can avoid loading this plugin by setting the "loaded_matchit" variable
in your |vimrc| file: >
:let loaded_matchit = 1
{Vi does not have any of this}
==============================================================================
1. Extended matching with "%" *matchit-intro*
*matchit-%*
% Cycle forward through matching groups, such as "if", "else", "endif",
as specified by |b:match_words|.
*g%* *v_g%* *o_g%*
g% Cycle backwards through matching groups, as specified by
|b:match_words|. For example, go from "if" to "endif" to "else".
*[%* *v_[%* *o_[%*
[% Go to [count] previous unmatched group, as specified by
|b:match_words|. Similar to |[{|.
*]%* *v_]%* *o_]%*
]% Go to [count] next unmatched group, as specified by
|b:match_words|. Similar to |]}|.
*v_a%*
a% In Visual mode, select the matching group, as specified by
|b:match_words|, containing the cursor. Similar to |v_a[|.
A [count] is ignored, and only the first character of the closing
pattern is selected.
In Vim, as in plain vi, the percent key, |%|, jumps the cursor from a brace,
bracket, or paren to its match. This can be configured with the 'matchpairs'
option. The matchit plugin extends this in several ways:
You can match whole words, such as "if" and "endif", not just
single characters. You can also specify a |regular-expression|.
You can define groups with more than two words, such as "if",
"else", "endif". Banging on the "%" key will cycle from the "if" to
the first "else", the next "else", ..., the closing "endif", and back
to the opening "if". Nested structures are skipped. Using |g%| goes
in the reverse direction.
By default, words inside comments and strings are ignored, unless
the cursor is inside a comment or string when you type "%". If the
only thing you want to do is modify the behavior of "%" so that it
behaves this way, you do not have to define |b:match_words|, since the
script uses the 'matchpairs' option as well as this variable.
See |matchit-details| for details on what the script does, and |b:match_words|
for how to specify matching patterns.
MODES: *matchit-modes* *matchit-v_%* *matchit-o_%*
Mostly, % and related motions (|g%| and |[%| and |]%|) work just like built-in
|motion| commands in |Operator-pending| and |Visual| modes. However, you
cannot make these motions |linewise| or |characterwise|, since the |:omap|s
that define them start with "v" in order to make the default behavior
inclusive. (See |o_v|.) In other words, "dV%" will not work. The
work-around is to go through Visual mode: "V%d" will work.
LANGUAGES: *matchit-languages*
Currently, the following languages are supported: Ada, ASP with VBS, Csh,
DTD, Entity, Essbase, Fortran, HTML, JSP (same as HTML), LaTeX, Lua, Pascal,
SGML, Shell, Tcsh, Vim, XML. Other languages may already have support via
the default |filetype-plugin|s in the standard vim distribution.
To support a new language, see |matchit-newlang| below.
DETAILS: *matchit-details* *matchit-parse*
Here is an outline of what matchit.vim does each time you hit the "%" key. If
there are |backref|s in |b:match_words| then the first step is to produce a
version in which these back references have been eliminated; if there are no
|backref|s then this step is skipped. This step is called parsing. For
example, "\(foo\|bar\):end\1" is parsed to yield
"\(foo\|bar\):end\(foo\|bar\)". This can get tricky, especially if there are
nested groups. If debugging is turned on, the parsed version is saved as
|b:match_pat|.
*matchit-choose*
Next, the script looks for a word on the current line that matches the pattern
just constructed. It includes the patterns from the 'matchpairs' option.
The goal is to do what you expect, which turns out to be a little complicated.
The script follows these rules:
Insist on a match that ends on or after the cursor.
Prefer a match that includes the cursor position (that is, one that
starts on or before the cursor).
Prefer a match that starts as close to the cursor as possible.
If more than one pattern in |b:match_words| matches, choose the one
that is listed first.
Examples:
Suppose you >
:let b:match_words = '<:>,<tag>:</tag>'
< and hit "%" with the cursor on or before the "<" in "a <tag> is born".
The pattern '<' comes first, so it is preferred over '<tag>', which
also matches. If the cursor is on the "t", however, then '<tag>' is
preferred, because this matches a bit of text containing the cursor.
If the two groups of patterns were reversed then '<' would never be
preferred.
Suppose you >
:let b:match_words = 'if:end if'
< (Note the space!) and hit "%" with the cursor at the end of "end if".
Then "if" matches, which is probably not what you want, but if the
cursor starts on the "end " then "end if" is chosen. (You can avoid
this problem by using a more complicated pattern.)
If there is no match, the cursor does not move. (Before version 1.13 of the
script, it would fall back on the usual behavior of |%|). If debugging is
turned on, the matched bit of text is saved as |b:match_match| and the cursor
column of the start of the match is saved as |b:match_col|.
Next, the script looks through |b:match_words| (original and parsed versions)
for the group and pattern that match. If debugging is turned on, the group is
saved as |b:match_ini| (the first pattern) and |b:match_tail| (the rest). If
there are |backref|s then, in addition, the matching pattern is saved as
|b:match_word| and a table of translations is saved as |b:match_table|. If
there are |backref|s, these are determined from the matching pattern and
|b:match_match| and substituted into each pattern in the matching group.
The script decides whether to search forwards or backwards and chooses
arguments for the |searchpair()| function. Then, the cursor is moved to the
start of the match, and |searchpair()| is called. By default, matching
structures inside strings and comments are ignored. This can be changed by
setting |b:match_skip|.
==============================================================================
2. Activation *matchit-activate*
You can use this script as a plugin, by copying it to your plugin directory.
See |add-global-plugin| for instructions. You can also add a line to your
|vimrc| file, such as >
:source $VIMRUNTIME/macros/matchit.vim
or >
:runtime macros/matchit.vim
Either way, the script should start working the next time you start up Vim.
(Earlier versions of the script did nothing unless a |buffer-variable| named
|b:match_words| was defined. Even earlier versions contained autocommands
that set this variable for various file types. Now, |b:match_words| is
defined in many of the default |filetype-plugin|s instead.)
For a new language, you can add autocommands to the script or to your vimrc
file, but the recommended method is to add a line such as >
let b:match_words = '\<foo\>:\<bar\>'
to the |filetype-plugin| for your language. See |b:match_words| below for how
this variable is interpreted.
TROUBLESHOOTING *matchit-troubleshoot*
The script should work in most installations of Vim. It may not work if Vim
was compiled with a minimal feature set, for example if the |+syntax| option
was not enabled. If your Vim has support for syntax compiled in, but you do
not have |syntax| highlighting turned on, matchit.vim should work, but it may
fail to skip matching groups in comments and strings. If the |filetype|
mechanism is turned off, the |b:match_words| variable will probably not be
defined automatically.
==============================================================================
3. Configuration *matchit-configure*
There are several variables that govern the behavior of matchit.vim. Note
that these are variables local to the buffer, not options, so use |:let| to
define them, not |:set|. Some of these variables have values that matter; for
others, it only matters whether the variable has been defined. All of these
can be defined in the |filetype-plugin| or autocommand that defines
|b:match_words| or "on the fly."
The main variable is |b:match_words|. It is described in the section below on
supporting a new language.
*MatchError* *matchit-hl* *matchit-highlight*
MatchError is the highlight group for error messages from the script. By
default, it is linked to WarningMsg. If you do not want to be bothered by
error messages, you can define this to be something invisible. For example,
if you use the GUI version of Vim and your command line is normally white, you
can do >
:hi MatchError guifg=white guibg=white
<
*b:match_ignorecase*
If you >
:let b:match_ignorecase = 1
then matchit.vim acts as if 'ignorecase' is set: for example, "end" and "END"
are equivalent. If you >
:let b:match_ignorecase = 0
then matchit.vim treats "end" and "END" differently. (There will be no
b:match_infercase option unless someone requests it.)
*b:match_debug*
Define b:match_debug if you want debugging information to be saved. See
|matchit-debug|, below.
*b:match_skip*
If b:match_skip is defined, it is passed as the skip argument to
|searchpair()|. This controls when matching structures are skipped, or
ignored. By default, they are ignored inside comments and strings, as
determined by the |syntax| mechanism. (If syntax highlighting is turned off,
nothing is skipped.) You can set b:match_skip to a string, which evaluates to
a non-zero, numerical value if the match is to be skipped or zero if the match
should not be skipped. In addition, the following special values are
supported by matchit.vim:
s:foo becomes (current syntax item) =~ foo
S:foo becomes (current syntax item) !~ foo
r:foo becomes (line before cursor) =~ foo
R:foo becomes (line before cursor) !~ foo
(The "s" is meant to suggest "syntax", and the "r" is meant to suggest
"regular expression".)
Examples:
You can get the default behavior with >
:let b:match_skip = 's:comment\|string'
<
If you want to skip matching structures unless they are at the start
of the line (ignoring whitespace) then you can >
:let b:match_skip = 'R:^\s*'
< Do not do this if strings or comments can span several lines, since
the normal syntax checking will not be done if you set b:match_skip.
In LaTeX, since "%" is used as the comment character, you can >
:let b:match_skip = 'r:%'
< Unfortunately, this will skip anything after "\%", an escaped "%". To
allow for this, and also "\\%" (an excaped backslash followed by the
comment character) you can >
:let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%'
<
See the $VIMRUNTIME/ftplugin/vim.vim for an example that uses both
syntax and a regular expression.
==============================================================================
4. Supporting a New Language *matchit-newlang*
*b:match_words*
In order for matchit.vim to support a new language, you must define a suitable
pattern for |b:match_words|. You may also want to set some of the
|matchit-configure| variables, as described above. If your language has a
complicated syntax, or many keywords, you will need to know something about
Vim's |regular-expression|s.
The format for |b:match_words| is similar to that of the 'matchpairs' option:
it is a comma (,)-separated list of groups; each group is a colon(:)-separated
list of patterns (regular expressions). Commas and backslashes that are part
of a pattern should be escaped with backslashes ('\:' and '\,'). It is OK to
have only one group; the effect is undefined if a group has only one pattern.
A simple example is >
:let b:match_words = '\<if\>:\<endif\>,'
\ . '\<while\>:\<continue\>:\<break\>:\<endwhile\>'
(In Vim regular expressions, |\<| and |\>| denote word boundaries. Thus "if"
matches the end of "endif" but "\<if\>" does not.) Then banging on the "%"
key will bounce the cursor between "if" and the matching "endif"; and from
"while" to any matching "continue" or "break", then to the matching "endwhile"
and back to the "while". It is almost always easier to use |literal-string|s
(single quotes) as above: '\<if\>' rather than "\\<if\\>" and so on.
Exception: If the ":" character does not appear in b:match_words, then it is
treated as an expression to be evaluated. For example, >
:let b:match_words = 'GetMatchWords()'
allows you to define a function. This can return a different string depending
on the current syntax, for example.
Once you have defined the appropriate value of |b:match_words|, you will
probably want to have this set automatically each time you edit the
appropriate file type. The recommended way to do this is by adding the
definition to a |filetype-plugin| file.
Tips: Be careful that your initial pattern does not match your final pattern.
See the example above for the use of word-boundary expressions. It is usually
better to use ".\{-}" (as many as necessary) instead of ".*" (as many as
possible). See |\{-|. For example, in the string "<tag>label</tag>", "<.*>"
matches the whole string whereas "<.\{-}>" and "<[^>]*>" match "<tag>" and
"</tag>".
*matchit-spaces* *matchit-s:notend*
If "if" is to be paired with "end if" (Note the space!) then word boundaries
are not enough. Instead, define a regular expression s:notend that will match
anything but "end" and use it as follows: >
:let s:notend = '\%(\<end\s\+\)\@<!'
:let b:match_words = s:notend . '\<if\>:\<end\s\+if\>'
< *matchit-s:sol*
This is a simplified version of what is done for Ada. The s:notend is a
|script-variable|. Similarly, you may want to define a start-of-line regular
expression >
:let s:sol = '\%(^\|;\)\s*'
if keywords are only recognized after the start of a line or after a
semicolon (;), with optional white space.
*matchit-backref* *matchit-\1*
In any group, the expressions |\1|, |\2|, ..., |\9| refer to parts of the
INITIAL pattern enclosed in |\(|escaped parentheses|\)|. These are referred
to as back references, or backrefs. For example, >
:let b:match_words = '\<b\(o\+\)\>:\(h\)\1\>'
means that "bo" pairs with "ho" and "boo" pairs with "hoo" and so on. Note
that "\1" does not refer to the "\(h\)" in this example. If you have
"\(nested \(parentheses\)\) then "\d" refers to the d-th "\(" and everything
up to and including the matching "\)": in "\(nested\(parentheses\)\)", "\1"
refers to everything and "\2" refers to "\(parentheses\)". If you use a
variable such as |s:notend| or |s:sol| in the previous paragraph then remember
to count any "\(" patterns in this variable. You do not have to count groups
defined by |\%(\)|.
It should be possible to resolve back references from any pattern in the
group. For example, >
:let b:match_words = '\(foo\)\(bar\):more\1:and\2:end\1\2'
would not work because "\2" cannot be determined from "morefoo" and "\1"
cannot be determined from "andbar". On the other hand, >
:let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
should work (and have the same effect as "foobar:barfoo:endfoobar"), although
this has not been thoroughly tested.
You can use |zero-width| patterns such as |\@<=| and |\zs|. (The latter has
not been thouroughly tested in matchit.vim.) For example, if the keyword "if"
must occur at the start of the line, with optional white space, you might use
the pattern "\(^\s*\)\@<=if" so that the cursor will end on the "i" instead of
at the start of the line. For another example, if HTML had only one tag then
one could >
:let b:match_words = '<:>,<\@<=tag>:<\@<=/tag>'
so that "%" can bounce between matching "<" and ">" pairs or (starting on
"tag" or "/tag") between matching tags. Without the |\@<=|, the script would
bounce from "tag" to the "<" in "</tag>", and another "%" would not take you
back to where you started.
DEBUGGING *matchit-debug* *:MatchDebug*
If you are having trouble figuring out the appropriate definition of
|b:match_words| then you can take advantage of the same information I use when
debugging the script. This is especially true if you are not sure whether
your patterns or my script are at fault! To make this more convenient, I have
made the command :MatchDebug, which defines the variable |b:match_debug| and
creates a Matchit menu. This menu makes it convenient to check the values of
the variables described below. You will probably also want to read
|matchit-details| above.
Defining the variable |b:match_debug| causes the script to set the following
variables, each time you hit the "%" key. Several of these are only defined
if |b:match_words| includes |backref|s.
*b:match_pat*
The b:match_pat variable is set to |b:match_words| with |backref|s parsed.
*b:match_match*
The b:match_match variable is set to the bit of text that is recognized as a
match.
*b:match_col*
The b:match_col variable is set to the cursor column of the start of the
matching text.
*b:match_wholeBR*
The b:match_wholeBR variable is set to the comma-separated group of patterns
that matches, with |backref|s unparsed.
*b:match_iniBR*
The b:match_iniBR variable is set to the first pattern in |b:match_wholeBR|.
*b:match_ini*
The b:match_ini variable is set to the first pattern in |b:match_wholeBR|,
with |backref|s resolved from |b:match_match|.
*b:match_tail*
The b:match_tail variable is set to the remaining patterns in
|b:match_wholeBR|, with |backref|s resolved from |b:match_match|.
*b:match_word*
The b:match_word variable is set to the pattern from |b:match_wholeBR| that
matches |b:match_match|.
*b:match_table*
The back reference '\'.d refers to the same thing as '\'.b:match_table[d] in
|b:match_word|.
==============================================================================
5. Known Bugs and Limitations *matchit-bugs*
Just because I know about a bug does not mean that it is on my todo list. I
try to respond to reports of bugs that cause real problems. If it does not
cause serious problems, or if there is a work-around, a bug may sit there for
a while. Moral: if a bug (known or not) bothers you, let me know.
The various |:vmap|s defined in the script (%, |g%|, |[%|, |]%|, |a%|) may
have undesired effects in Select mode |Select-mode-mapping|. At least, if you
want to replace the selection with any character in "ag%[]" there will be a
pause of |'updatetime'| first.
It would be nice if "\0" were recognized as the entire pattern. That is, it
would be nice if "foo:\end\0" had the same effect as "\(foo\):\end\1". I may
try to implement this in a future version. (This is not so easy to arrange as
you might think!)
==============================================================================
vim:tw=78:fo=tcq2:

@ -1,50 +0,0 @@
:MatchDebug matchit.txt /*:MatchDebug*
MatchError matchit.txt /*MatchError*
[% matchit.txt /*[%*
]% matchit.txt /*]%*
b:match_col matchit.txt /*b:match_col*
b:match_debug matchit.txt /*b:match_debug*
b:match_ignorecase matchit.txt /*b:match_ignorecase*
b:match_ini matchit.txt /*b:match_ini*
b:match_iniBR matchit.txt /*b:match_iniBR*
b:match_match matchit.txt /*b:match_match*
b:match_pat matchit.txt /*b:match_pat*
b:match_skip matchit.txt /*b:match_skip*
b:match_table matchit.txt /*b:match_table*
b:match_tail matchit.txt /*b:match_tail*
b:match_wholeBR matchit.txt /*b:match_wholeBR*
b:match_word matchit.txt /*b:match_word*
b:match_words matchit.txt /*b:match_words*
g% matchit.txt /*g%*
matchit matchit.txt /*matchit*
matchit-% matchit.txt /*matchit-%*
matchit-\1 matchit.txt /*matchit-\\1*
matchit-activate matchit.txt /*matchit-activate*
matchit-backref matchit.txt /*matchit-backref*
matchit-bugs matchit.txt /*matchit-bugs*
matchit-choose matchit.txt /*matchit-choose*
matchit-configure matchit.txt /*matchit-configure*
matchit-debug matchit.txt /*matchit-debug*
matchit-details matchit.txt /*matchit-details*
matchit-highlight matchit.txt /*matchit-highlight*
matchit-hl matchit.txt /*matchit-hl*
matchit-intro matchit.txt /*matchit-intro*
matchit-languages matchit.txt /*matchit-languages*
matchit-modes matchit.txt /*matchit-modes*
matchit-newlang matchit.txt /*matchit-newlang*
matchit-o_% matchit.txt /*matchit-o_%*
matchit-parse matchit.txt /*matchit-parse*
matchit-s:notend matchit.txt /*matchit-s:notend*
matchit-s:sol matchit.txt /*matchit-s:sol*
matchit-spaces matchit.txt /*matchit-spaces*
matchit-troubleshoot matchit.txt /*matchit-troubleshoot*
matchit-v_% matchit.txt /*matchit-v_%*
matchit.txt matchit.txt /*matchit.txt*
matchit.vim matchit.txt /*matchit.vim*
o_[% matchit.txt /*o_[%*
o_]% matchit.txt /*o_]%*
o_g% matchit.txt /*o_g%*
v_[% matchit.txt /*v_[%*
v_]% matchit.txt /*v_]%*
v_a% matchit.txt /*v_a%*
v_g% matchit.txt /*v_g%*

@ -1,812 +0,0 @@
" matchit.vim: (global plugin) Extended "%" matching
" Last Change: Fri Jan 25 10:00 AM 2008 EST
" Maintainer: Benji Fisher PhD <benji@member.AMS.org>
" Version: 1.13.2, for Vim 6.3+
" URL: http://www.vim.org/script.php?script_id=39
" Documentation:
" The documentation is in a separate file, matchit.txt .
" Credits:
" Vim editor by Bram Moolenaar (Thanks, Bram!)
" Original script and design by Raul Segura Acevedo
" Support for comments by Douglas Potts
" Support for back references and other improvements by Benji Fisher
" Support for many languages by Johannes Zellner
" Suggestions for improvement, bug reports, and support for additional
" languages by Jordi-Albert Batalla, Neil Bird, Servatius Brandt, Mark
" Collett, Stephen Wall, Dany St-Amant, Yuheng Xie, and Johannes Zellner.
" Debugging:
" If you'd like to try the built-in debugging commands...
" :MatchDebug to activate debugging for the current buffer
" This saves the values of several key script variables as buffer-local
" variables. See the MatchDebug() function, below, for details.
" TODO: I should think about multi-line patterns for b:match_words.
" This would require an option: how many lines to scan (default 1).
" This would be useful for Python, maybe also for *ML.
" TODO: Maybe I should add a menu so that people will actually use some of
" the features that I have implemented.
" TODO: Eliminate the MultiMatch function. Add yet another argument to
" Match_wrapper() instead.
" TODO: Allow :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
" TODO: Make backrefs safer by using '\V' (very no-magic).
" TODO: Add a level of indirection, so that custom % scripts can use my
" work but extend it.
" allow user to prevent loading
" and prevent duplicate loading
if exists("loaded_matchit") || &cp
finish
endif
let loaded_matchit = 1
let s:last_mps = ""
let s:last_words = ":"
let s:save_cpo = &cpo
set cpo&vim
nnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'n') <CR>
nnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'n') <CR>
vnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'v') <CR>m'gv``
vnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'v') <CR>m'gv``
onoremap <silent> % v:<C-U>call <SID>Match_wrapper('',1,'o') <CR>
onoremap <silent> g% v:<C-U>call <SID>Match_wrapper('',0,'o') <CR>
" Analogues of [{ and ]} using matching patterns:
nnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "n") <CR>
nnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "n") <CR>
vmap [% <Esc>[%m'gv``
vmap ]% <Esc>]%m'gv``
" vnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "v") <CR>m'gv``
" vnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "v") <CR>m'gv``
onoremap <silent> [% v:<C-U>call <SID>MultiMatch("bW", "o") <CR>
onoremap <silent> ]% v:<C-U>call <SID>MultiMatch("W", "o") <CR>
" text object:
vmap a% <Esc>[%v]%
" Auto-complete mappings: (not yet "ready for prime time")
" TODO Read :help write-plugin for the "right" way to let the user
" specify a key binding.
" let g:match_auto = '<C-]>'
" let g:match_autoCR = '<C-CR>'
" if exists("g:match_auto")
" execute "inoremap " . g:match_auto . ' x<Esc>"=<SID>Autocomplete()<CR>Pls'
" endif
" if exists("g:match_autoCR")
" execute "inoremap " . g:match_autoCR . ' <CR><C-R>=<SID>Autocomplete()<CR>'
" endif
" if exists("g:match_gthhoh")
" execute "inoremap " . g:match_gthhoh . ' <C-O>:call <SID>Gthhoh()<CR>'
" endif " gthhoh = "Get the heck out of here!"
let s:notslash = '\\\@<!\%(\\\\\)*'
function! s:Match_wrapper(word, forward, mode) range
" In s:CleanUp(), :execute "set" restore_options .
let restore_options = (&ic ? " " : " no") . "ignorecase"
if exists("b:match_ignorecase")
let &ignorecase = b:match_ignorecase
endif
let restore_options = " ve=" . &ve . restore_options
set ve=
" If this function was called from Visual mode, make sure that the cursor
" is at the correct end of the Visual range:
if a:mode == "v"
execute "normal! gv\<Esc>"
endif
" In s:CleanUp(), we may need to check whether the cursor moved forward.
let startline = line(".")
let startcol = col(".")
" Use default behavior if called with a count.
if v:count
exe "normal! " . v:count . "%"
return s:CleanUp(restore_options, a:mode, startline, startcol)
end
" First step: if not already done, set the script variables
" s:do_BR flag for whether there are backrefs
" s:pat parsed version of b:match_words
" s:all regexp based on s:pat and the default groups
"
if !exists("b:match_words") || b:match_words == ""
let match_words = ""
" Allow b:match_words = "GetVimMatchWords()" .
elseif b:match_words =~ ":"
let match_words = b:match_words
else
execute "let match_words =" b:match_words
endif
" Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion!
if (match_words != s:last_words) || (&mps != s:last_mps) ||
\ exists("b:match_debug")
let s:last_words = match_words
let s:last_mps = &mps
" The next several lines were here before
" BF started messing with this script.
" quote the special chars in 'matchpairs', replace [,:] with \| and then
" append the builtin pairs (/*, */, #if, #ifdef, #else, #elif, #endif)
" let default = substitute(escape(&mps, '[$^.*~\\/?]'), '[,:]\+',
" \ '\\|', 'g').'\|\/\*\|\*\/\|#if\>\|#ifdef\>\|#else\>\|#elif\>\|#endif\>'
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
" s:all = pattern with all the keywords
let match_words = match_words . (strlen(match_words) ? "," : "") . default
if match_words !~ s:notslash . '\\\d'
let s:do_BR = 0
let s:pat = match_words
else
let s:do_BR = 1
let s:pat = s:ParseWords(match_words)
endif
let s:all = substitute(s:pat, s:notslash . '\zs[,:]\+', '\\|', 'g')
let s:all = '\%(' . s:all . '\)'
" let s:all = '\%(' . substitute(s:all, '\\\ze[,:]', '', 'g') . '\)'
if exists("b:match_debug")
let b:match_pat = s:pat
endif
endif
" Second step: set the following local variables:
" matchline = line on which the cursor started
" curcol = number of characters before match
" prefix = regexp for start of line to start of match
" suffix = regexp for end of match to end of line
" Require match to end on or after the cursor and prefer it to
" start on or before the cursor.
let matchline = getline(startline)
if a:word != ''
" word given
if a:word !~ s:all
echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE
return s:CleanUp(restore_options, a:mode, startline, startcol)
endif
let matchline = a:word
let curcol = 0
let prefix = '^\%('
let suffix = '\)$'
" Now the case when "word" is not given
else " Find the match that ends on or after the cursor and set curcol.
let regexp = s:Wholematch(matchline, s:all, startcol-1)
let curcol = match(matchline, regexp)
" If there is no match, give up.
if curcol == -1
return s:CleanUp(restore_options, a:mode, startline, startcol)
endif
let endcol = matchend(matchline, regexp)
let suf = strlen(matchline) - endcol
let prefix = (curcol ? '^.*\%' . (curcol + 1) . 'c\%(' : '^\%(')
let suffix = (suf ? '\)\%' . (endcol + 1) . 'c.*$' : '\)$')
endif
if exists("b:match_debug")
let b:match_match = matchstr(matchline, regexp)
let b:match_col = curcol+1
endif
" Third step: Find the group and single word that match, and the original
" (backref) versions of these. Then, resolve the backrefs.
" Set the following local variable:
" group = colon-separated list of patterns, one of which matches
" = ini:mid:fin or ini:fin
"
" Reconstruct the version with unresolved backrefs.
let patBR = substitute(match_words.',',
\ s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
let patBR = substitute(patBR, s:notslash.'\zs:\{2,}', ':', 'g')
" Now, set group and groupBR to the matching group: 'if:endif' or
" 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns
" group . "," . groupBR, and we pick it apart.
let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
let i = matchend(group, s:notslash . ",")
let groupBR = strpart(group, i)
let group = strpart(group, 0, i-1)
" Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
if s:do_BR " Do the hard part: resolve those backrefs!
let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
endif
if exists("b:match_debug")
let b:match_wholeBR = groupBR
let i = matchend(groupBR, s:notslash . ":")
let b:match_iniBR = strpart(groupBR, 0, i-1)
endif
" Fourth step: Set the arguments for searchpair().
let i = matchend(group, s:notslash . ":")
let j = matchend(group, '.*' . s:notslash . ":")
let ini = strpart(group, 0, i-1)
let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g')
let fin = strpart(group, j)
"Un-escape the remaining , and : characters.
let ini = substitute(ini, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
let mid = substitute(mid, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
let fin = substitute(fin, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
" searchpair() requires that these patterns avoid \(\) groups.
let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g')
let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g')
let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g')
" Set mid. This is optimized for readability, not micro-efficiency!
if a:forward && matchline =~ prefix . fin . suffix
\ || !a:forward && matchline =~ prefix . ini . suffix
let mid = ""
endif
" Set flag. This is optimized for readability, not micro-efficiency!
if a:forward && matchline =~ prefix . fin . suffix
\ || !a:forward && matchline !~ prefix . ini . suffix
let flag = "bW"
else
let flag = "W"
endif
" Set skip.
if exists("b:match_skip")
let skip = b:match_skip
elseif exists("b:match_comment") " backwards compatibility and testing!
let skip = "r:" . b:match_comment
else
let skip = 's:comment\|string'
endif
let skip = s:ParseSkip(skip)
if exists("b:match_debug")
let b:match_ini = ini
let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin
endif
" Fifth step: actually start moving the cursor and call searchpair().
" Later, :execute restore_cursor to get to the original screen.
let restore_cursor = virtcol(".") . "|"
normal! g0
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
normal! H
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
execute restore_cursor
call cursor(0, curcol + 1)
" normal! 0
" if curcol
" execute "normal!" . curcol . "l"
" endif
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
let skip = "0"
else
execute "if " . skip . "| let skip = '0' | endif"
endif
let sp_return = searchpair(ini, mid, fin, flag, skip)
let final_position = "call cursor(" . line(".") . "," . col(".") . ")"
" Restore cursor position and original screen.
execute restore_cursor
normal! m'
if sp_return > 0
execute final_position
endif
return s:CleanUp(restore_options, a:mode, startline, startcol, mid.'\|'.fin)
endfun
" Restore options and do some special handling for Operator-pending mode.
" The optional argument is the tail of the matching group.
fun! s:CleanUp(options, mode, startline, startcol, ...)
execute "set" a:options
" Open folds, if appropriate.
if a:mode != "o"
if &foldopen =~ "percent"
normal! zv
endif
" In Operator-pending mode, we want to include the whole match
" (for example, d%).
" This is only a problem if we end up moving in the forward direction.
elseif (a:startline < line(".")) ||
\ (a:startline == line(".") && a:startcol < col("."))
if a:0
" Check whether the match is a single character. If not, move to the
" end of the match.
let matchline = getline(".")
let currcol = col(".")
let regexp = s:Wholematch(matchline, a:1, currcol-1)
let endcol = matchend(matchline, regexp)
if endcol > currcol " This is NOT off by one!
execute "normal!" . (endcol - currcol) . "l"
endif
endif " a:0
endif " a:mode != "o" && etc.
return 0
endfun
" Example (simplified HTML patterns): if
" a:groupBR = '<\(\k\+\)>:</\1>'
" a:prefix = '^.\{3}\('
" a:group = '<\(\k\+\)>:</\(\k\+\)>'
" a:suffix = '\).\{2}$'
" a:matchline = "123<tag>12" or "123</tag>12"
" then extract "tag" from a:matchline and return "<tag>:</tag>" .
fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline)
if a:matchline !~ a:prefix .
\ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix
return a:group
endif
let i = matchend(a:groupBR, s:notslash . ':')
let ini = strpart(a:groupBR, 0, i-1)
let tailBR = strpart(a:groupBR, i)
let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix,
\ a:groupBR)
let i = matchend(word, s:notslash . ":")
let wordBR = strpart(word, i)
let word = strpart(word, 0, i-1)
" Now, a:matchline =~ a:prefix . word . a:suffix
if wordBR != ini
let table = s:Resolve(ini, wordBR, "table")
else
" let table = "----------"
let table = ""
let d = 0
while d < 10
if tailBR =~ s:notslash . '\\' . d
" let table[d] = d
let table = table . d
else
let table = table . "-"
endif
let d = d + 1
endwhile
endif
let d = 9
while d
if table[d] != "-"
let backref = substitute(a:matchline, a:prefix.word.a:suffix,
\ '\'.table[d], "")
" Are there any other characters that should be escaped?
let backref = escape(backref, '*,:')
execute s:Ref(ini, d, "start", "len")
let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len)
let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d,
\ escape(backref, '\\'), 'g')
endif
let d = d-1
endwhile
if exists("b:match_debug")
if s:do_BR
let b:match_table = table
let b:match_word = word
else
let b:match_table = ""
let b:match_word = ""
endif
endif
return ini . ":" . tailBR
endfun
" Input a comma-separated list of groups with backrefs, such as
" a:groups = '\(foo\):end\1,\(bar\):end\1'
" and return a comma-separated list of groups with backrefs replaced:
" return '\(foo\):end\(foo\),\(bar\):end\(bar\)'
fun! s:ParseWords(groups)
let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g')
let parsed = ""
while groups =~ '[^,:]'
let i = matchend(groups, s:notslash . ':')
let j = matchend(groups, s:notslash . ',')
let ini = strpart(groups, 0, i-1)
let tail = strpart(groups, i, j-i-1) . ":"
let groups = strpart(groups, j)
let parsed = parsed . ini
let i = matchend(tail, s:notslash . ':')
while i != -1
" In 'if:else:endif', ini='if' and word='else' and then word='endif'.
let word = strpart(tail, 0, i-1)
let tail = strpart(tail, i)
let i = matchend(tail, s:notslash . ':')
let parsed = parsed . ":" . s:Resolve(ini, word, "word")
endwhile " Now, tail has been used up.
let parsed = parsed . ","
endwhile " groups =~ '[^,:]'
let parsed = substitute(parsed, ',$', '', '')
return parsed
endfun
" TODO I think this can be simplified and/or made more efficient.
" TODO What should I do if a:start is out of range?
" Return a regexp that matches all of a:string, such that
" matchstr(a:string, regexp) represents the match for a:pat that starts
" as close to a:start as possible, before being preferred to after, and
" ends after a:start .
" Usage:
" let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1)
" let i = match(getline("."), regexp)
" let j = matchend(getline("."), regexp)
" let match = matchstr(getline("."), regexp)
fun! s:Wholematch(string, pat, start)
let group = '\%(' . a:pat . '\)'
let prefix = (a:start ? '\(^.*\%<' . (a:start + 2) . 'c\)\zs' : '^')
let len = strlen(a:string)
let suffix = (a:start+1 < len ? '\(\%>'.(a:start+1).'c.*$\)\@=' : '$')
if a:string !~ prefix . group . suffix
let prefix = ''
endif
return prefix . group . suffix
endfun
" No extra arguments: s:Ref(string, d) will
" find the d'th occurrence of '\(' and return it, along with everything up
" to and including the matching '\)'.
" One argument: s:Ref(string, d, "start") returns the index of the start
" of the d'th '\(' and any other argument returns the length of the group.
" Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be
" executed, having the effect of
" :let foo = s:Ref(string, d, "start")
" :let bar = s:Ref(string, d, "len")
fun! s:Ref(string, d, ...)
let len = strlen(a:string)
if a:d == 0
let start = 0
else
let cnt = a:d
let match = a:string
while cnt
let cnt = cnt - 1
let index = matchend(match, s:notslash . '\\(')
if index == -1
return ""
endif
let match = strpart(match, index)
endwhile
let start = len - strlen(match)
if a:0 == 1 && a:1 == "start"
return start - 2
endif
let cnt = 1
while cnt
let index = matchend(match, s:notslash . '\\(\|\\)') - 1
if index == -2
return ""
endif
" Increment if an open, decrement if a ')':
let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')'
" let cnt = stridx('0(', match[index]) + cnt
let match = strpart(match, index+1)
endwhile
let start = start - 2
let len = len - start - strlen(match)
endif
if a:0 == 1
return len
elseif a:0 == 2
return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len
else
return strpart(a:string, start, len)
endif
endfun
" Count the number of disjoint copies of pattern in string.
" If the pattern is a literal string and contains no '0' or '1' characters
" then s:Count(string, pattern, '0', '1') should be faster than
" s:Count(string, pattern).
fun! s:Count(string, pattern, ...)
let pat = escape(a:pattern, '\\')
if a:0 > 1
let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g")
let foo = substitute(a:string, pat, a:2, "g")
let foo = substitute(foo, '[^' . a:2 . ']', "", "g")
return strlen(foo)
endif
let result = 0
let foo = a:string
let index = matchend(foo, pat)
while index != -1
let result = result + 1
let foo = strpart(foo, index)
let index = matchend(foo, pat)
endwhile
return result
endfun
" s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where
" word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first
" '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this
" indicates that all other instances of '\1' in target are to be replaced
" by '\3'. The hard part is dealing with nesting...
" Note that ":" is an illegal character for source and target,
" unless it is preceded by "\".
fun! s:Resolve(source, target, output)
let word = a:target
let i = matchend(word, s:notslash . '\\\d') - 1
let table = "----------"
while i != -2 " There are back references to be replaced.
let d = word[i]
let backref = s:Ref(a:source, d)
" The idea is to replace '\d' with backref. Before we do this,
" replace any \(\) groups in backref with :1, :2, ... if they
" correspond to the first, second, ... group already inserted
" into backref. Later, replace :1 with \1 and so on. The group
" number w+b within backref corresponds to the group number
" s within a:source.
" w = number of '\(' in word before the current one
let w = s:Count(
\ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1')
let b = 1 " number of the current '\(' in backref
let s = d " number of the current '\(' in a:source
while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1')
\ && s < 10
if table[s] == "-"
if w + b < 10
" let table[s] = w + b
let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1)
endif
let b = b + 1
let s = s + 1
else
execute s:Ref(backref, b, "start", "len")
let ref = strpart(backref, start, len)
let backref = strpart(backref, 0, start) . ":". table[s]
\ . strpart(backref, start+len)
let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1')
endif
endwhile
let word = strpart(word, 0, i-1) . backref . strpart(word, i+1)
let i = matchend(word, s:notslash . '\\\d') - 1
endwhile
let word = substitute(word, s:notslash . '\zs:', '\\', 'g')
if a:output == "table"
return table
elseif a:output == "word"
return word
else
return table . word
endif
endfun
" Assume a:comma = ",". Then the format for a:patterns and a:1 is
" a:patterns = "<pat1>,<pat2>,..."
" a:1 = "<alt1>,<alt2>,..."
" If <patn> is the first pattern that matches a:string then return <patn>
" if no optional arguments are given; return <patn>,<altn> if a:1 is given.
fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...)
let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma)
let i = matchend(tail, s:notslash . a:comma)
if a:0
let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma)
let j = matchend(alttail, s:notslash . a:comma)
endif
let current = strpart(tail, 0, i-1)
if a:branch == ""
let currpat = current
else
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
endif
while a:string !~ a:prefix . currpat . a:suffix
let tail = strpart(tail, i)
let i = matchend(tail, s:notslash . a:comma)
if i == -1
return -1
endif
let current = strpart(tail, 0, i-1)
if a:branch == ""
let currpat = current
else
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
endif
if a:0
let alttail = strpart(alttail, j)
let j = matchend(alttail, s:notslash . a:comma)
endif
endwhile
if a:0
let current = current . a:comma . strpart(alttail, 0, j-1)
endif
return current
endfun
" Call this function to turn on debugging information. Every time the main
" script is run, buffer variables will be saved. These can be used directly
" or viewed using the menu items below.
if !exists(":MatchDebug")
command! -nargs=0 MatchDebug call s:Match_debug()
endif
fun! s:Match_debug()
let b:match_debug = 1 " Save debugging information.
" pat = all of b:match_words with backrefs parsed
amenu &Matchit.&pat :echo b:match_pat<CR>
" match = bit of text that is recognized as a match
amenu &Matchit.&match :echo b:match_match<CR>
" curcol = cursor column of the start of the matching text
amenu &Matchit.&curcol :echo b:match_col<CR>
" wholeBR = matching group, original version
amenu &Matchit.wh&oleBR :echo b:match_wholeBR<CR>
" iniBR = 'if' piece, original version
amenu &Matchit.ini&BR :echo b:match_iniBR<CR>
" ini = 'if' piece, with all backrefs resolved from match
amenu &Matchit.&ini :echo b:match_ini<CR>
" tail = 'else\|endif' piece, with all backrefs resolved from match
amenu &Matchit.&tail :echo b:match_tail<CR>
" fin = 'endif' piece, with all backrefs resolved from match
amenu &Matchit.&word :echo b:match_word<CR>
" '\'.d in ini refers to the same thing as '\'.table[d] in word.
amenu &Matchit.t&able :echo '0:' . b:match_table . ':9'<CR>
endfun
" Jump to the nearest unmatched "(" or "if" or "<tag>" if a:spflag == "bW"
" or the nearest unmatched "</tag>" or "endif" or ")" if a:spflag == "W".
" Return a "mark" for the original position, so that
" let m = MultiMatch("bW", "n") ... execute m
" will return to the original position. If there is a problem, do not
" move the cursor and return "", unless a count is given, in which case
" go up or down as many levels as possible and again return "".
" TODO This relies on the same patterns as % matching. It might be a good
" idea to give it its own matching patterns.
fun! s:MultiMatch(spflag, mode)
if !exists("b:match_words") || b:match_words == ""
return ""
end
let restore_options = (&ic ? "" : "no") . "ignorecase"
if exists("b:match_ignorecase")
let &ignorecase = b:match_ignorecase
endif
let startline = line(".")
let startcol = col(".")
" First step: if not already done, set the script variables
" s:do_BR flag for whether there are backrefs
" s:pat parsed version of b:match_words
" s:all regexp based on s:pat and the default groups
" This part is copied and slightly modified from s:Match_wrapper().
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
" Allow b:match_words = "GetVimMatchWords()" .
if b:match_words =~ ":"
let match_words = b:match_words
else
execute "let match_words =" b:match_words
endif
if (match_words != s:last_words) || (&mps != s:last_mps) ||
\ exists("b:match_debug")
let s:last_words = match_words
let s:last_mps = &mps
if match_words !~ s:notslash . '\\\d'
let s:do_BR = 0
let s:pat = match_words
else
let s:do_BR = 1
let s:pat = s:ParseWords(match_words)
endif
let s:all = '\%(' . substitute(s:pat . (strlen(s:pat)?",":"") . default,
\ '[,:]\+','\\|','g') . '\)'
if exists("b:match_debug")
let b:match_pat = s:pat
endif
endif
" Second step: figure out the patterns for searchpair()
" and save the screen, cursor position, and 'ignorecase'.
" - TODO: A lot of this is copied from s:Match_wrapper().
" - maybe even more functionality should be split off
" - into separate functions!
let cdefault = (s:pat =~ '[^,]$' ? "," : "") . default
let open = substitute(s:pat . cdefault,
\ s:notslash . '\zs:.\{-}' . s:notslash . ',', '\\),\\(', 'g')
let open = '\(' . substitute(open, s:notslash . '\zs:.*$', '\\)', '')
let close = substitute(s:pat . cdefault,
\ s:notslash . '\zs,.\{-}' . s:notslash . ':', '\\),\\(', 'g')
let close = substitute(close, '^.\{-}' . s:notslash . ':', '\\(', '') . '\)'
if exists("b:match_skip")
let skip = b:match_skip
elseif exists("b:match_comment") " backwards compatibility and testing!
let skip = "r:" . b:match_comment
else
let skip = 's:comment\|string'
endif
let skip = s:ParseSkip(skip)
" let restore_cursor = line(".") . "G" . virtcol(".") . "|"
" normal! H
" let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
let restore_cursor = virtcol(".") . "|"
normal! g0
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
normal! H
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
execute restore_cursor
" Third step: call searchpair().
" Replace '\('--but not '\\('--with '\%(' and ',' with '\|'.
let openpat = substitute(open, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
let openpat = substitute(openpat, ',', '\\|', 'g')
let closepat = substitute(close, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
let closepat = substitute(closepat, ',', '\\|', 'g')
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
let skip = '0'
else
execute "if " . skip . "| let skip = '0' | endif"
endif
mark '
let level = v:count1
while level
if searchpair(openpat, '', closepat, a:spflag, skip) < 1
call s:CleanUp(restore_options, a:mode, startline, startcol)
return ""
endif
let level = level - 1
endwhile
" Restore options and return a string to restore the original position.
call s:CleanUp(restore_options, a:mode, startline, startcol)
return restore_cursor
endfun
" Search backwards for "if" or "while" or "<tag>" or ...
" and return "endif" or "endwhile" or "</tag>" or ... .
" For now, this uses b:match_words and the same script variables
" as s:Match_wrapper() . Later, it may get its own patterns,
" either from a buffer variable or passed as arguments.
" fun! s:Autocomplete()
" echo "autocomplete not yet implemented :-("
" if !exists("b:match_words") || b:match_words == ""
" return ""
" end
" let startpos = s:MultiMatch("bW")
"
" if startpos == ""
" return ""
" endif
" " - TODO: figure out whether 'if' or '<tag>' matched, and construct
" " - the appropriate closing.
" let matchline = getline(".")
" let curcol = col(".") - 1
" " - TODO: Change the s:all argument if there is a new set of match pats.
" let regexp = s:Wholematch(matchline, s:all, curcol)
" let suf = strlen(matchline) - matchend(matchline, regexp)
" let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(')
" let suffix = (suf ? '\).\{' . suf . '}$' : '\)$')
" " Reconstruct the version with unresolved backrefs.
" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g')
" let patBR = substitute(patBR, ':\{2,}', ':', "g")
" " Now, set group and groupBR to the matching group: 'if:endif' or
" " 'while:endwhile' or whatever.
" let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
" let i = matchend(group, s:notslash . ",")
" let groupBR = strpart(group, i)
" let group = strpart(group, 0, i-1)
" " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
" if s:do_BR
" let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
" endif
" " let g:group = group
"
" " - TODO: Construct the closing from group.
" let fake = "end" . expand("<cword>")
" execute startpos
" return fake
" endfun
" Close all open structures. "Get the heck out of here!"
" fun! s:Gthhoh()
" let close = s:Autocomplete()
" while strlen(close)
" put=close
" let close = s:Autocomplete()
" endwhile
" endfun
" Parse special strings as typical skip arguments for searchpair():
" s:foo becomes (current syntax item) =~ foo
" S:foo becomes (current syntax item) !~ foo
" r:foo becomes (line before cursor) =~ foo
" R:foo becomes (line before cursor) !~ foo
fun! s:ParseSkip(str)
let skip = a:str
if skip[1] == ":"
if skip[0] == "s"
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .
\ strpart(skip,2) . "'"
elseif skip[0] == "S"
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .
\ strpart(skip,2) . "'"
elseif skip[0] == "r"
let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'"
elseif skip[0] == "R"
let skip = "strpart(getline('.'),0,col('.'))!~'" . strpart(skip,2). "'"
endif
endif
return skip
endfun
let &cpo = s:save_cpo
" vim:sts=2:sw=2:

@ -1,3 +0,0 @@
*~
*.swp
tags

@ -1,108 +0,0 @@
The NERD Tree
=============
Intro
-----
The NERD tree allows you to explore your filesystem and to open files and
directories. It presents the filesystem to you in the form of a tree which you
manipulate with the keyboard and/or mouse. It also allows you to perform
simple filesystem operations.
The following features and functionality are provided by the NERD tree:
* Files and directories are displayed in a hierarchical tree structure
* Different highlighting is provided for the following types of nodes:
* files
* directories
* sym-links
* windows .lnk files
* read-only files
* executable files
* Many (customisable) mappings are provided to manipulate the tree:
* Mappings to open/close/explore directory nodes
* Mappings to open files in new/existing windows/tabs
* Mappings to change the current root of the tree
* Mappings to navigate around the tree
* ...
* Directories and files can be bookmarked.
* Most NERD tree navigation can also be done with the mouse
* Filtering of tree content (can be toggled at runtime)
* custom file filters to prevent e.g. vim backup files being displayed
* optional displaying of hidden files (. files)
* files can be "turned off" so that only directories are displayed
* The position and size of the NERD tree window can be customised
* The order in which the nodes in the tree are listed can be customised.
* A model of your filesystem is created/maintained as you explore it. This
has several advantages:
* All filesystem information is cached and is only re-read on demand
* If you revisit a part of the tree that you left earlier in your
session, the directory nodes will be opened/closed as you left them
* The script remembers the cursor position and window position in the NERD
tree so you can toggle it off (or just close the tree window) and then
reopen it (with NERDTreeToggle) the NERD tree window will appear exactly
as you left it
* You can have a separate NERD tree for each tab, share trees across tabs,
or a mix of both.
* By default the script overrides the default file browser (netrw), so if
you :edit a directory a (slightly modified) NERD tree will appear in the
current window
* A programmable menu system is provided (simulates right clicking on a node)
* one default menu plugin is provided to perform basic filesystem
operations (create/delete/move/copy files/directories)
* There's an API for adding your own keymappings
Installation
------------
[pathogen.vim](https://github.com/tpope/vim-pathogen) is the recommended way to install nerdtree.
cd ~/.vim/bundle
git clone https://github.com/scrooloose/nerdtree.git
Then reload vim, run `:helptags`, and check out `:help NERD_tree.txt`.
Faq
---
__Q. Can I have the nerdtree on every tab automatically?__
A. Nope. If this is something you want then chances are you aren't using tabs
and buffers as they were intended to be used. Read this
http://stackoverflow.com/questions/102384/using-vims-tabs-like-buffers
If you are interested in this behaviour then consider [vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs)
__Q. How can I open a NERDTree automatically when vim starts up?__
A. Stick this in your vimrc: `autocmd vimenter * NERDTree`
__Q. How can I open a NERDTree automatically when vim starts up if no files were specified?__
A. Stick this in your vimrc `autocmd vimenter * if !argc() | NERDTree | endif`
__Q. How can I map a specific key or shortcut to open NERDTree?__
A. Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want): `map <C-n> :NERDTreeToggle<CR>`
__Q. How can I close vim if the only window left open is a NERDTree?__
A. Stick this in your vimrc:
`autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif`
Changelog
---------
4.2.0 (2011-12-28)
* Add NERDTreeDirArrows option to make the UI use pretty arrow chars instead of the old +~| chars to define the tree structure (sickill)
* shift the syntax highlighting out into its own syntax file (gnap) * add some mac specific options to the filesystem menu - for macvim only (andersonfreitas)
* Add NERDTreeMinimalUI option to remove some non functional parts of the nerdtree ui (camthompson)
* tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the new behaviour (benjamingeiger)
* if no name is given to :Bookmark, make it default to the name of the target file/dir (minyoung)
* use 'file' completion when doing copying, create, and move operations (EvanDotPro)
* lots of misc bug fixes (paddyoloughlin, sdewald, camthompson, Vitaly Bogdanov, AndrewRadev, mathias, scottstvnsn, kml, wycats, me RAWR!)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,315 +0,0 @@
"CLASS: Bookmark
"============================================================
let s:Bookmark = {}
let g:NERDTreeBookmark = s:Bookmark
" FUNCTION: Bookmark.activate() {{{1
function! s:Bookmark.activate(...)
call self.open(a:0 ? a:1 : {})
endfunction
" FUNCTION: Bookmark.AddBookmark(name, path) {{{1
" Class method to add a new bookmark to the list, if a previous bookmark exists
" with the same name, just update the path for that bookmark
function! s:Bookmark.AddBookmark(name, path)
for i in s:Bookmark.Bookmarks()
if i.name ==# a:name
let i.path = a:path
return
endif
endfor
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
call s:Bookmark.Sort()
endfunction
" FUNCTION: Bookmark.Bookmarks() {{{1
" Class method to get all bookmarks. Lazily initializes the bookmarks global
" variable
function! s:Bookmark.Bookmarks()
if !exists("g:NERDTreeBookmarks")
let g:NERDTreeBookmarks = []
endif
return g:NERDTreeBookmarks
endfunction
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
" class method that returns 1 if a bookmark with the given name is found, 0
" otherwise
function! s:Bookmark.BookmarkExistsFor(name)
try
call s:Bookmark.BookmarkFor(a:name)
return 1
catch /^NERDTree.BookmarkNotFoundError/
return 0
endtry
endfunction
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
" Class method to get the bookmark that has the given name. {} is return if no
" bookmark is found
function! s:Bookmark.BookmarkFor(name)
for i in s:Bookmark.Bookmarks()
if i.name ==# a:name
return i
endif
endfor
throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"'
endfunction
" FUNCTION: Bookmark.BookmarkNames() {{{1
" Class method to return an array of all bookmark names
function! s:Bookmark.BookmarkNames()
let names = []
for i in s:Bookmark.Bookmarks()
call add(names, i.name)
endfor
return names
endfunction
" FUNCTION: Bookmark.CacheBookmarks(silent) {{{1
" Class method to read all bookmarks from the bookmarks file initialize
" bookmark objects for each one.
"
" Args:
" silent - dont echo an error msg if invalid bookmarks are found
function! s:Bookmark.CacheBookmarks(silent)
if filereadable(g:NERDTreeBookmarksFile)
let g:NERDTreeBookmarks = []
let g:NERDTreeInvalidBookmarks = []
let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
let invalidBookmarksFound = 0
for i in bookmarkStrings
"ignore blank lines
if i != ''
let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
try
let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path))
call add(g:NERDTreeBookmarks, bookmark)
catch /^NERDTree.InvalidArgumentsError/
call add(g:NERDTreeInvalidBookmarks, i)
let invalidBookmarksFound += 1
endtry
endif
endfor
if invalidBookmarksFound
call s:Bookmark.Write()
if !a:silent
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
endif
endif
call s:Bookmark.Sort()
endif
endfunction
" FUNCTION: Bookmark.compareTo(otherbookmark) {{{1
" Compare these two bookmarks for sorting purposes
function! s:Bookmark.compareTo(otherbookmark)
return a:otherbookmark.name < self.name
endfunction
" FUNCTION: Bookmark.ClearAll() {{{1
" Class method to delete all bookmarks.
function! s:Bookmark.ClearAll()
for i in s:Bookmark.Bookmarks()
call i.delete()
endfor
call s:Bookmark.Write()
endfunction
" FUNCTION: Bookmark.delete() {{{1
" Delete this bookmark. If the node for this bookmark is under the current
" root, then recache bookmarks for its Path object
function! s:Bookmark.delete()
let node = {}
try
let node = self.getNode(1)
catch /^NERDTree.BookmarkedNodeNotFoundError/
endtry
call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
if !empty(node)
call node.path.cacheDisplayString()
endif
call s:Bookmark.Write()
endfunction
" FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{1
" Gets the treenode for this bookmark
"
" Args:
" searchFromAbsoluteRoot: specifies whether we should search from the current
" tree root, or the highest cached node
function! s:Bookmark.getNode(searchFromAbsoluteRoot)
let searchRoot = a:searchFromAbsoluteRoot ? g:NERDTreeDirNode.AbsoluteTreeRoot() : b:NERDTreeRoot
let targetNode = searchRoot.findNode(self.path)
if empty(targetNode)
throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name
endif
return targetNode
endfunction
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{1
" Class method that finds the bookmark with the given name and returns the
" treenode for it.
function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot)
let bookmark = s:Bookmark.BookmarkFor(a:name)
return bookmark.getNode(a:searchFromAbsoluteRoot)
endfunction
" FUNCTION: Bookmark.GetSelected() {{{1
" returns the Bookmark the cursor is over, or {}
function! s:Bookmark.GetSelected()
let line = getline(".")
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
if name != line
try
return s:Bookmark.BookmarkFor(name)
catch /^NERDTree.BookmarkNotFoundError/
return {}
endtry
endif
return {}
endfunction
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
" Class method to get all invalid bookmark strings read from the bookmarks
" file
function! s:Bookmark.InvalidBookmarks()
if !exists("g:NERDTreeInvalidBookmarks")
let g:NERDTreeInvalidBookmarks = []
endif
return g:NERDTreeInvalidBookmarks
endfunction
" FUNCTION: Bookmark.mustExist() {{{1
function! s:Bookmark.mustExist()
if !self.path.exists()
call s:Bookmark.CacheBookmarks(1)
throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"".
\ self.name ."\" points to a non existing location: \"". self.path.str()
endif
endfunction
" FUNCTION: Bookmark.New(name, path) {{{1
" Create a new bookmark object with the given name and path object
function! s:Bookmark.New(name, path)
if a:name =~# ' '
throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name
endif
let newBookmark = copy(self)
let newBookmark.name = a:name
let newBookmark.path = a:path
return newBookmark
endfunction
" FUNCTION: Bookmark.open([options]) {{{1
"Args:
"A dictionary containing the following keys (all optional):
" 'where': Specifies whether the node should be opened in new split/tab or in
" the previous window. Can be either 'v' (vertical split), 'h'
" (horizontal split), 't' (new tab) or 'p' (previous window).
" 'reuse': if a window is displaying the file then jump the cursor there
" 'keepopen': dont close the tree window
" 'stay': open the file, but keep the cursor in the tree win
"
function! s:Bookmark.open(...)
let opts = a:0 ? a:1 : {}
if self.path.isDirectory && !has_key(opts, 'where')
call self.toRoot()
else
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
endif
endfunction
" FUNCTION: Bookmark.openInNewTab(options) {{{1
" Create a new bookmark object with the given name and path object
function! s:Bookmark.openInNewTab(options)
call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead')
call self.open(a:options)
endfunction
" FUNCTION: Bookmark.setPath(path) {{{1
" makes this bookmark point to the given path
function! s:Bookmark.setPath(path)
let self.path = a:path
endfunction
" FUNCTION: Bookmark.Sort() {{{1
" Class method that sorts all bookmarks
function! s:Bookmark.Sort()
let CompareFunc = function("nerdtree#compareBookmarks")
call sort(s:Bookmark.Bookmarks(), CompareFunc)
endfunction
" FUNCTION: Bookmark.str() {{{1
" Get the string that should be rendered in the view for this bookmark
function! s:Bookmark.str()
let pathStrMaxLen = winwidth(nerdtree#getTreeWinNum()) - 4 - len(self.name)
if &nu
let pathStrMaxLen = pathStrMaxLen - &numberwidth
endif
let pathStr = self.path.str({'format': 'UI'})
if len(pathStr) > pathStrMaxLen
let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen)
endif
return '>' . self.name . ' ' . pathStr
endfunction
" FUNCTION: Bookmark.toRoot() {{{1
" Make the node for this bookmark the new tree root
function! s:Bookmark.toRoot()
if self.validate()
try
let targetNode = self.getNode(1)
catch /^NERDTree.BookmarkedNodeNotFoundError/
let targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path)
endtry
call targetNode.makeRoot()
call nerdtree#renderView()
call targetNode.putCursorHere(0, 0)
endif
endfunction
" FUNCTION: Bookmark.ToRoot(name) {{{1
" Make the node for this bookmark the new tree root
function! s:Bookmark.ToRoot(name)
let bookmark = s:Bookmark.BookmarkFor(a:name)
call bookmark.toRoot()
endfunction
" FUNCTION: Bookmark.validate() {{{1
function! s:Bookmark.validate()
if self.path.exists()
return 1
else
call s:Bookmark.CacheBookmarks(1)
call nerdtree#renderView()
call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
return 0
endif
endfunction
" FUNCTION: Bookmark.Write() {{{1
" Class method to write all bookmarks to the bookmarks file
function! s:Bookmark.Write()
let bookmarkStrings = []
for i in s:Bookmark.Bookmarks()
call add(bookmarkStrings, i.name . ' ' . i.path.str())
endfor
"add a blank line before the invalid ones
call add(bookmarkStrings, "")
for j in s:Bookmark.InvalidBookmarks()
call add(bookmarkStrings, j)
endfor
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,322 +0,0 @@
"CLASS: Creator
"Creates primary/secondary/mirror nerdtree windows. Sets up all the window and
"buffer options and key mappings etc.
"============================================================
let s:Creator = {}
let g:NERDTreeCreator = s:Creator
"FUNCTION: s:Creator._bindMappings() {{{1
function! s:Creator._bindMappings()
"make <cr> do the same as the default 'o' mapping
exec "nnoremap <silent> <buffer> <cr> :call nerdtree#invokeKeyMap('". g:NERDTreeMapActivateNode ."')<cr>"
call g:NERDTreeKeyMap.BindAll()
command! -buffer -nargs=? Bookmark :call nerdtree#bookmarkNode('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#revealBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark :call nerdtree#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#clearBookmarks('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>')
command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call nerdtree#renderView()
command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call nerdtree#renderView()
command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write()
endfunction
"FUNCTION: s:Creator._broadcastInitEvent() {{{1
function! s:Creator._broadcastInitEvent()
silent doautocmd User NERDTreeInit
endfunction
" FUNCTION: s:Creator.BufNamePrefix() {{{2
function! s:Creator.BufNamePrefix()
return 'NERD_tree_'
endfunction
"FUNCTION: s:Creator.CreatePrimary(a:name) {{{1
function! s:Creator.CreatePrimary(name)
let creator = s:Creator.New()
call creator.createPrimary(a:name)
endfunction
"FUNCTION: s:Creator.createPrimary(a:name) {{{1
"name: the name of a bookmark or a directory
function! s:Creator.createPrimary(name)
let path = self._pathForString(a:name)
"if instructed to, then change the vim CWD to the dir the NERDTree is
"inited in
if g:NERDTreeChDirMode != 0
call path.changeToDir()
endif
if nerdtree#treeExistsForTab()
if nerdtree#isTreeOpen()
call nerdtree#closeTree()
endif
unlet t:NERDTreeBufName
endif
let newRoot = g:NERDTreeDirNode.New(path)
call newRoot.open()
call self._createTreeWin()
let b:treeShowHelp = 0
let b:NERDTreeIgnoreEnabled = 1
let b:NERDTreeShowFiles = g:NERDTreeShowFiles
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
let b:NERDTreeRoot = newRoot
let b:NERDTreeType = "primary"
call nerdtree#renderView()
call b:NERDTreeRoot.putCursorHere(0, 0)
call self._broadcastInitEvent()
endfunction
"FUNCTION: s:Creator.CreateSecondary(dir) {{{1
function! s:Creator.CreateSecondary(dir)
let creator = s:Creator.New()
call creator.createSecondary(a:dir)
endfunction
"FUNCTION: s:Creator.createSecondary(dir) {{{1
function! s:Creator.createSecondary(dir)
try
let path = g:NERDTreePath.New(a:dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("Invalid directory name:" . a:name)
return
endtry
"we want the directory buffer to disappear when we do the :edit below
setlocal bufhidden=wipe
let previousBuf = expand("#")
"we need a unique name for each secondary tree buffer to ensure they are
"all independent
exec "silent edit " . self._nextBufferName()
let b:NERDTreePreviousBuf = bufnr(previousBuf)
let b:NERDTreeRoot = g:NERDTreeDirNode.New(path)
call b:NERDTreeRoot.open()
call self._setCommonBufOptions()
let b:NERDTreeType = "secondary"
call nerdtree#renderView()
call self._broadcastInitEvent()
endfunction
" FUNCTION: s:Creator.CreateMirror() {{{1
function! s:Creator.CreateMirror()
let creator = s:Creator.New()
call creator.createMirror()
endfunction
" FUNCTION: s:Creator.createMirror() {{{1
function! s:Creator.createMirror()
"get the names off all the nerd tree buffers
let treeBufNames = []
for i in range(1, tabpagenr("$"))
let nextName = nerdtree#tabpagevar(i, 'NERDTreeBufName')
if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName)
call add(treeBufNames, nextName)
endif
endfor
let treeBufNames = nerdtree#unique(treeBufNames)
"map the option names (that the user will be prompted with) to the nerd
"tree buffer names
let options = {}
let i = 0
while i < len(treeBufNames)
let bufName = treeBufNames[i]
let treeRoot = getbufvar(bufName, "NERDTreeRoot")
let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName
let i = i + 1
endwhile
"work out which tree to mirror, if there is more than 1 then ask the user
let bufferName = ''
if len(keys(options)) > 1
let choices = ["Choose a tree to mirror"]
let choices = extend(choices, sort(keys(options)))
let choice = inputlist(choices)
if choice < 1 || choice > len(options) || choice ==# ''
return
endif
let bufferName = options[sort(keys(options))[choice-1]]
elseif len(keys(options)) ==# 1
let bufferName = values(options)[0]
else
call nerdtree#echo("No trees to mirror")
return
endif
if nerdtree#treeExistsForTab() && nerdtree#isTreeOpen()
call nerdtree#closeTree()
endif
let t:NERDTreeBufName = bufferName
call self._createTreeWin()
exec 'buffer ' . bufferName
if !&hidden
call nerdtree#renderView()
endif
endfunction
"FUNCTION: s:Creator._createTreeWin() {{{1
"Inits the NERD tree window. ie. opens it, sizes it, sets all the local
"options etc
function! s:Creator._createTreeWin()
"create the nerd tree window
let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright "
let splitSize = g:NERDTreeWinSize
if !exists('t:NERDTreeBufName')
let t:NERDTreeBufName = self._nextBufferName()
silent! exec splitLocation . 'vertical ' . splitSize . ' new'
silent! exec "edit " . t:NERDTreeBufName
else
silent! exec splitLocation . 'vertical ' . splitSize . ' split'
silent! exec "buffer " . t:NERDTreeBufName
endif
setlocal winfixwidth
call self._setCommonBufOptions()
endfunction
"FUNCTION: s:Creator.New() {{{1
function! s:Creator.New()
let newCreator = copy(self)
return newCreator
endfunction
" FUNCTION: s:Creator._nextBufferName() {{{2
" returns the buffer name for the next nerd tree
function! s:Creator._nextBufferName()
let name = s:Creator.BufNamePrefix() . self._nextBufferNumber()
return name
endfunction
" FUNCTION: s:Creator._nextBufferNumber() {{{2
" the number to add to the nerd tree buffer name to make the buf name unique
function! s:Creator._nextBufferNumber()
if !exists("s:Creator._NextBufNum")
let s:Creator._NextBufNum = 1
else
let s:Creator._NextBufNum += 1
endif
return s:Creator._NextBufNum
endfunction
"FUNCTION: s:Creator._pathForString(str) {{{1
"find a bookmark or adirectory for the given string
function! s:Creator._pathForString(str)
let path = {}
if g:NERDTreeBookmark.BookmarkExistsFor(a:str)
let path = g:NERDTreeBookmark.BookmarkFor(a:str).path
else
let dir = a:str ==# '' ? getcwd() : a:str
"hack to get an absolute path if a relative path is given
if dir =~# '^\.'
let dir = getcwd() . g:NERDTreePath.Slash() . dir
endif
let dir = g:NERDTreePath.Resolve(dir)
try
let path = g:NERDTreePath.New(dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("No bookmark or directory found for: " . a:str)
return
endtry
endif
if !path.isDirectory
let path = path.getParent()
endif
return path
endfunction
"FUNCTION: s:Creator._setCommonBufOptions() {{{1
function! s:Creator._setCommonBufOptions()
"throwaway buffer options
setlocal noswapfile
setlocal buftype=nofile
setlocal bufhidden=hide
setlocal nowrap
setlocal foldcolumn=0
setlocal foldmethod=manual
setlocal nofoldenable
setlocal nobuflisted
setlocal nospell
if g:NERDTreeShowLineNumbers
setlocal nu
else
setlocal nonu
if v:version >= 703
setlocal nornu
endif
endif
iabc <buffer>
if g:NERDTreeHighlightCursorline
setlocal cursorline
endif
call self._setupStatusline()
let b:treeShowHelp = 0
let b:NERDTreeIgnoreEnabled = 1
let b:NERDTreeShowFiles = g:NERDTreeShowFiles
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
setfiletype nerdtree
call self._bindMappings()
endfunction
"FUNCTION: s:Creator._setupStatusline() {{{1
function! s:Creator._setupStatusline()
if g:NERDTreeStatusline != -1
let &l:statusline = g:NERDTreeStatusline
endif
endfunction
"FUNCTION: s:Creator.TogglePrimary(dir) {{{1
function! s:Creator.TogglePrimary(dir)
let creator = s:Creator.New()
call creator.togglePrimary(a:dir)
endfunction
"FUNCTION: s:Creator.togglePrimary(dir) {{{1
"Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is
"closed it is restored or initialized (if it doesnt exist)
"
"Args:
"dir: the full path for the root node (is only used if the NERD tree is being
"initialized.
function! s:Creator.togglePrimary(dir)
if nerdtree#treeExistsForTab()
if !nerdtree#isTreeOpen()
call self._createTreeWin()
if !&hidden
call nerdtree#renderView()
endif
call nerdtree#restoreScreenState()
else
call nerdtree#closeTree()
endif
else
call self.createPrimary(a:dir)
endif
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,143 +0,0 @@
"CLASS: KeyMap
"============================================================
let s:KeyMap = {}
let g:NERDTreeKeyMap = s:KeyMap
"FUNCTION: KeyMap.All() {{{1
function! s:KeyMap.All()
if !exists("s:keyMaps")
let s:keyMaps = []
endif
return s:keyMaps
endfunction
"FUNCTION: KeyMap.FindFor(key, scope) {{{1
function! s:KeyMap.FindFor(key, scope)
for i in s:KeyMap.All()
if i.key ==# a:key && i.scope ==# a:scope
return i
endif
endfor
return {}
endfunction
"FUNCTION: KeyMap.BindAll() {{{1
function! s:KeyMap.BindAll()
for i in s:KeyMap.All()
call i.bind()
endfor
endfunction
"FUNCTION: KeyMap.bind() {{{1
function! s:KeyMap.bind()
" If the key sequence we're trying to map contains any '<>' notation, we
" must replace each of the '<' characters with '<lt>' to ensure the string
" is not translated into its corresponding keycode during the later part
" of the map command below
" :he <>
let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)'
if self.key =~# specialNotationRegex
let keymapInvokeString = substitute(self.key, specialNotationRegex, '<lt>\1', 'g')
else
let keymapInvokeString = self.key
endif
let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " "
exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#invokeKeyMap("'. keymapInvokeString .'")<cr>'
endfunction
"FUNCTION: KeyMap.Remove(key, scope) {{{1
function! s:KeyMap.Remove(key, scope)
let maps = s:KeyMap.All()
for i in range(len(maps))
if maps[i].key ==# a:key && maps[i].scope ==# a:scope
return remove(maps, i)
endif
endfor
endfunction
"FUNCTION: KeyMap.invoke() {{{1
"Call the KeyMaps callback function
function! s:KeyMap.invoke(...)
let Callback = function(self.callback)
if a:0
call Callback(a:1)
else
call Callback()
endif
endfunction
"FUNCTION: KeyMap.Invoke() {{{1
"Find a keymapping for a:key and the current scope invoke it.
"
"Scope is determined as follows:
" * if the cursor is on a dir node then "DirNode"
" * if the cursor is on a file node then "FileNode"
" * if the cursor is on a bookmark then "Bookmark"
"
"If a keymap has the scope of "all" then it will be called if no other keymap
"is found for a:key and the scope.
function! s:KeyMap.Invoke(key)
let node = g:NERDTreeFileNode.GetSelected()
if !empty(node)
"try file node
if !node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, "FileNode")
if !empty(km)
return km.invoke(node)
endif
endif
"try dir node
if node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, "DirNode")
if !empty(km)
return km.invoke(node)
endif
endif
"try generic node
let km = s:KeyMap.FindFor(a:key, "Node")
if !empty(km)
return km.invoke(node)
endif
endif
"try bookmark
let bm = g:NERDTreeBookmark.GetSelected()
if !empty(bm)
let km = s:KeyMap.FindFor(a:key, "Bookmark")
if !empty(km)
return km.invoke(bm)
endif
endif
"try all
let km = s:KeyMap.FindFor(a:key, "all")
if !empty(km)
return km.invoke()
endif
endfunction
"FUNCTION: KeyMap.Create(options) {{{1
function! s:KeyMap.Create(options)
let newKeyMap = copy(self)
let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options))
let newKeyMap.key = opts['key']
let newKeyMap.quickhelpText = opts['quickhelpText']
let newKeyMap.callback = opts['callback']
let newKeyMap.scope = opts['scope']
call s:KeyMap.Add(newKeyMap)
endfunction
"FUNCTION: KeyMap.Add(keymap) {{{1
function! s:KeyMap.Add(keymap)
call s:KeyMap.Remove(a:keymap.key, a:keymap.scope)
call add(s:KeyMap.All(), a:keymap)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,180 +0,0 @@
"CLASS: MenuController
"============================================================
let s:MenuController = {}
let g:NERDTreeMenuController = s:MenuController
"FUNCTION: MenuController.New(menuItems) {{{1
"create a new menu controller that operates on the given menu items
function! s:MenuController.New(menuItems)
let newMenuController = copy(self)
if a:menuItems[0].isSeparator()
let newMenuController.menuItems = a:menuItems[1:-1]
else
let newMenuController.menuItems = a:menuItems
endif
return newMenuController
endfunction
"FUNCTION: MenuController.showMenu() {{{1
"start the main loop of the menu and get the user to choose/execute a menu
"item
function! s:MenuController.showMenu()
call self._saveOptions()
try
let self.selection = 0
let done = 0
while !done
redraw!
call self._echoPrompt()
let key = nr2char(getchar())
let done = self._handleKeypress(key)
endwhile
finally
call self._restoreOptions()
endtry
if self.selection != -1
let m = self._current()
call m.execute()
endif
endfunction
"FUNCTION: MenuController._echoPrompt() {{{1
function! s:MenuController._echoPrompt()
echo "NERDTree Menu. Use j/k/enter and the shortcuts indicated"
echo "=========================================================="
for i in range(0, len(self.menuItems)-1)
if self.selection == i
echo "> " . self.menuItems[i].text
else
echo " " . self.menuItems[i].text
endif
endfor
endfunction
"FUNCTION: MenuController._current(key) {{{1
"get the MenuItem that is currently selected
function! s:MenuController._current()
return self.menuItems[self.selection]
endfunction
"FUNCTION: MenuController._handleKeypress(key) {{{1
"change the selection (if appropriate) and return 1 if the user has made
"their choice, 0 otherwise
function! s:MenuController._handleKeypress(key)
if a:key == 'j'
call self._cursorDown()
elseif a:key == 'k'
call self._cursorUp()
elseif a:key == nr2char(27) "escape
let self.selection = -1
return 1
elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j
return 1
else
let index = self._nextIndexFor(a:key)
if index != -1
let self.selection = index
if len(self._allIndexesFor(a:key)) == 1
return 1
endif
endif
endif
return 0
endfunction
"FUNCTION: MenuController._allIndexesFor(shortcut) {{{1
"get indexes to all menu items with the given shortcut
function! s:MenuController._allIndexesFor(shortcut)
let toReturn = []
for i in range(0, len(self.menuItems)-1)
if self.menuItems[i].shortcut == a:shortcut
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: MenuController._nextIndexFor(shortcut) {{{1
"get the index to the next menu item with the given shortcut, starts from the
"current cursor location and wraps around to the top again if need be
function! s:MenuController._nextIndexFor(shortcut)
for i in range(self.selection+1, len(self.menuItems)-1)
if self.menuItems[i].shortcut == a:shortcut
return i
endif
endfor
for i in range(0, self.selection)
if self.menuItems[i].shortcut == a:shortcut
return i
endif
endfor
return -1
endfunction
"FUNCTION: MenuController._setCmdheight() {{{1
"sets &cmdheight to whatever is needed to display the menu
function! s:MenuController._setCmdheight()
let &cmdheight = len(self.menuItems) + 3
endfunction
"FUNCTION: MenuController._saveOptions() {{{1
"set any vim options that are required to make the menu work (saving their old
"values)
function! s:MenuController._saveOptions()
let self._oldLazyredraw = &lazyredraw
let self._oldCmdheight = &cmdheight
set nolazyredraw
call self._setCmdheight()
endfunction
"FUNCTION: MenuController._restoreOptions() {{{1
"restore the options we saved in _saveOptions()
function! s:MenuController._restoreOptions()
let &cmdheight = self._oldCmdheight
let &lazyredraw = self._oldLazyredraw
endfunction
"FUNCTION: MenuController._cursorDown() {{{1
"move the cursor to the next menu item, skipping separators
function! s:MenuController._cursorDown()
let done = 0
while !done
if self.selection < len(self.menuItems)-1
let self.selection += 1
else
let self.selection = 0
endif
if !self._current().isSeparator()
let done = 1
endif
endwhile
endfunction
"FUNCTION: MenuController._cursorUp() {{{1
"move the cursor to the previous menu item, skipping separators
function! s:MenuController._cursorUp()
let done = 0
while !done
if self.selection > 0
let self.selection -= 1
else
let self.selection = len(self.menuItems)-1
endif
if !self._current().isSeparator()
let done = 1
endif
endwhile
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,114 +0,0 @@
"CLASS: MenuItem
"============================================================
let s:MenuItem = {}
let g:NERDTreeMenuItem = s:MenuItem
"FUNCTION: MenuItem.All() {{{1
"get all top level menu items
function! s:MenuItem.All()
if !exists("s:menuItems")
let s:menuItems = []
endif
return s:menuItems
endfunction
"FUNCTION: MenuItem.AllEnabled() {{{1
"get all top level menu items that are currently enabled
function! s:MenuItem.AllEnabled()
let toReturn = []
for i in s:MenuItem.All()
if i.enabled()
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: MenuItem.Create(options) {{{1
"make a new menu item and add it to the global list
function! s:MenuItem.Create(options)
let newMenuItem = copy(self)
let newMenuItem.text = a:options['text']
let newMenuItem.shortcut = a:options['shortcut']
let newMenuItem.children = []
let newMenuItem.isActiveCallback = -1
if has_key(a:options, 'isActiveCallback')
let newMenuItem.isActiveCallback = a:options['isActiveCallback']
endif
let newMenuItem.callback = -1
if has_key(a:options, 'callback')
let newMenuItem.callback = a:options['callback']
endif
if has_key(a:options, 'parent')
call add(a:options['parent'].children, newMenuItem)
else
call add(s:MenuItem.All(), newMenuItem)
endif
return newMenuItem
endfunction
"FUNCTION: MenuItem.CreateSeparator(options) {{{1
"make a new separator menu item and add it to the global list
function! s:MenuItem.CreateSeparator(options)
let standard_options = { 'text': '--------------------',
\ 'shortcut': -1,
\ 'callback': -1 }
let options = extend(a:options, standard_options, "force")
return s:MenuItem.Create(options)
endfunction
"FUNCTION: MenuItem.CreateSubmenu(options) {{{1
"make a new submenu and add it to global list
function! s:MenuItem.CreateSubmenu(options)
let standard_options = { 'callback': -1 }
let options = extend(a:options, standard_options, "force")
return s:MenuItem.Create(options)
endfunction
"FUNCTION: MenuItem.enabled() {{{1
"return 1 if this menu item should be displayed
"
"delegates off to the isActiveCallback, and defaults to 1 if no callback was
"specified
function! s:MenuItem.enabled()
if self.isActiveCallback != -1
return {self.isActiveCallback}()
endif
return 1
endfunction
"FUNCTION: MenuItem.execute() {{{1
"perform the action behind this menu item, if this menuitem has children then
"display a new menu for them, otherwise deletegate off to the menuitem's
"callback
function! s:MenuItem.execute()
if len(self.children)
let mc = s:MenuController.New(self.children)
call mc.showMenu()
else
if self.callback != -1
call {self.callback}()
endif
endif
endfunction
"FUNCTION: MenuItem.isSeparator() {{{1
"return 1 if this menuitem is a separator
function! s:MenuItem.isSeparator()
return self.callback == -1 && self.children == []
endfunction
"FUNCTION: MenuItem.isSubmenu() {{{1
"return 1 if this menuitem is a submenu
function! s:MenuItem.isSubmenu()
return self.callback == -1 && !empty(self.children)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,264 +0,0 @@
"CLASS: Opener
"============================================================
let s:Opener = {}
let g:NERDTreeOpener = s:Opener
"FUNCTION: Opener._checkToCloseTree(newtab) {{{1
"Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see
"if the tree should be closed now.
"
"Args:
"a:newtab - boolean. If set, only close the tree now if we are opening the
"target in a new tab. This is needed because we have to close tree before we
"leave the tab
function! s:Opener._checkToCloseTree(newtab)
if self._keepopen
return
endif
if (a:newtab && self._where == 't') || !a:newtab
call nerdtree#closeTreeIfQuitOnOpen()
endif
endfunction
"FUNCTION: Opener._gotoTargetWin() {{{1
function! s:Opener._gotoTargetWin()
if b:NERDTreeType ==# "secondary"
if self._where == 'v'
vsplit
elseif self._where == 'h'
split
elseif self._where == 't'
tabnew
endif
else
call self._checkToCloseTree(1)
if self._where == 'v'
call self._newVSplit()
elseif self._where == 'h'
call self._newSplit()
elseif self._where == 't'
tabnew
elseif self._where == 'p'
call self._previousWindow()
endif
call self._checkToCloseTree(0)
endif
endfunction
"FUNCTION: Opener.New(path, opts) {{{1
"Args:
"
"a:path: The path object that is to be opened.
"
"a:opts:
"
"A dictionary containing the following keys (all optional):
" 'where': Specifies whether the node should be opened in new split/tab or in
" the previous window. Can be either 'v' or 'h' or 't' (for open in
" new tab)
" 'reuse': if a window is displaying the file then jump the cursor there
" 'keepopen': dont close the tree window
" 'stay': open the file, but keep the cursor in the tree win
function! s:Opener.New(path, opts)
let newObj = copy(self)
let newObj._path = a:path
let newObj._stay = nerdtree#has_opt(a:opts, 'stay')
let newObj._reuse = nerdtree#has_opt(a:opts, 'reuse')
let newObj._keepopen = nerdtree#has_opt(a:opts, 'keepopen')
let newObj._where = has_key(a:opts, 'where') ? a:opts['where'] : ''
let newObj._treetype = b:NERDTreeType
call newObj._saveCursorPos()
return newObj
endfunction
"FUNCTION: Opener._newSplit() {{{1
function! s:Opener._newSplit()
" Save the user's settings for splitbelow and splitright
let savesplitbelow=&splitbelow
let savesplitright=&splitright
" 'there' will be set to a command to move from the split window
" back to the explorer window
"
" 'back' will be set to a command to move from the explorer window
" back to the newly split window
"
" 'right' and 'below' will be set to the settings needed for
" splitbelow and splitright IF the explorer is the only window.
"
let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l"
let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h"
let right= g:NERDTreeWinPos ==# "left"
let below=0
" Attempt to go to adjacent window
call nerdtree#exec(back)
let onlyOneWin = (winnr("$") ==# 1)
" If no adjacent window, set splitright and splitbelow appropriately
if onlyOneWin
let &splitright=right
let &splitbelow=below
else
" found adjacent window - invert split direction
let &splitright=!right
let &splitbelow=!below
endif
let splitMode = onlyOneWin ? "vertical" : ""
" Open the new window
try
exec(splitMode." sp ")
catch /^Vim\%((\a\+)\)\=:E37/
call nerdtree#putCursorInTreeWin()
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
catch /^Vim\%((\a\+)\)\=:/
"do nothing
endtry
"resize the tree window if no other window was open before
if onlyOneWin
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
call nerdtree#exec(there)
exec("silent ". splitMode ." resize ". size)
call nerdtree#exec('wincmd p')
endif
" Restore splitmode settings
let &splitbelow=savesplitbelow
let &splitright=savesplitright
endfunction
"FUNCTION: Opener._newVSplit() {{{1
function! s:Opener._newVSplit()
let winwidth = winwidth(".")
if winnr("$")==#1
let winwidth = g:NERDTreeWinSize
endif
call nerdtree#exec("wincmd p")
vnew
"resize the nerd tree back to the original size
call nerdtree#putCursorInTreeWin()
exec("silent vertical resize ". winwidth)
call nerdtree#exec('wincmd p')
endfunction
"FUNCTION: Opener.open(target) {{{1
function! s:Opener.open(target)
if self._path.isDirectory
call self._openDirectory(a:target)
else
call self._openFile()
endif
endfunction
"FUNCTION: Opener._openFile() {{{1
function! s:Opener._openFile()
if self._reuse && self._reuseWindow()
return
endif
call self._gotoTargetWin()
if self._treetype ==# "secondary"
call self._path.edit()
else
call self._path.edit()
if self._stay
call self._restoreCursorPos()
endif
endif
endfunction
"FUNCTION: Opener._openDirectory(node) {{{1
function! s:Opener._openDirectory(node)
if self._treetype ==# "secondary"
call self._gotoTargetWin()
call g:NERDTreeCreator.CreateSecondary(a:node.path.str())
else
call self._gotoTargetWin()
if empty(self._where)
call a:node.makeRoot()
call nerdtree#renderView()
call a:node.putCursorHere(0, 0)
elseif self._where == 't'
call g:NERDTreeCreator.CreatePrimary(a:node.path.str())
else
call g:NERDTreeCreator.CreateSecondary(a:node.path.str())
endif
endif
if self._stay
call self._restoreCursorPos()
endif
endfunction
"FUNCTION: Opener._previousWindow() {{{1
function! s:Opener._previousWindow()
if !nerdtree#isWindowUsable(winnr("#")) && nerdtree#firstUsableWindow() ==# -1
call self._newSplit()
else
try
if !nerdtree#isWindowUsable(winnr("#"))
call nerdtree#exec(nerdtree#firstUsableWindow() . "wincmd w")
else
call nerdtree#exec('wincmd p')
endif
catch /^Vim\%((\a\+)\)\=:E37/
call nerdtree#putCursorInTreeWin()
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
catch /^Vim\%((\a\+)\)\=:/
echo v:exception
endtry
endif
endfunction
"FUNCTION: Opener._restoreCursorPos(){{{1
function! s:Opener._restoreCursorPos()
call nerdtree#exec('normal ' . self._tabnr . 'gt')
call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w')
endfunction
"FUNCTION: Opener._reuseWindow(){{{1
"put the cursor in the first window we find for this file
"
"return 1 if we were successful
function! s:Opener._reuseWindow()
"check the current tab for the window
let winnr = bufwinnr('^' . self._path.str() . '$')
if winnr != -1
call nerdtree#exec(winnr . "wincmd w")
call self._checkToCloseTree(0)
return 1
else
"check other tabs
let tabnr = self._path.tabnr()
if tabnr
call self._checkToCloseTree(1)
call nerdtree#exec('normal! ' . tabnr . 'gt')
let winnr = bufwinnr('^' . self._path.str() . '$')
call nerdtree#exec(winnr . "wincmd w")
return 1
endif
endif
return 0
endfunction
"FUNCTION: Opener._saveCursorPos(){{{1
function! s:Opener._saveCursorPos()
let self._bufnr = bufnr("")
let self._tabnr = tabpagenr()
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,724 +0,0 @@
"we need to use this number many times for sorting... so we calculate it only
"once here
let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
"CLASS: Path
"============================================================
let s:Path = {}
let g:NERDTreePath = s:Path
"FUNCTION: Path.AbsolutePathFor(str) {{{1
function! s:Path.AbsolutePathFor(str)
let prependCWD = 0
if nerdtree#runningWindows()
let prependCWD = a:str !~# '^.:\(\\\|\/\)' && a:str !~# '^\(\\\\\|\/\/\)'
else
let prependCWD = a:str !~# '^/'
endif
let toReturn = a:str
if prependCWD
let toReturn = getcwd() . s:Path.Slash() . a:str
endif
return toReturn
endfunction
"FUNCTION: Path.bookmarkNames() {{{1
function! s:Path.bookmarkNames()
if !exists("self._bookmarkNames")
call self.cacheDisplayString()
endif
return self._bookmarkNames
endfunction
"FUNCTION: Path.cacheDisplayString() {{{1
function! s:Path.cacheDisplayString()
let self.cachedDisplayString = self.getLastPathComponent(1)
if self.isExecutable
let self.cachedDisplayString = self.cachedDisplayString . '*'
endif
let self._bookmarkNames = []
for i in g:NERDTreeBookmark.Bookmarks()
if i.path.equals(self)
call add(self._bookmarkNames, i.name)
endif
endfor
if !empty(self._bookmarkNames)
let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
endif
if self.isSymLink
let self.cachedDisplayString .= ' -> ' . self.symLinkDest
endif
if self.isReadOnly
let self.cachedDisplayString .= ' [RO]'
endif
endfunction
"FUNCTION: Path.changeToDir() {{{1
function! s:Path.changeToDir()
let dir = self.str({'format': 'Cd'})
if self.isDirectory ==# 0
let dir = self.getParent().str({'format': 'Cd'})
endif
try
execute "cd " . dir
call nerdtree#echo("CWD is now: " . getcwd())
catch
throw "NERDTree.PathChangeError: cannot change CWD to " . dir
endtry
endfunction
"FUNCTION: Path.compareTo() {{{1
"
"Compares this Path to the given path and returns 0 if they are equal, -1 if
"this Path is "less than" the given path, or 1 if it is "greater".
"
"Args:
"path: the path object to compare this to
"
"Return:
"1, -1 or 0
function! s:Path.compareTo(path)
let thisPath = self.getLastPathComponent(1)
let thatPath = a:path.getLastPathComponent(1)
"if the paths are the same then clearly we return 0
if thisPath ==# thatPath
return 0
endif
let thisSS = self.getSortOrderIndex()
let thatSS = a:path.getSortOrderIndex()
"compare the sort sequences, if they are different then the return
"value is easy
if thisSS < thatSS
return -1
elseif thisSS > thatSS
return 1
else
"if the sort sequences are the same then compare the paths
"alphabetically
let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
if pathCompare
return -1
else
return 1
endif
endif
endfunction
"FUNCTION: Path.Create(fullpath) {{{1
"
"Factory method.
"
"Creates a path object with the given path. The path is also created on the
"filesystem. If the path already exists, a NERDTree.Path.Exists exception is
"thrown. If any other errors occur, a NERDTree.Path exception is thrown.
"
"Args:
"fullpath: the full filesystem path to the file/dir to create
function! s:Path.Create(fullpath)
"bail if the a:fullpath already exists
if isdirectory(a:fullpath) || filereadable(a:fullpath)
throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'"
endif
try
"if it ends with a slash, assume its a dir create it
if a:fullpath =~# '\(\\\|\/\)$'
"whack the trailing slash off the end if it exists
let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '')
call mkdir(fullpath, 'p')
"assume its a file and create
else
call writefile([], a:fullpath)
endif
catch
throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'"
endtry
return s:Path.New(a:fullpath)
endfunction
"FUNCTION: Path.copy(dest) {{{1
"
"Copies the file/dir represented by this Path to the given location
"
"Args:
"dest: the location to copy this dir/file to
function! s:Path.copy(dest)
if !s:Path.CopyingSupported()
throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS"
endif
let dest = s:Path.WinToUnixPath(a:dest)
let cmd = g:NERDTreeCopyCmd . " " . escape(self.str(), nerdtree#escChars()) . " " . escape(dest, nerdtree#escChars())
let success = system(cmd)
if success != 0
throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'"
endif
endfunction
"FUNCTION: Path.CopyingSupported() {{{1
"
"returns 1 if copying is supported for this OS
function! s:Path.CopyingSupported()
return exists('g:NERDTreeCopyCmd')
endfunction
"FUNCTION: Path.copyingWillOverwrite(dest) {{{1
"
"returns 1 if copy this path to the given location will cause files to
"overwritten
"
"Args:
"dest: the location this path will be copied to
function! s:Path.copyingWillOverwrite(dest)
if filereadable(a:dest)
return 1
endif
if isdirectory(a:dest)
let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0))
if filereadable(path)
return 1
endif
endif
endfunction
"FUNCTION: Path.delete() {{{1
"
"Deletes the file represented by this path.
"Deletion of directories is not supported
"
"Throws NERDTree.Path.Deletion exceptions
function! s:Path.delete()
if self.isDirectory
let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1})
let success = system(cmd)
if v:shell_error != 0
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
endif
else
let success = delete(self.str())
if success != 0
throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
endif
endif
"delete all bookmarks for this path
for i in self.bookmarkNames()
let bookmark = g:NERDTreeBookmark.BookmarkFor(i)
call bookmark.delete()
endfor
endfunction
"FUNCTION: Path.displayString() {{{1
"
"Returns a string that specifies how the path should be represented as a
"string
function! s:Path.displayString()
if self.cachedDisplayString ==# ""
call self.cacheDisplayString()
endif
return self.cachedDisplayString
endfunction
"FUNCTION: Path.edit() {{{1
function! s:Path.edit()
exec "edit " . self.str({'format': 'Edit'})
endfunction
"FUNCTION: Path.extractDriveLetter(fullpath) {{{1
"
"If running windows, cache the drive letter for this path
function! s:Path.extractDriveLetter(fullpath)
if nerdtree#runningWindows()
if a:fullpath =~ '^\(\\\\\|\/\/\)'
"For network shares, the 'drive' consists of the first two parts of the path, i.e. \\boxname\share
let self.drive = substitute(a:fullpath, '^\(\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\).*', '\1', '')
let self.drive = substitute(self.drive, '/', '\', "g")
else
let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '')
endif
else
let self.drive = ''
endif
endfunction
"FUNCTION: Path.exists() {{{1
"return 1 if this path points to a location that is readable or is a directory
function! s:Path.exists()
let p = self.str()
return filereadable(p) || isdirectory(p)
endfunction
"FUNCTION: Path.getDir() {{{1
"
"Returns this path if it is a directory, else this paths parent.
"
"Return:
"a Path object
function! s:Path.getDir()
if self.isDirectory
return self
else
return self.getParent()
endif
endfunction
"FUNCTION: Path.getParent() {{{1
"
"Returns a new path object for this paths parent
"
"Return:
"a new Path object
function! s:Path.getParent()
if nerdtree#runningWindows()
let path = self.drive . '\' . join(self.pathSegments[0:-2], '\')
else
let path = '/'. join(self.pathSegments[0:-2], '/')
endif
return s:Path.New(path)
endfunction
"FUNCTION: Path.getLastPathComponent(dirSlash) {{{1
"
"Gets the last part of this path.
"
"Args:
"dirSlash: if 1 then a trailing slash will be added to the returned value for
"directory nodes.
function! s:Path.getLastPathComponent(dirSlash)
if empty(self.pathSegments)
return ''
endif
let toReturn = self.pathSegments[-1]
if a:dirSlash && self.isDirectory
let toReturn = toReturn . '/'
endif
return toReturn
endfunction
"FUNCTION: Path.getSortOrderIndex() {{{1
"returns the index of the pattern in g:NERDTreeSortOrder that this path matches
function! s:Path.getSortOrderIndex()
let i = 0
while i < len(g:NERDTreeSortOrder)
if self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i]
return i
endif
let i = i + 1
endwhile
return s:NERDTreeSortStarIndex
endfunction
"FUNCTION: Path.isUnixHiddenFile() {{{1
"check for unix hidden files
function! s:Path.isUnixHiddenFile()
return self.getLastPathComponent(0) =~# '^\.'
endfunction
"FUNCTION: Path.isUnixHiddenPath() {{{1
"check for unix path with hidden components
function! s:Path.isUnixHiddenPath()
if self.getLastPathComponent(0) =~# '^\.'
return 1
else
for segment in self.pathSegments
if segment =~# '^\.'
return 1
endif
endfor
return 0
endif
endfunction
"FUNCTION: Path.ignore() {{{1
"returns true if this path should be ignored
function! s:Path.ignore()
"filter out the user specified paths to ignore
if b:NERDTreeIgnoreEnabled
for i in g:NERDTreeIgnore
if self._ignorePatternMatches(i)
return 1
endif
endfor
endif
"dont show hidden files unless instructed to
if b:NERDTreeShowHidden ==# 0 && self.isUnixHiddenFile()
return 1
endif
if b:NERDTreeShowFiles ==# 0 && self.isDirectory ==# 0
return 1
endif
if exists("*NERDTreeCustomIgnoreFilter") && NERDTreeCustomIgnoreFilter(self)
return 1
endif
return 0
endfunction
"FUNCTION: Path._ignorePatternMatches(pattern) {{{1
"returns true if this path matches the given ignore pattern
function! s:Path._ignorePatternMatches(pattern)
let pat = a:pattern
if strpart(pat,len(pat)-7) == '[[dir]]'
if !self.isDirectory
return 0
endif
let pat = strpart(pat,0, len(pat)-7)
elseif strpart(pat,len(pat)-8) == '[[file]]'
if self.isDirectory
return 0
endif
let pat = strpart(pat,0, len(pat)-8)
endif
return self.getLastPathComponent(0) =~# pat
endfunction
"FUNCTION: Path.isUnder(path) {{{1
"return 1 if this path is somewhere under the given path in the filesystem.
"
"a:path should be a dir
function! s:Path.isUnder(path)
if a:path.isDirectory == 0
return 0
endif
let this = self.str()
let that = a:path.str()
return stridx(this, that . s:Path.Slash()) == 0
endfunction
"FUNCTION: Path.JoinPathStrings(...) {{{1
function! s:Path.JoinPathStrings(...)
let components = []
for i in a:000
let components = extend(components, split(i, '/'))
endfor
return '/' . join(components, '/')
endfunction
"FUNCTION: Path.equals() {{{1
"
"Determines whether 2 path objects are "equal".
"They are equal if the paths they represent are the same
"
"Args:
"path: the other path obj to compare this with
function! s:Path.equals(path)
return self.str() ==# a:path.str()
endfunction
"FUNCTION: Path.New() {{{1
"The Constructor for the Path object
function! s:Path.New(path)
let newPath = copy(self)
call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path))
let newPath.cachedDisplayString = ""
return newPath
endfunction
"FUNCTION: Path.Slash() {{{1
"return the slash to use for the current OS
function! s:Path.Slash()
return nerdtree#runningWindows() ? '\' : '/'
endfunction
"FUNCTION: Path.Resolve() {{{1
"Invoke the vim resolve() function and return the result
"This is necessary because in some versions of vim resolve() removes trailing
"slashes while in other versions it doesn't. This always removes the trailing
"slash
function! s:Path.Resolve(path)
let tmp = resolve(a:path)
return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp
endfunction
"FUNCTION: Path.readInfoFromDisk(fullpath) {{{1
"
"
"Throws NERDTree.Path.InvalidArguments exception.
function! s:Path.readInfoFromDisk(fullpath)
call self.extractDriveLetter(a:fullpath)
let fullpath = s:Path.WinToUnixPath(a:fullpath)
if getftype(fullpath) ==# "fifo"
throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath
endif
let self.pathSegments = split(fullpath, '/')
let self.isReadOnly = 0
if isdirectory(a:fullpath)
let self.isDirectory = 1
elseif filereadable(a:fullpath)
let self.isDirectory = 0
let self.isReadOnly = filewritable(a:fullpath) ==# 0
else
throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath
endif
let self.isExecutable = 0
if !self.isDirectory
let self.isExecutable = getfperm(a:fullpath) =~# 'x'
endif
"grab the last part of the path (minus the trailing slash)
let lastPathComponent = self.getLastPathComponent(0)
"get the path to the new node with the parent dir fully resolved
let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent
"if the last part of the path is a symlink then flag it as such
let self.isSymLink = (s:Path.Resolve(hardPath) != hardPath)
if self.isSymLink
let self.symLinkDest = s:Path.Resolve(fullpath)
"if the link is a dir then slap a / on the end of its dest
if isdirectory(self.symLinkDest)
"we always wanna treat MS windows shortcuts as files for
"simplicity
if hardPath !~# '\.lnk$'
let self.symLinkDest = self.symLinkDest . '/'
endif
endif
endif
endfunction
"FUNCTION: Path.refresh() {{{1
function! s:Path.refresh()
call self.readInfoFromDisk(self.str())
call self.cacheDisplayString()
endfunction
"FUNCTION: Path.rename() {{{1
"
"Renames this node on the filesystem
function! s:Path.rename(newPath)
if a:newPath ==# ''
throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath
endif
let success = rename(self.str(), a:newPath)
if success != 0
throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath
endif
call self.readInfoFromDisk(a:newPath)
for i in self.bookmarkNames()
let b = g:NERDTreeBookmark.BookmarkFor(i)
call b.setPath(copy(self))
endfor
call g:NERDTreeBookmark.Write()
endfunction
"FUNCTION: Path.str() {{{1
"
"Returns a string representation of this Path
"
"Takes an optional dictionary param to specify how the output should be
"formatted.
"
"The dict may have the following keys:
" 'format'
" 'escape'
" 'truncateTo'
"
"The 'format' key may have a value of:
" 'Cd' - a string to be used with the :cd command
" 'Edit' - a string to be used with :e :sp :new :tabedit etc
" 'UI' - a string used in the NERD tree UI
"
"The 'escape' key, if specified will cause the output to be escaped with
"shellescape()
"
"The 'truncateTo' key causes the resulting string to be truncated to the value
"'truncateTo' maps to. A '<' char will be prepended.
function! s:Path.str(...)
let options = a:0 ? a:1 : {}
let toReturn = ""
if has_key(options, 'format')
let format = options['format']
if has_key(self, '_strFor' . format)
exec 'let toReturn = self._strFor' . format . '()'
else
raise 'NERDTree.UnknownFormatError: unknown format "'. format .'"'
endif
else
let toReturn = self._str()
endif
if nerdtree#has_opt(options, 'escape')
let toReturn = shellescape(toReturn)
endif
if has_key(options, 'truncateTo')
let limit = options['truncateTo']
if len(toReturn) > limit
let toReturn = "<" . strpart(toReturn, len(toReturn) - limit + 1)
endif
endif
return toReturn
endfunction
"FUNCTION: Path._strForUI() {{{1
function! s:Path._strForUI()
let toReturn = '/' . join(self.pathSegments, '/')
if self.isDirectory && toReturn != '/'
let toReturn = toReturn . '/'
endif
return toReturn
endfunction
"FUNCTION: Path._strForCd() {{{1
"
" returns a string that can be used with :cd
function! s:Path._strForCd()
return escape(self.str(), nerdtree#escChars())
endfunction
"FUNCTION: Path._strForEdit() {{{1
"
"Return: the string for this path that is suitable to be used with the :edit
"command
function! s:Path._strForEdit()
let p = escape(self.str({'format': 'UI'}), nerdtree#escChars())
let cwd = getcwd() . s:Path.Slash()
"return a relative path if we can
let isRelative = 0
if nerdtree#runningWindows()
let isRelative = stridx(tolower(p), tolower(cwd)) == 0
else
let isRelative = stridx(p, cwd) == 0
endif
if isRelative
let p = strpart(p, strlen(cwd))
"handle the edge case where the file begins with a + (vim interprets
"the +foo in `:e +foo` as an option to :edit)
if p[0] == "+"
let p = '\' . p
endif
endif
if p ==# ''
let p = '.'
endif
return p
endfunction
"FUNCTION: Path._strForGlob() {{{1
function! s:Path._strForGlob()
let lead = s:Path.Slash()
"if we are running windows then slap a drive letter on the front
if nerdtree#runningWindows()
let lead = self.drive . '\'
endif
let toReturn = lead . join(self.pathSegments, s:Path.Slash())
if !nerdtree#runningWindows()
let toReturn = escape(toReturn, nerdtree#escChars())
endif
return toReturn
endfunction
"FUNCTION: Path._str() {{{1
"
"Gets the string path for this path object that is appropriate for the OS.
"EG, in windows c:\foo\bar
" in *nix /foo/bar
function! s:Path._str()
let lead = s:Path.Slash()
"if we are running windows then slap a drive letter on the front
if nerdtree#runningWindows()
let lead = self.drive . '\'
endif
return lead . join(self.pathSegments, s:Path.Slash())
endfunction
"FUNCTION: Path.strTrunk() {{{1
"Gets the path without the last segment on the end.
function! s:Path.strTrunk()
return self.drive . '/' . join(self.pathSegments[0:-2], '/')
endfunction
" FUNCTION: Path.tabnr() {{{1
" return the number of the first tab that is displaying this file
"
" return 0 if no tab was found
function! s:Path.tabnr()
let str = self.str()
for t in range(tabpagenr('$'))
for b in tabpagebuflist(t+1)
if str == expand('#' . b . ':p')
return t+1
endif
endfor
endfor
return 0
endfunction
"FUNCTION: Path.WinToUnixPath(pathstr){{{1
"Takes in a windows path and returns the unix equiv
"
"A class level method
"
"Args:
"pathstr: the windows path to convert
function! s:Path.WinToUnixPath(pathstr)
if !nerdtree#runningWindows()
return a:pathstr
endif
let toReturn = a:pathstr
"remove the x:\ of the front
let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "")
"remove the \\ network share from the front
let toReturn = substitute(toReturn, '^\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\(\\\|\/\)\?', '/', "")
"convert all \ chars to /
let toReturn = substitute(toReturn, '\', '/', "g")
return toReturn
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,528 +0,0 @@
"CLASS: TreeDirNode
"A subclass of NERDTreeFileNode.
"
"The 'composite' part of the file/dir composite.
"============================================================
let s:TreeDirNode = copy(g:NERDTreeFileNode)
let g:NERDTreeDirNode = s:TreeDirNode
"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
"class method that returns the highest cached ancestor of the current root
function! s:TreeDirNode.AbsoluteTreeRoot()
let currentNode = b:NERDTreeRoot
while currentNode.parent != {}
let currentNode = currentNode.parent
endwhile
return currentNode
endfunction
"FUNCTION: TreeDirNode.activate([options]) {{{1
unlet s:TreeDirNode.activate
function! s:TreeDirNode.activate(...)
let opts = a:0 ? a:1 : {}
call self.toggleOpen(opts)
call nerdtree#renderView()
call self.putCursorHere(0, 0)
endfunction
"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
"Adds the given treenode to the list of children for this node
"
"Args:
"-treenode: the node to add
"-inOrder: 1 if the new node should be inserted in sorted order
function! s:TreeDirNode.addChild(treenode, inOrder)
call add(self.children, a:treenode)
let a:treenode.parent = self
if a:inOrder
call self.sortChildren()
endif
endfunction
"FUNCTION: TreeDirNode.close() {{{1
"Closes this directory
function! s:TreeDirNode.close()
let self.isOpen = 0
endfunction
"FUNCTION: TreeDirNode.closeChildren() {{{1
"Closes all the child dir nodes of this node
function! s:TreeDirNode.closeChildren()
for i in self.children
if i.path.isDirectory
call i.close()
call i.closeChildren()
endif
endfor
endfunction
"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
"Instantiates a new child node for this node with the given path. The new
"nodes parent is set to this node.
"
"Args:
"path: a Path object that this node will represent/contain
"inOrder: 1 if the new node should be inserted in sorted order
"
"Returns:
"the newly created node
function! s:TreeDirNode.createChild(path, inOrder)
let newTreeNode = g:NERDTreeFileNode.New(a:path)
call self.addChild(newTreeNode, a:inOrder)
return newTreeNode
endfunction
"FUNCTION: TreeDirNode.findNode(path) {{{1
"Will find one of the children (recursively) that has the given path
"
"Args:
"path: a path object
unlet s:TreeDirNode.findNode
function! s:TreeDirNode.findNode(path)
if a:path.equals(self.path)
return self
endif
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return {}
endif
if self.path.isDirectory
for i in self.children
let retVal = i.findNode(a:path)
if retVal != {}
return retVal
endif
endfor
endif
return {}
endfunction
"FUNCTION: TreeDirNode.getChildCount() {{{1
"Returns the number of children this node has
function! s:TreeDirNode.getChildCount()
return len(self.children)
endfunction
"FUNCTION: TreeDirNode.getChild(path) {{{1
"Returns child node of this node that has the given path or {} if no such node
"exists.
"
"This function doesnt not recurse into child dir nodes
"
"Args:
"path: a path object
function! s:TreeDirNode.getChild(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return {}
endif
let index = self.getChildIndex(a:path)
if index ==# -1
return {}
else
return self.children[index]
endif
endfunction
"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
"returns the child at the given index
"Args:
"indx: the index to get the child from
"visible: 1 if only the visible children array should be used, 0 if all the
"children should be searched.
function! s:TreeDirNode.getChildByIndex(indx, visible)
let array_to_search = a:visible? self.getVisibleChildren() : self.children
if a:indx > len(array_to_search)
throw "NERDTree.InvalidArgumentsError: Index is out of bounds."
endif
return array_to_search[a:indx]
endfunction
"FUNCTION: TreeDirNode.getChildIndex(path) {{{1
"Returns the index of the child node of this node that has the given path or
"-1 if no such node exists.
"
"This function doesnt not recurse into child dir nodes
"
"Args:
"path: a path object
function! s:TreeDirNode.getChildIndex(path)
if stridx(a:path.str(), self.path.str(), 0) ==# -1
return -1
endif
"do a binary search for the child
let a = 0
let z = self.getChildCount()
while a < z
let mid = (a+z)/2
let diff = a:path.compareTo(self.children[mid].path)
if diff ==# -1
let z = mid
elseif diff ==# 1
let a = mid+1
else
return mid
endif
endwhile
return -1
endfunction
"FUNCTION: TreeDirNode.GetSelected() {{{1
"Returns the current node if it is a dir node, or else returns the current
"nodes parent
unlet s:TreeDirNode.GetSelected
function! s:TreeDirNode.GetSelected()
let currentDir = g:NERDTreeFileNode.GetSelected()
if currentDir != {} && !currentDir.isRoot()
if currentDir.path.isDirectory ==# 0
let currentDir = currentDir.parent
endif
endif
return currentDir
endfunction
"FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
"Returns the number of visible children this node has
function! s:TreeDirNode.getVisibleChildCount()
return len(self.getVisibleChildren())
endfunction
"FUNCTION: TreeDirNode.getVisibleChildren() {{{1
"Returns a list of children to display for this node, in the correct order
"
"Return:
"an array of treenodes
function! s:TreeDirNode.getVisibleChildren()
let toReturn = []
for i in self.children
if i.path.ignore() ==# 0
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
"returns 1 if this node has any childre, 0 otherwise..
function! s:TreeDirNode.hasVisibleChildren()
return self.getVisibleChildCount() != 0
endfunction
"FUNCTION: TreeDirNode._initChildren() {{{1
"Removes all childen from this node and re-reads them
"
"Args:
"silent: 1 if the function should not echo any "please wait" messages for
"large directories
"
"Return: the number of child nodes read
function! s:TreeDirNode._initChildren(silent)
"remove all the current child nodes
let self.children = []
"get an array of all the files in the nodes dir
let dir = self.path
let globDir = dir.str({'format': 'Glob'})
if version >= 703
let filesStr = globpath(globDir, '*', 1) . "\n" . globpath(globDir, '.*', 1)
else
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
endif
let files = split(filesStr, "\n")
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ...")
endif
let invalidFilesFound = 0
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ cos sometimes the globpath returns
"../ for path with strange chars (eg $)
if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
"put the next file in a new node and attach it
try
let path = g:NERDTreePath.New(i)
call self.createChild(path, 0)
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1
endtry
endif
endfor
call self.sortChildren()
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
call nerdtree#echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).")
endif
if invalidFilesFound
call nerdtree#echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
endif
return self.getChildCount()
endfunction
"FUNCTION: TreeDirNode.New(path) {{{1
"Returns a new TreeNode object with the given path and parent
"
"Args:
"path: a path object representing the full filesystem path to the file/dir that the node represents
unlet s:TreeDirNode.New
function! s:TreeDirNode.New(path)
if a:path.isDirectory != 1
throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object."
endif
let newTreeNode = copy(self)
let newTreeNode.path = a:path
let newTreeNode.isOpen = 0
let newTreeNode.children = []
let newTreeNode.parent = {}
return newTreeNode
endfunction
"FUNCTION: TreeDirNode.open([opts]) {{{1
"Open the dir in the current tree or in a new tree elsewhere.
"
"If opening in the current tree, return the number of cached nodes.
unlet s:TreeDirNode.open
function! s:TreeDirNode.open(...)
let opts = a:0 ? a:1 : {}
if has_key(opts, 'where') && !empty(opts['where'])
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
else
let self.isOpen = 1
if self.children ==# []
return self._initChildren(0)
else
return 0
endif
endif
endfunction
"FUNCTION: TreeDirNode.openAlong([opts]) {{{1
"recursive open the dir if it has only one directory child.
"
"return the level of opened directories.
function! s:TreeDirNode.openAlong(...)
let opts = a:0 ? a:1 : {}
let level = 0
let node = self
while node.path.isDirectory
call node.open(opts)
let level += 1
if node.getVisibleChildCount() == 1
let node = node.getChildByIndex(0, 1)
else
break
endif
endwhile
return level
endfunction
" FUNCTION: TreeDirNode.openExplorer() {{{1
" opens an explorer window for this node in the previous window (could be a
" nerd tree or a netrw)
function! s:TreeDirNode.openExplorer()
call self.open({'where': 'p'})
endfunction
"FUNCTION: TreeDirNode.openInNewTab(options) {{{1
unlet s:TreeDirNode.openInNewTab
function! s:TreeDirNode.openInNewTab(options)
call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead')
call self.open({'where': 't'})
endfunction
"FUNCTION: TreeDirNode._openInNewTab() {{{1
function! s:TreeDirNode._openInNewTab()
tabnew
call g:NERDTreeCreator.CreatePrimary(self.path.str())
endfunction
"FUNCTION: TreeDirNode.openRecursively() {{{1
"Opens this treenode and all of its children whose paths arent 'ignored'
"because of the file filters.
"
"This method is actually a wrapper for the OpenRecursively2 method which does
"the work.
function! s:TreeDirNode.openRecursively()
call self._openRecursively2(1)
endfunction
"FUNCTION: TreeDirNode._openRecursively2() {{{1
"Opens this all children of this treenode recursively if either:
" *they arent filtered by file filters
" *a:forceOpen is 1
"
"Args:
"forceOpen: 1 if this node should be opened regardless of file filters
function! s:TreeDirNode._openRecursively2(forceOpen)
if self.path.ignore() ==# 0 || a:forceOpen
let self.isOpen = 1
if self.children ==# []
call self._initChildren(1)
endif
for i in self.children
if i.path.isDirectory ==# 1
call i._openRecursively2(0)
endif
endfor
endif
endfunction
"FUNCTION: TreeDirNode.refresh() {{{1
unlet s:TreeDirNode.refresh
function! s:TreeDirNode.refresh()
call self.path.refresh()
"if this node was ever opened, refresh its children
if self.isOpen || !empty(self.children)
"go thru all the files/dirs under this node
let newChildNodes = []
let invalidFilesFound = 0
let dir = self.path
let globDir = dir.str({'format': 'Glob'})
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
let files = split(filesStr, "\n")
for i in files
"filter out the .. and . directories
"Note: we must match .. AND ../ cos sometimes the globpath returns
"../ for path with strange chars (eg $)
if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
try
"create a new path and see if it exists in this nodes children
let path = g:NERDTreePath.New(i)
let newNode = self.getChild(path)
if newNode != {}
call newNode.refresh()
call add(newChildNodes, newNode)
"the node doesnt exist so create it
else
let newNode = g:NERDTreeFileNode.New(path)
let newNode.parent = self
call add(newChildNodes, newNode)
endif
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound = 1
endtry
endif
endfor
"swap this nodes children out for the children we just read/refreshed
let self.children = newChildNodes
call self.sortChildren()
if invalidFilesFound
call nerdtree#echoWarning("some files could not be loaded into the NERD tree")
endif
endif
endfunction
"FUNCTION: TreeDirNode.reveal(path) {{{1
"reveal the given path, i.e. cache and open all treenodes needed to display it
"in the UI
function! s:TreeDirNode.reveal(path)
if !a:path.isUnder(self.path)
throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str()
endif
call self.open()
if self.path.equals(a:path.getParent())
let n = self.findNode(a:path)
call nerdtree#renderView()
call n.putCursorHere(1,0)
return
endif
let p = a:path
while !p.getParent().equals(self.path)
let p = p.getParent()
endwhile
let n = self.findNode(p)
call n.reveal(a:path)
endfunction
"FUNCTION: TreeDirNode.removeChild(treenode) {{{1
"
"Removes the given treenode from this nodes set of children
"
"Args:
"treenode: the node to remove
"
"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
function! s:TreeDirNode.removeChild(treenode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:treenode)
call remove(self.children, i)
return
endif
endfor
throw "NERDTree.ChildNotFoundError: child node was not found"
endfunction
"FUNCTION: TreeDirNode.sortChildren() {{{1
"
"Sorts the children of this node according to alphabetical order and the
"directory priority.
"
function! s:TreeDirNode.sortChildren()
let CompareFunc = function("nerdtree#compareNodes")
call sort(self.children, CompareFunc)
endfunction
"FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
"Opens this directory if it is closed and vice versa
function! s:TreeDirNode.toggleOpen(...)
let opts = a:0 ? a:1 : {}
if self.isOpen ==# 1
call self.close()
else
if g:NERDTreeCasadeOpenSingleChildDir == 0
call self.open(opts)
else
call self.openAlong(opts)
endif
endif
endfunction
"FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
"Replaces the child of this with the given node (where the child node's full
"path matches a:newNode's fullpath). The search for the matching node is
"non-recursive
"
"Arg:
"newNode: the node to graft into the tree
function! s:TreeDirNode.transplantChild(newNode)
for i in range(0, self.getChildCount()-1)
if self.children[i].equals(a:newNode)
let self.children[i] = a:newNode
let a:newNode.parent = self
break
endif
endfor
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,485 +0,0 @@
"CLASS: TreeFileNode
"This class is the parent of the TreeDirNode class and is the
"'Component' part of the composite design pattern between the treenode
"classes.
"============================================================
let s:TreeFileNode = {}
let g:NERDTreeFileNode = s:TreeFileNode
"FUNCTION: TreeFileNode.activate(...) {{{1
function! s:TreeFileNode.activate(...)
call self.open(a:0 ? a:1 : {})
endfunction
"FUNCTION: TreeFileNode.bookmark(name) {{{1
"bookmark this node with a:name
function! s:TreeFileNode.bookmark(name)
"if a bookmark exists with the same name and the node is cached then save
"it so we can update its display string
let oldMarkedNode = {}
try
let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1)
catch /^NERDTree.BookmarkNotFoundError/
catch /^NERDTree.BookmarkedNodeNotFoundError/
endtry
call g:NERDTreeBookmark.AddBookmark(a:name, self.path)
call self.path.cacheDisplayString()
call g:NERDTreeBookmark.Write()
if !empty(oldMarkedNode)
call oldMarkedNode.path.cacheDisplayString()
endif
endfunction
"FUNCTION: TreeFileNode.cacheParent() {{{1
"initializes self.parent if it isnt already
function! s:TreeFileNode.cacheParent()
if empty(self.parent)
let parentPath = self.path.getParent()
if parentPath.equals(self.path)
throw "NERDTree.CannotCacheParentError: already at root"
endif
let self.parent = s:TreeFileNode.New(parentPath)
endif
endfunction
"FUNCTION: TreeFileNode.clearBookmarks() {{{1
function! s:TreeFileNode.clearBookmarks()
for i in g:NERDTreeBookmark.Bookmarks()
if i.path.equals(self.path)
call i.delete()
end
endfor
call self.path.cacheDisplayString()
endfunction
"FUNCTION: TreeFileNode.copy(dest) {{{1
function! s:TreeFileNode.copy(dest)
call self.path.copy(a:dest)
let newPath = g:NERDTreePath.New(a:dest)
let parent = b:NERDTreeRoot.findNode(newPath.getParent())
if !empty(parent)
call parent.refresh()
return parent.findNode(newPath)
else
return {}
endif
endfunction
"FUNCTION: TreeFileNode.delete {{{1
"Removes this node from the tree and calls the Delete method for its path obj
function! s:TreeFileNode.delete()
call self.path.delete()
call self.parent.removeChild(self)
endfunction
"FUNCTION: TreeFileNode.displayString() {{{1
"
"Returns a string that specifies how the node should be represented as a
"string
"
"Return:
"a string that can be used in the view to represent this node
function! s:TreeFileNode.displayString()
return self.path.displayString()
endfunction
"FUNCTION: TreeFileNode.equals(treenode) {{{1
"
"Compares this treenode to the input treenode and returns 1 if they are the
"same node.
"
"Use this method instead of == because sometimes when the treenodes contain
"many children, vim seg faults when doing ==
"
"Args:
"treenode: the other treenode to compare to
function! s:TreeFileNode.equals(treenode)
return self.path.str() ==# a:treenode.path.str()
endfunction
"FUNCTION: TreeFileNode.findNode(path) {{{1
"Returns self if this node.path.Equals the given path.
"Returns {} if not equal.
"
"Args:
"path: the path object to compare against
function! s:TreeFileNode.findNode(path)
if a:path.equals(self.path)
return self
endif
return {}
endfunction
"FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{1
"
"Finds the next sibling for this node in the indicated direction. This sibling
"must be a directory and may/may not have children as specified.
"
"Args:
"direction: 0 if you want to find the previous sibling, 1 for the next sibling
"
"Return:
"a treenode object or {} if no appropriate sibling could be found
function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction)
"if we have no parent then we can have no siblings
if self.parent != {}
let nextSibling = self.findSibling(a:direction)
while nextSibling != {}
if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen
return nextSibling
endif
let nextSibling = nextSibling.findSibling(a:direction)
endwhile
endif
return {}
endfunction
"FUNCTION: TreeFileNode.findSibling(direction) {{{1
"
"Finds the next sibling for this node in the indicated direction
"
"Args:
"direction: 0 if you want to find the previous sibling, 1 for the next sibling
"
"Return:
"a treenode object or {} if no sibling could be found
function! s:TreeFileNode.findSibling(direction)
"if we have no parent then we can have no siblings
if self.parent != {}
"get the index of this node in its parents children
let siblingIndx = self.parent.getChildIndex(self.path)
if siblingIndx != -1
"move a long to the next potential sibling node
let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
"keep moving along to the next sibling till we find one that is valid
let numSiblings = self.parent.getChildCount()
while siblingIndx >= 0 && siblingIndx < numSiblings
"if the next node is not an ignored node (i.e. wont show up in the
"view) then return it
if self.parent.children[siblingIndx].path.ignore() ==# 0
return self.parent.children[siblingIndx]
endif
"go to next node
let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
endwhile
endif
endif
return {}
endfunction
"FUNCTION: TreeFileNode.getLineNum(){{{1
"returns the line number this node is rendered on, or -1 if it isnt rendered
function! s:TreeFileNode.getLineNum()
"if the node is the root then return the root line no.
if self.isRoot()
return s:TreeFileNode.GetRootLineNum()
endif
let totalLines = line("$")
"the path components we have matched so far
let pathcomponents = [substitute(b:NERDTreeRoot.path.str({'format': 'UI'}), '/ *$', '', '')]
"the index of the component we are searching for
let curPathComponent = 1
let fullpath = self.path.str({'format': 'UI'})
let lnum = s:TreeFileNode.GetRootLineNum()
while lnum > 0
let lnum = lnum + 1
"have we reached the bottom of the tree?
if lnum ==# totalLines+1
return -1
endif
let curLine = getline(lnum)
let indent = nerdtree#indentLevelFor(curLine)
if indent ==# curPathComponent
let curLine = nerdtree#stripMarkupFromLine(curLine, 1)
let curPath = join(pathcomponents, '/') . '/' . curLine
if stridx(fullpath, curPath, 0) ==# 0
if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/'
let curLine = substitute(curLine, '/ *$', '', '')
call add(pathcomponents, curLine)
let curPathComponent = curPathComponent + 1
if fullpath ==# curPath
return lnum
endif
endif
endif
endif
endwhile
return -1
endfunction
"FUNCTION: TreeFileNode.GetRootForTab(){{{1
"get the root node for this tab
function! s:TreeFileNode.GetRootForTab()
if nerdtree#treeExistsForTab()
return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot')
end
return {}
endfunction
"FUNCTION: TreeFileNode.GetRootLineNum(){{{1
"gets the line number of the root node
function! s:TreeFileNode.GetRootLineNum()
let rootLine = 1
while getline(rootLine) !~# '^\(/\|<\)'
let rootLine = rootLine + 1
endwhile
return rootLine
endfunction
"FUNCTION: TreeFileNode.GetSelected() {{{1
"gets the treenode that the cursor is currently over
function! s:TreeFileNode.GetSelected()
try
let path = nerdtree#getPath(line("."))
if path ==# {}
return {}
endif
return b:NERDTreeRoot.findNode(path)
catch /^NERDTree/
return {}
endtry
endfunction
"FUNCTION: TreeFileNode.isVisible() {{{1
"returns 1 if this node should be visible according to the tree filters and
"hidden file filters (and their on/off status)
function! s:TreeFileNode.isVisible()
return !self.path.ignore()
endfunction
"FUNCTION: TreeFileNode.isRoot() {{{1
"returns 1 if this node is b:NERDTreeRoot
function! s:TreeFileNode.isRoot()
if !nerdtree#treeExistsForBuf()
throw "NERDTree.NoTreeError: No tree exists for the current buffer"
endif
return self.equals(b:NERDTreeRoot)
endfunction
"FUNCTION: TreeFileNode.makeRoot() {{{1
"Make this node the root of the tree
function! s:TreeFileNode.makeRoot()
if self.path.isDirectory
let b:NERDTreeRoot = self
else
call self.cacheParent()
let b:NERDTreeRoot = self.parent
endif
call b:NERDTreeRoot.open()
"change dir to the dir of the new root if instructed to
if g:NERDTreeChDirMode ==# 2
exec "cd " . b:NERDTreeRoot.path.str({'format': 'Edit'})
endif
silent doautocmd User NERDTreeNewRoot
endfunction
"FUNCTION: TreeFileNode.New(path) {{{1
"Returns a new TreeNode object with the given path and parent
"
"Args:
"path: a path object representing the full filesystem path to the file/dir that the node represents
function! s:TreeFileNode.New(path)
if a:path.isDirectory
return g:NERDTreeDirNode.New(a:path)
else
let newTreeNode = copy(self)
let newTreeNode.path = a:path
let newTreeNode.parent = {}
return newTreeNode
endif
endfunction
"FUNCTION: TreeFileNode.open() {{{1
function! s:TreeFileNode.open(...)
let opts = a:0 ? a:1 : {}
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
endfunction
"FUNCTION: TreeFileNode.openSplit() {{{1
"Open this node in a new window
function! s:TreeFileNode.openSplit()
call nerdtree#deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.')
call self.open({'where': 'h'})
endfunction
"FUNCTION: TreeFileNode.openVSplit() {{{1
"Open this node in a new vertical window
function! s:TreeFileNode.openVSplit()
call nerdtree#deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.')
call self.open({'where': 'v'})
endfunction
"FUNCTION: TreeFileNode.openInNewTab(options) {{{1
function! s:TreeFileNode.openInNewTab(options)
echomsg 'TreeFileNode.openInNewTab is deprecated'
call self.open(extend({'where': 't'}, a:options))
endfunction
"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1
"Places the cursor on the line number this node is rendered on
"
"Args:
"isJump: 1 if this cursor movement should be counted as a jump by vim
"recurseUpward: try to put the cursor on the parent if the this node isnt
"visible
function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
let ln = self.getLineNum()
if ln != -1
if a:isJump
mark '
endif
call cursor(ln, col("."))
else
if a:recurseUpward
let node = self
while node != {} && node.getLineNum() ==# -1
let node = node.parent
call node.open()
endwhile
call nerdtree#renderView()
call node.putCursorHere(a:isJump, 0)
endif
endif
endfunction
"FUNCTION: TreeFileNode.refresh() {{{1
function! s:TreeFileNode.refresh()
call self.path.refresh()
endfunction
"FUNCTION: TreeFileNode.rename() {{{1
"Calls the rename method for this nodes path obj
function! s:TreeFileNode.rename(newName)
let newName = substitute(a:newName, '\(\\\|\/\)$', '', '')
call self.path.rename(newName)
call self.parent.removeChild(self)
let parentPath = self.path.getParent()
let newParent = b:NERDTreeRoot.findNode(parentPath)
if newParent != {}
call newParent.createChild(self.path, 1)
call newParent.refresh()
endif
endfunction
"FUNCTION: TreeFileNode.renderToString {{{1
"returns a string representation for this tree to be rendered in the view
function! s:TreeFileNode.renderToString()
return self._renderToString(0, 0, [], self.getChildCount() ==# 1)
endfunction
"Args:
"depth: the current depth in the tree for this call
"drawText: 1 if we should actually draw the line for this node (if 0 then the
"child nodes are rendered only)
"vertMap: a binary array that indicates whether a vertical bar should be draw
"for each depth in the tree
"isLastChild:true if this curNode is the last child of its parent
function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild)
let output = ""
if a:drawText ==# 1
let treeParts = ''
"get all the leading spaces and vertical tree parts for this line
if a:depth > 1
for j in a:vertMap[0:-2]
if g:NERDTreeDirArrows
let treeParts = treeParts . ' '
else
if j ==# 1
let treeParts = treeParts . '| '
else
let treeParts = treeParts . ' '
endif
endif
endfor
endif
"get the last vertical tree part for this line which will be different
"if this node is the last child of its parent
if !g:NERDTreeDirArrows
if a:isLastChild
let treeParts = treeParts . '`'
else
let treeParts = treeParts . '|'
endif
endif
"smack the appropriate dir/file symbol on the line before the file/dir
"name itself
if self.path.isDirectory
if self.isOpen
if g:NERDTreeDirArrows
let treeParts = treeParts . '▾ '
else
let treeParts = treeParts . '~'
endif
else
if g:NERDTreeDirArrows
let treeParts = treeParts . '▸ '
else
let treeParts = treeParts . '+'
endif
endif
else
if g:NERDTreeDirArrows
let treeParts = treeParts . ' '
else
let treeParts = treeParts . '-'
endif
endif
let line = treeParts . self.displayString()
let output = output . line . "\n"
endif
"if the node is an open dir, draw its children
if self.path.isDirectory ==# 1 && self.isOpen ==# 1
let childNodesToDraw = self.getVisibleChildren()
if len(childNodesToDraw) > 0
"draw all the nodes children except the last
let lastIndx = len(childNodesToDraw)-1
if lastIndx > 0
for i in childNodesToDraw[0:lastIndx-1]
let output = output . i._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 1), 0)
endfor
endif
"draw the last child, indicating that it IS the last
let output = output . childNodesToDraw[lastIndx]._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 0), 1)
endif
endif
return output
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,41 +0,0 @@
" ============================================================================
" File: exec_menuitem.vim
" Description: plugin for NERD Tree that provides an execute file menu item
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
" Last Change: 22 July, 2009
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
if exists("g:loaded_nerdtree_exec_menuitem")
finish
endif
let g:loaded_nerdtree_exec_menuitem = 1
call NERDTreeAddMenuItem({
\ 'text': '(!)Execute file',
\ 'shortcut': '!',
\ 'callback': 'NERDTreeExecFile',
\ 'isActiveCallback': 'NERDTreeExecFileActive' })
function! NERDTreeExecFileActive()
let node = g:NERDTreeFileNode.GetSelected()
return !node.path.isDirectory && node.path.isExecutable
endfunction
function! NERDTreeExecFile()
let treenode = g:NERDTreeFileNode.GetSelected()
echo "==========================================================\n"
echo "Complete the command to execute (add arguments etc):\n"
let cmd = treenode.path.str({'escape': 1})
let cmd = input(':!', cmd . ' ')
if cmd != ''
exec ':!' . cmd
else
echo "Aborted"
endif
endfunction

@ -1,262 +0,0 @@
" ============================================================================
" File: fs_menu.vim
" Description: plugin for the NERD Tree that provides a file system menu
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
" Last Change: 17 July, 2009
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
if exists("g:loaded_nerdtree_fs_menu")
finish
endif
let g:loaded_nerdtree_fs_menu = 1
"Automatically delete the buffer after deleting or renaming a file
if !exists("g:NERDTreeAutoDeleteBuffer")
let g:NERDTreeAutoDeleteBuffer = 0
endif
call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'})
call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'})
call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'})
if has("gui_mac") || has("gui_macvim")
call NERDTreeAddMenuItem({'text': '(r)eveal in Finder the current node', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'})
call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'})
call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'})
endif
if g:NERDTreePath.CopyingSupported()
call NERDTreeAddMenuItem({'text': '(c)opy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'})
endif
"FUNCTION: s:echo(msg){{{1
function! s:echo(msg)
redraw
echomsg "NERDTree: " . a:msg
endfunction
"FUNCTION: s:echoWarning(msg){{{1
function! s:echoWarning(msg)
echohl warningmsg
call s:echo(a:msg)
echohl normal
endfunction
"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1
"prints out the given msg and, if the user responds by pushing 'y' then the
"buffer with the given bufnum is deleted
"
"Args:
"bufnum: the buffer that may be deleted
"msg: a message that will be echoed to the user asking them if they wish to
" del the buffer
function! s:promptToDelBuffer(bufnum, msg)
echo a:msg
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
" 1. ensure that all windows which display the just deleted filename
" now display an empty buffer (so a layout is preserved).
" Is not it better to close single tabs with this file only ?
let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr()
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':enew! ' | endif"
exec "tabnext " . s:originalTabNumber
exec s:originalWindowNumber . "wincmd w"
" 3. We don't need a previous buffer anymore
exec "bwipeout! " . a:bufnum
endif
endfunction
"FUNCTION: s:promptToRenameBuffer(bufnum, msg){{{1
"prints out the given msg and, if the user responds by pushing 'y' then the
"buffer with the given bufnum is replaced with a new one
"
"Args:
"bufnum: the buffer that may be deleted
"msg: a message that will be echoed to the user asking them if they wish to
" del the buffer
function! s:promptToRenameBuffer(bufnum, msg, newFileName)
echo a:msg
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
" 1. ensure that a new buffer is loaded
exec "badd " . a:newFileName
" 2. ensure that all windows which display the just deleted filename
" display a buffer for a new filename.
let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr()
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':e! " . a:newFileName . "' | endif"
exec "tabnext " . s:originalTabNumber
exec s:originalWindowNumber . "wincmd w"
" 3. We don't need a previous buffer anymore
exec "bwipeout! " . a:bufnum
endif
endfunction
"FUNCTION: NERDTreeAddNode(){{{1
function! NERDTreeAddNode()
let curDirNode = g:NERDTreeDirNode.GetSelected()
let newNodeName = input("Add a childnode\n".
\ "==========================================================\n".
\ "Enter the dir/file name to be created. Dirs end with a '/'\n" .
\ "", curDirNode.path.str() . g:NERDTreePath.Slash(), "file")
if newNodeName ==# ''
call s:echo("Node Creation Aborted.")
return
endif
try
let newPath = g:NERDTreePath.Create(newNodeName)
let parentNode = b:NERDTreeRoot.findNode(newPath.getParent())
let newTreeNode = g:NERDTreeFileNode.New(newPath)
if parentNode.isOpen || !empty(parentNode.children)
call parentNode.addChild(newTreeNode, 1)
call NERDTreeRender()
call newTreeNode.putCursorHere(1, 0)
endif
catch /^NERDTree/
call s:echoWarning("Node Not Created.")
endtry
endfunction
"FUNCTION: NERDTreeMoveNode(){{{1
function! NERDTreeMoveNode()
let curNode = g:NERDTreeFileNode.GetSelected()
let newNodePath = input("Rename the current node\n" .
\ "==========================================================\n" .
\ "Enter the new path for the node: \n" .
\ "", curNode.path.str(), "file")
if newNodePath ==# ''
call s:echo("Node Renaming Aborted.")
return
endif
try
let bufnum = bufnr(curNode.path.str())
call curNode.rename(newNodePath)
call NERDTreeRender()
"if the node is open in a buffer, ask the user if they want to
"close that buffer
if bufnum != -1
let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Replace this buffer with a new file? (yN)"
call s:promptToRenameBuffer(bufnum, prompt, newNodePath)
endif
call curNode.putCursorHere(1, 0)
redraw
catch /^NERDTree/
call s:echoWarning("Node Not Renamed.")
endtry
endfunction
" FUNCTION: NERDTreeDeleteNode() {{{1
function! NERDTreeDeleteNode()
let currentNode = g:NERDTreeFileNode.GetSelected()
let confirmed = 0
if currentNode.path.isDirectory
let choice =input("Delete the current node\n" .
\ "==========================================================\n" .
\ "STOP! To delete this entire directory, type 'yes'\n" .
\ "" . currentNode.path.str() . ": ")
let confirmed = choice ==# 'yes'
else
echo "Delete the current node\n" .
\ "==========================================================\n".
\ "Are you sure you wish to delete the node:\n" .
\ "" . currentNode.path.str() . " (yN):"
let choice = nr2char(getchar())
let confirmed = choice ==# 'y'
endif
if confirmed
try
call currentNode.delete()
call NERDTreeRender()
"if the node is open in a buffer, ask the user if they want to
"close that buffer
let bufnum = bufnr(currentNode.path.str())
if buflisted(bufnum)
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
call s:promptToDelBuffer(bufnum, prompt)
endif
redraw
catch /^NERDTree/
call s:echoWarning("Could not remove node")
endtry
else
call s:echo("delete aborted")
endif
endfunction
" FUNCTION: NERDTreeCopyNode() {{{1
function! NERDTreeCopyNode()
let currentNode = g:NERDTreeFileNode.GetSelected()
let newNodePath = input("Copy the current node\n" .
\ "==========================================================\n" .
\ "Enter the new path to copy the node to: \n" .
\ "", currentNode.path.str(), "file")
if newNodePath != ""
"strip trailing slash
let newNodePath = substitute(newNodePath, '\/$', '', '')
let confirmed = 1
if currentNode.path.copyingWillOverwrite(newNodePath)
call s:echo("Warning: copying may overwrite files! Continue? (yN)")
let choice = nr2char(getchar())
let confirmed = choice ==# 'y'
endif
if confirmed
try
let newNode = currentNode.copy(newNodePath)
if !empty(newNode)
call NERDTreeRender()
call newNode.putCursorHere(0, 0)
endif
catch /^NERDTree/
call s:echoWarning("Could not copy node")
endtry
endif
else
call s:echo("Copy aborted.")
endif
redraw
endfunction
function! NERDTreeQuickLook()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
call system("qlmanage -p 2>/dev/null '" . treenode.path.str() . "'")
endif
endfunction
function! NERDTreeRevealInFinder()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
let x = system("open -R '" . treenode.path.str() . "'")
endif
endfunction
function! NERDTreeExecuteFile()
let treenode = g:NERDTreeFileNode.GetSelected()
if treenode != {}
let x = system("open '" . treenode.path.str() . "'")
endif
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,210 +0,0 @@
" ============================================================================
" File: NERD_tree.vim
" Description: vim global plugin that provides a nice tree explorer
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
" Last Change: 28 December, 2011
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" ============================================================================
"
" SECTION: Script init stuff {{{1
"============================================================
if exists("loaded_nerd_tree")
finish
endif
if v:version < 700
echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
finish
endif
let loaded_nerd_tree = 1
"for line continuation - i.e dont want C in &cpo
let s:old_cpo = &cpo
set cpo&vim
"Function: s:initVariable() function {{{2
"This function is used to initialise a given variable to a given value. The
"variable is only initialised if it does not exist prior
"
"Args:
"var: the name of the var to be initialised
"value: the value to initialise var to
"
"Returns:
"1 if the var is set, 0 otherwise
function! s:initVariable(var, value)
if !exists(a:var)
exec 'let ' . a:var . ' = ' . "'" . substitute(a:value, "'", "''", "g") . "'"
return 1
endif
return 0
endfunction
"SECTION: Init variable calls and other random constants {{{2
call s:initVariable("g:NERDChristmasTree", 1)
call s:initVariable("g:NERDTreeAutoCenter", 1)
call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
call s:initVariable("g:NERDTreeChDirMode", 0)
call s:initVariable("g:NERDTreeMinimalUI", 0)
if !exists("g:NERDTreeIgnore")
let g:NERDTreeIgnore = ['\~$']
endif
call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks')
call s:initVariable("g:NERDTreeHighlightCursorline", 1)
call s:initVariable("g:NERDTreeHijackNetrw", 1)
call s:initVariable("g:NERDTreeMouseMode", 1)
call s:initVariable("g:NERDTreeNotificationThreshold", 100)
call s:initVariable("g:NERDTreeQuitOnOpen", 0)
call s:initVariable("g:NERDTreeShowBookmarks", 0)
call s:initVariable("g:NERDTreeShowFiles", 1)
call s:initVariable("g:NERDTreeShowHidden", 0)
call s:initVariable("g:NERDTreeShowLineNumbers", 0)
call s:initVariable("g:NERDTreeSortDirs", 1)
call s:initVariable("g:NERDTreeDirArrows", !nerdtree#runningWindows())
call s:initVariable("g:NERDTreeCasadeOpenSingleChildDir", 1)
if !exists("g:NERDTreeSortOrder")
let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
else
"if there isnt a * in the sort sequence then add one
if count(g:NERDTreeSortOrder, '*') < 1
call add(g:NERDTreeSortOrder, '*')
endif
endif
if !exists('g:NERDTreeStatusline')
"the exists() crap here is a hack to stop vim spazzing out when
"loading a session that was created with an open nerd tree. It spazzes
"because it doesnt store b:NERDTreeRoot (its a b: var, and its a hash)
let g:NERDTreeStatusline = "%{exists('b:NERDTreeRoot')?b:NERDTreeRoot.path.str():''}"
endif
call s:initVariable("g:NERDTreeWinPos", "left")
call s:initVariable("g:NERDTreeWinSize", 31)
"init the shell commands that will be used to copy nodes, and remove dir trees
"
"Note: the space after the command is important
if nerdtree#runningWindows()
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ')
else
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ')
call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ')
endif
"SECTION: Init variable calls for key mappings {{{2
call s:initVariable("g:NERDTreeMapActivateNode", "o")
call s:initVariable("g:NERDTreeMapChangeRoot", "C")
call s:initVariable("g:NERDTreeMapChdir", "cd")
call s:initVariable("g:NERDTreeMapCloseChildren", "X")
call s:initVariable("g:NERDTreeMapCloseDir", "x")
call s:initVariable("g:NERDTreeMapDeleteBookmark", "D")
call s:initVariable("g:NERDTreeMapMenu", "m")
call s:initVariable("g:NERDTreeMapHelp", "?")
call s:initVariable("g:NERDTreeMapJumpFirstChild", "K")
call s:initVariable("g:NERDTreeMapJumpLastChild", "J")
call s:initVariable("g:NERDTreeMapJumpNextSibling", "<C-j>")
call s:initVariable("g:NERDTreeMapJumpParent", "p")
call s:initVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>")
call s:initVariable("g:NERDTreeMapJumpRoot", "P")
call s:initVariable("g:NERDTreeMapOpenExpl", "e")
call s:initVariable("g:NERDTreeMapOpenInTab", "t")
call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T")
call s:initVariable("g:NERDTreeMapOpenRecursively", "O")
call s:initVariable("g:NERDTreeMapOpenSplit", "i")
call s:initVariable("g:NERDTreeMapOpenVSplit", "s")
call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode)
call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit)
call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit)
call s:initVariable("g:NERDTreeMapQuit", "q")
call s:initVariable("g:NERDTreeMapRefresh", "r")
call s:initVariable("g:NERDTreeMapRefreshRoot", "R")
call s:initVariable("g:NERDTreeMapToggleBookmarks", "B")
call s:initVariable("g:NERDTreeMapToggleFiles", "F")
call s:initVariable("g:NERDTreeMapToggleFilters", "f")
call s:initVariable("g:NERDTreeMapToggleHidden", "I")
call s:initVariable("g:NERDTreeMapToggleZoom", "A")
call s:initVariable("g:NERDTreeMapUpdir", "u")
call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U")
call s:initVariable("g:NERDTreeMapCWD", "CD")
"SECTION: Load class files{{{2
call nerdtree#loadClassFiles()
" SECTION: Commands {{{1
"============================================================
"init the command that users start the nerd tree with
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.TogglePrimary('<args>')
command! -n=0 -bar NERDTreeClose :call nerdtree#closeTreeIfOpen()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=0 -bar NERDTreeFind call nerdtree#findAndRevealPath()
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
" SECTION: Auto commands {{{1
"============================================================
augroup NERDTree
"Save the cursor position whenever we close the nerd tree
exec "autocmd BufWinLeave ". g:NERDTreeCreator.BufNamePrefix() ."* call nerdtree#saveScreenState()"
"disallow insert mode in the NERDTree
exec "autocmd BufEnter ". g:NERDTreeCreator.BufNamePrefix() ."* stopinsert"
augroup END
if g:NERDTreeHijackNetrw
augroup NERDTreeHijackNetrw
autocmd VimEnter * silent! autocmd! FileExplorer
au BufEnter,VimEnter * call nerdtree#checkForBrowse(expand("<amatch>"))
augroup END
endif
" SECTION: Public API {{{1
"============================================================
function! NERDTreeAddMenuItem(options)
call g:NERDTreeMenuItem.Create(a:options)
endfunction
function! NERDTreeAddMenuSeparator(...)
let opts = a:0 ? a:1 : {}
call g:NERDTreeMenuItem.CreateSeparator(opts)
endfunction
function! NERDTreeAddSubmenu(options)
return g:NERDTreeMenuItem.Create(a:options)
endfunction
function! NERDTreeAddKeyMap(options)
call g:NERDTreeKeyMap.Create(a:options)
endfunction
function! NERDTreeRender()
call nerdtree#renderView()
endfunction
function! NERDTreeFocus()
if nerdtree#isTreeOpen()
call nerdtree#putCursorInTreeWin()
else
call g:NERDTreeCreator.TogglePrimary("")
endif
endfunction
function! NERDTreeCWD()
call NERDTreeFocus()
call nerdtree#chRootCwd()
endfunction
" SECTION: Post Source Actions {{{1
call nerdtree#postSourceActions()
"reset &cpo back to users setting
let &cpo = s:old_cpo
" vim: set sw=4 sts=4 et fdm=marker:

@ -1,88 +0,0 @@
let s:tree_up_dir_line = '.. (up a dir)'
"NERDTreeFlags are syntax items that should be invisible, but give clues as to
"how things should be highlighted
syn match NERDTreeFlag #\~#
syn match NERDTreeFlag #\[RO\]#
"highlighting for the .. (up dir) line at the top of the tree
execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#"
"highlighting for the ~/+ symbols for the directory nodes
syn match NERDTreeClosable #\~\<#
syn match NERDTreeClosable #\~\.#
syn match NERDTreeOpenable #+\<#
syn match NERDTreeOpenable #+\.#he=e-1
"highlighting for the tree structural parts
syn match NERDTreePart #|#
syn match NERDTreePart #`#
syn match NERDTreePartFile #[|`]-#hs=s+1 contains=NERDTreePart
"quickhelp syntax elements
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1
syn match NERDTreeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=NERDTreeFlag
syn match NERDTreeToggleOn #".*(on)#hs=e-2,he=e-1 contains=NERDTreeHelpKey
syn match NERDTreeToggleOff #".*(off)#hs=e-3,he=e-1 contains=NERDTreeHelpKey
syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3
syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeFlag,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand
"highlighting for readonly files
syn match NERDTreeRO #.*\[RO\]#hs=s+2 contains=NERDTreeFlag,NERDTreeBookmark,NERDTreePart,NERDTreePartFile
"highlighting for sym links
syn match NERDTreeLink #[^-| `].* -> # contains=NERDTreeBookmark,NERDTreeOpenable,NERDTreeClosable,NERDTreeDirSlash
"highlighing for directory nodes and file nodes
syn match NERDTreeDirSlash #/#
syn match NERDTreeDir #[^-| `].*/# contains=NERDTreeLink,NERDTreeDirSlash,NERDTreeOpenable,NERDTreeClosable
syn match NERDTreeExecFile #[|` ].*\*\($\| \)# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark
syn match NERDTreeFile #|-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
syn match NERDTreeFile #`-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
syn match NERDTreeCWD #^[</].*$#
"highlighting for bookmarks
syn match NERDTreeBookmark # {.*}#hs=s+1
"highlighting for the bookmarks table
syn match NERDTreeBookmarksLeader #^>#
syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmarksLeader
syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader
syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader
if exists("g:NERDChristmasTree") && g:NERDChristmasTree
hi def link NERDTreePart Special
hi def link NERDTreePartFile Type
hi def link NERDTreeFile Normal
hi def link NERDTreeExecFile Title
hi def link NERDTreeDirSlash Identifier
hi def link NERDTreeClosable Type
else
hi def link NERDTreePart Normal
hi def link NERDTreePartFile Normal
hi def link NERDTreeFile Normal
hi def link NERDTreeClosable Title
endif
hi def link NERDTreeBookmarksHeader statement
hi def link NERDTreeBookmarksLeader ignore
hi def link NERDTreeBookmarkName Identifier
hi def link NERDTreeBookmark normal
hi def link NERDTreeHelp String
hi def link NERDTreeHelpKey Identifier
hi def link NERDTreeHelpCommand Identifier
hi def link NERDTreeHelpTitle Macro
hi def link NERDTreeToggleOn Question
hi def link NERDTreeToggleOff WarningMsg
hi def link NERDTreeDir Directory
hi def link NERDTreeUp Directory
hi def link NERDTreeCWD Statement
hi def link NERDTreeLink Macro
hi def link NERDTreeOpenable Title
hi def link NERDTreeFlag ignore
hi def link NERDTreeRO WarningMsg
hi def link NERDTreeBookmark Statement
hi def link NERDTreeCurrentNode Search

@ -1,5 +0,0 @@
Quickly install with:
git clone git://github.com/msanders/snipmate.vim.git
cd snipmate.vim
cp -R * ~/.vim

@ -1,40 +0,0 @@
" These are the mappings for snipMate.vim. Putting it here ensures that it
" will be mapped after other plugins such as supertab.vim.
if !exists('loaded_snips') || exists('s:did_snips_mappings')
finish
endif
let s:did_snips_mappings = 1
" This is put here in the 'after' directory in order for snipMate to override
" other plugin mappings (e.g., supertab).
"
" You can safely adjust these mappings to your preferences (as explained in
" :help snipMate-remap).
ino <silent> <tab> <c-r>=TriggerSnippet()<cr>
snor <silent> <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
ino <silent> <s-tab> <c-r>=BackwardsSnippet()<cr>
snor <silent> <s-tab> <esc>i<right><c-r>=BackwardsSnippet()<cr>
ino <silent> <c-r><tab> <c-r>=ShowAvailableSnips()<cr>
" The default mappings for these are annoying & sometimes break snipMate.
" You can change them back if you want, I've put them here for convenience.
snor <bs> b<bs>
snor <right> <esc>a
snor <left> <esc>bi
snor ' b<bs>'
snor ` b<bs>`
snor % b<bs>%
snor U b<bs>U
snor ^ b<bs>^
snor \ b<bs>\
snor <c-x> b<bs><c-x>
" By default load snippets in snippets_dir
if empty(snippets_dir)
finish
endif
call GetSnippets(snippets_dir, '_') " Get global snippets
au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif
" vim:noet:sw=4:ts=4:ft=vim

@ -1,435 +0,0 @@
fun! Filename(...)
let filename = expand('%:t:r')
if filename == '' | return a:0 == 2 ? a:2 : '' | endif
return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g')
endf
fun s:RemoveSnippet()
unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen
\ s:lastBuf s:oldWord
if exists('s:update')
unl s:startCol s:origWordLen s:update
if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif
endif
aug! snipMateAutocmds
endf
fun snipMate#expandSnip(snip, col)
let lnum = line('.') | let col = a:col
let snippet = s:ProcessSnippet(a:snip)
" Avoid error if eval evaluates to nothing
if snippet == '' | return '' | endif
" Expand snippet onto current position with the tab stops removed
let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1)
let line = getline(lnum)
let afterCursor = strpart(line, col - 1)
" Keep text after the cursor
if afterCursor != "\t" && afterCursor != ' '
let line = strpart(line, 0, col - 1)
let snipLines[-1] .= afterCursor
else
let afterCursor = ''
" For some reason the cursor needs to move one right after this
if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore'
let col += 1
endif
endif
call setline(lnum, line.snipLines[0])
" Autoindent snippet according to previous indentation
let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1
call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val"))
" Open any folds snippet expands into
if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif
let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent)
if s:snipLen
aug snipMateAutocmds
au CursorMovedI * call s:UpdateChangedSnip(0)
au InsertEnter * call s:UpdateChangedSnip(1)
aug END
let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer
let s:curPos = 0
let s:endCol = g:snipPos[s:curPos][1]
let s:endLine = g:snipPos[s:curPos][0]
call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
let s:prevLen = [line('$'), col('$')]
if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif
else
unl g:snipPos s:snipLen
" Place cursor at end of snippet if no tab stop is given
let newlines = len(snipLines) - 1
call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor)
\ + (newlines ? 0: col - 1))
endif
return ''
endf
" Prepare snippet to be processed by s:BuildTabStops
fun s:ProcessSnippet(snip)
let snippet = a:snip
" Evaluate eval (`...`) expressions.
" Backquotes prefixed with a backslash "\" are ignored.
" Using a loop here instead of a regex fixes a bug with nested "\=".
if stridx(snippet, '`') != -1
while match(snippet, '\(^\|[^\\]\)`.\{-}[^\\]`') != -1
let snippet = substitute(snippet, '\(^\|[^\\]\)\zs`.\{-}[^\\]`\ze',
\ substitute(eval(matchstr(snippet, '\(^\|[^\\]\)`\zs.\{-}[^\\]\ze`')),
\ "\n\\%$", '', ''), '')
endw
let snippet = substitute(snippet, "\r", "\n", 'g')
let snippet = substitute(snippet, '\\`', '`', 'g')
endif
" Place all text after a colon in a tab stop after the tab stop
" (e.g. "${#:foo}" becomes "${:foo}foo").
" This helps tell the position of the tab stops later.
let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g')
" Update the a:snip so that all the $# become the text after
" the colon in their associated ${#}.
" (e.g. "${1:foo}" turns all "$1"'s into "foo")
let i = 1
while stridx(snippet, '${'.i) != -1
let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}')
if s != ''
let snippet = substitute(snippet, '$'.i, s.'&', 'g')
endif
let i += 1
endw
if &et " Expand tabs to spaces if 'expandtab' is set.
return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g')
endif
return snippet
endf
" Counts occurences of haystack in needle
fun s:Count(haystack, needle)
let counter = 0
let index = stridx(a:haystack, a:needle)
while index != -1
let index = stridx(a:haystack, a:needle, index+1)
let counter += 1
endw
return counter
endf
" Builds a list of a list of each tab stop in the snippet containing:
" 1.) The tab stop's line number.
" 2.) The tab stop's column number
" (by getting the length of the string between the last "\n" and the
" tab stop).
" 3.) The length of the text after the colon for the current tab stop
" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned.
" 4.) If the "${#:}" construct is given, another list containing all
" the matches of "$#", to be replaced with the placeholder. This list is
" composed the same way as the parent; the first item is the line number,
" and the second is the column.
fun s:BuildTabStops(snip, lnum, col, indent)
let snipPos = []
let i = 1
let withoutVars = substitute(a:snip, '$\d\+', '', 'g')
while stridx(a:snip, '${'.i) != -1
let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D')
let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g')
let j = i - 1
call add(snipPos, [0, 0, -1])
let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n")
let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D'))
if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif
" Get all $# matches in another list, if ${#:name} is given
if stridx(withoutVars, '${'.i.':') != -1
let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}'))
let dots = repeat('.', snipPos[j][2])
call add(snipPos[j], [])
let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g')
while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1
let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)')
call add(snipPos[j][3], [0, 0])
let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n")
let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum
\ ? len(matchstr(beforeMark, '.*\n\zs.*'))
\ : a:col + len(beforeMark))
let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '')
endw
endif
let i += 1
endw
return [snipPos, i - 1]
endf
fun snipMate#jumpTabStop(backwards)
let leftPlaceholder = exists('s:origWordLen')
\ && s:origWordLen != g:snipPos[s:curPos][2]
if leftPlaceholder && exists('s:oldEndCol')
let startPlaceholder = s:oldEndCol + 1
endif
if exists('s:update')
call s:UpdatePlaceholderTabStops()
else
call s:UpdateTabStops()
endif
" Don't reselect placeholder if it has been modified
if leftPlaceholder && g:snipPos[s:curPos][2] != -1
if exists('startPlaceholder')
let g:snipPos[s:curPos][1] = startPlaceholder
else
let g:snipPos[s:curPos][1] = col('.')
let g:snipPos[s:curPos][2] = 0
endif
endif
let s:curPos += a:backwards ? -1 : 1
" Loop over the snippet when going backwards from the beginning
if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif
if s:curPos == s:snipLen
let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2]
call s:RemoveSnippet()
return sMode ? "\<tab>" : TriggerSnippet()
endif
call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
let s:endLine = g:snipPos[s:curPos][0]
let s:endCol = g:snipPos[s:curPos][1]
let s:prevLen = [line('$'), col('$')]
return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord()
endf
fun s:UpdatePlaceholderTabStops()
let changeLen = s:origWordLen - g:snipPos[s:curPos][2]
unl s:startCol s:origWordLen s:update
if !exists('s:oldVars') | return | endif
" Update tab stops in snippet if text has been added via "$#"
" (e.g., in "${1:foo}bar$1${2}").
if changeLen != 0
let curLine = line('.')
for pos in g:snipPos
if pos == g:snipPos[s:curPos] | continue | endif
let changed = pos[0] == curLine && pos[1] > s:oldEndCol
let changedVars = 0
let endPlaceholder = pos[2] - 1 + pos[1]
" Subtract changeLen from each tab stop that was after any of
" the current tab stop's placeholders.
for [lnum, col] in s:oldVars
if lnum > pos[0] | break | endif
if pos[0] == lnum
if pos[1] > col || (pos[2] == -1 && pos[1] == col)
let changed += 1
elseif col < endPlaceholder
let changedVars += 1
endif
endif
endfor
let pos[1] -= changeLen * changed
let pos[2] -= changeLen * changedVars " Parse variables within placeholders
" e.g., "${1:foo} ${2:$1bar}"
if pos[2] == -1 | continue | endif
" Do the same to any placeholders in the other tab stops.
for nPos in pos[3]
let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol
for [lnum, col] in s:oldVars
if lnum > nPos[0] | break | endif
if nPos[0] == lnum && nPos[1] > col
let changed += 1
endif
endfor
let nPos[1] -= changeLen * changed
endfor
endfor
endif
unl s:endCol s:oldVars s:oldEndCol
endf
fun s:UpdateTabStops()
let changeLine = s:endLine - g:snipPos[s:curPos][0]
let changeCol = s:endCol - g:snipPos[s:curPos][1]
if exists('s:origWordLen')
let changeCol -= s:origWordLen
unl s:origWordLen
endif
let lnum = g:snipPos[s:curPos][0]
let col = g:snipPos[s:curPos][1]
" Update the line number of all proceeding tab stops if <cr> has
" been inserted.
if changeLine != 0
let changeLine -= 1
for pos in g:snipPos
if pos[0] >= lnum
if pos[0] == lnum | let pos[1] += changeCol | endif
let pos[0] += changeLine
endif
if pos[2] == -1 | continue | endif
for nPos in pos[3]
if nPos[0] >= lnum
if nPos[0] == lnum | let nPos[1] += changeCol | endif
let nPos[0] += changeLine
endif
endfor
endfor
elseif changeCol != 0
" Update the column of all proceeding tab stops if text has
" been inserted/deleted in the current line.
for pos in g:snipPos
if pos[1] >= col && pos[0] == lnum
let pos[1] += changeCol
endif
if pos[2] == -1 | continue | endif
for nPos in pos[3]
if nPos[0] > lnum | break | endif
if nPos[0] == lnum && nPos[1] >= col
let nPos[1] += changeCol
endif
endfor
endfor
endif
endf
fun s:SelectWord()
let s:origWordLen = g:snipPos[s:curPos][2]
let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1,
\ s:origWordLen)
let s:prevLen[1] -= s:origWordLen
if !empty(g:snipPos[s:curPos][3])
let s:update = 1
let s:endCol = -1
let s:startCol = g:snipPos[s:curPos][1] - 1
endif
if !s:origWordLen | return '' | endif
let l = col('.') != 1 ? 'l' : ''
if &sel == 'exclusive'
return "\<esc>".l.'v'.s:origWordLen."l\<c-g>"
endif
return s:origWordLen == 1 ? "\<esc>".l.'gh'
\ : "\<esc>".l.'v'.(s:origWordLen - 1)."l\<c-g>"
endf
" This updates the snippet as you type when text needs to be inserted
" into multiple places (e.g. in "${1:default text}foo$1bar$1",
" "default text" would be highlighted, and if the user types something,
" UpdateChangedSnip() would be called so that the text after "foo" & "bar"
" are updated accordingly)
"
" It also automatically quits the snippet if the cursor is moved out of it
" while in insert mode.
fun s:UpdateChangedSnip(entering)
if exists('g:snipPos') && bufnr(0) != s:lastBuf
call s:RemoveSnippet()
elseif exists('s:update') " If modifying a placeholder
if !exists('s:oldVars') && s:curPos + 1 < s:snipLen
" Save the old snippet & word length before it's updated
" s:startCol must be saved too, in case text is added
" before the snippet (e.g. in "foo$1${2}bar${1:foo}").
let s:oldEndCol = s:startCol
let s:oldVars = deepcopy(g:snipPos[s:curPos][3])
endif
let col = col('.') - 1
if s:endCol != -1
let changeLen = col('$') - s:prevLen[1]
let s:endCol += changeLen
else " When being updated the first time, after leaving select mode
if a:entering | return | endif
let s:endCol = col - 1
endif
" If the cursor moves outside the snippet, quit it
if line('.') != g:snipPos[s:curPos][0] || col < s:startCol ||
\ col - 1 > s:endCol
unl! s:startCol s:origWordLen s:oldVars s:update
return s:RemoveSnippet()
endif
call s:UpdateVars()
let s:prevLen[1] = col('$')
elseif exists('g:snipPos')
if !a:entering && g:snipPos[s:curPos][2] != -1
let g:snipPos[s:curPos][2] = -2
endif
let col = col('.')
let lnum = line('.')
let changeLine = line('$') - s:prevLen[0]
if lnum == s:endLine
let s:endCol += col('$') - s:prevLen[1]
let s:prevLen = [line('$'), col('$')]
endif
if changeLine != 0
let s:endLine += changeLine
let s:endCol = col
endif
" Delete snippet if cursor moves out of it in insert mode
if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1]))
\ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0]
call s:RemoveSnippet()
endif
endif
endf
" This updates the variables in a snippet when a placeholder has been edited.
" (e.g., each "$1" in "${1:foo} $1bar $1bar")
fun s:UpdateVars()
let newWordLen = s:endCol - s:startCol + 1
let newWord = strpart(getline('.'), s:startCol, newWordLen)
if newWord == s:oldWord || empty(g:snipPos[s:curPos][3])
return
endif
let changeLen = g:snipPos[s:curPos][2] - newWordLen
let curLine = line('.')
let startCol = col('.')
let oldStartSnip = s:startCol
let updateTabStops = changeLen != 0
let i = 0
for [lnum, col] in g:snipPos[s:curPos][3]
if updateTabStops
let start = s:startCol
if lnum == curLine && col <= start
let s:startCol -= changeLen
let s:endCol -= changeLen
endif
for nPos in g:snipPos[s:curPos][3][(i):]
" This list is in ascending order, so quit if we've gone too far.
if nPos[0] > lnum | break | endif
if nPos[0] == lnum && nPos[1] > col
let nPos[1] -= changeLen
endif
endfor
if lnum == curLine && col > start
let col -= changeLen
let g:snipPos[s:curPos][3][i][1] = col
endif
let i += 1
endif
" "Very nomagic" is used here to allow special characters.
call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'.
\ escape(s:oldWord, '\'), escape(newWord, '\&'), ''))
endfor
if oldStartSnip != s:startCol
call cursor(0, startCol + s:startCol - oldStartSnip)
endif
let s:oldWord = newWord
let g:snipPos[s:curPos][2] = newWordLen
endf
" vim:noet:sw=4:ts=4:ft=vim

@ -1,322 +0,0 @@
*snipMate.txt* Plugin for using TextMate-style snippets in Vim.
snipMate *snippet* *snippets* *snipMate*
Last Change: December 27, 2009
|snipMate-description| Description
|snipMate-syntax| Snippet syntax
|snipMate-usage| Usage
|snipMate-settings| Settings
|snipMate-features| Features
|snipMate-disadvantages| Disadvantages to TextMate
|snipMate-contact| Contact
|snipMate-license| License
For Vim version 7.0 or later.
This plugin only works if 'compatible' is not set.
{Vi does not have any of these features.}
==============================================================================
DESCRIPTION *snipMate-description*
snipMate.vim implements some of TextMate's snippets features in Vim. A
snippet is a piece of often-typed text that you can insert into your
document using a trigger word followed by a <tab>.
For instance, in a C file using the default installation of snipMate.vim, if
you type "for<tab>" in insert mode, it will expand a typical for loop in C: >
for (i = 0; i < count; i++) {
}
To go to the next item in the loop, simply <tab> over to it; if there is
repeated code, such as the "i" variable in this example, you can simply
start typing once it's highlighted and all the matches specified in the
snippet will be updated. To go in reverse, use <shift-tab>.
==============================================================================
SYNTAX *snippet-syntax*
Snippets can be defined in two ways. They can be in their own file, named
after their trigger in 'snippets/<filetype>/<trigger>.snippet', or they can be
defined together in a 'snippets/<filetype>.snippets' file. Note that dotted
'filetype' syntax is supported -- e.g., you can use >
:set ft=html.eruby
to activate snippets for both HTML and eRuby for the current file.
The syntax for snippets in *.snippets files is the following: >
snippet trigger
expanded text
more expanded text
Note that the first hard tab after the snippet trigger is required, and not
expanded in the actual snippet. The syntax for *.snippet files is the same,
only without the trigger declaration and starting indentation.
Also note that snippets must be defined using hard tabs. They can be expanded
to spaces later if desired (see |snipMate-indenting|).
"#" is used as a line-comment character in *.snippets files; however, they can
only be used outside of a snippet declaration. E.g.: >
# this is a correct comment
snippet trigger
expanded text
snippet another_trigger
# this isn't a comment!
expanded text
<
This should hopefully be obvious with the included syntax highlighting.
*snipMate-${#}*
Tab stops ~
By default, the cursor is placed at the end of a snippet. To specify where the
cursor is to be placed next, use "${#}", where the # is the number of the tab
stop. E.g., to place the cursor first on the id of a <div> tag, and then allow
the user to press <tab> to go to the middle of it:
>
snippet div
<div id="${1}">
${2}
</div>
<
*snipMate-placeholders* *snipMate-${#:}* *snipMate-$#*
Placeholders ~
Placeholder text can be supplied using "${#:text}", where # is the number of
the tab stop. This text then can be copied throughout the snippet using "$#",
given # is the same number as used before. So, to make a C for loop: >
snippet for
for (${2:i}; $2 < ${1:count}; $1++) {
${4}
}
This will cause "count" to first be selected and change if the user starts
typing. When <tab> is pressed, the "i" in ${2}'s position will be selected;
all $2 variables will default to "i" and automatically be updated if the user
starts typing.
NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate.
Variables within variables are also possible. For instance: >
snippet opt
<option value="${1:option}">${2:$1}</option>
Will, as usual, cause "option" to first be selected and update all the $1
variables if the user starts typing. Since one of these variables is inside of
${2}, this text will then be used as a placeholder for the next tab stop,
allowing the user to change it if he wishes.
To copy a value throughout a snippet without supplying default text, simply
use the "${#:}" construct without the text; e.g.: >
snippet foo
${1:}bar$1
< *snipMate-commands*
Interpolated Vim Script ~
Snippets can also contain Vim script commands that are executed (via |eval()|)
when the snippet is inserted. Commands are given inside backticks (`...`); for
TextMates's functionality, use the |system()| function. E.g.: >
snippet date
`system("date +%Y-%m-%d")`
will insert the current date, assuming you are on a Unix system. Note that you
can also (and should) use |strftime()| for this example.
Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()*
Since the current filename is used often in snippets, a default function
has been defined for it in snipMate.vim, appropriately called Filename().
With no arguments, the default filename without an extension is returned;
the first argument specifies what to place before or after the filename,
and the second argument supplies the default text to be used if the file
has not been named. "$1" in the first argument is replaced with the filename;
if you only want the filename to be returned, the first argument can be left
blank. Examples: >
snippet filename
`Filename()`
snippet filename_with_default
`Filename('', 'name')`
snippet filename_foo
`filename('$1_foo')`
The first example returns the filename if it the file has been named, and an
empty string if it hasn't. The second returns the filename if it's been named,
and "name" if it hasn't. The third returns the filename followed by "_foo" if
it has been named, and an empty string if it hasn't.
*multi_snip*
To specify that a snippet can have multiple matches in a *.snippets file, use
this syntax: >
snippet trigger A description of snippet #1
expand this text
snippet trigger A description of snippet #2
expand THIS text!
In this example, when "trigger<tab>" is typed, a numbered menu containing all
of the descriptions of the "trigger" will be shown; when the user presses the
corresponding number, that snippet will then be expanded.
To create a snippet with multiple matches using *.snippet files,
simply place all the snippets in a subdirectory with the trigger name:
'snippets/<filetype>/<trigger>/<name>.snippet'.
==============================================================================
USAGE *snipMate-usage*
*'snippets'* *g:snippets_dir*
Snippets are by default looked for any 'snippets' directory in your
'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or
'$HOME\vimfiles\snippets\' on Windows. To change that location or add another
one, change the g:snippets_dir variable in your |.vimrc| to your preferred
directory, or use the |ExtractSnips()|function. This will be used by the
|globpath()| function, and so accepts the same syntax as it (e.g.,
comma-separated paths).
ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets*
ExtractSnipsFile() extracts the specified *.snippets file for the given
filetype. A .snippets file contains multiple snippet declarations for the
filetype. It is further explained above, in |snippet-syntax|.
ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet*
ExtractSnips() extracts *.snippet files from the specified directory and
defines them as snippets for the given filetype. The directory tree should
look like this: 'snippets/<filetype>/<trigger>.snippet'. If the snippet has
multiple matches, it should look like this:
'snippets/<filetype>/<trigger>/<name>.snippet' (see |multi_snip|).
ResetAllSnippets() *ResetAllSnippets()*
ResetAllSnippets() removes all snippets from memory. This is useful to put at
the top of a snippet setup file for if you would like to |:source| it multiple
times.
ResetSnippets({filetype}) *ResetSnippets()*
ResetSnippets() removes all snippets from memory for the given filetype.
ReloadAllSnippets() *ReloadAllSnippets()*
ReloadAllSnippets() reloads all snippets for all filetypes. This is useful for
testing and debugging.
ReloadSnippets({filetype}) *ReloadSnippets()*
ReloadSnippets() reloads all snippets for the given filetype.
*list-snippets* *i_CTRL-R_<Tab>*
If you would like to see what snippets are available, simply type <c-r><tab>
in the current buffer to show a list via |popupmenu-completion|.
==============================================================================
SETTINGS *snipMate-settings* *g:snips_author*
The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set
to your name; it can then be used in snippets to automatically add it. E.g.: >
let g:snips_author = 'Hubert Farnsworth'
snippet name
`g:snips_author`
<
*snipMate-expandtab* *snipMate-indenting*
If you would like your snippets to be expanded using spaces instead of tabs,
just enable 'expandtab' and set 'softtabstop' to your preferred amount of
spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead.
*snipMate-remap*
snipMate does not come with a setting to customize the trigger key, but you
can remap it easily in the two lines it's defined in the 'after' directory
under 'plugin/snipMate.vim'. For instance, to change the trigger key
to CTRL-J, just change this: >
ino <tab> <c-r>=TriggerSnippet()<cr>
snor <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
to this: >
ino <c-j> <c-r>=TriggerSnippet()<cr>
snor <c-j> <esc>i<right><c-r>=TriggerSnippet()<cr>
==============================================================================
FEATURES *snipMate-features*
snipMate.vim has the following features among others:
- The syntax of snippets is very similar to TextMate's, allowing
easy conversion.
- The position of the snippet is kept transparently (i.e. it does not use
markers/placeholders written to the buffer), which allows you to escape
out of an incomplete snippet, something particularly useful in Vim.
- Variables in snippets are updated as-you-type.
- Snippets can have multiple matches.
- Snippets can be out of order. For instance, in a do...while loop, the
condition can be added before the code.
- [New] File-based snippets are supported.
- [New] Triggers after non-word delimiters are expanded, e.g. "foo"
in "bar.foo".
- [New] <shift-tab> can now be used to jump tab stops in reverse order.
==============================================================================
DISADVANTAGES *snipMate-disadvantages*
snipMate.vim currently has the following disadvantages to TextMate's snippets:
- There is no $0; the order of tab stops must be explicitly stated.
- Placeholders within placeholders are not possible. E.g.: >
'<div${1: id="${2:some_id}}">${3}</div>'
<
In TextMate this would first highlight ' id="some_id"', and if
you hit delete it would automatically skip ${2} and go to ${3}
on the next <tab>, but if you didn't delete it it would highlight
"some_id" first. You cannot do this in snipMate.vim.
- Regex cannot be performed on variables, such as "${1/.*/\U&}"
- Placeholders cannot span multiple lines.
- Activating snippets in different scopes of the same file is
not possible.
Perhaps some of these features will be added in a later release.
==============================================================================
CONTACT *snipMate-contact* *snipMate-author*
To contact the author (Michael Sanders), please email:
msanders42+snipmate <at> gmail <dot> com
I greatly appreciate any suggestions or improvements offered for the script.
==============================================================================
LICENSE *snipMate-license*
snipMate is released under the MIT license:
Copyright 2009-2010 Michael Sanders. All rights reserved.
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.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:

@ -1,37 +0,0 @@
'snippets' snipMate.txt /*'snippets'*
.snippet snipMate.txt /*.snippet*
.snippets snipMate.txt /*.snippets*
ExtractSnips() snipMate.txt /*ExtractSnips()*
ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()*
Filename() snipMate.txt /*Filename()*
ReloadAllSnippets() snipMate.txt /*ReloadAllSnippets()*
ReloadSnippets() snipMate.txt /*ReloadSnippets()*
ResetAllSnippets() snipMate.txt /*ResetAllSnippets()*
ResetSnippets() snipMate.txt /*ResetSnippets()*
g:snippets_dir snipMate.txt /*g:snippets_dir*
g:snips_author snipMate.txt /*g:snips_author*
i_CTRL-R_<Tab> snipMate.txt /*i_CTRL-R_<Tab>*
list-snippets snipMate.txt /*list-snippets*
multi_snip snipMate.txt /*multi_snip*
snipMate snipMate.txt /*snipMate*
snipMate-$# snipMate.txt /*snipMate-$#*
snipMate-${#:} snipMate.txt /*snipMate-${#:}*
snipMate-${#} snipMate.txt /*snipMate-${#}*
snipMate-author snipMate.txt /*snipMate-author*
snipMate-commands snipMate.txt /*snipMate-commands*
snipMate-contact snipMate.txt /*snipMate-contact*
snipMate-description snipMate.txt /*snipMate-description*
snipMate-disadvantages snipMate.txt /*snipMate-disadvantages*
snipMate-expandtab snipMate.txt /*snipMate-expandtab*
snipMate-features snipMate.txt /*snipMate-features*
snipMate-filename snipMate.txt /*snipMate-filename*
snipMate-indenting snipMate.txt /*snipMate-indenting*
snipMate-license snipMate.txt /*snipMate-license*
snipMate-placeholders snipMate.txt /*snipMate-placeholders*
snipMate-remap snipMate.txt /*snipMate-remap*
snipMate-settings snipMate.txt /*snipMate-settings*
snipMate-usage snipMate.txt /*snipMate-usage*
snipMate.txt snipMate.txt /*snipMate.txt*
snippet snipMate.txt /*snippet*
snippet-syntax snipMate.txt /*snippet-syntax*
snippets snipMate.txt /*snippets*

@ -1,10 +0,0 @@
" Helper function for (x)html snippets
if exists('s:did_snip_helper') || &cp || !exists('loaded_snips')
finish
endif
let s:did_snip_helper = 1
" Automatically closes tag if in xhtml
fun! Close()
return stridx(&ft, 'xhtml') == -1 ? '' : ' /'
endf

@ -1,8 +0,0 @@
{
"name" : "snipmate",
"version" : "dev",
"author" : "Michael Sanders <msanders42@gmail.com>",
"repository" : {"type": "git", "url": "git://github.com/msanders/snipmate.vim.git"},
"dependencies" : {},
"description" : "snipMate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim."
}

@ -1,271 +0,0 @@
" File: snipMate.vim
" Author: Michael Sanders
" Version: 0.84
" Description: snipMate.vim implements some of TextMate's snippets features in
" Vim. A snippet is a piece of often-typed text that you can
" insert into your document using a trigger word followed by a "<tab>".
"
" For more help see snipMate.txt; you can do this by using:
" :helptags ~/.vim/doc
" :h snipMate.txt
if exists('loaded_snips') || &cp || version < 700
finish
endif
let loaded_snips = 1
if !exists('snips_author') | let snips_author = 'Me' | endif
au BufRead,BufNewFile *.snippets\= set ft=snippet
au FileType snippet setl noet fdm=indent
let s:snippets = {} | let s:multi_snips = {}
if !exists('snippets_dir')
let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g')
endif
fun! MakeSnip(scope, trigger, content, ...)
let multisnip = a:0 && a:1 != ''
let var = multisnip ? 's:multi_snips' : 's:snippets'
if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif
if !has_key({var}[a:scope], a:trigger)
let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content
elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]]
else
echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.'
\ .' See :h multi_snip for help on snippets with multiple matches.'
endif
endf
fun! ExtractSnips(dir, ft)
for path in split(globpath(a:dir, '*'), "\n")
if isdirectory(path)
let pathname = fnamemodify(path, ':t')
for snipFile in split(globpath(path, '*.snippet'), "\n")
call s:ProcessFile(snipFile, a:ft, pathname)
endfor
elseif fnamemodify(path, ':e') == 'snippet'
call s:ProcessFile(path, a:ft)
endif
endfor
endf
" Processes a single-snippet file; optionally add the name of the parent
" directory for a snippet with multiple matches.
fun s:ProcessFile(file, ft, ...)
let keyword = fnamemodify(a:file, ':t:r')
if keyword == '' | return | endif
try
let text = join(readfile(a:file), "\n")
catch /E484/
echom "Error in snipMate.vim: couldn't read file: ".a:file
endtry
return a:0 ? MakeSnip(a:ft, a:1, text, keyword)
\ : MakeSnip(a:ft, keyword, text)
endf
fun! ExtractSnipsFile(file, ft)
if !filereadable(a:file) | return | endif
let text = readfile(a:file)
let inSnip = 0
for line in text + ["\n"]
if inSnip && (line[0] == "\t" || line == '')
let content .= strpart(line, 1)."\n"
continue
elseif inSnip
call MakeSnip(a:ft, trigger, content[:-2], name)
let inSnip = 0
endif
if line[:6] == 'snippet'
let inSnip = 1
let trigger = strpart(line, 8)
let name = ''
let space = stridx(trigger, ' ') + 1
if space " Process multi snip
let name = strpart(trigger, space)
let trigger = strpart(trigger, 0, space - 1)
endif
let content = ''
endif
endfor
endf
" Reset snippets for filetype.
fun! ResetSnippets(ft)
let ft = a:ft == '' ? '_' : a:ft
for dict in [s:snippets, s:multi_snips, g:did_ft]
if has_key(dict, ft)
unlet dict[ft]
endif
endfor
endf
" Reset snippets for all filetypes.
fun! ResetAllSnippets()
let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {}
endf
" Reload snippets for filetype.
fun! ReloadSnippets(ft)
let ft = a:ft == '' ? '_' : a:ft
call ResetSnippets(ft)
call GetSnippets(g:snippets_dir, ft)
endf
" Reload snippets for all filetypes.
fun! ReloadAllSnippets()
for ft in keys(g:did_ft)
call ReloadSnippets(ft)
endfor
endf
let g:did_ft = {}
fun! GetSnippets(dir, filetypes)
for ft in split(a:filetypes, '\.')
if has_key(g:did_ft, ft) | continue | endif
call s:DefineSnips(a:dir, ft, ft)
if ft == 'objc' || ft == 'cpp' || ft == 'cs'
call s:DefineSnips(a:dir, 'c', ft)
elseif ft == 'xhtml'
call s:DefineSnips(a:dir, 'html', 'xhtml')
endif
let g:did_ft[ft] = 1
endfor
endf
" Define "aliasft" snippets for the filetype "realft".
fun s:DefineSnips(dir, aliasft, realft)
for path in split(globpath(a:dir, a:aliasft.'/')."\n".
\ globpath(a:dir, a:aliasft.'-*/'), "\n")
call ExtractSnips(path, a:realft)
endfor
for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n".
\ globpath(a:dir, a:aliasft.'-*.snippets'), "\n")
call ExtractSnipsFile(path, a:realft)
endfor
endf
fun! TriggerSnippet()
if exists('g:SuperTabMappingForward')
if g:SuperTabMappingForward == "<tab>"
let SuperTabKey = "\<c-n>"
elseif g:SuperTabMappingBackward == "<tab>"
let SuperTabKey = "\<c-p>"
endif
endif
if pumvisible() " Update snippet if completion is used, or deal with supertab
if exists('SuperTabKey')
call feedkeys(SuperTabKey) | return ''
endif
call feedkeys("\<esc>a", 'n') " Close completion menu
call feedkeys("\<tab>") | return ''
endif
if exists('g:snipPos') | return snipMate#jumpTabStop(0) | endif
let word = matchstr(getline('.'), '\S\+\%'.col('.').'c')
for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
let [trigger, snippet] = s:GetSnippet(word, scope)
" If word is a trigger for a snippet, delete the trigger & expand
" the snippet.
if snippet != ''
let col = col('.') - len(trigger)
sil exe 's/\V'.escape(trigger, '/\.').'\%#//'
return snipMate#expandSnip(snippet, col)
endif
endfor
if exists('SuperTabKey')
call feedkeys(SuperTabKey)
return ''
endif
return "\<tab>"
endf
fun! BackwardsSnippet()
if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif
if exists('g:SuperTabMappingForward')
if g:SuperTabMappingBackward == "<s-tab>"
let SuperTabKey = "\<c-p>"
elseif g:SuperTabMappingForward == "<s-tab>"
let SuperTabKey = "\<c-n>"
endif
endif
if exists('SuperTabKey')
call feedkeys(SuperTabKey)
return ''
endif
return "\<s-tab>"
endf
" Check if word under cursor is snippet trigger; if it isn't, try checking if
" the text after non-word characters is (e.g. check for "foo" in "bar.foo")
fun s:GetSnippet(word, scope)
let word = a:word | let snippet = ''
while snippet == ''
if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]')
let snippet = s:snippets[a:scope][word]
elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]')
let snippet = s:ChooseSnippet(a:scope, word)
if snippet == '' | break | endif
else
if match(word, '\W') == -1 | break | endif
let word = substitute(word, '.\{-}\W', '', '')
endif
endw
if word == '' && a:word != '.' && stridx(a:word, '.') != -1
let [word, snippet] = s:GetSnippet('.', a:scope)
endif
return [word, snippet]
endf
fun s:ChooseSnippet(scope, trigger)
let snippet = []
let i = 1
for snip in s:multi_snips[a:scope][a:trigger]
let snippet += [i.'. '.snip[0]]
let i += 1
endfor
if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif
let num = inputlist(snippet) - 1
return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1]
endf
fun! ShowAvailableSnips()
let line = getline('.')
let col = col('.')
let word = matchstr(getline('.'), '\S\+\%'.col.'c')
let words = [word]
if stridx(word, '.')
let words += split(word, '\.', 1)
endif
let matchlen = 0
let matches = []
for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : []
if has_key(s:multi_snips, scope)
let triggers += keys(s:multi_snips[scope])
endif
for trigger in triggers
for word in words
if word == ''
let matches += [trigger] " Show all matches if word is empty
elseif trigger =~ '^'.word
let matches += [trigger]
let len = len(word)
if len > matchlen | let matchlen = len | endif
endif
endfor
endfor
endfor
" This is to avoid a bug with Vim when using complete(col - matchlen, matches)
" (Issue#46 on the Google Code snipMate issue tracker).
call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', ''))
call complete(col, matches)
return ''
endf
" vim:noet:sw=4:ts=4:ft=vim

@ -1,66 +0,0 @@
snippet if
If ${1:condition} Then
${2:; True code}
EndIf
snippet el
Else
${1}
snippet elif
ElseIf ${1:condition} Then
${2:; True code}
# If/Else block
snippet ifel
If ${1:condition} Then
${2:; True code}
Else
${3:; Else code}
EndIf
# If/ElseIf/Else block
snippet ifelif
If ${1:condition 1} Then
${2:; True code}
ElseIf ${3:condition 2} Then
${4:; True code}
Else
${5:; Else code}
EndIf
# Switch block
snippet switch
Switch (${1:condition})
Case {$2:case1}:
{$3:; Case 1 code}
Case Else:
{$4:; Else code}
EndSwitch
# Select block
snippet select
Select (${1:condition})
Case {$2:case1}:
{$3:; Case 1 code}
Case Else:
{$4:; Else code}
EndSelect
# While loop
snippet while
While (${1:condition})
${2:; code...}
WEnd
# For loop
snippet for
For ${1:n} = ${3:1} to ${2:count}
${4:; code...}
Next
# New Function
snippet func
Func ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
${4:Return}
EndFunc
# Message box
snippet msg
MsgBox(${3:MsgType}, ${1:"Title"}, ${2:"Message Text"})
# Debug Message
snippet debug
MsgBox(0, "Debug", ${1:"Debug Message"})
# Show Variable Debug Message
snippet showvar
MsgBox(0, "${1:VarName}", $1)

@ -1,113 +0,0 @@
# main()
snippet main
int main(int argc, const char *argv[])
{
${1}
return 0;
}
snippet mainn
int main(void)
{
${1}
return 0;
}
# #include <...>
snippet inc
#include <${1:stdio}.h>${2}
# #include "..."
snippet Inc
#include "${1:`Filename("$1.h")`}"${2}
# #ifndef ... #define ... #endif
snippet Def
#ifndef $1
#define ${1:SYMBOL} ${2:value}
#endif${3}
snippet def
#define
snippet ifdef
#ifdef ${1:FOO}
${2:#define }
#endif
snippet #if
#if ${1:FOO}
${2}
#endif
# Header Include-Guard
snippet once
#ifndef ${1:`toupper(Filename('$1_H', 'UNTITLED_H'))`}
#define $1
${2}
#endif /* end of include guard: $1 */
# If Condition
snippet if
if (${1:/* condition */}) {
${2:/* code */}
}
snippet el
else {
${1}
}
# Ternary conditional
snippet t
${1:/* condition */} ? ${2:a} : ${3:b}
# Do While Loop
snippet do
do {
${2:/* code */}
} while (${1:/* condition */});
# While Loop
snippet wh
while (${1:/* condition */}) {
${2:/* code */}
}
# For Loop
snippet for
for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) {
${4:/* code */}
}
# Custom For Loop
snippet forr
for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) {
${5:/* code */}
}
# Function
snippet fun
${1:void} ${2:function_name}(${3})
{
${4:/* code */}
}
# Function Declaration
snippet fund
${1:void} ${2:function_name}(${3});${4}
# Typedef
snippet td
typedef ${1:int} ${2:MyCustomType};${3}
# Struct
snippet st
struct ${1:`Filename('$1_t', 'name')`} {
${2:/* data */}
}${3: /* optional variable list */};${4}
# Typedef struct
snippet tds
typedef struct ${2:_$1 }{
${3:/* data */}
} ${1:`Filename('$1_t', 'name')`};
# Typdef enum
snippet tde
typedef enum {
${1:/* data */}
} ${2:foo};
# printf
# unfortunately version this isn't as nice as TextMates's, given the lack of a
# dynamic `...`
snippet pr
printf("${1:%s}\n"${2});${3}
# fprintf (again, this isn't as nice as TextMate's version, but it works)
snippet fpr
fprintf(${1:stderr}, "${2:%s}\n"${3});${4}
# This is kind of convenient
snippet .
[${1}]${2}

@ -1,34 +0,0 @@
# Read File Into Vector
snippet readfile
std::vector<char> v;
if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) {
char buf[1024];
while (size_t len = fread(buf, 1, sizeof(buf), $2))
v.insert(v.end(), buf, buf + len);
fclose($2);
}${3}
# std::map
snippet map
std::map<${1:key}, ${2:value}> map${3};
# std::vector
snippet vector
std::vector<${1:char}> v${2};
# Namespace
snippet ns
namespace ${1:`Filename('', 'my')`} {
${2}
} /* $1 */
# Class
snippet cl
class ${1:`Filename('$1_t', 'name')`} {
public:
$1 (${2:arguments});
virtual ~$1 ();
private:
${3:/* data */}
};
snippet fori
for (int ${2:i} = 0; $2 < ${1:count}; $2${3:++}) {
${4:/* code */}
}

@ -1,39 +0,0 @@
# module and export all
snippet mod
-module(${1:`Filename('', 'my')`}).
-compile([export_all]).
start() ->
${2}
stop() ->
ok.
# define directive
snippet def
-define(${1:macro}, ${2:body}).${3}
# export directive
snippet exp
-export([${1:function}/${2:arity}]).
# include directive
snippet inc
-include("${1:file}").${2}
# behavior directive
snippet beh
-behaviour(${1:behaviour}).${2}
# if expression
snippet if
if
${1:guard} ->
${2:body}
end
# case expression
snippet case
case ${1:expression} of
${2:pattern} ->
${3:body};
end
# record directive
snippet rec
-record(${1:record}, {
${2:field}=${3:value}}).${4}

@ -1,190 +0,0 @@
# Some useful Unicode entities
# Non-Breaking Space
snippet nbs
&nbsp;
# ←
snippet left
&#x2190;
# →
snippet right
&#x2192;
# ↑
snippet up
&#x2191;
# ↓
snippet down
&#x2193;
# ↩
snippet return
&#x21A9;
# ⇤
snippet backtab
&#x21E4;
# ⇥
snippet tab
&#x21E5;
# ⇧
snippet shift
&#x21E7;
# ⌃
snippet control
&#x2303;
# ⌅
snippet enter
&#x2305;
# ⌘
snippet command
&#x2318;
# ⌥
snippet option
&#x2325;
# ⌦
snippet delete
&#x2326;
# ⌫
snippet backspace
&#x232B;
# ⎋
snippet escape
&#x238B;
# Generic Doctype
snippet doctype HTML 4.01 Strict
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
snippet doctype HTML 4.01 Transitional
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
snippet doctype HTML 5
<!DOCTYPE HTML>
snippet doctype XHTML 1.0 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
snippet doctype XHTML 1.0 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
snippet doctype XHTML 1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
snippet doctype XHTML 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
# HTML Doctype 4.01 Strict
snippet docts
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
# HTML Doctype 4.01 Transitional
snippet doct
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
# HTML Doctype 5
snippet doct5
<!DOCTYPE HTML>
# XHTML Doctype 1.0 Frameset
snippet docxf
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
# XHTML Doctype 1.0 Strict
snippet docxs
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# XHTML Doctype 1.0 Transitional
snippet docxt
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
# XHTML Doctype 1.1
snippet docx
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
snippet html
<html>
${1}
</html>
snippet xhtml
<html xmlns="http://www.w3.org/1999/xhtml">
${1}
</html>
snippet body
<body>
${1}
</body>
snippet head
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"`Close()`>
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>
${2}
</head>
snippet title
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>${2}
snippet script
<script type="text/javascript" charset="utf-8">
${1}
</script>${2}
snippet scriptsrc
<script src="${1}.js" type="text/javascript" charset="utf-8"></script>${2}
snippet style
<style type="text/css" media="${1:screen}">
${2}
</style>${3}
snippet base
<base href="${1}" target="${2}"`Close()`>
snippet r
<br`Close()[1:]`>
snippet div
<div id="${1:name}">
${2}
</div>
# Embed QT Movie
snippet movie
<object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab">
<param name="src" value="$1"`Close()`>
<param name="controller" value="$4"`Close()`>
<param name="autoplay" value="$5"`Close()`>
<embed src="${1:movie.mov}"
width="${2:320}" height="${3:240}"
controller="${4:true}" autoplay="${5:true}"
scale="tofit" cache="true"
pluginspage="http://www.apple.com/quicktime/download/"
`Close()[1:]`>
</object>${6}
snippet fieldset
<fieldset id="$1">
<legend>${1:name}</legend>
${3}
</fieldset>
snippet form
<form action="${1:`Filename('$1_submit')`}" method="${2:get}" accept-charset="utf-8">
${3}
<p><input type="submit" value="Continue &rarr;"`Close()`></p>
</form>
snippet h1
<h1 id="${1:heading}">${2:$1}</h1>
snippet input
<input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="${3}"`Close()`>${4}
snippet label
<label for="${2:$1}">${1:name}</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="${5}" id="${6:$2}"`Close()`>${7}
snippet link
<link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" charset="utf-8"`Close()`>${4}
snippet mailto
<a href="mailto:${1:joe@example.com}?subject=${2:feedback}">${3:email me}</a>
snippet meta
<meta name="${1:name}" content="${2:content}"`Close()`>${3}
snippet opt
<option value="${1:option}">${2:$1}</option>${3}
snippet optt
<option>${1:option}</option>${2}
snippet select
<select name="${1:some_name}" id="${2:$1}">
<option value="${3:option}">${4:$3}</option>
</select>${5}
snippet table
<table border="${1:0}">
<tr><th>${2:Header}</th></tr>
<tr><th>${3:Data}</th></tr>
</table>${4}
snippet textarea
<textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">${4}</textarea>${5}

@ -1,95 +0,0 @@
snippet main
public static void main (String [] args)
{
${1:/* code */}
}
snippet pu
public
snippet po
protected
snippet pr
private
snippet st
static
snippet fi
final
snippet ab
abstract
snippet re
return
snippet br
break;
snippet de
default:
${1}
snippet ca
catch(${1:Exception} ${2:e}) ${3}
snippet th
throw
snippet sy
synchronized
snippet im
import
snippet imp
implements
snippet ext
extends
snippet j.u
java.util
snippet j.i
java.io.
snippet j.b
java.beans.
snippet j.n
java.net.
snippet j.m
java.math.
snippet if
if (${1}) ${2}
snippet el
else
snippet elif
else if (${1}) ${2}
snippet wh
while (${1}) ${2}
snippet for
for (${1}; ${2}; ${3}) ${4}
snippet fore
for (${1} : ${2}) ${3}
snippet sw
switch (${1}) ${2}
snippet cs
case ${1}:
${2}
${3}
snippet tc
public class ${1:`Filename()`} extends ${2:TestCase}
snippet t
public void test${1:Name}() throws Exception ${2}
snippet cl
class ${1:`Filename("", "untitled")`} ${2}
snippet in
interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3}
snippet m
${1:void} ${2:method}(${3}) ${4:throws }${5}
snippet v
${1:String} ${2:var}${3: = null}${4};${5}
snippet co
static public final ${1:String} ${2:var} = ${3};${4}
snippet cos
static public final String ${1:var} = "${2}";${3}
snippet as
assert ${1:test} : "${2:Failure message}";${3}
snippet try
try {
${3}
} catch(${1:Exception} ${2:e}) {
}
snippet tryf
try {
${3}
} catch(${1:Exception} ${2:e}) {
} finally {
}
snippet rst
ResultSet ${1:rst}${2: = null}${3};${4}

@ -1,74 +0,0 @@
# Prototype
snippet proto
${1:class_name}.prototype.${2:method_name} =
function(${3:first_argument}) {
${4:// body...}
};
# Function
snippet fun
function ${1:function_name} (${2:argument}) {
${3:// body...}
}
# Anonymous Function
snippet f
function(${1}) {${2}};
# if
snippet if
if (${1:true}) {${2}}
# if ... else
snippet ife
if (${1:true}) {${2}}
else{${3}}
# tertiary conditional
snippet t
${1:/* condition */} ? ${2:a} : ${3:b}
# switch
snippet switch
switch(${1:expression}) {
case '${3:case}':
${4:// code}
break;
${5}
default:
${2:// code}
}
# case
snippet case
case '${1:case}':
${2:// code}
break;
${3}
# for (...) {...}
snippet for
for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) {
${4:$1[$2]}
};
# for (...) {...} (Improved Native For-Loop)
snippet forr
for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) {
${4:$1[$2]}
};
# while (...) {...}
snippet wh
while (${1:/* condition */}) {
${2:/* code */}
}
# do...while
snippet do
do {
${2:/* code */}
} while (${1:/* condition */});
# Object Method
snippet :f
${1:method_name}: function(${2:attribute}) {
${4}
}${3:,}
# setTimeout function
snippet timeout
setTimeout(function() {${3}}${2}, ${1:10};
# Get Elements
snippet get
getElementsBy${1:TagName}('${2}')${3}
# Get Element
snippet gett
getElementBy${1:Id}('${2}')${3}

@ -1,54 +0,0 @@
snippet def
<%def name="${1:name}">
${2:}
</%def>
snippet call
<%call expr="${1:name}">
${2:}
</%call>
snippet doc
<%doc>
${1:}
</%doc>
snippet text
<%text>
${1:}
</%text>
snippet for
% for ${1:i} in ${2:iter}:
${3:}
% endfor
snippet if if
% if ${1:condition}:
${2:}
% endif
snippet if if/else
% if ${1:condition}:
${2:}
% else:
${3:}
% endif
snippet try
% try:
${1:}
% except${2:}:
${3:pass}
% endtry
snippet wh
% while ${1:}:
${2:}
% endwhile
snippet $
${ ${1:} }
snippet <%
<% ${1:} %>
snippet <!%
<!% ${1:} %>
snippet inherit
<%inherit file="${1:filename}" />
snippet include
<%include file="${1:filename}" />
snippet namespace
<%namespace file="${1:name}" />
snippet page
<%page args="${1:}" />

@ -1,247 +0,0 @@
# #import <...>
snippet Imp
#import <${1:Cocoa/Cocoa.h}>${2}
# #import "..."
snippet imp
#import "${1:`Filename()`.h}"${2}
# @selector(...)
snippet sel
@selector(${1:method}:)${3}
# @"..." string
snippet s
@"${1}"${2}
# Object
snippet o
${1:NSObject} *${2:foo} = [${3:$1 alloc}]${4};${5}
# NSLog(...)
snippet log
NSLog(@"${1:%@}"${2});${3}
# Class
snippet objc
@interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
{
}
@end
@implementation $1
${3}
@end
# Class Interface
snippet int
@interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
{${3}
}
${4}
@end
snippet @interface
@interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
{${3}
}
${4}
@end
# Class Implementation
snippet impl
@implementation ${1:`Filename('', 'someClass')`}
${2}
@end
snippet @implementation
@implementation ${1:`Filename('', 'someClass')`}
${2}
@end
# Protocol
snippet pro
@protocol ${1:`Filename('$1Delegate', 'MyProtocol')`} ${2:<NSObject>}
${3}
@end
snippet @protocol
@protocol ${1:`Filename('$1Delegate', 'MyProtocol')`} ${2:<NSObject>}
${3}
@end
# init Definition
snippet init
- (id)init
{
if (self = [super init]) {
${1}
}
return self;
}
# dealloc Definition
snippet dealloc
- (void) dealloc
{
${1:deallocations}
[super dealloc];
}
snippet su
[super ${1:init}]${2}
snippet ibo
IBOutlet ${1:NSSomeClass} *${2:$1};${3}
# Category
snippet cat
@interface ${1:NSObject} (${2:MyCategory})
@end
@implementation $1 ($2)
${3}
@end
# Category Interface
snippet cath
@interface ${1:`Filename('$1', 'NSObject')`} (${2:MyCategory})
${3}
@end
# Method
snippet m
- (${1:id})${2:method}
{
${3}
}
# Method declaration
snippet md
- (${1:id})${2:method};${3}
# IBAction declaration
snippet ibad
- (IBAction)${1:method}:(${2:id})sender;${3}
# IBAction method
snippet iba
- (IBAction)${1:method}:(${2:id})sender
{
${3}
}
# awakeFromNib method
snippet wake
- (void)awakeFromNib
{
${1}
}
# Class Method
snippet M
+ (${1:id})${2:method}
{
${3:return nil;}
}
# Sub-method (Call super)
snippet sm
- (${1:id})${2:method}
{
[super $2];${3}
return self;
}
# Accessor Methods For:
# Object
snippet objacc
- (${1:id})${2:thing}
{
return $2;
}
- (void)set$2:($1)${3:new$2}
{
[$3 retain];
[$2 release];
$2 = $3;
}${4}
# for (object in array)
snippet forin
for (${1:Class} *${2:some$1} in ${3:array}) {
${4}
}
snippet fore
for (${1:object} in ${2:array}) {
${3:statements}
}
snippet forarray
unsigned int ${1:object}Count = [${2:array} count];
for (unsigned int index = 0; index < $1Count; index++) {
${3:id} $1 = [$2 $1AtIndex:index];
${4}
}
snippet fora
unsigned int ${1:object}Count = [${2:array} count];
for (unsigned int index = 0; index < $1Count; index++) {
${3:id} $1 = [$2 $1AtIndex:index];
${4}
}
# Try / Catch Block
snippet @try
@try {
${1:statements}
}
@catch (NSException * e) {
${2:handler}
}
@finally {
${3:statements}
}
snippet @catch
@catch (${1:exception}) {
${2:handler}
}
snippet @finally
@finally {
${1:statements}
}
# IBOutlet
# @property (Objective-C 2.0)
snippet prop
@property (${1:retain}) ${2:NSSomeClass} ${3:*$2};${4}
# @synthesize (Objective-C 2.0)
snippet syn
@synthesize ${1:property};${2}
# [[ alloc] init]
snippet alloc
[[${1:foo} alloc] init${2}];${3}
snippet a
[[${1:foo} alloc] init${2}];${3}
# retain
snippet ret
[${1:foo} retain];${2}
# release
snippet rel
[${1:foo} release];
# autorelease
snippet arel
[${1:foo} autorelease];
# autorelease pool
snippet pool
NSAutoreleasePool *${1:pool} = [[NSAutoreleasePool alloc] init];
${2:/* code */}
[$1 drain];
# Throw an exception
snippet except
NSException *${1:badness};
$1 = [NSException exceptionWithName:@"${2:$1Name}"
reason:@"${3}"
userInfo:nil];
[$1 raise];
snippet prag
#pragma mark ${1:-}
snippet cl
@class ${1:Foo};${2}
snippet color
[[NSColor ${1:blackColor}] set];
# NSArray
snippet array
NSMutableArray *${1:array} = [NSMutable array];${2}
snippet nsa
NSArray ${1}
snippet nsma
NSMutableArray ${1}
snippet aa
NSArray * array;${1}
snippet ma
NSMutableArray * array;${1}
# NSDictionary
snippet dict
NSMutableDictionary *${1:dict} = [NSMutableDictionary dictionary];${2}
snippet nsd
NSDictionary ${1}
snippet nsmd
NSMutableDictionary ${1}
# NSString
snippet nss
NSString ${1}
snippet nsms
NSMutableString ${1}

@ -1,97 +0,0 @@
# #!/usr/bin/perl
snippet #!
#!/usr/bin/perl
# Hash Pointer
snippet .
=>
# Function
snippet sub
sub ${1:function_name} {
${2:#body ...}
}
# Conditional
snippet if
if (${1}) {
${2:# body...}
}
# Conditional if..else
snippet ife
if (${1}) {
${2:# body...}
}
else {
${3:# else...}
}
# Conditional if..elsif..else
snippet ifee
if (${1}) {
${2:# body...}
}
elsif (${3}) {
${4:# elsif...}
}
else {
${5:# else...}
}
# Conditional One-line
snippet xif
${1:expression} if ${2:condition};${3}
# Unless conditional
snippet unless
unless (${1}) {
${2:# body...}
}
# Unless conditional One-line
snippet xunless
${1:expression} unless ${2:condition};${3}
# Try/Except
snippet eval
eval {
${1:# do something risky...}
};
if ($@) {
${2:# handle failure...}
}
# While Loop
snippet wh
while (${1}) {
${2:# body...}
}
# While Loop One-line
snippet xwh
${1:expression} while ${2:condition};${3}
# C-style For Loop
snippet cfor
for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) {
${4:# body...}
}
# For loop one-line
snippet xfor
${1:expression} for @${2:array};${3}
# Foreach Loop
snippet for
foreach my $${1:x} (@${2:array}) {
${3:# body...}
}
# Foreach Loop One-line
snippet fore
${1:expression} foreach @${2:array};${3}
# Package
snippet cl
package ${1:ClassName};
use base qw(${2:ParentClass});
sub new {
my $class = shift;
$class = ref $class if ref $class;
my $self = bless {}, $class;
$self;
}
1;${3}
# Read File
snippet slurp
my $${1:var};
{ local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = <FILE>; close FILE }${3}

@ -1,216 +0,0 @@
snippet php
<?php
${1}
?>
snippet ec
echo "${1:string}"${2};
snippet inc
include '${1:file}';${2}
snippet inc1
include_once '${1:file}';${2}
snippet req
require '${1:file}';${2}
snippet req1
require_once '${1:file}';${2}
# $GLOBALS['...']
snippet globals
$GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5}
snippet $_ COOKIE['...']
$_COOKIE['${1:variable}']${2}
snippet $_ ENV['...']
$_ENV['${1:variable}']${2}
snippet $_ FILES['...']
$_FILES['${1:variable}']${2}
snippet $_ Get['...']
$_GET['${1:variable}']${2}
snippet $_ POST['...']
$_POST['${1:variable}']${2}
snippet $_ REQUEST['...']
$_REQUEST['${1:variable}']${2}
snippet $_ SERVER['...']
$_SERVER['${1:variable}']${2}
snippet $_ SESSION['...']
$_SESSION['${1:variable}']${2}
# Start Docblock
snippet /*
/**
* ${1}
**/
# Class - post doc
snippet doc_cp
/**
* ${1:undocumented class}
*
* @package ${2:default}
* @author ${3:`g:snips_author`}
**/${4}
# Class Variable - post doc
snippet doc_vp
/**
* ${1:undocumented class variable}
*
* @var ${2:string}
**/${3}
# Class Variable
snippet doc_v
/**
* ${3:undocumented class variable}
*
* @var ${4:string}
**/
${1:var} $${2};${5}
# Class
snippet doc_c
/**
* ${3:undocumented class}
*
* @packaged ${4:default}
* @author ${5:`g:snips_author`}
**/
${1:}class ${2:}
{${6}
} // END $1class $2
# Constant Definition - post doc
snippet doc_dp
/**
* ${1:undocumented constant}
**/${2}
# Constant Definition
snippet doc_d
/**
* ${3:undocumented constant}
**/
define(${1}, ${2});${4}
# Function - post doc
snippet doc_fp
/**
* ${1:undocumented function}
*
* @return ${2:void}
* @author ${3:`g:snips_author`}
**/${4}
# Function signature
snippet doc_s
/**
* ${4:undocumented function}
*
* @return ${5:void}
* @author ${6:`g:snips_author`}
**/
${1}function ${2}(${3});${7}
# Function
snippet doc_f
/**
* ${4:undocumented function}
*
* @return ${5:void}
* @author ${6:`g:snips_author`}
**/
${1}function ${2}(${3})
{${7}
}
# Header
snippet doc_h
/**
* ${1}
*
* @author ${2:`g:snips_author`}
* @version ${3:$Id$}
* @copyright ${4:$2}, `strftime('%d %B, %Y')`
* @package ${5:default}
**/
/**
* Define DocBlock
*//
# Interface
snippet doc_i
/**
* ${2:undocumented class}
*
* @package ${3:default}
* @author ${4:`g:snips_author`}
**/
interface ${1:}
{${5}
} // END interface $1
# class ...
snippet class
/**
* ${1}
**/
class ${2:ClassName}
{
${3}
function ${4:__construct}(${5:argument})
{
${6:// code...}
}
}
# define(...)
snippet def
define('${1}'${2});${3}
# defined(...)
snippet def?
${1}defined('${2}')${3}
snippet wh
while (${1:/* condition */}) {
${2:// code...}
}
# do ... while
snippet do
do {
${2:// code... }
} while (${1:/* condition */});
snippet if
if (${1:/* condition */}) {
${2:// code...}
}
snippet ife
if (${1:/* condition */}) {
${2:// code...}
} else {
${3:// code...}
}
${4}
snippet else
else {
${1:// code...}
}
snippet elseif
elseif (${1:/* condition */}) {
${2:// code...}
}
# Tertiary conditional
snippet t
$${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5}
snippet switch
switch ($${1:variable}) {
case '${2:value}':
${3:// code...}
break;
${5}
default:
${4:// code...}
break;
}
snippet case
case '${1:value}':
${2:// code...}
break;${3}
snippet for
for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {
${4: // code...}
}
snippet foreach
foreach ($${1:variable} as $${2:key}) {
${3:// code...}
}
snippet fun
${1:public }function ${2:FunctionName}(${3})
{
${4:// code...}
}
# $... = array (...)
snippet array
$${1:arrayName} = array('${2}' => ${3});${4}

@ -1,86 +0,0 @@
snippet #!
#!/usr/bin/env python
snippet imp
import ${1:module}
# Module Docstring
snippet docs
'''
File: ${1:`Filename('$1.py', 'foo.py')`}
Author: ${2:`g:snips_author`}
Description: ${3}
'''
snippet wh
while ${1:condition}:
${2:# code...}
snippet for
for ${1:needle} in ${2:haystack}:
${3:# code...}
# New Class
snippet cl
class ${1:ClassName}(${2:object}):
"""${3:docstring for $1}"""
def __init__(self, ${4:arg}):
${5:super($1, self).__init__()}
self.$4 = $4
${6}
# New Function
snippet def
def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
"""${3:docstring for $1}"""
${4:pass}
snippet deff
def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
${3}
# New Method
snippet defs
def ${1:mname}(self, ${2:arg}):
${3:pass}
# New Property
snippet property
def ${1:foo}():
doc = "${2:The $1 property.}"
def fget(self):
${3:return self._$1}
def fset(self, value):
${4:self._$1 = value}
# Lambda
snippet ld
${1:var} = lambda ${2:vars} : ${3:action}
snippet .
self.
snippet try Try/Except
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
snippet try Try/Except/Else
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
else:
${5:pass}
snippet try Try/Except/Finally
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
finally:
${5:pass}
snippet try Try/Except/Else/Finally
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
else:
${5:pass}
finally:
${6:pass}
# if __name__ == '__main__':
snippet ifmain
if __name__ == '__main__':
${1:main()}
# __magic__
snippet _
__${1:init}__${2}

@ -1,504 +0,0 @@
# #!/usr/bin/env ruby
snippet #!
#!/usr/bin/env ruby
# New Block
snippet =b
=begin rdoc
${1}
=end
snippet y
:yields: ${1:arguments}
snippet rb
#!/usr/bin/env ruby -wKU
snippet beg
begin
${3}
rescue ${1:Exception} => ${2:e}
end
snippet req
require "${1}"${2}
snippet #
# =>
snippet end
__END__
snippet case
case ${1:object}
when ${2:condition}
${3}
end
snippet when
when ${1:condition}
${2}
snippet def
def ${1:method_name}
${2}
end
snippet deft
def test_${1:case_name}
${2}
end
snippet if
if ${1:condition}
${2}
end
snippet ife
if ${1:condition}
${2}
else
${3}
end
snippet elsif
elsif ${1:condition}
${2}
snippet unless
unless ${1:condition}
${2}
end
snippet while
while ${1:condition}
${2}
end
snippet for
for ${1:e} in ${2:c}
${3}
end
snippet until
until ${1:condition}
${2}
end
snippet cla class .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`}
${2}
end
snippet cla class .. initialize .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`}
def initialize(${2:args})
${3}
end
end
snippet cla class .. < ParentClass .. initialize .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass}
def initialize(${3:args})
${4}
end
end
snippet cla ClassName = Struct .. do .. end
${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do
def ${3:method_name}
${4}
end
end
snippet cla class BlankSlate .. initialize .. end
class ${1:BlankSlate}
instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ }
snippet cla class << self .. end
class << ${1:self}
${2}
end
# class .. < DelegateClass .. initialize .. end
snippet cla-
class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass})
def initialize(${3:args})
super(${4:del_obj})
${5}
end
end
snippet mod module .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
${2}
end
snippet mod module .. module_function .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
module_function
${2}
end
snippet mod module .. ClassMethods .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
module ClassMethods
${2}
end
module InstanceMethods
end
def self.included(receiver)
receiver.extend ClassMethods
receiver.send :include, InstanceMethods
end
end
# attr_reader
snippet r
attr_reader :${1:attr_names}
# attr_writer
snippet w
attr_writer :${1:attr_names}
# attr_accessor
snippet rw
attr_accessor :${1:attr_names}
# include Enumerable
snippet Enum
include Enumerable
def each(&block)
${1}
end
# include Comparable
snippet Comp
include Comparable
def <=>(other)
${1}
end
# extend Forwardable
snippet Forw-
extend Forwardable
# def self
snippet defs
def self.${1:class_method_name}
${2}
end
# def method_missing
snippet defmm
def method_missing(meth, *args, &blk)
${1}
end
snippet defd
def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name}
snippet defds
def_delegators :${1:@del_obj}, :${2:del_methods}
snippet am
alias_method :${1:new_name}, :${2:old_name}
snippet app
if __FILE__ == $PROGRAM_NAME
${1}
end
# usage_if()
snippet usai
if ARGV.${1}
abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
end
# usage_unless()
snippet usau
unless ARGV.${1}
abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
end
snippet array
Array.new(${1:10}) { |${2:i}| ${3} }
snippet hash
Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} }
snippet file File.foreach() { |line| .. }
File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} }
snippet file File.read()
File.read(${1:"path/to/file"})${2}
snippet Dir Dir.global() { |file| .. }
Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} }
snippet Dir Dir[".."]
Dir[${1:"glob/**/*.rb"}]${2}
snippet dir
Filename.dirname(__FILE__)
snippet deli
delete_if { |${1:e}| ${2} }
snippet fil
fill(${1:range}) { |${2:i}| ${3} }
# flatten_once()
snippet flao
inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3}
snippet zip
zip(${1:enums}) { |${2:row}| ${3} }
# downto(0) { |n| .. }
snippet dow
downto(${1:0}) { |${2:n}| ${3} }
snippet ste
step(${1:2}) { |${2:n}| ${3} }
snippet tim
times { |${1:n}| ${2} }
snippet upt
upto(${1:1.0/0.0}) { |${2:n}| ${3} }
snippet loo
loop { ${1} }
snippet ea
each { |${1:e}| ${2} }
snippet ead
each do |${1:e}|
${2}
end
snippet eab
each_byte { |${1:byte}| ${2} }
snippet eac- each_char { |chr| .. }
each_char { |${1:chr}| ${2} }
snippet eac- each_cons(..) { |group| .. }
each_cons(${1:2}) { |${2:group}| ${3} }
snippet eai
each_index { |${1:i}| ${2} }
snippet eaid
each_index do |${1:i}|
end
snippet eak
each_key { |${1:key}| ${2} }
snippet eakd
each_key do |${1:key}|
${2}
end
snippet eal
each_line { |${1:line}| ${2} }
snippet eald
each_line do |${1:line}|
${2}
end
snippet eap
each_pair { |${1:name}, ${2:val}| ${3} }
snippet eapd
each_pair do |${1:name}, ${2:val}|
${3}
end
snippet eas-
each_slice(${1:2}) { |${2:group}| ${3} }
snippet easd-
each_slice(${1:2}) do |${2:group}|
${3}
end
snippet eav
each_value { |${1:val}| ${2} }
snippet eavd
each_value do |${1:val}|
${2}
end
snippet eawi
each_with_index { |${1:e}, ${2:i}| ${3} }
snippet eawid
each_with_index do |${1:e},${2:i}|
${3}
end
snippet reve
reverse_each { |${1:e}| ${2} }
snippet reved
reverse_each do |${1:e}|
${2}
end
snippet inj
inject(${1:init}) { |${2:mem}, ${3:var}| ${4} }
snippet injd
inject(${1:init}) do |${2:mem}, ${3:var}|
${4}
end
snippet map
map { |${1:e}| ${2} }
snippet mapd
map do |${1:e}|
${2}
end
snippet mapwi-
enum_with_index.map { |${1:e}, ${2:i}| ${3} }
snippet sor
sort { |a, b| ${1} }
snippet sorb
sort_by { |${1:e}| ${2} }
snippet ran
sort_by { rand }
snippet all
all? { |${1:e}| ${2} }
snippet any
any? { |${1:e}| ${2} }
snippet cl
classify { |${1:e}| ${2} }
snippet col
collect { |${1:e}| ${2} }
snippet cold
collect do |${1:e}|
${2}
end
snippet det
detect { |${1:e}| ${2} }
snippet detd
detect do |${1:e}|
${2}
end
snippet fet
fetch(${1:name}) { |${2:key}| ${3} }
snippet fin
find { |${1:e}| ${2} }
snippet find
find do |${1:e}|
${2}
end
snippet fina
find_all { |${1:e}| ${2} }
snippet finad
find_all do |${1:e}|
${2}
end
snippet gre
grep(${1:/pattern/}) { |${2:match}| ${3} }
snippet sub
${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} }
snippet sca
scan(${1:/pattern/}) { |${2:match}| ${3} }
snippet scad
scan(${1:/pattern/}) do |${2:match}|
${3}
end
snippet max
max { |a, b| ${1} }
snippet min
min { |a, b| ${1} }
snippet par
partition { |${1:e}| ${2} }
snippet pard
partition do |${1:e}|
${2}
end
snippet rej
reject { |${1:e}| ${2} }
snippet rejd
reject do |${1:e}|
${2}
end
snippet sel
select { |${1:e}| ${2} }
snippet seld
select do |${1:e}|
${2}
end
snippet lam
lambda { |${1:args}| ${2} }
snippet do
do |${1:variable}|
${2}
end
snippet :
:${1:key} => ${2:"value"}${3}
snippet ope
open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} }
# path_from_here()
snippet patfh
File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2}
# unix_filter {}
snippet unif
ARGF.each_line${1} do |${2:line}|
${3}
end
# option_parse {}
snippet optp
require "optparse"
options = {${1:default => "args"}}
ARGV.options do |opts|
opts.banner = "Usage: #{File.basename($PROGRAM_NAME)}
snippet opt
opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String},
"${4:Option description.}") do |${5:opt}|
${6}
end
snippet tc
require "test/unit"
require "${1:library_file_name}"
class Test${2:$1} < Test::Unit::TestCase
def test_${3:case_name}
${4}
end
end
snippet ts
require "test/unit"
require "tc_${1:test_case_file}"
require "tc_${2:test_case_file}"${3}
snippet as
assert(${1:test}, "${2:Failure message.}")${3}
snippet ase
assert_equal(${1:expected}, ${2:actual})${3}
snippet asne
assert_not_equal(${1:unexpected}, ${2:actual})${3}
snippet asid
assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4}
snippet asio
assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3}
snippet asko
assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3}
snippet asn
assert_nil(${1:instance})${2}
snippet asnn
assert_not_nil(${1:instance})${2}
snippet asm
assert_match(/${1:expected_pattern}/, ${2:actual_string})${3}
snippet asnm
assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3}
snippet aso
assert_operator(${1:left}, :${2:operator}, ${3:right})${4}
snippet asr
assert_raise(${1:Exception}) { ${2} }
snippet asnr
assert_nothing_raised(${1:Exception}) { ${2} }
snippet asrt
assert_respond_to(${1:object}, :${2:method})${3}
snippet ass assert_same(..)
assert_same(${1:expected}, ${2:actual})${3}
snippet ass assert_send(..)
assert_send([${1:object}, :${2:message}, ${3:args}])${4}
snippet asns
assert_not_same(${1:unexpected}, ${2:actual})${3}
snippet ast
assert_throws(:${1:expected}) { ${2} }
snippet asnt
assert_nothing_thrown { ${1} }
snippet fl
flunk("${1:Failure message.}")${2}
# Benchmark.bmbm do .. end
snippet bm-
TESTS = ${1:10_000}
Benchmark.bmbm do |results|
${2}
end
snippet rep
results.report("${1:name}:") { TESTS.times { ${2} }}
# Marshal.dump(.., file)
snippet Md
File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4}
# Mashal.load(obj)
snippet Ml
File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3}
# deep_copy(..)
snippet deec
Marshal.load(Marshal.dump(${1:obj_to_copy}))${2}
snippet Pn-
PStore.new(${1:"file_name.pstore"})${2}
snippet tra
transaction(${1:true}) { ${2} }
# xmlread(..)
snippet xml-
REXML::Document.new(File.read(${1:"path/to/file"}))${2}
# xpath(..) { .. }
snippet xpa
elements.each(${1:"//Xpath"}) do |${2:node}|
${3}
end
# class_from_name()
snippet clafn
split("::").inject(Object) { |par, const| par.const_get(const) }
# singleton_class()
snippet sinc
class << self; self end
snippet nam
namespace :${1:`Filename()`} do
${2}
end
snippet tas
desc "${1:Task description\}"
task :${2:task_name => [:dependent, :tasks]} do
${3}
end

@ -1,28 +0,0 @@
# #!/bin/bash
snippet #!
#!/bin/bash
snippet if
if [[ ${1:condition} ]]; then
${2:#statements}
fi
snippet elif
elif [[ ${1:condition} ]]; then
${2:#statements}
snippet for
for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
${3:#statements}
done
snippet wh
while [[ ${1:condition} ]]; do
${2:#statements}
done
snippet until
until [[ ${1:condition} ]]; do
${2:#statements}
done
snippet case
case ${1:word} in
${2:pattern})
${3};;
esac

@ -1,7 +0,0 @@
# snippets for making snippets :)
snippet snip
snippet ${1:trigger}
${2}
snippet msnip
snippet ${1:trigger} ${2:description}
${3}

@ -1,92 +0,0 @@
# #!/usr/bin/env tclsh
snippet #!
#!/usr/bin/env tclsh
# Process
snippet pro
proc ${1:function_name} {${2:args}} {
${3:#body ...}
}
#xif
snippet xif
${1:expr}? ${2:true} : ${3:false}
# Conditional
snippet if
if {${1}} {
${2:# body...}
}
# Conditional if..else
snippet ife
if {${1}} {
${2:# body...}
} else {
${3:# else...}
}
# Conditional if..elsif..else
snippet ifee
if {${1}} {
${2:# body...}
} elseif {${3}} {
${4:# elsif...}
} else {
${5:# else...}
}
# If catch then
snippet ifc
if { [catch {${1:#do something...}} ${2:err}] } {
${3:# handle failure...}
}
# Catch
snippet catch
catch {${1}} ${2:err} ${3:options}
# While Loop
snippet wh
while {${1}} {
${2:# body...}
}
# For Loop
snippet for
for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} {
${4:# body...}
}
# Foreach Loop
snippet fore
foreach ${1:x} {${2:#list}} {
${3:# body...}
}
# after ms script...
snippet af
after ${1:ms} ${2:#do something}
# after cancel id
snippet afc
after cancel ${1:id or script}
# after idle
snippet afi
after idle ${1:script}
# after info id
snippet afin
after info ${1:id}
# Expr
snippet exp
expr {${1:#expression here}}
# Switch
snippet sw
switch ${1:var} {
${3:pattern 1} {
${4:#do something}
}
default {
${2:#do something}
}
}
# Case
snippet ca
${1:pattern} {
${2:#do something}
}${3}
# Namespace eval
snippet ns
namespace eval ${1:path} {${2:#script...}}
# Namespace current
snippet nsc
namespace current

@ -1,115 +0,0 @@
# \begin{}...\end{}
snippet begin
\begin{${1:env}}
${2}
\end{$1}
# Tabular
snippet tab
\begin{${1:tabular}}{${2:c}}
${3}
\end{$1}
# Align(ed)
snippet ali
\begin{align${1:ed}}
${2}
\end{align$1}
# Gather(ed)
snippet gat
\begin{gather${1:ed}}
${2}
\end{gather$1}
# Equation
snippet eq
\begin{equation}
${1}
\end{equation}
# Unnumbered Equation
snippet \
\\[
${1}
\\]
# Enumerate
snippet enum
\begin{enumerate}
\item ${1}
\end{enumerate}
# Itemize
snippet item
\begin{itemize}
\item ${1}
\end{itemize}
# Description
snippet desc
\begin{description}
\item[${1}] ${2}
\end{description}
# Matrix
snippet mat
\begin{${1:p/b/v/V/B/small}matrix}
${2}
\end{$1matrix}
# Cases
snippet cas
\begin{cases}
${1:equation}, &\text{ if }${2:case}\\
${3}
\end{cases}
# Split
snippet spl
\begin{split}
${1}
\end{split}
# Part
snippet part
\part{${1:part name}} % (fold)
\label{prt:${2:$1}}
${3}
% part $2 (end)
# Chapter
snippet cha
\chapter{${1:chapter name}} % (fold)
\label{cha:${2:$1}}
${3}
% chapter $2 (end)
# Section
snippet sec
\section{${1:section name}} % (fold)
\label{sec:${2:$1}}
${3}
% section $2 (end)
# Sub Section
snippet sub
\subsection{${1:subsection name}} % (fold)
\label{sub:${2:$1}}
${3}
% subsection $2 (end)
# Sub Sub Section
snippet subs
\subsubsection{${1:subsubsection name}} % (fold)
\label{ssub:${2:$1}}
${3}
% subsubsection $2 (end)
# Paragraph
snippet par
\paragraph{${1:paragraph name}} % (fold)
\label{par:${2:$1}}
${3}
% paragraph $2 (end)
# Sub Paragraph
snippet subp
\subparagraph{${1:subparagraph name}} % (fold)
\label{subp:${2:$1}}
${3}
% subparagraph $2 (end)
snippet itd
\item[${1:description}] ${2:item}
snippet figure
${1:Figure}~\ref{${2:fig:}}${3}
snippet table
${1:Table}~\ref{${2:tab:}}${3}
snippet listing
${1:Listing}~\ref{${2:list}}${3}
snippet section
${1:Section}~\ref{${2:sec:}}${3}
snippet page
${1:page}~\pageref{${2}}${3}

@ -1,32 +0,0 @@
snippet header
" File: ${1:`expand('%:t')`}
" Author: ${2:`g:snips_author`}
" Description: ${3}
${4:" Last Modified: `strftime("%B %d, %Y")`}
snippet guard
if exists('${1:did_`Filename()`}') || &cp${2: || version < 700}
finish
endif
let $1 = 1${3}
snippet f
fun ${1:function_name}(${2})
${3:" code}
endf
snippet for
for ${1:needle} in ${2:haystack}
${3:" code}
endfor
snippet wh
while ${1:condition}
${2:" code}
endw
snippet if
if ${1:condition}
${2:" code}
endif
snippet ife
if ${1:condition}
${2}
else
${3}
endif

@ -1,58 +0,0 @@
# #!/bin/zsh
snippet #!
#!/bin/zsh
snippet if
if ${1:condition}; then
${2:# statements}
fi
snippet ife
if ${1:condition}; then
${2:# statements}
else
${3:# statements}
fi
snippet elif
elif ${1:condition} ; then
${2:# statements}
snippet for
for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
${3:# statements}
done
snippet fore
for ${1:item} in ${2:list}; do
${3:# statements}
done
snippet wh
while ${1:condition}; do
${2:# statements}
done
snippet until
until ${1:condition}; do
${2:# statements}
done
snippet repeat
repeat ${1:integer}; do
${2:# statements}
done
snippet case
case ${1:word} in
${2:pattern})
${3};;
esac
snippet select
select ${1:answer} in ${2:choices}; do
${3:# statements}
done
snippet (
( ${1:#statements} )
snippet {
{ ${1:#statements} }
snippet [
[[ ${1:test} ]]
snippet always
{ ${1:try} } always { ${2:always} }
snippet fun
function ${1:name} (${2:args}) {
${3:# body}
}

@ -1,19 +0,0 @@
" Syntax highlighting for snippet files (used for snipMate.vim)
" Hopefully this should make snippets a bit nicer to write!
syn match snipComment '^#.*'
syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand
syn match tabStop '\$\d\+'
syn match snipCommand '[^\\]`.\{-}`'
syn match snippet '^snippet.*' transparent contains=multiSnipText,snipKeyword
syn match multiSnipText '\S\+ \zs.*' contained
syn match snipKeyword '^snippet'me=s+8 contained
syn match snipError "^[^#s\t].*$"
hi link snipComment Comment
hi link multiSnipText String
hi link snipKeyword Keyword
hi link snipComment Comment
hi link placeHolder Special
hi link tabStop Special
hi link snipCommand String
hi link snipError Error

@ -1,4 +0,0 @@
*.swp
*.vmb
doc/tags
/README.html

@ -1,17 +0,0 @@
SHELL=/bin/bash
all: dist
dist:
@rm supertab.vmb 2> /dev/null || true
@vim -c 'r! git ls-files doc plugin' \
-c '$$,$$d _' -c '%MkVimball supertab .' -c 'q!'
clean:
@rm -R build 2> /dev/null || true
install: supertab.vmb
vim $< -c 'so %' -c 'q'
uninstall:
vim -c 'RmVimball supertab.vmb' -c 'q'

@ -1,172 +0,0 @@
.. Copyright (c) 2012 - 2014, Eric Van Dewoestine
All rights reserved.
Redistribution and use of this software in source and binary forms, with
or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of Eric Van Dewoestine nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission of
Eric Van Dewoestine.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.. _overview:
==================
Overview
==================
Supertab is a vim plugin which allows you to use <Tab> for all your insert
completion needs (:help ins-completion).
Features
--------
- Configurable to suit you needs:
- Default completion type to use.
- Prevent <Tab> from completing after/before defined patterns.
- Close vim's completion preview window when code completion is finished.
- When using other completion types, you can configure how long to 'remember'
the current completion type before returning to the default.
- Don't like using <Tab>? You can also configure a different pair of keys to
scroll forwards and backwards through completion results.
- Optional improved 'longest' completion support (after typing some characters,
hitting <Tab> will highlight the next longest match).
- Built in 'context' completion option which chooses the appropriate completion
type based on the text preceding the cursor.
- You can also plug in your own functions to determine which completion type
to use.
- Support for simple completion chaining (falling back to a different
completion type, keyword completion for example, if omni or user completion
returns no results).
Installation
------------
You have a few options when it comes to installing supertab:
1. Use your linux package manager:
Some linux distributions include a supertab package so you don't have to
manage the install/upgrade of supertab separately from other software on your
system.
2. Use a vim plugin manager:
There are several plugin managers for vim, which will either allow you to
manually clone vim plugin repositories, or will do so for you. Probably the
two most popular ones currently are `pathogen
<https://github.com/tpope/vim-pathogen>`_ and `vundle
<https://github.com/gmarik/Vundle.vim>`_. Please refer to their docs for
instructions on how to install plugins.
3. And lastly you can use the vimball (.vmb) file found on
`vim.org <http://www.vim.org/scripts/script.php?script_id=1643>`_:
Vimball files are installed by simply opening them in vim and then sourcing
the file:
::
$ vim supertab.vmb
:source %
Frequently Asked Questions
--------------------------
- **Why isn't supertab honoring my configured settings (attempts to complete at the
start of a line, always performs keyword completion instead of my configured
default, etc.)?**
Chances are that you have a very old version of `snipmate
<https://github.com/msanders/snipmate.vim>`_ installed, or something similar,
which will issue a `<c-n>` when no snippet is found. Supertab use to map to
`<c-n>`, so this behavior would act as a fallback to supertab, but current
versions of supertab no longer do so, resulting in snipmate bypassing supertab
entirely.
You can check if this is the case by running the following in vim to see what
is mapped to `<tab>`:
::
:verbose imap <tab>
To resolve the issue you can either:
#. Install my `fork <https://github.com/ervandew/snipmate.vim>`_ or
#. Upgrade to a more recent snipmate fork, like `garbase/vim-snipmate
<https://github.com/garbas/vim-snipmate>`_
See `#74 <https://github.com/ervandew/supertab/issues/74>`_ for additional
details.
- **Why does <tab> navigate the completion menu from bottom to top?**
First, if after reading the explanation below (or if you don't want to bother
reading it), you still want the default to scroll down the list then you can
use:
::
let g:SuperTabDefaultCompletionType = "<c-n>"
or if your default completion type is currently `context` then you can use
this instead:
::
let g:SuperTabContextDefaultCompletionType = "<c-n>"
Now on to the reasoning behind this. When using `<c-p>` or `<c-n>` to start
insert completion, both populate the completion popup with the same list of
words in the same order, the only difference is that `<c-p>` highlights the
nearest matching word located above the current cursor position, which is the
result at the bottom of the completion popup. Without supertab installed,
continuing to hit `<c-p>` will walk up the list to next nearest word above the
cursor.
I think Bram chose to display the results like this so that
#. the completion logic is the same for `<c-n>` and `<c-p>`, only the first
entry to highlight differs
#. so that the behavior of `<c-p>` mode is consistent, always moving up the
list and
#. when starting `<c-p>` mode you don't have to switch over to
using `<c-n>` to get the next nearest entry, just continue to hit `<c-p>`.
So, with supertab I wanted to preserve the same behavior. If `<c-p>` is your
default completion method (supertab defaults to this being the case), then
`<tab>` will start it and additional uses of `<tab>` will move up the list
instead of down so that you don't have to suddenly switch to using `<s-tab>`
to get the next nearest result.
Why is `<c-p>` the supertab default? The original supertab author found (and I
agree with his finding) that while coding, the keyword match you want is
typically the closer of the matches above the cursor, which `<c-p>` naturally
provides.

@ -1,442 +0,0 @@
*supertab.txt*
Author: Eric Van Dewoestine <ervandew@gmail.com>
Original concept and versions up to 0.32 written by
Gergely Kontra <kgergely@mcl.hu>
This plugin is licensed under the terms of the BSD License. Please see
supertab.vim for the license in its entirety.
==============================================================================
Supertab *supertab*
1. Introduction |supertab-intro|
2. Supertab Usage |supertab-usage|
3. Supertab Options |supertab-options|
Default completion type |supertab-defaultcompletion|
Secondary default completion type |supertab-contextdefault|
Completion contexts |supertab-completioncontexts|
Context text |supertab-contexttext|
Context Discover |supertab-contextdiscover|
Example |supertab-contextexample|
Completion Duration |supertab-duration|
Preventing Completion After/Before... |supertab-preventcomplete|
Changing default mapping |supertab-forwardbackward|
Inserting true tabs |supertab-mappingtabliteral|
Enhanced longest match support |supertab-longestenhanced|
Preselecting the first entry |supertab-longesthighlight|
Mapping <cr> to end completion |supertab-crmapping|
Auto close the preview window |supertab-closepreviewonpopupclose|
Completion Chaining |supertab-completionchaining|
==============================================================================
1. Introduction *supertab-intro*
Supertab is a plugin which allows you to perform all your insert completion
(|ins-completion|) using the tab key.
Supertab requires Vim version 7.0 or above.
==============================================================================
2. Supertab usage *supertab-usage*
Using Supertab is as easy as hitting <Tab> or <S-Tab> (shift+tab) while in
insert mode, with at least one non whitespace character before the cursor, to
start the completion and then <Tab> or <S-Tab> again to cycle forwards or
backwards through the available completions.
Example ('|' denotes the cursor location):
bar
baz
b|<Tab> Hitting <Tab> here will start the completion, allowing you to
then cycle through the suggested words ('bar' and 'baz').
==============================================================================
3. Supertab Options *supertab-options*
Supertab is configured via several global variables that you can set in your
|vimrc| file according to your needs. Below is a comprehensive list of
the variables available.
Default Completion Type *supertab-defaultcompletion*
*g:SuperTabDefaultCompletionType*
g:SuperTabDefaultCompletionType (default value: "<c-p>")
Used to set the default completion type. There is no need to escape this
value as that will be done for you when the type is set.
Example: setting the default completion to 'user' completion:
>
let g:SuperTabDefaultCompletionType = "<c-x><c-u>"
<
Note: a special value of 'context' is supported which will result in
super tab attempting to use the text preceding the cursor to decide which
type of completion to attempt. Currently supertab can recognize method calls
or attribute references via '.', '::' or '->', and file path references
containing '/'. If the language you are using doesn't use any of the member
reference characters listed above, or you'd like to add additional patterns,
you can write a custom context function also described in the next section
(Completion context).
Example: setting the default completion to supertab's 'context' completion:
>
let g:SuperTabDefaultCompletionType = "context"
<
/usr/l<tab> # will use filename completion
myvar.t<tab> # will use user completion if completefunc set,
# or omni completion if omnifunc set.
myvar-><tab> # same as above
When using context completion, super tab will fall back to a secondary default
completion type set by |g:SuperTabContextDefaultCompletionType|.
Note: once the buffer has been initialized, changing the value of this setting
will not change the default complete type used. If you want to change the
default completion type for the current buffer after it has been set, perhaps
in an ftplugin, you'll need to call *SuperTabSetDefaultCompletionType* like so,
supplying the completion type you wish to switch to:
>
call SuperTabSetDefaultCompletionType("<c-x><c-u>")
<
Secondary default completion type *supertab-contextdefault*
*g:SuperTabContextDefaultCompletionType*
g:SuperTabContextDefaultCompletionType (default value: "<c-p>")
Sets the default completion type used when g:SuperTabDefaultCompletionType is
set to 'context' and no completion type is returned by any of the configured
contexts.
Completion contexts *supertab-completioncontexts*
*g:SuperTabCompletionContexts*
g:SuperTabCompletionContexts (default value: ['s:ContextText'])
Sets the list of contexts used for context completion. This value should
be a list of function names which provide the context implementation.
When supertab starts context completion, each of these contexts will be
consulted, in the order they were supplied, to determine the completion type
to use. If a context returns a completion type, that type will be used,
otherwise the next context in the list will be consulted. If after executing
all the context functions, no completion type has been determined, then the
value of |g:SuperTabContextDefaultCompletionType| will be used.
Note: supertab also supports the b:SuperTabCompletionContexts variable
allowing you to set the list of contexts separately for the current buffer,
like from an ftplugin for example.
Built in completion contexts:
s:ContextText *supertab-contexttext*
The text context will examine the text near the cursor to decide which type
of completion to attempt. Currently the text context can recognize method
calls or attribute references via '.', '::' or '->', and file path
references containing '/'.
/usr/l<tab> # will use filename completion
myvar.t<tab> # will use user completion if completefunc set, or
# omni completion if omnifunc set.
myvar-><tab> # same as above
Supported configuration attributes:
*g:SuperTabContextTextFileTypeExclusions*
List of file types for which the text context will be skipped.
*g:SuperTabContextTextOmniPrecedence*
List of omni completion option names in the order of precedence that they
should be used if available. By default, user completion will be given
precedence over omni completion, but you can use this variable to give
omni completion higher precedence by placing it first in the list.
s:ContextDiscover *supertab-contextdiscover*
This context will use the 'g:SuperTabContextDiscoverDiscovery' variable to
determine the completion type to use. It will evaluate each value, in the
order they were defined, until a variable evaluates to a non-zero or
non-empty value, then the associated completion type is used.
Supported configuration properties:
g:SuperTabContextDiscoverDiscovery
List of variable:completionType mappings.
Example context configuration: *supertab-contextexample*
>
let g:SuperTabCompletionContexts = ['s:ContextText', 's:ContextDiscover']
let g:SuperTabContextTextOmniPrecedence = ['&omnifunc', '&completefunc']
let g:SuperTabContextDiscoverDiscovery =
\ ["&completefunc:<c-x><c-u>", "&omnifunc:<c-x><c-o>"]
<
In addition to the default completion contexts, you can plug in your own
implementation by creating a globally accessible function that returns
the completion type to use (eg. "\<c-x>\<c-u>").
>
function MyTagContext()
if filereadable(expand('%:p:h') . '/tags')
return "\<c-x>\<c-]>"
endif
" no return will result in the evaluation of the next
" configured context
endfunction
let g:SuperTabCompletionContexts =
\ ['MyTagContext', 's:ContextText', 's:ContextDiscover']
<
Here is another example that could be used to add context support for
clojure, and perhaps other lisp variants:
>
let b:SuperTabCompletionContexts =
\ ['ClojureContext'] + g:SuperTabCompletionContexts
function! ClojureContext()
let curline = getline('.')
let cnum = col('.')
let synname = synIDattr(synID(line('.'), cnum - 1, 1), 'name')
if curline =~ '(\S\+\%' . cnum . 'c' && synname !~ '\(String\|Comment\)'
return "\<c-x>\<c-o>"
endif
endfunction
<
Completion Duration *supertab-duration*
*g:SuperTabRetainCompletionDuration*
g:SuperTabRetainCompletionDuration (default value: 'insert')
Determines if, and for how long, the current completion type is retained.
The possible values include:
'completion' - The current completion type is only retained for the
current completion. Once you have chosen a completion
result or exited the completion mode, the default
completion type is restored.
'insert' - The current completion type is saved until you exit insert
mode (via ESC). Once you exit insert mode the default
completion type is restored. (supertab default)
'session' - The current completion type is saved for the duration of
your vim session or until you enter a different completion
mode.
Preventing completion after... *supertab-preventcomplete*
*g:SuperTabNoCompleteBefore*
*g:SuperTabNoCompleteAfter*
g:SuperTabNoCompleteBefore (default value: [])
g:SuperTabNoCompleteAfter (default value: ['^', '\s'])
These two variables are used to control when supertab will attempt completion
or instead fall back to inserting a literal <tab>. There are two possible ways
to define these variables:
1) by specifying a list of patterns which are tested against the text before
and after the current cursor position that when matched, prevent completion.
So if you don't want supertab to start completion at the start of a line,
after a comma, or after a space, you can set g:SuperTabNoCompleteAfter
to ['^', ',', '\s'].
2) by specifying a funcref to a global accessible function which expects
as parameter the text to be inspected (before or after) and, based on that (or
other factors), it returns 1 if completion must be prevented, 0 otherwise.
Note: That a buffer local version of these variables
(b:SuperTabNoCompleteBefore, b:SuperTabNoCompleteAfter) are also supported
should you wish to have different values depending on the file type for
instance.
Changing the default mapping *supertab-forwardbackward*
*g:SuperTabMappingForward*
*g:SuperTabMappingBackward*
g:SuperTabMappingForward (default value: '<tab>')
g:SuperTabMappingBackward (default value: '<s-tab>')
These two variables allow you to set the keys used to kick off the current
completion. By default this is <tab> and <s-tab>. To change to something
like <c-space> and <s-c-space>, you can add the following to your |vimrc|.
>
let g:SuperTabMappingForward = '<c-space>'
let g:SuperTabMappingBackward = '<s-c-space>'
>
Note: if the above does not have the desired effect (which may happen in
console version of vim), you can try the following mappings. Although the
backwards mapping still doesn't seem to work in the console for me, your
milage may vary.
>
let g:SuperTabMappingForward = '<nul>'
let g:SuperTabMappingBackward = '<s-nul>'
<
Inserting true tabs *supertab-mappingtabliteral*
*g:SuperTabMappingTabLiteral*
g:SuperTabMappingTabLiteral (default value: '<c-tab>')
Sets the key mapping used to insert a literal tab where supertab would
otherwise attempt to kick off insert completion. The default is '<c-tab>'
(ctrl-tab) which unfortunately might not work at the console. So if you are
using a console vim and want this functionality, you may have to change it to
something that is supported. Alternatively, you can escape the <tab> with
<c-v> (see |i_CTRL-V| for more infos).
Enhanced longest match support *supertab-longestenhanced*
*g:SuperTabLongestEnhanced*
g:SuperTabLongestEnhanced (default value: 0)
When enabled and 'longest' is in your |completeopt| setting, supertab will
provide an enhanced longest match support where typing one or more letters and
hitting tab again while in a completion mode will complete the longest common
match using the new text in the buffer.
For example, say you have a buffer with the following contents:
FooBarFoo
FooBar
Foo
FooBarBaz
And you then type F<tab>. Vim's builtin longest support will complete the
longest common text 'Foo' and offer 'FooBarFoo', 'FooBar', 'Foo', and
'FooBarBaz' as possible completions. With supertab's longest match
enhancement disabled, typing B<tab> while still in the completion mode will
end up completing 'FooBarBaz' or 'FooBarFoo' depending your settings, instead
of the next longest common match of 'FooBar'. With supertab's enhanced
longest match feature enabled, the typing of B<tab> will result in the next
longest text being completed.
Preselecting the first entry *supertab-longesthighlight*
*g:SuperTabLongestHighlight*
g:SuperTabLongestHighlight (default value: 0)
Sets whether or not to pre-highlight the first match when completeopt has the
popup menu enabled and the 'longest' option as well. When enabled, <tab> will
kick off completion and pre-select the first entry in the popup menu, allowing
you to simply hit <enter> to use it.
Mapping <cr> to end completion *supertab-crmapping*
*g:SuperTabCrMapping*
g:SuperTabCrMapping (default value: 1)
When enabled, <cr> will cancel completion mode preserving the current text.
Compatibility with other plugins:
- endwise: compatible
- delimitMate: not compatible (disabled if the delimitMate <cr> mapping is
detected.)
Note: if you have an insert expression mapping with a <cr> in it or an insert
abbreviation containing a <cr>, then supertab will not create a <cr> mapping
which could potentially cause problems with those.
Auto close the preview window *supertab-closepreviewonpopupclose*
*g:SuperTabClosePreviewOnPopupClose*
g:SuperTabClosePreviewOnPopupClose (default value: 0)
When enabled, supertab will attempt to close vim's completion preview window
when the completion popup closes (completion is finished or canceled).
Completion Chaining *supertab-completionchaining*
SuperTab provides the ability to chain one of the completion functions
(|completefunc| or |omnifunc|) together with one of the default vim
completion key sequences (|ins-completion|), giving you the ability to attempt
completion with the first, and upon no results, fall back to the second.
To utilize this feature you need to call the *SuperTabChain* function where
the first argument is the name of a vim compatible |complete-function| and the
second is one of vim's insert completion (|ins-completion|) key bindings
(<c-p>, <c-n>, <c-x><c-]>, etc). Calling this function will set the current
buffer's |completefunc| option to a supertab provided implementation which
utilizes the supplied arguments to perform the completion. Since the
|completefunc| option is being set, this feature must be used with
|g:SuperTabDefaultCompletionType| set to either "context" or "<c-x><c-u>".
Here is an example that can be added to your .vimrc which will setup the
supertab chaining for any filetype that has a provided |omnifunc| to first
try that, then fall back to supertab's default, <c-p>, completion:
>
autocmd FileType *
\ if &omnifunc != '' |
\ call SuperTabChain(&omnifunc, "<c-p>") |
\ call SuperTabSetDefaultCompletionType("<c-x><c-u>") |
\ endif
<
Notice that this autocmd set's the supertab default completion type to user
completion. This is because the call to SuperTabChain will set your buffer's
|'completefunc'| to a supertab defined function which handles the completion
chaining. If that function is never called, by user completion being invoked
via supertab, then completion chaining will not execute. As noted above though,
instead of setting the default to user completion, you can alternatively set
it supertab's 'context' completion type, in which case supertab's 'context'
completion mechanism document above will execute first, and when that context
logic kicks off a user completion, based on the current context, then
supertab's completion chaining will then take over.
Here is an example where 'context' is the global default and completion
chaining is enabled for file types that have omni completion support:
>
let g:SuperTabDefaultCompletionType = 'context'
autocmd FileType *
\ if &omnifunc != '' |
\ call SuperTabChain(&omnifunc, "<c-p>") |
\ endif
<
That configuration will result in a completion flow like so:
if text before the cursor looks like a file path:
use file completion
elif text before the cursor looks like an attempt to access a member
(method, field, etc):
use user completion
where user completion is currently set to supertab's
completion chaining, resulting in:
if omni completion has results:
use omni completion
else:
use keyword completion
else:
use keyword completion
Note: Completion chaining only supports chaining 1 completion function (omni
or user) with 1 regular completion keybinding. All other combinations of
completions (2 or more completion functions, 2 or more key bindings, etc.) are
not supported due to limitations imposed by vim's code completion
implementation.
Note: If the |completefunc| or |omnifunc| use vim's |complete_add()| instead
of returning completion results as a list, then Supertab's completion chaining
won't work properly with it since Supertab uses the function result to
determine if it should fallback to the next completion type.
vim:tw=78:ts=8:ft=help:norl:

File diff suppressed because it is too large Load Diff

@ -1,48 +0,0 @@
This is a mirror of http://www.vim.org/scripts/script.php?script_id=1173
:TComment works like a toggle, i.e., it will comment out text that
contains uncommented lines, and it will uncomment already
commented text (i.e. text that contains no uncommented lines).
If the file-type is properly defined, :TComment will figure out which
comment string to use based on the values of &commentstring or &comments.
For some filetypes, the comment definition is explicitly defined. You can
|tcomment#DefineType()| to add your own definitions.
TComment knows how to deal with embedded code of a different filetype
than the main filetype, e.g., ruby/python/perl regions in vim scripts, HTML or
JavaScript in php code etc.
As operator (the prefix can be customized via g:tcommentMapLeaderOp1
and g:tcommentMapLeaderOp2):
gc{motion} :: Toggle comments (for small comments within one line
the &filetype_inline style will be used, if
defined)
gcc :: Toggle comment for the current line
gC{motion} :: Comment region
gCc :: Comment the current line
Primary key maps:
<c-_><c-_> :: :TComment
<c-_><space> :: :TComment <QUERY COMMENT-BEGIN ?COMMENT-END>
<c-_>b :: :TCommentBlock
<c-_>a :: :TCommentAs <QUERY COMMENT TYPE>
<c-_>n :: :TCommentAs &filetype <QUERY COUNT>
<c-_>s :: :TCommentAs &filetype_<QUERY COMMENT SUBTYPE>
<c-_>i :: :TCommentInline
<c-_>r :: :TCommentRight
<c-_>p :: Comment the current inner paragraph
There is also a secondary set of key maps with <Leader>_ as leader (more
preferable on terminals).
The full documentation is available here:
http://github.com/tomtom/tcomment_vim/blob/master/doc/tcomment.txt
Demo:
http://vimsomnia.blogspot.com/2010/11/tcomment-vim-plugin.html
Also available via git
http://github.com/tomtom/tcomment_vim

File diff suppressed because it is too large Load Diff

@ -1,98 +0,0 @@
:TComment tcomment.txt /*:TComment*
:TCommentAs tcomment.txt /*:TCommentAs*
:TCommentBlock tcomment.txt /*:TCommentBlock*
:TCommentInline tcomment.txt /*:TCommentInline*
:TCommentMaybeInline tcomment.txt /*:TCommentMaybeInline*
:TCommentRight tcomment.txt /*:TCommentRight*
<Plug>TComment-<Leader>_<space> tcomment.txt /*<Plug>TComment-<Leader>_<space>*
<Plug>TComment-<Leader>__ tcomment.txt /*<Plug>TComment-<Leader>__*
<Plug>TComment-<Leader>_a tcomment.txt /*<Plug>TComment-<Leader>_a*
<Plug>TComment-<Leader>_b tcomment.txt /*<Plug>TComment-<Leader>_b*
<Plug>TComment-<Leader>_n tcomment.txt /*<Plug>TComment-<Leader>_n*
<Plug>TComment-<Leader>_p tcomment.txt /*<Plug>TComment-<Leader>_p*
<Plug>TComment-<Leader>_r tcomment.txt /*<Plug>TComment-<Leader>_r*
<Plug>TComment-<Leader>_s tcomment.txt /*<Plug>TComment-<Leader>_s*
<Plug>TComment-<c-_><c-_> tcomment.txt /*<Plug>TComment-<c-_><c-_>*
<Plug>TComment-<c-_><space> tcomment.txt /*<Plug>TComment-<c-_><space>*
<Plug>TComment-<c-_>a tcomment.txt /*<Plug>TComment-<c-_>a*
<Plug>TComment-<c-_>b tcomment.txt /*<Plug>TComment-<c-_>b*
<Plug>TComment-<c-_>ca tcomment.txt /*<Plug>TComment-<c-_>ca*
<Plug>TComment-<c-_>cc tcomment.txt /*<Plug>TComment-<c-_>cc*
<Plug>TComment-<c-_>i tcomment.txt /*<Plug>TComment-<c-_>i*
<Plug>TComment-<c-_>n tcomment.txt /*<Plug>TComment-<c-_>n*
<Plug>TComment-<c-_>p tcomment.txt /*<Plug>TComment-<c-_>p*
<Plug>TComment-<c-_>r tcomment.txt /*<Plug>TComment-<c-_>r*
<Plug>TComment-<c-_>s tcomment.txt /*<Plug>TComment-<c-_>s*
<Plug>TComment-ic tcomment.txt /*<Plug>TComment-ic*
b:tcomment_def_{NAME} tcomment.txt /*b:tcomment_def_{NAME}*
g:tcomment#blank_lines tcomment.txt /*g:tcomment#blank_lines*
g:tcomment#ignore_char_type tcomment.txt /*g:tcomment#ignore_char_type*
g:tcomment#ignore_comment_def tcomment.txt /*g:tcomment#ignore_comment_def*
g:tcomment#options_comments tcomment.txt /*g:tcomment#options_comments*
g:tcomment#options_commentstring tcomment.txt /*g:tcomment#options_commentstring*
g:tcomment#replacements_c tcomment.txt /*g:tcomment#replacements_c*
g:tcomment#replacements_xml tcomment.txt /*g:tcomment#replacements_xml*
g:tcomment#rstrip_on_uncomment tcomment.txt /*g:tcomment#rstrip_on_uncomment*
g:tcomment#syntax_substitute tcomment.txt /*g:tcomment#syntax_substitute*
g:tcommentBlockC2 tcomment.txt /*g:tcommentBlockC2*
g:tcommentBlockXML tcomment.txt /*g:tcommentBlockXML*
g:tcommentGuessFileType tcomment.txt /*g:tcommentGuessFileType*
g:tcommentGuessFileType_blade tcomment.txt /*g:tcommentGuessFileType_blade*
g:tcommentGuessFileType_django tcomment.txt /*g:tcommentGuessFileType_django*
g:tcommentGuessFileType_dsl tcomment.txt /*g:tcommentGuessFileType_dsl*
g:tcommentGuessFileType_eruby tcomment.txt /*g:tcommentGuessFileType_eruby*
g:tcommentGuessFileType_html tcomment.txt /*g:tcommentGuessFileType_html*
g:tcommentGuessFileType_php tcomment.txt /*g:tcommentGuessFileType_php*
g:tcommentGuessFileType_smarty tcomment.txt /*g:tcommentGuessFileType_smarty*
g:tcommentGuessFileType_tskeleton tcomment.txt /*g:tcommentGuessFileType_tskeleton*
g:tcommentGuessFileType_vim tcomment.txt /*g:tcommentGuessFileType_vim*
g:tcommentIgnoreTypes_php tcomment.txt /*g:tcommentIgnoreTypes_php*
g:tcommentInlineC tcomment.txt /*g:tcommentInlineC*
g:tcommentInlineXML tcomment.txt /*g:tcommentInlineXML*
g:tcommentMapLeader1 tcomment.txt /*g:tcommentMapLeader1*
g:tcommentMapLeader2 tcomment.txt /*g:tcommentMapLeader2*
g:tcommentMapLeaderOp1 tcomment.txt /*g:tcommentMapLeaderOp1*
g:tcommentMapLeaderOp2 tcomment.txt /*g:tcommentMapLeaderOp2*
g:tcommentMaps tcomment.txt /*g:tcommentMaps*
g:tcommentModeExtra tcomment.txt /*g:tcommentModeExtra*
g:tcommentOpModeExtra tcomment.txt /*g:tcommentOpModeExtra*
g:tcommentOptions tcomment.txt /*g:tcommentOptions*
g:tcommentSyntaxMap tcomment.txt /*g:tcommentSyntaxMap*
g:tcommentTextObjectInlineComment tcomment.txt /*g:tcommentTextObjectInlineComment*
g:tcomment_types tcomment.txt /*g:tcomment_types*
i_<Plug>TComment-<c-_><c-_> tcomment.txt /*i_<Plug>TComment-<c-_><c-_>*
i_<Plug>TComment-<c-_><space> tcomment.txt /*i_<Plug>TComment-<c-_><space>*
i_<Plug>TComment-<c-_>a tcomment.txt /*i_<Plug>TComment-<c-_>a*
i_<Plug>TComment-<c-_>b tcomment.txt /*i_<Plug>TComment-<c-_>b*
i_<Plug>TComment-<c-_>i tcomment.txt /*i_<Plug>TComment-<c-_>i*
i_<Plug>TComment-<c-_>n tcomment.txt /*i_<Plug>TComment-<c-_>n*
i_<Plug>TComment-<c-_>p tcomment.txt /*i_<Plug>TComment-<c-_>p*
i_<Plug>TComment-<c-_>r tcomment.txt /*i_<Plug>TComment-<c-_>r*
i_<Plug>TComment-<c-_>s tcomment.txt /*i_<Plug>TComment-<c-_>s*
n_<Plug>TComment-gC tcomment.txt /*n_<Plug>TComment-gC*
n_<Plug>TComment-gCb tcomment.txt /*n_<Plug>TComment-gCb*
n_<Plug>TComment-gCc tcomment.txt /*n_<Plug>TComment-gCc*
n_<Plug>TComment-gc tcomment.txt /*n_<Plug>TComment-gc*
n_<Plug>TComment-gcb tcomment.txt /*n_<Plug>TComment-gcb*
n_<Plug>TComment-gcc tcomment.txt /*n_<Plug>TComment-gcc*
tcomment#Comment() tcomment.txt /*tcomment#Comment()*
tcomment#CommentAs() tcomment.txt /*tcomment#CommentAs()*
tcomment#DefineType() tcomment.txt /*tcomment#DefineType()*
tcomment#GetCommentDef() tcomment.txt /*tcomment#GetCommentDef()*
tcomment#GuessCommentType() tcomment.txt /*tcomment#GuessCommentType()*
tcomment#Operator() tcomment.txt /*tcomment#Operator()*
tcomment#OperatorAnyway() tcomment.txt /*tcomment#OperatorAnyway()*
tcomment#OperatorLine() tcomment.txt /*tcomment#OperatorLine()*
tcomment#OperatorLineAnyway() tcomment.txt /*tcomment#OperatorLineAnyway()*
tcomment#SetOption() tcomment.txt /*tcomment#SetOption()*
tcomment#TextObjectInlineComment() tcomment.txt /*tcomment#TextObjectInlineComment()*
tcomment-maps tcomment.txt /*tcomment-maps*
tcomment-operator tcomment.txt /*tcomment-operator*
tcomment.txt tcomment.txt /*tcomment.txt*
v_<Plug>TComment-<c-_><c-_> tcomment.txt /*v_<Plug>TComment-<c-_><c-_>*
v_<Plug>TComment-<c-_>i tcomment.txt /*v_<Plug>TComment-<c-_>i*
v_<Plug>TComment-ic tcomment.txt /*v_<Plug>TComment-ic*
x_<Plug>TComment-<Leader>__ tcomment.txt /*x_<Plug>TComment-<Leader>__*
x_<Plug>TComment-<Leader>_i tcomment.txt /*x_<Plug>TComment-<Leader>_i*
x_<Plug>TComment-gC tcomment.txt /*x_<Plug>TComment-gC*
x_<Plug>TComment-gc tcomment.txt /*x_<Plug>TComment-gc*

@ -1,727 +0,0 @@
*tcomment.txt* An easily extensible & universal comment plugin
Author: Thomas Link, micathom AT gmail com?subject=vim
tcomment provides easy to use, file-type sensible comments for Vim. It
can handle embedded syntax.
TComment works like a toggle, i.e., it will comment out text that
contains uncommented lines, and it will remove comment markup for
already commented text (i.e. text that contains no uncommented lines).
If the file-type is properly defined, TComment will figure out which
comment string to use. Otherwise you use |tcomment#DefineType()| to
override the default choice.
TComment can properly handle an embedded syntax, e.g., ruby/python/perl
regions in vim scripts, HTML or JavaScript in php code etc.
tcomment favours the use of line-wise comment styles. This implies that usually
whole line will be commented out. tcomment also knows block-style and inline
comments that can be used via special maps (see below) or the |:TCommentAs|
command.
Demo:
http://vimsomnia.blogspot.com/2010/11/tcomment-vim-plugin.html
*tcomment-maps*
Key bindings~
Most of the time the default toggle keys will do what you want (or to be
more precise: what I think you want it to do ;-).
*tcomment-operator*
As operator (the prefix can be customized via |g:tcommentMapLeaderOp1|
and |g:tcommentMapLeaderOp2|):
gc{motion} :: Toggle comments (for small comments within one line
the &filetype_inline style will be used, if
defined)
gc<Count>c{motion} :: Toggle comment text with count argument
(see |tcomment#Comment()|)
gcc :: Toggle comment for the current line
gC{motion} :: Comment region
gCc :: Comment the current line
In visual mode:
gc :: Toggle comments
gC :: Comment selected text
CAVEAT: If you visually select text within a line, the visual mode map will
comment out the selected text. If you selected text across several lines, the
visual mode map will assume though that you wanted to comment out lines --
since this is how many vim maps work. In order to make tcomment use e.g. inline
comments anyway, use the <c-_>i map -- see below.
By default the cursor stays put. If you want the cursor to the end of
the commented text, set |g:tcommentOpModeExtra| to '>' (but this may not
work properly with exclusive motions).
Primary key maps for normal and insert mode:
<c-_><c-_> :: :TComment
<c-_><space> :: :TComment <QUERY COMMENT-BEGIN ?COMMENT-END>
<c-_>b :: :TCommentBlock
In insert mode, the cursor will be positioned inside
the comment. In normal mode, the cursor will stay
put.
<c-_>a :: :TCommentAs <QUERY COMMENT TYPE>
<c-_>n :: :TCommentAs &filetype <QUERY COUNT>
<c-_>s :: :TCommentAs &filetype_<QUERY COMMENT SUBTYPE>
<c-_>i :: :TCommentInline (in normal and insert mode, this map will
create an empty inline comment, which isn't suitable for
all filetypes though)
In insert mode, the cursor will be positioned inside
the comment. In normal mode, the cursor will stay
put.
<c-_>r :: :TCommentRight
<c-_>p :: Comment the current inner paragraph
<c-_><Count> :: Set the count argument (a number from 1 to 9) for use with
the subsequent tcomment map/command (see
|tcomment#Comment()|)
E.g. in JavaScript, in order to get an empty /** */
comment for documentation purposes, in insert mode type
<c-_>2<c-_>i
In order to get an empty block comment like >
/**
*
*/
< type <c-_>2<c-_>b
Most of the above maps are also available in visual mode.
A secondary set of key maps is defined for normal and insert mode:
<Leader>__ :: :TComment
<Leader>_p :: Comment the current inner paragraph
<Leader>_<space> :: :TComment <QUERY COMMENT-BEGIN ?COMMENT-END>
<Leader>_i :: :TCommentInline
<Leader>_r :: :TCommentRight
<Leader>_b :: :TCommentBlock
<Leader>_a :: :TCommentAs <QUERY COMMENT TYPE>
<Leader>_n :: :TCommentAs &filetype <QUERY COUNT>
<Leader>_s :: :TCommentAs &filetype_<QUERY COMMENT SUBTYPE>
... and for select mode:
<Leader>__ :: :TComment
<Leader>_i :: :TCommentInline
-----------------------------------------------------------------------
Install~
Edit the vba file and type: >
:so %
See :help vimball for details. If you have difficulties or use vim 7.0,
please make sure, you have the current version of vimball (vimscript
#1502) installed or update your runtime.
========================================================================
Contents~
g:tcommentMaps ...................... |g:tcommentMaps|
g:tcommentMapLeader1 ................ |g:tcommentMapLeader1|
g:tcommentMapLeader2 ................ |g:tcommentMapLeader2|
g:tcommentMapLeaderOp1 .............. |g:tcommentMapLeaderOp1|
g:tcommentMapLeaderOp2 .............. |g:tcommentMapLeaderOp2|
g:tcommentTextObjectInlineComment ... |g:tcommentTextObjectInlineComment|
:TComment ........................... |:TComment|
:TCommentAs ......................... |:TCommentAs|
:TCommentRight ...................... |:TCommentRight|
:TCommentBlock ...................... |:TCommentBlock|
:TCommentInline ..................... |:TCommentInline|
:TCommentMaybeInline ................ |:TCommentMaybeInline|
<Plug>TComment-<c-_><c-_> ........... |<Plug>TComment-<c-_><c-_>|
v_<Plug>TComment-<c-_><c-_> ......... |v_<Plug>TComment-<c-_><c-_>|
i_<Plug>TComment-<c-_><c-_> ......... |i_<Plug>TComment-<c-_><c-_>|
<Plug>TComment-<c-_>p ............... |<Plug>TComment-<c-_>p|
i_<Plug>TComment-<c-_>p ............. |i_<Plug>TComment-<c-_>p|
<Plug>TComment-<c-_><space> ......... |<Plug>TComment-<c-_><space>|
i_<Plug>TComment-<c-_><space> ....... |i_<Plug>TComment-<c-_><space>|
i_<Plug>TComment-<c-_>r ............. |i_<Plug>TComment-<c-_>r|
<Plug>TComment-<c-_>r ............... |<Plug>TComment-<c-_>r|
v_<Plug>TComment-<c-_>i ............. |v_<Plug>TComment-<c-_>i|
<Plug>TComment-<c-_>i ............... |<Plug>TComment-<c-_>i|
i_<Plug>TComment-<c-_>i ............. |i_<Plug>TComment-<c-_>i|
<Plug>TComment-<c-_>b ............... |<Plug>TComment-<c-_>b|
i_<Plug>TComment-<c-_>b ............. |i_<Plug>TComment-<c-_>b|
<Plug>TComment-<c-_>a ............... |<Plug>TComment-<c-_>a|
i_<Plug>TComment-<c-_>a ............. |i_<Plug>TComment-<c-_>a|
<Plug>TComment-<c-_>n ............... |<Plug>TComment-<c-_>n|
i_<Plug>TComment-<c-_>n ............. |i_<Plug>TComment-<c-_>n|
<Plug>TComment-<c-_>s ............... |<Plug>TComment-<c-_>s|
i_<Plug>TComment-<c-_>s ............. |i_<Plug>TComment-<c-_>s|
<Plug>TComment-<c-_>cc .............. |<Plug>TComment-<c-_>cc|
<Plug>TComment-<c-_>ca .............. |<Plug>TComment-<c-_>ca|
<Plug>TComment-<Leader>__ ........... |<Plug>TComment-<Leader>__|
x_<Plug>TComment-<Leader>__ ......... |x_<Plug>TComment-<Leader>__|
<Plug>TComment-<Leader>_p ........... |<Plug>TComment-<Leader>_p|
<Plug>TComment-<Leader>_<space> ..... |<Plug>TComment-<Leader>_<space>|
x_<Plug>TComment-<Leader>_i ......... |x_<Plug>TComment-<Leader>_i|
<Plug>TComment-<Leader>_r ........... |<Plug>TComment-<Leader>_r|
<Plug>TComment-<Leader>_b ........... |<Plug>TComment-<Leader>_b|
<Plug>TComment-<Leader>_a ........... |<Plug>TComment-<Leader>_a|
<Plug>TComment-<Leader>_n ........... |<Plug>TComment-<Leader>_n|
<Plug>TComment-<Leader>_s ........... |<Plug>TComment-<Leader>_s|
n_<Plug>TComment-gC ................. |n_<Plug>TComment-gC|
n_<Plug>TComment-gCc ................ |n_<Plug>TComment-gCc|
n_<Plug>TComment-gCb ................ |n_<Plug>TComment-gCb|
x_<Plug>TComment-gC ................. |x_<Plug>TComment-gC|
v_<Plug>TComment-ic ................. |v_<Plug>TComment-ic|
<Plug>TComment-ic ................... |<Plug>TComment-ic|
n_<Plug>TComment-gcc ................ |n_<Plug>TComment-gcc|
n_<Plug>TComment-gcb ................ |n_<Plug>TComment-gcb|
x_<Plug>TComment-gc ................. |x_<Plug>TComment-gc|
n_<Plug>TComment-gc ................. |n_<Plug>TComment-gc|
g:tcomment#blank_lines .............. |g:tcomment#blank_lines|
g:tcomment#rstrip_on_uncomment ...... |g:tcomment#rstrip_on_uncomment|
g:tcommentModeExtra ................. |g:tcommentModeExtra|
g:tcommentOpModeExtra ............... |g:tcommentOpModeExtra|
g:tcommentOptions ................... |g:tcommentOptions|
g:tcomment#options_comments ......... |g:tcomment#options_comments|
g:tcomment#options_commentstring .... |g:tcomment#options_commentstring|
g:tcomment#ignore_char_type ......... |g:tcomment#ignore_char_type|
g:tcommentGuessFileType ............. |g:tcommentGuessFileType|
g:tcommentGuessFileType_dsl ......... |g:tcommentGuessFileType_dsl|
g:tcommentGuessFileType_php ......... |g:tcommentGuessFileType_php|
g:tcommentGuessFileType_blade ....... |g:tcommentGuessFileType_blade|
g:tcommentGuessFileType_html ........ |g:tcommentGuessFileType_html|
g:tcommentGuessFileType_tskeleton ... |g:tcommentGuessFileType_tskeleton|
g:tcommentGuessFileType_vim ......... |g:tcommentGuessFileType_vim|
g:tcommentGuessFileType_django ...... |g:tcommentGuessFileType_django|
g:tcommentGuessFileType_eruby ....... |g:tcommentGuessFileType_eruby|
g:tcommentGuessFileType_smarty ...... |g:tcommentGuessFileType_smarty|
g:tcommentIgnoreTypes_php ........... |g:tcommentIgnoreTypes_php|
g:tcomment#syntax_substitute ........ |g:tcomment#syntax_substitute|
g:tcommentSyntaxMap ................. |g:tcommentSyntaxMap|
g:tcomment#replacements_c ........... |g:tcomment#replacements_c|
g:tcommentInlineC ................... |g:tcommentInlineC|
g:tcommentBlockC2 ................... |g:tcommentBlockC2|
g:tcomment#replacements_xml ......... |g:tcomment#replacements_xml|
g:tcommentBlockXML .................. |g:tcommentBlockXML|
g:tcommentInlineXML ................. |g:tcommentInlineXML|
g:tcomment#ignore_comment_def ....... |g:tcomment#ignore_comment_def|
tcomment#DefineType ................. |tcomment#DefineType()|
tcomment#GetCommentDef .............. |tcomment#GetCommentDef()|
g:tcomment_types .................... |g:tcomment_types|
tcomment#Comment .................... |tcomment#Comment()|
tcomment#SetOption .................. |tcomment#SetOption()|
tcomment#Operator ................... |tcomment#Operator()|
tcomment#OperatorLine ............... |tcomment#OperatorLine()|
tcomment#OperatorAnyway ............. |tcomment#OperatorAnyway()|
tcomment#OperatorLineAnyway ......... |tcomment#OperatorLineAnyway()|
tcomment#CommentAs .................. |tcomment#CommentAs()|
tcomment#GuessCommentType ........... |tcomment#GuessCommentType()|
tcomment#TextObjectInlineComment .... |tcomment#TextObjectInlineComment()|
========================================================================
plugin/tcomment.vim~
*g:tcommentMaps*
g:tcommentMaps (default: 1)
If true, set maps.
*g:tcommentMapLeader1*
g:tcommentMapLeader1 (default: '<c-_>')
g:tcommentMapLeader1 should be a shortcut that can be used with
map, imap, vmap.
*g:tcommentMapLeader2*
g:tcommentMapLeader2 (default: '<Leader>_')
g:tcommentMapLeader2 should be a shortcut that can be used with
map, xmap.
*g:tcommentMapLeaderOp1*
g:tcommentMapLeaderOp1 (default: 'gc')
See |tcomment-operator|.
*g:tcommentMapLeaderOp2*
g:tcommentMapLeaderOp2 (default: 'gC')
See |tcomment-operator|.
*g:tcommentTextObjectInlineComment*
g:tcommentTextObjectInlineComment (default: 'ic')
*:TComment*
:[range]TComment[!] ?ARGS...
If there is a visual selection that begins and ends in the same line,
then |:TCommentInline| is used instead.
The optional range defaults to the current line. With a bang '!',
always comment the line.
ARGS... are either (see also |tcomment#Comment()|):
1. a list of key=value pairs
2. 1-2 values for: ?commentBegin, ?commentEnd
*:TCommentAs*
:[range]TCommentAs[!] commenttype ?ARGS...
TCommentAs requires g:tcomment_{filetype} to be defined.
With a bang '!', always comment the line.
ARGS... are either (see also |tcomment#Comment()|):
1. a list of key=value pairs
2. 1-2 values for: ?commentBegin, ?commentEnd
*:TCommentRight*
:[range]TCommentRight[!] ?ARGS...
Comment the text to the right of the cursor. If a visual selection was
made (be it block-wise or not), all lines are commented out at from
the current cursor position downwards.
With a bang '!', always comment the line.
ARGS... are either (see also |tcomment#Comment()|):
1. a list of key=value pairs
2. 1-2 values for: ?commentBegin, ?commentEnd
*:TCommentBlock*
:[range]TCommentBlock[!] ?ARGS...
Comment as "block", e.g. use the {&ft}_block comment style. The
commented text isn't indented or reformated.
With a bang '!', always comment the line.
ARGS... are either (see also |tcomment#Comment()|):
1. a list of key=value pairs
2. 1-2 values for: ?commentBegin, ?commentEnd
*:TCommentInline*
:[range]TCommentInline[!] ?ARGS...
Use the {&ft}_inline comment style.
With a bang '!', always comment the line.
ARGS... are either (see also |tcomment#Comment()|):
1. a list of key=value pairs
2. 1-2 values for: ?commentBegin, ?commentEnd
*:TCommentMaybeInline*
:[range]TCommentMaybeInline[!] ?ARGS...
With a bang '!', always comment the line.
ARGS... are either (see also |tcomment#Comment()|):
1. a list of key=value pairs
2. 1-2 values for: ?commentBegin, ?commentEnd
*<Plug>TComment-<c-_><c-_>*
<Plug>TComment-<c-_><c-_> ... :TComment<cr>
*v_<Plug>TComment-<c-_><c-_>*
v_<Plug>TComment-<c-_><c-_> ... :TCommentMaybeInline<cr>
*i_<Plug>TComment-<c-_><c-_>*
i_<Plug>TComment-<c-_><c-_> ... <c-o>:TComment<cr>
*<Plug>TComment-<c-_>p*
<Plug>TComment-<c-_>p ... m`vip:TComment<cr>``
*i_<Plug>TComment-<c-_>p*
i_<Plug>TComment-<c-_>p ... <c-o>:norm! m`vip<cr>:TComment<cr><c-o>``
*<Plug>TComment-<c-_><space>*
<Plug>TComment-<c-_><space> ... :TComment
*i_<Plug>TComment-<c-_><space>*
i_<Plug>TComment-<c-_><space> ... <c-o>:TComment
*i_<Plug>TComment-<c-_>r*
i_<Plug>TComment-<c-_>r ... <c-o>:TCommentRight<cr>
*<Plug>TComment-<c-_>r*
<Plug>TComment-<c-_>r ... :TCommentRight<cr>
*v_<Plug>TComment-<c-_>i*
v_<Plug>TComment-<c-_>i ... :TCommentInline<cr>
*<Plug>TComment-<c-_>i*
<Plug>TComment-<c-_>i ... v:TCommentInline mode=I#<cr>
*i_<Plug>TComment-<c-_>i*
i_<Plug>TComment-<c-_>i ... <c-\><c-o>v:TCommentInline mode=#<cr>
*<Plug>TComment-<c-_>b*
<Plug>TComment-<c-_>b ... :TCommentBlock<cr>
*i_<Plug>TComment-<c-_>b*
i_<Plug>TComment-<c-_>b ... <c-\><c-o>:TCommentBlock mode=#<cr>
*<Plug>TComment-<c-_>a*
<Plug>TComment-<c-_>a ... :TCommentAs
*i_<Plug>TComment-<c-_>a*
i_<Plug>TComment-<c-_>a ... <c-o>:TCommentAs
*<Plug>TComment-<c-_>n*
<Plug>TComment-<c-_>n ... :TCommentAs <c-r>=&ft<cr>
*i_<Plug>TComment-<c-_>n*
i_<Plug>TComment-<c-_>n ... <c-o>:TCommentAs <c-r>=&ft<cr>
*<Plug>TComment-<c-_>s*
<Plug>TComment-<c-_>s ... :TCommentAs <c-r>=&ft<cr>_
*i_<Plug>TComment-<c-_>s*
i_<Plug>TComment-<c-_>s ... <c-o>:TCommentAs <c-r>=&ft<cr>_
*<Plug>TComment-<c-_>cc*
<Plug>TComment-<c-_>cc ... :<c-u>call tcomment#SetOption("count", v:count1)<cr>
*<Plug>TComment-<c-_>ca*
<Plug>TComment-<c-_>ca ... :<c-u>call tcomment#SetOption("as", input("Comment as: ", &filetype, "customlist,tcomment#Complete"))<cr>
*<Plug>TComment-<Leader>__*
<Plug>TComment-<Leader>__ ... :TComment<cr>
*x_<Plug>TComment-<Leader>__*
x_<Plug>TComment-<Leader>__ ... :TCommentMaybeInline<cr>
*<Plug>TComment-<Leader>_p*
<Plug>TComment-<Leader>_p ... vip:TComment<cr>
*<Plug>TComment-<Leader>_<space>*
<Plug>TComment-<Leader>_<space> ... :TComment
*x_<Plug>TComment-<Leader>_i*
x_<Plug>TComment-<Leader>_i ... :TCommentInline<cr>
*<Plug>TComment-<Leader>_r*
<Plug>TComment-<Leader>_r ... :TCommentRight<cr>
*<Plug>TComment-<Leader>_b*
<Plug>TComment-<Leader>_b ... :TCommentBlock<cr>
*<Plug>TComment-<Leader>_a*
<Plug>TComment-<Leader>_a ... :TCommentAs
*<Plug>TComment-<Leader>_n*
<Plug>TComment-<Leader>_n ... :TCommentAs <c-r>=&ft<cr>
*<Plug>TComment-<Leader>_s*
<Plug>TComment-<Leader>_s ... :TCommentAs <c-r>=&ft<cr>_
*n_<Plug>TComment-gC*
n_<Plug>TComment-gC ... :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorAnyway<cr>g@
*n_<Plug>TComment-gCc*
n_<Plug>TComment-gCc ... :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLineAnyway<cr>g@$
*n_<Plug>TComment-gCb*
n_<Plug>TComment-gCb ... :let w:tcommentPos = getpos(".") \| call tcomment#SetOption("mode_extra", "B") \| set opfunc=tcomment#OperatorLine<cr>g@
*x_<Plug>TComment-gC*
x_<Plug>TComment-gC ... :TCommentMaybeInline!<cr>
*v_<Plug>TComment-ic*
v_<Plug>TComment-ic ... :<c-U>call tcomment#TextObjectInlineComment()<cr>
*<Plug>TComment-ic*
<Plug>TComment-ic ... :<c-U>call tcomment#TextObjectInlineComment()<cr>
*n_<Plug>TComment-gcc*
n_<Plug>TComment-gcc ... :<c-u>if v:count > 0 \| call tcomment#SetOption("count", v:count) \| endif \| let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLine<cr>g@$
*n_<Plug>TComment-gcb*
n_<Plug>TComment-gcb ... :<c-u>if v:count > 0 \| call tcomment#SetOption("count", v:count) \| endif \| let w:tcommentPos = getpos(".") \| call tcomment#SetOption("mode_extra", "B") \| set opfunc=tcomment#OperatorLine<cr>g@
*x_<Plug>TComment-gc*
x_<Plug>TComment-gc ... :TCommentMaybeInline<cr>
*n_<Plug>TComment-gc*
n_<Plug>TComment-gc ... :<c-u>if v:count > 0 \| call tcomment#SetOption("count", v:count) \| endif \| let w:tcommentPos = getpos(".") \| set opfunc=tcomment#Operator<cr>g@
========================================================================
autoload/tcomment.vim~
*g:tcomment#blank_lines*
g:tcomment#blank_lines (default: 2)
If 1, comment blank lines too.
If 2, also comment blank lines within indented code blocks
(requires mixedindent -- see |tcomment#Comment()|).
*g:tcomment#rstrip_on_uncomment*
g:tcomment#rstrip_on_uncomment (default: 1)
If 1, remove right-hand whitespace on uncomment from empty lines.
If 2, remove right-hand whitespace on uncomment from all lines.
*g:tcommentModeExtra*
g:tcommentModeExtra (default: '')
Modifies how commenting works.
> ... Move the cursor to the end of the comment
>> ... Like above but move the cursor to the next line
# ... Move the cursor to the position of the commented text
(NOTE: this only works when creating empty comments using
|:TCommentInline| from normal or insert mode and should
not be set here as a global option.)
*g:tcommentOpModeExtra*
g:tcommentOpModeExtra (default: '')
Modifies how the operator works.
See |g:tcommentModeExtra| for a list of possible values.
*g:tcommentOptions*
g:tcommentOptions (default: {})
Other key-value options used by |tcomment#Comment()|.
Example: If you want to put the opening comment marker always in
the first column regardless of the block's indentation, put this
into your |vimrc| file: >
let g:tcommentOptions = {'col': 1}
<
*g:tcomment#options_comments*
g:tcomment#options_comments (default: {'whitespace': 'both'})
Options when using a the 'comments' option.
*g:tcomment#options_commentstring*
g:tcomment#options_commentstring (default: {'whitespace': 'both'})
Options when using a the 'commentstring' option.
*g:tcomment#ignore_char_type*
g:tcomment#ignore_char_type (default: 1)
|text-objects| for use with |tcomment#Operator| can have different
types: line, block, char etc. Text objects like aB, it, at etc.
have type char but this may not work reliably. By default,
tcomment handles those text objects most often as if they were of
type line. Set this variable to 0 in order to change this
behaviour. Be prepared that the result may not always match your
intentions.
*g:tcommentGuessFileType*
g:tcommentGuessFileType (default: 0)
Guess the file type based on syntax names always or for some fileformat only
If non-zero, try to guess filetypes.
tcomment also checks g:tcommentGuessFileType_{&filetype} for
filetype specific values.
Values:
0 ... don't guess
1 ... guess
FILETYPE ... assume this filetype
*g:tcommentGuessFileType_dsl*
g:tcommentGuessFileType_dsl (default: 'xml')
For dsl documents, assume filetype = xml.
*g:tcommentGuessFileType_php*
g:tcommentGuessFileType_php (default: 'html')
In php documents, the php part is usually marked as phpRegion. We
thus assume that the buffers default comment style isn't php but
html.
*g:tcommentGuessFileType_blade*
g:tcommentGuessFileType_blade (default: 'html')
See |g:tcommentGuessFileType_php|.
*g:tcommentGuessFileType_html*
g:tcommentGuessFileType_html (default: 1)
*g:tcommentGuessFileType_tskeleton*
g:tcommentGuessFileType_tskeleton (default: 1)
*g:tcommentGuessFileType_vim*
g:tcommentGuessFileType_vim (default: 1)
*g:tcommentGuessFileType_django*
g:tcommentGuessFileType_django (default: 1)
*g:tcommentGuessFileType_eruby*
g:tcommentGuessFileType_eruby (default: 1)
*g:tcommentGuessFileType_smarty*
g:tcommentGuessFileType_smarty (default: 1)
*g:tcommentIgnoreTypes_php*
g:tcommentIgnoreTypes_php (default: 'sql')
In php files, some syntax regions are wrongly highlighted as sql
markup. We thus ignore sql syntax when guessing the filetype in
php files.
*g:tcomment#syntax_substitute*
g:tcomment#syntax_substitute (default: {...})
*g:tcommentSyntaxMap*
g:tcommentSyntaxMap (default: {...})
tcomment guesses filetypes based on the name of the current syntax
region. This works well if the syntax names match
/filetypeSomeName/. Other syntax names have to be explicitly
mapped onto the corresponding filetype.
*g:tcomment#replacements_c*
g:tcomment#replacements_c (default: {...})
Replacements for c filetype.
*g:tcommentInlineC*
g:tcommentInlineC (default: {...})
Generic c-like comments.
*g:tcommentBlockC2*
g:tcommentBlockC2 (default: {...})
Generic c-like block comments (alternative markup).
*g:tcomment#replacements_xml*
g:tcomment#replacements_xml (default: {...})
Replacements for xml filetype.
*g:tcommentBlockXML*
g:tcommentBlockXML (default: {...})
Generic xml-like block comments.
*g:tcommentInlineXML*
g:tcommentInlineXML (default: {...})
Generic xml-like comments.
*g:tcomment#ignore_comment_def*
g:tcomment#ignore_comment_def (default: [])
A list of names or filetypes, which should be ignored by
|tcomment#DefineType()| -- no custom comment definition will be
stored for these names.
This variable should be set before loading autoload/tcomment.vim.
*tcomment#DefineType()*
tcomment#DefineType(name, commentdef, ?cdef={}, ?anyway=0)
If you don't explicitly define a comment style, |:TComment| will use
'commentstring' instead. We override the default values here in order
to have a blank after the comment marker. Block comments work only if
we explicitly define the markup.
NAME usually is a 'filetype'. You can use special suffixes to define
special comment types. E.g. the name "FILETYPE_block" is used for
block comments for 'filetype'. The name "FILETYPE_inline" is used for
inline comments. If no specialized comment definition exists, the
normal one with name "FILETYPE" is used.
The comment definition can be either a string or a dictionary.
If it is a string:
The format for block comments is similar to 'commentstrings' with the
exception that the format strings for blocks can contain a second line
that defines how "middle lines" (see :h format-comments) should be
displayed.
Example: If the string is "--%s--\n-- ", lines will be commented as
"--%s--" but the middle lines in block comments will be commented as
"--%s".
If it is a dictionary:
See the help on the args argument of |tcomment#Comment| (see item 1,
args is a list of key=value pairs) to find out which fields can be
used.
*tcomment#GetCommentDef()*
tcomment#GetCommentDef(name, ...)
Return the comment definition for NAME.
*b:tcomment_def_{NAME}*
Return b:tcomment_def_{NAME} if the variable exists. Otherwise return
the comment definition as set with |tcomment#DefineType|.
*g:tcomment_types*
g:tcomment_types (default: {})
A dictionary of NAME => COMMENT DEFINITION (see |tcomment#DefineType|)
that can be set in vimrc to override tcomment's default comment
styles.
*tcomment#Comment()*
tcomment#Comment(beg, end, ...)
tcomment#Comment(line1, line2, ?comment_mode, ?comment_anyway, ?args...)
args... are either:
1. a list of key=value pairs where known keys are (see also
|g:tcommentOptions|):
as=STRING ... Use a specific comment definition
count=N ... Repeat the comment string N times
col=N ... Start the comment at column N (in block
mode; must be smaller than |indent()|)
mode=STRING ... See the notes below on the "comment_mode" argument
mode_extra=STRING ... Add to comment_mode
begin=STRING ... Comment prefix
end=STRING ... Comment postfix
middle=STRING ... Middle line comments in block mode
rxbeg=N ... Regexp to find the substring of "begin"
that should be multiplied by "count"
rxend=N ... The above for "end"
rxmid=N ... The above for "middle"
mixedindent=BOOL ... If true, allow use of mixed
characters for indentation
commentstring_rx ... A regexp format string that matches
commented lines (no new groups may be
introduced, the |regexp| is |\V|; % have
to be doubled); "commentstring", "begin"
and optionally "end" must be defined or
deducible.
whitespace ... Define whether commented text is
surrounded with whitespace; if
both ... surround with whitespace (default)
left ... keep whitespace on the left
right... keep whitespace on the right
no ... don't use whitespace
strip_whitespace ... Strip trailing whitespace: if 1
(default), strip from empty lines only,
if 2, always strip whitespace; if 0,
don't strip any whitespace
2. 1-2 values for: ?commentPrefix, ?commentPostfix
3. a dictionary (internal use only)
comment_mode (see also ¦g:tcommentModeExtra¦):
G ... guess the value of comment_mode
B ... block (use extra lines for the comment markers)
i ... maybe inline, guess
I ... inline
R ... right (comment the line right of the cursor)
v ... visual
o ... operator
By default, each line in range will be commented by adding the comment
prefix and postfix.
*tcomment#SetOption()*
tcomment#SetOption(name, arg)
*tcomment#Operator()*
tcomment#Operator(type, ...)
*tcomment#OperatorLine()*
tcomment#OperatorLine(type)
*tcomment#OperatorAnyway()*
tcomment#OperatorAnyway(type)
*tcomment#OperatorLineAnyway()*
tcomment#OperatorLineAnyway(type)
*tcomment#CommentAs()*
tcomment#CommentAs(beg, end, comment_anyway, filetype, ?args...)
Where args is either:
1. A count NUMBER
2. An args list (see the notes on the "args" argument of
|tcomment#Comment()|)
comment text as if it were of a specific filetype
*tcomment#GuessCommentType()*
tcomment#GuessFileType(?options={})
A function that makes the s:GuessFileType() function usable for other
library developers.
The argument is a dictionary with the following keys:
beg ................ (default = line("."))
end ................ (default = line("."))
comment_mode ........ (default = "G")
filetype ........... (default = &filetype)
fallbackFiletype ... (default = "")
This function return a dictionary that contains information about how
to make comments. The information about the filetype of the text
between lines "beg" and "end" is in the "filetype" key of the return
value. It returns the first discernible filetype it encounters.
*tcomment#TextObjectInlineComment()*
tcomment#TextObjectInlineComment()
vim:tw=78:fo=tcq2:isk=!-~,^*,^|,^":ts=8:ft=help:norl:

@ -1,242 +0,0 @@
" tComment.vim -- An easily extensible & universal comment plugin
" @Author: Tom Link (micathom AT gmail com)
" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
" @Created: 27-Dez-2004.
" @Last Change: 2014-02-05.
" @Revision: 811
" GetLatestVimScripts: 1173 1 tcomment.vim
if &cp || exists('loaded_tcomment')
finish
endif
let loaded_tcomment = 303
let s:save_cpo = &cpo
set cpo&vim
if !exists('g:tcommentMaps')
" If true, set maps.
let g:tcommentMaps = 1 "{{{2
endif
if !exists("g:tcommentMapLeader1")
" g:tcommentMapLeader1 should be a shortcut that can be used with
" map, imap, vmap.
let g:tcommentMapLeader1 = '<c-_>' "{{{2
endif
if !exists("g:tcommentMapLeader2")
" g:tcommentMapLeader2 should be a shortcut that can be used with
" map, xmap.
let g:tcommentMapLeader2 = '<Leader>_' "{{{2
endif
if !exists("g:tcommentMapLeaderOp1")
" See |tcomment-operator|.
let g:tcommentMapLeaderOp1 = 'gc' "{{{2
endif
if !exists("g:tcommentMapLeaderOp2")
" See |tcomment-operator|.
let g:tcommentMapLeaderOp2 = 'gC' "{{{2
endif
if !exists('g:tcommentTextObjectInlineComment')
let g:tcommentTextObjectInlineComment = 'ic' "{{{2
endif
" :display: :[range]TComment[!] ?ARGS...
" If there is a visual selection that begins and ends in the same line,
" then |:TCommentInline| is used instead.
" The optional range defaults to the current line. With a bang '!',
" always comment the line.
"
" ARGS... are either (see also |tcomment#Comment()|):
" 1. a list of key=value pairs
" 2. 1-2 values for: ?commentBegin, ?commentEnd
command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TComment
\ keepjumps call tcomment#Comment(<line1>, <line2>, 'G', "<bang>", <f-args>)
" :display: :[range]TCommentAs[!] commenttype ?ARGS...
" TCommentAs requires g:tcomment_{filetype} to be defined.
" With a bang '!', always comment the line.
"
" ARGS... are either (see also |tcomment#Comment()|):
" 1. a list of key=value pairs
" 2. 1-2 values for: ?commentBegin, ?commentEnd
command! -bang -complete=customlist,tcomment#Complete -range -nargs=+ TCommentAs
\ call tcomment#CommentAs(<line1>, <line2>, "<bang>", <f-args>)
" :display: :[range]TCommentRight[!] ?ARGS...
" Comment the text to the right of the cursor. If a visual selection was
" made (be it block-wise or not), all lines are commented out at from
" the current cursor position downwards.
" With a bang '!', always comment the line.
"
" ARGS... are either (see also |tcomment#Comment()|):
" 1. a list of key=value pairs
" 2. 1-2 values for: ?commentBegin, ?commentEnd
command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentRight
\ keepjumps call tcomment#Comment(<line1>, <line2>, 'R', "<bang>", <f-args>)
" :display: :[range]TCommentBlock[!] ?ARGS...
" Comment as "block", e.g. use the {&ft}_block comment style. The
" commented text isn't indented or reformated.
" With a bang '!', always comment the line.
"
" ARGS... are either (see also |tcomment#Comment()|):
" 1. a list of key=value pairs
" 2. 1-2 values for: ?commentBegin, ?commentEnd
command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentBlock
\ keepjumps call tcomment#Comment(<line1>, <line2>, 'B', "<bang>", <f-args>)
" :display: :[range]TCommentInline[!] ?ARGS...
" Use the {&ft}_inline comment style.
" With a bang '!', always comment the line.
"
" ARGS... are either (see also |tcomment#Comment()|):
" 1. a list of key=value pairs
" 2. 1-2 values for: ?commentBegin, ?commentEnd
command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentInline
\ keepjumps call tcomment#Comment(<line1>, <line2>, 'I', "<bang>", <f-args>)
" :display: :[range]TCommentMaybeInline[!] ?ARGS...
" With a bang '!', always comment the line.
"
" ARGS... are either (see also |tcomment#Comment()|):
" 1. a list of key=value pairs
" 2. 1-2 values for: ?commentBegin, ?commentEnd
command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentMaybeInline
\ keepjumps call tcomment#Comment(<line1>, <line2>, 'i', "<bang>", <f-args>)
noremap <Plug>TComment-<c-_><c-_> :TComment<cr>
vnoremap <Plug>TComment-<c-_><c-_> :TCommentMaybeInline<cr>
inoremap <Plug>TComment-<c-_><c-_> <c-o>:TComment<cr>
noremap <Plug>TComment-<c-_>p m`vip:TComment<cr>``
inoremap <Plug>TComment-<c-_>p <c-o>:norm! m`vip<cr>:TComment<cr><c-o>``
noremap <Plug>TComment-<c-_><space> :TComment
inoremap <Plug>TComment-<c-_><space> <c-o>:TComment
inoremap <Plug>TComment-<c-_>r <c-o>:TCommentRight<cr>
noremap <Plug>TComment-<c-_>r :TCommentRight<cr>
vnoremap <Plug>TComment-<c-_>i :TCommentInline<cr>
noremap <Plug>TComment-<c-_>i v:TCommentInline mode=I#<cr>
inoremap <Plug>TComment-<c-_>i <c-\><c-o>v:TCommentInline mode=#<cr>
noremap <Plug>TComment-<c-_>b :TCommentBlock<cr>
inoremap <Plug>TComment-<c-_>b <c-\><c-o>:TCommentBlock mode=#<cr>
noremap <Plug>TComment-<c-_>a :TCommentAs
inoremap <Plug>TComment-<c-_>a <c-o>:TCommentAs
noremap <Plug>TComment-<c-_>n :TCommentAs <c-r>=&ft<cr>
inoremap <Plug>TComment-<c-_>n <c-o>:TCommentAs <c-r>=&ft<cr>
noremap <Plug>TComment-<c-_>s :TCommentAs <c-r>=&ft<cr>_
inoremap <Plug>TComment-<c-_>s <c-o>:TCommentAs <c-r>=&ft<cr>_
noremap <Plug>TComment-<c-_>cc :<c-u>call tcomment#SetOption("count", v:count1)<cr>
noremap <Plug>TComment-<c-_>ca :<c-u>call tcomment#SetOption("as", input("Comment as: ", &filetype, "customlist,tcomment#Complete"))<cr>
noremap <Plug>TComment-<Leader>__ :TComment<cr>
xnoremap <Plug>TComment-<Leader>__ :TCommentMaybeInline<cr>
noremap <Plug>TComment-<Leader>_p vip:TComment<cr>
noremap <Plug>TComment-<Leader>_<space> :TComment
xnoremap <Plug>TComment-<Leader>_i :TCommentInline<cr>
noremap <Plug>TComment-<Leader>_r :TCommentRight<cr>
noremap <Plug>TComment-<Leader>_b :TCommentBlock<cr>
noremap <Plug>TComment-<Leader>_a :TCommentAs
noremap <Plug>TComment-<Leader>_n :TCommentAs <c-r>=&ft<cr>
noremap <Plug>TComment-<Leader>_s :TCommentAs <c-r>=&ft<cr>_
nnoremap <silent> <Plug>TComment-gC :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorAnyway<cr>g@
nnoremap <silent> <Plug>TComment-gCc :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLineAnyway<cr>g@$
nnoremap <silent> <Plug>TComment-gCb :let w:tcommentPos = getpos(".") \| call tcomment#SetOption("mode_extra", "B") \| set opfunc=tcomment#OperatorLine<cr>g@
xnoremap <Plug>TComment-gC :TCommentMaybeInline!<cr>
vnoremap <Plug>TComment-ic :<c-U>call tcomment#TextObjectInlineComment()<cr>
noremap <Plug>TComment-ic :<c-U>call tcomment#TextObjectInlineComment()<cr>
nnoremap <silent> <Plug>TComment-gcc :<c-u>if v:count > 0 \| call tcomment#SetOption("count", v:count) \| endif \| let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLine<cr>g@$
nnoremap <silent> <Plug>TComment-gcb :<c-u>if v:count > 0 \| call tcomment#SetOption("count", v:count) \| endif \| let w:tcommentPos = getpos(".") \| call tcomment#SetOption("mode_extra", "B") \| set opfunc=tcomment#OperatorLine<cr>g@
xnoremap <Plug>TComment-gc :TCommentMaybeInline<cr>
nnoremap <silent> <Plug>TComment-gc :<c-u>if v:count > 0 \| call tcomment#SetOption("count", v:count) \| endif \| let w:tcommentPos = getpos(".") \| set opfunc=tcomment#Operator<cr>g@
for s:i in range(1, 9)
exec 'noremap <Plug>TComment-<c-_>' . s:i . ' :call tcomment#SetOption("count", '. s:i .')<cr>'
exec 'inoremap <Plug>TComment-<c-_>' . s:i . ' <c-\><c-o>:call tcomment#SetOption("count", '. s:i .')<cr>'
exec 'vnoremap <Plug>TComment-<c-_>' . s:i . ' :call tcomment#SetOption("count", '. s:i .')<cr>'
endfor
for s:i in range(1, 9)
exec 'nnoremap <silent> <Plug>TComment-gc' . s:i .'c :let w:tcommentPos = getpos(".") \| call tcomment#SetOption("count", '. s:i .') \| set opfunc=tcomment#Operator<cr>g@'
endfor
unlet s:i
if g:tcommentMaps
if g:tcommentMapLeader1 != ''
exec 'map '. g:tcommentMapLeader1 . g:tcommentMapLeader1 .' <Plug>TComment-<c-_><c-_>'
exec 'vmap '. g:tcommentMapLeader1 . g:tcommentMapLeader1 .' <Plug>TComment-<c-_><c-_>'
exec 'imap '. g:tcommentMapLeader1 . g:tcommentMapLeader1 .' <Plug>TComment-<c-_><c-_>'
exec 'map '. g:tcommentMapLeader1 .'p <Plug>TComment-<c-_>p'
exec 'imap '. g:tcommentMapLeader1 .'p <Plug>TComment-<c-_>p'
exec 'map '. g:tcommentMapLeader1 .'<space> <Plug>TComment-<c-_><space>'
exec 'imap '. g:tcommentMapLeader1 .'<space> <Plug>TComment-<c-_><space>'
exec 'imap '. g:tcommentMapLeader1 .'r <Plug>TComment-<c-_>r'
exec 'map '. g:tcommentMapLeader1 .'r <Plug>TComment-<c-_>r'
exec 'vmap '. g:tcommentMapLeader1 .'i <Plug>TComment-<c-_>i'
exec 'map '. g:tcommentMapLeader1 .'i <Plug>TComment-<c-_>i'
exec 'imap '. g:tcommentMapLeader1 .'i <Plug>TComment-<c-_>i'
exec 'map '. g:tcommentMapLeader1 .'b <Plug>TComment-<c-_>b'
exec 'imap '. g:tcommentMapLeader1 .'b <Plug>TComment-<c-_>b'
exec 'map '. g:tcommentMapLeader1 .'a <Plug>TComment-<c-_>a'
exec 'imap '. g:tcommentMapLeader1 .'a <Plug>TComment-<c-_>a'
exec 'map '. g:tcommentMapLeader1 .'n <Plug>TComment-<c-_>n'
exec 'imap '. g:tcommentMapLeader1 .'n <Plug>TComment-<c-_>n'
exec 'map '. g:tcommentMapLeader1 .'s <Plug>TComment-<c-_>s'
exec 'imap '. g:tcommentMapLeader1 .'s <Plug>TComment-<c-_>s'
exec 'map '. g:tcommentMapLeader1 .'cc <Plug>TComment-<c-_>cc'
exec 'map '. g:tcommentMapLeader1 .'ca <Plug>TComment-<c-_>ca'
for s:i in range(1, 9)
exec 'map '. g:tcommentMapLeader1 . s:i .' <Plug>TComment-<c-_>'.s:i
exec 'imap '. g:tcommentMapLeader1 . s:i .' <Plug>TComment-<c-_>'.s:i
exec 'vmap '. g:tcommentMapLeader1 . s:i .' <Plug>TComment-<c-_>'.s:i
endfor
unlet s:i
endif
if g:tcommentMapLeader2 != ''
exec 'map '. g:tcommentMapLeader2 .'_ <Plug>TComment-<Leader>__'
exec 'xmap '. g:tcommentMapLeader2 .'_ <Plug>TComment-<Leader>__'
exec 'map '. g:tcommentMapLeader2 .'p <Plug>TComment-<Leader>_p'
exec 'map '. g:tcommentMapLeader2 .'<space> <Plug>TComment-<Leader>_<space>'
exec 'xmap '. g:tcommentMapLeader2 .'i <Plug>TComment-<Leader>_i'
exec 'map '. g:tcommentMapLeader2 .'r <Plug>TComment-<Leader>_r'
exec 'map '. g:tcommentMapLeader2 .'b <Plug>TComment-<Leader>_b'
exec 'map '. g:tcommentMapLeader2 .'a <Plug>TComment-<Leader>_a'
exec 'map '. g:tcommentMapLeader2 .'n <Plug>TComment-<Leader>_n'
exec 'map '. g:tcommentMapLeader2 .'s <Plug>TComment-<Leader>_s'
endif
if g:tcommentMapLeaderOp1 != ''
exec 'nmap <silent> '. g:tcommentMapLeaderOp1 .' <Plug>TComment-gc'
for s:i in range(1, 9)
exec 'nmap <silent> '. g:tcommentMapLeaderOp1 . s:i .' <Plug>TComment-gc'.s:i
endfor
unlet s:i
exec 'nmap <silent> '. g:tcommentMapLeaderOp1 .'c <Plug>TComment-gcc'
exec 'nmap <silent> '. g:tcommentMapLeaderOp1 .'b <Plug>TComment-gcb'
exec 'xmap '. g:tcommentMapLeaderOp1 .' <Plug>TComment-gc'
endif
if g:tcommentMapLeaderOp2 != ''
exec 'nmap <silent> '. g:tcommentMapLeaderOp2 .' <Plug>TComment-gC'
exec 'nmap <silent> '. g:tcommentMapLeaderOp2 .'c <Plug>TComment-gCc'
exec 'nmap <silent> '. g:tcommentMapLeaderOp2 .'b <Plug>TComment-gCb'
exec 'xmap '. g:tcommentMapLeaderOp2 .' <Plug>TComment-gC'
endif
if g:tcommentTextObjectInlineComment != ''
exec 'vmap' g:tcommentTextObjectInlineComment ' <Plug>TComment-ic'
exec 'omap' g:tcommentTextObjectInlineComment ' <Plug>TComment-ic'
endif
endif
let &cpo = s:save_cpo
unlet s:save_cpo
" vi: ft=vim:tw=72:ts=4:fo=w2croql

@ -1,29 +0,0 @@
Tabular
==============
Sometimes, it's useful to line up text. Naturally, it's nicer to have the
computer do this for you, since aligning things by hand quickly becomes
unpleasant. While there are other plugins for aligning text, the ones I've
tried are either impossibly difficult to understand and use, or too simplistic
to handle complicated tasks. This plugin aims to make the easy things easy
and the hard things possible, without providing an unnecessarily obtuse
interface. It's still a work in progress, and criticisms are welcome.
See [Aligning Text with Tabular.vim](http://vimcasts.org/episodes/aligning-text-with-tabular-vim/)
for a screencast that shows how Tabular.vim works.
See [doc/Tabular.txt](http://raw.github.com/godlygeek/tabular/master/doc/Tabular.txt)
for detailed documentation.
Installation
==============
If you don't have a preferred installation method, I recommend installing
[pathogen.vim](https://github.com/tpope/vim-pathogen), and then simply
copy and paste:
mkdir -p ~/.vim/bundle
cd ~/.vim/bundle
git clone git://github.com/godlygeek/tabular.git
Once help tags have been generated (either using Pathogen's `:Helptags`
command, or by pointing vim's `:helptags` command at the directory where you
installed Tabular), you can view the manual with `:help tabular`.

@ -1,48 +0,0 @@
if !exists(':Tabularize') || get(g:, 'no_default_tabular_maps', 0)
finish " Tabular.vim wasn't loaded or the default maps are unwanted
endif
let s:save_cpo = &cpo
set cpo&vim
AddTabularPattern! assignment /[|&+*/%<>=!~-]\@<!\([<>!=]=\|=\~\)\@![|&+*/%<>=!~-]*=/l1r1
AddTabularPattern! two_spaces / /l0
AddTabularPipeline! multiple_spaces / / map(a:lines, "substitute(v:val, ' *', ' ', 'g')") | tabular#TabularizeStrings(a:lines, ' ', 'l0')
AddTabularPipeline! argument_list /(.*)/ map(a:lines, 'substitute(v:val, ''\s*\([(,)]\)\s*'', ''\1'', ''g'')')
\ | tabular#TabularizeStrings(a:lines, '[(,)]', 'l0')
\ | map(a:lines, 'substitute(v:val, ''\(\s*\),'', '',\1 '', "g")')
\ | map(a:lines, 'substitute(v:val, ''\s*)'', ")", "g")')
function! SplitCDeclarations(lines)
let rv = []
for line in a:lines
" split the line into declaractions
let split = split(line, '\s*[,;]\s*')
" separate the type from the first declaration
let type = substitute(split[0], '\%(\%([&*]\s*\)*\)\=\k\+$', '', '')
" add the ; back on every declaration
call map(split, 'v:val . ";"')
" add the first element to the return as-is, and remove it from the list
let rv += [ remove(split, 0) ]
" transform the other elements by adding the type on at the beginning
call map(split, 'type . v:val')
" and add them all to the return
let rv += split
endfor
return rv
endfunction
AddTabularPipeline! split_declarations /,.*;/ SplitCDeclarations(a:lines)
AddTabularPattern! ternary_operator /^.\{-}\zs?\|:/l1
AddTabularPattern! cpp_io /<<\|>>/l1
AddTabularPattern! pascal_assign /:=/l1
AddTabularPattern! trailing_c_comments /\/\*\|\*\/\|\/\//l1
let &cpo = s:save_cpo
unlet s:save_cpo

@ -1,409 +0,0 @@
" Tabular: Align columnar data using regex-designated column boundaries
" Maintainer: Matthew Wozniski (godlygeek@gmail.com)
" Date: Thu, 03 May 2012 20:49:32 -0400
" Version: 1.0
"
" Long Description:
" Sometimes, it's useful to line up text. Naturally, it's nicer to have the
" computer do this for you, since aligning things by hand quickly becomes
" unpleasant. While there are other plugins for aligning text, the ones I've
" tried are either impossibly difficult to understand and use, or too simplistic
" to handle complicated tasks. This plugin aims to make the easy things easy
" and the hard things possible, without providing an unnecessarily obtuse
" interface. It's still a work in progress, and criticisms are welcome.
"
" License:
" Copyright (c) 2012, Matthew J. Wozniski
" All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
" * Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" * Redistributions in binary form must reproduce the above copyright
" notice, this list of conditions and the following disclaimer in the
" documentation and/or other materials provided with the distribution.
" * The names of the contributors may not be used to endorse or promote
" products derived from this software without specific prior written
" permission.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
" NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
" Stupid vimscript crap {{{1
let s:savecpo = &cpo
set cpo&vim
" Private Functions {{{1
" Return the number of bytes in a string after expanding tabs to spaces. {{{2
" This expansion is done based on the current value of 'tabstop'
if exists('*strdisplaywidth')
" Needs vim 7.3
let s:Strlen = function("strdisplaywidth")
else
function! s:Strlen(string)
" Implement the tab handling part of strdisplaywidth for vim 7.2 and
" earlier - not much that can be done about handling doublewidth
" characters.
let rv = 0
let i = 0
for char in split(a:string, '\zs')
if char == "\t"
let rv += &ts - i
let i = 0
else
let rv += 1
let i = (i + 1) % &ts
endif
endfor
return rv
endfunction
endif
" Align a string within a field {{{2
" These functions do not trim leading and trailing spaces.
" Right align 'string' in a field of size 'fieldwidth'
function! s:Right(string, fieldwidth)
let spaces = a:fieldwidth - s:Strlen(a:string)
return matchstr(a:string, '^\s*') . repeat(" ", spaces) . substitute(a:string, '^\s*', '', '')
endfunction
" Left align 'string' in a field of size 'fieldwidth'
function! s:Left(string, fieldwidth)
let spaces = a:fieldwidth - s:Strlen(a:string)
return a:string . repeat(" ", spaces)
endfunction
" Center align 'string' in a field of size 'fieldwidth'
function! s:Center(string, fieldwidth)
let spaces = a:fieldwidth - s:Strlen(a:string)
let right = spaces / 2
let left = right + (right * 2 != spaces)
return repeat(" ", left) . a:string . repeat(" ", right)
endfunction
" Remove spaces around a string {{{2
" Remove all trailing spaces from a string.
function! s:StripTrailingSpaces(string)
return matchstr(a:string, '^.\{-}\ze\s*$')
endfunction
" Remove all leading spaces from a string.
function! s:StripLeadingSpaces(string)
return matchstr(a:string, '^\s*\zs.*$')
endfunction
" Split a string into fields and delimiters {{{2
" Like split(), but include the delimiters as elements
" All odd numbered elements are delimiters
" All even numbered elements are non-delimiters (including zero)
function! s:SplitDelim(string, delim)
let rv = []
let beg = 0
let len = len(a:string)
let searchoff = 0
while 1
let mid = match(a:string, a:delim, beg + searchoff, 1)
if mid == -1 || mid == len
break
endif
let matchstr = matchstr(a:string, a:delim, beg + searchoff, 1)
let length = strlen(matchstr)
if length == 0 && beg == mid
" Zero-length match for a zero-length delimiter - advance past it
let searchoff += 1
continue
endif
if beg == mid
let rv += [ "" ]
else
let rv += [ a:string[beg : mid-1] ]
endif
let rv += [ matchstr ]
let beg = mid + length
let searchoff = 0
endwhile
let rv += [ strpart(a:string, beg) ]
return rv
endfunction
" Replace lines from `start' to `start + len - 1' with the given strings. {{{2
" If more lines are needed to show all strings, they will be added.
" If there are too few strings to fill all lines, lines will be removed.
function! s:SetLines(start, len, strings)
if a:start > line('$') + 1 || a:start < 1
throw "Invalid start line!"
endif
if len(a:strings) > a:len
let fensave = &fen
let view = winsaveview()
call append(a:start + a:len - 1, repeat([''], len(a:strings) - a:len))
call winrestview(view)
let &fen = fensave
elseif len(a:strings) < a:len
let fensave = &fen
let view = winsaveview()
sil exe (a:start + len(a:strings)) . ',' . (a:start + a:len - 1) . 'd_'
call winrestview(view)
let &fen = fensave
endif
call setline(a:start, a:strings)
endfunction
" Runs the given commandstring argument as an expression. {{{2
" The commandstring expression is expected to reference the a:lines argument.
" If the commandstring expression returns a list the items of that list will
" replace the items in a:lines, otherwise the expression is assumed to have
" modified a:lines itself.
function! s:FilterString(lines, commandstring)
exe 'let rv = ' . a:commandstring
if type(rv) == type(a:lines) && rv isnot a:lines
call filter(a:lines, 0)
call extend(a:lines, rv)
endif
endfunction
" Public API {{{1
if !exists("g:tabular_default_format")
let g:tabular_default_format = "l1"
endif
let s:formatelempat = '\%([lrc]\d\+\)'
function! tabular#ElementFormatPattern()
return s:formatelempat
endfunction
" Given a list of strings and a delimiter, split each string on every
" occurrence of the delimiter pattern, format each element according to either
" the provided format (optional) or the default format, and join them back
" together with enough space padding to guarantee that the nth delimiter of
" each string is aligned.
function! tabular#TabularizeStrings(strings, delim, ...)
if a:0 > 1
echoerr "TabularizeStrings accepts only 2 or 3 arguments (got ".(a:0+2).")"
return 1
endif
let formatstr = (a:0 ? a:1 : g:tabular_default_format)
if formatstr !~? s:formatelempat . '\+'
echoerr "Tabular: Invalid format \"" . formatstr . "\" specified!"
return 1
endif
let format = split(formatstr, s:formatelempat . '\zs')
let lines = map(a:strings, 's:SplitDelim(v:val, a:delim)')
" Strip spaces
" - Only from non-delimiters; spaces in delimiters must have been matched
" intentionally
" - Don't strip leading spaces from the first element; we like indenting.
for line in lines
if len(line) == 1 && s:do_gtabularize
continue " Leave non-matching lines unchanged for GTabularize
endif
if line[0] !~ '^\s*$'
let line[0] = s:StripTrailingSpaces(line[0])
endif
if len(line) >= 3
for i in range(2, len(line)-1, 2)
let line[i] = s:StripLeadingSpaces(s:StripTrailingSpaces(line[i]))
endfor
endif
endfor
" Find the max length of each field
let maxes = []
for line in lines
if len(line) == 1 && s:do_gtabularize
continue " non-matching lines don't affect field widths for GTabularize
endif
for i in range(len(line))
if i == len(maxes)
let maxes += [ s:Strlen(line[i]) ]
else
let maxes[i] = max( [ maxes[i], s:Strlen(line[i]) ] )
endif
endfor
endfor
let lead_blank = empty(filter(copy(lines), 'v:val[0] =~ "\\S"'))
" Concatenate the fields, according to the format pattern.
for idx in range(len(lines))
let line = lines[idx]
if len(line) == 1 && s:do_gtabularize
let lines[idx] = line[0] " GTabularize doesn't change non-matching lines
continue
endif
for i in range(len(line))
let how = format[i % len(format)][0]
let pad = format[i % len(format)][1:-1]
if how =~? 'l'
let field = s:Left(line[i], maxes[i])
elseif how =~? 'r'
let field = s:Right(line[i], maxes[i])
elseif how =~? 'c'
let field = s:Center(line[i], maxes[i])
endif
let line[i] = field . (lead_blank && i == 0 ? '' : repeat(" ", pad))
endfor
let lines[idx] = s:StripTrailingSpaces(join(line, ''))
endfor
endfunction
" Apply 0 or more filters, in sequence, to selected text in the buffer {{{2
" The lines to be filtered are determined as follows:
" If the function is called with a range containing multiple lines, then
" those lines will be used as the range.
" If the function is called with no range or with a range of 1 line, then
" if GTabularize mode is being used,
" the range will not be adjusted
" if "includepat" is not specified,
" that 1 line will be filtered,
" if "includepat" is specified and that line does not match it,
" no lines will be filtered
" if "includepat" is specified and that line does match it,
" all contiguous lines above and below the specified line matching the
" pattern will be filtered.
"
" The remaining arguments must each be a filter to apply to the text.
" Each filter must either be a String evaluating to a function to be called.
function! tabular#PipeRange(includepat, ...) range
exe a:firstline . ',' . a:lastline
\ . 'call tabular#PipeRangeWithOptions(a:includepat, a:000, {})'
endfunction
" Extended version of tabular#PipeRange, which
" 1) Takes the list of filters as an explicit list rather than as varargs
" 2) Supports passing a dictionary of options to control the routine.
" Currently, the only supported option is 'mode', which determines whether
" to behave as :Tabularize or as :GTabularize
" This allows me to add new features here without breaking API compatibility
" in the future.
function! tabular#PipeRangeWithOptions(includepat, filterlist, options) range
let top = a:firstline
let bot = a:lastline
let s:do_gtabularize = (get(a:options, 'mode', '') ==# 'GTabularize')
if !s:do_gtabularize
" In the default mode, apply range extension logic
if a:includepat != '' && top == bot
if top < 0 || top > line('$') || getline(top) !~ a:includepat
return
endif
while top > 1 && getline(top-1) =~ a:includepat
let top -= 1
endwhile
while bot < line('$') && getline(bot+1) =~ a:includepat
let bot += 1
endwhile
endif
endif
let lines = map(range(top, bot), 'getline(v:val)')
for filter in a:filterlist
if type(filter) != type("")
echoerr "PipeRange: Bad filter: " . string(filter)
endif
call s:FilterString(lines, filter)
unlet filter
endfor
call s:SetLines(top, bot - top + 1, lines)
endfunction
" Part of the public interface so interested pipelines can query this and
" adjust their behavior appropriately.
function! tabular#DoGTabularize()
return s:do_gtabularize
endfunction
function! s:SplitDelimTest(string, delim, expected)
let result = s:SplitDelim(a:string, a:delim)
if result !=# a:expected
echomsg 'Test failed!'
echomsg ' string=' . string(a:string) . ' delim=' . string(a:delim)
echomsg ' Returned=' . string(result)
echomsg ' Expected=' . string(a:expected)
endif
endfunction
function! tabular#SplitDelimUnitTest()
let assignment = '[|&+*/%<>=!~-]\@<!\([<>!=]=\|=\~\)\@![|&+*/%<>=!~-]*='
let two_spaces = ' '
let ternary_operator = '^.\{-}\zs?\|:'
let cpp_io = '<<\|>>'
let pascal_assign = ':='
let trailing_c_comments = '\/\*\|\*\/\|\/\/'
call s:SplitDelimTest('a+=b', assignment, ['a', '+=', 'b'])
call s:SplitDelimTest('a-=b', assignment, ['a', '-=', 'b'])
call s:SplitDelimTest('a!=b', assignment, ['a!=b'])
call s:SplitDelimTest('a==b', assignment, ['a==b'])
call s:SplitDelimTest('a&=b', assignment, ['a', '&=', 'b'])
call s:SplitDelimTest('a|=b', assignment, ['a', '|=', 'b'])
call s:SplitDelimTest('a=b=c', assignment, ['a', '=', 'b', '=', 'c'])
call s:SplitDelimTest('a b c', two_spaces, ['a', ' ', 'b', ' ', 'c'])
call s:SplitDelimTest('a b c', two_spaces, ['a b', ' ', ' c'])
call s:SplitDelimTest('ab c', two_spaces, ['ab', ' ', '', ' ', 'c'])
call s:SplitDelimTest('a?b:c', ternary_operator, ['a', '?', 'b', ':', 'c'])
call s:SplitDelimTest('a<<b<<c', cpp_io, ['a', '<<', 'b', '<<', 'c'])
call s:SplitDelimTest('a:=b=c', pascal_assign, ['a', ':=', 'b=c'])
call s:SplitDelimTest('x//foo', trailing_c_comments, ['x', '//', 'foo'])
call s:SplitDelimTest('x/*foo*/',trailing_c_comments, ['x', '/*', 'foo', '*/', ''])
call s:SplitDelimTest('#ab#cd#ef', '[^#]*', ['#', 'ab', '#', 'cd', '#', 'ef', ''])
call s:SplitDelimTest('#ab#cd#ef', '#\zs', ['#', '', 'ab#', '', 'cd#', '', 'ef'])
endfunction
" Stupid vimscript crap, part 2 {{{1
let &cpo = s:savecpo
unlet s:savecpo
" vim:set sw=2 sts=2 fdm=marker:

@ -1,260 +0,0 @@
*Tabular.txt* Configurable, flexible, intuitive text aligning
*tabular* *tabular.vim*
#|#|#|#|#| #| #| ~
#| #|#|#| #|#|#| #| #| #| #|#|#| #| #|#| ~
#| #| #| #| #| #| #| #| #| #| #|#| ~
#| #| #| #| #| #| #| #| #| #| #| ~
#| #|#|#| #|#|#| #|#|#| #| #|#|#| #| ~
For Vim version 7.0 or newer
By Matt Wozniski
mjw@drexel.edu
Reference Manual ~
*tabular-toc*
1. Description |tabular-intro|
2. Walkthrough |tabular-walkthrough|
3. Scripting |tabular-scripting|
The functionality mentioned here is a plugin, see |add-plugin|.
You can avoid loading this plugin by setting the "Tabular_loaded" global
variable in your |vimrc| file: >
:let g:tabular_loaded = 1
==============================================================================
1. Description *tabular-intro*
Sometimes, it's useful to line up text. Naturally, it's nicer to have the
computer do this for you, since aligning things by hand quickly becomes
unpleasant. While there are other plugins for aligning text, the ones I've
tried are either impossibly difficult to understand and use, or too simplistic
to handle complicated tasks. This plugin aims to make the easy things easy
and the hard things possible, without providing an unnecessarily obtuse
interface. It's still a work in progress, and criticisms are welcome.
==============================================================================
2. Walkthrough *tabular-walkthrough*
Tabular's commands are based largely on regular expressions. The basic
technique used by Tabular is taking some regex to match field delimiters,
splitting the input lines at those delimiters, trimming unnecessary spaces
from the non-delimiter parts, padding the non-delimiter parts of the lines
with spaces to make them the same length, and joining things back together
again.
For instance, consider starting with the following lines:
>
Some short phrase,some other phrase
A much longer phrase here,and another long phrase
<
Let's say we want to line these lines up at the commas. We can tell
Tabularize to do this by passing a pattern matching , to the Tabularize
command:
>
:Tabularize /,
Some short phrase , some other phrase
A much longer phrase here , and another long phrase
<
I encourage you to try copying those lines to another buffer and trying to
call :Tabularize. You'll want to take notice of two things quickly: First,
instead of requiring a range, Tabularize tries to figure out what you want to
happen. Since it knows that you want to act on lines matching a comma, it
will look upwards and downwards for lines around the current line that match a
comma, and consider all contiguous lines matching the pattern to be the range
to be acted upon. You can always override this by specifying a range, though.
The second thing you should notice is that you'll almost certainly be able to
abbreviate :Tabularize to :Tab - using this form in mappings and scripts is
discouraged as it will make conflicts with other scripts more likely, but for
interactive use it's a nice timesaver. Another convenience feature is that
running :Tabularize without providing a new pattern will cause it to reuse the
last pattern it was called with.
So, anyway, now the commas line up. Splitting the lines on commas, Tabular
realized that 'Some short phrase' would need to be padded with spaces to match
the length of 'A much longer phrase here', and it did that before joining the
lines back together. You'll also notice that, in addition to the spaces
inserting for padding, extra spaces were inserted between fields. That's
because by default, Tabular prints things left-aligned with one space between
fields. If you wanted to print things right-aligned with no spaces between
fields, you would provide a different format to the Tabularize command:
>
:Tabularize /,/r0
Some short phrase, some other phrase
A much longer phrase here,and another long phrase
<
A format specifier is either l, r, or c, followed by one or more digits. If
the letter is l, the field will be left aligned, similarly for r and right
aligning and c and center aligning. The number following the letter is the
number of spaces padding to insert before the start of the next field.
Multiple format specifiers can be added to the same command - each field will
be printed with the next format specifier in the list; when they all have been
used the first will be used again, and so on. So, the last command right
aligned every field, then inserted 0 spaces of padding before the next field.
What if we wanted to right align the text before the comma, and left align the
text after the comma? The command would look like this:
>
:Tabularize /,/r1c1l0
Some short phrase , some other phrase
A much longer phrase here , and another long phrase
<
That command would be read as "Align the matching text, splitting fields on
commas. Print everything before the first comma right aligned, then 1 space,
then the comma center aligned, then 1 space, then everything after the comma
left aligned." Notice that the alignment of the field the comma is in is
irrelevant - since it's only 1 cell wide, it looks the same whether it's right,
left, or center aligned. Also notice that the 0 padding spaces specified for
the 3rd field are unused - but they would be used if there were enough fields
to require looping through the fields again. For instance:
>
abc,def,ghi
a,b
a,b,c
:Tabularize /,/r1c1l0
abc , def, ghi
a , b
a , b , c
<
Notice that now, the format pattern has been reused; field 4 (the second comma)
is right aligned, field 5 is center aligned. No spaces were inserted between
the 3rd field (containing "def") and the 4th field (the second comma) because
the format specified 'l0'.
But, what if you only wanted to act on the first comma on the line, rather than
all of the commas on the line? Let's say we want everything before the first
comma right aligned, then the comma, then everything after the comma left
aligned:
>
abc,def,ghi
a,b
a,b,c
:Tabularize /^[^,]*\zs,/r0c0l0
abc,def,ghi
a,b
a,b,c
<
Here, we used a Vim regex that would only match the first comma on the line.
It matches the beginning of the line, followed by all the non-comma characters
up to the first comma, and then forgets about what it matched so far and
pretends that the match starts exactly at the comma.
But, now that this command does exactly what we want it to, it's become pretty
unwieldy. It would be unpleasant to need to type that more than once or
twice. The solution is to assign a name to it.
>
:AddTabularPattern first_comma /^[^,]*\zs,/r0c0l0
<
Now, typing ":Tabularize first_comma" will do the same thing as typing the
whole pattern out each time. Of course this is more useful if you store the
name in a file to be used later.
NOTE: In order to make these new commands available every time vim starts,
you'll need to put those new commands into a .vim file in a plugin directory
somewhere in your 'runtimepath'. In order to make sure that Tabular.vim has
already been loaded before your file tries to use :AddTabularPattern or
:AddTabularPipeline, the new file should be installed in an after/plugin
directory in 'runtimepath'. In general, it will be safe to find out where the
TabularMaps.vim plugin was installed, and place other files extending
Tabular.vim in the same directory as TabularMaps.vim. For more information,
and some suggested best practices, check out the |tabular-scripting| section.
Lastly, we'll approach the case where tabular cannot achieve your desired goal
just by splitting lines appart, trimming whitespace, padding with whitespace,
and rejoining the lines. As an example, consider the multiple_spaces command
from TabularMaps.vim. The goal is to split using two or more spaces as a
field delimiter, and join fields back together, properly lined up, with only
two spaces between the end of each field and the beginning of the next.
Unfortunately, Tabular can't do this with only the commands we know so far:
>
:Tabularize / /
<
The above function won't work, because it will consider "a b" as 5 fields
delimited by two pairs of 2 spaces ( 'a', ' ', '', ' ', 'b' ) instead of as
3 fields delimited by one set of 2 or more spaces ( 'a', ' ', 'b' ).
>
:Tabularize / \+/
<
The above function won't work either, because it will leave the delimiter as 4
spaces when used against "a b", meaning that we would fail at our goal of
collapsing everything down to two spaces between fields. So, we need a new
command to get around this:
>
:AddTabularPipeline multiple_spaces / \{2,}/
\ map(a:lines, "substitute(v:val, ' \{2,}', ' ', 'g')")
\ | tabular#TabularizeStrings(a:lines, ' ', 'l0')
<
Yeah. I know it looks complicated. Bear with me. I probably will try to add
in some shortcuts for this syntax, but this verbose will be guaranteed to
always work.
You should already recognize the name being assigned. The next thing to
happen is / \{2,}/ which is a pattern specifying which lines should
automatically be included in the range when no range is given. Without this,
there would be no pattern to use for extending the range. Everything after
that is a | separated list of expressions to be evaluated. In the context in
which they will be evaluated, a:lines will be set to a List of Strings
containing the text of the lines being filtered as they procede through the
pipeline you've set up. The \ at the start of the lines are just vim's line
continuation marker; you needn't worry much about them. So, the first
expression in the pipeline transforms each line by replacing every instance of
2 or more spaces with exactly two spaces. The second command in the pipeline
performs the equivalent of ":Tabularize / /l0"; the only difference is that
it is operating on a List of Strings rather than text in the buffer. At the
end of the pipeline, the Strings in the modified a:lines (or the return value
of the last expression in the pipeline, if it returns a List) will replace the
chosen range.
==============================================================================
3. Extending *tabular-scripting*
As mentioned above, the most important consideration when extending Tabular
with new maps or commands is that your plugin must be loaded after Tabular.vim
has finished loading, and only if Tabular.vim has loaded successfully. The
easiest approach to making sure it loads after Tabular.vim is simply putting
the new file (we'll call it "tabular_extra.vim" as an example) into an
"after/plugin/" directory in 'runtimepath', for instance:
>
~/.vim/after/plugin/tabular_extra.vim
<
The default set of mappings, found in "TabularMaps.vim", is installed in
the after/plugin/ subdirectory of whatever directory Tabular was installed to.
The other important consideration is making sure that your commands are only
called if Tabular.vim was actually loaded. The easiest way to do this is by
checking for the existence of the :Tabularize command at the start of your
plugin. A short example plugin would look like this:
>
" after/plugin/my_tabular_commands.vim
" Provides extra :Tabularize commands
if !exists(':Tabularize')
finish " Give up here; the Tabular plugin musn't have been loaded
endif
" Make line wrapping possible by resetting the 'cpo' option, first saving it
let s:save_cpo = &cpo
set cpo&vim
AddTabularPattern! asterisk /*/l1
AddTabularPipeline! remove_leading_spaces /^ /
\ map(a:lines, "substitute(v:val, '^ *', '', '')")
" Restore the saved value of 'cpo'
let &cpo = s:save_cpo
unlet s:save_cpo
<
==============================================================================
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:

@ -1,346 +0,0 @@
" Tabular: Align columnar data using regex-designated column boundaries
" Maintainer: Matthew Wozniski (godlygeek@gmail.com)
" Date: Thu, 03 May 2012 20:49:32 -0400
" Version: 1.0
"
" Long Description:
" Sometimes, it's useful to line up text. Naturally, it's nicer to have the
" computer do this for you, since aligning things by hand quickly becomes
" unpleasant. While there are other plugins for aligning text, the ones I've
" tried are either impossibly difficult to understand and use, or too simplistic
" to handle complicated tasks. This plugin aims to make the easy things easy
" and the hard things possible, without providing an unnecessarily obtuse
" interface. It's still a work in progress, and criticisms are welcome.
"
" License:
" Copyright (c) 2012, Matthew J. Wozniski
" All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
" * Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" * Redistributions in binary form must reproduce the above copyright
" notice, this list of conditions and the following disclaimer in the
" documentation and/or other materials provided with the distribution.
" * The names of the contributors may not be used to endorse or promote
" products derived from this software without specific prior written
" permission.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
" NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
" Abort if running in vi-compatible mode or the user doesn't want us.
if &cp || exists('g:tabular_loaded')
if &cp && &verbose
echo "Not loading Tabular in compatible mode."
endif
finish
endif
let g:tabular_loaded = 1
" Stupid vimscript crap {{{1
let s:savecpo = &cpo
set cpo&vim
" Private Things {{{1
" Dictionary of command name to command
let s:TabularCommands = {}
" Generate tab completion list for :Tabularize {{{2
" Return a list of commands that match the command line typed so far.
" NOTE: Tries to handle commands with spaces in the name, but Vim doesn't seem
" to handle that terribly well... maybe I should give up on that.
function! s:CompleteTabularizeCommand(argstart, cmdline, cursorpos)
let names = keys(s:TabularCommands)
if exists("b:TabularCommands")
let names += keys(b:TabularCommands)
endif
let cmdstart = substitute(a:cmdline, '^\s*\S\+\s*', '', '')
return filter(names, 'v:val =~# ''^\V'' . escape(cmdstart, ''\'')')
endfunction
" Choose the proper command map from the given command line {{{2
" Returns [ command map, command line with leading <buffer> removed ]
function! s:ChooseCommandMap(commandline)
let map = s:TabularCommands
let cmd = a:commandline
if cmd =~# '^<buffer>\s\+'
if !exists('b:TabularCommands')
let b:TabularCommands = {}
endif
let map = b:TabularCommands
let cmd = substitute(cmd, '^<buffer>\s\+', '', '')
endif
return [ map, cmd ]
endfunction
" Parse '/pattern/format' into separate pattern and format parts. {{{2
" If parsing fails, return [ '', '' ]
function! s:ParsePattern(string)
if a:string[0] != '/'
return ['','']
endif
let pat = '\\\@<!\%(\\\\\)\{-}\zs/' . tabular#ElementFormatPattern() . '*$'
let format = matchstr(a:string[1:-1], pat)
if !empty(format)
let format = format[1 : -1]
let pattern = a:string[1 : -len(format) - 2]
else
let pattern = a:string[1 : -1]
endif
return [pattern, format]
endfunction
" Split apart a list of | separated expressions. {{{2
function! s:SplitCommands(string)
if a:string =~ '^\s*$'
return []
endif
let end = match(a:string, "[\"'|]")
" Loop until we find a delimiting | or end-of-string
while end != -1 && (a:string[end] != '|' || a:string[end+1] == '|')
if a:string[end] == "'"
let end = match(a:string, "'", end+1) + 1
if end == 0
throw "No matching end single quote"
endif
elseif a:string[end] == '"'
" Find a " preceded by an even number of \ (or 0)
let pattern = '\%(\\\@<!\%(\\\\\)*\)\@<="'
let end = matchend(a:string, pattern, end+1) + 1
if end == 0
throw "No matching end double quote"
endif
else " Found ||
let end += 2
endif
let end = match(a:string, "[\"'|]", end)
endwhile
if end == 0 || a:string[0 : end - (end > 0)] =~ '^\s*$'
throw "Empty element"
endif
if end == -1
let rv = [ a:string ]
else
let rv = [ a:string[0 : end-1] ] + s:SplitCommands(a:string[end+1 : -1])
endif
return rv
endfunction
" Public Things {{{1
" Command associating a command name with a simple pattern command {{{2
" AddTabularPattern[!] [<buffer>] name /pattern[/format]
"
" If <buffer> is provided, the command will only be available in the current
" buffer, and will be used instead of any global command with the same name.
"
" If a command with the same name and scope already exists, it is an error,
" unless the ! is provided, in which case the existing command will be
" replaced.
"
" pattern is a regex describing the delimiter to be used.
"
" format describes the format pattern to be used. The default will be used if
" none is provided.
com! -nargs=+ -bang AddTabularPattern
\ call AddTabularPattern(<q-args>, <bang>0)
function! AddTabularPattern(command, force)
try
let [ commandmap, rest ] = s:ChooseCommandMap(a:command)
let name = matchstr(rest, '.\{-}\ze\s*/')
let pattern = substitute(rest, '.\{-}\s*\ze/', '', '')
let [ pattern, format ] = s:ParsePattern(pattern)
if empty(name) || empty(pattern)
throw "Invalid arguments!"
endif
if !a:force && has_key(commandmap, name)
throw string(name) . " is already defined, use ! to overwrite."
endif
let command = "tabular#TabularizeStrings(a:lines, " . string(pattern)
if !empty(format)
let command .= ", " . string(format)
endif
let command .= ")"
let commandmap[name] = { 'pattern' : pattern, 'commands' : [ command ] }
catch
echohl ErrorMsg
echomsg "AddTabularPattern: " . v:exception
echohl None
endtry
endfunction
" Command associating a command name with a pipeline of functions {{{2
" AddTabularPipeline[!] [<buffer>] name /pattern/ func [ | func2 [ | func3 ] ]
"
" If <buffer> is provided, the command will only be available in the current
" buffer, and will be used instead of any global command with the same name.
"
" If a command with the same name and scope already exists, it is an error,
" unless the ! is provided, in which case the existing command will be
" replaced.
"
" pattern is a regex that will be used to determine which lines will be
" filtered. If the cursor line doesn't match the pattern, using the command
" will be a no-op, otherwise the cursor and all contiguous lines matching the
" pattern will be filtered.
"
" Each 'func' argument represents a function to be called. This function
" will have access to a:lines, a List containing one String per line being
" filtered.
com! -nargs=+ -bang AddTabularPipeline
\ call AddTabularPipeline(<q-args>, <bang>0)
function! AddTabularPipeline(command, force)
try
let [ commandmap, rest ] = s:ChooseCommandMap(a:command)
let name = matchstr(rest, '.\{-}\ze\s*/')
let pattern = substitute(rest, '.\{-}\s*\ze/', '', '')
let commands = matchstr(pattern, '^/.\{-}\\\@<!\%(\\\\\)\{-}/\zs.*')
let pattern = matchstr(pattern, '/\zs.\{-}\\\@<!\%(\\\\\)\{-}\ze/')
if empty(name) || empty(pattern)
throw "Invalid arguments!"
endif
if !a:force && has_key(commandmap, name)
throw string(name) . " is already defined, use ! to overwrite."
endif
let commandlist = s:SplitCommands(commands)
if empty(commandlist)
throw "Must provide a list of functions!"
endif
let commandmap[name] = { 'pattern' : pattern, 'commands' : commandlist }
catch
echohl ErrorMsg
echomsg "AddTabularPipeline: " . v:exception
echohl None
endtry
endfunction
" Tabularize /pattern[/format] {{{2
" Tabularize name
"
" Align text, either using the given pattern, or the command associated with
" the given name.
com! -nargs=* -range -complete=customlist,<SID>CompleteTabularizeCommand
\ Tabularize <line1>,<line2>call Tabularize(<q-args>)
function! Tabularize(command, ...) range
let piperange_opt = {}
if a:0
let piperange_opt = a:1
endif
if empty(a:command)
if !exists("s:last_tabularize_command")
echohl ErrorMsg
echomsg "Tabularize hasn't been called yet; no pattern/command to reuse!"
echohl None
return
endif
else
let s:last_tabularize_command = a:command
endif
let command = s:last_tabularize_command
let range = a:firstline . ',' . a:lastline
try
let [ pattern, format ] = s:ParsePattern(command)
if !empty(pattern)
let cmd = "tabular#TabularizeStrings(a:lines, " . string(pattern)
if !empty(format)
let cmd .= "," . string(format)
endif
let cmd .= ")"
exe range . 'call tabular#PipeRangeWithOptions(pattern, [ cmd ], '
\ . 'piperange_opt)'
else
if exists('b:TabularCommands') && has_key(b:TabularCommands, command)
let usercmd = b:TabularCommands[command]
elseif has_key(s:TabularCommands, command)
let usercmd = s:TabularCommands[command]
else
throw "Unrecognized command " . string(command)
endif
exe range . 'call tabular#PipeRangeWithOptions(usercmd["pattern"], '
\ . 'usercmd["commands"], piperange_opt)'
endif
catch
echohl ErrorMsg
echomsg "Tabularize: " . v:exception
echohl None
return
endtry
endfunction
" GTabularize /pattern[/format] {{{2
" GTabularize name
"
" Align text on only matching lines, either using the given pattern, or the
" command associated with the given name. Mnemonically, this is similar to
" the :global command, which takes some action on all rows matching a pattern
" in a range. This command is different from normal :Tabularize in 3 ways:
" 1) If a line in the range does not match the pattern, it will be left
" unchanged, and not in any way affect the outcome of other lines in the
" range (at least, normally - but Pipelines can and will still look at
" non-matching rows unless they are specifically written to be aware of
" tabular#DoGTabularize() and handle it appropriately).
" 2) No automatic range determination - :Tabularize automatically expands
" a single-line range (or a call with no range) to include all adjacent
" matching lines. That behavior does not make sense for this command.
" 3) If called without a range, it will act on all lines in the buffer (like
" :global) rather than only a single line
com! -nargs=* -range=% -complete=customlist,<SID>CompleteTabularizeCommand
\ GTabularize <line1>,<line2>
\ call Tabularize(<q-args>, { 'mode': 'GTabularize' } )
" Stupid vimscript crap, part 2 {{{1
let &cpo = s:savecpo
unlet s:savecpo
" vim:set sw=2 sts=2 fdm=marker:

@ -1,5 +0,0 @@
taskpaper.tar.gz:
tar zcvf taskpaper.tar.gz autoload/ doc/ ftplugin/ ftdetect/ syntax/
deploy:
rsync --exclude '*.sw?' -av autoload doc ftdetect ftplugin syntax $(HOME)/.vim

@ -1,302 +0,0 @@
taskpaper.txt For Vim version 6.0 Last change: 2012 March 13
David O'Callaghan <david.ocallaghan@cs.tcd.ie>
13th March 2012
Introduction
=============
*Latest version from https://github.com/davidoc/taskpaper.vim*
From the TaskPaper website (<http://hogbaysoftware.com/projects/taskpaper>):
"TaskPaper is a simple to-do list application that helps you stay
organized. Unlike competing applications, TaskPaper is based on plain text
files which offer you paper-like simplicity and ease of use."
TaskPaper is a to-do list application for Mac OS X based on the "Getting
Things Done" approach of David Allen (<http://www.davidco.com/>). It supports
the GTD notions of projects, tasks and contexts.
This package contains a syntax file and a file-type plugin for the simple
format used by the TaskPaper application. It is intended for Mac users who
want to edit their TaskPaper lists in Vim from time to time (for example, in
a SSH session, or on a non-Mac system) and for anyone who is looking for a
simple to-do list format.
Installation
=============
It should be safe to simply unpack the package into your .vim directory.
It contains the following files:
autoload/taskpaper.vim
doc/example.taskpaper
doc/taskpaper.txt
doc/taskpaper_licence.txt
ftdetect/taskpaper.vim
ftplugin/taskpaper.vim
syntax/taskpaper.vim
To access this help file from within Vim you must first update your help
tags:
:helptags ~/.vim/doc
The path may need to be modified depending on where you install to. Once
you have done this you can access the help with this command:
:help taskpaper
Syntax
=======
The syntax file highlights project headings and task contexts (tags), and
"greys out" completed tasks. The exact style of the displayed file depends
on your Vim colour scheme.
A project heading is a piece of text ending in a colon.
A task is a line beginning with a hyphen '-' and can have zero or more
context tags.
A context tag has the form "@tag".
Other text is considered as a "note" and is displayed as a Vim comment.
File-type Plugin
=================
The file-type plugin tries to make editing TaskPaper files in Vim more
comfortable.
Vim can complete context names after the '@' using the keyword completion
commands (e.g. Ctrl-X Ctrl-N).
The plugin defines some new mappings:
\td Mark task as done
\tx Mark task as cancelled
\tt Mark task as today
\tD Archive @done items
\tX Show tasks marked as cancelled
\tT Show tasks marked as today
\t/ Search for items including keyword
\ts Search for items including tag
\tp Fold all projects
\t. Fold all notes
\tP Focus on the current project
\tj Go to next project
\tk Go to previous project
\tg Go to specified project
\tm Move task to specified project
Note: if `<Leader>` has been changed (e.g. `:let mapleader=",,"`)
then its value should be used instead of `\` in the mappings.
Marking a task as done will add the "@done" context tag to the end of the
task, and it will be greyed out by the syntax file.
To show all tasks with a particular context tag, type `\ts` and a tag name to
search. If you use the `\ts` command over the desired context tag, the tag
name is set as default value. This will fold all the irrelevant tasks leaving
only the tasks in the current context visible.
To fold all top-level projects leaving only the headings visible use the `\tp`
command. Standard fold commands can be used to open (`zo`) and close (`zc`)
individual projects.
To show all projects and tasks use the `zR` command. This disables folding so
that the entire file is expanded.
To go to next or previous project use the `\tj` command or `\tk` command. To
go to a project you specify use the `\tg` command. You can complete project
names with <Tab> on prompt.
Configuration
==============
The plugin supports a number of configuration variables, which can be set in
your .vimrc file.
To change the default date format string used when marking a task complete,
define the `task_paper_date_format` variable. The format matches your system's
`strftime()` function.
For example, to include the date and time in ISO8601 format:
let g:task_paper_date_format = "%Y-%m-%dT%H:%M:%S%z"
To change the default archive project name, define the
`task_paper_archive_project` variable. The default value is "Archive".
let g:task_paper_archive_project = "Archive"
By default, when you move a task, the cursor will follow that task to its new
location. To make the cursor stay in it's current location, change the
`task_paper_follow_move` variable.
let g:task_paper_follow_move = 0
If you want to hide done tasks when searching you can change the
`task_paper_search_hide_done` variable.
let g:task_paper_search_hide_done = 1
To set a custom style (colour, bold, etc.) for tags task_paper_styles variable,
which is a dictionary.
let g:task_paper_styles={'wait': 'ctermfg=Blue guifg=Blue', 'FAIL':
'ctermbg=Red guibg=Red'}
See |highlight-args| for a full description of the syntax.
File-type Detection
====================
This package also contains a script to automatically use the TaskPaper file
type for all files with the ".taskpaper" extension.
Customize
==========
You can create your own shortcut for tagging. To define your own shortcut,
write settings in ~/.vim/ftplugin/taskpaper.vim or ~/.vimrc. If you use the
.vimrc file, define settings like:
function! s:taskpaper_setup()
" Your settings
nnoremap <buffer> <silent> <Leader>tn
\ :<C-u>call taskpaper#toggle_tag('next', '')<CR>
endfunction
augroup vimrc-taskpaper
autocmd!
autocmd FileType taskpaper call s:taskpaper_setup()
augroup END
To add a tag without argument:
nnoremap <buffer> <silent> <Leader>tn
\ :<C-u>call taskpaper#add_tag('next', '')<CR>
To delete a tag:
nnoremap <buffer> <silent> <Leader>tN
\ :<C-u>call taskpaper#delete_tag('next', '')<CR>
To toggle a tag:
nnoremap <buffer> <silent> <Leader>tn
\ :<C-u>call taskpaper#toggle_tag('next', '')<CR>
To add a tag with an argument:
nnoremap <buffer> <silent> <Leader>tq
\ :<C-u>call taskpaper#add_tag('priority')<CR>
You can specify the priority value on prompt.
To delete the priority tag with any argument:
nnoremap <buffer> <silent> <Leader>tQ
\ :<C-u>call taskpaper#delete_tag('priority', '')<CR>
To delete only the level 1 of priority tag:
nnoremap <buffer> <silent> <Leader>tQ
\ :<C-u>call taskpaper#delete_tag('priority', '1')<CR>
To toggle a tag with an argument:
nnoremap <buffer> <silent> <Leader>tq
\ :<C-u>call taskpaper#toggle_tag('priority')<CR>
To update a tag (not delete if the tag exists):
nnoremap <buffer> <silent> <Leader>tq
\ :<C-u>call taskpaper#update_tag('priority')<CR>
Licence
========
Copyright (C) 2007--2012 by David O'Callaghan <david.ocallaghan@cs.tcd.ie>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Acknowledgements
=================
The initial version of the ToggleDone() function was based on SwitchBox()
from the VimOutliner Checkboxes script written by Noel Henson (available
from <http://www.vimoutliner.org>).
Context folding expression was based on a snippet from Vim Tip 282
(<http://vim.sourceforge.net/tips/tip.php?tip_id=282>).
Thanks are due to a number of contributors who have supplied suggestions
or patches to improve TaskPaper.vim:
* Alexander Wodniok
- hint to allow this file to be used as a help file
* Ben Armstron
- various fixes that make the scripts more robust
- fix to show only complete tag matches
- include `_` in contexts
* Huahai Yang
- fixed handling of indented tasks
* Steve Audette
- suggested change to folding
* Andreas Kühntopf
- display non-tasks as comments
* Julien Blanchard (https://github.com/julienXX)
- added ToggleCancelled
* Robert James Kaes (https://github.com/rjkaes)
- added task_paper_date_format
* Adriano Castro (https://github.com/adrianocastro)
- use tabs not spaces (noexpandtab)
* Morgan Sutherland (https://github.com/msutherl)
- Use <Leader> rather than <LocalLeader>
- Start new task after <CR>
* Matt Sacks (https://github.com/mattsa)
- Optional (date) syntax for @done tasks
- Add Tag command for add/removing tag
- Fix lagging space after removing a tag
- Better syntax
* Anyakichi (https://github.com/anyakichi)
- Add useful functions for users to define his own mappings easily
- Add, delete, toggle, and update tags
- Go previous or next project
- Move projects, tasks and notes to another project
- Search for keywords or tags with regexp
- More compatible with HogBaySoftware's TaskPaper
- Tag to projects and notes not only tasks
- Shortcut to @today tag
- Archiving done support
- Multi-level folding of projects work perfectly
- Add a new feature to fold only notes
Contact
========
The author of these Vim scripts is David O'Callaghan
<david.ocallaghan@cs.tcd.ie>.
For all information regarding the TaskPaper application itself please visit
<http://hogbaysoftware.com/projects/taskpaper/>.

@ -1,561 +0,0 @@
" plugin to handle the TaskPaper to-do list format
" Language: Taskpaper (http://hogbaysoftware.com/projects/taskpaper)
" Maintainer: David O'Callaghan <david.ocallaghan@cs.tcd.ie>
" URL: https://github.com/davidoc/taskpaper.vim
" Last Change: 2012-03-07
let s:save_cpo = &cpo
set cpo&vim
function! s:add_delete_tag(tag, value, add)
let cur_line = getline(".")
let tag = " @" . a:tag
if a:value != ''
let tag .= "(" . a:value . ")"
endif
" Add tag
if a:add
let new_line = cur_line . tag
call setline(".", new_line)
return 1
endif
" Delete tag
if cur_line =~# '\V' . tag
if a:value != ''
let new_line = substitute(cur_line, '\V' . tag, "", "g")
else
let new_line = substitute(cur_line, '\V' . tag . '\v(\([^)]*\))?',
\ "", "g")
endif
call setline(".", new_line)
return 1
endif
return 0
endfunction
function! taskpaper#add_tag(tag, ...)
let value = a:0 > 0 ? a:1 : input('Value: ')
return s:add_delete_tag(a:tag, value, 1)
endfunction
function! taskpaper#delete_tag(tag, ...)
let value = a:0 > 0 ? a:1 : ''
return s:add_delete_tag(a:tag, value, 0)
endfunction
function! taskpaper#swap_tag(oldtag, newtag)
call taskpaper#delete_tag(a:oldtag)
call taskpaper#add_tag(a:newtag, '')
endfunction
function! taskpaper#swap_tags(oldtags, newtags)
for oldtag in a:oldtags
call taskpaper#delete_tag(oldtag)
endfor
for newtag in a:newtags
call taskpaper#add_tag(newtag, '')
endfor
endfunction
function! taskpaper#toggle_tag(tag, ...)
if !taskpaper#delete_tag(a:tag, '')
let args = a:0 > 0 ? [a:tag, a:1] : [a:tag]
call call("taskpaper#add_tag", args)
endif
endfunction
function! taskpaper#has_tag(tag)
let cur_line = getline(".")
let m = matchstr(cur_line, '@'.a:tag)
if m != ''
return 1
else
return 0
endfunction
function! taskpaper#cycle_tags(...)
let tags_index = 0
let tag_list = a:000
let tag_added = 0
for tag_name in tag_list
let tags_index = tags_index + 1
if tags_index == len(tag_list)
let tags_index = 0
endif
let has_tag = taskpaper#has_tag(tag_name)
if has_tag == 1
let tag_added = 1
call taskpaper#delete_tag(tag_name)
let new_tag = tag_list[tags_index]
if new_tag != ''
call taskpaper#add_tag(new_tag, '')
endif
break
endif
endfor
if tag_added == 0
call taskpaper#add_tag(tag_list[0], '')
endif
endfunction
function! taskpaper#update_tag(tag, ...)
call taskpaper#delete_tag(a:tag, '')
let args = a:0 > 0 ? [a:tag, a:1] : [a:tag]
call call("taskpaper#add_tag", args)
endfunction
function! taskpaper#date()
return strftime(g:task_paper_date_format, localtime())
endfunction
function! taskpaper#complete_project(lead, cmdline, pos)
let lnum = 1
let list = []
let stack = ['']
let depth = 0
while lnum <= line('$')
let line = getline(lnum)
let ml = matchlist(line, '\v\C^\t*(.+):(\s+\@[^ \t(]+(\([^)]*\))?)*$')
if !empty(ml)
let d = len(matchstr(line, '^\t*'))
while d < depth
call remove(stack, -1)
let depth -= 1
endwhile
while d > depth
call add(stack, '')
let depth += 1
endwhile
let stack[d] = ml[1]
let candidate = join(stack, ':')
if candidate =~ '^' . a:lead
call add(list, join(stack, ':'))
endif
endif
let lnum += 1
endwhile
return list
endfunction
function! taskpaper#go_to_project()
let res = input('Project: ', '', 'customlist,taskpaper#complete_project')
if res != ''
call taskpaper#search_project(split(res, ':'))
endif
endfunction
function! taskpaper#next_project()
return search('^\t*\zs.\+:\(\s\+@[^\s(]\+\(([^)]*)\)\?\)*$', 'w')
endfunction
function! taskpaper#previous_project()
return search('^\t*\zs.\+:\(\s\+@[^\s(]\+\(([^)]*)\)\?\)*$', 'bw')
endfunction
function! s:search_project(project, depth, begin, end)
call cursor(a:begin, 1)
return search('\v^\t{' . a:depth . '}\V' . a:project . ':', 'c', a:end)
endfunction
function! taskpaper#search_project(projects)
if empty(a:projects)
return 0
endif
let save_pos = getpos('.')
let begin = 1
let end = line('$')
let depth = 0
for project in a:projects
if !s:search_project(project, depth, begin, end)
call setpos('.', save_pos)
return 0
endif
let begin = line('.')
let end = taskpaper#search_end_of_item(begin)
let depth += 1
endfor
call cursor(begin, 1)
normal! ^
return begin
endfunction
function! taskpaper#search_end_of_item(...)
let lnum = a:0 > 0 ? a:1 : line('.')
let flags = a:0 > 1 ? a:2 : ''
let depth = len(matchstr(getline(lnum), '^\t*'))
let end = lnum
let lnum += 1
while lnum <= line('$')
let line = getline(lnum)
if line =~ '^\s*$'
" Do nothing
elseif depth < len(matchstr(line, '^\t*'))
let end = lnum
else
break
endif
let lnum += 1
endwhile
if flags !~# 'n'
call cursor(end, 0)
normal! ^
endif
return end
endfunction
function! taskpaper#delete(...)
let start = a:0 > 0 ? a:1 : line('.')
let reg = a:0 > 1 ? a:2 : '"'
let kill_indent = a:0 > 2 ? a:3 : 0
let reg_save = ''
if kill_indent && reg =~# '\u'
let reg = tolower(reg)
let reg_save = getreg(reg)
endif
let save_fen = &l:foldenable
setlocal nofoldenable
let depth = len(matchstr(getline(start), '^\t*'))
let end = taskpaper#search_end_of_item(start)
silent execute start . ',' . end . 'delete ' . reg
let &l:foldenable = save_fen
if kill_indent
let pat = '\(^\|\n\)\t\{' . depth . '\}'
let content = substitute(getreg(reg), pat, '\1', 'g')
if reg_save != ''
let content = reg_save . content
endif
call setreg(reg, content)
endif
return end - start + 1
endfunction
function! taskpaper#put(...)
let projects = a:0 > 0 ? a:1 : []
let reg = a:0 > 1 ? a:2 : '"'
let indent = a:0 > 2 ? a:3 : 0
let save_fen = &l:foldenable
setlocal nofoldenable
if !empty(projects) && !taskpaper#search_project(projects)
let &l:foldenable = save_fen
return 0
endif
if indent > 0
let project_depth = len(matchstr(getline('.'), '^\t*'))
let tabs = repeat("\t", project_depth + indent)
else
let tabs = ''
endif
execute 'put' reg
silent execute "'[,']" . 's/^\ze./' . tabs
let &l:foldenable = save_fen
return line("']") - line("'[") + 1
endfunction
function! taskpaper#move(projects, ...)
let lnum = a:0 > 0 ? a:1 : line('.')
let save_fen = &l:foldenable
setlocal nofoldenable
if !taskpaper#search_project(a:projects)
let &l:foldenable = save_fen
return 0
endif
let reg = 'a'
let save_reg = [getreg(reg), getregtype(reg)]
let nlines = taskpaper#delete(lnum, reg, 1)
call taskpaper#put(a:projects, reg, 1)
let &l:foldenable = save_fen
call setreg(reg, save_reg[0], save_reg[1])
if g:task_paper_follow_move == 0
execute lnum
endif
return nlines
endfunction
function! taskpaper#move_to_project()
let res = input('Project: ', '', 'customlist,taskpaper#complete_project')
call taskpaper#move(split(res, ':'))
endfunction
function! taskpaper#update_project()
let indent = matchstr(getline("."), '^\t*')
let depth = len(indent)
let projects = []
for linenr in range(line('.'), 1, -1)
let line = getline(linenr)
let ml = matchlist(line, '\v^\t{0,' . depth . '}([^\t:]+):')
if empty(ml)
continue
endif
let project = ml[1]
if project != ""
call add(projects, project)
let indent = matchstr(line, '^\t*')
let depth = len(indent) - 1
if depth < 0
break
endif
endif
endfor
call taskpaper#update_tag('project', join(reverse(projects), ' / '))
endfunction
function! taskpaper#archive_done()
let archive_start = search('^' . g:task_paper_archive_project . ':', 'cw')
if archive_start == 0
call append('$', g:task_paper_archive_project . ':')
let archive_start = line('$')
let archive_end = 0
else
let archive_end = search('^\S\+:', 'W')
endif
let save_fen = &l:foldenable
let save_reg = [getreg('a'), getregtype('a')]
setlocal nofoldenable
call setreg('a', '')
call cursor(1, 1)
let deleted = 0
while 1
let lnum = search('@done', 'W', archive_start - deleted)
if lnum == 0
break
endif
call taskpaper#update_project()
let deleted += taskpaper#delete(lnum, 'A', 1)
endwhile
if archive_end != 0
call cursor(archive_end, 1)
while 1
let lnum = search('@done', 'W')
if lnum == 0
break
endif
call taskpaper#update_project()
let deleted += taskpaper#delete(lnum, 'A', 1)
endwhile
endif
if deleted != 0
call taskpaper#put([g:task_paper_archive_project], 'a', 1)
else
echo 'No done items.'
endif
let &l:foldenable = save_fen
call setreg('a', save_reg[0], save_reg[1])
return deleted
endfunction
function! taskpaper#fold(lnum, pat, ipat)
let line = getline(a:lnum)
let level = foldlevel(a:lnum)
if line =~? a:pat && (a:ipat == '' || line !~? a:ipat)
return 0
elseif synIDattr(synID(a:lnum, 1, 1), "name") != 'taskpaperProject'
return 1
elseif level != -1
return level
endif
let depth = len(matchstr(getline(a:lnum), '^\t*'))
for lnum in range(a:lnum + 1, line('$'))
let line = getline(lnum)
if depth >= len(matchstr(line, '^\t*'))
break
endif
if line =~? a:pat && (a:ipat == '' || line !~? a:ipat)
return 0
endif
endfor
return 1
endfunction
function! taskpaper#search(...)
let pat = a:0 > 0 ? a:1 : input('Search: ')
let ipat = a:0 > 1 ? a:2 : ''
if pat == ''
return
endif
setlocal foldexpr=taskpaper#fold(v:lnum,pat,ipat)
setlocal foldminlines=0 foldtext=''
setlocal foldmethod=expr foldlevel=0 foldenable
endfunction
function! taskpaper#fold_except_range(lnum, begin, end)
if a:lnum > a:end
return 1
elseif a:lnum >= a:begin
return 0
elseif synIDattr(synID(a:lnum, 1, 1), "name") != 'taskpaperProject'
return 1
elseif level != -1
return level
endif
if a:end <= taskpaper#search_end_of_item(a:lnum, 'n')
return 0
endif
return 1
endfunction
function! taskpaper#focus_project()
let pos = getpos('.')
normal! $
let begin = taskpaper#previous_project()
if begin == 0
call setpos('.', pos)
return
endif
let end = taskpaper#search_end_of_item(begin, 'n')
" Go to the top level project
while taskpaper#previous_project()
if getline('.') =~ '^[^\t]'
break
endif
endwhile
setlocal foldexpr=taskpaper#fold_except_range(v:lnum,begin,end)
setlocal foldminlines=0 foldtext=''
setlocal foldmethod=expr foldlevel=0 foldenable
endfunction
function! taskpaper#search_tag(...)
if a:0 > 0
let tag = a:1
else
let cword = expand('<cword>')
let tag = input('Tag: ', cword =~ '@\k\+' ? cword[1:] : '')
endif
if tag != ''
let ipat = (g:task_paper_search_hide_done == 1)?'\<@done\>':''
call taskpaper#search('\<@' . tag . '\>', ipat)
endif
endfunction
function! taskpaper#_fold_projects(lnum)
if synIDattr(synID(a:lnum, 1, 1), "name") != 'taskpaperProject'
return '='
endif
let line = getline(a:lnum)
let depth = len(matchstr(line, '^\t*'))
return '>' . (depth + 1)
endfunction
function! taskpaper#fold_projects()
setlocal foldexpr=taskpaper#_fold_projects(v:lnum)
setlocal foldminlines=0 foldtext=foldtext()
setlocal foldmethod=expr foldlevel=0 foldenable
endfunction
function! taskpaper#newline()
let lnum = line('.')
let line = getline('.')
if lnum == 1 || line !~ '^\s*$' ||
\ synIDattr(synID(lnum - 1, 1, 1), "name") != 'taskpaperProject'
return ''
endif
let pline = getline(lnum - 1)
let depth = len(matchstr(pline, '^\t*'))
call setline(lnum, repeat("\t", depth + 1) . '- ')
return "\<End>"
endfunction
function! taskpaper#tag_style(...)
if a:0 > 0
let tag_name = a:1
endif
if a:0 > 1
let tag_style = a:2
let tag_style_name = 'taskpaperAutoStyle_' . tag_name
execute 'syn match' tag_style_name '/\s\zs@'.tag_name.'\(([^)]*)\)\?/'
execute 'hi' tag_style_name tag_style
if version < 508
execute 'hi link' tag_style_name tag_style_name
else
execute 'hi def link' tag_style_name tag_style_name
endif
else
echo "No style specified."
return ''
endif
endfunction
function! taskpaper#tag_style_dict(tsd)
for tag_name in keys(a:tsd)
call taskpaper#tag_style(tag_name,a:tsd[tag_name])
endfor
endfunction
let &cpo = s:save_cpo

@ -1,10 +0,0 @@
Example Project:
- Start example project file @computer @done
- Brainstorm project with colleagues @work
- Email Joan about project @email
Sub Project:
- Sub task
Next Project:
- Draft ideas for next project @anywhere
- Email Bob to arrange meeting @email

@ -1,310 +0,0 @@
*taskpaper.txt* For Vim version 6.0 Last change: 2012 March 13
David O'Callaghan <david.ocallaghan@cs.tcd.ie>
13th March 2012
Introduction
=============
*taskpaper*
*Latest version from https://github.com/davidoc/taskpaper.vim*
From the TaskPaper website (<http://hogbaysoftware.com/projects/taskpaper>):
"TaskPaper is a simple to-do list application that helps you stay
organized. Unlike competing applications, TaskPaper is based on plain text
files which offer you paper-like simplicity and ease of use."
TaskPaper is a to-do list application for Mac OS X based on the "Getting
Things Done" approach of David Allen (<http://www.davidco.com/>). It supports
the GTD notions of projects, tasks and contexts.
This package contains a syntax file and a file-type plugin for the simple
format used by the TaskPaper application. It is intended for Mac users who
want to edit their TaskPaper lists in Vim from time to time (for example, in
a SSH session, or on a non-Mac system) and for anyone who is looking for a
simple to-do list format.
Installation
=============
*taskpaper-install*
It should be safe to simply unpack the package into your .vim directory.
It contains the following files:
autoload/taskpaper.vim
doc/example.taskpaper
doc/taskpaper.txt
doc/taskpaper_licence.txt
ftdetect/taskpaper.vim
ftplugin/taskpaper.vim
syntax/taskpaper.vim
To access this help file from within Vim you must first update your help
tags:
:helptags ~/.vim/doc
The path may need to be modified depending on where you install to. Once
you have done this you can access the help with this command:
:help taskpaper
Syntax
=======
*taskpaper-syntax*
The syntax file highlights project headings and task contexts (tags), and
"greys out" completed tasks. The exact style of the displayed file depends
on your Vim colour scheme.
A project heading is a piece of text ending in a colon.
A task is a line beginning with a hyphen '-' and can have zero or more
context tags.
A context tag has the form "@tag".
Other text is considered as a "note" and is displayed as a Vim comment.
File-type Plugin
=================
*taskpaper-plugin*
The file-type plugin tries to make editing TaskPaper files in Vim more
comfortable.
Vim can complete context names after the '@' using the keyword completion
commands (e.g. Ctrl-X Ctrl-N).
*taskpaper-mappings*
The plugin defines some new mappings:
\td Mark task as done
\tx Mark task as cancelled
\tt Mark task as today
\tD Archive @done items
\tX Show tasks marked as cancelled
\tT Show tasks marked as today
\t/ Search for items including keyword
\ts Search for items including tag
\tp Fold all projects
\t. Fold all notes
\tP Focus on the current project
\tj Go to next project
\tk Go to previous project
\tg Go to specified project
\tm Move task to specified project
Note: if `<Leader>` has been changed (e.g. `:let mapleader=",,"`)
then its value should be used instead of `\` in the mappings.
Marking a task as done will add the "@done" context tag to the end of the
task, and it will be greyed out by the syntax file.
To show all tasks with a particular context tag, type `\ts` and a tag name to
search. If you use the `\ts` command over the desired context tag, the tag
name is set as default value. This will fold all the irrelevant tasks leaving
only the tasks in the current context visible.
To fold all top-level projects leaving only the headings visible use the `\tp`
command. Standard fold commands can be used to open (`zo`) and close (`zc`)
individual projects.
To show all projects and tasks use the `zR` command. This disables folding so
that the entire file is expanded.
To go to next or previous project use the `\tj` command or `\tk` command. To
go to a project you specify use the `\tg` command. You can complete project
names with <Tab> on prompt.
Configuration
==============
*taskpaper-config*
The plugin supports a number of configuration variables, which can be set in
your .vimrc file.
To change the default date format string used when marking a task complete,
define the `task_paper_date_format` variable. The format matches your system's
`strftime()` function.
For example, to include the date and time in ISO8601 format:
let g:task_paper_date_format = "%Y-%m-%dT%H:%M:%S%z"
To change the default archive project name, define the
`task_paper_archive_project` variable. The default value is "Archive".
let g:task_paper_archive_project = "Archive"
By default, when you move a task, the cursor will follow that task to its new
location. To make the cursor stay in it's current location, change the
`task_paper_follow_move` variable.
let g:task_paper_follow_move = 0
If you want to hide done tasks when searching you can change the
`task_paper_search_hide_done` variable.
let g:task_paper_search_hide_done = 1
To set a custom style (colour, bold, etc.) for tags task_paper_styles variable,
which is a dictionary.
let g:task_paper_styles={'wait': 'ctermfg=Blue guifg=Blue', 'FAIL':
'ctermbg=Red guibg=Red'}
See |highlight-args| for a full description of the syntax.
File-type Detection
====================
This package also contains a script to automatically use the TaskPaper file
type for all files with the ".taskpaper" extension.
Customize
==========
*taskpaper-customize*
You can create your own shortcut for tagging. To define your own shortcut,
write settings in ~/.vim/ftplugin/taskpaper.vim or ~/.vimrc. If you use the
.vimrc file, define settings like:
function! s:taskpaper_setup()
" Your settings
nnoremap <buffer> <silent> <Leader>tn
\ :<C-u>call taskpaper#toggle_tag('next', '')<CR>
endfunction
augroup vimrc-taskpaper
autocmd!
autocmd FileType taskpaper call s:taskpaper_setup()
augroup END
To add a tag without argument:
nnoremap <buffer> <silent> <Leader>tn
\ :<C-u>call taskpaper#add_tag('next', '')<CR>
To delete a tag:
nnoremap <buffer> <silent> <Leader>tN
\ :<C-u>call taskpaper#delete_tag('next', '')<CR>
To toggle a tag:
nnoremap <buffer> <silent> <Leader>tn
\ :<C-u>call taskpaper#toggle_tag('next', '')<CR>
To add a tag with an argument:
nnoremap <buffer> <silent> <Leader>tq
\ :<C-u>call taskpaper#add_tag('priority')<CR>
You can specify the priority value on prompt.
To delete the priority tag with any argument:
nnoremap <buffer> <silent> <Leader>tQ
\ :<C-u>call taskpaper#delete_tag('priority', '')<CR>
To delete only the level 1 of priority tag:
nnoremap <buffer> <silent> <Leader>tQ
\ :<C-u>call taskpaper#delete_tag('priority', '1')<CR>
To toggle a tag with an argument:
nnoremap <buffer> <silent> <Leader>tq
\ :<C-u>call taskpaper#toggle_tag('priority')<CR>
To update a tag (not delete if the tag exists):
nnoremap <buffer> <silent> <Leader>tq
\ :<C-u>call taskpaper#update_tag('priority')<CR>
Licence
========
*taskpaper-licence*
Copyright (C) 2007--2012 by David O'Callaghan <david.ocallaghan@cs.tcd.ie>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Acknowledgements
=================
The initial version of the ToggleDone() function was based on SwitchBox()
from the VimOutliner Checkboxes script written by Noel Henson (available
from <http://www.vimoutliner.org>).
Context folding expression was based on a snippet from Vim Tip 282
(<http://vim.sourceforge.net/tips/tip.php?tip_id=282>).
Thanks are due to a number of contributors who have supplied suggestions
or patches to improve TaskPaper.vim:
* Alexander Wodniok
- hint to allow this file to be used as a help file
* Ben Armstron
- various fixes that make the scripts more robust
- fix to show only complete tag matches
- include `_` in contexts
* Huahai Yang
- fixed handling of indented tasks
* Steve Audette
- suggested change to folding
* Andreas Kühntopf
- display non-tasks as comments
* Julien Blanchard (https://github.com/julienXX)
- added ToggleCancelled
* Robert James Kaes (https://github.com/rjkaes)
- added task_paper_date_format
* Adriano Castro (https://github.com/adrianocastro)
- use tabs not spaces (noexpandtab)
* Morgan Sutherland (https://github.com/msutherl)
- Use <Leader> rather than <LocalLeader>
- Start new task after <CR>
* Matt Sacks (https://github.com/mattsa)
- Optional (date) syntax for @done tasks
- Add Tag command for add/removing tag
- Fix lagging space after removing a tag
- Better syntax
* Anyakichi (https://github.com/anyakichi)
- Add useful functions for users to define his own mappings easily
- Add, delete, toggle, and update tags
- Go previous or next project
- Move projects, tasks and notes to another project
- Search for keywords or tags with regexp
- More compatible with HogBaySoftware's TaskPaper
- Tag to projects and notes not only tasks
- Shortcut to @today tag
- Archiving done support
- Multi-level folding of projects work perfectly
- Add a new feature to fold only notes
Contact
========
The author of these Vim scripts is David O'Callaghan
<david.ocallaghan@cs.tcd.ie>.
For all information regarding the TaskPaper application itself please visit
<http://hogbaysoftware.com/projects/taskpaper/>.

@ -1,8 +0,0 @@
Version Control
----------------
github (http://github.com) is used for version control. The main
repository is at <https://github.com/davidoc/taskpaper.vim>.
To start working on the source code you should create an account on github,
fork taskpaper.vim and checkout your fork.

@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

@ -1,9 +0,0 @@
" Vim filetype detection file
" Language: Taskpaper (http://hogbaysoftware.com/projects/taskpaper)
" Maintainer: David O'Callaghan <david.ocallaghan@cs.tcd.ie>
" URL: https://github.com/davidoc/taskpaper.vim
" Last Change: 2011-03-28
"
augroup taskpaper
au! BufRead,BufNewFile *.taskpaper setfiletype taskpaper
augroup END

@ -1,117 +0,0 @@
" plugin to handle the TaskPaper to-do list format
" Language: Taskpaper (http://hogbaysoftware.com/projects/taskpaper)
" Maintainer: David O'Callaghan <david.ocallaghan@cs.tcd.ie>
" URL: https://github.com/davidoc/taskpaper.vim
" Last Change: 2012-02-20
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
let s:save_cpo = &cpo
set cpo&vim
" Define a default date format
if !exists('g:task_paper_date_format')
let g:task_paper_date_format = "%Y-%m-%d"
endif
" Define a default archive project name
if !exists('g:task_paper_archive_project')
let g:task_paper_archive_project = "Archive"
endif
" When moving a task, should the cursor follow or stay in the same place
" (default: follow)
if !exists('g:task_paper_follow_move')
let g:task_paper_follow_move = 1
endif
" Hide @done tasks when searching tags
if !exists('g:task_paper_search_hide_done')
let g:task_paper_search_hide_done = 0
endif
" Add '@' to keyword character set so that we can complete contexts as keywords
setlocal iskeyword+=@-@
" Tab character has special meaning on TaskPaper
setlocal noexpandtab
" Change 'comments' and 'formatoptions' to continue to write a task item
setlocal comments=b:-
setlocal fo-=c fo+=rol
" Set 'autoindent' to maintain indent level
setlocal autoindent
" Set up mappings
if !exists("no_plugin_maps") && !exists("no_taskpaper_maps")
nnoremap <silent> <buffer> <Plug>TaskPaperFoldProjects
\ :<C-u>call taskpaper#fold_projects()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperFoldNotes
\ :<C-u>call taskpaper#search('\v^(\s*\|\t+-\s+.*\|.+:)$')<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperFocusProject
\ :<C-u>call taskpaper#focus_project()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperSearchKeyword
\ :<C-u>call taskpaper#search()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperSearchTag
\ :<C-u>call taskpaper#search_tag()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperGoToProject
\ :<C-u>call taskpaper#go_to_project()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperNextProject
\ :<C-u>call taskpaper#next_project()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperPreviousProject
\ :<C-u>call taskpaper#previous_project()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperArchiveDone
\ :<C-u>call taskpaper#archive_done()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperShowToday
\ :<C-u>call taskpaper#search_tag('today')<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperShowCancelled
\ :<C-u>call taskpaper#search_tag('cancelled')<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperToggleCancelled
\ :call taskpaper#toggle_tag('cancelled', taskpaper#date())<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperToggleDone
\ :call taskpaper#toggle_tag('done', taskpaper#date())<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperToggleToday
\ :call taskpaper#toggle_tag('today', '')<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperMoveToProject
\ :call taskpaper#move_to_project()<CR>
nnoremap <silent> <buffer> <Plug>TaskPaperNewline
\ o<C-r>=taskpaper#newline()<CR>
inoremap <silent> <buffer> <Plug>TaskPaperNewline
\ <CR><C-r>=taskpaper#newline()<CR>
nmap <buffer> <Leader>tp <Plug>TaskPaperFoldProjects
nmap <buffer> <Leader>t. <Plug>TaskPaperFoldNotes
nmap <buffer> <Leader>tP <Plug>TaskPaperFocusProject
nmap <buffer> <Leader>t/ <Plug>TaskPaperSearchKeyword
nmap <buffer> <Leader>ts <Plug>TaskPaperSearchTag
nmap <buffer> <Leader>tg <Plug>TaskPaperGoToProject
nmap <buffer> <Leader>tj <Plug>TaskPaperNextProject
nmap <buffer> <Leader>tk <Plug>TaskPaperPreviousProject
nmap <buffer> <Leader>tD <Plug>TaskPaperArchiveDone
nmap <buffer> <Leader>tT <Plug>TaskPaperShowToday
nmap <buffer> <Leader>tX <Plug>TaskPaperShowCancelled
nmap <buffer> <Leader>td <Plug>TaskPaperToggleDone
nmap <buffer> <Leader>tt <Plug>TaskPaperToggleToday
nmap <buffer> <Leader>tx <Plug>TaskPaperToggleCancelled
nmap <buffer> <Leader>tm <Plug>TaskPaperMoveToProject
if mapcheck("o", "n") == ''
nmap <buffer> o <Plug>TaskPaperNewline
endif
if mapcheck("\<CR>", "i") == ''
imap <buffer> <CR> <Plug>TaskPaperNewline
endif
endif
let &cpo = s:save_cpo

@ -1,48 +0,0 @@
" Vim syntax file
" Language: Taskpaper (http://hogbaysoftware.com/projects/taskpaper)
" Maintainer: David O'Callaghan <david.ocallaghan@cs.tcd.ie>
" URL: https://github.com/davidoc/taskpaper.vim
" Last Change: 2012-03-07
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
if version < 508
command! -nargs=+ HiLink hi link <args>
else
command! -nargs=+ HiLink hi def link <args>
endif
" Define tag styles
if !exists('g:task_paper_styles')
let g:task_paper_styles = {'FAIL': 'guibg=Red guifg=White'}
endif
syn case ignore
syn match taskpaperComment /^.*$/ contains=taskpaperContext
syn match taskpaperProject /^.\+:\(\s\+@[^ \t(]\+\(([^)]*)\)\?\)*$/ contains=taskpaperContext
syn match taskpaperListItem /^\t*-\s\+/
syn match taskpaperContext /\s\zs@[^ \t(]\+\(([^)]*)\)\?/
syn match taskpaperDone /^.*\s@done\(\(\s\|([^)]*)\).*\)\?$/
syn match taskpaperCancelled /^.*\s@cancelled\(\(\s\|([^)]*)\).*\)\?$/
syn sync fromstart
"highlighting for Taskpaper groups
HiLink taskpaperListItem Identifier
HiLink taskpaperContext Identifier
HiLink taskpaperProject Title
HiLink taskpaperDone NonText
HiLink taskpaperCancelled NonText
HiLink taskpaperComment Comment
call taskpaper#tag_style_dict(g:task_paper_styles)
let b:current_syntax = "taskpaper"
delcommand HiLink
" vim: ts=8

@ -1,6 +0,0 @@
Release:
Tasks to be completed before next release
- Note compatibility with ToDoPaper
- stylesheets for tags (e.g. "fail" produces red bg) @done(2012-03-13)
- include patch for notes. @done

@ -1,3 +0,0 @@
textile*.zip
*.swp
doc/tags

@ -1,4 +0,0 @@
h1. A textile plugin for vim
"See the documentation":http://github.com/timcharper/textile.vim/raw/master/doc/textile.txt

@ -1,66 +0,0 @@
*textile.txt* Textile for Vim Last Change: November 3, 2008
==============================================================================
REQUIREMENTS *textile-requirements*
- ruby - http://ruby-lang.org/ (seperate executable, not compiled in)
- RedCloth - http://redcloth.org/
Files with the extension *.textile will auto-detected. If editing a new file,
or otherwise, run ":setf textile" to enable textile commands.
==============================================================================
CHANGELOG *textile-changelog*
0.3 - Fixed keymappings in the documentation
0.2 - Added multiple colors for headers, and alternating colors for list
items
- Fixed error in the vim script for TextileRenderBufferToFile
- Changed shortcut keys from \tp to \rp (render preview instead of
textile preview, since it's file-type specific anyways)
0.1 - Initial Release
==============================================================================
COMMANDS *textile-commands*
:TextilePreview - Render the current buffer to a temp file, and open it in
your web browser (OSX only)
<Leader>rp
:TextileRenderTab - ... to a new tab
<Leader>rt
:TextileRenderFile - ... to a file
<Leader>rf
<Leader> is \ by default, so <Leader>rp == \rp
==============================================================================
CONFIG *textile-config*
MAC OS X:
Optional:
let g:TextileBrowser="Google Chrome" - Open preview in "Google Chrome"
rather than Safari (optional)
Other:
Mandatory:
let g:TextileOS="Linux"
let g:TextileBrowser="/path/to/browser_bin"
==============================================================================
CREDITS *textile-credits*
- "Dominic Mitchell":http://happygiraffe.net/: initial syntax highlighting
- "Aaron Bieber":http://blog.aaronbieber.com/: improved syntax highlighting
- "Tim Harper":http://tim.theenchanter.com/ : improved syntax highlighting,
plugin
vim:tw=78:noet:wrap:ts=2:expandtab:ft=help:norl:

@ -1,8 +0,0 @@
" textile.vim
"
" Tim Harper (tim.theenchanter.com)
" Force filetype to be textile even if already set
" This will override the system ftplugin/changelog
" set on some distros
au BufRead,BufNewFile *.textile set filetype=textile

@ -1,59 +0,0 @@
" textile.vim
"
" Tim Harper (tim.theenchanter.com)
command! -nargs=0 TextileRenderFile call TextileRenderBufferToFile()
command! -nargs=0 TextileRenderTab call TextileRenderBufferToTab()
command! -nargs=0 TextilePreview call TextileRenderBufferToPreview()
noremap <buffer> <Leader>rp :TextilePreview<CR>
noremap <buffer> <Leader>rf :TextileRenderFile<CR>
noremap <buffer> <Leader>rt :TextileRenderTab<CR>
setlocal ignorecase
setlocal wrap
setlocal lbr
function! TextileRender(lines)
if (system('which ruby') == "")
throw "Could not find ruby!"
end
let text = join(a:lines, "\n")
let html = system("ruby -e \"def e(msg); puts msg; exit 1; end; begin; require 'rubygems'; rescue LoadError; e('rubygems not found'); end; begin; require 'redcloth'; rescue LoadError; e('RedCloth gem not installed. Run this from the terminal: sudo gem install RedCloth'); end; puts(RedCloth.new(\\$stdin.read).to_html(:textile))\"", text)
return html
endfunction
function! TextileRenderFile(lines, filename)
let html = TextileRender(getbufline(bufname("%"), 1, '$'))
let html = "<html><head><title>" . bufname("%") . "</title></head><body>\n" . html . "\n</body></html>"
return writefile(split(html, "\n"), a:filename)
endfunction
function! TextileRenderBufferToPreview()
let filename = "/tmp/textile-preview.html"
call TextileRenderFile(getbufline(bufname("%"), 1, '$'), filename)
" Verify if browser was set
if !exists("g:TextileBrowser")
let g:TextileBrowser='Safari'
endif
" call configured browser according OS
if !exists("g:TextileOS") || g:TextileOS == 'mac'
call system("open -a \"".g:TextileBrowser."\" ".filename)
else
echo g:TextileBrowser." ".filename
call system(g:TextileBrowser." ".filename)
endif
endfunction
function! TextileRenderBufferToFile()
let filename = input("Filename:", substitute(bufname("%"), "textile$", "html", ""), "file")
call TextileRenderFile(getbufline(bufname("%"), 1, '$'), filename)
echo "Rendered to '" . filename . "'"
endfunction
function! TextileRenderBufferToTab()
let html = TextileRender(getbufline(bufname("%"), 1, '$'))
tabnew
call append("^", split(html, "\n"))
set syntax=html
endfunction

@ -1,9 +0,0 @@
#!/bin/bash
cd `dirname "$0"`
VERSION=`git tag | sort_rev | tail -n 1`
git archive --prefix=textile/ $VERSION | tar xf -
rm textile/.gitignore textile/package.sh
zip -r textile-$VERSION.zip textile
rm -rf textile

@ -1,91 +0,0 @@
"
" You will have to restart vim for this to take effect. In any case
" it is a good idea to read ":he new-filetype" so that you know what
" is going on, and why the above lines work.
"
" Written originally by Dominic Mitchell, Jan 2006.
" happygiraffe.net
"
" Modified by Aaron Bieber, May 2007.
" blog.aaronbieber.com
"
" Modified by Tim Harper, July 2008 - current
" tim.theenchanter.com
" @(#) $Id$
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
" Textile commands like "h1" are case sensitive, AFAIK.
syn case match
" Textile syntax: <http://textism.com/tools/textile/>
" Inline elements.
syn match txtEmphasis /_[^_]\+_/
syn match txtBold /\*[^*]\+\*/
syn match txtCite /??.\+??/
syn match txtDeleted /-[^-]\+-/
syn match txtInserted /+[^+]\++/
syn match txtSuper /\^[^^]\+\^/
syn match txtSub /\~[^~]\+\~/
syn match txtSpan /%[^%]\+%/
syn match txtFootnoteRef /\[[0-9]\+]/
syn match txtCode /@[^@]\+@/
" Block elements.
syn match txtHeader /^h1\(([^)]*)\|{[^}]*}\|\[[^]]*\]\|[<>=()]\)*\. .\+/
syn match txtHeader2 /^h2\(([^)]*)\|{[^}]*}\|\[[^]]*\]\|[<>=()]\)*\. .\+/
syn match txtHeader3 /^h[3-6]\(([^)]*)\|{[^}]*}\|\[[^]]*\]\|[<>=()]\)*\..\+/
syn match txtFootnoteDef /^fn[0-9]\+\(([^)]*)\|{[^}]*}\|\[[^]]*\]\|[<>=()]\)*\./
syn match txtListBullet /\v^\*+ /
syn match txtListBullet2 /\v^(\*\*)+ /
syn match txtListNumber /\v^#+ /
syn match txtListNumber2 /\v^(##)+ /
syn region txtCodeblock start="^bc\(([^)]*)\|{[^}]*}\|\[[^]]*\]\|[<>=()]\)*\. " end="^$"
syn region txtBlockquote start="^bq\(([^)]*)\|{[^}]*}\|\[[^]]*\]\|[<>=()]\)*\. " end="^$"
syn region txtParagraph start="^bq\(([^)]*)\|{[^}]*}\|\[[^]]*\]\|[<>=()]\)*\. " end="^$"
syn cluster txtBlockElement contains=txtHeader,txtBlockElement,txtFootnoteDef,txtListBullet,txtListNumber
" Everything after the first colon is from RFC 2396, with extra
" backslashes to keep vim happy... Original:
" ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
"
" Revised the pattern to exclude spaces from the URL portion of the
" pattern. Aaron Bieber, 2007.
syn match txtLink /"[^"]\+":\(\([^:\/?# ]\+\):\)\?\(\/\/\([^\/?# ]*\)\)\?\([^?# ]*\)\(?\([^# ]*\)\)\?\(#\([^ ]*\)\)\?/
syn cluster txtInlineElement contains=txtEmphasis,txtBold,txtCite,txtDeleted,txtInserted,txtSuper,txtSub,txtSpan
if version >= 508 || !exists("did_txt_syn_inits")
if version < 508
let did_txt_syn_inits = 1
command -nargs=+ HiLink hi link <args>
else
command -nargs=+ HiLink hi def link <args>
endif
HiLink txtHeader Title
HiLink txtHeader2 Question
HiLink txtHeader3 Statement
HiLink txtBlockquote Comment
HiLink txtCodeblock Identifier
HiLink txtListBullet Operator
HiLink txtListBullet2 Constant
HiLink txtListNumber Operator
HiLink txtListNumber2 Constant
HiLink txtLink String
HiLink txtCode Identifier
hi def txtEmphasis term=underline cterm=underline gui=italic
hi def txtBold term=bold cterm=bold gui=bold
delcommand HiLink
endif
" vim: set ai et sw=4 :

@ -1,3 +0,0 @@
doc/tags
*.lock
.vim-flavor

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save