Configuration

This commit is contained in:
Simon Vieille 2015-09-23 13:33:15 +02:00
parent 8fabfe2385
commit b9630fdb70
155 changed files with 29610 additions and 9 deletions

4
.vim/bundle/gundo/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.un~
*.pyc
tags
.DS_Store

View file

@ -0,0 +1,6 @@
syntax:glob
*.un~
*.pyc
tags
.DS_Store

13
.vim/bundle/gundo/.hgtags Normal file
View file

@ -0,0 +1,13 @@
4101cbccf1d5fd0cfb81a3c6757c8f71657c1243 v0.8.0
4101cbccf1d5fd0cfb81a3c6757c8f71657c1243 semver
aa431c484c032ebc7b11e1e49c3b339d6d775384 v0.9.0
ede41dc6613eac08af5c98e69e123788b5a8e65a v1.0.0
e1365403fefc8b192252fa1dfda997f6c166ab60 v2.0.0
7fb1c286cca3c0c07974cc1b59002cfe2b7132f5 v2.1.0
dc582486455b428fc2ae50913b7844966ce64afc v2.1.1
d2406d0bce25549bb35c59767574386d3d241ace v2.2.0
c1cda256969c75523f9a8ef9629f08fca9ded216 v2.2.1
d6f98011d079bb1fd1bf6debb3f7cae55263b093 v2.2.2
bf31800e9784bd83c220f18fafde215abc72c4ef v2.3.0
25b74fe299c35aba1bc54c4af3febad1682b682b v2.4.0
39f23f08456425288c4a7e0ab94bec34c0b629ab v2.5.0

View file

@ -0,0 +1,34 @@
<a href="http://flattr.com/thing/74149/Gundo-vim" target="_blank">
<img src="http://api.flattr.com/button/button-compact-static-100x17.png" alt="Flattr this" title="Flattr this" border="0" /></a>
Gundo.vim is Vim plugin to visualize your Vim undo tree.
Preview
-------
Screencast:
### [http://screenr.com/M9l](http://screenr.com/M9l)
Screenshot:
<a href="http://www.flickr.com/photos/sjl7678/5093114605/" title="gundo by stevelosh, on Flickr"><img src="http://farm5.static.flickr.com/4113/5093114605_ebc46d6494.jpg" width="487" height="500" alt="gundo" /></a>
Requirements
------------
* Vim 7.3+
* Python support for Vim
* Python 2.4+
Installation and Usage
----------------------
Check out the [project site][] for installation instructions.
[project site]: http://sjl.bitbucket.org/gundo.vim/
License
-------
GPLv2+, just like Mercurial.

View file

@ -0,0 +1,580 @@
# ============================================================================
# File: gundo.py
# Description: vim global plugin to visualize your undo tree
# Maintainer: Steve Losh <steve@stevelosh.com>
# License: GPLv2+ -- look it up.
# Notes: Much of this code was thiefed from Mercurial, and the rest was
# heavily inspired by scratch.vim and histwin.vim.
#
# ============================================================================
import difflib
import itertools
import sys
import time
import vim
# Mercurial's graphlog code --------------------------------------------------------
def asciiedges(seen, rev, parents):
"""adds edge info to changelog DAG walk suitable for ascii()"""
if rev not in seen:
seen.append(rev)
nodeidx = seen.index(rev)
knownparents = []
newparents = []
for parent in parents:
if parent in seen:
knownparents.append(parent)
else:
newparents.append(parent)
ncols = len(seen)
seen[nodeidx:nodeidx + 1] = newparents
edges = [(nodeidx, seen.index(p)) for p in knownparents]
if len(newparents) > 0:
edges.append((nodeidx, nodeidx))
if len(newparents) > 1:
edges.append((nodeidx, nodeidx + 1))
nmorecols = len(seen) - ncols
return nodeidx, edges, ncols, nmorecols
def get_nodeline_edges_tail(
node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
# Still going in the same non-vertical direction.
if n_columns_diff == -1:
start = max(node_index + 1, p_node_index)
tail = ["|", " "] * (start - node_index - 1)
tail.extend(["/", " "] * (n_columns - start))
return tail
else:
return ["\\", " "] * (n_columns - node_index - 1)
else:
return ["|", " "] * (n_columns - node_index - 1)
def draw_edges(edges, nodeline, interline):
for (start, end) in edges:
if start == end + 1:
interline[2 * end + 1] = "/"
elif start == end - 1:
interline[2 * start + 1] = "\\"
elif start == end:
interline[2 * start] = "|"
else:
nodeline[2 * end] = "+"
if start > end:
(start, end) = (end, start)
for i in range(2 * start + 1, 2 * end):
if nodeline[i] != "+":
nodeline[i] = "-"
def fix_long_right_edges(edges):
for (i, (start, end)) in enumerate(edges):
if end > start:
edges[i] = (start, end + 1)
def ascii(buf, state, type, char, text, coldata):
"""prints an ASCII graph of the DAG
takes the following arguments (one call per node in the graph):
- Somewhere to keep the needed state in (init to asciistate())
- Column of the current node in the set of ongoing edges.
- Type indicator of node data == ASCIIDATA.
- Payload: (char, lines):
- Character to use as node's symbol.
- List of lines to display as the node's text.
- Edges; a list of (col, next_col) indicating the edges between
the current node and its parents.
- Number of columns (ongoing edges) in the current revision.
- The difference between the number of columns (ongoing edges)
in the next revision and the number of columns (ongoing edges)
in the current revision. That is: -1 means one column removed;
0 means no columns added or removed; 1 means one column added.
"""
idx, edges, ncols, coldiff = coldata
assert -2 < coldiff < 2
if coldiff == -1:
# Transform
#
# | | | | | |
# o | | into o---+
# |X / |/ /
# | | | |
fix_long_right_edges(edges)
# add_padding_line says whether to rewrite
#
# | | | | | | | |
# | o---+ into | o---+
# | / / | | | # <--- padding line
# o | | | / /
# o | |
add_padding_line = (len(text) > 2 and coldiff == -1 and
[x for (x, y) in edges if x + 1 < y])
# fix_nodeline_tail says whether to rewrite
#
# | | o | | | | o | |
# | | |/ / | | |/ /
# | o | | into | o / / # <--- fixed nodeline tail
# | |/ / | |/ /
# o | | o | |
fix_nodeline_tail = len(text) <= 2 and not add_padding_line
# nodeline is the line containing the node character (typically o)
nodeline = ["|", " "] * idx
nodeline.extend([char, " "])
nodeline.extend(
get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
state[0], fix_nodeline_tail))
# shift_interline is the line containing the non-vertical
# edges between this entry and the next
shift_interline = ["|", " "] * idx
if coldiff == -1:
n_spaces = 1
edge_ch = "/"
elif coldiff == 0:
n_spaces = 2
edge_ch = "|"
else:
n_spaces = 3
edge_ch = "\\"
shift_interline.extend(n_spaces * [" "])
shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
# draw edges from the current node to its parents
draw_edges(edges, nodeline, shift_interline)
# lines is the list of all graph lines to print
lines = [nodeline]
if add_padding_line:
lines.append(get_padding_line(idx, ncols, edges))
lines.append(shift_interline)
# make sure that there are as many graph lines as there are
# log strings
while len(text) < len(lines):
text.append("")
if len(lines) < len(text):
extra_interline = ["|", " "] * (ncols + coldiff)
while len(lines) < len(text):
lines.append(extra_interline)
# print lines
indentation_level = max(ncols, ncols + coldiff)
for (line, logstr) in zip(lines, text):
ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
buf.write(ln.rstrip() + '\n')
# ... and start over
state[0] = coldiff
state[1] = idx
def generate(dag, edgefn, current):
seen, state = [], [0, 0]
buf = Buffer()
for node, parents in list(dag):
if node.time:
age_label = age(int(node.time))
else:
age_label = 'Original'
line = '[%s] %s' % (node.n, age_label)
if node.n == current:
char = '@'
else:
char = 'o'
ascii(buf, state, 'C', char, [line], edgefn(seen, node, parents))
return buf.b
# Mercurial age function -----------------------------------------------------------
agescales = [("year", 3600 * 24 * 365),
("month", 3600 * 24 * 30),
("week", 3600 * 24 * 7),
("day", 3600 * 24),
("hour", 3600),
("minute", 60),
("second", 1)]
def age(ts):
'''turn a timestamp into an age string.'''
def plural(t, c):
if c == 1:
return t
return t + "s"
def fmt(t, c):
return "%d %s" % (c, plural(t, c))
now = time.time()
then = ts
if then > now:
return 'in the future'
delta = max(1, int(now - then))
if delta > agescales[0][1] * 2:
return time.strftime('%Y-%m-%d', time.gmtime(float(ts)))
for t, s in agescales:
n = delta // s
if n >= 2 or s == 1:
return '%s ago' % fmt(t, n)
# Python Vim utility functions -----------------------------------------------------
normal = lambda s: vim.command('normal %s' % s)
MISSING_BUFFER = "Cannot find Gundo's target buffer (%s)"
MISSING_WINDOW = "Cannot find window (%s) for Gundo's target buffer (%s)"
def _check_sanity():
'''Check to make sure we're not crazy.
Does the following things:
* Make sure the target buffer still exists.
'''
b = int(vim.eval('g:gundo_target_n'))
if not vim.eval('bufloaded(%d)' % b):
vim.command('echo "%s"' % (MISSING_BUFFER % b))
return False
w = int(vim.eval('bufwinnr(%d)' % b))
if w == -1:
vim.command('echo "%s"' % (MISSING_WINDOW % (w, b)))
return False
return True
def _goto_window_for_buffer(b):
w = int(vim.eval('bufwinnr(%d)' % int(b)))
vim.command('%dwincmd w' % w)
def _goto_window_for_buffer_name(bn):
b = vim.eval('bufnr("%s")' % bn)
return _goto_window_for_buffer(b)
def _undo_to(n):
n = int(n)
if n == 0:
vim.command('silent earlier %s' % (int(vim.eval('&undolevels')) + 1))
else:
vim.command('silent undo %d' % n)
INLINE_HELP = '''\
" Gundo for %s (%d)
" %s/%s - move between undo states
" p - preview diff of selected and current states
" <cr> - revert to selected state
'''
# Python undo tree data structures and functions -----------------------------------
class Buffer(object):
def __init__(self):
self.b = ''
def write(self, s):
self.b += s
class Node(object):
def __init__(self, n, parent, time, curhead):
self.n = int(n)
self.parent = parent
self.children = []
self.curhead = curhead
self.time = time
def _make_nodes(alts, nodes, parent=None):
p = parent
for alt in alts:
curhead = 'curhead' in alt
node = Node(n=alt['seq'], parent=p, time=alt['time'], curhead=curhead)
nodes.append(node)
if alt.get('alt'):
_make_nodes(alt['alt'], nodes, p)
p = node
def make_nodes():
ut = vim.eval('undotree()')
entries = ut['entries']
root = Node(0, None, False, 0)
nodes = []
_make_nodes(entries, nodes, root)
nodes.append(root)
nmap = dict((node.n, node) for node in nodes)
return nodes, nmap
def changenr(nodes):
_curhead_l = list(itertools.dropwhile(lambda n: not n.curhead, nodes))
if _curhead_l:
current = _curhead_l[0].parent.n
else:
current = int(vim.eval('changenr()'))
return current
# Gundo rendering ------------------------------------------------------------------
# Rendering utility functions
def _fmt_time(t):
return time.strftime('%Y-%m-%d %I:%M:%S %p', time.localtime(float(t)))
def _output_preview_text(lines):
_goto_window_for_buffer_name('__Gundo_Preview__')
vim.command('setlocal modifiable')
vim.current.buffer[:] = lines
vim.command('setlocal nomodifiable')
def _generate_preview_diff(current, node_before, node_after):
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
if not node_after.n: # we're at the original file
before_lines = []
_undo_to(0)
after_lines = vim.current.buffer[:]
before_name = 'n/a'
before_time = ''
after_name = 'Original'
after_time = ''
elif not node_before.n: # we're at a pseudo-root state
_undo_to(0)
before_lines = vim.current.buffer[:]
_undo_to(node_after.n)
after_lines = vim.current.buffer[:]
before_name = 'Original'
before_time = ''
after_name = node_after.n
after_time = _fmt_time(node_after.time)
else:
_undo_to(node_before.n)
before_lines = vim.current.buffer[:]
_undo_to(node_after.n)
after_lines = vim.current.buffer[:]
before_name = node_before.n
before_time = _fmt_time(node_before.time)
after_name = node_after.n
after_time = _fmt_time(node_after.time)
_undo_to(current)
return list(difflib.unified_diff(before_lines, after_lines,
before_name, after_name,
before_time, after_time))
def _generate_change_preview_diff(current, node_before, node_after):
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
_undo_to(node_before.n)
before_lines = vim.current.buffer[:]
_undo_to(node_after.n)
after_lines = vim.current.buffer[:]
before_name = node_before.n or 'Original'
before_time = node_before.time and _fmt_time(node_before.time) or ''
after_name = node_after.n or 'Original'
after_time = node_after.time and _fmt_time(node_after.time) or ''
_undo_to(current)
return list(difflib.unified_diff(before_lines, after_lines,
before_name, after_name,
before_time, after_time))
def GundoRenderGraph():
if not _check_sanity():
return
nodes, nmap = make_nodes()
for node in nodes:
node.children = [n for n in nodes if n.parent == node]
def walk_nodes(nodes):
for node in nodes:
if node.parent:
yield (node, [node.parent])
else:
yield (node, [])
dag = sorted(nodes, key=lambda n: int(n.n), reverse=True)
current = changenr(nodes)
result = generate(walk_nodes(dag), asciiedges, current).rstrip().splitlines()
result = [' ' + l for l in result]
target = (vim.eval('g:gundo_target_f'), int(vim.eval('g:gundo_target_n')))
mappings = (vim.eval('g:gundo_map_move_older'),
vim.eval('g:gundo_map_move_newer'))
if int(vim.eval('g:gundo_help')):
header = (INLINE_HELP % (target + mappings)).splitlines()
else:
header = []
vim.command('call s:GundoOpenGraph()')
vim.command('setlocal modifiable')
vim.current.buffer[:] = (header + result)
vim.command('setlocal nomodifiable')
i = 1
for line in result:
try:
line.split('[')[0].index('@')
i += 1
break
except ValueError:
pass
i += 1
vim.command('%d' % (i+len(header)-1))
def GundoRenderPreview():
if not _check_sanity():
return
target_state = vim.eval('s:GundoGetTargetState()')
# Check that there's an undo state. There may not be if we're talking about
# a buffer with no changes yet.
if target_state == None:
_goto_window_for_buffer_name('__Gundo__')
return
else:
target_state = int(target_state)
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
nodes, nmap = make_nodes()
current = changenr(nodes)
node_after = nmap[target_state]
node_before = node_after.parent
vim.command('call s:GundoOpenPreview()')
_output_preview_text(_generate_preview_diff(current, node_before, node_after))
_goto_window_for_buffer_name('__Gundo__')
def GundoRenderChangePreview():
if not _check_sanity():
return
target_state = vim.eval('s:GundoGetTargetState()')
# Check that there's an undo state. There may not be if we're talking about
# a buffer with no changes yet.
if target_state == None:
_goto_window_for_buffer_name('__Gundo__')
return
else:
target_state = int(target_state)
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
nodes, nmap = make_nodes()
current = changenr(nodes)
node_after = nmap[target_state]
node_before = nmap[current]
vim.command('call s:GundoOpenPreview()')
_output_preview_text(_generate_change_preview_diff(current, node_before, node_after))
_goto_window_for_buffer_name('__Gundo__')
# Gundo undo/redo
def GundoRevert():
if not _check_sanity():
return
target_n = int(vim.eval('s:GundoGetTargetState()'))
back = vim.eval('g:gundo_target_n')
_goto_window_for_buffer(back)
_undo_to(target_n)
vim.command('GundoRenderGraph')
_goto_window_for_buffer(back)
if int(vim.eval('g:gundo_close_on_revert')):
vim.command('GundoToggle')
def GundoPlayTo():
if not _check_sanity():
return
target_n = int(vim.eval('s:GundoGetTargetState()'))
back = int(vim.eval('g:gundo_target_n'))
delay = int(vim.eval('g:gundo_playback_delay'))
vim.command('echo "%s"' % back)
_goto_window_for_buffer(back)
normal('zR')
nodes, nmap = make_nodes()
start = nmap[changenr(nodes)]
end = nmap[target_n]
def _walk_branch(origin, dest):
rev = origin.n < dest.n
nodes = []
if origin.n > dest.n:
current, final = origin, dest
else:
current, final = dest, origin
while current.n >= final.n:
if current.n == final.n:
break
nodes.append(current)
current = current.parent
else:
return None
nodes.append(current)
if rev:
return reversed(nodes)
else:
return nodes
branch = _walk_branch(start, end)
if not branch:
vim.command('unsilent echo "No path to that node from here!"')
return
for node in branch:
_undo_to(node.n)
vim.command('GundoRenderGraph')
normal('zz')
_goto_window_for_buffer(back)
vim.command('redraw')
vim.command('sleep %dm' % delay)
def initPythonModule():
if sys.version_info[:2] < (2, 4):
vim.command('let s:has_supported_python = 0')

View file

@ -0,0 +1,472 @@
" ============================================================================
" File: gundo.vim
" Description: vim global plugin to visualize your undo tree
" Maintainer: Steve Losh <steve@stevelosh.com>
" License: GPLv2+ -- look it up.
" Notes: Much of this code was thiefed from Mercurial, and the rest was
" heavily inspired by scratch.vim and histwin.vim.
"
" ============================================================================
"{{{ Init
if v:version < '703'"{{{
function! s:GundoDidNotLoad()
echohl WarningMsg|echomsg "Gundo unavailable: requires Vim 7.3+"|echohl None
endfunction
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
finish
endif"}}}
if !exists('g:gundo_width')"{{{
let g:gundo_width = 45
endif"}}}
if !exists('g:gundo_preview_height')"{{{
let g:gundo_preview_height = 15
endif"}}}
if !exists('g:gundo_preview_bottom')"{{{
let g:gundo_preview_bottom = 0
endif"}}}
if !exists('g:gundo_right')"{{{
let g:gundo_right = 0
endif"}}}
if !exists('g:gundo_help')"{{{
let g:gundo_help = 1
endif"}}}
if !exists("g:gundo_map_move_older")"{{{
let g:gundo_map_move_older = 'j'
endif"}}}
if !exists("g:gundo_map_move_newer")"{{{
let g:gundo_map_move_newer = 'k'
endif"}}}
if !exists("g:gundo_close_on_revert")"{{{
let g:gundo_close_on_revert = 0
endif"}}}
if !exists("g:gundo_prefer_python3")"{{{
let g:gundo_prefer_python3 = 0
endif"}}}
if !exists("g:gundo_auto_preview")"{{{
let g:gundo_auto_preview = 1
endif"}}}
if !exists("g:gundo_playback_delay")"{{{
let g:gundo_playback_delay = 60
endif"}}}
let s:has_supported_python = 0
if g:gundo_prefer_python3 && has('python3')"{{{
let s:has_supported_python = 2
elseif has('python')"
let s:has_supported_python = 1
endif
if !s:has_supported_python
function! s:GundoDidNotLoad()
echohl WarningMsg|echomsg "Gundo requires Vim to be compiled with Python 2.4+"|echohl None
endfunction
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
finish
endif"}}}
let s:plugin_path = escape(expand('<sfile>:p:h'), '\')
"}}}
"{{{ Gundo utility functions
function! s:GundoGetTargetState()"{{{
let target_line = matchstr(getline("."), '\v\[[0-9]+\]')
return matchstr(target_line, '\v[0-9]+')
endfunction"}}}
function! s:GundoGoToWindowForBufferName(name)"{{{
if bufwinnr(bufnr(a:name)) != -1
exe bufwinnr(bufnr(a:name)) . "wincmd w"
return 1
else
return 0
endif
endfunction"}}}
function! s:GundoIsVisible()"{{{
if bufwinnr(bufnr("__Gundo__")) != -1 || bufwinnr(bufnr("__Gundo_Preview__")) != -1
return 1
else
return 0
endif
endfunction"}}}
function! s:GundoInlineHelpLength()"{{{
if g:gundo_help
return 6
else
return 0
endif
endfunction"}}}
"}}}
"{{{ Gundo buffer settings
function! s:GundoMapGraph()"{{{
exec 'nnoremap <script> <silent> <buffer> ' . g:gundo_map_move_older . " :call <sid>GundoMove(1)<CR>"
exec 'nnoremap <script> <silent> <buffer> ' . g:gundo_map_move_newer . " :call <sid>GundoMove(-1)<CR>"
nnoremap <script> <silent> <buffer> <CR> :call <sid>GundoRevert()<CR>
nnoremap <script> <silent> <buffer> o :call <sid>GundoRevert()<CR>
nnoremap <script> <silent> <buffer> <down> :call <sid>GundoMove(1)<CR>
nnoremap <script> <silent> <buffer> <up> :call <sid>GundoMove(-1)<CR>
nnoremap <script> <silent> <buffer> gg gg:call <sid>GundoMove(1)<CR>
nnoremap <script> <silent> <buffer> P :call <sid>GundoPlayTo()<CR>
nnoremap <script> <silent> <buffer> p :call <sid>GundoRenderChangePreview()<CR>
nnoremap <script> <silent> <buffer> r :call <sid>GundoRenderPreview()<CR>
nnoremap <script> <silent> <buffer> q :call <sid>GundoClose()<CR>
cabbrev <script> <silent> <buffer> q call <sid>GundoClose()
cabbrev <script> <silent> <buffer> quit call <sid>GundoClose()
nnoremap <script> <silent> <buffer> <2-LeftMouse> :call <sid>GundoMouseDoubleClick()<CR>
endfunction"}}}
function! s:GundoMapPreview()"{{{
nnoremap <script> <silent> <buffer> q :call <sid>GundoClose()<CR>
cabbrev <script> <silent> <buffer> q call <sid>GundoClose()
cabbrev <script> <silent> <buffer> quit call <sid>GundoClose()
endfunction"}}}
function! s:GundoSettingsGraph()"{{{
setlocal buftype=nofile
setlocal bufhidden=hide
setlocal noswapfile
setlocal nobuflisted
setlocal nomodifiable
setlocal filetype=gundo
setlocal nolist
setlocal nonumber
setlocal norelativenumber
setlocal nowrap
call s:GundoSyntaxGraph()
call s:GundoMapGraph()
endfunction"}}}
function! s:GundoSettingsPreview()"{{{
setlocal buftype=nofile
setlocal bufhidden=hide
setlocal noswapfile
setlocal nobuflisted
setlocal nomodifiable
setlocal filetype=diff
setlocal nonumber
setlocal norelativenumber
setlocal nowrap
setlocal foldlevel=20
setlocal foldmethod=diff
call s:GundoMapPreview()
endfunction"}}}
function! s:GundoSyntaxGraph()"{{{
let b:current_syntax = 'gundo'
syn match GundoCurrentLocation '@'
syn match GundoHelp '\v^".*$'
syn match GundoNumberField '\v\[[0-9]+\]'
syn match GundoNumber '\v[0-9]+' contained containedin=GundoNumberField
hi def link GundoCurrentLocation Keyword
hi def link GundoHelp Comment
hi def link GundoNumberField Comment
hi def link GundoNumber Identifier
endfunction"}}}
"}}}
"{{{ Gundo buffer/window management
function! s:GundoResizeBuffers(backto)"{{{
call s:GundoGoToWindowForBufferName('__Gundo__')
exe "vertical resize " . g:gundo_width
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
exe "resize " . g:gundo_preview_height
exe a:backto . "wincmd w"
endfunction"}}}
function! s:GundoOpenGraph()"{{{
let existing_gundo_buffer = bufnr("__Gundo__")
if existing_gundo_buffer == -1
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
exe "new __Gundo__"
if g:gundo_preview_bottom
if g:gundo_right
wincmd L
else
wincmd H
endif
endif
call s:GundoResizeBuffers(winnr())
else
let existing_gundo_window = bufwinnr(existing_gundo_buffer)
if existing_gundo_window != -1
if winnr() != existing_gundo_window
exe existing_gundo_window . "wincmd w"
endif
else
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
if g:gundo_preview_bottom
if g:gundo_right
exe "botright vsplit +buffer" . existing_gundo_buffer
else
exe "topleft vsplit +buffer" . existing_gundo_buffer
endif
else
exe "split +buffer" . existing_gundo_buffer
endif
call s:GundoResizeBuffers(winnr())
endif
endif
if exists("g:gundo_tree_statusline")
let &l:statusline = g:gundo_tree_statusline
endif
endfunction"}}}
function! s:GundoOpenPreview()"{{{
let existing_preview_buffer = bufnr("__Gundo_Preview__")
if existing_preview_buffer == -1
if g:gundo_preview_bottom
exe "botright new __Gundo_Preview__"
else
if g:gundo_right
exe "botright vnew __Gundo_Preview__"
else
exe "topleft vnew __Gundo_Preview__"
endif
endif
else
let existing_preview_window = bufwinnr(existing_preview_buffer)
if existing_preview_window != -1
if winnr() != existing_preview_window
exe existing_preview_window . "wincmd w"
endif
else
if g:gundo_preview_bottom
exe "botright split +buffer" . existing_preview_buffer
else
if g:gundo_right
exe "botright vsplit +buffer" . existing_preview_buffer
else
exe "topleft vsplit +buffer" . existing_preview_buffer
endif
endif
endif
endif
if exists("g:gundo_preview_statusline")
let &l:statusline = g:gundo_preview_statusline
endif
endfunction"}}}
function! s:GundoClose()"{{{
if s:GundoGoToWindowForBufferName('__Gundo__')
quit
endif
if s:GundoGoToWindowForBufferName('__Gundo_Preview__')
quit
endif
exe bufwinnr(g:gundo_target_n) . "wincmd w"
endfunction"}}}
function! s:GundoOpen()"{{{
if !exists('g:gundo_py_loaded')
if s:has_supported_python == 2 && g:gundo_prefer_python3
exe 'py3file ' . s:plugin_path . '/gundo.py'
python3 initPythonModule()
else
exe 'pyfile ' . s:plugin_path . '/gundo.py'
python initPythonModule()
endif
if !s:has_supported_python
function! s:GundoDidNotLoad()
echohl WarningMsg|echomsg "Gundo unavailable: requires Vim 7.3+"|echohl None
endfunction
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
call s:GundoDidNotLoad()
return
endif"
let g:gundo_py_loaded = 1
endif
" Save `splitbelow` value and set it to default to avoid problems with
" positioning new windows.
let saved_splitbelow = &splitbelow
let &splitbelow = 0
call s:GundoOpenPreview()
exe bufwinnr(g:gundo_target_n) . "wincmd w"
call s:GundoRenderGraph()
call s:GundoRenderPreview()
" Restore `splitbelow` value.
let &splitbelow = saved_splitbelow
endfunction"}}}
function! s:GundoToggle()"{{{
if s:GundoIsVisible()
call s:GundoClose()
else
let g:gundo_target_n = bufnr('')
let g:gundo_target_f = @%
call s:GundoOpen()
endif
endfunction"}}}
function! s:GundoShow()"{{{
if !s:GundoIsVisible()
let g:gundo_target_n = bufnr('')
let g:gundo_target_f = @%
call s:GundoOpen()
endif
endfunction"}}}
function! s:GundoHide()"{{{
if s:GundoIsVisible()
call s:GundoClose()
endif
endfunction"}}}
"}}}
"{{{ Gundo mouse handling
function! s:GundoMouseDoubleClick()"{{{
let start_line = getline('.')
if stridx(start_line, '[') == -1
return
else
call s:GundoRevert()
endif
endfunction"}}}
"}}}
"{{{ Gundo movement
function! s:GundoMove(direction) range"{{{
let start_line = getline('.')
if v:count1 == 0
let move_count = 1
else
let move_count = v:count1
endif
let distance = 2 * move_count
" If we're in between two nodes we move by one less to get back on track.
if stridx(start_line, '[') == -1
let distance = distance - 1
endif
let target_n = line('.') + (distance * a:direction)
" Bound the movement to the graph.
if target_n <= s:GundoInlineHelpLength() - 1
call cursor(s:GundoInlineHelpLength(), 0)
else
call cursor(target_n, 0)
endif
let line = getline('.')
" Move to the node, whether it's an @ or an o
let idx1 = stridx(line, '@')
let idx2 = stridx(line, 'o')
if idx1 != -1
call cursor(0, idx1 + 1)
else
call cursor(0, idx2 + 1)
endif
if g:gundo_auto_preview == 1
call s:GundoRenderPreview()
endif
endfunction"}}}
"}}}
"{{{ Gundo rendering
function! s:GundoRenderGraph()"{{{
if s:has_supported_python == 2 && g:gundo_prefer_python3
python3 GundoRenderGraph()
else
python GundoRenderGraph()
endif
endfunction"}}}
function! s:GundoRenderPreview()"{{{
if s:has_supported_python == 2 && g:gundo_prefer_python3
python3 GundoRenderPreview()
else
python GundoRenderPreview()
endif
endfunction"}}}
function! s:GundoRenderChangePreview()"{{{
if s:has_supported_python == 2 && g:gundo_prefer_python3
python3 GundoRenderChangePreview()
else
python GundoRenderChangePreview()
endif
endfunction"}}}
"}}}
"{{{ Gundo undo/redo
function! s:GundoRevert()"{{{
if s:has_supported_python == 2 && g:gundo_prefer_python3
python3 GundoRevert()
else
python GundoRevert()
endif
endfunction"}}}
function! s:GundoPlayTo()"{{{
if s:has_supported_python == 2 && g:gundo_prefer_python3
python3 GundoPlayTo()
else
python GundoPlayTo()
endif
endfunction"}}}
"}}}
"{{{ Misc
function! gundo#GundoToggle()"{{{
call s:GundoToggle()
endfunction"}}}
function! gundo#GundoShow()"{{{
call s:GundoShow()
endfunction"}}}
function! gundo#GundoHide()"{{{
call s:GundoHide()
endfunction"}}}
function! gundo#GundoRenderGraph()"{{{
call s:GundoRenderGraph()
endfunction"}}}
augroup GundoAug
autocmd!
autocmd BufNewFile __Gundo__ call s:GundoSettingsGraph()
autocmd BufNewFile __Gundo_Preview__ call s:GundoSettingsPreview()
augroup END
"}}}

View file

@ -0,0 +1,297 @@
*gundo.txt* Graph your undo tree so you can actually USE it.
Making Vim's undo tree usable by humans.
==============================================================================
CONTENTS *Gundo-contents*
1. Intro ........................... |GundoIntro|
2. Usage ........................... |GundoUsage|
3. Configuration ................... |GundoConfig|
3.1 gundo_width ............... |gundo_width|
3.2 gundo_preview_height ...... |gundo_preview_height|
3.3 gundo_preview_bottom ...... |gundo_preview_bottom|
3.4 gundo_right ............... |gundo_right|
3.5 gundo_help ................ |gundo_help|
3.6 gundo_disable ............. |gundo_disable|
3.7 gundo_map_move_older ...... |gundo_map_move_older|
gundo_map_move_newer ...... |gundo_map_move_newer|
3.8 gundo_close_on_revert ..... |gundo_close_on_revert|
3.9 gundo_preview_statusline .. |gundo_preview_statusline|
gundo_tree_statusline ..... |gundo_tree_statusline|
3.10 gundo_auto_preview ........ |gundo_auto_preview|
3.11 gundo_playback_delay ...... |gundo_playback_delay|
4. License ......................... |GundoLicense|
5. Bugs ............................ |GundoBugs|
6. Contributing .................... |GundoContributing|
7. Changelog ....................... |GundoChangelog|
8. Credits ......................... |GundoCredits|
==============================================================================
1. Intro *GundoIntro*
You know that Vim lets you undo changes like any text editor. What you might
not know is that it doesn't just keep a list of your changes -- it keeps
a goddamed |:undo-tree| of them.
Say you make a change (call it X), undo that change, and then make another
change (call it Y). With most editors, change X is now gone forever. With Vim
you can get it back.
The problem is that trying to do this in the real world is painful. Vim gives
you an |:undolist| command that shows you the leaves of the tree. Good luck
finding the change you want in that list.
Gundo is a plugin to make browsing this ridiculously powerful undo tree less
painful.
==============================================================================
2. Usage *GundoUsage*
We'll get to the technical details later, but if you're a human the first
thing you need to do is add a mapping to your |:vimrc| to toggle the undo
graph: >
nnoremap <F5> :GundoToggle<CR>
Change the mapped key to suit your taste. We'll stick with F5 because that's
what the author uses.
Now you can press F5 to toggle the undo graph and preview pane, which will
look something like this: >
Undo graph File
+-----------------------------------+------------------------------------+
| " Gundo for something.txt [1] |one |
| " j/k - move between undo states |two |
| " <cr> - revert to that state |three |
| |five |
| @ [5] 3 hours ago | |
| | | |
| | o [4] 4 hours ago | |
| | | | |
| o | [3] 4 hours ago | |
| | | | |
| o | [2] 4 hours ago | |
| |/ | |
| o [1] 4 hours ago | |
| | | |
| o [0] Original | |
+-----------------------------------+ |
| --- 3 2010-10-12 06:27:35 PM | |
| +++ 5 2010-10-12 07:38:37 PM | |
| @@ -1,3 +1,4 | |
| one | |
| two | |
| three | |
| +five | |
+-----------------------------------+------------------------------------+
Preview pane
Your current position in the undo tree is marked with an '@' character. Other
nodes are marked with an 'o' character.
When you toggle open the graph Gundo will put your cursor on your current
position in the tree. You can move up and down the graph with the j and
k keys.
You can move to the top of the graph (the newest state) with gg and to the
bottom of the graph (the oldest state) with G.
As you move between undo states the preview pane will show you a unified diff
of the change that state made.
Pressing enter on a state (or double clicking on it) will revert the contents
of the file to match that state.
You can use p on a state to make the preview window show the diff between
your current state and the selected state, instead of a preview of what the
selected state changed.
Pressing P while on a state will initiate "play to" mode targeted at that
state. This will replay all the changes between your current state and the
target, with a slight pause after each change. It's mostly useless, but can be
fun to watch and see where your editing lags -- that might be a good place to
define a new mapping to speed up your editing.
Pressing q while in the undo graph will close it. You can also just press your
toggle mapping key.
==============================================================================
3. Configuration *GundoConfig*
You can tweak the behavior of Gundo by setting a few variables in your :vimrc
file. For example: >
let g:gundo_width = 60
let g:gundo_preview_height = 40
let g:gundo_right = 1
------------------------------------------------------------------------------
3.1 g:gundo_width *gundo_width*
Set the horizontal width of the Gundo graph (and preview).
Default: 45
------------------------------------------------------------------------------
3.2 g:gundo_preview_height *gundo_preview_height*
Set the vertical height of the Gundo preview.
Default: 15
------------------------------------------------------------------------------
3.3 g:gundo_preview_bottom *gundo_preview_bottom*
Force the preview window below current windows instead of below the graph.
This gives the preview window more space to show the unified diff.
Example:
+--------+ +--------+
!g! ! ! !g!
!g! ! or ! !g!
!g!______! !______!g!
!g!pppppp! !pppppp!g!
+--------+ +--------+
Default: 0
------------------------------------------------------------------------------
3.4 g:gundo_right *gundo_right*
Set this to 1 to make the Gundo graph (and preview) open on the right side
instead of the left.
Default: 0 (off, open on the left side)
------------------------------------------------------------------------------
3.5 g:gundo_help *gundo_help*
Set this to 0 to disable the help text in the Gundo graph window.
Default: 1 (show the help)
------------------------------------------------------------------------------
3.6 g:gundo_disable *gundo_disable*
Set this to 1 to disable Gundo entirely.
Useful if you use the same ~/.vim folder on multiple machines, and some of
them may not have Python support.
Default: 0 (Gundo is enabled as usual)
------------------------------------------------------------------------------
3.7 g:gundo_map_move_older, g:gundo_map_move_newer *gundo_map_move_older*
*gundo_map_move_newer*
These options let you change the keys that navigate the undo graph. This is
useful if you use a Dvorak keyboard and have changed your movement keys.
Default: gundo_map_move_older = "j"
gundo_map_move_newer = "k"
------------------------------------------------------------------------------
3.8 g:gundo_close_on_revert *gundo_close_on_revert*
Set this to 1 to automatically close the Gundo windows when reverting.
Default: 0 (windows do not automatically close)
------------------------------------------------------------------------------
3.9 g:gundo_preview_statusline *gundo_preview_statusline*
g:gundo_tree_statusline *gundo_tree_statusline*
Set these to a string to display it as the status line for each Gundo window.
Default: unset (windows use the default statusline)
------------------------------------------------------------------------------
3.10 g:gundo_auto_preview *gundo_auto_preview*
Set this to 0 to disable automatically rendering preview diffs as you move
through the undo tree (you can still render a specific diff with r). This can
be useful on large files and undo trees to speed up Gundo.
Default: 1 (automatically preview diffs)
------------------------------------------------------------------------------
3.11 g:gundo_playback_delay *gundo_playback_delay*
This is the delay in milliseconds between each change when running 'play to'
mode. Set this to a higher number for a slower playback or to a lower number
for a faster playback.
Default: 60
==============================================================================
4. License *GundoLicense*
GPLv2+. Look it up.
==============================================================================
5. Bugs *GundoBugs*
If you find a bug please post it on the issue tracker:
http://bitbucket.org/sjl/gundo.vim/issues?status=new&status=open
==============================================================================
6. Contributing *GundoContributing*
Think you can make this plugin better? Awesome. Fork it on BitBucket or GitHub
and send a pull request.
BitBucket: http://bitbucket.org/sjl/gundo.vim/
GitHub: http://github.com/sjl/gundo.vim/
==============================================================================
7. Changelog *GundoChangelog*
v2.5.0
* Fix the help window to take custom mappings into account.
* Add g:gundo_playback_delay option.
v2.4.0
* Add auto preview option.
* Add 'r' mapping to preview current state.
* Add public gundo#GundoShow() and gundo#GundoHide() functions.
v2.3.0
* Add statusline configuration.
v2.2.2
* More performance improvements.
v2.2.1
* Refactoring and performance improvements.
v2.2.0
* Add the g:gundo_close_on_revert setting.
* Fix a bug with the splitbelow setting.
v2.1.1
* Fix a bug with the movement key mappings.
v2.1.0
* Warnings about having an incompatible Vim and/or Python installation
are now deferred until the first time you try to use Gundo, instead
of being displayed on launch.
* The <j> and <k> mappings are now configurable with
g:gundo_map_move_older and g:gundo_map_move_newer.
* The o, <Up> and <Down> keys are now mapped in the Gundo pane.
* Improve and add several unit tests for Gundo.
v2.0.0
* Make GundoToggle close the Gundo windows if they're visible but not the
current window, instead of moving to them.
* Add the g:gundo_help setting.
* Add the g:gundo_disable setting.
* Add the 'p' mapping to preview the result of reverting to the selected
state.
* Fix movement commands with counts in the graph.
v1.0.0
* Initial stable release.
==============================================================================
8. Credits *GundoCredits*
The graphing code was all taken from Mercurial, hence the GPLv2+ license.
The plugin was heavily inspired by histwin.vim, and the code for scratch.vim
helped the author get started.
==============================================================================

3
.vim/bundle/gundo/package.sh Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
hg archive ~/Desktop/gundo.zip -I 'doc' -I 'plugin' -I 'autoload' -I README.markdown

View file

@ -0,0 +1,24 @@
" ============================================================================
" File: gundo.vim
" Description: vim global plugin to visualize your undo tree
" Maintainer: Steve Losh <steve@stevelosh.com>
" License: GPLv2+ -- look it up.
" Notes: Much of this code was thiefed from Mercurial, and the rest was
" heavily inspired by scratch.vim and histwin.vim.
"
" ============================================================================
"{{{ Init
if !exists('g:gundo_debug') && (exists('g:gundo_disable') || exists('loaded_gundo') || &cp)"{{{
finish
endif
let loaded_gundo = 1"}}}
"}}}
"{{{ Misc
command! -nargs=0 GundoToggle call gundo#GundoToggle()
command! -nargs=0 GundoShow call gundo#GundoShow()
command! -nargs=0 GundoHide call gundo#GundoHide()
command! -nargs=0 GundoRenderGraph call gundo#GundoRenderGraph()
"}}}

Binary file not shown.

View file

@ -0,0 +1,544 @@
<!DOCTYPE html>
<html>
<head>
<title>Gundo - Visualize your Vim Undo Tree</title>
<base href="/gundo.vim/">
<link rel="stylesheet/less" href="style.less" type="text/css">
<script src="less.js" type="text/javascript"></script>
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.5.0/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-15328874-3']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="repos">
<a href="http://bitbucket.org/sjl/gundo.vim/">Mercurial Repository</a><br/>
<a href="http://github.com/sjl/gundo.vim/">Git Repository</a><br/>
<a class="FlattrButton" style="display:none;" rev="flattr;button:compact;" href="http://bitbucket.org/sjl/gundo.vim/"></a>
</div>
<div class="wrap">
<header>
<h1>Gundo</h1>
<h2>Graph your Vim undo tree in style.</h2>
</header>
<section>
<a href="http://www.flickr.com/photos/sjl7678/5093114605/"
title="gundo by stevelosh, on Flickr"
><img src="http://farm5.static.flickr.com/4113/5093114605_ebc46d6494_m.jpg"
width="234" height="240" alt="gundo" /></a>
<p>
You know that Vim lets you undo changes like any text editor. What you might
not know is that it doesn't just keep a list of your changes &mdash; it keeps
a <a href="http://vim.wikia.com/wiki/Using_undo_branches">tree</a> of them.
</p>
<p>
Say you make a change (call it X), undo that change, and then make another
change (call it Y). With most editors, change X is now gone forever. With Vim
you can get it back.
</p>
<p>
The problem is that trying to do this in the real world is painful. Vim gives
you an <code>:undolist</code> command that shows you the leaves of the tree. Good luck
finding the change you want in that list.
</p>
<p>
Gundo is a plugin to make browsing this ridiculously powerful undo tree less
painful.
</p>
<p>
Check out this
<a href="http://screenr.com/M9l">quick screencast</a>
if you want to see it in action.
</p>
</section>
<nav>
<ol>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#usage">Usage</a></li>
<li>
<a href="#configuration">Configuration</a>
<ul>
<li><a href="#gundo_width">g:gundo_width</a></li>
<li><a href="#gundo_preview_height">g:gundo_preview_height</a></li>
<li><a href="#gundo_preview_bottom">g:gundo_preview_bottom</a></li>
<li><a href="#gundo_right">g:gundo_right</a></li>
<li><a href="#gundo_help">g:gundo_help</a></li>
<li><a href="#gundo_disable">g:gundo_disable</a></li>
<li><a href="#gundo_map_move">g:gundo_map_move_[older/newer]</a></li>
<li><a href="#gundo_close_on_revert">g:gundo_close_on_revert</a></li>
<li><a href="#gundo_statusline">g:gundo_[preview/tree]_statusline</a></li>
<li><a href="#gundo_auto_preview">g:gundo_auto_preview</a></li>
<li><a href="#gundo_playback_delay">g:gundo_playback_delay</a></li>
</ul>
</li>
<li><a href="#license">License</a></li>
<li><a href="#bugs">Bugs</a></li>
<li><a href="#contributing">Contributing</a></li>
<li><a href="#changelog">Changelog</a></li>
<li><a href="#credits">Credits</a></li>
</ol>
</nav>
<section>
<a name="requirements"></a>
<h1>Requirements</h1>
<p>
Gundo requires Vim 7.3+ compiled with Python support, and Python 2.4+.
</p>
</section>
<section>
<a name="installation"></a>
<h1>Installation</h1>
<p>Use Pathogen. Don't use pathogen? Start.</p>
<pre>hg clone http://bitbucket.org/sjl/gundo.vim ~/.vim/bundle/gundo</pre>
<p>There's a git mirror if you prefer:</p>
<pre>git clone http://github.com/sjl/gundo.vim.git ~/.vim/bundle/gundo</pre>
<p>Add a mapping to your ~/.vimrc (change the key to suit your taste):</p>
<pre>nnoremap &lt;F5&gt; :GundoToggle&lt;CR&gt;</pre>
</section>
<section>
<a name="usage"></a>
<h1>Usage</h1>
<p>
We'll get to the technical details later, but if you're a human the first
thing you need to do is add a mapping to your vimrc file to toggle the undo
graph:
</p>
<pre>nnoremap &lt;F5&gt; :GundoToggle&lt;CR&gt;</pre>
<p>
Change the mapped key to suit your taste. We'll stick with <code>&lt;F5&gt;</code> because that's
what the author uses.
</p>
<p>
Now you can press <code>&lt;F5&gt;</code> to toggle the undo graph and preview pane, which will
look something like this:
</p>
<pre>
Undo graph File
+-----------------------------------+---------------------------+
| " Gundo for something.txt [1] |one |
| " j/k - move between undo states |two |
| " &lt;cr&gt; - revert to that state |three |
| |five |
| @ [5] 3 hours ago | |
| | | |
| | o [4] 4 hours ago | |
| | | | |
| o | [3] 4 hours ago | |
| | | | |
| o | [2] 4 hours ago | |
| |/ | |
| o [1] 4 hours ago | |
| | | |
| o [0] Original | |
+-----------------------------------+ |
| --- 3 2010-10-12 06:27:35 PM | |
| +++ 5 2010-10-12 07:38:37 PM | |
| @@ -1,3 +1,4 | |
| one | |
| two | |
| three | |
| +five | |
+-----------------------------------+---------------------------+
Preview pane
</pre>
<p>
Your current position in the undo tree is marked with an <code>@</code> character. Other
nodes are marked with an <code>o</code> character.
</p>
<p>
When you toggle open the graph Gundo will put your cursor on your current
position in the tree. You can move up and down the graph with the <code>j</code> and
<code>k</code> keys.
</p>
<p>
You can move to the top of the graph (the newest state) with <code>gg</code> and to the
bottom of the graph (the oldest state) with <code>G</code>.
</p>
<p>
As you move between undo states the preview pane will show you a unified diff
of the change that state made.
</p>
<p>
Pressing <code>return</code> on a state (or double clicking on it) will
revert the contents of the file to match that state.
</p>
<p>
You can use <code>p</code> on a state to make the preview window show the
diff between your current state and the selected state, instead of a preview
of what the selected state changed.
</p>
<p>
Pressing <code>P</code> while on a state will initiate "play to" mode targeted at that
state. This will replay all the changes between your current state and the
target, with a slight pause after each change. It's mostly useless, but can be
fun to watch and see where your editing lags &mdash; that might be a good place to
define a new mapping to speed up your editing.
</p>
<p>
Pressing <code>q</code> while in the undo graph will close it. You can also just press your
toggle mapping key.
</p>
</section>
<section>
<a name="configuration"></a>
<h1>Configuration</h1>
<p>
You can tweak the behavior of Gundo by setting a few variables
in your :vimrc file. For example:
</p>
<pre>
let g:gundo_width = 60
let g:gundo_preview_height = 40
let g:gundo_right = 1
</pre>
<a name="gundo_width"></a>
<h2>g:gundo_width</h2>
<p>Set the horizontal width of the Gundo graph (and preview).</p>
<p>Default: 45</p>
<a name="gundo_preview_height"></a>
<h2>g:gundo_preview_height</h2>
<p>Set the vertical height of the Gundo preview.</p>
<p>Default: 15</p>
<a name="gundo_preview_bottom"></a>
<h2>g:gundo_preview_bottom</h2>
<p>
Force the preview window below current windows instead of below
the graph. This gives the preview window more space to show the
unified diff.
</p>
<p>Example:</p>
<pre>
+--------+ +--------+
!g! ! ! !g!
!g! ! or ! !g!
!g!______! !______!g!
!g!pppppp! !pppppp!g!
+--------+ +--------+
</pre>
<p>Default: 0</p>
<a name="gundo_right"></a>
<h2>g:gundo_right</h2>
<p>
Set this to 1 to make the Gundo graph (and preview) open on the
right side instead of the left.
</p>
<p>Default: 0 (off, open on the left side)</p>
<a name="gundo_help"></a>
<h2>g:gundo_help</h2>
<p>Set this to 0 to disable the help text in the Gundo graph window.</p>
<p>Default: 1 (show the help)</p>
<a name="gundo_disable"></a>
<h2>g:gundo_disable</h2>
<p>Set this to 1 to disable Gundo entirely.</p>
<p>
Useful if you use the same <code>~/.vim</code> folder on
multiple machines, and some of them may not have Python support.
</p>
<p>Default: 0 (Gundo is enabled as usual)</p>
<a name="gundo_map_move"></a>
<h2>g:gundo_map_move_[older/newer]</h2>
<p>
These options let you change the keys that navigate the
undo graph. This is useful if you use a Dvorak keyboard and
have changed your movement keys.
</p>
<p>
Default:<br/>
gundo_map_move_older: "j"<br/>
gundo_map_move_newer: "k"
</p>
<a name="gundo_close_on_revert"></a>
<h2>g:gundo_close_on_revert</h2>
<p>Set this to 1 to automatically close the Gundo windows when reverting.</p>
<p>Default: 0 (windows do not automatically close)</p>
<a name="gundo_statusline"></a>
<h2>g:gundo_[preview/tree]_statusline</h2>
<p>
Set this to 0 to disable automatically rendering preview diffs as you move
through the undo tree (you can still render a specific diff with r). This can
be useful on large files and undo trees to speed up Gundo.
</p>
<p>Default: unset (windows use the default statusline)</p>
<a name="#gundo_auto_preview"></a>
<h2>g:gundo_auto_preview</h2>
<p>Set this to 1 to rendering diff automatically with cursor move.</p>
<p>Default: 1 (auto preview diff)</p>
<a name="#gundo_playback_delay"></a>
<h2>g:gundo_playback_delay</h2>
<p>
This is the delay in milliseconds between each change when running 'play to'
mode. Set this to a higher number for a slower playback or to a lower number
for a faster playback.
</p>
<p>Default: 60</p>
</section>
<section>
<a name="license"></a>
<h1>License</h1>
<p><a href="http://www.opensource.org/licenses/gpl-2.0.php">GPLv2+</a>.</p>
</section>
<section>
<a name="bugs"></a>
<h1>Bugs</h1>
<p>
If you find a bug please post it on the
<a href="http://bitbucket.org/sjl/gundo.vim/issues?status=new&status=open">issue tracker</a>.
</p>
</section>
<section>
<a name="contributing"></a>
<h1>Contributing</h1>
<p>
Fork the repository on
<a href="http://bitbucket.org/sjl/gundo.vim/">BitBucket</a>
or
<a href="http://github.com/sjl/gundo.vim/">GitHub</a>
and send a pull request.
</p>
<p>Make sure you document your changes in the following places:</p>
<ul>
<li>The <code>README.markdown</code> file.</li>
<li>The <code>site/index.html</code> file.</li>
<li>The <code>doc/gundo.txt</code> file.</li>
</ul>
</section>
<section>
<a name="changelog"></a>
<h1>Changelog</h1>
<ol class="changelog">
<li>v2.5.0
<ul>
<li>
Fix the help window to take custom mappings into account.
</li>
<li>
Add <code>g:gundo_playback_delay</code> option.
</li>
</ul>
</li>
<li>v2.4.0
<ul>
<li>
Add auto preview option.
</li>
<li>
Add 'r' mapping to preview current state.
</li>
<li>
Add public <code>gundo#GundoShow()</code> and <code>gundo#GundoHide()</code> functions.
</li>
</ul>
</li>
<li>v2.3.0
<ul>
<li>
Add statusline configuration.
</li>
</ul>
</li>
<li>v2.2.2
<ul>
<li>
More performance improvements.
</li>
</ul>
</li>
<li>v2.2.1
<ul>
<li>
Refactoring and performance improvements.
</li>
</ul>
</li>
<li>v2.2.0
<ul>
<li>
Add the <code>g:gundo_close_on_revert</code> setting.
</li>
<li>
Fix a bug with the <code>splitbelow</code> setting.
</li>
</ul>
</li>
<li>v2.1.1
<ul>
<li>
Fix a bug with the movement key mappings.
</li>
</ul>
</li>
<li>v2.1.0
<ul>
<li>
Warnings about having an incompatible Vim and/or
Python installation are now deferred until the
first time you try to use Gundo, instead of being
displayed on launch.
</li>
<li>
The <code>j</code> and <code>k</code> mappings are
now configurable with
<code>g:gundo_map_move_older</code> and
<code>g:gundo_map_move_newer</code>.
</li>
<li>
The <code>o</code>, <code>Up</code> and
<code>Down</code> keys are now mapped in the
Gundo pane.
</li>
<li>
Improve and add several unit tests for Gundo.
</li>
</ul>
</li>
<li>v2.0.0
<ul>
<li>
Make <code>GundoToggle</code> close the Gundo windows if they're
visible but not the current window, instead of moving to them.
</li>
<li>Add the <code>g:gundo_disable</code> setting.</li>
<li>Add the <code>g:gundo_help</code> setting.</li>
<li>
Add the <code>p</code> mapping to preview the result of
reverting to the selected state.
</li>
<li>Fix movement commands with counts in the graph.</li>
</ul>
</li>
<li>v1.0.0
<ul>
<li>Initial stable release.</li>
</ul>
</li>
</ol>
</section>
<section>
<a name="credits"></a>
<h1>Credits</h1>
<p>
The graphing code was all taken from Mercurial, hence the
GPLv2+ license.
</p>
<p>
The plugin was heavily inspired by histwin.vim, and the code
for scratch.vim helped the author get started.
</p>
</section>
<footer>
Gundo was written by
<a href="http://stevelosh.com">Steve Losh</a>
with a lot of help from others.
</footer>
</div>
<script type="text/javascript">
var _gauges = _gauges || [];
(function() {
var t = document.createElement('script');
t.type = 'text/javascript';
t.async = true;
t.id = 'gauges-tracker';
t.setAttribute('data-site-id', '4f843f8c613f5d65280000e6');
t.src = '//secure.gaug.es/track.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(t, s);
})();
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
hg -R ~/src/sjl.bitbucket.org pull -u
rsync --delete -az . ~/src/sjl.bitbucket.org/gundo.vim
hg -R ~/src/sjl.bitbucket.org commit -Am 'gundo.vim: Update documentation.'
hg -R ~/src/sjl.bitbucket.org push

View file

@ -0,0 +1,99 @@
@font-face {
font-family: "Essays 1743";
src: url(Essays1743.ttf);
}
html {
overflow-y: scroll;
}
html, body {
background-color: #fdfdfd;
color: #111;
font: normal 16px/22px Palatino, Georgia, serif;
.wrap {
width: 599px;
margin: 48px auto;
}
h1, h2, h3, h4, h5, h6 {
font-family: "Essays 1743", Palatino, serif;
line-height: 1;
margin: 0;
margin-bottom: 22px;
}
a {
color: #04C;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
p, pre {
margin: 0 0 22px 0;
}
code {
background-color: #f5f5f5;
border: 1px solid #ccc;
font: normal 14px Menlo, Monaco, Consolas, monospace;
padding: 1px 4px;
line-height: 1;
}
pre {
background-color: #f5f5f5;
border: 1px solid #ccc;
font: normal 14px Menlo, Monaco, Consolas, monospace;
margin-left: 22px;
padding: 11px;
}
img {
border: 1px solid #ccc;
padding: 4px;
float: right;
margin-left: 36px;
margin-bottom: 44px;
}
}
#repos {
position: fixed;
right: 10px;
top: 10px;
}
header {
h1 {
text-align: center;
font-size: 92px;
margin-bottom: 6px;
}
h2 {
color: #444;
text-align: center;
font-size: 36px;
letter-spacing: -1px;
}
}
section {
margin-top: 44px;
h1 {
font-size: 38px;
}
h2 {
font-size: 28px;
}
ol.changelog {
list-style-type: none;
padding-left: 0;
font-weight: bold;
ul {
font-weight: normal;
}
}
}
footer {
text-align: center;
font-style: italic;
margin-top: 66px;
}

View file

@ -0,0 +1,20 @@
This is Gundo's test suite. In case you didn't know, unit testing vim plugins
is a horrible experience.
Gundo bundles Luc Hermitte's [UT][] framework to make the process less painful.
[UT]: http://code.google.com/p/lh-vim/wiki/UT
To run a test, `cd` into the `tests` directory and use:
./run-tests.sh [[some-test.vim] ...]
The script will run the console vim command with its own vimrc and .vim
directory, so none of your other plugins should interfere. The result of the
tests will be shown in the quickfix window of this vim instance.
The `q` key will be remapped to perform `:qa!` so you can close everything
quickly if it all looks good.
The `run-tests.sh` script is still a work in progress. I need to figure out
a good way of collecting results. Suggestions and/or patches are very welcome.

View file

@ -0,0 +1 @@
../../../../bundled/ut/autoload/lh/UT.vim

View file

@ -0,0 +1,147 @@
"=============================================================================
" $Id: askvim.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/askvim.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 17th Apr 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (17th Apr 2007)
"------------------------------------------------------------------------
" Description:
" Defines functions that asks vim what it is relinquish to tell us
" - menu
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.0.0:
" TODO: «missing features»
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#askvim#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#askvim#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" # Public {{{2
" Function: lh#askvim#exe(command) {{{3
function! lh#askvim#Exe(command)
echomsg 'lh#askvim#Exe() is deprecated, use lh#askvim#exe()'
return lh#askvim#exe(a:command)
endfunction
function! lh#askvim#exe(command)
let save_a = @a
try
silent! redir @a
silent! exe a:command
redir END
finally
" Always restore everything
let res = @a
let @a = save_a
return res
endtry
endfunction
" Function: lh#askvim#menu(menuid) {{{3
function! s:AskOneMenu(menuact, res)
let sKnown_menus = lh#askvim#exe(a:menuact)
let lKnown_menus = split(sKnown_menus, '\n')
" echo string(lKnown_menus)
" 1- search for the menuid
" todo: fix the next line to correctly interpret "stuff\.stuff" and
" "stuff\\.stuff".
let menuid_parts = split(a:menuact, '\.')
let simplifiedKnown_menus = deepcopy(lKnown_menus)
call map(simplifiedKnown_menus, 'substitute(v:val, "&", "", "g")')
" let idx = lh#list#match(simplifiedKnown_menus, '^\d\+\s\+'.menuid_parts[-1])
let idx = match(simplifiedKnown_menus, '^\d\+\s\+'.menuid_parts[-1])
if idx == -1
" echo "not found"
return
endif
" echo "l[".idx."]=".lKnown_menus[idx]
if empty(a:res)
let a:res.priority = matchstr(lKnown_menus[idx], '\d\+\ze\s\+.*')
let a:res.name = matchstr(lKnown_menus[idx], '\d\+\s\+\zs.*')
let a:res.actions = {}
" else
" what if the priority isn't the same?
endif
" 2- search for the menu definition
let idx += 1
while idx != len(lKnown_menus)
echo "l[".idx."]=".lKnown_menus[idx]
" should not happen
if lKnown_menus[idx] =~ '^\d\+' | break | endif
" :h showing-menus
" -> The format of the result of the call to Exe() seems to be:
" ^ssssMns-sACTION$
" s == 1 whitespace
" M == mode (inrvcs)
" n == noremap(*)/script(&)
" - == disable(-)/of not
let act = {}
let menu_def = matchlist(lKnown_menus[idx],
\ '^\s*\([invocs]\)\([&* ]\) \([- ]\) \(.*\)$')
if len(menu_def) > 4
let act.mode = menu_def[1]
let act.nore_script = menu_def[2]
let act.disabled = menu_def[3]
let act.action = menu_def[4]
else
echomsg string(menu_def)
echoerr "lh#askvim#menu(): Cannot decode ``".lKnown_menus[idx]."''"
endif
let a:res.actions["mode_" . act.mode] = act
let idx += 1
endwhile
" n- Return the result
return a:res
endfunction
function! lh#askvim#menu(menuid, modes)
let res = {}
let i = 0
while i != strlen(a:modes)
call s:AskOneMenu(a:modes[i].'menu '.a:menuid, res)
let i += 1
endwhile
return res
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,97 @@
"=============================================================================
" $Id: buffer.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/buffer.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 23rd Jan 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Defines functions that help finding windows and handling buffers.
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v 1.0.0 First Version
" (*) Functions moved from searchInRuntimeTime
" v 2.2.0
" (*) new function: lh#buffer#list()
" TODO:
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
" ## Functions {{{1
"------------------------------------------------------------------------
" # Debug {{{2
function! lh#buffer#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#buffer#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" # Public {{{2
" Function: lh#buffer#find({filename}) {{{3
" If {filename} is opened in a window, jump to this window, otherwise return -1
" Moved from searchInRuntimeTime.vim
function! lh#buffer#find(filename)
let b = bufwinnr(a:filename)
if b == -1 | return b | endif
exe b.'wincmd w'
return b
endfunction
function! lh#buffer#Find(filename)
return lh#buffer#find(a:filename)
endfunction
" Function: lh#buffer#jump({filename},{cmd}) {{{3
function! lh#buffer#jump(filename, cmd)
if lh#buffer#find(a:filename) != -1 | return | endif
exe a:cmd . ' ' . a:filename
endfunction
function! lh#buffer#Jump(filename, cmd)
return lh#buffer#jump(a:filename, a:cmd)
endfunction
" Function: lh#buffer#scratch({bname},{where}) {{{3
function! lh#buffer#scratch(bname, where)
try
silent exe a:where.' sp '.a:bname
catch /.*/
throw "Can't open a buffer named '".a:bname."'!"
endtry
setlocal bt=nofile bh=wipe nobl noswf ro
endfunction
function! lh#buffer#Scratch(bname, where)
return lh#buffer#scratch(a:bname, a:where)
endfunction
" Function: lh#buffer#list() {{{3
function! lh#buffer#list()
let all = range(0, bufnr('$'))
" let res = lh#list#transform_if(all, [], 'v:1_', 'buflisted')
let res = lh#list#copy_if(all, [], 'buflisted')
return res
endfunction
" Ex: echo lh#list#transform(lh#buffer#list(), [], "bufname")
"=============================================================================
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,268 @@
"=============================================================================
" $Id: dialog.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/buffer/dialog.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 21st Sep 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description: «description»
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v 1.0.0 First Version
" (*) Functions imported from Mail_mutt_alias.vim
" TODO:
" (*) --abort-- line
" (*) custom messages
" (*) do not mess with search history
" (*) support any &magic
" (*) syntax
" (*) add number/letters
" (*) tag with '[x] ' instead of '* '
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"=============================================================================
" ## Globals {{{1
let s:LHdialog = {}
"=============================================================================
" ## Functions {{{1
" # Debug {{{2
function! lh#buffer#dialog#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#buffer#dialog#debug(expr)
return eval(a:expr)
endfunction
"=============================================================================
" # Dialog functions {{{2
"------------------------------------------------------------------------
function! s:Mappings(abuffer)
" map <enter> to edit a file, also dbl-click
exe "nnoremap <silent> <buffer> <esc> :silent call ".a:abuffer.action."(-1, ".a:abuffer.id.")<cr>"
exe "nnoremap <silent> <buffer> q :call lh#buffer#dialog#select(-1, ".a:abuffer.id.")<cr>"
exe "nnoremap <silent> <buffer> <cr> :call lh#buffer#dialog#select(line('.'), ".a:abuffer.id.")<cr>"
" nnoremap <silent> <buffer> <2-LeftMouse> :silent call <sid>GrepEditFileLine(line("."))<cr>
" nnoremap <silent> <buffer> Q :call <sid>Reformat()<cr>
" nnoremap <silent> <buffer> <Left> :set tabstop-=1<cr>
" nnoremap <silent> <buffer> <Right> :set tabstop+=1<cr>
if a:abuffer.support_tagging
nnoremap <silent> <buffer> t :silent call <sid>ToggleTag(line("."))<cr>
nnoremap <silent> <buffer> <space> :silent call <sid>ToggleTag(line("."))<cr>
endif
nnoremap <silent> <buffer> <tab> :silent call <sid>NextChoice('')<cr>
nnoremap <silent> <buffer> <S-tab> :silent call <sid>NextChoice('b')<cr>
exe "nnoremap <silent> <buffer> h :silent call <sid>ToggleHelp(".a:abuffer.id.")<cr>"
endfunction
"----------------------------------------
" Tag / untag the current choice {{{
function! s:ToggleTag(lineNum)
if a:lineNum > s:Help_NbL()
" If tagged
if (getline(a:lineNum)[0] == '*')
let b:NbTags = b:NbTags - 1
silent exe a:lineNum.'s/^\* / /e'
else
let b:NbTags = b:NbTags + 1
silent exe a:lineNum.'s/^ /* /e'
endif
" Move after the tag ; there is something with the two previous :s. They
" don't leave the cursor at the same position.
silent! normal! 3|
call s:NextChoice('') " move to the next choice
endif
endfunction
" }}}
function! s:Help_NbL()
" return 1 + nb lines of BuildHelp
return 2 + len(b:dialog['help_'.b:dialog.help_type])
endfunction
"----------------------------------------
" Go to the Next (/previous) possible choice. {{{
function! s:NextChoice(direction)
" echomsg "next!"
call search('^[ *]\s*\zs\S\+', a:direction)
endfunction
" }}}
"------------------------------------------------------------------------
function! s:RedisplayHelp(dialog)
silent! 2,$g/^@/d_
normal! gg
for help in a:dialog['help_'.a:dialog.help_type]
silent put=help
endfor
endfunction
function! lh#buffer#dialog#update(dialog)
set noro
exe (s:Help_NbL()+1).',$d_'
for choice in a:dialog.choices
silent $put=' '.choice
endfor
set ro
endfunction
function! s:Display(dialog, atitle)
set noro
0 put = a:atitle
call s:RedisplayHelp(a:dialog)
for choice in a:dialog.choices
silent $put=' '.choice
endfor
set ro
exe s:Help_NbL()+1
endfunction
function! s:ToggleHelp(bufferId)
call lh#buffer#find(a:bufferId)
call b:dialog.toggle_help()
endfunction
function! lh#buffer#dialog#toggle_help() dict
let self.help_type
\ = (self.help_type == 'short')
\ ? 'long'
\ : 'short'
call s:RedisplayHelp(self)
endfunction
function! lh#buffer#dialog#new(bname, title, where, support_tagging, action, choices)
" The ID will be the buffer id
let res = {}
let where_it_started = getpos('.')
let where_it_started[0] = bufnr('%')
let res.where_it_started = where_it_started
try
call lh#buffer#scratch(a:bname, a:where)
catch /.*/
echoerr v:exception
return res
endtry
let res.id = bufnr('%')
let b:NbTags = 0
let b:dialog = res
let s:LHdialog[res.id] = res
let res.help_long = []
let res.help_short = []
let res.help_type = 'short'
let res.support_tagging = a:support_tagging
let res.action = a:action
let res.choices = a:choices
" Long help
call lh#buffer#dialog#add_help(res, '@| <cr>, <double-click> : select this', 'long')
call lh#buffer#dialog#add_help(res, '@| <esc>, q : Abort', 'long')
if a:support_tagging
call lh#buffer#dialog#add_help(res, '@| <t>, <space> : Tag/Untag the current item', 'long')
endif
call lh#buffer#dialog#add_help(res, '@| <up>/<down>, <tab>, +/- : Move between entries', 'long')
call lh#buffer#dialog#add_help(res, '@|', 'long')
" call lh#buffer#dialog#add_help(res, '@| h : Toggle help', 'long')
call lh#buffer#dialog#add_help(res, '@+'.repeat('-', winwidth(bufwinnr(res.id))-3), 'long')
" Short Help
" call lh#buffer#dialog#add_help(res, '@| h : Toggle help', 'short')
call lh#buffer#dialog#add_help(res, '@+'.repeat('-', winwidth(bufwinnr(res.id))-3), 'short')
let res.toggle_help = function("lh#buffer#dialog#toggle_help")
let title = '@ ' . a:title
let helpstr = '| Toggle (h)elp'
let title = title
\ . repeat(' ', winwidth(bufwinnr(res.id))-strlen(title)-strlen(helpstr)-1)
\ . helpstr
call s:Display(res, title)
call s:Mappings(res)
return res
endfunction
function! lh#buffer#dialog#add_help(abuffer, text, help_type)
call add(a:abuffer['help_'.a:help_type],a:text)
endfunction
"=============================================================================
function! lh#buffer#dialog#quit()
let bufferId = b:dialog.where_it_started[0]
echohl WarningMsg
echo "Abort"
echohl None
quit
call lh#buffer#find(bufferId)
endfunction
" Function: lh#buffer#dialog#select(line, bufferId [,overriden-action])
function! lh#buffer#dialog#select(line, bufferId, ...)
if a:line == -1
call lh#buffer#dialog#quit()
return
" elseif a:line <= s:Help_NbL() + 1
elseif a:line <= s:Help_NbL()
echoerr "Unselectable item"
return
else
let dialog = s:LHdialog[a:bufferId]
let results = { 'dialog' : dialog, 'selection' : [] }
if b:NbTags == 0
" -1 because first index is 0
" let results = [ dialog.choices[a:line - s:Help_NbL() - 1] ]
let results.selection = [ a:line - s:Help_NbL() - 1 ]
else
silent g/^* /call add(results.selection, line('.')-s:Help_NbL()-1)
endif
endif
if a:0 > 0 " action overriden
exe 'call '.dialog.action.'(results, a:000)'
else
exe 'call '.dialog.action.'(results)'
endif
endfunction
function! lh#buffer#dialog#Select(line, bufferId, ...)
echomsg "lh#buffer#dialog#Select() is deprecated, use lh#buffer#dialog#select() instead"
if a:0 > 0 " action overriden
exe 'call lh#buffer#dialog#select(a:line, a:bufferId, a:1)'
else
exe 'call lh#buffer#dialog#select(a:line, a:bufferId)'
endif
endfunction
function! Action(results)
let dialog = a:results.dialog
let choices = dialog.choices
for r in a:results.selection
echomsg '-> '.choices[r]
endfor
endfunction
"=============================================================================
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,224 @@
"=============================================================================
" $Id: command.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/command.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 08th Jan 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (08th Jan 2007)
"------------------------------------------------------------------------
" Description:
" Helpers to define commands that:
" - support subcommands
" - support autocompletion
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.0.0:
" Code move from other plugins
" TODO: «missing features»
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
" ## Debug {{{1
function! lh#command#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#command#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" ## Functions {{{1
" Tool functions {{{2
" Function: lh#command#Fargs2String(aList) {{{3
" @param[in,out] aList list of params from <f-args>
" @see tests/lh/test-Fargs2String.vim
function! lh#command#Fargs2String(aList)
if empty(a:aList) | return '' | endif
let quote_char = a:aList[0][0]
let res = a:aList[0]
call remove(a:aList, 0)
if quote_char !~ '["'."']"
return res
endif
" else
let end_string = '[^\\]\%(\\\\\)*'.quote_char.'$'
while !empty(a:aList) && res !~ end_string
let res .= ' ' . a:aList[0]
call remove(a:aList, 0)
endwhile
return res
endfunction
"------------------------------------------------------------------------
" ## Experimental Functions {{{1
" Internal functions {{{2
" Function: s:SaveData({Data}) {{{3
" @param Data Command definition
" Saves {Data} as s:Data{s:data_id++}. The definition will be used by
" automatically generated commands.
" @return s:data_id
let s:data_id = 0
function! s:SaveData(Data)
if has_key(a:Data, "command_id")
" Avoid data duplication
return a:Data.command_id
else
let s:Data{s:data_id} = a:Data
let id = s:data_id
let s:data_id += 1
let a:Data.command_id = id
return id
endif
endfunction
" BTWComplete(ArgLead, CmdLine, CursorPos): Auto-complete {{{3
function! lh#command#complete(ArgLead, CmdLine, CursorPos)
let tmp = substitute(a:CmdLine, '\s*\S*', 'Z', 'g')
let pos = strlen(tmp)
if 0
call confirm( "AL = ". a:ArgLead."\nCL = ". a:CmdLine."\nCP = ".a:CursorPos
\ . "\ntmp = ".tmp."\npos = ".pos
\, '&Ok', 1)
endif
if 2 == pos
" First argument: a command
return s:commands
elseif 3 == pos
" Second argument: first arg of the command
if -1 != match(a:CmdLine, '^BTW\s\+echo')
return s:functions . "\n" . s:variables
elseif -1 != match(a:CmdLine, '^BTW\s\+\%(help\|?\)')
elseif -1 != match(a:CmdLine, '^BTW\s\+\%(set\|add\)\%(local\)\=')
" Adds a filter
" let files = globpath(&rtp, 'compiler/BT-*')
" let files = files . globpath(&rtp, 'compiler/BT_*')
" let files = files . globpath(&rtp, 'compiler/BT/*')
let files = s:FindFilter('*')
let files = substitute(files,
\ '\(^\|\n\).\{-}compiler[\\/]BTW[-_\\/]\(.\{-}\)\.vim\>\ze\%(\n\|$\)',
\ '\1\2', 'g')
return files
elseif -1 != match(a:CmdLine, '^BTW\s\+remove\%(local\)\=')
" Removes a filter
return substitute(s:FiltersList(), ',', '\n', 'g')
endif
endif
" finally: unknown
echoerr 'BTW: unespected parameter ``'. a:ArgLead ."''"
return ''
endfunction
function! s:BTW(command, ...)
" todo: check a:0 > 1
if 'set' == a:command | let g:BTW_build_tool = a:1
if exists('b:BTW_build_tool')
let b:BTW_build_tool = a:1
endif
elseif 'setlocal' == a:command | let b:BTW_build_tool = a:1
elseif 'add' == a:command | call s:AddFilter('g', a:1)
elseif 'addlocal' == a:command | call s:AddFilter('b', a:1)
" if exists('b:BTW_filters_list') " ?????
" call s:AddFilter('b', a:1)
" endif
elseif 'remove' == a:command | call s:RemoveFilter('g', a:1)
elseif 'removelocal' == a:command | call s:RemoveFilter('b', a:1)
elseif 'rebuild' == a:command " wait for s:ReconstructToolsChain()
elseif 'echo' == a:command | exe "echo s:".a:1
" echo s:{a:f1} ## don't support «echo s:f('foo')»
elseif 'reloadPlugin' == a:command
let g:force_reload_BuildToolsWrapper = 1
let g:BTW_BTW_in_use = 1
exe 'so '.s:sfile
unlet g:force_reload_BuildToolsWrapper
unlet g:BTW_BTW_in_use
return
elseif a:command =~ '\%(help\|?\)'
call s:Usage()
return
endif
call s:ReconstructToolsChain()
endfunction
" ##############################################################
" Public functions {{{2
function! s:FindSubcommand(definition, subcommand)
for arg in a:definition.arguments
if arg.name == a:subcommand
return arg
endif
endfor
throw "NF"
endfunction
function! s:execute_function(definition, params)
if len(a:params) < 1
throw "(lh#command) Not enough arguments"
endif
let l:Fn = a:definition.action
echo "calling ".string(l:Fn)
echo "with ".string(a:params)
" call remove(a:params, 0)
call l:Fn(a:params)
endfunction
function! s:execute_sub_commands(definition, params)
try
if len(a:params) < 1
throw "(lh#command) Not enough arguments"
endif
let subcommand = s:FindSubcommand(a:definition, a:params[0])
call remove(a:params, 0)
call s:int_execute(subcommand, a:params)
catch /NF.*/
throw "(lh#command) Unexpected subcommand `".a:params[0]."'."
endtry
endfunction
function! s:int_execute(definition, params)
echo "params=".string(a:params)
call s:execute_{a:definition.arg_type}(a:definition, a:params)
endfunction
function! s:execute(definition, ...)
try
let params = copy(a:000)
call s:int_execute(a:definition, params)
catch /(lh#command).*/
echoerr v:exception . " in `".a:definition.name.' '.join(a:000, ' ')."'"
endtry
endfunction
function! lh#command#new(definition)
let cmd_name = a:definition.name
" Save the definition as an internal script variable
let id = s:SaveData(a:definition)
exe "command! -nargs=* ".cmd_name." :call s:execute(s:Data".id.", <f-args>)"
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,93 @@
"=============================================================================
" $Id: common.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/common.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 07th Oct 2006
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (08th Feb 2008)
"------------------------------------------------------------------------
" Description:
" Some common functions for:
" - displaying error messages
" - checking dependencies
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.1.1
" - New function: lh#common#echomsg_multilines()
" - lh#common#warning_msg() supports multilines messages
"
" v2.0.0:
" - Code moved from other plugins
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" Functions {{{1
" Function: lh#common#echomsg_multilines {{{2
function! lh#common#echomsg_multilines(text)
let lines = split(a:text, "[\n\r]")
for line in lines
echomsg line
endfor
endfunction
function! lh#common#echomsgMultilines(text)
return lh#common#echomsg_multilines(a:text)
endfunction
" Function: lh#common#error_msg {{{2
function! lh#common#error_msg(text)
if has('gui_running')
call confirm(a:text, '&Ok', '1', 'Error')
else
" echohl ErrorMsg
echoerr a:text
" echohl None
endif
endfunction
function! lh#common#ErrorMsg(text)
return lh#common#error_msg(a:text)
endfunction
" Function: lh#common#warning_msg {{{2
function! lh#common#warning_msg(text)
echohl WarningMsg
" echomsg a:text
call lh#common#echomsg_multilines(a:text)
echohl None
endfunction
function! lh#common#WarningMsg(text)
return lh#common#warning_msg(a:text)
endfunction
" Dependencies {{{2
function! lh#common#check_deps(Symbol, File, path, plugin) " {{{3
if !exists(a:Symbol)
exe "runtime ".a:path.a:File
if !exists(a:Symbol)
call lh#common#error_msg( a:plugin.': Requires <'.a:File.'>')
return 0
endif
endif
return 1
endfunction
function! lh#common#CheckDeps(Symbol, File, path, plugin) " {{{3
echomsg "lh#common#CheckDeps() is deprecated, use lh#common#check_deps() instead."
return lh#common#check_deps(a:Symbol, a:File, a:path, a:plugin)
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,49 @@
"=============================================================================
" $Id: encoding.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/encoding.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 21st Feb 2008
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Defines functions that help managing various encodings
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.0.7:
" (*) lh#encoding#Iconv() copied from map-tools
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" Function: lh#encoding#iconv(expr, from, to) " {{{3
" Unlike |iconv()|, this wrapper returns {expr} when we know no convertion can
" be acheived.
function! lh#encoding#iconv(expr, from, to)
" call Dfunc("s:ICONV(".a:expr.','.a:from.','.a:to.')')
if has('multi_byte') &&
\ ( has('iconv') || has('iconv/dyn') ||
\ ((a:from=~'latin1\|utf-8') && (a:to=~'latin1\|utf-8')))
" call confirm('encoding: '.&enc."\nto:".a:to, "&Ok", 1)
" call Dret("s:ICONV convert=".iconv(a:expr, a:from, a:to))
return iconv(a:expr,a:from,a:to)
else
" Cannot convert
" call Dret("s:ICONV no convert=".a:expr)
return a:expr
endif
endfunction
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,75 @@
"=============================================================================
" $Id: env.vim 244 2010-09-19 22:38:24Z luc.hermitte $
" File: autoload/lh/env.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 19th Jul 2010
" Last Update: $Date: 2010-09-19 18:38:24 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Functions related to environment (variables)
"
"------------------------------------------------------------------------
" Installation:
" Drop this file into {rtp}/autoload/lh
" Requires Vim7+
" History:
" v2.2.1 First Version
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Misc Functions {{{1
" # Version {{{2
let s:k_version = 221
function! lh#env#version()
return s:k_version
endfunction
" # Debug {{{2
let s:verbose = 0
function! lh#env#verbose(...)
if a:0 > 0 | let s:verbose = a:1 | endif
return s:verbose
endfunction
function! s:Verbose(expr)
if s:verbose
echomsg a:expr
endif
endfunction
function! lh#env#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" ## Exported functions {{{1
function! lh#env#expand_all(string)
let res = ''
let tail = a:string
while !empty(tail)
let [ all, head, var, tail; dummy ] = matchlist(tail, '\(.\{-}\)\%(${\(.\{-}\)}\)\=\(.*\)')
if empty(var)
let res .= tail
break
else
let res .= head
let val = eval('$'.var)
let res .= val
endif
endwhile
return res
endfunction
"------------------------------------------------------------------------
" ## Internal functions {{{1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,68 @@
"=============================================================================
" $Id: event.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/event.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 15th Feb 2008
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Function to help manage vim |autocommand-events|
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.0.6:
" Creation
" TODO:
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#event#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#event#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" # Event Registration {{{2
function! s:RegisteredOnce(cmd, group)
" We can't delete the current augroup autocommand => increment a counter
if !exists('s:'.a:group) || s:{a:group} == 0
let s:{a:group} = 1
exe a:cmd
endif
endfunction
function! lh#event#register_for_one_execution_at(event, cmd, group)
let group = a:group.'_once'
let s:{group} = 0
exe 'augroup '.group
au!
exe 'au '.a:event.' '.expand('%:p').' call s:RegisteredOnce('.string(a:cmd).','.string(group).')'
augroup END
endfunction
function! lh#event#RegisterForOneExecutionAt(event, cmd, group)
return lh#event#register_for_one_execution_at(a:event, a:cmd, a:group)
endfunction
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,214 @@
"=============================================================================
" $Id: function.vim 161 2010-05-07 01:04:44Z luc.hermitte $
" File: autoload/lh/function.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.0
" Created: 03rd Nov 2008
" Last Update: $Date: 2010-05-06 21:04:44 -0400 (Thu, 06 May 2010) $
"------------------------------------------------------------------------
" Description:
" Implements:
" - lh#function#bind()
" - lh#function#execute()
" - lh#function#prepare()
" - a binded function type
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.2.0: first implementation
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#function#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#function#debug(expr)
return eval(a:expr)
endfunction
" # Function: s:Join(arguments...) {{{2
function! s:Join(args)
let res = ''
if len(a:args) > 0
let res = string(a:args[0])
let i = 1
while i != len(a:args)
let res.=','.string(a:args[i])
let i += 1
endwhile
endif
return res
endfunction
" # Function: s:DoBindList(arguments...) {{{2
function! s:DoBindList(formal, real)
let args = []
for arg in a:formal
if type(arg)==type('string') && arg =~ '^v:\d\+_$'
let new = a:real[matchstr(arg, 'v:\zs\d\+\ze_')-1]
elseif type(arg)==type('string')
let new = eval(s:DoBindEvaluatedString(arg, a:real))
else
let new = arg
endif
call add(args, new)
unlet new
unlet arg
endfor
return args
endfunction
" # Function: s:DoBindString(arguments...) {{{2
function! s:DoBindString(expr, real)
let expr = substitute(a:expr, '\<v:\(\d\+\)_\>', a:real.'[\1-1]', 'g')
return expr
endfunction
function! s:ToString(expr)
return type(a:expr) != type('')
\ ? string(a:expr)
\ : (a:expr)
endfunction
function! s:DoBindEvaluatedString(expr, real)
let expr = a:expr
let p = 0
while 1
let p = match(expr, '\<v:\d\+_\>', p)
if -1 == p | break | endif
let e = matchend(expr, '\<v:\d\+_\>', p)
let n = eval(expr[p+2 : e-2])
" let new = (type(a:real[n-1])==type('') && a:real[n-1]=~ '\<v:\d\+_\>')
" \ ? a:real[n-1]
" \ : string(a:real[n-1])
let new = s:ToString(a:real[n-1])
" let new = string(a:real[n-1]) " -> bind_counpound vars
let expr = ((p>0) ? (expr[0:p-1]) : '') . new . expr[e : -1]
" echo expr
let p += len(new)
" silent! unlet new
endwhile
return expr
endfunction
" # Function: s:Execute(arguments...) {{{2
function! s:Execute(args) dict
if type(self.function) == type(function('exists'))
let args = s:DoBindList(self.args, a:args)
" echomsg '##'.string(self.function).'('.join(args, ',').')'
let res = eval(string(self.function).'('.s:Join(args).')')
elseif type(self.function) == type('string')
let expr = s:DoBindString(self.function, 'a:args')
let res = eval(expr)
elseif type(self.function) == type({})
return self.function.execute(a:args)
else
throw "lh#functor#execute: unpected function type: ".type(self.function)
endif
return res
endfunction
" # Function: lh#function#prepare(function, arguments_list) {{{2
function! lh#function#prepare(Fn, arguments_list)
if type(a:Fn) == type(function('exists'))
let expr = string(a:Fn).'('.s:Join(a:arguments_list).')'
return expr
elseif type(a:Fn) == type('string')
if a:Fn =~ '^[a-zA-Z0-9_#]\+$'
let expr = string(function(a:Fn)).'('.s:Join(a:arguments_list).')'
return expr
else
let expr = s:DoBindString(a:Fn, 'a:000')
return expr
endif
else
throw "lh#function#prepare(): {Fn} argument of type ".type(a:Fn). " is unsupported"
endif
endfunction
" # Function: lh#function#execute(function, arguments...) {{{2
function! lh#function#execute(Fn, ...)
if type(a:Fn) == type({}) && has_key(a:Fn, 'execute')
return a:Fn.execute(a:000)
else
let expr = lh#function#prepare(a:Fn, a:000)
return eval(expr)
endif
endfunction
" # Function: lh#function#bind(function, arguments...) {{{2
function! lh#function#bind(Fn, ...)
let args = copy(a:000)
if type(a:Fn) == type('string') && a:Fn =~ '^[a-zA-Z0-9_#]\+$'
\ && exists('*'.a:Fn)
let Fn = function(a:Fn)
elseif type(a:Fn) == type({})
" echo string(a:Fn).'('.string(a:000).')'
" Rebinding another binded function
" TASSERT has_key(a:Fn, 'function')
" TASSERT has_key(a:Fn, 'execute')
" TASSERT has_key(a:Fn, 'args')
let Fn = a:Fn.function
let N = len(a:Fn.args)
if N != 0 " args to rebind
let i = 0
let t_args = [] " necessary to avoid type changes
while i != N
silent! unlet arg
let arg = a:Fn.args[i]
if arg =~ 'v:\d\+_$'
let arg2 = eval(s:DoBindString(arg, string(args)))
" echo arg."-(".string(args).")->".string(arg2)
unlet arg
let arg = arg2
unlet arg2
endif
call add(t_args, arg)
let i += 1
endwhile
unlet a:Fn.args
let a:Fn.args = t_args
else " expression to fix
" echo Fn
" echo s:DoBindString(Fn, string(args))
" echo eval(string(s:DoBindString(Fn, string(args))))
let Fn = (s:DoBindEvaluatedString(Fn, args))
endif
let args = a:Fn.args
else
let Fn = a:Fn
endif
let binded_fn = {
\ 'function': Fn,
\ 'args': args,
\ 'execute': function('s:Execute')
\}
return binded_fn
endfunction
" }}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:
" Vim: let g:UTfiles='tests/lh/function.vim'

View file

@ -0,0 +1,177 @@
"=============================================================================
" $Id: tsort.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/tsort.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 21st Apr 2008
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description: Library functions for Topological Sort
"
"------------------------------------------------------------------------
" Drop the file into {rtp}/autoload/lh/graph
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Debug {{{1
function! lh#graph#tsort#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#graph#tsort#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
"## Helper functions {{{1
"# s:Successors_fully_defined(node) {{{2
function! s:Successors_fully_defined(node) dict
if has_key(self.table, a:node)
return self.table[a:node]
else
return []
endif
endfunction
"# s:Successors_lazy(node) {{{2
function! s:Successors_lazy(node) dict
if !has_key(self.table, a:node)
let nodes = self.fetch(a:node)
let self.table[a:node] = nodes
" if len(nodes) > 0
" let self.nb += 1
" endif
return nodes
else
return self.table[a:node]
endif
endfunction
"# s:PrepareDAG(dag) {{{2
function! s:PrepareDAG(dag)
if type(a:dag) == type(function('has_key'))
let dag = {
\ 'successors': function('s:Successors_lazy'),
\ 'fetch' : a:dag,
\ 'table' : {}
\}
else
let dag = {
\ 'successors': function('s:Successors_fully_defined'),
\ 'table' : deepcopy(a:dag)
\}
endif
return dag
endfunction
"## Depth-first search (recursive) {{{1
" Do not detect cyclic graphs
"# lh#graph#tsort#depth(dag, start_nodes) {{{2
function! lh#graph#tsort#depth(dag, start_nodes)
let dag = s:PrepareDAG(a:dag)
let results = []
let visited_nodes = { 'Visited':function('s:Visited')}
call s:RecursiveDTSort(dag, a:start_nodes, results, visited_nodes)
call reverse(results)
return results
endfunction
"# The real, recursive, T-Sort {{{2
"see boost.graph for a non recursive implementation
function! s:RecursiveDTSort(dag, start_nodes, results, visited_nodes)
for node in a:start_nodes
let visited = a:visited_nodes.Visited(node)
if visited == 1 | continue " done
elseif visited == 2 | throw "Tsort: cyclic graph detected: ".node
endif
let a:visited_nodes[node] = 2 " visiting
let succs = a:dag.successors(node)
try
call s:RecursiveDTSort(a:dag, succs, a:results, a:visited_nodes)
catch /Tsort:/
throw v:exception.'>'.node
endtry
let a:visited_nodes[node] = 1 " visited
call add(a:results, node)
endfor
endfunction
function! s:Visited(node) dict
return has_key(self, a:node) ? self[a:node] : 0
endfunction
"## Breadth-first search (non recursive) {{{1
"# lh#graph#tsort#breadth(dag, start_nodes) {{{2
" warning: This implementation does not work with lazy dag, but only with fully
" defined ones
function! lh#graph#tsort#breadth(dag, start_nodes)
let result = []
let dag = s:PrepareDAG(a:dag)
let queue = deepcopy(a:start_nodes)
while len(queue) > 0
let node = remove(queue, 0)
" echomsg "result <- ".node
call add(result, node)
let successors = dag.successors(node)
while len(successors) > 0
let m = s:RemoveEdgeFrom(dag, node)
" echomsg "graph loose ".node."->".m
if !s:HasIncomingEgde(dag, m)
" echomsg "queue <- ".m
call add(queue, m)
endif
endwhile
endwhile
if !s:Empty(dag)
throw "Tsort: cyclic graph detected: "
endif
return result
endfunction
function! s:HasIncomingEgde(dag, node)
for node in keys(a:dag.table)
if type(a:dag.table[node]) != type([])
continue
endif
if index(a:dag.table[node], a:node) != -1
return 1
endif
endfor
return 0
endfunction
function! s:RemoveEdgeFrom(dag, node)
let successors = a:dag.successors(a:node)
if len(successors) > 0
let successor = remove(successors, 0)
if len(successors) == 0
" echomsg "finished with ->".a:node
call remove(a:dag.table, a:node)
endif
return successor
endif
throw "No more edges from ".a:node
endfunction
function! s:Empty(dag)
" echomsg "len="len(a:dag.table)
return len(a:dag.table) == 0
endfunction
" }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker

View file

@ -0,0 +1,338 @@
"=============================================================================
" $Id: list.vim 236 2010-06-01 00:43:34Z luc.hermitte $
" File: autoload/lh/list.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 17th Apr 2007
" Last Update: $Date: 2010-05-31 20:43:34 -0400 (Mon, 31 May 2010) $ (17th Apr 2007)
"------------------------------------------------------------------------
" Description:
" Defines functions related to |Lists|
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.2.1:
" (*) use :unlet in :for loop to support heterogeneous lists
" (*) binary search algorithms (upper_bound, lower_bound, equal_range)
" v2.2.0:
" (*) new functions: lh#list#accumulate, lh#list#transform,
" lh#list#transform_if, lh#list#find_if, lh#list#copy_if,
" lh#list#subset, lh#list#intersect
" (*) the functions are compatible with lh#function functors
" v2.1.1:
" (*) unique_sort
" v2.0.7:
" (*) Bug fix: lh#list#Match()
" v2.0.6:
" (*) lh#list#Find_if() supports search predicate, and start index
" (*) lh#list#Match() supports start index
" v2.0.0:
" TODO: «missing features»
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#list#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#list#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" # Public {{{2
" Function: lh#list#Transform(input, output, action) {{{3
" deprecated version
function! lh#list#Transform(input, output, action)
let new = map(copy(a:input), a:action)
let res = extend(a:output,new)
return res
for element in a:input
let action = substitute(a:action, 'v:val','element', 'g')
let res = eval(action)
call add(a:output, res)
unlet element " for heterogeneous lists
endfor
return a:output
endfunction
function! lh#list#transform(input, output, action)
for element in a:input
let res = lh#function#execute(a:action, element)
call add(a:output, res)
unlet element " for heterogeneous lists
endfor
return a:output
endfunction
function! lh#list#transform_if(input, output, action, predicate)
for element in a:input
if lh#function#execute(a:predicate, element)
let res = lh#function#execute(a:action, element)
call add(a:output, res)
endif
unlet element " for heterogeneous lists
endfor
return a:output
endfunction
function! lh#list#copy_if(input, output, predicate)
for element in a:input
if lh#function#execute(a:predicate, element)
call add(a:output, element)
endif
unlet element " for heterogeneous lists
endfor
return a:output
endfunction
function! lh#list#accumulate(input, transformation, accumulator)
let transformed = lh#list#transform(a:input, [], a:transformation)
let res = lh#function#execute(a:accumulator, transformed)
return res
endfunction
" Function: lh#list#match(list, to_be_matched [, idx]) {{{3
function! lh#list#match(list, to_be_matched, ...)
let idx = (a:0>0) ? a:1 : 0
while idx < len(a:list)
if match(a:list[idx], a:to_be_matched) != -1
return idx
endif
let idx += 1
endwhile
return -1
endfunction
function! lh#list#Match(list, to_be_matched, ...)
let idx = (a:0>0) ? a:1 : 0
return lh#list#match(a:list, a:to_be_matched, idx)
endfunction
" Function: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
function! lh#list#Find_if(list, predicate, ...)
" Parameters
let idx = 0
let args = []
if a:0 == 2
let idx = a:2
let args = a:1
elseif a:0 == 1
if type(a:1) == type([])
let args = a:1
elseif type(a:1) == type(42)
let idx = a:1
else
throw "lh#list#Find_if: unexpected argument type"
endif
elseif a:0 != 0
throw "lh#list#Find_if: unexpected number of arguments: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos])"
endif
" The search loop
while idx != len(a:list)
let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
let predicate = substitute(predicate, 'v:\(\d\+\)_', 'args[\1-1]', 'g')
let res = eval(predicate)
if res | return idx | endif
let idx += 1
endwhile
return -1
endfunction
" Function: lh#list#find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
function! lh#list#find_if(list, predicate, ...)
" Parameters
let idx = 0
let args = []
if a:0 == 1
let idx = a:1
elseif a:0 != 0
throw "lh#list#find_if: unexpected number of arguments: lh#list#find_if(list, predicate [, start-pos])"
endif
" The search loop
while idx != len(a:list)
" let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
let res = lh#function#execute(a:predicate, a:list[idx])
if res | return idx | endif
let idx += 1
endwhile
return -1
endfunction
" Function: lh#list#lower_bound(sorted_list, value [, first[, last]]) {{{3
function! lh#list#lower_bound(list, val, ...)
let first = 0
let last = len(a:list)
if a:0 >= 1 | let first = a:1
elseif a:0 >= 2 | let last = a:2
elseif a:0 > 2
throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value [, first[, last]])"
endif
let len = last - first
while len > 0
let half = len / 2
let middle = first + half
if a:list[middle] < a:val
let first = middle + 1
let len -= half + 1
else
let len = half
endif
endwhile
return first
endfunction
" Function: lh#list#upper_bound(sorted_list, value [, first[, last]]) {{{3
function! lh#list#upper_bound(list, val, ...)
let first = 0
let last = len(a:list)
if a:0 >= 1 | let first = a:1
elseif a:0 >= 2 | let last = a:2
elseif a:0 > 2
throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value [, first[, last]])"
endif
let len = last - first
while len > 0
let half = len / 2
let middle = first + half
if a:val < a:list[middle]
let len = half
else
let first = middle + 1
let len -= half + 1
endif
endwhile
return first
endfunction
" Function: lh#list#equal_range(sorted_list, value [, first[, last]]) {{{3
" @return [f, l], where
" f : First position where {value} could be inserted
" l : Last position where {value} could be inserted
function! lh#list#equal_range(list, val, ...)
let first = 0
let last = len(a:list)
" Parameters
if a:0 >= 1 | let first = a:1
elseif a:0 >= 2 | let last = a:2
elseif a:0 > 2
throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value [, first[, last]])"
endif
" The search loop ( == STLPort's equal_range)
let len = last - first
while len > 0
let half = len / 2
let middle = first + half
if a:list[middle] < a:val
let first = middle + 1
let len -= half + 1
elseif a:val < a:list[middle]
let len = half
else
let left = lh#list#lower_bound(a:list, a:val, first, middle)
let right = lh#list#upper_bound(a:list, a:val, middle+1, first+len)
return [left, right]
endif
" let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
" let res = lh#function#execute(a:predicate, a:list[idx])
endwhile
return [first, first]
endfunction
" Function: lh#list#unique_sort(list [, func]) {{{3
" See also http://vim.wikia.com/wiki/Unique_sorting
"
" Works like sort(), optionally taking in a comparator (just like the
" original), except that duplicate entries will be removed.
" todo: support another argument that act as an equality predicate
function! lh#list#unique_sort(list, ...)
let dictionary = {}
for i in a:list
let dictionary[string(i)] = i
endfor
let result = []
" echo join(values(dictionary),"\n")
if ( exists( 'a:1' ) )
let result = sort( values( dictionary ), a:1 )
else
let result = sort( values( dictionary ) )
endif
return result
endfunction
function! lh#list#unique_sort2(list, ...)
let list = copy(a:list)
if ( exists( 'a:1' ) )
call sort(list, a:1 )
else
call sort(list)
endif
if len(list) <= 1 | return list | endif
let result = [ list[0] ]
let last = list[0]
let i = 1
while i < len(list)
if last != list[i]
let last = list[i]
call add(result, last)
endif
let i += 1
endwhile
return result
endfunction
" Function: lh#list#subset(list, indices) {{{3
function! lh#list#subset(list, indices)
let result=[]
for e in a:indices
call add(result, a:list[e])
endfor
return result
endfunction
" Function: lh#list#intersect(list1, list2) {{{3
function! lh#list#intersect(list1, list2)
let result = copy(a:list1)
call filter(result, 'index(a:list2, v:val) >= 0')
return result
for e in a:list1
if index(a:list2, e) > 0
call result(result, e)
endif
endfor
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,384 @@
"=============================================================================
" $Id: menu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/menu.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 13th Oct 2006
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (28th Aug 2007)
"------------------------------------------------------------------------
" Description:
" Defines the global function lh#menu#def_menu
" Aimed at (ft)plugin writers.
"
"------------------------------------------------------------------------
" Installation:
" Drop this file into {rtp}/autoload/lh/
" Requires Vim 7+
" History:
" v2.0.0: Moving to vim7
" v2.0.1: :ToggleXxx echoes the new value
" v2.2.0: Support environment variables
" Only one :Toggle command is defined.
" TODO:
" Should the argument to :Toggle be simplified to use the variable
" name instead ?
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Internal Variables {{{1
let s:k_Toggle_cmd = 'Toggle'
if !exists('s:toggle_commands')
let s:toggle_commands = {}
endif
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#menu#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#menu#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" # Common stuff {{{2
" Function: lh#menu#text({text}) {{{3
" @return a text to be used in menus where "\" and spaces have been escaped.
function! lh#menu#text(text)
return escape(a:text, '\ ')
endfunction
" # Toggling menu item {{{2
" Function: s:Fetch({Data},{key}) {{{3
" @param[in] Data Menu-item definition
" @param[in] key Table table from which the result will be fetched
" @return the current value, or text, whose index is Data.idx_crt_value.
function! s:Fetch(Data, key)
let len = len(a:Data[a:key])
if a:Data.idx_crt_value >= len | let a:Data.idx_crt_value = 0 | endif
let value = a:Data[a:key][a:Data.idx_crt_value]
return value
endfunction
" Function: s:Search({Data},{value}) {{{3
" Searches for the index of {value} in {Data.values} list. Return 0 if not
" found.
function! s:Search(Data, value)
let idx = 0
while idx != len(a:Data.values)
if a:value == a:Data.values[idx]
" echo a:Data.variable . "[".idx."] == " . a:value
return idx
endif
let idx = idx + 1
endwhile
" echo a:Data.variable . "[".-1."] == " . a:value
return 0 " default is first element
endfunction
" Function: s:Set({Data}) {{{3
" @param[in,out] Data Menu item definition
"
" Sets the global variable associated to the menu item according to the item's
" current value.
function! s:Set(Data)
let value = a:Data.values[a:Data.idx_crt_value]
let variable = a:Data.variable
if variable[0] == '$' " environment variabmes
exe "let ".variable." = ".string(value)
else
let g:{variable} = value
endif
if has_key(a:Data, "actions")
let l:Action = a:Data.actions[a:Data.idx_crt_value]
if type(l:Action) == type(function('tr'))
call l:Action()
else
exe l:Action
endif
endif
return value
endfunction
" Function: s:MenuKey({Data}) {{{3
" @return the table name from which the current value name (to dsplay in the
" menu) must be fetched.
" Priority is given to the optional "texts" table over the madatory "values" table.
function! s:MenuKey(Data)
if has_key(a:Data, "texts")
let menu_id = "texts"
else
let menu_id = "values"
endif
return menu_id
endfunction
" Function: s:NextValue({Data}) {{{3
" Change the value of the variable to the next in the list of value.
" The menu, and the variable are updated in consequence.
function! s:NextValue(Data)
" Where the texts for values must be fetched
let labels_key = s:MenuKey(a:Data)
" Fetch the old current value
let old = s:Fetch(a:Data, labels_key)
" Remove the entry from the menu
call s:ClearMenu(a:Data.menu, old)
" Cycle/increment the current value
let a:Data.idx_crt_value += 1
" Fetch it
let new = s:Fetch(a:Data,labels_key)
" Add the updated entry in the menu
call s:UpdateMenu(a:Data.menu, new, a:Data.command)
" Update the binded global variable
let value = s:Set(a:Data)
echo a:Data.variable.'='.value
endfunction
" Function: s:ClearMenu({Menu}, {text}) {{{3
" Removes a menu item
"
" @param[in] Menu.priority Priority of the new menu-item
" @param[in] Menu.name Name of the new menu-item
" @param[in] text Text of the previous value of the variable binded
function! s:ClearMenu(Menu, text)
if has('gui_running')
let name = substitute(a:Menu.name, '&', '', 'g')
let cmd = 'unmenu '.lh#menu#text(name.'<tab>('.a:text.')')
silent! exe cmd
endif
endfunction
" Function: s:UpdateMenu({Menu}, {text}, {command}) {{{3
" Adds a new menu item, with the text associated to the current value in
" braces.
"
" @param[in] Menu.priority Priority of the new menu-item
" @param[in] Menu.name Name of the new menu-item
" @param[in] text Text of the current value of the variable binded to
" the menu-item
" @param[in] command Toggle command to execute when the menu-item is selected
function! s:UpdateMenu(Menu, text, command)
if has('gui_running')
let cmd = 'nnoremenu <silent> '.a:Menu.priority.' '.
\ lh#menu#text(a:Menu.name.'<tab>('.a:text.')').
\ ' :silent '.s:k_Toggle_cmd.' '.a:command."\<cr>"
silent! exe cmd
endif
endfunction
" Function: s:SaveData({Data}) {{{3
" @param Data Menu-item definition
" Saves {Data} as s:Data{s:data_id++}. The definition will be used by
" automatically generated commands.
" @return s:data_id
let s:data_id = 0
function! s:SaveData(Data)
let s:Data{s:data_id} = a:Data
let id = s:data_id
let s:data_id += 1
return id
endfunction
" Function: lh#menu#def_toggle_item({Data}) {{{3
" @param Data.idx_crt_value
" @param Data.definitions == [ {value:, menutext: } ]
" @param Data.menu == { name:, position: }
"
" Sets a toggle-able menu-item defined by {Data}.
"
function! lh#menu#def_toggle_item(Data)
" Save the menu data as an internal script variable
let id = s:SaveData(a:Data)
" If the index of the current value hasn't been set, fetch it from the
" associated variable
if !has_key(a:Data, "idx_crt_value")
" Fetch the value of the associated variable
let value = lh#option#get(a:Data.variable, 0, 'g')
" echo a:Data.variable . " <- " . value
" Update the index of the current value
let a:Data.idx_crt_value = s:Search(a:Data, value)
endif
" Name of the auto-matically generated toggle command
let cmdName = substitute(a:Data.menu.name, '[^a-zA-Z_]', '', 'g')
" Lazy definition of the command
if 2 != exists(':'.s:k_Toggle_cmd)
exe 'command! -nargs=1 -complete=custom,lh#menu#_toggle_complete '
\ . s:k_Toggle_cmd . ' :call s:Toggle(<f-args>)'
endif
" silent exe 'command! -nargs=0 '.cmdName.' :call s:NextValue(s:Data'.id.')'
let s:toggle_commands[cmdName] = eval('s:Data'.id)
let a:Data["command"] = cmdName
" Add the menu entry according to the current value
call s:UpdateMenu(a:Data.menu, s:Fetch(a:Data, s:MenuKey(a:Data)), cmdName)
" Update the associated global variable
call s:Set(a:Data)
endfunction
"------------------------------------------------------------------------
function! s:Toggle(cmdName)
if !has_key(s:toggle_commands, a:cmdName)
throw "toggle-menu: unknown toggable variable ".a:cmdName
endif
let data = s:toggle_commands[a:cmdName]
call s:NextValue(data)
endfunction
function! lh#menu#_toggle_complete(ArgLead, CmdLine, CursorPos)
return join(keys(s:toggle_commands),"\n")
endfunction
"------------------------------------------------------------------------
" # IVN Menus {{{2
" Function: s:CTRL_O({cmd}) {{{3
" Build the command (sequence of ':ex commands') to be executed from
" INSERT-mode.
function! s:CTRL_O(cmd)
return substitute(a:cmd, '\(^\|<CR>\):', '\1\<C-O>:', 'g')
endfunction
" Function: lh#menu#is_in_visual_mode() {{{3
function! lh#menu#is_in_visual_mode()
return exists('s:is_in_visual_mode') && s:is_in_visual_mode
endfunction
" Function: lh#menu#_CMD_and_clear_v({cmd}) {{{3
" Internal function that executes the command and then clears the @v buffer
" todo: save and restore @v,
function! lh#menu#_CMD_and_clear_v(cmd)
try
let s:is_in_visual_mode = 1
exe a:cmd
finally
let @v=''
silent! unlet s:is_in_visual_mode
endtry
endfunction
" Function: s:Build_CMD({prefix},{cmd}) {{{3
" build the exact command to execute regarding the mode it is dedicated
function! s:Build_CMD(prefix, cmd)
if a:cmd[0] != ':' | return ' ' . a:cmd
endif
if a:prefix[0] == "i" | return ' ' . <SID>CTRL_O(a:cmd)
elseif a:prefix[0] == "n" | return ' ' . a:cmd
elseif a:prefix[0] == "v"
if match(a:cmd, ":VCall") == 0
return substitute(a:cmd, ':VCall', ' :call', ''). "\<cr>gV"
" gV exit select-mode if we where in it!
else
return
\ " \"vy\<C-C>:call lh#menu#_CMD_and_clear_v('" .
\ substitute(a:cmd, "<CR>$", '', '') ."')\<cr>"
endif
elseif a:prefix[0] == "c" | return " \<C-C>" . a:cmd
else | return ' ' . a:cmd
endif
endfunction
" Function: lh#menu#map_all({map_type}, [{map args}...) {{{3
" map the command to all the modes required
function! lh#menu#map_all(map_type,...)
let nore = (match(a:map_type, '[aincv]*noremap') != -1) ? "nore" : ""
let prefix = matchstr(substitute(a:map_type, nore, '', ''), '[aincv]*')
if a:1 == "<buffer>" | let i = 3 | let binding = a:1 . ' ' . a:2
else | let i = 2 | let binding = a:1
endif
let binding = '<silent> ' . binding
let cmd = a:{i}
let i += 1
while i <= a:0
let cmd .= ' ' . a:{i}
let i += 1
endwhile
let build_cmd = nore . 'map ' . binding
while strlen(prefix)
if prefix[0] == "a" | let prefix = "incv"
else
execute prefix[0] . build_cmd . <SID>Build_CMD(prefix[0],cmd)
let prefix = strpart(prefix, 1)
endif
endwhile
endfunction
" Function: lh#menu#make({prefix},{code},{text},{binding},...) {{{3
" Build the menu and map its associated binding to all the modes required
function! lh#menu#make(prefix, code, text, binding, ...)
let nore = (match(a:prefix, '[aincv]*nore') != -1) ? "nore" : ""
let prefix = matchstr(substitute(a:prefix, nore, '', ''), '[aincv]*')
let b = (a:1 == "<buffer>") ? 1 : 0
let i = b + 1
let cmd = a:{i}
let i += 1
while i <= a:0
let cmd .= ' ' . a:{i}
let i += 1
endwhile
let build_cmd = nore . "menu <silent> " . a:code . ' ' . lh#menu#text(a:text)
if strlen(a:binding) != 0
let build_cmd .= '<tab>' .
\ substitute(lh#menu#text(a:binding), '&', '\0\0', 'g')
if b != 0
call lh#menu#map_all(prefix.nore."map", ' <buffer> '.a:binding, cmd)
else
call lh#menu#map_all(prefix.nore."map", a:binding, cmd)
endif
endif
if has("gui_running")
while strlen(prefix)
execute <SID>BMenu(b).prefix[0].build_cmd.<SID>Build_CMD(prefix[0],cmd)
let prefix = strpart(prefix, 1)
endwhile
endif
endfunction
" Function: s:BMenu({b}) {{{3
" If <buffermenu.vim> is installed and the menu should be local, then the
" apropriate string is returned.
function! s:BMenu(b)
let res = (a:b && exists(':Bmenu')
\ && (1 == lh#option#get("want_buffermenu_or_global_disable", 1, "bg"))
\) ? 'B' : ''
" call confirm("BMenu(".a:b.")=".res, '&Ok', 1)
return res
endfunction
" Function: lh#menu#IVN_make(...) {{{3
function! lh#menu#IVN_make(code, text, binding, i_cmd, v_cmd, n_cmd, ...)
" nore options
let nore_i = (a:0 > 0) ? ((a:1 != 0) ? 'nore' : '') : ''
let nore_v = (a:0 > 1) ? ((a:2 != 0) ? 'nore' : '') : ''
let nore_n = (a:0 > 2) ? ((a:3 != 0) ? 'nore' : '') : ''
"
call lh#menu#make('i'.nore_i,a:code,a:text, a:binding, '<buffer>', a:i_cmd)
call lh#menu#make('v'.nore_v,a:code,a:text, a:binding, '<buffer>', a:v_cmd)
if strlen(a:n_cmd) != 0
call lh#menu#make('n'.nore_n,a:code,a:text, a:binding, '<buffer>', a:n_cmd)
endif
endfunction
"
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,107 @@
"=============================================================================
" $Id: option.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/option.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 24th Jul 2004
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (07th Oct 2006)
"------------------------------------------------------------------------
" Description:
" Defines the global function lh#option#get().
" Aimed at (ft)plugin writers.
"
"------------------------------------------------------------------------
" Installation:
" Drop this file into {rtp}/autoload/lh/
" Requires Vim 7+
" History:
" v2.0.5
" (*) lh#option#get_non_empty() manages Lists and Dictionaries
" (*) lh#option#get() doesn't test emptyness anymore
" v2.0.0
" Code moved from {rtp}/macros/
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#option#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#option#debug(expr)
return eval(a:expr)
endfunction
" # Public {{{2
" Function: lh#option#get(name, default [, scope]) {{{3
" @return b:{name} if it exists, or g:{name} if it exists, or {default}
" otherwise
" The order of the variables checked can be specified through the optional
" argument {scope}
function! lh#option#get(name,default,...)
let scope = (a:0 == 1) ? a:1 : 'bg'
let name = a:name
let i = 0
while i != strlen(scope)
if exists(scope[i].':'.name)
" \ && (0 != strlen({scope[i]}:{name}))
return {scope[i]}:{name}
endif
let i += 1
endwhile
return a:default
endfunction
function! lh#option#Get(name,default,...)
let scope = (a:0 == 1) ? a:1 : 'bg'
return lh#option#get(a:name, a:default, scope)
endfunction
function! s:IsEmpty(variable)
if type(a:variable) == type('string') | return 0 == strlen(a:variable)
elseif type(a:variable) == type(42) | return 0 == a:variable
elseif type(a:variable) == type([]) | return 0 == len(a:variable)
elseif type(a:variable) == type({}) | return 0 == len(a:variable)
else | return false
endif
endfunction
" Function: lh#option#get_non_empty(name, default [, scope]) {{{3
" @return of b:{name}, g:{name}, or {default} the first which exists and is not empty
" The order of the variables checked can be specified through the optional
" argument {scope}
function! lh#option#get_non_empty(name,default,...)
let scope = (a:0 == 1) ? a:1 : 'bg'
let name = a:name
let i = 0
while i != strlen(scope)
if exists(scope[i].':'.name) && !s:IsEmpty({scope[i]}:{name})
return {scope[i]}:{name}
endif
let i += 1
endwhile
return a:default
endfunction
function! lh#option#GetNonEmpty(name,default,...)
let scope = (a:0 == 1) ? a:1 : 'bg'
return lh#option#get_non_empty(a:name, a:default, scope)
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,308 @@
"=============================================================================
" $Id: path.vim 237 2010-06-01 00:44:35Z luc.hermitte $
" File: autoload/lh/path.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 23rd Jan 2007
" Last Update: 11th Feb 2008
"------------------------------------------------------------------------
" Description:
" Functions related to the handling of pathnames
"
"------------------------------------------------------------------------
" Installation:
" Drop this file into {rtp}/autoload/lh
" Requires Vim7+
" History:
" v 1.0.0 First Version
" (*) Functions moved from searchInRuntimeTime
" v 2.0.1
" (*) lh#path#Simplify() becomes like |simplify()| except for trailing
" v 2.0.2
" (*) lh#path#SelectOne()
" (*) lh#path#ToRelative()
" v 2.0.3
" (*) lh#path#GlobAsList()
" v 2.0.4
" (*) lh#path#StripStart()
" v 2.0.5
" (*) lh#path#StripStart() interprets '.' as getcwd()
" v 2.2.0
" (*) new functions: lh#path#common(), lh#path#to_dirname(),
" lh#path#depth(), lh#path#relative_to(), lh#path#to_regex(),
" lh#path#find()
" (*) lh#path#simplify() fixed
" (*) lh#path#to_relative() use simplify()
" TODO:
" (*) Decide what #depth('../../bar') shall return
" (*) Fix #simplify('../../bar')
" }}}1
"=============================================================================
"=============================================================================
" Avoid global reinclusion {{{1
let s:cpo_save=&cpo
set cpo&vim
"=============================================================================
" ## Functions {{{1
" # Debug {{{2
let s:verbose = 0
function! lh#path#verbose(...)
if a:0 > 0 | let s:verbose = a:1 | endif
return s:verbose
endfunction
function! s:Verbose(expr)
if s:verbose
echomsg a:expr
endif
endfunction
function! lh#path#debug(expr)
return eval(a:expr)
endfunction
"=============================================================================
" # Public {{{2
" Function: lh#path#simplify({pathname}) {{{3
" Like |simplify()|, but also strip the leading './'
" It seems unable to simplify '..\' when compiled without +shellslash
function! lh#path#simplify(pathname)
let pathname = simplify(a:pathname)
let pathname = substitute(pathname, '^\%(\.[/\\]\)\+', '', '')
let pathname = substitute(pathname, '\([/\\]\)\%(\.[/\\]\)\+', '\1', 'g')
let pwd = getcwd().'/'
let pathname = substitute(pathname, '^'.lh#path#to_regex(pwd), '', 'g')
return pathname
endfunction
function! lh#path#Simplify(pathname)
return lh#path#simplify(a:pathname)
endfunction
" Function: lh#path#common({pathnames}) {{{3
" Find the common leading path between all pathnames
function! lh#path#common(pathnames)
" assert(len(pathnames)) > 1
let common = a:pathnames[0]
let i = 1
while i < len(a:pathnames)
let fcrt = a:pathnames[i]
" pathnames should not contain @
let common = matchstr(common.'@@'.fcrt, '^\zs\(.*[/\\]\)\ze.\{-}@@\1.*$')
if strlen(common) == 0
" No need to further checks
break
endif
let i += 1
endwhile
return common
endfunction
" Function: lh#path#strip_common({pathnames}) {{{3
" Find the common leading path between all pathnames, and strip it
function! lh#path#strip_common(pathnames)
" assert(len(pathnames)) > 1
let common = lh#path#common(a:pathnames)
let l = strlen(common)
if l == 0
return a:pathnames
else
let pathnames = a:pathnames
call map(pathnames, 'strpart(v:val, '.l.')' )
return pathnames
endif
endfunction
function! lh#path#StripCommon(pathnames)
return lh#path#strip_common(a:pathnames)
endfunction
" Function: lh#path#is_absolute_path({path}) {{{3
function! lh#path#is_absolute_path(path)
return a:path =~ '^/'
\ . '\|^[a-zA-Z]:[/\\]'
\ . '\|^[/\\]\{2}'
" Unix absolute path
" or Windows absolute path
" or UNC path
endfunction
function! lh#path#IsAbsolutePath(path)
return lh#path#is_absolute_path(a:path)
endfunction
" Function: lh#path#is_url({path}) {{{3
function! lh#path#is_url(path)
" todo: support UNC paths and other urls
return a:path =~ '^\%(https\=\|s\=ftp\|dav\|fetch\|file\|rcp\|rsynch\|scp\)://'
endfunction
function! lh#path#IsURL(path)
return lh#path#is_url(a:path)
endfunction
" Function: lh#path#select_one({pathnames},{prompt}) {{{3
function! lh#path#select_one(pathnames, prompt)
if len(a:pathnames) > 1
let simpl_pathnames = deepcopy(a:pathnames)
let simpl_pathnames = lh#path#strip_common(simpl_pathnames)
let simpl_pathnames = [ '&Cancel' ] + simpl_pathnames
" Consider guioptions+=c is case of difficulties with the gui
let selection = confirm(a:prompt, join(simpl_pathnames,"\n"), 1, 'Question')
let file = (selection == 1) ? '' : a:pathnames[selection-2]
return file
elseif len(a:pathnames) == 0
return ''
else
return a:pathnames[0]
endif
endfunction
function! lh#path#SelectOne(pathnames, prompt)
return lh#path#select_one(a:pathnames, a:prompt)
endfunction
" Function: lh#path#to_relative({pathname}) {{{3
function! lh#path#to_relative(pathname)
let newpath = fnamemodify(a:pathname, ':p:.')
let newpath = simplify(newpath)
return newpath
endfunction
function! lh#path#ToRelative(pathname)
return lh#path#to_relative(a:pathname)
endfunction
" Function: lh#path#to_dirname({dirname}) {{{3
" todo: use &shellslash
function! lh#path#to_dirname(dirname)
let dirname = a:dirname . (a:dirname[-1:] =~ '[/\\]' ? '' : '/')
return dirname
endfunction
" Function: lh#path#depth({dirname}) {{{3
" todo: make a choice about "negative" paths like "../../foo"
function! lh#path#depth(dirname)
if empty(a:dirname) | return 0 | endif
let dirname = lh#path#to_dirname(a:dirname)
let dirname = lh#path#simplify(dirname)
if lh#path#is_absolute_path(dirname)
let dirname = matchstr(dirname, '.\{-}[/\\]\zs.*')
endif
let depth = len(substitute(dirname, '[^/\\]\+[/\\]', '§', 'g'))
return depth
endfunction
" Function: lh#path#relative_to({from}, {to}) {{{3
" @param two directories
" @return a directories delta that ends with a '/' (may depends on
" &shellslash)
function! lh#path#relative_to(from, to)
" let from = fnamemodify(a:from, ':p')
" let to = fnamemodify(a:to , ':p')
let from = lh#path#to_dirname(a:from)
let to = lh#path#to_dirname(a:to )
let [from, to] = lh#path#strip_common([from, to])
let nb_up = lh#path#depth(from)
return repeat('../', nb_up).to
" cannot rely on :cd (as it alters things, and doesn't work with
" non-existant paths)
let pwd = getcwd()
exe 'cd '.a:to
let res = lh#path#to_relative(a:from)
exe 'cd '.pwd
return res
endfunction
" Function: lh#path#glob_as_list({pathslist}, {expr}) {{{3
function! s:GlobAsList(pathslist, expr)
let sResult = globpath(a:pathslist, a:expr)
let lResult = split(sResult, '\n')
" workaround a non feature of wildignore: it does not ignore directories
for ignored_pattern in split(&wildignore,',')
if stridx(ignored_pattern,'/') != -1
call filter(lResult, 'v:val !~ '.string(ignored_pattern))
endif
endfor
return lResult
endfunction
function! lh#path#glob_as_list(pathslist, expr)
if type(a:expr) == type('string')
return s:GlobAsList(a:pathslist, a:expr)
elseif type(a:expr) == type([])
let res = []
for expr in a:expr
call extend(res, s:GlobAsList(a:pathslist, expr))
endfor
return res
else
throw "Unexpected type for a:expression"
endif
endfunction
function! lh#path#GlobAsList(pathslist, expr)
return lh#path#glob_as_list(a:pathslist, a:expr)
endfunction
" Function: lh#path#strip_start({pathname}, {pathslist}) {{{3
" Strip occurrence of paths from {pathslist} in {pathname}
" @param[in] {pathname} name to simplify
" @param[in] {pathslist} list of pathname (can be a |string| of pathnames
" separated by ",", of a |List|).
function! lh#path#strip_start(pathname, pathslist)
if type(a:pathslist) == type('string')
" let strip_re = escape(a:pathslist, '\\.')
" let strip_re = '^' . substitute(strip_re, ',', '\\|^', 'g')
let pathslist = split(a:pathslist, ',')
elseif type(a:pathslist) == type([])
let pathslist = deepcopy(a:pathslist)
else
throw "Unexpected type for a:pathname"
endif
" apply a realpath like operation
let nb_paths = len(pathslist) " set before the loop
let i = 0
while i != nb_paths
if pathslist[i] =~ '^\.\%(/\|$\)'
let path2 = getcwd().pathslist[i][1:]
call add(pathslist, path2)
endif
let i += 1
endwhile
" replace path separators by a regex that can match them
call map(pathslist, 'substitute(v:val, "[\\\\/]", "[\\\\/]", "g")')
" echomsg string(pathslist)
" escape .
call map(pathslist, '"^".escape(v:val, ".")')
" build the strip regex
let strip_re = join(pathslist, '\|')
" echomsg strip_re
let res = substitute(a:pathname, '\%('.strip_re.'\)[/\\]\=', '', '')
return res
endfunction
function! lh#path#StripStart(pathname, pathslist)
return lh#path#strip_start(a:pathname, a:pathslist)
endfunction
" Function: lh#path#to_regex({pathname}) {{{3
function! lh#path#to_regex(path)
let regex = substitute(a:path, '[/\\]', '[/\\\\]', 'g')
return regex
endfunction
" Function: lh#path#find({pathname}, {regex}) {{{3
function! lh#path#find(paths, regex)
let paths = (type(a:paths) == type([]))
\ ? (a:paths)
\ : split(a:paths,',')
for path in paths
if match(path ,a:regex) != -1
return path
endif
endfor
return ''
endfunction
"=============================================================================
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,93 @@
"=============================================================================
" $Id: position.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/position.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 05th Sep 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (05th Sep 2007)
"------------------------------------------------------------------------
" Description: «description»
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History: «history»
" v1.0.0:
" Creation
" TODO:
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#position#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#position#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" # Public {{{2
" Function: lh#position#is_before {{{3
" @param[in] positions as those returned from |getpos()|
" @return whether lhs_pos is before rhs_pos
function! lh#position#is_before(lhs_pos, rhs_pos)
if a:lhs_pos[0] != a:rhs_pos[0]
throw "Positions from incompatible buffers can't be ordered"
endif
"1 test lines
"2 test cols
let before
\ = (a:lhs_pos[1] == a:rhs_pos[1])
\ ? (a:lhs_pos[2] < a:rhs_pos[2])
\ : (a:lhs_pos[1] < a:rhs_pos[1])
return before
endfunction
function! lh#position#IsBefore(lhs_pos, rhs_pos)
return lh#position#is_before(a:lhs_pos, a:rhs_pos)
endfunction
" Function: lh#position#char_at_mark {{{3
" @return the character at a given mark (|mark|)
function! lh#position#char_at_mark(mark)
let c = getline(a:mark)[col(a:mark)-1]
return c
endfunction
function! lh#position#CharAtMark(mark)
return lh#position#char_at_mark(a:mark)
endfunction
" Function: lh#position#char_at_pos {{{3
" @return the character at a given position (|getpos()|)
function! lh#position#char_at_pos(pos)
let c = getline(a:pos[1])[col(a:pos[2])-1]
return c
endfunction
function! lh#position#CharAtPos(pos)
return lh#position#char_at_pos(a:pos)
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,138 @@
"=============================================================================
" $Id: syntax.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: autoload/lh/syntax.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 05th Sep 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (05th Sep 2007)
"------------------------------------------------------------------------
" Description: «description»
"
"------------------------------------------------------------------------
" Installation:
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History: «history»
" v1.0.0:
" Creation ;
" Functions moved from lhVimSpell
" TODO:
" function, to inject "contained", see lhVimSpell approach
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! lh#syntax#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! lh#syntax#debug(expr)
return eval(a:expr)
endfunction
" # Public {{{2
" Functions: Show name of the syntax kind of a character {{{3
function! lh#syntax#name_at(l,c, ...)
let what = a:0 > 0 ? a:1 : 0
return synIDattr(synID(a:l, a:c, what),'name')
endfunction
function! lh#syntax#NameAt(l,c, ...)
let what = a:0 > 0 ? a:1 : 0
return lh#syntax#name_at(a:l, a:c, what)
endfunction
function! lh#syntax#name_at_mark(mark, ...)
let what = a:0 > 0 ? a:1 : 0
return lh#syntax#name_at(line(a:mark), col(a:mark), what)
endfunction
function! lh#syntax#NameAtMark(mark, ...)
let what = a:0 > 0 ? a:1 : 0
return lh#syntax#name_at_mark(a:mark, what)
endfunction
" Functions: skip string, comment, character, doxygen {{{3
func! lh#syntax#skip_at(l,c)
return lh#syntax#name_at(a:l,a:c) =~? 'string\|comment\|character\|doxygen'
endfun
func! lh#syntax#SkipAt(l,c)
return lh#syntax#skip_at(a:l,a:c)
endfun
func! lh#syntax#skip()
return lh#syntax#skip_at(line('.'), col('.'))
endfun
func! lh#syntax#Skip()
return lh#syntax#skip()
endfun
func! lh#syntax#skip_at_mark(mark)
return lh#syntax#skip_at(line(a:mark), col(a:mark))
endfun
func! lh#syntax#SkipAtMark(mark)
return lh#syntax#skip_at_mark(a:mark)
endfun
" Function: Show current syntax kind {{{3
command! SynShow echo 'hi<'.lh#syntax#name_at_mark('.',1).'> trans<'
\ lh#syntax#name_at_mark('.',0).'> lo<'.
\ synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name').'>'
" Function: lh#syntax#list_raw(name) : string {{{3
function! lh#syntax#list_raw(name)
let a_save = @a
try
redir @a
exe 'silent! syn list '.a:name
redir END
let res = @a
finally
let @a = a_save
endtry
return res
endfunction
" Function: lh#syntax#list(name) : List {{{3
function! lh#syntax#list(name)
let raw = lh#syntax#list_raw(a:name)
let res = []
let lines = split(raw, '\n')
let started = 0
for l in lines
if started
let li = (l =~ 'links to') ? '' : l
elseif l =~ 'xxx'
let li = matchstr(l, 'xxx\s*\zs.*')
let started = 1
else
let li = ''
endif
if strlen(li) != 0
let li = substitute(li, 'contained\S*\|transparent\|nextgroup\|skipwhite\|skipnl\|skipempty', '', 'g')
let kinds = split(li, '\s\+')
call extend(res, kinds)
endif
endfor
return res
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,42 @@
"=============================================================================
" $Id$
" File: autoload/lh/visual.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 08th Sep 2008
" Last Update: $Date$
"------------------------------------------------------------------------
" Helpers functions releated to the visual mode
"
"------------------------------------------------------------------------
" Drop it into {rtp}/autoload/lh/
" Vim 7+ required.
" History:
" v2.0.6: First appearance
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" Functions {{{1
" Function: lh#visual#selection() {{{3
" @return the text currently selected
function! lh#visual#selection()
try
let a_save = @a
normal! gv"ay
return @a
finally
let @a = a_save
endtry
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
------------------
lh-vim-lib 2.2.1
------------------
lh-vim-lib is a library plugin for vim v7+. It is just a collection of
functions that are meant to be used by script writers.
Audience : Vim script writers
Requirements : Vim 7.1
Required by : Just a few other plugins for the moment
Author : Luc Hermitte
License : GPL2
More Help At : http://code.google.com/p/lh-vim/wiki/lhVimLib
Vim script#214: http://www.vim.org/scripts/script.php?script_id=214
Repository :
svn checkout http://lh-vim.googlecode.com/svn/vim-lib/trunk lh-vim-lib

View file

@ -0,0 +1,83 @@
"===========================================================================
" $Id: menu-map.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: macros/menu-map.vim
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
"
" Purpose: Define functions to build mappings and menus at the same time
"
" Version: 2.2.1
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (02nd Dec 2006)
"
" Last Changes: {{{
" Version 2.0.0:
" Moved to vim7,
" Functions moved to {rtp}/autoload/
" Version 1.6.2:
" (*) Silent mappings and menus
" Version 1.6. :
" (*) Uses has('gui_running') instead of has('gui') to check if
" we can generate the menu.
" Version 1.5. :
" (*) visual mappings launched from select-mode don't end with
" text still selected -- applied to :VCalls
" Version 1.4. :
" (*) address obfuscated for spammers
" (*) support the local option
" b:want_buffermenu_or_global_disable if we don't want
" buffermenu to be used systematically.
" 0 -> buffer menu not used
" 1 -> buffer menu used
" 2 -> the VimL developper will use a global disable.
" cf.: tex-maps.vim:: s:SimpleMenu()
" and texmenus.vim
" Version 1.3. :
" (*) add continuation lines support ; cf 'cpoptions'
" Version 1.2. :
" (*) Code folded.
" (*) Take advantage of buffermenu.vim if present for local
" menus.
" (*) If non gui is available, the menus won't be defined
" Version 1.1. :
" (*) Bug corrected :
" vnore(map\|menu) does not imply v+n(map\|menu) any more
" }}}
"
" Inspired By: A function from Benji Fisher
"
" TODO: (*) no menu if no gui.
"
"===========================================================================
if exists("g:loaded_menu_map") | finish | endif
let g:loaded_menu_map = 1
"" line continuation used here ??
let s:cpo_save = &cpo
set cpo&vim
"=========================================================================
" Commands {{{
command! -nargs=+ -bang MAP map<bang> <args>
command! -nargs=+ IMAP imap <args>
command! -nargs=+ NMAP nmap <args>
command! -nargs=+ CMAP cmap <args>
command! -nargs=+ VMAP vmap <args>
command! -nargs=+ AMAP
\ call lh#menu#map_all('amap', <f-args>)
command! -nargs=+ -bang NOREMAP noremap<bang> <args>
command! -nargs=+ INOREMAP inoremap <args>
command! -nargs=+ NNOREMAP nnoremap <args>
command! -nargs=+ CNOREMAP cnoremap <args>
command! -nargs=+ VNOREMAP vnoremap <args>
command! -nargs=+ ANOREMAP
\ call lh#menu#map_all('anoremap', <f-args>)
" }}}
" End !
let &cpo = s:cpo_save
finish
"=========================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,53 @@
"=============================================================================
" $Id: mk-lh-vim-lib.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: mk-lh-lib.vim
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
let s:version = '2.2.1'
" Created: 06th Nov 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
cd <sfile>:p:h
try
let save_rtp = &rtp
let &rtp = expand('<sfile>:p:h:h').','.&rtp
exe '22,$MkVimball! lh-vim-lib-'.s:version
set modifiable
set buftype=
finally
let &rtp = save_rtp
endtry
finish
autoload/lh/askvim.vim
autoload/lh/buffer.vim
autoload/lh/buffer/dialog.vim
autoload/lh/command.vim
autoload/lh/common.vim
autoload/lh/encoding.vim
autoload/lh/env.vim
autoload/lh/event.vim
autoload/lh/graph/tsort.vim
autoload/lh/list.vim
autoload/lh/menu.vim
autoload/lh/option.vim
autoload/lh/path.vim
autoload/lh/position.vim
autoload/lh/syntax.vim
autoload/lh/visual.vim
doc/lh-vim-lib.txt
macros/menu-map.vim
mkVba/mk-lh-vim-lib.vim
plugin/let.vim
plugin/lhvl.vim
plugin/ui-functions.vim
plugin/words_tools.vim
tests/lh/function.vim
tests/lh/list.vim
tests/lh/path.vim
tests/lh/test-Fargs2String.vim
tests/lh/test-askmenu.vim
tests/lh/test-command.vim
tests/lh/test-menu-map.vim
tests/lh/test-toggle-menu.vim
tests/lh/topological-sort.vim

View file

@ -0,0 +1,54 @@
"=============================================================================
" $Id: let.vim 239 2010-06-01 00:48:43Z luc.hermitte $
" File: plugin/let.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 31st May 2010
" Last Update: $Date: 2010-05-31 20:48:43 -0400 (Mon, 31 May 2010) $
"------------------------------------------------------------------------
" Description:
" Defines a command :LetIfUndef that sets a variable if undefined
"
"------------------------------------------------------------------------
" Installation:
" Drop this file into {rtp}/plugin
" Requires Vim7+
" History:
" v2.2.1: first version of this command into lh-vim-lib
" TODO:
" }}}1
"=============================================================================
" Avoid global reinclusion {{{1
let s:k_version = 221
if &cp || (exists("g:loaded_let")
\ && (g:loaded_let >= s:k_version)
\ && !exists('g:force_reload_let'))
finish
endif
let g:loaded_let = s:k_version
let s:cpo_save=&cpo
set cpo&vim
" Avoid global reinclusion }}}1
"------------------------------------------------------------------------
" Commands and Mappings {{{1
command! -nargs=+ LetIfUndef call s:LetIfUndef(<f-args>)
" Commands and Mappings }}}1
"------------------------------------------------------------------------
" Functions {{{1
" Note: most functions are best placed into
" autoload/«your-initials»/«let».vim
" Keep here only the functions are are required when the plugin is loaded,
" like functions that help building a vim-menu for this plugin.
function! s:LetIfUndef(var, value)
if !exists(a:var)
let {a:var} = eval(a:value)
endif
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,45 @@
"=============================================================================
" $Id: lhvl.vim 245 2010-09-19 22:40:10Z luc.hermitte $
" File: plugin/lhvl.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 27th Apr 2010
" Last Update: $Date: 2010-09-19 18:40:10 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Non-function resources from lh-vim-lib
"
"------------------------------------------------------------------------
" Installation:
" Drop the file into {rtp}/plugin
" History:
" v2.2.1 first version
" TODO: «missing features»
" }}}1
"=============================================================================
" Avoid global reinclusion {{{1
let s:k_version = 221
if &cp || (exists("g:loaded_lhvl")
\ && (g:loaded_lhvl >= s:k_version)
\ && !exists('g:force_reload_lhvl'))
finish
endif
let g:loaded_lhvl = s:k_version
let s:cpo_save=&cpo
set cpo&vim
" Avoid global reinclusion }}}1
"------------------------------------------------------------------------
" Commands and Mappings {{{1
" Moved from lh-cpp
command! PopSearch :call histdel('search', -1)| let @/=histget('search',-1)
" Commands and Mappings }}}1
"------------------------------------------------------------------------
" Functions {{{1
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,480 @@
"=============================================================================
" File: plugin/ui-functions.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" URL: http://hermitte.free.fr/vim/ressources/vimfiles/plugin/ui-functions.vim
"
" Version: 2.2.1
" Created: 18th nov 2002
" Last Update: 28th Nov 2007
"------------------------------------------------------------------------
" Description: Functions for the interaction with a User Interface.
" The UI can be graphical or textual.
" At first, this was designed to ease the syntax of
" mu-template's templates.
"
" Option: {{{2
" {[bg]:ui_type}
" = "g\%[ui]",
" = "t\%[ext]" ; the call must not be |:silent|
" = "f\%[te]"
" }}}2
"------------------------------------------------------------------------
" Installation: Drop this into one of your {rtp}/plugin/ directories.
" History: {{{2
" v0.01 Initial Version
" v0.02
" (*) Code "factorisations"
" (*) Help on <F1> enhanced.
" (*) Small changes regarding the parameter accepted
" (*) Function SWITCH
" v0.03
" (*) Small bug fix with INPUT()
" v0.04
" (*) New function: WHICH()
" v0.05
" (*) In vim7e, inputdialog() returns a trailing '\n'. INPUT() strips the
" NL character.
" v0.06
" (*) :s/echoerr/throw/ => vim7 only
" v2.2.0
" (*) menu to switch the ui_type
"
" TODO: {{{2
" (*) Save the hl-User1..9 before using them
" (*) Possibility other than &statusline:
" echohl User1 |echon "bla"|echohl User2|echon "bli"|echohl None
" (*) Wraps too long choices-line (length > term-width)
" (*) Add to the documentation: "don't use CTRL-C to abort !!"
" (*) Look if I need to support 'wildmode'
" (*) 3rd mode: return string for FTE
" (*) 4th mode: interaction in a scratch buffer
"
" }}}1
"=============================================================================
" Avoid reinclusion {{{1
"
if exists("g:loaded_ui_functions") && !exists('g:force_reload_ui_functions')
finish
endif
let g:loaded_ui_functions = 1
let s:cpo_save=&cpo
set cpo&vim
" }}}1
"------------------------------------------------------------------------
" External functions {{{1
" Function: IF(var, then, else) {{{2
function! IF(var,then, else)
let o = s:Opt_type() " {{{3
if o =~ 'g\%[ui]\|t\%[ext]' " {{{4
return a:var ? a:then : a:else
elseif o =~ 'f\%[te]' " {{{4
return s:if_fte(a:var, a:then, a:else)
else " {{{4
throw "UI-Fns::IF(): Unkonwn user-interface style (".o.")"
endif
" }}}3
endfunction
" Function: SWITCH(var, case, action [, case, action] [default_action]) {{{2
function! SWITCH(var, ...)
let o = s:Opt_type() " {{{3
if o =~ 'g\%[ui]\|t\%[ext]' " {{{4
let explicit_def = ((a:0 % 2) == 1)
let default = explicit_def ? a:{a:0} : ''
let i = a:0 - 1 - explicit_def
while i > 0
if a:var == a:{i}
return a:{i+1}
endif
let i = i - 2
endwhile
return default
elseif o =~ 'f\%[te]' " {{{4
return s:if_fte(a:var, a:then, a:else)
else " {{{4
throw "UI-Fns::SWITCH(): Unkonwn user-interface style (".o.")"
endif
" }}}3
endfunction
" Function: CONFIRM(text [, choices [, default [, type]]]) {{{2
function! CONFIRM(text, ...)
" 1- Check parameters {{{3
if a:0 > 4 " {{{4
throw "UI-Fns::CONFIRM(): too many parameters"
return 0
endif
" build the parameters string {{{4
let i = 1
while i <= a:0
if i == 1 | let params = 'a:{1}'
else | let params = params. ',a:{'.i.'}'
endif
let i = i + 1
endwhile
" 2- Choose the correct way to execute according to the option {{{3
let o = s:Opt_type()
if o =~ 'g\%[ui]' " {{{4
exe 'return confirm(a:text,'.params.')'
elseif o =~ 't\%[ext]' " {{{4
if !has('gui_running') && has('dialog_con')
exe 'return confirm(a:text,'.params.')'
else
exe 'return s:confirm_text("none", a:text,'.params.')'
endif
elseif o =~ 'f\%[te]' " {{{4
exe 'return s:confirm_fte(a:text,'.params.')'
else " {{{4
throw "UI-Fns::CONFIRM(): Unkonwn user-interface style (".o.")"
endif
" }}}3
endfunction
" Function: INPUT(prompt [, default ]) {{{2
function! INPUT(prompt, ...)
" 1- Check parameters {{{3
if a:0 > 4 " {{{4
throw "UI-Fns::INPUT(): too many parameters"
return 0
endif
" build the parameters string {{{4
let i = 1 | let params = ''
while i <= a:0
if i == 1 | let params = 'a:{1}'
else | let params = params. ',a:{'.i.'}'
endif
let i = i + 1
endwhile
" 2- Choose the correct way to execute according to the option {{{3
let o = s:Opt_type()
if o =~ 'g\%[ui]' " {{{4
exe 'return matchstr(inputdialog(a:prompt,'.params.'), ".\\{-}\\ze\\n\\=$")'
elseif o =~ 't\%[ext]' " {{{4
exe 'return input(a:prompt,'.params.')'
elseif o =~ 'f\%[te]' " {{{4
exe 'return s:input_fte(a:prompt,'.params.')'
else " {{{4
throw "UI-Fns::INPUT(): Unkonwn user-interface style (".o.")"
endif
" }}}3
endfunction
" Function: COMBO(prompt, choice [, ... ]) {{{2
function! COMBO(prompt, ...)
" 1- Check parameters {{{3
if a:0 > 4 " {{{4
throw "UI-Fns::COMBO(): too many parameters"
return 0
endif
" build the parameters string {{{4
let i = 1
while i <= a:0
if i == 1 | let params = 'a:{1}'
else | let params = params. ',a:{'.i.'}'
endif
let i = i + 1
endwhile
" 2- Choose the correct way to execute according to the option {{{3
let o = s:Opt_type()
if o =~ 'g\%[ui]' " {{{4
exe 'return confirm(a:prompt,'.params.')'
elseif o =~ 't\%[ext]' " {{{4
exe 'return s:confirm_text("combo", a:prompt,'.params.')'
elseif o =~ 'f\%[te]' " {{{4
exe 'return s:combo_fte(a:prompt,'.params.')'
else " {{{4
throw "UI-Fns::COMBO(): Unkonwn user-interface style (".o.")"
endif
" }}}3
endfunction
" Function: WHICH(function, prompt, choice [, ... ]) {{{2
function! WHICH(fn, prompt, ...)
" 1- Check parameters {{{3
" build the parameters string {{{4
let i = 1
while i <= a:0
if i == 1 | let params = 'a:{1}'
else | let params = params. ',a:{'.i.'}'
endif
let i = i + 1
endwhile
" 2- Execute the function {{{3
exe 'let which = '.a:fn.'(a:prompt,'.params.')'
if 0 >= which | return ''
elseif 1 == which
return substitute(matchstr(a:{1}, '^.\{-}\ze\%(\n\|$\)'), '&', '', 'g')
else
return substitute(
\ matchstr(a:{1}, '^\%(.\{-}\n\)\{'.(which-1).'}\zs.\{-}\ze\%(\n\|$\)')
\ , '&', '', 'g')
endif
" }}}3
endfunction
" Function: CHECK(prompt, choice [, ... ]) {{{2
function! CHECK(prompt, ...)
" 1- Check parameters {{{3
if a:0 > 4 " {{{4
throw "UI-Fns::CHECK(): too many parameters"
return 0
endif
" build the parameters string {{{4
let i = 1
while i <= a:0
if i == 1 | let params = 'a:{1}'
else | let params = params. ',a:{'.i.'}'
endif
let i = i + 1
endwhile
" 2- Choose the correct way to execute according to the option {{{3
let o = s:Opt_type()
if o =~ 'g\%[ui]' " {{{4
exe 'return s:confirm_text("check", a:prompt,'.params.')'
elseif o =~ 't\%[ext]' " {{{4
exe 'return s:confirm_text("check", a:prompt,'.params.')'
elseif o =~ 'f\%[te]' " {{{4
exe 'return s:check_fte(a:prompt,'.params.')'
else " {{{4
throw "UI-Fns::CHECK(): Unkonwn user-interface style (".o.")"
endif
" }}}3
endfunction
" }}}1
"------------------------------------------------------------------------
" Options setting {{{1
let s:OptionData = {
\ "variable": "ui_type",
\ "idx_crt_value": 1,
\ "values": ['gui', 'text', 'fte'],
\ "menu": { "priority": '500.2700', "name": '&Plugin.&LH.&UI type'}
\}
call lh#menu#def_toggle_item(s:OptionData)
" }}}1
"------------------------------------------------------------------------
" Internal functions {{{1
function! s:Option(name, default) " {{{2
if exists('b:ui_'.a:name) | return b:ui_{a:name}
elseif exists('g:ui_'.a:name) | return g:ui_{a:name}
else | return a:default
endif
endfunction
function! s:Opt_type() " {{{2
return s:Option('type', 'gui')
endfunction
"
" Function: s:status_line(current, hl [, choices] ) {{{2
" a:current: current item
" a:hl : Generic, Warning, Error
function! s:status_line(current, hl, ...)
" Highlightning {{{3
if a:hl == "Generic" | let hl = '%1*'
elseif a:hl == "Warning" | let hl = '%2*'
elseif a:hl == "Error" | let hl = '%3*'
elseif a:hl == "Info" | let hl = '%4*'
elseif a:hl == "Question" | let hl = '%5*'
else | let hl = '%1*'
endif
" Build the string {{{3
let sl_choices = '' | let i = 1
while i <= a:0
if i == a:current
let sl_choices = sl_choices . ' '. hl .
\ substitute(a:{i}, '&\(.\)', '%6*\1'.hl, '') . '%* '
else
let sl_choices = sl_choices . ' ' .
\ substitute(a:{i}, '&\(.\)', '%6*\1%*', '') . ' '
endif
let i = i + 1
endwhile
" }}}3
return sl_choices
endfunction
" Function: s:confirm_text(box, text [, choices [, default [, type]]]) {{{2
function! s:confirm_text(box, text, ...)
let help = "/<esc>/<s-tab>/<tab>/<left>/<right>/<cr>/<F1>"
" 1- Retrieve the parameters {{{3
let choices = ((a:0>=1) ? a:1 : '&Ok')
let default = ((a:0>=2) ? a:2 : (('check' == a:box) ? 0 : 1))
let type = ((a:0>=3) ? a:3 : 'Generic')
if 'none' == a:box | let prefix = ''
elseif 'combo' == a:box | let prefix = '( )_'
elseif 'check' == a:box | let prefix = '[ ]_'
let help = '/ '.help
else | let prefix = ''
endif
" 2- Retrieve the proposed choices {{{3
" Prepare the hot keys
let i = 0
while i != 26
let hotkey_{nr2char(i+65)} = 0
let i += 1
endwhile
let hotkeys = '' | let help_k = '/'
" Parse the choices
let i = 0
while choices != ""
let i = i + 1
let item = matchstr(choices, "^.\\{-}\\ze\\(\n\\|$\\)")
let choices = matchstr(choices, "\n\\zs.*$")
" exe 'anoremenu ]'.a:text.'.'.item.' :let s:choice ='.i.'<cr>'
if ('check' == a:box) && (strlen(default)>=i) && (1 == default[i-1])
" let choice_{i} = '[X]' . substitute(item, '&', '', '')
let choice_{i} = '[X]_' . item
else
" let choice_{i} = prefix . substitute(item, '&', '', '')
let choice_{i} = prefix . item
endif
if i == 1
let list_choices = 'choice_{1}'
else
let list_choices = list_choices . ',choice_{'.i.'}'
endif
" Update the hotkey.
let key = toupper(matchstr(choice_{i}, '&\zs.\ze'))
let hotkey_{key} = i
let hotkeys = hotkeys . tolower(key) . toupper(key)
let help_k = help_k . tolower(key)
endwhile
let nb_choices = i
if default > nb_choices | let default = nb_choices | endif
" 3- Run an interactive text menu {{{3
" Note: emenu can not be used through ":exe" {{{4
" let wcm = &wcm
" set wcm=<tab>
" exe ':emenu ]'.a:text.'.'."<tab>"
" let &wcm = wcm
" 3.1- Preparations for the statusline {{{4
" save the statusline
let sl = &l:statusline
" Color schemes for selected item {{{5
:hi User1 term=inverse,bold cterm=inverse,bold ctermfg=Yellow
\ guifg=Black guibg=Yellow
:hi User2 term=inverse,bold cterm=inverse,bold ctermfg=LightRed
\ guifg=Black guibg=LightRed
:hi User3 term=inverse,bold cterm=inverse,bold ctermfg=Red
\ guifg=Black guibg=Red
:hi User4 term=inverse,bold cterm=inverse,bold ctermfg=Cyan
\ guifg=Black guibg=Cyan
:hi User5 term=inverse,bold cterm=inverse,bold ctermfg=LightYellow
\ guifg=Black guibg=LightYellow
:hi User6 term=inverse,bold cterm=inverse,bold ctermfg=LightGray
\ guifg=DarkRed guibg=LightGray
" }}}5
" 3.2- Interactive loop {{{4
let help = "\r-- Keys available (".help_k.help.")"
" item selected at the start
let i = ('check' != a:box) ? default : 1
let direction = 0 | let toggle = 0
while 1
if 'combo' == a:box
let choice_{i} = substitute(choice_{i}, '^( )', '(*)', '')
endif
" Colored statusline
" Note: unfortunately the 'statusline' is a global option, {{{
" not a local one. I the hope that may change, as it does not provokes any
" error, I use '&l:statusline'. }}}
exe 'let &l:statusline=s:status_line(i, type,'. list_choices .')'
if has(':redrawstatus')
redrawstatus!
else
redraw!
endif
" Echo the current selection
echo "\r". a:text.' '.substitute(choice_{i}, '&', '', '')
" Wait the user to hit a key
let key=getchar()
let complType=nr2char(key)
" If the key hit matched awaited keys ...
if -1 != stridx(" \<tab>\<esc>\<enter>".hotkeys,complType) ||
\ (key =~ "\<F1>\\|\<right>\\|\<left>\\|\<s-tab>")
if key == "\<F1>" " Help {{{5
redraw!
echohl StatusLineNC
echo help
echohl None
let key=getchar()
let complType=nr2char(key)
endif
" TODO: support CTRL-D
if complType == "\<enter>" " Validate {{{5
break
elseif complType == " " " check box {{{5
let toggle = 1
elseif complType == "\<esc>" " Abort {{{5
let i = -1 | break
elseif complType == "\<tab>" || key == "\<right>" " Next {{{5
let direction = 1
elseif key =~ "\<left>\\|\<s-tab>" " Previous {{{5
let direction = -1
elseif -1 != stridx(hotkeys, complType ) " Hotkeys {{{5
if '' == complType | continue | endif
let direction = hotkey_{toupper(complType)} - i
let toggle = 1
" else
endif
" }}}5
endif
if direction != 0 " {{{5
if 'combo' == a:box
let choice_{i} = substitute(choice_{i}, '^(\*)', '( )', '')
endif
let i = i + direction
if i > nb_choices | let i = 1
elseif i == 0 | let i = nb_choices
endif
let direction = 0
endif
if toggle == 1 " {{{5
if 'check' == a:box
let choice_{i} = ((choice_{i}[1] == ' ')? '[X]' : '[ ]')
\ . strpart(choice_{i}, 3)
endif
let toggle = 0
endif
endwhile " }}}4
" 4- Terminate {{{3
" Clear screen
redraw!
" Restore statusline
let &l:statusline=sl
" Return
if (i == -1) || ('check' != a:box)
return i
else
let r = '' | let i = 1
while i <= nb_choices
let r = r . ((choice_{i}[1] == 'X') ? '1' : '0')
let i = i + 1
endwhile
return r
endif
endfunction
" }}}1
"------------------------------------------------------------------------
" Functions that insert fte statements {{{1
" Function: s:if_fte(var, then, else) {{{2
" Function: s:confirm_fte(text, [, choices [, default [, type]]]) {{{2
" Function: s:input_fte(prompt [, default]) {{{2
" Function: s:combo_fte(prompt, choice [, ...]) {{{2
" Function: s:check_fte(prompt, choice [, ...]) {{{2
" }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,104 @@
" File: plugin/words_tools.vim
" Author: Luc Hermitte <hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" URL: http://hermitte.free.fr/vim/ressources/vim_dollar/plugin/words_tools.vim
"
" Last Update: 14th nov 2002
" Purpose: Define functions better than expand("<cword>")
"
" Note: They are expected to be used in insert mode (thanks to <c-r>
" or <c-o>)
"
"===========================================================================
" Return the current keyword, uses spaces to delimitate {{{1
function! GetNearestKeyword()
let c = col ('.')-1
let ll = getline('.')
let ll1 = strpart(ll,0,c)
let ll1 = matchstr(ll1,'\k*$')
let ll2 = strpart(ll,c,strlen(ll)-c+1)
let ll2 = matchstr(ll2,'^\k*')
" let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
return ll1.ll2
endfunction
" Return the current word, uses spaces to delimitate {{{1
function! GetNearestWord()
let c = col ('.')-1
let l = line('.')
let ll = getline(l)
let ll1 = strpart(ll,0,c)
let ll1 = matchstr(ll1,'\S*$')
let ll2 = strpart(ll,c,strlen(ll)-c+1)
let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
""echo ll1.ll2
return ll1.ll2
endfunction
" Return the word before the cursor, uses spaces to delimitate {{{1
" Rem : <cword> is the word under or after the cursor
function! GetCurrentWord()
let c = col ('.')-1
let l = line('.')
let ll = getline(l)
let ll1 = strpart(ll,0,c)
let ll1 = matchstr(ll1,'\S*$')
if strlen(ll1) == 0
return ll1
else
let ll2 = strpart(ll,c,strlen(ll)-c+1)
let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
return ll1.ll2
endif
endfunction
" Return the keyword before the cursor, uses \k to delimitate {{{1
" Rem : <cword> is the word under or after the cursor
function! GetCurrentKeyword()
let c = col ('.')-1
let l = line('.')
let ll = getline(l)
let ll1 = strpart(ll,0,c)
let ll1 = matchstr(ll1,'\k*$')
if strlen(ll1) == 0
return ll1
else
let ll2 = strpart(ll,c,strlen(ll)-c+1)
let ll2 = matchstr(ll2,'^\k*')
" let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
return ll1.ll2
endif
endfunction
" Extract the word before the cursor, {{{1
" use keyword definitions, skip latter spaces (see "bla word_accepted ")
function! GetPreviousWord()
let lig = getline(line('.'))
let lig = strpart(lig,0,col('.')-1)
return matchstr(lig, '\<\k*\>\s*$')
endfunction
" GetLikeCTRL_W() retrieves the characters that i_CTRL-W deletes. {{{1
" Initial need by Hari Krishna Dara <hari_vim@yahoo.com>
" Last ver:
" Pb: "if strlen(w) == " --> ") == " instead of just "== ".
" There still exists a bug regarding the last char of a line. VIM bug ?
function! GetLikeCTRL_W()
let lig = getline(line('.'))
let lig = strpart(lig,0,col('.')-1)
" treat ending spaces apart.
let s = matchstr(lig, '\s*$')
let lig = strpart(lig, 0, strlen(lig)-strlen(s))
" First case : last characters belong to a "word"
let w = matchstr(lig, '\<\k\+\>$')
if strlen(w) == 0
" otherwise, they belong to a "non word" (without any space)
let w = substitute(lig, '.*\(\k\|\s\)', '', 'g')
endif
return w . s
endfunction
" }}}1
"========================================================================
" vim60: set fdm=marker:

View file

@ -0,0 +1,284 @@
"=============================================================================
" $Id: function.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: tests/lh/function.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 03rd Nov 2008
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Tests for autoload/lh/function.vim
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
UTSuite [lh-vim-lib] Testing lh#function plugin
runtime autoload/lh/function.vim
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
function! Test(...)
let nb = len(a:000)
" echo "test(".nb.':' .join(a:000, ' -- ')')'
let i =0
while i!= len(a:000)
echo "Test: type(".i.")=".type(a:000[i]).' --> '. string(a:000[i])
let i += 1
endwhile
endfunction
function! Print(...)
let res = lh#list#accumulate([1,2,'foo'], 'string', 'join(v:1_, " ## ")')
return res
endfunction
function! Id(...)
return copy(a:000)
endfunction
function! s:TestId()
let r = Id(1, 'string', [0], [[1]], {'ffo':42}, function('exists'), 1.2)
Assert! len(r) == 7
Assert! should#be#number (r[0])
Assert! should#be#string (r[1])
Assert! should#be#list (r[2])
Assert! should#be#list (r[3])
Assert! should#be#dict (r[4])
Assert! should#be#funcref(r[5])
Assert! should#be#float (r[6])
Assert r[0] == 1
Assert r[1] == 'string'
Assert r[2] == [0]
Assert r[3] == [[1]]
Assert r[4].ffo == 42
Assert r[5] == function('exists')
Assert r[6] == 1.2
endfunction
function! s:Test_bind()
" lh#function#bind + lh#function#execute
let rev4 = lh#function#bind(function('Id'), 'v:4_', 42, 'v:3_', 'v:2_', 'v:1_')
let r = lh#function#execute(rev4, 1,'two','three', [4,5])
Assert! len(r) == 5
Assert! should#be#list (r[0])
Assert! should#be#number (r[1])
Assert! should#be#string (r[2])
Assert! should#be#string (r[3])
Assert! should#be#number (r[4])
Assert r[0] == [4,5]
Assert r[1] == 42
Assert r[2] == 'three'
Assert r[3] == 'two'
Assert r[4] == 1
endfunction
function! s:Test_bind_compound_vars()
" lh#function#bind + lh#function#execute
let rev4 = lh#function#bind(function('Id'), 'v:4_', 'v:1_ . v:2_', 'v:3_', 'v:2_', 'v:1_')
let r = lh#function#execute(rev4, 1,'two','three', [4,5])
Assert! len(r) == 5
Assert! should#be#list (r[0])
Assert! should#be#string (r[1])
Assert! should#be#string (r[2])
Assert! should#be#string (r[3])
Assert! should#be#number (r[4])
Assert r[0] == [4,5]
Assert r[1] == '1two'
Assert r[2] == 'three'
Assert r[3] == 'two'
Assert r[4] == 1
endfunction
function! s:Test_execute_func_string_name()
" function name as string
let r = lh#function#execute('Id', 1,'two',3)
Assert! len(r) == 3
Assert! should#be#number (r[0])
Assert! should#be#string (r[1])
Assert! should#be#number (r[2])
Assert r[0] == 1
Assert r[1] == 'two'
Assert r[2] == 3
endfunction
function! s:Test_execute_string_expr()
" exp as binded-string
let r = lh#function#execute('Id(12,len(v:2_).v:2_, 42, v:3_, v:1_)', 1,'two',3)
Assert! len(r) == 5
Assert! should#be#number (r[0])
Assert! should#be#string (r[1])
Assert! should#be#number (r[2])
Assert! should#be#number (r[3])
Assert! should#be#number (r[4])
Assert r[0] == 12
Assert r[1] == len('two').'two'
Assert r[2] == 42
Assert r[3] == 3
Assert r[4] == 1
endfunction
function! s:Test_execute_func()
" calling a function() + bind
let r = lh#function#execute(function('Id'), 1,'two','v:1_',['a',42])
Assert! len(r) == 4
Assert! should#be#number (r[0])
Assert! should#be#string (r[1])
Assert! should#be#string (r[2])
Assert! should#be#list (r[3])
Assert r[0] == 1
Assert r[1] == 'two'
Assert r[2] == 'v:1_'
Assert r[3] == ['a', 42]
endfunction
"------------------------------------------------------------------------
function! s:Test_bind_func_string_name_AND_execute()
" function name as string
let rev3 = lh#function#bind('Id', 'v:3_', 12, 'v:2_', 'v:1_')
let r = lh#function#execute(rev3, 1,'two',3)
Assert! len(r) == 4
Assert! should#be#number (r[0])
Assert! should#be#number (r[1])
Assert! should#be#string (r[2])
Assert! should#be#number (r[3])
Assert r[0] == 3
Assert r[1] == 12
Assert r[2] == 'two'
Assert r[3] == 1
endfunction
function! s:Test_bind_string_expr_AND_execute()
" expressions as string
let rev3 = lh#function#bind('Id(12,len(v:2_).v:2_, 42, v:3_, v:1_)')
let r = lh#function#execute(rev3, 1,'two',3)
Assert! len(r) == 5
Assert! should#be#number (r[0])
Assert! should#be#string (r[1])
Assert! should#be#number (r[2])
Assert! should#be#number (r[3])
Assert! should#be#number (r[4])
Assert r[0] == 12
Assert r[1] == len('two').'two'
Assert r[2] == 42
Assert r[3] == 3
Assert r[4] == 1
endfunction
function! s:Test_double_bind_func_name()
let f1 = lh#function#bind('Id', 1, 2, 'v:1_', 4, 'v:2_')
" Comment "f1=".string(f1)
let r = lh#function#execute(f1, 3, 5)
Assert! len(r) == 5
let i = 0
while i != len(r)
Assert! should#be#number (r[i])
Assert r[i] == i+1
let i += 1
endwhile
" f2
let f2 = lh#function#bind(f1, 'v:1_', 5)
" Comment "f2=f1(v:1_, 5)=".string(f2)
let r = lh#function#execute(f2, 3)
Assert! len(r) == 5
let i = 0
while i != len(r)
Assert! should#be#number (r[i])
" echo "?? ".(r[i])."==".(i+1)
Assert r[i] == i+1
let i += 1
endwhile
endfunction
function! s:Test_double_bind_func()
let f1 = lh#function#bind(function('Id'), 1, 2, 'v:1_', 4, 'v:2_')
" Comment "f1=".string(f1)
let r = lh#function#execute(f1, 3, 5)
Assert! len(r) == 5
let i = 0
while i != len(r)
Assert! should#be#number (r[i])
Assert r[i] == i+1
let i += 1
endwhile
" f2
let f2 = lh#function#bind(f1, 'v:1_', 5)
" Comment "f2=f1(v:1_, 5)=".string(f2)
let r = lh#function#execute(f2, 3)
Assert! len(r) == 5
let i = 0
while i != len(r)
Assert! should#be#number (r[i])
Assert r[i] == i+1
let i += 1
endwhile
endfunction
function! s:Test_double_bind_func_cplx()
let s:bar = "bar"
let f1 = lh#function#bind(function('Id'), 1, 2, 'v:1_', 4, 'v:2_', 'v:3_', 'v:4_', 'v:5_', 'v:6_', 'v:7_')
" Comment "f1=".string(f1)
let f2 = lh#function#bind(f1, 'v:1_', 5, 'foo', s:bar, 'len(s:bar.v:1_)+v:1_', [1,2], '[v:1_, v:2_]')
" Comment "f2=f1(v:1_, 5)=".string(f2)
let r = lh#function#execute(f2, 42, "foo")
Assert! 0 && "not ready"
Comment "2bcpl# ".string(r)
endfunction
function! s:Test_double_bind_expr()
let f1 = lh#function#bind('Id(1, 2, v:1_, v:3_, v:2_)')
Comment "2be# f1=".string(f1)
let r = lh#function#execute(f1, 3, 5, 4)
Comment "2be# ".string(r)
Assert! len(r) == 5
let i = 0
while i != len(r)
Assert! should#be#number (r[i])
Assert r[i] == i+1
let i += 1
endwhile
" f2
let f2 = lh#function#bind(f1, 'v:1_', '"foo"', [])
Comment "2be# f2=f1(v:1_, 5)=".string(f2)
let r = lh#function#execute(f2, 3)
Comment "2be# ".string(r)
Assert! len(r) == 5
let i = 0
while i != len(r)-2
Assert! should#be#number (r[i])
Assert r[i] == i+1
let i += 1
endwhile
Assert! should#be#list (r[-2])
Assert r[-2] == []
Assert! should#be#string (r[-1])
Assert r[-1] == 'foo'
endfunction
"todo: write double-binded tests for all kind of binded parameters:
" 'len(g:bar)'
" 42
" []
" v:1_ + len(v:2_.v:3_)
" '"foo"'
" v:1_
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,165 @@
"=============================================================================
" $Id: list.vim 238 2010-06-01 00:47:16Z luc.hermitte $
" File: tests/lh/list.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 19th Nov 2008
" Last Update: $Date: 2010-05-31 20:47:16 -0400 (Mon, 31 May 2010) $
"------------------------------------------------------------------------
" Description:
" Tests for autoload/lh/list.vim
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
UTSuite [lh-vim-lib] Testing lh#list functions
runtime autoload/lh/function.vim
runtime autoload/lh/list.vim
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" Find_if
function! s:Test_Find_If_string_predicate()
:let b = { 'min': 12, 'max': 42 }
:let l = [ 1, 5, 48, 25, 5, 28, 6]
:let i = lh#list#Find_if(l, 'v:val>v:1_.min && v:val<v:1_.max && v:val%v:2_==0', [b, 2] )
" echo i . '/' . len(l)
Assert i == 5
Assert l[i] == 28
" :echo l[i]
endfunction
function! s:Test_Find_If_functor_predicate()
:let l = [ 1, 5, 48, 25, 5, 28, 6]
:let i = lh#list#find_if(l, 'v:1_>12 && v:1_<42 && v:1_%2==0')
" echo i . '/' . len(l)
Assert i == 5
Assert l[i] == 28
" :echo l[i]
endfunction
function! s:Test_find_if_double_bind()
:let b = { 'min': 12, 'max': 42 }
:let l = [ 1, 5, 48, 25, 5, 28, 6]
:let f = lh#function#bind( 'v:3_>v:1_.min && v:3_<v:1_.max && v:3_%v:2_==0')
:let p = lh#function#bind(f, b,2,'v:1_')
:let i = lh#list#find_if(l, p)
:echo l[i]
endfunction
" double bind is not yet operational
UTIgnore Test_find_if_double_bind
"------------------------------------------------------------------------
" Unique Sorting
function! CmpNumbers(lhs, rhs)
if a:lhs < a:rhs | return -1
elseif a:lhs == a:rhs | return 0
else | return +1
endif
endfunction
function! s:Test_sort()
:let l = [ 1, 5, 48, 25, 5, 28, 6]
:let expected = [ 1, 5, 6, 25, 28, 48]
:let s = lh#list#unique_sort(l, "CmpNumbers")
" Comment string(s)
Assert s == expected
endfunction
function! s:Test_sort2()
:let l = [ 1, 5, 48, 25, 5, 28, 6]
:let expected = [ 1, 5, 6, 25, 28, 48]
:let s = lh#list#unique_sort2(l, "CmpNumbers")
" Comment string(s)
Assert s == expected
endfunction
"------------------------------------------------------------------------
" Searchs
function! s:TestBinarySearches()
let v1 = [ -3, -2, -1, -1, 0, 0, 1, 2, 3, 4, 6 ]
let i = lh#list#lower_bound(v1, 3)
Assert v1[i] == 3
let i = lh#list#upper_bound(v1, 3)
Assert v1[i] == 4
let r = lh#list#equal_range(v1, 3)
Assert v1[r[0]:r[1]-1] == [3]
let i = lh#list#lower_bound(v1, -1)
Assert v1[i] == -1
let i = lh#list#upper_bound(v1, -1)
Assert v1[i] == 0
let r = lh#list#equal_range(v1, -1)
Assert v1[r[0]:r[1]-1] == [-1, -1]
let i = lh#list#lower_bound(v1, 5)
Assert v1[i] == 6
let i = lh#list#upper_bound(v1, 5)
Assert v1[i] == 6
let r = lh#list#equal_range(v1, 5)
Assert v1[r[0]:r[1]-1] == []
Assert len(v1) == lh#list#lower_bound(v1, 10)
Assert len(v1) == lh#list#upper_bound(v1, 10)
Assert [len(v1), len(v1)] == lh#list#equal_range(v1, 10)
endfunction
"------------------------------------------------------------------------
" accumulate
function! s:Test_accumulate_len_strings()
let strings = [ 'foo', 'bar', 'toto' ]
let len = eval(lh#list#accumulate(strings, 'strlen', 'join(v:1_, "+")'))
Assert len == 3+3+4
endfunction
function! s:Test_accumulate_join()
let ll = [ 1, 2, 'foo', ['bar'] ]
let res = lh#list#accumulate(ll, 'string', 'join(v:1_, " ## ")')
Assert res == "1 ## 2 ## 'foo' ## ['bar']"
" This test will fail because it seems :for each loop cannot iterate on
" heterogeneous containers
endfunction
"------------------------------------------------------------------------
" Copy_if
function! s:Test_copy_if()
:let l = [ 1, 25, 5, 48, 25, 5, 28, 6]
:let expected = [ 25, 48, 25, 28, 6]
:let s = lh#list#copy_if(l, [], "v:1_ > 5")
" Comment string(s)
Assert s == expected
endfunction
"------------------------------------------------------------------------
" subset
function! s:Test_subset()
:let l = [ 1, 25, 5, 48, 25, 5, 28, 6]
:let indices = [ 0, 5, 7, 3 ]
:let expected = [ 1, 5, 6, 48 ]
:let s = lh#list#subset(l, indices)
" Comment string(s)
Assert s == expected
endfunction
"------------------------------------------------------------------------
" intersect
function! s:Test_intersect()
:let l1 = [ 1, 25, 7, 48, 26, 5, 28, 6]
:let l2 = [ 3, 8, 7, 25, 6 ]
:let expected = [ 25, 7, 6 ]
:let s = lh#list#intersect(l1, l2)
" Comment string(s)
Assert s == expected
endfunction
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,173 @@
"=============================================================================
" $Id: path.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: tests/lh/path.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 28th May 2009
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Tests for autoload/lh/path.vim
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
UTSuite [lh-vim-lib] Testing lh#path functions
runtime autoload/lh/path.vim
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
function! s:Test_simplify()
Assert lh#path#simplify('a/b/c') == 'a/b/c'
Assert lh#path#simplify('a/b/./c') == 'a/b/c'
Assert lh#path#simplify('./a/b/./c') == 'a/b/c'
Assert lh#path#simplify('./a/../b/./c') == 'b/c'
Assert lh#path#simplify('../a/../b/./c') == '../b/c'
Assert lh#path#simplify('a\b\c') == 'a\b\c'
Assert lh#path#simplify('a\b\.\c') == 'a\b\c'
Assert lh#path#simplify('.\a\b\.\c') == 'a\b\c'
if exists('+shellslash')
Assert lh#path#simplify('.\a\..\b\.\c') == 'b\c'
Assert lh#path#simplify('..\a\..\b\.\c') == '..\b\c'
endif
endfunction
function! s:Test_strip_common()
let paths = ['foo/bar/file', 'foo/file', 'foo/foo/file']
let expected = [ 'bar/file', 'file', 'foo/file']
Assert lh#path#strip_common(paths) == expected
endfunction
function! s:Test_common()
Assert 'foo/' == lh#path#common(['foo/bar/dir', 'foo'])
Assert 'foo/bar/' == lh#path#common(['foo/bar/dir', 'foo/bar'])
Assert 'foo/' == lh#path#common(['foo/bar/dir', 'foo/bar2'])
endfunction
function! s:Test_strip_start()
let expected = 'template/bar.template'
Assert lh#path#strip_start($HOME.'/.vim/template/bar.template',
\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ])
\ == expected
Assert lh#path#strip_start($HOME.'/vimfiles/template/bar.template',
\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ])
\ == expected
Assert lh#path#strip_start('/usr/local/share/vim/template/bar.template',
\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ])
\ == expected
endfunction
function! s:Test_IsAbsolutePath()
" nix paths
Assert lh#path#is_absolute_path('/usr/local')
Assert lh#path#is_absolute_path($HOME)
Assert ! lh#path#is_absolute_path('./usr/local')
Assert ! lh#path#is_absolute_path('.usr/local')
" windows paths
Assert lh#path#is_absolute_path('e:\usr\local')
Assert ! lh#path#is_absolute_path('.\usr\local')
Assert ! lh#path#is_absolute_path('.usr\local')
" UNC paths
Assert lh#path#is_absolute_path('\\usr\local')
Assert lh#path#is_absolute_path('//usr/local')
endfunction
function! s:Test_IsURL()
" nix paths
Assert ! lh#path#is_url('/usr/local')
Assert ! lh#path#is_url($HOME)
Assert ! lh#path#is_url('./usr/local')
Assert ! lh#path#is_url('.usr/local')
" windows paths
Assert ! lh#path#is_url('e:\usr\local')
Assert ! lh#path#is_url('.\usr\local')
Assert ! lh#path#is_url('.usr\local')
" UNC paths
Assert ! lh#path#is_url('\\usr\local')
Assert ! lh#path#is_url('//usr/local')
" URLs
Assert lh#path#is_url('http://www.usr/local')
Assert lh#path#is_url('https://www.usr/local')
Assert lh#path#is_url('ftp://www.usr/local')
Assert lh#path#is_url('sftp://www.usr/local')
Assert lh#path#is_url('dav://www.usr/local')
Assert lh#path#is_url('fetch://www.usr/local')
Assert lh#path#is_url('file://www.usr/local')
Assert lh#path#is_url('rcp://www.usr/local')
Assert lh#path#is_url('rsynch://www.usr/local')
Assert lh#path#is_url('scp://www.usr/local')
endfunction
function! s:Test_ToRelative()
let pwd = getcwd()
Assert lh#path#to_relative(pwd.'/foo/bar') == 'foo/bar'
Assert lh#path#to_relative(pwd.'/./foo') == 'foo'
Assert lh#path#to_relative(pwd.'/foo/../bar') == 'bar'
" Does not work yet as it returns an absolute path it that case
Assert lh#path#to_relative(pwd.'/../bar') == '../bar'
endfunction
function! s:Test_relative_path()
Assert lh#path#relative_to('foo/bar/dir', 'foo') == '../../'
Assert lh#path#relative_to('foo', 'foo/bar/dir') == 'bar/dir/'
Assert lh#path#relative_to('foo/bar', 'foo/bar2/dir') == '../bar2/dir/'
let pwd = getcwd()
Assert lh#path#relative_to(pwd ,pwd.'/../bar') == '../bar/'
endfunction
function! s:Test_search_vimfiles()
let expected_win = $HOME . '/vimfiles'
let expected_nix = $HOME . '/.vim'
let what = lh#path#to_regex($HOME.'/').'\(vimfiles\|.vim\)'
" Comment what
let z = lh#path#find(&rtp,what)
if has('win16')||has('win32')||has('win64')
Assert z == expected_win
else
Assert z == expected_nix
endif
endfunction
function! s:Test_path_depth()
Assert 0 == lh#path#depth('.')
Assert 0 == lh#path#depth('./')
Assert 0 == lh#path#depth('.\')
Assert 1 == lh#path#depth('toto')
Assert 1 == lh#path#depth('toto/')
Assert 1 == lh#path#depth('toto\')
Assert 1 == lh#path#depth('toto/.')
Assert 1 == lh#path#depth('toto\.')
Assert 1 == lh#path#depth('toto/./.')
Assert 1 == lh#path#depth('toto\.\.')
Assert 0 == lh#path#depth('toto/..')
if exists('+shellslash')
Assert 0 == lh#path#depth('toto\..')
endif
Assert 2 == lh#path#depth('toto/titi/')
Assert 2 == lh#path#depth('toto\titi\')
Assert 2 == lh#path#depth('/toto/titi/')
Assert 2 == lh#path#depth('c:/toto/titi/')
Assert 2 == lh#path#depth('c:\toto/titi/')
" todo: make a choice about "negative" paths like "../../foo"
Assert -1 == lh#path#depth('../../foo')
endfunction
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,83 @@
"=============================================================================
" $Id: test-Fargs2String.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: tests/lh/test-Fargs2String.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 16th Apr 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description: Tests for lh-vim-lib . lh#command#Fargs2String
"
"------------------------------------------------------------------------
" Installation:
" Relies on the version «patched by myself|1?» of vim_units
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
function! s:TestEmpty()
let empty = []
let res = lh#command#Fargs2String(empty)
call VUAssertEquals(len(empty), 0, 'Expected empty', 22)
call VUAssertEquals(res, '', 'Expected empty result', 23)
endfunction
function! s:TestSimpleText1()
let expected = 'text'
let one = [ expected ]
let res = lh#command#Fargs2String(one)
call VUAssertEquals(len(one), 0, 'Expected empty', 27)
call VUAssertEquals(res, expected, 'Expected a simple result', 28)
endfunction
function! s:TestSimpleTextN()
let expected = 'text'
let list = [ expected , 'stuff1', 'stuff2']
let res = lh#command#Fargs2String(list)
call VUAssertEquals(len(list), 2, 'Expected not empty', 38)
call VUAssertEquals(res, expected, 'Expected a simple result', 39)
endfunction
function! s:TestComposedN()
let expected = '"a several tokens string"'
let list = [ '"a', 'several', 'tokens', 'string"', 'stuff1', 'stuff2']
let res = lh#command#Fargs2String(list)
call VUAssertEquals(len(list), 2, 'Expected not empty', 46)
call VUAssertEquals(res, expected, 'Expected a composed string', 47)
call VUAssertEquals(list, ['stuff1', 'stuff2'], 'Expected a list', 48)
call VUAssertNotSame(list, ['stuff1', 'stuff2'], 'Expected different lists', 49)
endfunction
function! s:TestComposed1()
let expected = '"string"'
let list = [ '"string"', 'stuff1', 'stuff2']
let res = lh#command#Fargs2String(list)
call VUAssertEquals(len(list), 2, 'Expected not empty', 56)
call VUAssertEquals(res, expected, 'Expected a string', 57)
call VUAssertEquals(list, ['stuff1', 'stuff2'], 'Expected a list', 58)
call VUAssertNotSame(list, ['stuff1', 'stuff2'], 'Expected different lists', 59)
endfunction
function! s:TestInvalidString()
let expected = '"a string'
let list = [ '"a', 'string']
let res = lh#command#Fargs2String(list)
call VUAssertEquals(len(list), 0, 'Expected empty', 66)
call VUAssertEquals(res, expected, 'Expected an invalid string', 67)
endfunction
function! AllTests()
call s:TestEmpty()
call s:TestSimpleText1()
call s:TestSimpleTextN()
call s:TestComposed1()
call s:TestComposedN()
endfunction
" call VURunnerRunTest('AllTests')
VURun % AllTests
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,65 @@
"=============================================================================
" $Id: test-askmenu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: test-buffer-menu.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 18th Apr 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Test units for buffermenu.vim
"
"------------------------------------------------------------------------
" Installation: Requires:
" (*) Vim 7.0+
" (*) vim_units.vim v0.2/1.0?
" Vimscript # «???»
" (*) lh-vim-lib (lh#ask#menu)
"
" User Manual:
" Source this file.
"
" History:
" (*) 17th Apr 2007: First version
" TODO: «missing features»
" }}}1
"=============================================================================
"=============================================================================
let s:cpo_save=&cpo
"------------------------------------------------------------------------
" Functions {{{1
function! TestAskMenu()
imenu 42.40.10 &LH-Tests.&Menu.&ask.i iask
inoremenu 42.40.10 &LH-Tests.&Menu.&ask.inore inoreask
nmenu 42.40.10 &LH-Tests.&Menu.&ask.n nask
nnoremenu 42.40.10 &LH-Tests.&Menu.&ask.nnore nnoreask
nmenu <script> 42.40.10 &LH-Tests.&Menu.&ask.nscript nscriptask
nnoremenu <script> 42.40.10 &LH-Tests.&Menu.&ask.nnnscript nnscriptask
vmenu 42.40.10 &LH-Tests.&Menu.&ask.v vask
vnoremenu 42.40.10 &LH-Tests.&Menu.&ask.vnore vnoreask
call s:CheckInMode('i', 'i')
endfunction
function! s:CheckInMode(mode, name)
let g:menu = lh#askvim#menu('LH-Tests.Menu.ask.'.a:name, a:mode)
let g:name = a:name
" VUAssert 55 Equals g:menu.name g:name "Name mismatch"
" VUAssert 56 Equals g:menu.priority '42.40.10' "Priority mismatch"
" VUAssert 57 Fail "parce qu'il le faut bien"
echomsg "name= ".g:menu.name
echomsg "prio= ".g:menu.priority
endfunction
" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,69 @@
" $Id: test-command.vim 156 2010-05-07 00:54:36Z luc.hermitte $
" Tests for lh-vim-lib . lh#command
" FindFilter(filter): Helper {{{3
function! s:FindFilter(filter)
let filter = a:filter . '.vim'
let result =globpath(&rtp, "compiler/BTW-".filter) . "\n" .
\ globpath(&rtp, "compiler/BTW_".filter). "\n" .
\ globpath(&rtp, "compiler/BTW/".filter)
let result = substitute(result, '\n\n', '\n', 'g')
let result = substitute(result, '^\n', '', 'g')
return result
endfunction
function! s:ComplFilter(filter)
let files = s:FindFilter('*')
let files = substitute(files,
\ '\(^\|\n\).\{-}compiler[\\/]BTW[-_\\/]\(.\{-}\)\.vim\>\ze\%(\n\|$\)',
\ '\1\2', 'g')
return files
endfunction
function! s:Add()
endfunction
let s:v1 = 'v1'
let s:v2 = 2
function! s:Foo(i)
return a:i*a:i
endfunction
function! s:echo(params)
echo s:{join(a:params, '')}
endfunction
function! Echo(params)
" echo "Echo(".string(a:params).')'
let expr = 's:'.join(a:params, '')
" echo expr
exe 'echo '.expr
endfunction
let TBTWcommand = {
\ "name" : "TBT",
\ "arg_type" : "sub_commands",
\ "arguments" :
\ [
\ { "name" : "echo",
\ "arg_type" : "function",
\ "arguments" : "v1,v2",
\ "action": function("\<sid>echo") },
\ { "name" : "Echo",
\ "arg_type" : "function",
\ "arguments" : "v1,v2",
\ "action": function("Echo") },
\ { "name" : "help" },
\ { "name" : "add",
\ "arguments": function("s:ComplFilter"),
\ "action" : function("s:Add") }
\ ]
\ }
call lh#command#new(TBTWcommand)
nnoremap µ :call lh#command#new(TBTWcommand)<cr>
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,54 @@
"=============================================================================
" $Id: test-menu-map.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: tests/lh/test-menu-map.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 05th Dec 2006
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description: Tests for lh-vim-lib . lh#menu#
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
" let g:want_buffermenu_or_global_disable = 1
" let b:want_buffermenu_or_global_disable = 1
" echo lh#option#get("want_buffermenu_or_global_disable", 1, "bg")
" Call a command (':Command')
call lh#menu#make("nic", '42.50.340',
\ '&LH-Tests.&Menu-Make.Build Ta&gs', "<C-L>g",
\ '<buffer>',
\ ":echo 'TeXtags'<CR>")
" With '{' expanding to '{}××', or '{}' regarding the mode
call lh#menu#IVN_make('42.50.360.200',
\ '&LH-Tests.&Menu-Make.&Insert.\toto{}', ']toto',
\ '\\toto{',
\ '{%i\\toto<ESC>%l',
\ "viw]toto")
" Noremap for the visual maps
call lh#menu#IVN_make('42.50.360.200',
\ '&LH-Tests.&Menu-Make.&Insert.\titi{}', ']titi',
\ '\\titi{',
\ '<ESC>`>a}<ESC>`<i\\titi{<ESC>%l',
\ "viw]titi",
\ 0, 1, 0)
" Noremap for the insert and visual maps
call lh#menu#IVN_make('42.50.360.200',
\ '&LH-Tests.&Menu-Make.&Insert.<tata></tata>', ']tata',
\ '<tata></tata><esc>?<<CR>i',
\ '<ESC>`>a</tata><ESC>`<i<tata><ESC>/<\\/tata>/e1<CR>',
\ "viw]tata",
\ 1, 1, 0)
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,84 @@
"=============================================================================
" $Id: test-toggle-menu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: tests/lh/topological-sort.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 17th Apr 2007
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description:
" Tests for lh-vim-lib . lh#menu#def_toggle_item()
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
source autoload/lh/menu.vim
let Data = {
\ "variable": "bar",
\ "idx_crt_value": 1,
\ "values": [ 'a', 'b', 'c', 'd' ],
\ "menu": { "priority": '42.50.10', "name": '&LH-Tests.&TogMenu.&bar'}
\}
call lh#menu#def_toggle_item(Data)
let Data2 = {
\ "variable": "foo",
\ "idx_crt_value": 3,
\ "texts": [ 'un', 'deux', 'trois', 'quatre' ],
\ "values": [ 1, 2, 3, 4 ],
\ "menu": { "priority": '42.50.11', "name": '&LH-Tests.&TogMenu.&foo'}
\}
call lh#menu#def_toggle_item(Data2)
" No default
let Data3 = {
\ "variable": "nodef",
\ "texts": [ 'one', 'two', 'three', 'four' ],
\ "values": [ 1, 2, 3, 4 ],
\ "menu": { "priority": '42.50.12', "name": '&LH-Tests.&TogMenu.&nodef'}
\}
call lh#menu#def_toggle_item(Data3)
" No default
let g:def = 2
let Data4 = {
\ "variable": "def",
\ "values": [ 1, 2, 3, 4 ],
\ "menu": { "priority": '42.50.13', "name": '&LH-Tests.&TogMenu.&def'}
\}
call lh#menu#def_toggle_item(Data4)
" What follows does not work because we can't build an exportable FuncRef on top
" of a script local function
" finish
function! s:getSNR()
if !exists("s:SNR")
let s:SNR=matchstr(expand("<sfile>"), "<SNR>\\d\\+_\\zegetSNR$")
endif
return s:SNR
endfunction
function! s:Yes()
echomsg "Yes"
endfunction
function! s:No()
echomsg "No"
endfunction
let Data4 = {
\ "variable": "yesno",
\ "values": [ 1, 2 ],
\ "text": [ "No", "Yes" ],
\ "actions": [ function(s:getSNR()."No"), function(s:getSNR()."Yes") ],
\ "menu": { "priority": '42.50.20', "name": '&LH-Tests.&TogMenu.&yesno'}
\}
call lh#menu#def_toggle_item(Data4)

View file

@ -0,0 +1,120 @@
"=============================================================================
" $Id: topological-sort.vim 246 2010-09-19 22:40:58Z luc.hermitte $
" File: tests/lh/topological-sort.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 2.2.1
" Created: 17th Apr 2008
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
"------------------------------------------------------------------------
" Description: «description»
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
UTSuite [lh-vim-lib] topological sort
" Fully defineds DAGs {{{1
" A Direct Acyclic Graph {{{2
let s:dag1 = {}
let s:dag1[7] = [11, 8]
let s:dag1[5] = [11]
let s:dag1[3] = [8, 10]
let s:dag1[11] = [2, 9, 10]
let s:dag1[8] = [9]
" A Direct Cyclic Graph {{{2
let s:dcg1 = deepcopy(s:dag1)
let s:dcg1[9] = [11]
" Check routine: are the elements correctly sorted? {{{2
function! s:DoTestOrder(elements)
Assert! len(a:elements) == 8
Assert index(a:elements, 7) < index(a:elements, 11)
Assert index(a:elements, 7) < index(a:elements, 8)
Assert index(a:elements, 5) < index(a:elements, 11)
Assert index(a:elements, 3) < index(a:elements, 8)
Assert index(a:elements, 3) < index(a:elements, 10)
Assert index(a:elements, 11) < index(a:elements, 2)
Assert index(a:elements, 11) < index(a:elements, 9)
Assert index(a:elements, 11) < index(a:elements, 10)
Assert index(a:elements, 8) < index(a:elements, 9)
endfunction
" Test DAG1 {{{2
function! s:TestDAG_depth()
let res = lh#graph#tsort#depth(s:dag1, [3, 5,7])
call s:DoTestOrder(res)
echo "D(s:dag1)=".string(res)
endfunction
function! s:TestDAG_breadth()
let res = lh#graph#tsort#breadth(s:dag1, [3, 5,7])
call s:DoTestOrder(res)
echo "B(s:dag1)=".string(res)
endfunction
" Test DCG1 {{{2
function! s:TestDCG_depth()
let expr = 'lh#graph#tsort#depth('.string(s:dcg1).', [3, 5,7])'
Assert should#throw(expr, 'Tsort: cyclic graph detected')
endfunction
function! s:TestDCG_breadth()
let expr = 'lh#graph#tsort#breadth('.string(s:dcg1).', [3, 5,7])'
Assert should#throw(expr, 'Tsort: cyclic graph detected')
endfunction
" Lazzy Evaluated DAGs {{{1
" Emulated lazzyness {{{2
" The time-consumings evaluation function
let s:called = 0
function! Fetch(node)
let s:called += 1
return has_key(s:dag1, a:node) ? (s:dag1[a:node]) : []
endfunction
" Test Fetch on a DAG {{{2
function! s:TestDAG_fetch()
let s:called = 0
let res = lh#graph#tsort#depth(function('Fetch'), [3,5,7])
call s:DoTestOrder(res)
echo "D(fetch)=".string(res)
echo "Fetch has been evaluated ".s:called." times / ".len(res)
Assert s:called == len(res)
endfunction
" Setup/Teardown functions {{{1
" display the test name before each assertion
function! s:Setup()
if exists('g:UT_print_test')
let s:old_print_test = g:UT_print_test
endif
let g:UT_print_test = 1
endfunction
function! s:Teardown()
if exists('s:old_print_test')
let g:UT_print_test = s:old_print_test
unlet s:old_print_test
else
unlet g:UT_print_test
endif
endfunction
" }}}1
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,16 @@
--------------------
UT v0.0.3
--------------------
UT is a Unit Testing Framework for Vim
Audience : Vim script maintainers
Requirements : Vim 7, lh-vim-lib v2.2.0 ;
takes advantage of BuildtoolsWrappers if installed.
Required by : Only lh-vim
Maintainer : Luc Hermitte
License : GPL 2 (see http://www.gnu.org/licenses/gpl.txt)
More Help At : http://code.google.com/p/lh-vim/wiki/UT
Vim script#???: http://www.vim.org/scripts/script.php?script_id=???
Repository :
svn checkout http://lh-vim.googlecode.com/svn/UT/trunk UT

View file

@ -0,0 +1,442 @@
"=============================================================================
" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
" File: autoload/lh/UT.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
" Version: 0.0.3
" Created: 11th Feb 2009
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
"------------------------------------------------------------------------
" Description: Yet Another Unit Testing Framework for Vim
"
"------------------------------------------------------------------------
" Installation:
" Drop this file into {rtp}/autoload/lh/
" History:
" Strongly inspired by Tom Link's tAssert plugin: all its functions are
" compatible with this framework.
"
" Features:
" - Assertion failures are reported in the quickfix window
" - Assertion syntax is simple, check Tom Link's suite, it's the same
" - Supports banged :Assert! to stop processing a given test on failed
" assertions
" - All the s:Test* functions of a suite are executed (almost) independently
" (i.e., a critical :Assert! failure will stop the Test of the function, and
" lh#UT will proceed to the next s:Test function
" - Lightweight and simple to use: there is only one command defined, all the
" other definitions are kept in an autoload plugin.
" - A suite == a file
" - Several s:TestXxx() per suite
" - +optional s:Setup(), s:Teardown()
" - Supports :Comment's ; :Comment takes an expression to evaluate
" - s:LocalFunctions(), s:variables, and l:variables are supported
" - Takes advantage of BuildToolsWrapper's :Copen command if installed
" - Count successful tests (and not successful assertions)
" - Short-cuts to run the Unit Tests associated to a given vim script
" Relies on: Let-Modeline/local_vimrc/Project to set g:UTfiles (space
" separated list of glob-able paths), and on lh-vim-lib#path
" - Command to exclude, or specify the tests to play => UTPlay, UTIgnore
" - Option g:UT_print_test to display, on assertion failure, the current test
" name with the assertion failed.
"
" TODO:
" - Always execute s:Teardown() -- move its call to a :finally bloc
" - Test in UTF-8 (because of <SNR>_ injection)
" - test under windows (where paths have spaces, etc)
" - What about s:/SNR pollution ? The tmpfile is reused, and there is no
" guaranty a script will clean its own place
" - add &efm for viml errors like the one produced by :Assert 0 + [0]
" and take into account the offset introduced by lines injected at the top of
" the file
" - simplify s:errors functions
" - merge with Tom Link tAssert plugin? (the UI is quite different)
" - :AssertEquals that shows the name of both expressions and their values as
" well -- a correct distinction of both parameters will be tricky with
" regexes ; using functions will loose either the name, or the value in case
" of local/script variables use ; we need macros /à la C/...
" - Support Embedded comments like for instance:
" Assert 1 == 1 " 1 must value 1
" - Ways to test buffers produced
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
"------------------------------------------------------------------------
" # Debug {{{2
function! lh#UT#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr, ...)
let lvl = a:0>0 ? a:1 : 1
if exists('s:verbose') && s:verbose >= lvl
echomsg a:expr
endif
endfunction
function! lh#UT#debug(expr)
return eval(a:expr)
endfunction
"------------------------------------------------------------------------
" # Internal functions {{{2
"------------------------------------------------------------------------
" Sourcing a script doesn't imply a new entry with its name in :scriptnames
" As a consequence, the easiest thing to do is to reuse the same file over and
" over in a given vim session.
" This approach should be fine as long as there are less than 26 VimL testing vim
" sessions opened simultaneously.
let s:tempfile = tempname()
"------------------------------------------------------------------------
" s:errors
let s:errors = {
\ 'qf' : [],
\ 'crt_suite' : {},
\ 'nb_asserts' : 0,
\ 'nb_successful_asserts' : 0,
\ 'nb_success' : 0,
\ 'suites' : []
\ }
function! s:errors.clear() dict
let self.qf = []
let self.nb_asserts = 0
let self.nb_successful_asserts = 0
let self.nb_success = 0
let self.nb_tests = 0
let self.suites = []
let self.crt_suite = {}
endfunction
function! s:errors.display() dict
let g:errors = self.qf
cexpr self.qf
" Open the quickfix window
if exists(':Copen')
" Defined in lh-BTW, make the windows as big as the number of errors, not
" opened if there is no error
Copen
else
copen
endif
endfunction
function! s:errors.set_current_SNR(SNR)
let self.crt_suite.snr = a:SNR
endfunction
function! s:errors.get_current_SNR()
return self.crt_suite.snr
endfunction
function! s:errors.add(FILE, LINE, message) dict
let msg = a:FILE.':'.a:LINE.':'
if lh#option#get('UT_print_test', 0, 'g') && has_key(s:errors, 'crt_test')
let msg .= '['. s:errors.crt_test.name .'] '
endif
let msg.= a:message
call add(self.qf, msg)
endfunction
function! s:errors.add_test(test_name) dict
call self.add_test(a:test_name)
endfunction
function! s:errors.set_test_failed() dict
if has_key(self, 'crt_test')
let self.crt_test.failed = 1
endif
endfunction
"------------------------------------------------------------------------
" Tests wrapper functions
function! s:RunOneTest(file) dict
try
let s:errors.crt_test = self
if has_key(s:errors.crt_suite, 'setup')
let F = function(s:errors.get_current_SNR().'Setup')
call F()
endif
let F = function(s:errors.get_current_SNR(). self.name)
call F()
if has_key(s:errors.crt_suite, 'teardown')
let F = function(s:errors.get_current_SNR().'Teardown')
call F()
endif
catch /Assert: abort/
call s:errors.add(a:file,
\ matchstr(v:exception, '.*(\zs\d\+\ze)'),
\ 'Test <'. self.name .'> execution aborted on critical assertion failure')
catch /.*/
let throwpoint = substitute(v:throwpoint, escape(s:tempfile, '.\'), a:file, 'g')
let msg = throwpoint . ': '.v:exception
call s:errors.add(a:file, 0, msg)
finally
unlet s:errors.crt_test
endtry
endfunction
function! s:AddTest(test_name) dict
let test = {
\ 'name' : a:test_name,
\ 'run' : function('s:RunOneTest'),
\ 'failed' : 0
\ }
call add(self.tests, test)
endfunction
"------------------------------------------------------------------------
" Suites wrapper functions
function! s:ConcludeSuite() dict
call s:errors.add(self.file,0, 'SUITE<'. self.name.'> '. s:errors.nb_success .'/'. s:errors.nb_tests . ' tests successfully executed.')
" call add(s:errors.qf, 'SUITE<'. self.name.'> '. s:rrors.nb_success .'/'. s:errors.nb_tests . ' tests successfully executed.')
endfunction
function! s:PlayTests(...) dict
call s:Verbose('Execute tests: '.join(a:000, ', '))
call filter(self.tests, 'index(a:000, v:val.name) >= 0')
call s:Verbose('Keeping tests: '.join(self.tests, ', '))
endfunction
function! s:IgnoreTests(...) dict
call s:Verbose('Ignoring tests: '.join(a:000, ', '))
call filter(self.tests, 'index(a:000, v:val.name) < 0')
call s:Verbose('Keeping tests: '.join(self.tests, ', '))
endfunction
function! s:errors.new_suite(file) dict
let suite = {
\ 'scriptname' : s:tempfile,
\ 'file' : a:file,
\ 'tests' : [],
\ 'snr' : '',
\ 'add_test' : function('s:AddTest'),
\ 'conclude' : function('s:ConcludeSuite'),
\ 'play' : function('s:PlayTests'),
\ 'ignore' : function('s:IgnoreTests'),
\ 'nb_tests_failed' : 0
\ }
call add(self.suites, suite)
let self.crt_suite = suite
return suite
endfunction
function! s:errors.set_suite(suite_name) dict
let a = s:Decode(a:suite_name)
call s:Verbose('SUITE <- '. a.expr, 1)
call s:Verbose('SUITE NAME: '. a:suite_name, 2)
" call self.add(a.file, a.line, 'SUITE <'. a.expr .'>')
call self.add(a.file,0, 'SUITE <'. a.expr .'>')
let self.crt_suite.name = a.expr
" let self.crt_suite.file = a.file
endfunction
"------------------------------------------------------------------------
function! s:Decode(expression)
let filename = s:errors.crt_suite.file
let expr = a:expression
let line = matchstr(expr, '^\d\+')
" echo filename.':'.line
let expr = strpart(expr, strlen(line)+1)
let res = { 'file':filename, 'line':line, 'expr':expr}
call s:Verbose('decode:'. (res.file) .':'. (res.line) .':'. (res.expr), 2)
return res
endfunction
function! lh#UT#callback_decode(expression)
return s:Decode(a:expression)
endfunction
"------------------------------------------------------------------------
let s:k_commands = '\%(Assert\|UTSuite\|Comment\)'
let s:k_local_evaluate = [
\ 'command! -bang -nargs=1 Assert '.
\ 'let s:a = lh#UT#callback_decode(<q-args>) |'.
\ 'let s:ok = !empty(eval(s:a.expr)) |'.
\ 'exe "UTAssert<bang> ".s:ok." ".(<f-args>)|'
\]
let s:k_getSNR = [
\ 'function! s:getSNR()',
\ ' if !exists("s:SNR")',
\ ' let s:SNR=matchstr(expand("<sfile>"), "<SNR>\\d\\+_\\zegetSNR$")',
\ ' endif',
\ ' return s:SNR',
\ 'endfunction',
\ 'call lh#UT#callback_set_SNR(s:getSNR())',
\ ''
\ ]
function! s:PrepareFile(file)
if !filereadable(a:file)
call s:errors.add('-', 0, a:file . " can not be read")
return
endif
let file = escape(a:file, ' \')
let lines = readfile(a:file)
let need_to_know_SNR = 0
let suite = s:errors.new_suite(a:file)
let no = 0
let last_line = len(lines)
while no < last_line
if lines[no] =~ '^\s*'.s:k_commands.'\>'
let lines[no] = substitute(lines[no], '^\s*'.s:k_commands.'!\= \zs', (no+1).' ', '')
elseif lines[no] =~ '^\s*function!\=\s\+s:Test'
let test_name = matchstr(lines[no], '^\s*function!\=\s\+s:\zsTest\S\{-}\ze(')
call suite.add_test(test_name)
elseif lines[no] =~ '^\s*function!\=\s\+s:Teardown'
let suite.teardown = 1
elseif lines[no] =~ '^\s*function!\=\s\+s:Setup'
let suite.setup = 1
endif
if lines[no] =~ '^\s*function!\=\s\+s:'
let need_to_know_SNR = 1
endif
let no += 1
endwhile
" Inject s:getSNR() in the script if there is a s:Function in the Test script
if need_to_know_SNR
call extend(lines, s:k_getSNR, 0)
let last_line += len(s:k_getSNR)
endif
" Inject local evualation of expressions in the script
" => takes care of s:variables, s:Functions(), and l:variables
call extend(lines, s:k_local_evaluate, 0)
call writefile(lines, suite.scriptname)
let g:lines=lines
endfunction
function! s:RunOneFile(file)
try
call s:PrepareFile(a:file)
exe 'source '.s:tempfile
let s:errors.nb_tests = len(s:errors.crt_suite.tests)
if !empty(s:errors.crt_suite.tests)
call s:Verbose('Executing tests: '.join(s:errors.crt_suite.tests, ', '))
for test in s:errors.crt_suite.tests
call test.run(a:file)
let s:errors.nb_success += 1 - test.failed
endfor
endif
catch /Assert: abort/
call s:errors.add(a:file,
\ matchstr(v:exception, '.*(\zs\d\+\ze)'),
\ 'Suite <'. s:errors.crt_suite .'> execution aborted on critical assertion failure')
catch /.*/
let throwpoint = substitute(v:throwpoint, escape(s:tempfile, '.\'), a:file, 'g')
let msg = throwpoint . ': '.v:exception
call s:errors.add(a:file, 0, msg)
finally
call s:errors.crt_suite.conclude()
" Never! the name must not be used by other Vim sessions
" call delete(s:tempfile)
endtry
endfunction
"------------------------------------------------------------------------
function! s:StripResultAndDecode(expr)
" Function needed because of an odd degenerescence of vim: commands
" eventually loose their '\'
return s:Decode(matchstr(a:expr, '^\d\+\s\+\zs.*'))
endfunction
function! s:GetResult(expr)
" Function needed because of an odd degenerescence of vim: commands
" eventually loose their '\'
return matchstr(a:expr, '^\d\+\ze\s\+.*')
endfunction
function! s:DefineCommands()
" NB: variables are already interpreted, make it a function
" command! -nargs=1 Assert call s:Assert(<q-args>)
command! -bang -nargs=1 UTAssert
\ let s:a = s:StripResultAndDecode(<q-args>) |
\ let s:ok = s:GetResult(<q-args>) |
\ let s:errors.nb_asserts += 1 |
\ if ! s:ok |
\ call s:errors.set_test_failed() |
\ call s:errors.add(s:a.file, s:a.line, 'assertion failed: '.s:a.expr) |
\ if '<bang>' == '!' |
\ throw "Assert: abort (".s:a.line.")" |
\ endif |
\ else |
\ let s:errors.nb_successful_asserts += 1 |
\ endif
command! -nargs=1 Comment
\ let s:a = s:Decode(<q-args>) |
\ call s:errors.add(s:a.file, s:a.line, eval(s:a.expr))
command! -nargs=1 UTSuite call s:errors.set_suite(<q-args>)
command! -nargs=+ UTPlay call s:errors.crt_suite.play(<f-args>)
command! -nargs=+ UTIgnore call s:errors.crt_suite.ignore(<f-args>)
endfunction
function! s:UnDefineCommands()
silent! delcommand Assert
silent! delcommand UTAssert
silent! command! -nargs=* UTSuite :echoerr "Use :UTRun and not :source on this script"<bar>finish
silent! delcommand UTPlay
silent! delcommand UTIgnore
endfunction
"------------------------------------------------------------------------
" # callbacks {{{2
function! lh#UT#callback_set_SNR(SNR)
call s:errors.set_current_SNR(a:SNR)
endfunction
" # Main function {{{2
function! lh#UT#run(bang,...)
" 1- clear the errors table
let must_keep = a:bang == "!"
if ! must_keep
call s:errors.clear()
endif
try
" 2- define commands
call s:DefineCommands()
" 3- run every test
let rtp = '.,'.&rtp
let files = []
for file in a:000
let lFile = lh#path#glob_as_list(rtp, file)
if len(lFile) > 0
call add(files, lFile[0])
endif
endfor
for file in files
call s:RunOneFile(file)
endfor
finally
call s:UnDefineCommands()
call s:errors.display()
endtry
" 3- Open the quickfix
endfunction
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:
" VIM: let g:UTfiles='tests/lh/UT*.vim'

View file

@ -0,0 +1,68 @@
"=============================================================================
" $Id: be.vim 193 2010-05-17 23:10:03Z luc.hermitte $
" File: autoload/should/be.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://hermitte.free.fr/vim/>
" Version: 0.0.3
" Created: 23rd Feb 2009
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
"------------------------------------------------------------------------
" Description:
" UT & tAssert API
"
"------------------------------------------------------------------------
" Installation:
" Drop this file into {rtp}/autoload/should
" History:
"
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
function! should#be#verbose(level)
let s:verbose = a:level
endfunction
function! s:Verbose(expr)
if exists('s:verbose') && s:verbose
echomsg a:expr
endif
endfunction
function! should#be#debug(expr)
return eval(a:expr)
endfunction
" # Convinience functions for tAssert/UT {{{2
function! should#be#list(var)
return type(a:var) == type([])
endfunction
function! should#be#number(var)
return type(a:var) == type(42)
endfunction
function! should#be#string(var)
return type(a:var) == type('')
endfunction
function! should#be#dict(var)
return type(a:var) == type({})
endfunction
function! should#be#float(var)
return type(a:var) == type(0.1)
endfunction
function! should#be#funcref(var)
return type(a:var) == type(function('exists'))
endfunction
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,165 @@
*UT.txt* Unit Testing Framework for Vim (v0.0.3)
For Vim version 7+. Last change: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
By Luc Hermitte
hermitte {at} free {dot} fr
------------------------------------------------------------------------------
CONTENTS *UT-contents* {{{1
|UT-presentation| Presentation
|UT-usage| Usage
|UT-API| UT API
|UT-examples| Examples
|UT-todo| Bugs to fix and futur enhancements to come
|UT-design| Design choices
|UT-others| Other tests related plugins for vim
|add-local-help| Instructions on installing this file
------------------------------------------------------------------------------
PRESENTATION *UT-presentation* {{{1
UT is another Test Unit Framework for Vim, which main particularity is to fill
the |quickfix| window with the assertion failures.
Features~
- Assertion failures are reported in the |quickfix| window
- Assertion syntax is simple, check Tom Link's suite, it's the same
- Supports banged ":Assert!" to stop processing a given test on failed
assertions
- All the |s:Test()| functions of a suite are executed (almost)
independently (i.e., a critical ":Assert!" failure will stop the Test of
the function, and |lh#UT| will proceed to the next |s:Test()| function
- Lightweight and simple to use: there is only one command defined, all the
other definitions are kept in an autoload plugin.
- A suite == a file
- Several |s:Test()| functions per suite
- +optional |s:Setup()|, |s:Teardown()|
- Supports |:Comments|
- |local-function|s, |script-variable|s, and |local-variable|s are supported
- Takes advantage of |BuildToolsWrapper|'s |:Copen| command if installed
- Counts successful tests and not successful assertions
- Short-cuts to run the Unit Tests associated to a given vim script; Relies
on: |Let-Modeline|, |local_vimrc|/|project.vim| to set |g:UTfiles| (space
separated list of glob-able paths), and on |lhvl#path|.
- Command to exclude, or specify the tests to play => |:UTPlay|, |UTIgnore|
Requirements~
This suite requires Vim 7.1 and |lh-vim-lib| v2.2.0+.
------------------------------------------------------------------------------
USAGE *UT-usage* {{{1
First, create a new vim script, it will be a Unit Testing Suite.
*:UTSuite*
One of the first lines must contain >
UTSuite Some intelligible name for the suite
<
*:Assert*
Then you are free to directly assert anything you wish as long as it is a
valid vim |expression|, e.g. >
Assert 1 > 2
Assert 1 > 0
Assert s:foo > s:Bar(g:var + 28) / strlen("foobar")
or to define as many independent tests as you wish.
*:Comment*
Comments may be added to the |quickfix| report thanks to the |:Comment|
fake command.
*s:Test()*
A test is a function with a name starting with |s:Test|. Even if a test
critically fails, the next test will be executed, e.g. >
function s:Test1()
let var = SomeFucntion()
Assert! type(var) == type(0)
Assert var < 42
Assert! var > 0
" Some other code that won't be executed if the previous assertion failed
let i = var / 42.0
Comment This comment may never be displayed if {var} is negative or not a number
endfunction
function s:Test2()
Assert s:what != Ever()
endfunction
<
*s:Setup()* *s:Teardown()*
If you wish to see a set-up function executed before each test, define the
|s:Setup()| function.
If you wish to see a clean-up function executed after each test, define the
|s:Teardown()| function.
*:UTRun*
Finally run |:UTRun| on your test script (filename), and ... debug your failed
assertions from the |quickfix| window.
------------------------------------------------------------------------------
UT API *UT-API* {{{1
*should#be#dict()* returns whether the parameter is a |Dictionary|
*should#be#float()* returns whether the parameter is a |float|
*should#be#funcref()* returns whether the parameter is a |Funcref|
*should#be#list()* returns whether the parameter is a |List|
*should#be#number()* returns whether the parameter is a |expr-number|
*should#be#string()* returns whether the parameter is a |expr-string|
------------------------------------------------------------------------------
EXAMPLES *UT-examples* {{{1
See:
- {rtp}/tests/lh/UT.vim tests/lh/UT.vim for a classical test,
- {rtp}/tests/lh/UT-fixtures.vim tests/lh/UT-fixtures.vim for a test with
fixtures.
------------------------------------------------------------------------------
TO DO *UT-todo* {{{1
- Add |'efm'| for VimL errors like the one produced by >
:Assert 0 + [0]
- Check UT works fine under windows (where paths have spaces, etc), and on
UTF-8 files
- Simplify "s:errors" functions
- Merge with Tom Link's tAssert plugin? (the UI is quite different)
- |:AssertEquals| that shows the name of both expressions and their values as
well -- a correct distinction of both parameters will be tricky with regexes
; using functions will loose either the name, or the value in case of
local/script variables use ; we need macros /à la C/...
- Support Embedded comments like for instance: >
Assert 1 == 1 " 1 must value 1
- Ways to test buffers produced
- Always execute |s:Teardown()| -- move its call to a |:finally| bloc
- Find a way to prevent the potential script scope pollution
------------------------------------------------------------------------------
DESIGN CHOICES *UT-design* {{{1
The assertions supported by this plugin are expected to be made in a Unit
Testing file, they are not to be used in regular VimL scripts as a /Design by
Contract/ tool. Check Thomas Link's plugin, it is much more suited for that
kind of assertions.
In order to be able to produce the |quickfix| entries, the plugin first parses
the Unit Test file to complete all |:Assert| occurrences with extra
information about the line number where the assertion is made.
------------------------------------------------------------------------------
OTHER TESTS RELATED PLUGINS FOR VIM *UT-others* {{{1
You may also want to have a look at:
- Tom Link's |tAssert| plugin
http://www.vim.org/scripts/script.php?script_id=1730
- Staale Flock's |vimUnit| plugin
http://www.vim.org/scripts/script.php?script_id=1125
- Meikel Brandmeyer's |vimTAP| plugin
http://www.vim.org/scripts/script.php?script_id=2213
------------------------------------------------------------------------------
© Luc Hermitte, 2010, http://code.google.com/p/lh-vim/
$Id: UT.txt 193 2010-05-17 23:10:03Z luc.hermitte $
VIM: let b:VS_language = 'american'
vim:ts=8:sw=4:tw=80:fo=tcq2:isk=!-~,^*,^\|,^\":ft=help:fdm=marker:

View file

@ -0,0 +1,67 @@
"=============================================================================
" $Id: vim_UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
" File: ftplugin/vim/vim_UT.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
let s:k_version = 003
" Version: 0.0.3
" Created: 20th Feb 2009
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
"------------------------------------------------------------------------
" Description: Yet Another Unit Testing Framework for Vim
" - Defines <F7> as :UTRun {targets=g:UTfiles}
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
" Buffer-local Definitions {{{1
" Avoid local reinclusion {{{2
if &cp || (exists("b:loaded_ftplug_vim_UT") && !exists('g:force_reload_ftplug_vim_UT'))
finish
endif
let b:loaded_ftplug_vim_UT = s:k_version
let s:cpo_save=&cpo
set cpo&vim
" Avoid local reinclusion }}}2
"------------------------------------------------------------------------
" Local mappings {{{2
nnoremap <buffer> <silent> <Plug>UTMake :call <sid>UTMake()<cr>
let s:key = lh#option#get('UTMake_key', '<F7>')
exe 'imap <buffer> '.s:key.' <c-\><c-n><Plug>UTMake'
exe 'vmap <buffer> '.s:key.' <c-\><c-n><Plug>UTMake'
exe 'nmap <buffer> '.s:key.' <Plug>UTMake'
"=============================================================================
" Global Definitions {{{1
" Avoid global reinclusion {{{2
if &cp || (exists("g:loaded_ftplug_vim_UT") && !exists('g:force_reload_ftplug_vim_UT'))
let &cpo=s:cpo_save
finish
endif
let g:loaded_ftplug_vim_UT = s:k_version
" Avoid global reinclusion }}}2
"------------------------------------------------------------------------
" Functions {{{2
function! s:UTMake()
let files = lh#option#get('UTfiles', '%')
echo 'update|source '.expand('%').'|UTRun '.files
update
so%
exe 'UTRun '.files
endfunction
" Functions }}}2
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:
" VIM: let g:UTfiles='tests/lh/UT*.vim'

View file

@ -0,0 +1,32 @@
"=============================================================================
" $Id: mk-UT.vim 194 2010-05-17 23:26:14Z luc.hermitte $
" File: mk-UT.vim
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://hermitte.free.fr/vim/>
" Version: 0.0.3
let s:version = '0.0.3'
" Created: 19th Feb 2009
" Last Update: $Date: 2010-05-17 19:26:14 -0400 (Mon, 17 May 2010) $
"------------------------------------------------------------------------
cd <sfile>:p:h
try
let save_rtp = &rtp
let &rtp = expand('<sfile>:p:h:h').','.&rtp
exe '22,$MkVimball! UT-'.s:version
set modifiable
set buftype=
finally
let &rtp = save_rtp
endtry
finish
UT.README
autoload/lh/UT.vim
autoload/should.vim
autoload/should/be.vim
doc/UT.txt
ftplugin/vim/vim_UT.vim
mkVba/mk-UT.vim
plugin/UT.vim
tests/lh/UT-fixtures.vim
tests/lh/UT.vim
tests/lh/assert.vim

View file

@ -0,0 +1,48 @@
"=============================================================================
" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
" File: plugin/UT.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://code.google.com/p/lh-vim/>
let s:k_version = 003
" Version: 0.0.3
" Created: 11th Feb 2009
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
"------------------------------------------------------------------------
" Description: Yet Another Unit Testing Framework for Vim
"
"------------------------------------------------------------------------
" Installation:
" Drop the file into {rtp}/plugin/lh/
" History:
" Strongly inspired by Tom Link's tAssert
" TODO: «missing features»
" }}}1
"=============================================================================
" Avoid global reinclusion {{{1
if &cp || (exists("g:loaded_UT") && !exists('g:force_reload_UT'))
finish
endif
let g:loaded_UT = s:k_version
let s:cpo_save=&cpo
set cpo&vim
" Avoid global reinclusion }}}1
"------------------------------------------------------------------------
" Commands and Mappings {{{1
" Real commands (used to call UT files)
"command! UTRun {filenames}
command! -bang -nargs=+ -complete=file UTRun :call lh#UT#run("<bang>",<f-args>)
" Fake commands (used in UT files)
"command UTSuite {expression} [#{comments}]
command! -nargs=* UTSuite :echoerr "Use :UTRun and not :source on this script"<bar>finish
"command Assert {expression} [#{comments}]
" Commands and Mappings }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:
" VIM: let g:UTfiles='tests/lh/UT*.vim'

View file

@ -0,0 +1,58 @@
"=============================================================================
" $Id: UT-fixtures.vim 193 2010-05-17 23:10:03Z luc.hermitte $
" File: tests/lh/UT-fixtures.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://hermitte.free.fr/vim/>
" Version: 0.0.1
" Created: 11th Feb 2009
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
"------------------------------------------------------------------------
" Description: UnitTests for the UT plugin.
" - Test fixtures
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
UTSuite [lh#UT] Testing fixtures
let s:v1 = 0
let s:v2 = 0
function! s:Setup()
Assert! exists('s:v1')
Assert! exists('s:v2')
let s:v1 += 1
let s:v2 += 1
endfunction
function! s:Teardown()
let s:v1 = 0
endfunction
function! s:TestSetup()
Comment "First test weither s:v1 and g:v2 are set to 1"
" Assert0 s:v1 == 1
Assert s:v1 == 1
Assert s:v2 == 1
endfunction
function! s:TestTeardown()
Comment "Second test weither only s:v1 is incremented, while g:v2 is set to 1"
Assert s:v1 == 1
Assert s:v2 == 2
endfunction
" UTPlay TestTeardown
UTIgnore TestTeardown
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,73 @@
"=============================================================================
" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
" File: tests/lh/UT.vim {{{1
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
" <URL:http://hermitte.free.fr/vim/>
" Version: 0.0.1
" Created: 11th Feb 2009
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
"------------------------------------------------------------------------
" Description: UnitTests for the UT plugin.
" - Tests global assertions
" - Tests assertions definied in tests (functions s:Test)
"
"------------------------------------------------------------------------
" Installation: «install details»
" History: «history»
" TODO: «missing features»
" }}}1
"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
UTSuite [lh#UT] Testing global and local assertions
Assert 1 == 1
Assert 1 != 42
Assert 1 < 20
Assert 1 > 20
let st = "string"
Assert st =~ 'str'
Assert st !~ 'str'
Assert st == 'str'
Assert st != 'str'
Assert st == 0
" Assert 0 + [0]
function! s:One()
return 1
endfunction
Assert s:One() == 1
"------------------------------------------------------------------------
function! s:TestOK()
Comment "TestOK"
Assert! 1 == 1
Assert 1 == 1
Assert repeat('1', 5) == '11111'
Assert! repeat('1', 5) == '11111'
endfunction
"------------------------------------------------------------------------
function! s:TestCriticalNOK()
Comment "TestCriticalNOK"
Assert! 1 == 0
Assert repeat('1', 5) == '1111'
endfunction
"------------------------------------------------------------------------
function! s:TestNOK()
Comment "TestNOK"
Assert 0 == 1
Assert repeat('1', 5) == '1111'
endfunction
function! s:Foo()
endfunction
"------------------------------------------------------------------------
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:

View file

@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -e
if [[ $# -eq 0 ]]
then
TESTS="`ls *.vim | tr "\n" ' '`"
else
IFS=' '
TESTS="$*"
fi
vim -u vimrc_test -c ":UTRun $TESTS"

View file

@ -0,0 +1,64 @@
UTSuite [Gundo] Testing Toggling
function! s:Setup()"{{{
exec 'edit test'
call g:Goto('test')
setlocal buftype=nofile
endfunction"}}}
function! s:Teardown()"{{{
if bufwinnr(bufnr('__Gundo__')) != -1
exec bufwinnr(bufnr('__Gundo__')) . 'wincmd w'
quit
endif
if bufwinnr(bufnr('__Gundo_Preview__')) != -1
exec bufwinnr(bufnr('__Gundo_Preview__')) . 'wincmd w'
quit
endif
if bufnr('__Gundo__') != -1
exec 'bwipeout ' . bufnr('__Gundo__')
endif
if bufnr('__Gundo_Preview__') != -1
exec 'bwipeout ' . bufnr('__Gundo_Preview__')
endif
if bufnr('test') != -1
exec 'bwipeout ' . bufnr('test')
endif
if bufnr('test2') != -1
exec 'bwipeout ' . bufnr('test2')
endif
endfunction"}}}
function! s:TestToggleBasic()"{{{
call g:TypeLine("ONE")
call g:TypeLineDone("TWO")
GundoToggle
Assert g:Contains("o [0]")
Assert g:Contains("o [1]")
Assert g:Contains("@ [2]")
Assert !g:Contains("[3]")
endfunction"}}}
function! s:TestToggleBranches()"{{{
call g:TypeLineDone("ONE")
silent! undo
call g:TypeLineDone("TWO")
GundoToggle
" Make sure there is a branch next to state 2
call g:GotoLineContaining("[1]")
Assert g:CurrentLineContains("|")
" Make sure there is no branch next to states 0 and 2
call g:GotoLineContaining("[0]")
Assert !g:CurrentLineContains("|")
call g:GotoLineContaining("[2]")
Assert !g:CurrentLineContains("|")
" Make sure the branch point is directly above state 0
call g:GotoLineContaining("[0]")
call g:MoveUp()
Assert g:CurrentLineContains("|/")
endfunction"}}}

View file

@ -0,0 +1,150 @@
UTSuite [Gundo] Testing Movement
function! s:Setup()"{{{
exec 'edit test'
call g:Goto('test')
endfunction"}}}
function! s:Teardown()"{{{
if bufwinnr(bufnr('__Gundo__')) != -1
exec bufwinnr(bufnr('__Gundo__')) . 'wincmd w'
quit
endif
if bufwinnr(bufnr('__Gundo_Preview__')) != -1
exec bufwinnr(bufnr('__Gundo_Preview__')) . 'wincmd w'
quit
endif
if bufnr('__Gundo__') != -1
exec 'bwipeout! ' . bufnr('__Gundo__')
endif
if bufnr('__Gundo_Preview__') != -1
exec 'bwipeout! ' . bufnr('__Gundo_Preview__')
endif
if bufnr('test') != -1
exec 'bwipeout! ' . bufnr('test')
endif
if bufnr('test2') != -1
exec 'bwipeout! ' . bufnr('test2')
endif
endfunction"}}}
function! s:TestMovementBasic()"{{{
" Make three linear changes
call g:TypeLineDone("ONE")
call g:TypeLineDone("TWO")
call g:TypeLineDone("THREE")
" Open Gundo
GundoToggle
" Make sure we're on the newest/current state
Assert g:CurrentLineContains("[3]")
" Move down
normal j
Assert g:CurrentLineContains("[2]")
" Move down
normal j
Assert g:CurrentLineContains("[1]")
" Move down
normal j
Assert g:CurrentLineContains("[0]")
" Move up
normal k
Assert g:CurrentLineContains("[1]")
" Move up
normal k
Assert g:CurrentLineContains("[2]")
" Move up
normal k
Assert g:CurrentLineContains("[3]")
" Test arrow mappings
" Move down
exec "normal \<down>"
Assert g:CurrentLineContains("[2]")
" Move down
exec "normal \<down>"
Assert g:CurrentLineContains("[1]")
" Move down
exec "normal \<down>"
Assert g:CurrentLineContains("[0]")
" Move up
exec "normal \<up>"
Assert g:CurrentLineContains("[1]")
" Move up
exec "normal \<up>"
Assert g:CurrentLineContains("[2]")
" Move up
exec "normal \<up>"
Assert g:CurrentLineContains("[3]")
endfunction"}}}
function! s:TestMovementLinear()"{{{
" Make four changes:
"
" o [4]
" |
" | o [3]
" | |
" o | [2]
" |/
" o [1]
" |
" o [0] (original)
call g:TypeLineDone("ONE")
call g:TypeLineDone("TWO")
silent! undo
call g:TypeLineDone("THREE")
silent! undo 2
call g:TypeLineDone("FOUR")
" Open Gundo
GundoToggle
" Make sure we're on the newest/current state
Assert g:CurrentLineContains("[4]")
" Move down
normal j
Assert g:CurrentLineContains("[3]")
" Move down
normal j
Assert g:CurrentLineContains("[2]")
" Move down
normal j
Assert g:CurrentLineContains("[1]")
" Move down
normal j
Assert g:CurrentLineContains("[0]")
" Move up
normal k
Assert g:CurrentLineContains("[1]")
" Move up
normal k
Assert g:CurrentLineContains("[2]")
" Move up
normal k
Assert g:CurrentLineContains("[3]")
" Move up
normal k
Assert g:CurrentLineContains("[4]")
endfunction"}}}

View file

@ -0,0 +1,131 @@
UTSuite [Gundo] Testing Preview Pane
function! s:Setup()"{{{
exec 'edit test'
call g:Goto('test')
endfunction"}}}
function! s:Teardown()"{{{
if bufwinnr(bufnr('__Gundo__')) != -1
exec bufwinnr(bufnr('__Gundo__')) . 'wincmd w'
quit
endif
if bufwinnr(bufnr('__Gundo_Preview__')) != -1
exec bufwinnr(bufnr('__Gundo_Preview__')) . 'wincmd w'
quit
endif
if bufnr('__Gundo__') != -1
exec 'bwipeout! ' . bufnr('__Gundo__')
endif
if bufnr('__Gundo_Preview__') != -1
exec 'bwipeout! ' . bufnr('__Gundo_Preview__')
endif
if bufnr('test') != -1
exec 'bwipeout! ' . bufnr('test')
endif
if bufnr('test2') != -1
exec 'bwipeout! ' . bufnr('test2')
endif
endfunction"}}}
function! s:TestPreviewBasic()"{{{
" Make three linear changes, then a change that deletes the last line
call g:TypeLineDone("ONE")
call g:TypeLineDone("TWO")
call g:TypeLineDone("THREE")
normal k
normal dd
" Open Gundo
GundoToggle
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("THREE")
Assert g:CurrentLineContains("-THREE")
call g:Goto("__Gundo__")
normal j
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("THREE")
Assert g:CurrentLineContains("+THREE")
call g:Goto("__Gundo__")
normal j
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("TWO")
Assert g:CurrentLineContains("+TWO")
call g:Goto("__Gundo__")
normal j
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("ONE")
Assert g:CurrentLineContains("+ONE")
call g:Goto("__Gundo__")
normal k
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("TWO")
Assert g:CurrentLineContains("+TWO")
call g:Goto("__Gundo__")
normal k
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("THREE")
Assert g:CurrentLineContains("+THREE")
call g:Goto("__Gundo__")
normal k
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("THREE")
Assert g:CurrentLineContains("-THREE")
endfunction"}}}
function! s:TestPreviewLinear()"{{{
" Make four non-linear changes
"
" o [4]
" |
" | o [3]
" | |
" o | [2]
" |/
" o [1]
call g:TypeLineDone("ONE")
call g:TypeLineDone("TWO")
silent! undo
call g:TypeLineDone("THREE")
silent! undo 2
call g:TypeLineDone("FOUR")
" Open Gundo
GundoToggle
" Check state 4
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("FOUR")
Assert g:CurrentLineContains("+FOUR")
call g:GotoLineContaining("THREE")
Assert !g:CurrentLineContains("THREE")
" Check state 3
call g:Goto("__Gundo__")
normal j
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("THREE")
Assert g:CurrentLineContains("+THREE")
call g:GotoLineContaining("FOUR")
Assert !g:CurrentLineContains("FOUR")
call g:GotoLineContaining("TWO")
Assert !g:CurrentLineContains("TWO")
call g:GotoLineContaining("ONE")
Assert g:CurrentLineContains("ONE")
" Check state 2
call g:Goto("__Gundo__")
normal j
call g:Goto("__Gundo_Preview__")
call g:GotoLineContaining("TWO")
Assert g:CurrentLineContains("+TWO")
call g:GotoLineContaining("ONE")
Assert g:CurrentLineContains("ONE")
endfunction"}}}

View file

@ -0,0 +1,123 @@
UTSuite [Gundo] Testing Toggling
function! s:Setup()"{{{
exec 'edit test'
call g:Goto('test')
endfunction"}}}
function! s:Teardown()"{{{
if bufwinnr(bufnr('__Gundo__')) != -1
exec bufwinnr(bufnr('__Gundo__')) . 'wincmd w'
quit
endif
if bufwinnr(bufnr('__Gundo_Preview__')) != -1
exec bufwinnr(bufnr('__Gundo_Preview__')) . 'wincmd w'
quit
endif
if bufnr('__Gundo__') != -1
exec 'bwipeout ' . bufnr('__Gundo__')
endif
if bufnr('__Gundo_Preview__') != -1
exec 'bwipeout ' . bufnr('__Gundo_Preview__')
endif
if bufnr('test') != -1
exec 'bwipeout ' . bufnr('test')
endif
if bufnr('test2') != -1
exec 'bwipeout ' . bufnr('test2')
endif
endfunction"}}}
function! s:TestToggleBasic()"{{{
" Make sure we're starting from scratch.
Assert bufnr('__Gundo__') == -1
Assert bufnr('__Gundo_Preview__') == -1
Assert bufwinnr(bufnr('__Gundo__')) == -1
Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
" Open Gundo
GundoToggle
" Buffers and windows should exist.
Assert bufnr('__Gundo__') != -1
Assert bufnr('__Gundo_Preview__') != -1
Assert bufwinnr(bufnr('__Gundo__')) != -1
Assert bufwinnr(bufnr('__Gundo_Preview__')) != -1
" We should be in the Gundo pane.
Assert expand('%') == '__Gundo__'
" Close Gundo
GundoToggle
" Windows should have been closed, but buffers should remain.
Assert bufnr('__Gundo__') != -1
Assert bufnr('__Gundo_Preview__') != -1
Assert bufwinnr(bufnr('__Gundo__')) == -1
Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
endfunction"}}}
function! s:TestToggleWhenMoved()"{{{
" Make sure we're starting from scratch.
Assert bufnr('__Gundo__') == -1
Assert bufnr('__Gundo_Preview__') == -1
Assert bufwinnr(bufnr('__Gundo__')) == -1
Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
" Open Gundo
GundoToggle
call g:Goto('test')
Assert expand('%') == 'test'
" Close Gundo
GundoToggle
" Windows should have been closed, but buffers should remain.
Assert bufnr('__Gundo__') != -1
Assert bufnr('__Gundo_Preview__') != -1
Assert bufwinnr(bufnr('__Gundo__')) == -1
Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
" Open Gundo
GundoToggle
call g:Goto('__Gundo_Preview__')
Assert expand('%') == '__Gundo_Preview__'
" Close Gundo
GundoToggle
" Windows should have been closed, but buffers should remain.
Assert bufnr('__Gundo__') != -1
Assert bufnr('__Gundo_Preview__') != -1
Assert bufwinnr(bufnr('__Gundo__')) == -1
Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
endfunction"}}}
function! s:TestToggleReturnToTarget()"{{{
" Make sure we're starting from scratch.
Assert bufnr('__Gundo__') == -1
Assert bufnr('__Gundo_Preview__') == -1
Assert bufwinnr(bufnr('__Gundo__')) == -1
Assert bufwinnr(bufnr('__Gundo_Preview__')) == -1
exec 'new test2'
call g:Goto('test')
" Toggle Gundo
GundoToggle
GundoToggle
" We should be returned to test
Assert expand('%') == 'test'
" Move to test2
call g:Goto('test2')
" Toggle Gundo
GundoToggle
GundoToggle
" We should be returned to test2
Assert expand('%') == 'test2'
endfunction"}}}

View file

@ -0,0 +1 @@
../../bundled/lh-vim-lib/autoload/lh

View file

@ -0,0 +1,108 @@
" Vim color file
" Maintainer: Hans Fugal <hans@fugal.net>
" Last Change: $Date: 2004/06/13 19:30:30 $
" Last Change: $Date: 2004/06/13 19:30:30 $
" URL: http://hans.fugal.net/vim/colors/desert.vim
" Version: $Id: desert.vim,v 1.1 2004/06/13 19:30:30 vimboss Exp $
" cool help screens
" :he group-name
" :he highlight-groups
" :he cterm-colors
set background=dark
if version > 580
" no guarantees for version 5.8 and below, but this makes it stop
" complaining
hi clear
if exists("syntax_on")
syntax reset
endif
endif
let g:colors_name="desert"
hi Normal guifg=White guibg=grey20
" highlight groups
hi Cursor guibg=khaki guifg=slategrey
"hi CursorIM
"hi Directory
"hi DiffAdd
"hi DiffChange
"hi DiffDelete
"hi DiffText
"hi ErrorMsg
hi VertSplit guibg=#c2bfa5 guifg=grey50 gui=none
hi Folded guibg=grey30 guifg=gold
hi FoldColumn guibg=grey30 guifg=tan
hi IncSearch guifg=slategrey guibg=khaki
"hi LineNr
hi ModeMsg guifg=goldenrod
hi MoreMsg guifg=SeaGreen
hi NonText guifg=LightBlue guibg=grey30
hi Question guifg=springgreen
hi Search guibg=peru guifg=wheat
hi SpecialKey guifg=yellowgreen
hi StatusLine guibg=#c2bfa5 guifg=black gui=none
hi StatusLineNC guibg=#c2bfa5 guifg=grey50 gui=none
hi Title guifg=indianred
hi Visual gui=none guifg=khaki guibg=olivedrab
"hi VisualNOS
hi WarningMsg guifg=salmon
"hi WildMenu
"hi Menu
"hi Scrollbar
"hi Tooltip
" syntax highlighting groups
hi Comment guifg=SkyBlue
hi Constant guifg=#ffa0a0
hi Identifier guifg=palegreen
hi Statement guifg=khaki
hi PreProc guifg=indianred
hi Type guifg=darkkhaki
hi Special guifg=navajowhite
"hi Underlined
hi Ignore guifg=grey40
"hi Error
hi Todo guifg=orangered guibg=yellow2
" color terminal definitions
hi SpecialKey ctermfg=darkgreen
hi NonText cterm=bold ctermfg=darkblue
hi Directory ctermfg=darkcyan
hi ErrorMsg cterm=bold ctermfg=7 ctermbg=1
hi IncSearch cterm=NONE ctermfg=yellow ctermbg=green
hi Search cterm=NONE ctermfg=grey ctermbg=blue
hi MoreMsg ctermfg=darkgreen
hi ModeMsg cterm=NONE ctermfg=brown
hi LineNr ctermfg=3
hi Question ctermfg=green
hi StatusLine cterm=bold,reverse
hi StatusLineNC cterm=reverse
hi VertSplit cterm=reverse
hi Title ctermfg=5
hi Visual cterm=reverse
hi VisualNOS cterm=bold,underline
hi WarningMsg ctermfg=1
hi WildMenu ctermfg=0 ctermbg=3
hi Folded ctermfg=darkgrey ctermbg=NONE
hi FoldColumn ctermfg=darkgrey ctermbg=NONE
hi DiffAdd ctermbg=4
hi DiffChange ctermbg=5
hi DiffDelete cterm=bold ctermfg=4 ctermbg=6
hi DiffText cterm=bold ctermbg=1
hi Comment ctermfg=darkcyan
hi Constant ctermfg=brown
hi Special ctermfg=5
hi Identifier ctermfg=6
hi Statement ctermfg=3
hi PreProc ctermfg=5
hi Type ctermfg=2
hi Underlined cterm=underline ctermfg=5
hi Ignore cterm=bold ctermfg=7
hi Ignore ctermfg=darkgrey
hi Error cterm=bold ctermfg=7 ctermbg=1
"vim: sw=4

View file

@ -0,0 +1 @@
../../bundled/ut/ftplugin/vim

View file

@ -0,0 +1 @@
../../bundled/lh-vim-lib/macros/menu-map.vim

View file

@ -0,0 +1 @@
../../bundled/ut/plugin/UT.vim

View file

@ -0,0 +1 @@
../../../plugin/gundo.vim

View file

@ -0,0 +1,46 @@
let s:undolevels_save = &undolevels
function! g:Goto(buffername)"{{{
exec bufwinnr(bufnr(a:buffername)) . 'wincmd w'
endfunction"}}}
function! g:GotoLineContaining(text)"{{{
exe "silent! normal gg/\\M" . a:text . "\n"
endfunction"}}}
function! g:CurrentLineContains(text)"{{{
if stridx(getline('.'), a:text) != -1
return 1
else
return 0
endif
endfunction"}}}
function! g:Contains(text)"{{{
call g:GotoLineContaining(a:text)
return g:CurrentLineContains(a:text)
endfunction"}}}
function! g:TypeLine(text)"{{{
exe "normal i" . a:text . "\<C-g>u\n\e"
endfunction"}}}
function! g:TypeLineDone(text)"{{{
exe "normal i" . a:text . "\n\e"
" Break the undo chain
let &undolevels = s:undolevels_save
endfunction"}}}
function! g:PrintTheFuckingBuffer()"{{{
echo join(getline(1, 100000), "\n")
echo "SOMETIMES I HATE YOU VIM"
endfunction"}}}
function! g:MoveUp()"{{{
call cursor(line('.') - 1, 0)
endfunction"}}}
function! g:MoveDown()"{{{
call cursor(line('.') + 1, 0)
endfunction"}}}

View file

@ -0,0 +1 @@
../../bundled/lh-vim-lib/plugin/let.vim

View file

@ -0,0 +1 @@
../../bundled/lh-vim-lib/plugin/lhvl.vim

View file

@ -0,0 +1 @@
../../bundled/lh-vim-lib/plugin/ui-functions.vim

View file

@ -0,0 +1 @@
../../bundled/lh-vim-lib/plugin/words_tools.vim

View file

@ -0,0 +1,5 @@
set nocompatible
set runtimepath=vim_test
filetype plugin on
nnoremap q :qa!<cr>
color desert

View file

@ -0,0 +1 @@
doc/tags

View file

@ -0,0 +1,6 @@
before_script:
- git clone https://github.com/syngan/vim-vimlint /tmp/vim-vimlint
- git clone https://github.com/ynkdir/vim-vimlparser /tmp/vim-vimlparser
script:
- sh /tmp/vim-vimlint/bin/vimlint.sh -l /tmp/vim-vimlint -p /tmp/vim-vimlparser -e EVL103=1 -e EVL102.l:_=1 autoload

View file

@ -0,0 +1,27 @@
# Problems summary
## Expected
## Environment Information
* OS:
* Vim version:
## Minimal vimrc less than 50 lines
" Your vimrc
set nocompatible
set runtimepath+=~/path/to/neocomplete.vim/
set fo+=aw
let g:neocomplete#enable_at_startup = 1
let g:neocomplete#enable_auto_select = 0
set tw=10 " just for testing purposes
## Reproducable ways from Vim starting
1.
2.
3.
## Screen shot (if possible)

View file

@ -0,0 +1,206 @@
neocomplete
===========
[![Stories in Ready](http://badge.waffle.io/Shougo/neocomplete.vim.png)](http://waffle.io/Shougo/neocomplete.vim)
neocomplete is the abbreviation of "neo-completion with cache". It provides
keyword completion system by maintaining a cache of keywords in the current
buffer. neocomplete can be customized easily and has many more features than
Vim's built-in completion.
## Installation
**Note:** neocomplete requires Vim 7.3.885+ with Lua enabled.
See [requirements](#requirements) if you aren't sure whether you have this.
1. Extract the files and put them in your Vim directory
(usually `~/.vim/` or `Program Files/Vim/vimfiles` on Windows).
2. Execute the `:NeoCompleteEnable` command or set `let g:neocomplete#enable_at_startup = 1`
in your `.vimrc` (**not** in `.gvimrc` or `_gvimrc`!)
## Requirements
neocomplete requires Vim 7.3.885+ compiled with [if\_lua](http://vimdoc.sourceforge.net/htmldoc/if_lua.html).
If `:echo has("lua")` returns `1`, then you're done; otherwise, see below.
### Vim builds for Windows
* [Vim 32bit](http://files.kaoriya.net/goto/vim73w32)
* [Vim 64bit](http://files.kaoriya.net/goto/vim73w64)
* [Vim 32bit alternative](http://tuxproject.de/projects/vim/)
* [Another alternative](http://wyw.dcweb.cn/#download)
**Note:** the Vim build may not include the Lua DLL. In that case,
[download Lua](http://lua-users.org/wiki/LuaBinaries) and put the `lua52.dll`
file in the same directory as `gvim.exe`.
### Vim for Mac OS X:
[MacVim with `if\_lua`](https://github.com/zhaocai/macvim)
Or, you can install MacVim with homebrew:
brew install macvim --with-cscope --with-lua --HEAD
To install Vim (as opposed to MacVim) with homebrew:
brew install vim --with-lua
### Vim for Linux:
#### Debian (or Ubuntu)
Make sure you have any of these packages:
* vim-nox
* vim-gtk
* vim-gnome
* vim-athena
Which package depends on your graphical environment (except vim-nox which is for vim with no GUI).
#### Fedora
The latest version of vim includes lua.
As of 2014-04-16 you need to [download the rpm](http://koji.fedoraproject.org/koji/packageinfo?packageID=216).
#### Misc
Be aware, your distribution's package manager may have a fairly outdated
Vim build (for example, Ubuntu 12.04 ships Vim 7.3.429).
However, [building Vim](http://vim.wikia.com/wiki/Building_Vim) on Linux is not difficult.
Remember to specify `--with-lua` (or `--with-features=huge`).
### Vim for Cygwin:
In a cygwin environment, Lua interface is supported by default.
If you want to make manually, you also need gcc and make.
When everything is prepared, execute these commands.
cd /usr/src
tar jxf vim-7.4.tar.bz2
tar xvfz lua-5.1.5.tar.gz
cd vim74/
./configure --enable-luainterp --enable-gui=no \
--without-x --enable-multibyte --prefix=/usr
make && make install
To check if everything was successfull enter the following `vim --version`. You should see ` +lua` in the list of features.
## Snippets
The Snippets feature of neocomplete was split into a
[separate plugin](https://github.com/Shougo/neosnippet).
A migration guide for existing users of neocomplcache is available:
[Migration guide](https://github.com/Shougo/neocomplete.vim/wiki/neocomplete-migration-guide)
## Screenshots
### Original filename completion
![Original filename completion.](https://f.cloud.github.com/assets/41495/622454/f519f6b8-cf42-11e2-921e-6e34dba148a6.png)
![Include filename completion.](https://f.cloud.github.com/assets/214488/623151/284ad86e-cf5b-11e2-828e-257d31bf0572.png)
### Omni completion
![Omni completion.](https://f.cloud.github.com/assets/41495/622456/fb2cc0bc-cf42-11e2-94e8-403cdcf5427e.png)
### Completion with [vimshell](http://github.com/Shougo/vimshell)
![Completion with vimshell(http://github.com/Shougo/vimshell).](https://f.cloud.github.com/assets/41495/622458/01dbc660-cf43-11e2-85f1-326e7432b0a1.png)
### Vim completion
![Vim completion.](https://f.cloud.github.com/assets/41495/622457/fe90ad5e-cf42-11e2-8e03-8f189b5e26e5.png)
![Vim completion with animation.](https://f.cloud.github.com/assets/214488/623496/94ed19a2-cf68-11e2-8d33-3aad8a39d7c1.gif)
## Configuration Examples
```vim
"Note: This option must set it in .vimrc(_vimrc). NOT IN .gvimrc(_gvimrc)!
" Disable AutoComplPop.
let g:acp_enableAtStartup = 0
" Use neocomplete.
let g:neocomplete#enable_at_startup = 1
" Use smartcase.
let g:neocomplete#enable_smart_case = 1
" Set minimum syntax keyword length.
let g:neocomplete#sources#syntax#min_keyword_length = 3
let g:neocomplete#lock_buffer_name_pattern = '\*ku\*'
" Define dictionary.
let g:neocomplete#sources#dictionary#dictionaries = {
\ 'default' : '',
\ 'vimshell' : $HOME.'/.vimshell_hist',
\ 'scheme' : $HOME.'/.gosh_completions'
\ }
" Define keyword.
if !exists('g:neocomplete#keyword_patterns')
let g:neocomplete#keyword_patterns = {}
endif
let g:neocomplete#keyword_patterns['default'] = '\h\w*'
" Plugin key-mappings.
inoremap <expr><C-g> neocomplete#undo_completion()
inoremap <expr><C-l> neocomplete#complete_common_string()
" Recommended key-mappings.
" <CR>: close popup and save indent.
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
function! s:my_cr_function()
return neocomplete#close_popup() . "\<CR>"
" For no inserting <CR> key.
"return pumvisible() ? neocomplete#close_popup() : "\<CR>"
endfunction
" <TAB>: completion.
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
" <C-h>, <BS>: close popup and delete backword char.
inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><C-y> neocomplete#close_popup()
inoremap <expr><C-e> neocomplete#cancel_popup()
" Close popup by <Space>.
"inoremap <expr><Space> pumvisible() ? neocomplete#close_popup() : "\<Space>"
" For cursor moving in insert mode(Not recommended)
"inoremap <expr><Left> neocomplete#close_popup() . "\<Left>"
"inoremap <expr><Right> neocomplete#close_popup() . "\<Right>"
"inoremap <expr><Up> neocomplete#close_popup() . "\<Up>"
"inoremap <expr><Down> neocomplete#close_popup() . "\<Down>"
" Or set this.
"let g:neocomplete#enable_cursor_hold_i = 1
" Or set this.
"let g:neocomplete#enable_insert_char_pre = 1
" AutoComplPop like behavior.
"let g:neocomplete#enable_auto_select = 1
" Shell like behavior(not recommended).
"set completeopt+=longest
"let g:neocomplete#enable_auto_select = 1
"let g:neocomplete#disable_auto_complete = 1
"inoremap <expr><TAB> pumvisible() ? "\<Down>" : "\<C-x>\<C-u>"
" Enable omni completion.
autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS
autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags
" Enable heavy omni completion.
if !exists('g:neocomplete#sources#omni#input_patterns')
let g:neocomplete#sources#omni#input_patterns = {}
endif
"let g:neocomplete#sources#omni#input_patterns.php = '[^. \t]->\h\w*\|\h\w*::'
"let g:neocomplete#sources#omni#input_patterns.c = '[^.[:digit:] *\t]\%(\.\|->\)'
"let g:neocomplete#sources#omni#input_patterns.cpp = '[^.[:digit:] *\t]\%(\.\|->\)\|\h\w*::'
" For perlomni.vim setting.
" https://github.com/c9s/perlomni.vim
let g:neocomplete#sources#omni#input_patterns.perl = '\h\w*->\h\w*\|\h\w*::'
```

View file

@ -0,0 +1,352 @@
"=============================================================================
" FILE: neocomplete.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
if !exists('g:loaded_neocomplete')
runtime! plugin/neocomplete.vim
endif
let s:save_cpo = &cpo
set cpo&vim
" Global options definition. "{{{
let g:neocomplete#max_list =
\ get(g:, 'neocomplete#max_list', 100)
let g:neocomplete#max_keyword_width =
\ get(g:, 'neocomplete#max_keyword_width', 80)
let g:neocomplete#auto_completion_start_length =
\ get(g:, 'neocomplete#auto_completion_start_length', 2)
let g:neocomplete#manual_completion_start_length =
\ get(g:, 'neocomplete#manual_completion_start_length', 0)
let g:neocomplete#min_keyword_length =
\ get(g:, 'neocomplete#min_keyword_length', 4)
let g:neocomplete#enable_ignore_case =
\ get(g:, 'neocomplete#enable_ignore_case', &ignorecase)
let g:neocomplete#enable_smart_case =
\ get(g:, 'neocomplete#enable_smart_case', &infercase)
let g:neocomplete#enable_camel_case =
\ get(g:, 'neocomplete#enable_camel_case', 0)
let g:neocomplete#disable_auto_complete =
\ get(g:, 'neocomplete#disable_auto_complete', 0)
let g:neocomplete#enable_fuzzy_completion =
\ get(g:, 'neocomplete#enable_fuzzy_completion', 1)
let g:neocomplete#enable_insert_char_pre =
\ get(g:, 'neocomplete#enable_insert_char_pre', 0)
let g:neocomplete#enable_cursor_hold_i =
\ get(g:, 'neocomplete#enable_cursor_hold_i', 0)
let g:neocomplete#cursor_hold_i_time =
\ get(g:, 'neocomplete#cursor_hold_i_time', 300)
let g:neocomplete#enable_auto_select =
\ get(g:, 'neocomplete#enable_auto_select', 0)
let g:neocomplete#enable_auto_delimiter =
\ get(g:, 'neocomplete#enable_auto_delimiter', 0)
let g:neocomplete#lock_buffer_name_pattern =
\ get(g:, 'neocomplete#lock_buffer_name_pattern', '')
let g:neocomplete#ctags_command =
\ get(g:, 'neocomplete#ctags_command', 'ctags')
let g:neocomplete#lock_iminsert =
\ get(g:, 'neocomplete#lock_iminsert', 0)
let g:neocomplete#enable_multibyte_completion =
\ get(g:, 'neocomplete#enable_multibyte_completion', 0)
let g:neocomplete#release_cache_time =
\ get(g:, 'neocomplete#release_cache_time', 900)
let g:neocomplete#skip_auto_completion_time =
\ get(g:, 'neocomplete#skip_auto_completion_time', '0.3')
let g:neocomplete#enable_auto_close_preview =
\ get(g:, 'neocomplete#enable_auto_close_preview', 0)
let g:neocomplete#fallback_mappings =
\ get(g:, 'neocomplete#fallback_mappings', [])
let g:neocomplete#sources =
\ get(g:, 'neocomplete#sources', {})
let g:neocomplete#keyword_patterns =
\ get(g:, 'neocomplete#keyword_patterns', {})
let g:neocomplete#same_filetypes =
\ get(g:, 'neocomplete#same_filetypes', {})
let g:neocomplete#delimiter_patterns =
\ get(g:, 'neocomplete#delimiter_patterns', {})
let g:neocomplete#ctags_arguments =
\ get(g:, 'neocomplete#ctags_arguments', {})
let g:neocomplete#text_mode_filetypes =
\ get(g:, 'neocomplete#text_mode_filetypes', {})
let g:neocomplete#tags_filter_patterns =
\ get(g:, 'neocomplete#tags_filter_patterns', {})
let g:neocomplete#force_omni_input_patterns =
\ get(g:, 'neocomplete#force_omni_input_patterns', {})
let g:neocomplete#ignore_composite_filetypes =
\ get(g:, 'neocomplete#ignore_composite_filetypes', {})
let g:neocomplete#ignore_source_files =
\ get(g:, 'neocomplete#ignore_source_files', [])
"}}}
function! neocomplete#initialize() "{{{
return neocomplete#init#enable()
endfunction"}}}
function! neocomplete#get_current_neocomplete() "{{{
if !exists('b:neocomplete')
call neocomplete#init#_current_neocomplete()
endif
return b:neocomplete
endfunction"}}}
function! neocomplete#get_context() "{{{
return neocomplete#get_current_neocomplete().context
endfunction"}}}
" Source helper. "{{{
function! neocomplete#define_source(source) "{{{
let sources = neocomplete#variables#get_sources()
for source in neocomplete#util#convert2list(a:source)
let source = neocomplete#init#_source(source)
if !source.disabled
let sources[source.name] = source
endif
endfor
endfunction"}}}
function! neocomplete#define_filter(filter) "{{{
let filters = neocomplete#variables#get_filters()
for filter in neocomplete#util#convert2list(a:filter)
let filters[filter.name] = neocomplete#init#_filter(filter)
endfor
endfunction"}}}
function! neocomplete#available_sources() "{{{
return copy(neocomplete#variables#get_sources())
endfunction"}}}
function! neocomplete#custom_source(source_name, option_name, value) "{{{
return neocomplete#custom#source(a:source_name, a:option_name, a:value)
endfunction"}}}
function! neocomplete#dup_filter(list) "{{{
return neocomplete#util#dup_filter(a:list)
endfunction"}}}
function! neocomplete#system(...) "{{{
return call('neocomplete#util#system', a:000)
endfunction"}}}
function! neocomplete#has_vimproc() "{{{
return neocomplete#util#has_vimproc()
endfunction"}}}
function! neocomplete#get_cur_text(...) "{{{
" Return cached text.
let neocomplete = neocomplete#get_current_neocomplete()
return (a:0 == 0 && mode() ==# 'i' &&
\ neocomplete.cur_text != '') ?
\ neocomplete.cur_text : neocomplete#helper#get_cur_text()
endfunction"}}}
function! neocomplete#get_keyword_pattern(...) "{{{
let filetype = a:0 != 0? a:1 : neocomplete#get_context_filetype()
if a:0 < 2
return neocomplete#helper#unite_patterns(
\ g:neocomplete#keyword_patterns, filetype)
endif
let source = neocomplete#variables#get_source(a:2)
if !has_key(source, 'neocomplete__keyword_patterns')
let source.neocomplete__keyword_patterns = {}
endif
if !has_key(source.neocomplete__keyword_patterns, filetype)
let source.neocomplete__keyword_patterns[filetype] =
\ neocomplete#helper#unite_patterns(
\ source.keyword_patterns, filetype)
endif
return source.neocomplete__keyword_patterns[filetype]
endfunction"}}}
function! neocomplete#get_keyword_pattern_end(...) "{{{
return '\%('.call('neocomplete#get_keyword_pattern', a:000).'\m\)$'
endfunction"}}}
function! neocomplete#match_word(...) "{{{
return call('neocomplete#helper#match_word', a:000)
endfunction"}}}
function! neocomplete#is_enabled() "{{{
return neocomplete#init#is_enabled()
endfunction"}}}
function! neocomplete#is_locked(...) "{{{
return neocomplete#is_cache_disabled() || &paste
\ || (&t_Co != '' && &t_Co < 8)
\ || g:neocomplete#disable_auto_complete
endfunction"}}}
function! neocomplete#is_cache_disabled() "{{{
let ignore_filetypes = ['fuf', 'ku']
let bufnr = a:0 > 0 ? a:1 : bufnr('%')
return !neocomplete#is_enabled()
\ || index(ignore_filetypes, &filetype) >= 0
\ || neocomplete#get_current_neocomplete().lock
\ || (g:neocomplete#lock_buffer_name_pattern != '' &&
\ bufname(bufnr) =~ g:neocomplete#lock_buffer_name_pattern)
endfunction"}}}
function! neocomplete#is_auto_select() "{{{
return g:neocomplete#enable_auto_select && !neocomplete#is_eskk_enabled()
endfunction"}}}
function! neocomplete#is_auto_complete() "{{{
let neocomplete = neocomplete#get_current_neocomplete()
return neocomplete.is_auto_complete
endfunction"}}}
function! neocomplete#is_eskk_enabled() "{{{
return exists('*eskk#is_enabled') && eskk#is_enabled()
endfunction"}}}
function! neocomplete#is_eskk_convertion(cur_text) "{{{
return neocomplete#is_eskk_enabled()
\ && eskk#get_preedit().get_henkan_phase() !=#
\ g:eskk#preedit#PHASE_NORMAL
endfunction"}}}
function! neocomplete#is_multibyte_input(cur_text) "{{{
return (exists('b:skk_on') && b:skk_on)
\ || (!g:neocomplete#enable_multibyte_completion
\ && char2nr(split(a:cur_text, '\zs')[-1]) > 0x80)
endfunction"}}}
function! neocomplete#is_text_mode() "{{{
let neocomplete = neocomplete#get_current_neocomplete()
return get(g:neocomplete#text_mode_filetypes,
\ neocomplete.context_filetype, 0)
endfunction"}}}
function! neocomplete#is_windows() "{{{
return neocomplete#util#is_windows()
endfunction"}}}
function! neocomplete#is_prefetch() "{{{
return 1
endfunction"}}}
function! neocomplete#exists_echodoc() "{{{
return exists('g:loaded_echodoc') && g:loaded_echodoc
endfunction"}}}
function! neocomplete#within_comment() "{{{
return neocomplete#get_current_neocomplete().within_comment
endfunction"}}}
function! neocomplete#print_error(string) "{{{
echohl Error | echomsg '[neocomplete] ' . a:string | echohl None
endfunction"}}}
function! neocomplete#print_warning(string) "{{{
echohl WarningMsg | echomsg '[neocomplete] ' . a:string | echohl None
endfunction"}}}
function! neocomplete#head_match(checkstr, headstr) "{{{
let checkstr = &ignorecase ?
\ tolower(a:checkstr) : a:checkstr
let headstr = &ignorecase ?
\ tolower(a:headstr) : a:headstr
return stridx(checkstr, headstr) == 0
endfunction"}}}
function! neocomplete#get_source_filetypes(filetype) "{{{
return neocomplete#helper#get_source_filetypes(a:filetype)
endfunction"}}}
function! neocomplete#escape_match(str) "{{{
return escape(a:str, '~"*\.^$[]')
endfunction"}}}
function! neocomplete#get_context_filetype(...) "{{{
let neocomplete = exists('b:neocomplete') ?
\ b:neocomplete : neocomplete#get_current_neocomplete()
if a:0 != 0 || mode() !=# 'i' ||
\ neocomplete.context_filetype == ''
call neocomplete#context_filetype#set()
endif
return neocomplete.context_filetype
endfunction"}}}
function! neocomplete#get_context_filetype_range(...) "{{{
if !neocomplete#is_enabled()
return [[1, 1], [line('$'), len(getline('$'))+1]]
endif
let neocomplete = neocomplete#get_current_neocomplete()
if a:0 != 0 || mode() !=# 'i' ||
\ neocomplete.context_filetype == ''
call neocomplete#context_filetype#set()
endif
if neocomplete.context_filetype ==# &filetype
return [[1, 1], [line('$'), len(getline('$'))+1]]
endif
return neocomplete.context_filetype_range
endfunction"}}}
function! neocomplete#print_debug(expr) "{{{
if g:neocomplete#enable_debug
echomsg string(a:expr)
endif
endfunction"}}}
function! neocomplete#get_data_directory() "{{{
let g:neocomplete#data_directory =
\ get(g:, 'neocomplete#data_directory',
\ ($XDG_CACHE_HOME != '' ?
\ $XDG_CACHE_HOME . '/neocomplete' : '~/.cache/neocomplete'))
let directory = neocomplete#util#substitute_path_separator(
\ neocomplete#util#expand(g:neocomplete#data_directory))
if !isdirectory(directory)
if neocomplete#util#is_sudo()
call neocomplete#print_error(printf(
\ 'Cannot create Directory "%s" in sudo session.', directory))
else
call mkdir(directory, 'p')
endif
endif
return directory
endfunction"}}}
function! neocomplete#complete_check() "{{{
return neocomplete#helper#complete_check()
endfunction"}}}
function! neocomplete#skip_next_complete() "{{{
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.skip_next_complete = 1
endfunction"}}}
function! neocomplete#set_dictionary_helper(variable, keys, value) "{{{
return neocomplete#util#set_dictionary_helper(
\ a:variable, a:keys, a:value)
endfunction"}}}
function! neocomplete#disable_default_dictionary(variable) "{{{
return neocomplete#util#disable_default_dictionary(a:variable)
endfunction"}}}
function! neocomplete#filetype_complete(arglead, cmdline, cursorpos) "{{{
return neocomplete#helper#filetype_complete(a:arglead, a:cmdline, a:cursorpos)
endfunction"}}}
"}}}
" Key mapping functions. "{{{
function! neocomplete#smart_close_popup()
return neocomplete#mappings#smart_close_popup()
endfunction
function! neocomplete#close_popup()
return neocomplete#mappings#close_popup()
endfunction
function! neocomplete#cancel_popup()
return neocomplete#mappings#cancel_popup()
endfunction
function! neocomplete#undo_completion()
return neocomplete#mappings#undo_completion()
endfunction
function! neocomplete#complete_common_string()
return neocomplete#mappings#complete_common_string()
endfunction
function! neocomplete#start_manual_complete(...)
return call('neocomplete#mappings#start_manual_complete', a:000)
endfunction
"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,276 @@
"=============================================================================
" FILE: async_cache.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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 condition
"
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! s:main(argv) "{{{
" args: funcname, outputname filename pattern_file_name mark minlen fileencoding
let [funcname, outputname, filename, pattern_file_name, mark, minlen, fileencoding]
\ = a:argv
if funcname ==# 'load_from_file'
let keyword_list = s:load_from_file(
\ filename, pattern_file_name, mark, minlen, fileencoding, 1)
let string = '{' . escape(string(keyword_list)[1 : -2], '\\') . '}'
else
let keyword_list = s:load_from_tags(
\ filename, pattern_file_name, mark, minlen, fileencoding)
let string = string(keyword_list)
endif
if empty(keyword_list)
return
endif
" For neocomplete.
" Output cache.
call writefile([string], outputname)
endfunction"}}}
function! s:load_from_file(filename, pattern_file_name, mark, minlen, fileencoding, is_string) "{{{
if !filereadable(a:filename)
" File not found.
return []
endif
let lines = readfile(a:filename)
if a:fileencoding !=# &encoding
let lines = map(lines, 's:iconv(v:val, a:fileencoding, &encoding)')
endif
let pattern = get(readfile(a:pattern_file_name), 0, '\h\w*')
let pattern2 = '^\%('.pattern.'\m\)'
let keyword_list = []
let dup_check = {}
for line in lines "{{{
let match = match(line, pattern)
while match >= 0 "{{{
let match_str = matchstr(line, pattern2, match)
if !has_key(dup_check, match_str) && len(match_str) >= a:minlen
" Append list.
call add(keyword_list, match_str)
let dup_check[match_str] = 1
endif
if match_str == ''
break
endif
let match += len(match_str)
let match = match(line, pattern, match)
endwhile"}}}
endfor"}}}
if !a:is_string
call map(keyword_list, "{'word' : match_str}")
endif
return keyword_list
endfunction"}}}
function! s:load_from_tags(filename, pattern_file_name, mark, minlen, fileencoding) "{{{
let keyword_lists = []
let dup_check = {}
let [tags_file_name, filter_pattern] =
\ readfile(a:pattern_file_name)[1 : 2]
if tags_file_name !=# '$dummy$'
" Check output.
let tags_list = []
let i = 0
while i < 2
if filereadable(tags_file_name)
" Use filename.
let tags_list = map(readfile(tags_file_name),
\ 's:iconv(v:val, a:fileencoding, &encoding)')
break
endif
sleep 500m
let i += 1
endwhile
else
if !filereadable(a:filename)
return []
endif
" Use filename.
let tags_list = map(readfile(a:filename),
\ 's:iconv(v:val, a:fileencoding, &encoding)')
endif
if empty(tags_list)
return s:load_from_file(a:filename, a:pattern_file_name,
\ a:mark, a:minlen, a:fileencoding, 0)
endif
for line in tags_list "{{{
let tag = split(substitute(line, "\<CR>", '', 'g'), '\t', 1)
" Add keywords.
if line =~ '^!' || len(tag) < 3 || len(tag[0]) < a:minlen
\ || has_key(dup_check, tag[0])
continue
endif
let opt = join(tag[2:], "\<TAB>")
let cmd = matchstr(opt, '.*/;"')
let option = {
\ 'cmd' : substitute(substitute(substitute(cmd,
\'^\%([/?]\^\?\)\?\s*\|\%(\$\?[/?]\)\?;"$', '', 'g'),
\ '\\\\', '\\', 'g'), '\\/', '/', 'g'),
\ 'kind' : ''
\}
if option.cmd =~ '\d\+'
let option.cmd = tag[0]
endif
for opt in split(opt[len(cmd):], '\t', 1)
let key = matchstr(opt, '^\h\w*\ze:')
if key == ''
let option['kind'] = opt
else
let option[key] = matchstr(opt, '^\h\w*:\zs.*')
endif
endfor
if has_key(option, 'file')
\ || (has_key(option, 'access') && option.access != 'public')
continue
endif
let abbr = has_key(option, 'signature')? tag[0] . option.signature :
\ (option['kind'] == 'd' || option['cmd'] == '') ?
\ tag[0] : option['cmd']
let abbr = substitute(abbr, '\s\+', ' ', 'g')
" Substitute "namespace foobar" to "foobar <namespace>".
let abbr = substitute(abbr,
\'^\(namespace\|class\|struct\|enum\|union\)\s\+\(.*\)$',
\'\2 <\1>', '')
" Substitute typedef.
let abbr = substitute(abbr,
\'^typedef\s\+\(.*\)\s\+\(\h\w*\%(::\w*\)*\);\?$',
\'\2 <typedef \1>', 'g')
" Substitute extends and implements.
let abbr = substitute(abbr,
\'\<\%(extends\|implements\)\s\+\S\+\>', '', '')
" Substitute marker.
let abbr = substitute(abbr, '"\s*{{{', '', '')
let keyword = {
\ 'word' : tag[0], 'abbr' : abbr, 'menu' : a:mark,
\ 'kind' : option['kind'],
\ }
if has_key(option, 'struct')
let keyword.menu = option.struct
elseif has_key(option, 'class')
let keyword.menu = option.class
elseif has_key(option, 'enum')
let keyword.menu = option.enum
elseif has_key(option, 'union')
let keyword.menu = option.union
endif
call add(keyword_lists, keyword)
let dup_check[tag[0]] = 1
endfor"}}}
if filter_pattern != ''
call filter(keyword_lists, filter_pattern)
endif
return keyword_lists
endfunction"}}}
function! s:truncate(str, width) "{{{
" Original function is from mattn.
" http://github.com/mattn/googlereader-vim/tree/master
if a:str =~# '^[\x00-\x7f]*$'
return len(a:str) < a:width ?
\ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width)
endif
let ret = a:str
let width = strdisplaywidth(a:str)
if width > a:width
let ret = s:strwidthpart(ret, a:width)
let width = strdisplaywidth(ret)
endif
if width < a:width
let ret .= repeat(' ', a:width - width)
endif
return ret
endfunction"}}}
function! s:strwidthpart(str, width) "{{{
let ret = a:str
let width = strdisplaywidth(a:str)
while width > a:width
let char = matchstr(ret, '.$')
let ret = ret[: -1 - len(char)]
let width -= strwidth(char)
endwhile
return ret
endfunction"}}}
function! s:iconv(expr, from, to)
if a:from == '' || a:to == '' || a:from ==? a:to
return a:expr
endif
let result = iconv(a:expr, a:from, a:to)
return result != '' ? result : a:expr
endfunction
if argc() == 7 &&
\ (argv(0) ==# 'load_from_file' || argv(0) ==# 'load_from_tags')
try
call s:main(argv())
catch
call writefile([v:throwpoint, v:exception],
\ fnamemodify(argv(1), ':h:h').'/async_error_log')
endtry
qall!
else
function! neocomplete#async_cache#main(argv) "{{{
call s:main(a:argv)
endfunction"}}}
endif
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,336 @@
"=============================================================================
" FILE: cache.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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 conditionneocomplete#cache#
"
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
let s:Cache = neocomplete#util#get_vital().import('System.Cache')
" Cache loader.
function! neocomplete#cache#load_from_cache(cache_dir, filename, ...) "{{{
let is_string = get(a:000, 0, 0)
try
" Note: For neocomplete.
let list = []
if is_string
lua << EOF
do
local ret = vim.eval('list')
local list = {}
for line in io.lines(vim.eval(
'neocomplete#cache#encode_name(a:cache_dir, a:filename)')) do
list = loadstring('return ' .. line)()
end
for i = 1, #list do
ret:add(list[i])
end
end
EOF
else
let list = eval(get(neocomplete#cache#readfile(
\ a:cache_dir, a:filename), 0, '[]'))
endif
if !empty(list) && is_string && type(list[0]) != type('')
" Type check.
throw 'Type error'
endif
return list
catch
" echomsg string(v:errmsg)
" echomsg string(v:exception)
" Delete old cache file.
let cache_name =
\ neocomplete#cache#encode_name(a:cache_dir, a:filename)
if filereadable(cache_name)
call delete(cache_name)
endif
return []
endtry
endfunction"}}}
" New cache loader.
function! neocomplete#cache#check_cache(cache_dir, key, async_cache_dictionary, keyword_cache, is_string) "{{{
if !has_key(a:async_cache_dictionary, a:key)
return
endif
let cache_list = a:async_cache_dictionary[a:key]
if !has_key(a:keyword_cache, a:key)
let a:keyword_cache[a:key] = []
endif
for cache in filter(copy(cache_list), 'filereadable(v:val.cachename)')
let a:keyword_cache[a:key] += neocomplete#cache#load_from_cache(
\ a:cache_dir, cache.filename, a:is_string)
endfor
call filter(cache_list, '!filereadable(v:val.cachename)')
if empty(cache_list)
" Delete from dictionary.
call remove(a:async_cache_dictionary, a:key)
return
endif
endfunction"}}}
" For buffer source cache loader.
function! neocomplete#cache#get_cache_list(cache_dir, async_cache_list) "{{{
let cache_list = a:async_cache_list
let loaded_keywords = []
let loaded = 0
for cache in filter(copy(cache_list), 'filereadable(v:val.cachename)')
let loaded = 1
let loaded_keywords = neocomplete#cache#load_from_cache(
\ a:cache_dir, cache.filename, 1)
endfor
call filter(cache_list, '!filereadable(v:val.cachename)')
return [loaded, loaded_keywords]
endfunction"}}}
function! neocomplete#cache#save_cache(cache_dir, filename, keyword_list) "{{{
if neocomplete#util#is_sudo()
return
endif
" Output cache.
let string = substitute(substitute(substitute(
\ string(a:keyword_list), '^[', '{', ''),
\ ']$', '}', ''), '\\', '\\\\', 'g')
call neocomplete#cache#writefile(
\ a:cache_dir, a:filename, [string])
endfunction"}}}
" Cache helper.
function! neocomplete#cache#getfilename(cache_dir, filename) "{{{
let cache_dir = neocomplete#get_data_directory() . '/' . a:cache_dir
return s:Cache.getfilename(cache_dir, a:filename)
endfunction"}}}
function! neocomplete#cache#filereadable(cache_dir, filename) "{{{
let cache_dir = neocomplete#get_data_directory() . '/' . a:cache_dir
return s:Cache.filereadable(cache_dir, a:filename)
endfunction"}}}
function! neocomplete#cache#readfile(cache_dir, filename) "{{{
let cache_dir = neocomplete#get_data_directory() . '/' . a:cache_dir
return s:Cache.readfile(cache_dir, a:filename)
endfunction"}}}
function! neocomplete#cache#writefile(cache_dir, filename, list) "{{{
if neocomplete#util#is_sudo()
return
endif
let cache_dir = neocomplete#get_data_directory() . '/' . a:cache_dir
return s:Cache.writefile(cache_dir, a:filename, a:list)
endfunction"}}}
function! neocomplete#cache#encode_name(cache_dir, filename)
" Check cache directory.
let cache_dir = neocomplete#get_data_directory() . '/' . a:cache_dir
return s:Cache.getfilename(cache_dir, a:filename)
endfunction
function! neocomplete#cache#check_old_cache(cache_dir, filename) "{{{
let cache_dir = neocomplete#get_data_directory() . '/' . a:cache_dir
return s:Cache.check_old_cache(cache_dir, a:filename)
endfunction"}}}
function! neocomplete#cache#make_directory(directory) "{{{
let directory =
\ neocomplete#get_data_directory() .'/'.a:directory
if !isdirectory(directory)
if neocomplete#util#is_sudo()
call neocomplete#print_error(printf(
\ 'Cannot create Directory "%s" in sudo session.', directory))
else
call mkdir(directory, 'p')
endif
endif
endfunction"}}}
let s:sdir = neocomplete#util#substitute_path_separator(
\ fnamemodify(expand('<sfile>'), ':p:h'))
function! neocomplete#cache#async_load_from_file(cache_dir, filename, pattern, mark) "{{{
if !neocomplete#cache#check_old_cache(a:cache_dir, a:filename)
\ || neocomplete#util#is_sudo()
return neocomplete#cache#encode_name(a:cache_dir, a:filename)
endif
let pattern_file_name =
\ neocomplete#cache#encode_name('keyword_patterns', a:filename)
let cache_name =
\ neocomplete#cache#encode_name(a:cache_dir, a:filename)
" Create pattern file.
call neocomplete#cache#writefile(
\ 'keyword_patterns', a:filename, [a:pattern])
" args: funcname, outputname, filename pattern mark
" minlen maxlen encoding
let fileencoding =
\ &fileencoding == '' ? &encoding : &fileencoding
let argv = [
\ 'load_from_file', cache_name, a:filename, pattern_file_name, a:mark,
\ g:neocomplete#min_keyword_length, fileencoding
\ ]
return s:async_load(argv, a:cache_dir, a:filename)
endfunction"}}}
function! neocomplete#cache#async_load_from_tags(cache_dir, filename, filetype, pattern, mark, is_create_tags) "{{{
if !neocomplete#cache#check_old_cache(a:cache_dir, a:filename)
\ || !neocomplete#cache#check_old_cache('tags_output', a:filename)
\ || neocomplete#util#is_sudo()
return neocomplete#cache#encode_name(a:cache_dir, a:filename)
endif
let cache_name =
\ neocomplete#cache#encode_name(a:cache_dir, a:filename)
let pattern_file_name =
\ neocomplete#cache#encode_name('tags_patterns', a:filename)
if a:is_create_tags
if !executable(g:neocomplete#ctags_command)
echoerr 'Create tags error! Please install '
\ . g:neocomplete#ctags_command . '.'
return neocomplete#cache#encode_name(a:cache_dir, a:filename)
endif
" Create tags file.
let tags_file_name =
\ neocomplete#cache#encode_name('tags_output', a:filename)
let default = get(g:neocomplete#ctags_arguments, '_', '')
let args = get(g:neocomplete#ctags_arguments, a:filetype, default)
if has('win32') || has('win64')
let filename =
\ neocomplete#util#substitute_path_separator(a:filename)
let command = printf('%s -f "%s" %s "%s" ',
\ g:neocomplete#ctags_command, tags_file_name, args, filename)
else
let command = printf('%s -f ''%s'' 2>/dev/null %s ''%s''',
\ g:neocomplete#ctags_command, tags_file_name, args, a:filename)
endif
if neocomplete#has_vimproc()
call vimproc#system_bg(command)
else
call system(command)
endif
else
let tags_file_name = '$dummy$'
endif
let filter_pattern =
\ get(g:neocomplete#tags_filter_patterns, a:filetype, '')
call neocomplete#cache#writefile('tags_patterns', a:filename,
\ [a:pattern, tags_file_name, filter_pattern, a:filetype])
" args: funcname, outputname, filename
" pattern mark minlen encoding
let fileencoding = &fileencoding == '' ? &encoding : &fileencoding
let argv = [
\ 'load_from_tags', cache_name, a:filename, pattern_file_name, a:mark,
\ g:neocomplete#min_keyword_length, fileencoding
\ ]
return s:async_load(argv, a:cache_dir, a:filename)
endfunction"}}}
function! s:async_load(argv, cache_dir, filename) "{{{
" if 0
if neocomplete#has_vimproc()
let vim_path = s:search_vim_path()
if vim_path == ''
" Error
return
elseif !executable(vim_path)
call neocomplete#print_error(
\ printf('Vim path : "%s" is not executable.', vim_path))
let g:neocomplete#use_vimproc = 0
return
endif
let args = [vim_path, '-u', 'NONE', '-i', 'NONE', '-n',
\ '-N', '-S', s:sdir.'/async_cache.vim']
\ + a:argv
call vimproc#system_bg(args)
" call vimproc#system(args)
" call system(join(args))
else
call neocomplete#async_cache#main(a:argv)
endif
return neocomplete#cache#encode_name(a:cache_dir, a:filename)
endfunction"}}}
function! s:search_vim_path() "{{{
if exists('s:vim_path')
return s:vim_path
endif
let paths = vimproc#get_command_name(v:progname, $PATH, -1)
if empty(paths)
if has('gui_macvim')
" MacVim check.
if !executable('/Applications/MacVim.app/Contents/MacOS/Vim')
call neocomplete#print_error(
\ 'You installed MacVim in not default directory!'.
\ ' You must add MacVim installed path in $PATH.')
let g:neocomplete#use_vimproc = 0
return ''
endif
let s:vim_path = '/Applications/MacVim.app/Contents/MacOS/Vim'
else
call neocomplete#print_error(
\ printf('Vim path : "%s" is not found.'.
\ ' You must add "%s" installed path in $PATH.',
\ v:progname, v:progname))
let g:neocomplete#use_vimproc = 0
return ''
endif
else
let base_path = neocomplete#util#substitute_path_separator(
\ fnamemodify(paths[0], ':p:h'))
let s:vim_path = base_path . '/vim'
if !executable(s:vim_path) && neocomplete#util#is_mac()
" Note: Search "Vim" instead of vim.
let s:vim_path = base_path. '/Vim'
endif
endif
return s:vim_path
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,96 @@
"=============================================================================
" FILE: commands.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#commands#_initialize() "{{{
command! -nargs=1 NeoCompleteAutoCompletionLength
\ call s:set_auto_completion_length(<args>)
endfunction"}}}
function! neocomplete#commands#_toggle_lock() "{{{
if !neocomplete#is_enabled()
call neocomplete#init#enable()
return
endif
if neocomplete#get_current_neocomplete().lock
echo 'neocomplete is unlocked!'
call neocomplete#commands#_unlock()
else
echo 'neocomplete is locked!'
call neocomplete#commands#_lock()
endif
endfunction"}}}
function! neocomplete#commands#_lock() "{{{
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.lock = 1
endfunction"}}}
function! neocomplete#commands#_unlock() "{{{
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.lock = 0
endfunction"}}}
function! neocomplete#commands#_clean() "{{{
" Delete cache files.
let data_directory = neocomplete#get_data_directory()
for directory in filter(neocomplete#util#glob(
\ data_directory.'/*'), 'isdirectory(v:val)')
for filename in filter(neocomplete#util#glob(directory.'/*'),
\ '!isdirectory(v:val)')
call delete(filename)
endfor
endfor
echo 'Cleaned cache files in: ' . data_directory
endfunction"}}}
function! neocomplete#commands#_set_file_type(filetype) "{{{
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.context_filetype = a:filetype
endfunction"}}}
function! s:rand(max) "{{{
if !has('reltime')
" Same value.
return 0
endif
let time = reltime()[1]
return (time < 0 ? -time : time)% (a:max + 1)
endfunction"}}}
function! s:set_auto_completion_length(len) "{{{
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.completion_length = a:len
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,318 @@
"=============================================================================
" FILE: complete.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#complete#_get_results(cur_text, ...) "{{{
call neocomplete#print_debug('start get_complete_sources')
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.start_time = reltime()
" Comment check.
let neocomplete.within_comment =
\ neocomplete#helper#get_syn_name(1) ==# 'Comment'
let complete_sources = call(
\ 'neocomplete#complete#_set_results_pos', [a:cur_text] + a:000)
if empty(complete_sources)
call neocomplete#print_debug('Skipped.')
return []
endif
if neocomplete#is_auto_complete()
let complete_pos =
\ neocomplete#complete#_get_complete_pos(complete_sources)
call neocomplete#complete#_set_previous_position(a:cur_text, complete_pos)
endif
call neocomplete#complete#_set_results_words(complete_sources)
return filter(copy(complete_sources),
\ '!empty(v:val.neocomplete__context.candidates)')
endfunction"}}}
function! neocomplete#complete#_get_complete_pos(sources) "{{{
if empty(a:sources)
return -1
endif
return min([col('.')] + map(copy(a:sources),
\ 'v:val.neocomplete__context.complete_pos'))
endfunction"}}}
function! neocomplete#complete#_get_words(sources, complete_pos, complete_str) "{{{
let frequencies = neocomplete#variables#get_frequencies()
if exists('*neocomplete#sources#buffer#get_frequencies')
let frequencies = extend(copy(
\ neocomplete#sources#buffer#get_frequencies()),
\ frequencies)
endif
" Append prefix.
let candidates = []
let len_words = 0
for source in sort(filter(copy(a:sources),
\ '!empty(v:val.neocomplete__context.candidates)'),
\ 's:compare_source_rank')
let mark = source.mark
let context = source.neocomplete__context
let words =
\ type(context.candidates[0]) == type('') ?
\ map(copy(context.candidates), "{'word': v:val, 'menu' : mark}") :
\ deepcopy(context.candidates)
let context.candidates = words
call neocomplete#helper#call_hook(
\ source, 'on_post_filter', {})
if context.complete_pos > a:complete_pos
let prefix = a:complete_str[: context.complete_pos
\ - a:complete_pos - 1]
" Fix complete position.
let context.complete_pos = a:complete_pos
let context.complete_str = prefix
for candidate in words
let candidate.word = prefix . candidate.word
endfor
endif
lua << EOF
do
local frequencies = vim.eval('frequencies')
local candidates = vim.eval('words')
for i = 0, #candidates-1 do
if frequencies[candidates[i].word] ~= nil then
candidates[i].rank = frequencies[candidates[i].word]
end
end
end
EOF
let words = neocomplete#helper#call_filters(
\ source.neocomplete__sorters, source, {})
if source.max_candidates > 0
let words = words[: len(source.max_candidates)-1]
endif
" Set default menu.
lua << EOF
do
local candidates = vim.eval('words')
local mark = vim.eval('mark')
for i = 0, #candidates-1 do
if candidates[i].menu == nil then
candidates[i].menu = mark
end
end
end
EOF
let words = neocomplete#helper#call_filters(
\ source.neocomplete__converters, source, {})
let candidates += words
let len_words += len(words)
if g:neocomplete#max_list > 0
\ && len_words > g:neocomplete#max_list
break
endif
if neocomplete#complete_check()
return []
endif
endfor
if g:neocomplete#max_list > 0
let candidates = candidates[: g:neocomplete#max_list]
endif
" Check dup and set icase.
let icase = g:neocomplete#enable_ignore_case &&
\ !((g:neocomplete#enable_smart_case
\ || g:neocomplete#enable_camel_case) && a:complete_str =~ '\u')
if icase
for candidate in candidates
let candidate.icase = 1
endfor
endif
if neocomplete#complete_check()
return []
endif
return candidates
endfunction"}}}
function! neocomplete#complete#_set_results_pos(cur_text, ...) "{{{
" Initialize sources.
let neocomplete = neocomplete#get_current_neocomplete()
let filetype = neocomplete#get_context_filetype()
let sources = (a:0 > 0) ? a:1 :
\ (filetype ==# neocomplete.sources_filetype) ?
\ neocomplete.sources : neocomplete#helper#get_sources_list()
let pos = winsaveview()
" Try source completion. "{{{
let complete_sources = []
for source in filter(values(sources),
\ 'neocomplete#helper#is_enabled_source(v:val, filetype)')
if !source.loaded
call neocomplete#helper#call_hook(source, 'on_init', {})
let source.loaded = 1
endif
let context = source.neocomplete__context
let context.input = a:cur_text
try
let complete_pos =
\ has_key(source, 'get_complete_position') ?
\ source.get_complete_position(context) :
\ neocomplete#helper#match_word(context.input,
\ neocomplete#get_keyword_pattern_end(filetype, source.name))[0]
catch
call neocomplete#print_error(v:throwpoint)
call neocomplete#print_error(v:exception)
call neocomplete#print_error(
\ 'Error occurred in source''s get_complete_position()!')
call neocomplete#print_error(
\ 'Source name is ' . source.name)
return complete_sources
finally
if winsaveview() != pos
call winrestview(pos)
endif
endtry
if complete_pos < 0
let context.complete_pos = -1
let context.complete_str = ''
continue
endif
let complete_str = context.input[complete_pos :]
if neocomplete#is_auto_complete() &&
\ len(complete_str) < source.min_pattern_length
" Skip.
let context.complete_pos = -1
let context.complete_str = ''
continue
endif
let context.complete_pos = complete_pos
let context.complete_str = complete_str
call add(complete_sources, source)
endfor
"}}}
return complete_sources
endfunction"}}}
function! neocomplete#complete#_set_results_words(sources) "{{{
" Try source completion.
" Save options.
let ignorecase_save = &ignorecase
let pos = winsaveview()
try
for source in a:sources
if neocomplete#complete_check()
return
endif
let context = source.neocomplete__context
let &ignorecase = (g:neocomplete#enable_smart_case
\ || g:neocomplete#enable_camel_case) ?
\ context.complete_str !~ '\u' : g:neocomplete#enable_ignore_case
if !source.is_volatile
\ && context.prev_complete_pos == context.complete_pos
\ && !empty(context.prev_candidates)
" Use previous candidates.
let context.candidates = context.prev_candidates
else
try
let context.candidates = source.gather_candidates(context)
catch
call neocomplete#print_error(v:throwpoint)
call neocomplete#print_error(v:exception)
call neocomplete#print_error(
\ 'Source name is ' . source.name)
call neocomplete#print_error(
\ 'Error occurred in source''s gather_candidates()!')
return
finally
if winsaveview() != pos
call winrestview(pos)
endif
endtry
endif
let context.prev_candidates = copy(context.candidates)
let context.prev_complete_pos = context.complete_pos
if !empty(context.candidates)
let context.candidates = neocomplete#helper#call_filters(
\ source.neocomplete__matchers, source, {})
endif
call neocomplete#print_debug(source.name)
endfor
finally
let &ignorecase = ignorecase_save
endtry
endfunction"}}}
function! neocomplete#complete#_check_previous_position(cur_text, complete_pos) abort "{{{
let neocomplete = neocomplete#get_current_neocomplete()
return a:complete_pos == neocomplete.old_complete_pos
\ && line('.') == neocomplete.old_linenr
\ && a:cur_text ==# neocomplete.old_cur_text
endfunction"}}}
function! neocomplete#complete#_set_previous_position(cur_text, complete_pos) abort "{{{
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.old_complete_pos = a:complete_pos
let neocomplete.old_linenr = line('.')
let neocomplete.old_cur_text = a:cur_text
endfunction"}}}
" Source rank order. "{{{
function! s:compare_source_rank(i1, i2)
return a:i2.rank - a:i1.rank
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,65 @@
"=============================================================================
" FILE: context_filetype.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
" context_filetype.vim installation check.
if !exists('s:exists_context_filetype')
try
call context_filetype#version()
let s:exists_context_filetype = 1
catch
let s:exists_context_filetype = 0
endtry
endif
function! neocomplete#context_filetype#set() "{{{
let neocomplete = neocomplete#get_current_neocomplete()
let context_filetype =
\ s:exists_context_filetype ?
\ context_filetype#get_filetype() : &filetype
if context_filetype == ''
let context_filetype = 'nothing'
endif
let neocomplete.context_filetype = context_filetype
return neocomplete.context_filetype
endfunction"}}}
function! neocomplete#context_filetype#get(filetype) "{{{
let context_filetype =
\ s:exists_context_filetype ?
\ context_filetype#get_filetype(a:filetype) : a:filetype
if context_filetype == ''
let context_filetype = 'nothing'
endif
return context_filetype
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,54 @@
"=============================================================================
" FILE: custom.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#custom#get() "{{{
if !exists('s:custom')
let s:custom = {}
let s:custom.sources = {}
let s:custom.sources._ = {}
endif
return s:custom
endfunction"}}}
function! neocomplete#custom#source(source_name, option_name, value) "{{{
let custom_sources = neocomplete#custom#get().sources
for key in split(a:source_name, '\s*,\s*')
if !has_key(custom_sources, key)
let custom_sources[key] = {}
endif
let custom_sources[key][a:option_name] = a:value
endfor
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,80 @@
"=============================================================================
" FILE: echodoc.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
" For echodoc. "{{{
let s:doc_dict = {
\ 'name' : 'neocomplete',
\ 'rank' : 10,
\ }
function! s:doc_dict.search(cur_text) "{{{
let item = neocomplete#get_current_neocomplete().completed_item
if empty(item)
return []
endif
let ret = []
let abbr = (has_key(item, 'abbr') && item.word !=# item.abbr) ?
\ item.abbr : split(item.info, '\n')[0]
if abbr == ''
return []
endif
if has_key(item, 'abbr')
\ && abbr ==# item.abbr && len(get(item, 'menu', '')) > 5
" Combine menu.
let abbr .= ' ' . item.menu
endif
" Skip
if len(abbr) < len(item.word) + 2
return []
endif
let match = stridx(abbr, item.word)
if match < 0
call add(ret, { 'text' : abbr })
else
call add(ret, { 'text' : item.word, 'highlight' : 'Identifier' })
call add(ret, { 'text' : abbr[match+len(item.word) :] })
endif
return ret
endfunction"}}}
"}}}
function! neocomplete#echodoc#init() "{{{
if neocomplete#exists_echodoc()
call echodoc#register(s:doc_dict.name, s:doc_dict)
endif
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,48 @@
"=============================================================================
" FILE: filters.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#fuzzy_escape(string) "{{{
" Escape string for lua regexp.
let string = substitute(neocomplete#filters#escape(a:string),
\ '\w', '\0.*', 'g')
if g:neocomplete#enable_camel_case && string =~ '\u'
let string = substitute(string, '\l', '[\0\u\0\E]', 'g')
endif
return string
endfunction"}}}
function! neocomplete#filters#escape(string) "{{{
" Escape string for lua regexp.
return substitute(a:string,
\ '[%\[\]().*+?^$-]', '%\0', 'g')
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,66 @@
"=============================================================================
" FILE: converter_abbr.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#converter_abbr#define() "{{{
return s:converter
endfunction"}}}
let s:converter = {
\ 'name' : 'converter_abbr',
\ 'description' : 'abbreviate abbr converter',
\}
function! s:converter.filter(context) "{{{
if g:neocomplete#max_keyword_width < 0
return a:context.candidates
endif
lua << EOF
do
local candidates = vim.eval('a:context.candidates')
local max = vim.eval('g:neocomplete#max_keyword_width')
for i = 0, #candidates-1 do
local abbr = candidates[i].abbr == nil and
candidates[i].word or candidates[i].abbr
if string.len(abbr) > max then
vim.command("let a:context.candidates[".. i .."].abbr = neocomplete#util#truncate_smart("..
"get(a:context.candidates[".. i .."], 'abbr', " ..
"a:context.candidates[".. i .."].word), g:neocomplete#max_keyword_width," ..
"g:neocomplete#max_keyword_width/2, '..')")
end
end
end
EOF
return a:context.candidates
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,80 @@
"=============================================================================
" FILE: converter_case.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#converter_case#define() "{{{
return s:converter
endfunction"}}}
let s:converter = {
\ 'name' : 'converter_case',
\ 'description' : 'case converter',
\}
function! s:converter.filter(context) "{{{
if !neocomplete#is_text_mode() && !neocomplete#within_comment()
return a:context.candidates
endif
if a:context.complete_str =~ '^\l\{3}$'
for candidate in s:get_convert_candidates(a:context.candidates)
let candidate.word = tolower(candidate.word)
if has_key(candidate, 'abbr')
let candidate.abbr = tolower(candidate.abbr)
endif
endfor
elseif a:context.complete_str =~ '^\u\{3}$'
for candidate in s:get_convert_candidates(a:context.candidates)
let candidate.word = toupper(candidate.word)
if has_key(candidate, 'abbr')
let candidate.abbr = toupper(candidate.abbr)
endif
endfor
elseif a:context.complete_str =~ '^\u\l\+$'
for candidate in s:get_convert_candidates(a:context.candidates)
let candidate.word = toupper(candidate.word[0]).
\ candidate.word[1:]
if has_key(candidate, 'abbr')
let candidate.abbr = toupper(candidate.abbr[0]).
\ tolower(candidate.abbr[1:])
endif
endfor
endif
return a:context.candidates
endfunction"}}}
function! s:get_convert_candidates(candidates)
return filter(copy(a:candidates),
\ "get(v:val, 'neocomplete__convertable', 1)
\ && v:val.word =~ '^[a-zA-Z0-9_''-]\\+$'")
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,111 @@
"=============================================================================
" FILE: converter_delimiter.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#converter_delimiter#define() "{{{
return s:converter
endfunction"}}}
let s:converter = {
\ 'name' : 'converter_delimiter',
\ 'description' : 'delimiter converter',
\}
" @vimlint(EVL102, 1, l:delim_cnt)
function! s:converter.filter(context) "{{{
if g:neocomplete#max_keyword_width < 0
return a:context.candidates
endif
" Delimiter check.
let filetype = neocomplete#get_context_filetype()
for delimiter in get(g:neocomplete#delimiter_patterns, filetype, [])
" Count match.
let delim_cnt = 0
let delimiter_vim = neocomplete#util#escape_pattern(delimiter)
let matchend = matchend(a:context.complete_str, delimiter_vim)
while matchend >= 0
let matchend = matchend(a:context.complete_str,
\ delimiter_vim, matchend)
let delim_cnt += 1
endwhile
lua << EOF
do
local candidates = vim.eval('a:context.candidates')
local pattern = vim.eval('neocomplete#filters#escape(delimiter)')..'.'
for i = 0, #candidates-1 do
if string.find(candidates[i].word, pattern, 1) ~= nil then
vim.command('call s:process_delimiter(a:context, '..
'a:context.candidates['.. i ..
'], delimiter_vim, delim_cnt)')
end
end
end
EOF
endfor
return a:context.candidates
endfunction"}}}
" @vimlint(EVL102, 0, l:delim_cnt)
function! s:process_delimiter(context, candidate, delimiter, delim_cnt)
let candidate = a:candidate
let split_list = split(candidate.word, a:delimiter.'\ze.', 1)
let delimiter_sub = substitute(
\ a:delimiter, '\\\(.\)', '\1', 'g')
let candidate.abbr = join(
\ split(get(candidate, 'abbr', candidate.word),
\ a:delimiter.'\ze.', 1)[ : a:delim_cnt],
\ delimiter_sub)
let candidate.word = join(split_list[ : a:delim_cnt], delimiter_sub)
if g:neocomplete#max_keyword_width >= 0
\ && len(candidate.abbr) > g:neocomplete#max_keyword_width
let candidate.abbr = substitute(candidate.abbr,
\ '\(\h\)\w*'.a:delimiter, '\1'.delimiter_sub, 'g')
endif
if a:delim_cnt+1 < len(split_list)
let candidate.abbr .= delimiter_sub . '~'
let candidate.dup = 0
if g:neocomplete#enable_auto_delimiter
let candidate.word .= delimiter_sub
endif
endif
" Clear previous result.
let a:context.prev_candidates = []
let a:context.prev_complete_pos = -1
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,49 @@
"=============================================================================
" FILE: converter_disable_abbr.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#converter_disable_abbr#define() "{{{
return s:converter
endfunction"}}}
let s:converter = {
\ 'name' : 'converter_disable_abbr',
\ 'description' : 'disable abbr converter',
\}
function! s:converter.filter(context) "{{{
for candidate in a:context.candidates
let candidate.abbr = candidate.word
endfor
return a:context.candidates
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,50 @@
"=============================================================================
" FILE: converter_remove_last_paren.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#converter_remove_last_paren#define() "{{{
return s:converter
endfunction"}}}
let s:converter = {
\ 'name' : 'converter_remove_last_paren',
\ 'description' : 'remove last parenthesis',
\}
function! s:converter.filter(context) "{{{
for candidate in a:context.candidates
let candidate.word =
\ substitute(candidate.word, '[\[<({]$', '', '')
endfor
return a:context.candidates
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,129 @@
"=============================================================================
" FILE: converter_overlap.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#converter_remove_overlap#define() "{{{
return s:converter
endfunction"}}}
let s:converter = {
\ 'name' : 'converter_remove_overlap',
\ 'description' : 'remove overlapped characters',
\}
function! s:converter.filter(context) "{{{
let next = matchstr(getline('.')[
\ len(neocomplete#helper#get_cur_text()) :], '^\S\+')
if next == ''
return a:context.candidates
endif
let neocomplete = neocomplete#get_current_neocomplete()
let neocomplete.overlapped_items = {}
let candidates = []
for candidate in a:context.candidates
let overlapped_len = neocomplete#filters#
\converter_remove_overlap#length(candidate.word, next)
if overlapped_len > 0
if !has_key(candidate, 'abbr')
let candidate.abbr = candidate.word
endif
let word = candidate.word
let candidate.word = candidate.word[: -overlapped_len-1]
if candidate.word != ''
let neocomplete.overlapped_items[candidate.word] = word
endif
call add(candidates, candidate)
elseif !neocomplete#is_auto_complete()
call add(candidates, candidate)
endif
endfor
if empty(candidates)
return a:context.candidates
endif
let candidates = filter(candidates,
\ 'v:val.word !=# a:context.complete_str')
return candidates
endfunction"}}}
function! neocomplete#filters#converter_remove_overlap#length(left, right) "{{{
if a:left == '' || a:right == ''
return 0
endif
let ret = 0
lua << EOF
do
local ret = vim.eval('ret')
local left = vim.eval('a:left')
local right = vim.eval('a:right')
local left_len = string.len(left)
local right_len = string.len(right)
if left_len > right_len then
left = string.sub(left, left_len-right_len, left_len)
elseif left_len < right_len then
right = string.sub(right, 0, left_len)
end
if left == right then
ret = math.min(left_len, right_len)
else
local length = 1
left_len = string.len(left)
while 1 do
local pattern = string.sub(left, left_len-length+1, left_len)
local pos = string.find(right, pattern, 1, 1)
if pos == nil then
break
end
length = length + pos - 1
if string.sub(left, left_len-length+1, left_len) ==
string.sub(right, 1, length) then
ret = length
length = length + 1
end
end
end
vim.command('let ret = ' .. ret)
end
EOF
return ret
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,89 @@
"=============================================================================
" FILE: matcher_fuzzy.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#matcher_fuzzy#define() "{{{
return s:matcher
endfunction"}}}
let s:matcher = {
\ 'name' : 'matcher_fuzzy',
\ 'description' : 'fuzzy matcher',
\}
function! s:matcher.filter(context) "{{{
if len(a:context.complete_str) > 10
" Mix fuzzy mode.
let len = len(a:context.complete_str)
let fuzzy_len = len - len/(1 + len/10)
let pattern =
\ neocomplete#filters#escape(
\ a:context.complete_str[: fuzzy_len-1]) .
\ neocomplete#filters#fuzzy_escape(
\ a:context.complete_str[fuzzy_len :])
else
let pattern = neocomplete#filters#fuzzy_escape(
\ a:context.complete_str)
endif
" The first letter must be matched.
let pattern = '^' . pattern
lua << EOF
do
local pattern = vim.eval('pattern')
local input = vim.eval('a:context.complete_str')
local candidates = vim.eval('a:context.candidates')
if vim.eval('&ignorecase') ~= 0 then
pattern = string.lower(pattern)
input = string.lower(input)
for i = #candidates-1, 0, -1 do
local word = vim.type(candidates[i]) == 'dict' and
string.lower(candidates[i].word) or string.lower(candidates[i])
if string.find(word, pattern, 1) == nil then
candidates[i] = nil
end
end
else
for i = #candidates-1, 0, -1 do
local word = vim.type(candidates[i]) == 'dict' and
candidates[i].word or candidates[i]
if string.find(word, pattern, 1) == nil then
candidates[i] = nil
end
end
end
end
EOF
return a:context.candidates
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,72 @@
"=============================================================================
" FILE: matcher_head.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#matcher_head#define() "{{{
return s:matcher
endfunction"}}}
let s:matcher = {
\ 'name' : 'matcher_head',
\ 'description' : 'head matcher',
\}
function! s:matcher.filter(context) "{{{
lua << EOF
do
local pattern = vim.eval(
"'^' . neocomplete#filters#escape(a:context.complete_str)")
local input = vim.eval('a:context.complete_str')
local candidates = vim.eval('a:context.candidates')
if vim.eval('&ignorecase') ~= 0 then
pattern = string.lower(pattern)
for i = #candidates-1, 0, -1 do
local word = vim.type(candidates[i]) == 'dict' and
string.lower(candidates[i].word) or string.lower(candidates[i])
if string.find(word, pattern, 1) == nil then
candidates[i] = nil
end
end
else
for i = #candidates-1, 0, -1 do
local word = vim.type(candidates[i]) == 'dict' and
candidates[i].word or candidates[i]
if string.find(word, pattern, 1) == nil then
candidates[i] = nil
end
end
end
end
EOF
return a:context.candidates
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,63 @@
"=============================================================================
" FILE: matcher_length.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#matcher_length#define() "{{{
return s:matcher
endfunction"}}}
let s:matcher = {
\ 'name' : 'matcher_length',
\ 'description' : 'input length matcher',
\}
function! s:matcher.filter(context) "{{{
if empty(a:context.candidates)
return []
endif
lua << EOF
do
local candidates = vim.eval('a:context.candidates')
local len = string.len(vim.eval('a:context.complete_str'))
for i = #candidates-1, 0, -1 do
local word = vim.type(candidates[i]) == 'dict' and
candidates[i].word or candidates[i]
if string.len(word) <= len then
candidates[i] = nil
end
end
end
EOF
return a:context.candidates
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,50 @@
"=============================================================================
" FILE: sorter_filename.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#sorter_filename#define() "{{{
return s:sorter
endfunction"}}}
let s:sorter = {
\ 'name' : 'sorter_filename',
\ 'description' : 'sort by filename order',
\}
function! s:sorter.filter(context) "{{{
let dir_list = filter(copy(a:context.candidates),
\ 'v:val.action__is_directory')
let file_list = filter(copy(a:context.candidates),
\ '!v:val.action__is_directory')
return neocomplete#helper#sort_human(dir_list)
\ + neocomplete#helper#sort_human(file_list)
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

View file

@ -0,0 +1,53 @@
"=============================================================================
" FILE: sorter_length.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! neocomplete#filters#sorter_length#define() "{{{
return s:sorter
endfunction"}}}
let s:sorter = {
\ 'name' : 'sorter_length',
\ 'description' : 'sort by length order',
\}
function! s:sorter.filter(context) "{{{
return sort(a:context.candidates, 's:compare')
endfunction"}}}
function! s:compare(i1, i2)
let diff = len(a:i1.word) - len(a:i2.word)
if !diff
let diff = (a:i1.word ># a:i2.word) ? 1 : -1
endif
return diff
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker

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