First attempt at GTabularize

This commit is contained in:
Matt Wozniski 2012-09-04 23:36:30 -04:00
parent ad2a5a1d54
commit 4894d4add2
2 changed files with 103 additions and 24 deletions

View File

@ -219,6 +219,12 @@ function! tabular#TabularizeStrings(strings, delim, ...)
" intentionally " intentionally
" - Don't strip leading spaces from the first element; we like indenting. " - Don't strip leading spaces from the first element; we like indenting.
for line in lines for line in lines
if len(line) == 1 && len(tabular#LineInclusionPattern())
" FIXME Does LineInclusionPattern even need to be a pattern? Can it
" just be a boolean? That's all I've needed to use it as...
continue " Leave non-matching lines unchanged for GTabularize
endif
if line[0] !~ '^\s*$' if line[0] !~ '^\s*$'
let line[0] = s:StripTrailingSpaces(line[0]) let line[0] = s:StripTrailingSpaces(line[0])
endif endif
@ -232,6 +238,10 @@ function! tabular#TabularizeStrings(strings, delim, ...)
" Find the max length of each field " Find the max length of each field
let maxes = [] let maxes = []
for line in lines for line in lines
if len(line) == 1 && len(tabular#LineInclusionPattern())
continue " non-matching lines don't affect field widths for GTabularize
endif
for i in range(len(line)) for i in range(len(line))
if i == len(maxes) if i == len(maxes)
let maxes += [ s:Strlen(line[i]) ] let maxes += [ s:Strlen(line[i]) ]
@ -246,6 +256,12 @@ function! tabular#TabularizeStrings(strings, delim, ...)
" Concatenate the fields, according to the format pattern. " Concatenate the fields, according to the format pattern.
for idx in range(len(lines)) for idx in range(len(lines))
let line = lines[idx] let line = lines[idx]
if len(line) == 1 && len(tabular#LineInclusionPattern())
let lines[idx] = line[0] " GTabularize just ignores non-matching lines
continue
endif
for i in range(len(line)) for i in range(len(line))
let how = format[i % len(format)][0] let how = format[i % len(format)][0]
let pad = format[i % len(format)][1:-1] let pad = format[i % len(format)][1:-1]
@ -270,6 +286,8 @@ endfunction
" If the function is called with a range containing multiple lines, then " If the function is called with a range containing multiple lines, then
" those lines will be used as the range. " 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 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, " if "includepat" is not specified,
" that 1 line will be filtered, " that 1 line will be filtered,
" if "includepat" is specified and that line does not match it, " if "includepat" is specified and that line does not match it,
@ -281,34 +299,65 @@ endfunction
" The remaining arguments must each be a filter to apply to the text. " 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. " Each filter must either be a String evaluating to a function to be called.
function! tabular#PipeRange(includepat, ...) range function! tabular#PipeRange(includepat, ...) range
let top = a:firstline try
let bot = a:lastline let top = a:firstline
let bot = a:lastline
if a:includepat != '' && top == bot if get(s:, 'tabularize_mode', '') ==# 'GTabularize'
if top < 0 || top > line('$') || getline(top) !~ a:includepat " Save the include pattern for future use by TabularizeStrings (and by
return " any Pipeline that wants to handle it) for GTabularize; it can be
" queried later via tabular#LineInclusionPattern
let s:line_inclusion_pattern = a:includepat
else
" 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 endif
while top > 1 && getline(top-1) =~ a:includepat
let top -= 1 let lines = map(range(top, bot), 'getline(v:val)')
endwhile
while bot < line('$') && getline(bot+1) =~ a:includepat for filter in a:000
let bot += 1 if type(filter) != type("")
endwhile echoerr "PipeRange: Bad filter: " . string(filter)
endif
call s:FilterString(lines, filter)
unlet filter
endfor
call s:SetLines(top, bot - top + 1, lines)
finally
unlet! s:line_inclusion_pattern
endtry
endfunction
" For passing the current mode to autoload/tabular.vim from plugin/Tabular.vim
" FIXME This could be done more cleanly if the :AddTabularize* functions
" didn't hardcode the arguments to the PipeRange call...
function! tabular#SetTabularizeMode(mode)
if len(a:mode)
let s:tabularize_mode = a:mode
else
unlet! s:tabularize_mode
endif endif
endfunction
let lines = map(range(top, bot), 'getline(v:val)') " Part of the public interface so interested pipelines can query this.
" When not in GTabularize mode, an empty string will be returned, otherwise
for filter in a:000 " the pattern to be used to determine whether a line should be changed is
if type(filter) != type("") " returned.
echoerr "PipeRange: Bad filter: " . string(filter) function! tabular#LineInclusionPattern()
endif return get(s:, 'line_inclusion_pattern', '')
call s:FilterString(lines, filter)
unlet filter
endfor
call s:SetLines(top, bot - top + 1, lines)
endfunction endfunction
function! s:SplitDelimTest(string, delim, expected) function! s:SplitDelimTest(string, delim, expected)

View File

@ -321,6 +321,36 @@ function! Tabularize(command) range
endtry endtry
endfunction 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#LineInclusionPattern() 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 GTabularize(<q-args>)
function! GTabularize(command) range
call tabular#SetTabularizeMode('GTabularize')
try
exe a:firstline . ',' . a:lastline
\ . 'call Tabularize(' . string(a:command) . ')'
finally
call tabular#SetTabularizeMode('')
endtry
endfunction
" Stupid vimscript crap, part 2 {{{1 " Stupid vimscript crap, part 2 {{{1
let &cpo = s:savecpo let &cpo = s:savecpo
unlet s:savecpo unlet s:savecpo