1
0
Fork 0
mirror of synced 2024-11-16 14:05:34 -05:00

Merge branch 'master' into master

This commit is contained in:
Vignesh D 2017-01-14 10:16:49 +05:30 committed by GitHub
commit 6c2f340405
10 changed files with 1165 additions and 10 deletions

View file

@ -2392,7 +2392,7 @@ Maintainer: Kamil Kisiel <kamil@kamilkisiel.net>
See the tool's documentation for details:
https://godoc.org/golang.org/x/tools/cmd/vet
https://godoc.org/cmd/vet
Note~

1
sources_non_forked/tabular/.gitignore vendored Normal file
View file

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

View file

@ -0,0 +1,24 @@
Copyright (c) 2016, Matthew J. Wozniski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The names of the contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

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

View file

@ -0,0 +1,73 @@
" Copyright (c) 2016, Matthew J. Wozniski
" All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
" * Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" * Redistributions in binary form must reproduce the above copyright
" notice, this list of conditions and the following disclaimer in the
" documentation and/or other materials provided with the distribution.
" * The names of the contributors may not be used to endorse or promote
" products derived from this software without specific prior written
" permission.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
" NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if !exists(':Tabularize') || get(g:, 'no_default_tabular_maps', 0)
finish " Tabular.vim wasn't loaded or the default maps are unwanted
endif
let s:save_cpo = &cpo
set cpo&vim
AddTabularPattern! assignment /[|&+*/%<>=!~-]\@<!\([<>!=]=\|=\~\)\@![|&+*/%<>=!~-]*=/l1r1
AddTabularPattern! two_spaces / /l0
AddTabularPipeline! multiple_spaces / / map(a:lines, "substitute(v:val, ' *', ' ', 'g')") | tabular#TabularizeStrings(a:lines, ' ', 'l0')
AddTabularPipeline! argument_list /(.*)/ map(a:lines, 'substitute(v:val, ''\s*\([(,)]\)\s*'', ''\1'', ''g'')')
\ | tabular#TabularizeStrings(a:lines, '[(,)]', 'l0')
\ | map(a:lines, 'substitute(v:val, ''\(\s*\),'', '',\1 '', "g")')
\ | map(a:lines, 'substitute(v:val, ''\s*)'', ")", "g")')
function! SplitCDeclarations(lines)
let rv = []
for line in a:lines
" split the line into declaractions
let split = split(line, '\s*[,;]\s*')
" separate the type from the first declaration
let type = substitute(split[0], '\%(\%([&*]\s*\)*\)\=\k\+$', '', '')
" add the ; back on every declaration
call map(split, 'v:val . ";"')
" add the first element to the return as-is, and remove it from the list
let rv += [ remove(split, 0) ]
" transform the other elements by adding the type on at the beginning
call map(split, 'type . v:val')
" and add them all to the return
let rv += split
endfor
return rv
endfunction
AddTabularPipeline! split_declarations /,.*;/ SplitCDeclarations(a:lines)
AddTabularPattern! ternary_operator /^.\{-}\zs?\|:/l1
AddTabularPattern! cpp_io /<<\|>>/l1
AddTabularPattern! pascal_assign /:=/l1
AddTabularPattern! trailing_c_comments /\/\*\|\*\/\|\/\//l1
let &cpo = s:save_cpo
unlet s:save_cpo

View file

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

View file

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

View file

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

View file

@ -240,15 +240,28 @@ snippet fig figure environment (includegraphics)
\\end{figure}
${0}
snippet tikz figure environment (tikzpicture)
\\begin{figure}
\\begin{figure}[htpb]
\\begin{center}
\\begin{tikzpicture}[scale=${1:1}]
\\begin{tikzpicture}[scale=${1:1}, transform shape]
${2}
\\end{tikzpicture}
\\end{center}
\\caption{${3}}
\\label{fig:${4}}
\\end{figure}
${0}
snippet subfig subfigure environment
\\begin{subfigure}[${1}]{${2:\\textwidth}}
\\begin{center}
${3}
\\end{center}
\\caption{${4}}
\\label{fig:${5}}
\\end{subfigure}
${0}
#math
snippet stackrel \stackrel{}{}
@ -289,15 +302,15 @@ snippet \{ \{ \}
#delimiter
snippet lr left right
\\left${1} ${0} \\right$1
snippet lr( left( right)
snippet lr( left( right)
\\left( ${0} \\right)
snippet lr| left| right|
snippet lr| left| right|
\\left| ${0} \\right|
snippet lr{ left\{ right\}
snippet lr{ left\{ right\}
\\left\\{ ${0} \\right\\}
snippet lr[ left[ right]
snippet lr[ left[ right]
\\left[ ${0} \\right]
snippet lra langle rangle
snippet lra langle rangle
\\langle ${0} \\rangle
# Code listings
snippet lst

View file

@ -383,11 +383,11 @@ function! VisualSelection(direction, extra_filter) range
let l:saved_reg = @"
execute "normal! vgvy"
let l:pattern = escape(@", '\\/.*$^~[]')
let l:pattern = escape(@", "\\/.*'$^~[]")
let l:pattern = substitute(l:pattern, "\n$", "", "")
if a:direction == 'gv'
call CmdLine("Ag \"" . l:pattern . "\" " )
call CmdLine("Ag '" . l:pattern . "' " )
elseif a:direction == 'replace'
call CmdLine("%s" . '/'. l:pattern . '/')
endif