611 lines
19 KiB
VimL
611 lines
19 KiB
VimL
|
" Text formatter plugin for Vim text editor
|
||
|
"
|
||
|
" Version: 2.1
|
||
|
" Last Change: 2008-09-13
|
||
|
" Maintainer: Teemu Likonen <tlikonen@iki.fi>
|
||
|
" License: This file is placed in the public domain.
|
||
|
" GetLatestVimScripts: 2324 1 :AutoInstall: TextFormat
|
||
|
|
||
|
"{{{1 The beginning stuff
|
||
|
if &compatible
|
||
|
finish
|
||
|
endif
|
||
|
let s:save_cpo = &cpo
|
||
|
set cpo&vim
|
||
|
|
||
|
" Constant variables(s) {{{1
|
||
|
let s:default_width = 80
|
||
|
|
||
|
function! s:Align_Range_Left(...) range "{{{1
|
||
|
" The optional parameter is the left indent. If it is not given we
|
||
|
" detect the indent used in the buffer.
|
||
|
if a:0 && a:1 >= 0
|
||
|
" The parameter was given so we just use that as the left
|
||
|
" indent.
|
||
|
let l:leading_ws = s:Retab_Indent(a:1)
|
||
|
for l:line in range(a:firstline,a:lastline)
|
||
|
let l:line_string = getline(l:line)
|
||
|
let l:line_replace = s:Align_String_Left(l:line_string)
|
||
|
if &formatoptions =~ 'w' && l:line_string =~ '\m\s$'
|
||
|
" Preserve trailing whitespace because fo=~w
|
||
|
let l:line_replace .= ' '
|
||
|
endif
|
||
|
if l:line_replace =~ '\m^\s*$'
|
||
|
call setline(l:line,'')
|
||
|
else
|
||
|
call setline(l:line,l:leading_ws.l:line_replace)
|
||
|
endif
|
||
|
endfor
|
||
|
else
|
||
|
" The parameter was not given so we detect each paragraph's
|
||
|
" indent.
|
||
|
let l:line = a:firstline
|
||
|
while l:line <= a:lastline
|
||
|
let l:line_string = getline(l:line)
|
||
|
if l:line_string =~ '\m^\s*$'
|
||
|
" The line is empty or contains only
|
||
|
" whitespaces so print empty line and
|
||
|
" continue.
|
||
|
call setline(l:line,'')
|
||
|
let l:line += 1
|
||
|
continue
|
||
|
endif
|
||
|
|
||
|
" Paragraph (or the whole line range) begins here so
|
||
|
" get the indent of the first line and print the line.
|
||
|
let l:leading_ws = s:Retab_Indent(indent(l:line))
|
||
|
let l:line_replace = s:Align_String_Left(l:line_string)
|
||
|
if &formatoptions =~ 'w' && l:line_string =~ '\m\s$'
|
||
|
let l:line_replace .= ' '
|
||
|
endif
|
||
|
call setline(l:line,l:leading_ws.l:line_replace)
|
||
|
let l:line += 1
|
||
|
|
||
|
" If fo=~w, does the paragraph end here? If yes,
|
||
|
" continue to next round and find a new first line.
|
||
|
if &formatoptions =~ 'w' && l:line_string =~ '\m\S$'
|
||
|
continue
|
||
|
endif
|
||
|
|
||
|
" If fo=~2 get the indent of the second line
|
||
|
if &formatoptions =~ '2'
|
||
|
let l:leading_ws = s:Retab_Indent(indent(l:line))
|
||
|
endif
|
||
|
|
||
|
" This loop will go through all the lines in the
|
||
|
" paragraph (or till the a:lastline) - starting from
|
||
|
" the second line.
|
||
|
while l:line <= a:lastline && getline(l:line) !~ '\m^\s*$'
|
||
|
let l:line_string = getline(l:line)
|
||
|
let l:line_replace = s:Align_String_Left(l:line_string)
|
||
|
if &formatoptions =~ 'w'
|
||
|
if l:line_string =~ '\m\s$'
|
||
|
call setline(l:line,l:leading_ws.l:line_replace.' ')
|
||
|
let l:line += 1
|
||
|
continue
|
||
|
else
|
||
|
call setline(l:line,l:leading_ws.l:line_replace)
|
||
|
let l:line += 1
|
||
|
" fo=~w and paragraph ends
|
||
|
" here so we break the loop.
|
||
|
" The next line is new first
|
||
|
" line.
|
||
|
break
|
||
|
endif
|
||
|
else
|
||
|
call setline(l:line,l:leading_ws.l:line_replace)
|
||
|
let l:line += 1
|
||
|
endif
|
||
|
endwhile
|
||
|
endwhile
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! s:Align_Range_Right(width) "{{{1
|
||
|
let l:line_replace = s:Align_String_Right(getline('.'),a:width)
|
||
|
if &formatoptions =~ 'w' && getline('.') =~ '\m\s$'
|
||
|
let l:line_replace .= ' '
|
||
|
endif
|
||
|
if l:line_replace =~ '\m^\s*$'
|
||
|
" If line would be full of spaces just print empty line.
|
||
|
call setline(line('.'),'')
|
||
|
else
|
||
|
" Retab leading whitespaces
|
||
|
let l:leading_ws = s:Retab_Indent(strlen(substitute(l:line_replace,'\v^( *).*$','\1','')))
|
||
|
" Get the rest of the line
|
||
|
let l:line_replace = substitute(l:line_replace,'^ *','','')
|
||
|
call setline(line('.'),l:leading_ws.l:line_replace)
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! s:Align_Range_Justify(width, ...) range "{{{1
|
||
|
" If the optional second argument is given (and is non-zero) each
|
||
|
" paragraph's last line and range's last line is left-aligned.
|
||
|
if a:0 && a:1
|
||
|
let l:paragraph = 1
|
||
|
else
|
||
|
let l:paragraph = 0
|
||
|
endif
|
||
|
let l:line = a:firstline
|
||
|
while l:line <= a:lastline
|
||
|
let l:line_string = getline(l:line)
|
||
|
if l:line_string =~ '\m^\s*$'
|
||
|
" The line is empty or contains only
|
||
|
" whitespaces so print empty line and
|
||
|
" continue.
|
||
|
call setline(l:line,'')
|
||
|
let l:line += 1
|
||
|
continue
|
||
|
endif
|
||
|
|
||
|
" Paragraph (or the whole line range) begins here so
|
||
|
" get the indent of the first line and print the line.
|
||
|
let l:indent = indent(l:line)
|
||
|
let l:width = a:width - l:indent
|
||
|
let l:leading_ws = s:Retab_Indent(l:indent)
|
||
|
|
||
|
if l:paragraph && (l:line == a:lastline || getline(l:line+1) =~ '\m^\s*$' || (&formatoptions =~ 'w' && l:line_string =~ '\m\S$'))
|
||
|
let l:line_replace = s:Align_String_Left(l:line_string)
|
||
|
else
|
||
|
let l:line_replace = s:Align_String_Justify(l:line_string,l:width)
|
||
|
endif
|
||
|
if &formatoptions =~ 'w' && l:line_string =~ '\m\s$'
|
||
|
let l:line_replace .= ' '
|
||
|
endif
|
||
|
call setline(l:line,l:leading_ws.l:line_replace)
|
||
|
let l:line += 1
|
||
|
|
||
|
" If fo=~w, does the paragraph end here? If yes,
|
||
|
" continue to next round and find a new first line.
|
||
|
if &formatoptions =~ 'w' && l:line_string =~ '\m\S$'
|
||
|
continue
|
||
|
endif
|
||
|
|
||
|
" If fo=~2 get the indent of the second line
|
||
|
if &formatoptions =~ '2'
|
||
|
let l:indent = indent(l:line)
|
||
|
let l:width = a:width - l:indent
|
||
|
let l:leading_ws = s:Retab_Indent(l:indent)
|
||
|
endif
|
||
|
|
||
|
" This loop will go through all the lines in the
|
||
|
" paragraph (or till the a:lastline) - starting from
|
||
|
" paragraph's second line.
|
||
|
while l:line <= a:lastline && getline(l:line) !~ '\m^\s*$'
|
||
|
let l:line_string = getline(l:line)
|
||
|
if l:paragraph && (l:line == a:lastline || getline(l:line+1) =~ '\m^\s*$' || (&formatoptions =~ 'w' && l:line_string =~ '\m\S$'))
|
||
|
let l:line_replace = s:Align_String_Left(l:line_string)
|
||
|
else
|
||
|
let l:line_replace = s:Align_String_Justify(l:line_string,l:width)
|
||
|
endif
|
||
|
if &formatoptions =~ 'w'
|
||
|
if l:line_string =~ '\m\s$'
|
||
|
call setline(l:line,l:leading_ws.l:line_replace.' ')
|
||
|
let l:line += 1
|
||
|
continue
|
||
|
else
|
||
|
call setline(l:line,l:leading_ws.l:line_replace)
|
||
|
let l:line += 1
|
||
|
" fo=~w and paragraph ends
|
||
|
" here so we break the loop.
|
||
|
" The next line is new first
|
||
|
" line.
|
||
|
break
|
||
|
endif
|
||
|
else
|
||
|
call setline(l:line,l:leading_ws.l:line_replace)
|
||
|
let l:line += 1
|
||
|
endif
|
||
|
endwhile
|
||
|
endwhile
|
||
|
endfunction
|
||
|
|
||
|
function! s:Align_Range_Center(width) "{{{1
|
||
|
let l:line_replace = s:Truncate_Spaces(getline('.'))
|
||
|
let l:line_replace = s:Add_Double_Spacing(l:line_replace)
|
||
|
if &formatoptions =~ 'w' && getline('.') =~ '\m\s$'
|
||
|
let l:line_replace .= ' '
|
||
|
endif
|
||
|
call setline(line('.'),l:line_replace)
|
||
|
execute '.center '.a:width
|
||
|
endfunction
|
||
|
|
||
|
function! s:Align_String_Left(string) "{{{1
|
||
|
let l:string_replace = s:Truncate_Spaces(a:string)
|
||
|
let l:string_replace = s:Add_Double_Spacing(l:string_replace)
|
||
|
return l:string_replace
|
||
|
endfunction
|
||
|
|
||
|
function! s:Align_String_Right(string, width) "{{{1
|
||
|
let l:string_replace = s:Truncate_Spaces(a:string)
|
||
|
let l:string_replace = s:Add_Double_Spacing(l:string_replace)
|
||
|
let l:string_width = s:String_Width(l:string_replace)
|
||
|
let l:more_spaces = a:width-l:string_width
|
||
|
return repeat(' ',l:more_spaces).l:string_replace
|
||
|
endfunction
|
||
|
|
||
|
function! s:Align_String_Justify(string, width) "{{{1
|
||
|
let l:string = s:Truncate_Spaces(a:string)
|
||
|
" If the parameter string is empty we can just return a line full of
|
||
|
" spaces. No need to go further.
|
||
|
if l:string =~ '\m^ *$'
|
||
|
return repeat(' ',a:width)
|
||
|
endif
|
||
|
if s:String_Width(s:Add_Double_Spacing(l:string)) >= a:width
|
||
|
" The original string is longer than width so we can just
|
||
|
" return the string. No need to go further.
|
||
|
return s:Add_Double_Spacing(l:string)
|
||
|
endif
|
||
|
let l:string_width = s:String_Width(l:string)
|
||
|
|
||
|
" This many extra spaces we need.
|
||
|
let l:more_spaces = a:width-l:string_width
|
||
|
" Convert the string to a list of words.
|
||
|
let l:word_list = split(l:string)
|
||
|
" This is the amount of spaces available in the original string (word
|
||
|
" count minus one).
|
||
|
let l:string_spaces = len(l:word_list)-1
|
||
|
" If there are no spaces there is only one word. We can just return
|
||
|
" the string with padded spaces. No need to go further.
|
||
|
if l:string_spaces == 0
|
||
|
return l:string.repeat(' ',l:more_spaces)
|
||
|
endif
|
||
|
" Ok, there are more than one word in the string so we get to do some
|
||
|
" real work...
|
||
|
|
||
|
" Make a list of which each item represent a space available in the
|
||
|
" string. The value means how many spaces there are. At the moment set
|
||
|
" every list item to one: [1, 1, 1, 1, ...]
|
||
|
let l:space_list = []
|
||
|
for l:item in range(l:string_spaces)
|
||
|
let l:space_list += [1]
|
||
|
endfor
|
||
|
|
||
|
" Repeat while there are no more need to add any spaces.
|
||
|
while l:more_spaces > 0
|
||
|
if l:more_spaces >= l:string_spaces
|
||
|
" More extra spaces are needed than there are spaces
|
||
|
" available in the string so we add one more space
|
||
|
" after every word (add 1 to items of space list).
|
||
|
for l:i in range(l:string_spaces)
|
||
|
let l:space_list[l:i] += 1
|
||
|
endfor
|
||
|
let l:more_spaces -= l:string_spaces
|
||
|
" And then another round... and a check if more spaces
|
||
|
" are needed.
|
||
|
else " l:more_spaces < l:string_spaces
|
||
|
" This list tells where .?! characters are.
|
||
|
let l:space_sentence_full = []
|
||
|
" This list tells where ,:; characters are.
|
||
|
let l:space_sentence_semi = []
|
||
|
" And this is for the rest of spaces.
|
||
|
let l:space_other = []
|
||
|
" Now, find those things:
|
||
|
for l:i in range(l:string_spaces)
|
||
|
if l:word_list[l:i] =~ '\m\S[.?!]$'
|
||
|
let l:space_sentence_full += [l:i]
|
||
|
elseif l:word_list[l:i] =~ '\m\S[,:;]$'
|
||
|
let l:space_sentence_semi += [l:i]
|
||
|
else
|
||
|
let l:space_other += [l:i]
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
" First distribute spaces after .?!
|
||
|
if l:more_spaces >= len(l:space_sentence_full)
|
||
|
" If we need more extra spaces than there are
|
||
|
" .?! spaces, just add one after every item.
|
||
|
for l:i in l:space_sentence_full
|
||
|
let l:space_list[l:i] += 1
|
||
|
endfor
|
||
|
let l:more_spaces -= len(l:space_sentence_full)
|
||
|
if l:more_spaces == 0 | break | endif
|
||
|
else
|
||
|
" Distribute the rest of spaces evenly and
|
||
|
" break the loop. All the spaces have been
|
||
|
" added.
|
||
|
for l:i in s:Distributed_Selection(l:space_sentence_full,l:more_spaces)
|
||
|
let l:space_list[l:i] +=1
|
||
|
endfor
|
||
|
break
|
||
|
endif
|
||
|
|
||
|
" Then distribute spaces after ,:;
|
||
|
if l:more_spaces >= len(l:space_sentence_semi)
|
||
|
" If we need more extra spaces than there are
|
||
|
" ,:; spaces available, just add one after
|
||
|
" every item.
|
||
|
for l:i in l:space_sentence_semi
|
||
|
let l:space_list[l:i] += 1
|
||
|
endfor
|
||
|
let l:more_spaces -= len(l:space_sentence_semi)
|
||
|
if l:more_spaces == 0 | break | endif
|
||
|
else
|
||
|
" Distribute the rest of spaces evenly and
|
||
|
" break the loop. All the spaces have been
|
||
|
" added.
|
||
|
for l:i in s:Distributed_Selection(l:space_sentence_semi,l:more_spaces)
|
||
|
let l:space_list[l:i] +=1
|
||
|
endfor
|
||
|
break
|
||
|
endif
|
||
|
|
||
|
" Finally distribute spaces to other available
|
||
|
" positions and exit the loop.
|
||
|
for l:i in s:Distributed_Selection(l:space_other,l:more_spaces)
|
||
|
let l:space_list[l:i] +=1
|
||
|
endfor
|
||
|
break
|
||
|
endif
|
||
|
endwhile
|
||
|
|
||
|
" Now we now where all the extra spaces will go. We have to construct
|
||
|
" the string again.
|
||
|
let l:string = ''
|
||
|
for l:item in range(l:string_spaces)
|
||
|
let l:string .= l:word_list[l:item].repeat(' ',l:space_list[l:item])
|
||
|
endfor
|
||
|
" Add the last word to the end and return the string.
|
||
|
return l:string.l:word_list[-1]
|
||
|
endfunction
|
||
|
|
||
|
function! s:Truncate_Spaces(string) "{{{1
|
||
|
let l:string = substitute(a:string,'\v\s+',' ','g')
|
||
|
let l:string = substitute(l:string,'\m^\s*','','')
|
||
|
let l:string = substitute(l:string,'\m\s*$','','')
|
||
|
return l:string
|
||
|
endfunction
|
||
|
|
||
|
function! s:String_Width(string) "{{{1
|
||
|
" This counts the string width in characters. Combining diacritical
|
||
|
" marks do not count so the base character with all the combined
|
||
|
" diacritics is just one character (which is good for our purposes).
|
||
|
" Double-wide characters will not get double width so unfortunately
|
||
|
" they don't work in our algorithm.
|
||
|
return strlen(substitute(a:string,'\m.','x','g'))
|
||
|
endfunction
|
||
|
|
||
|
function! s:Add_Double_Spacing(string) "{{{1
|
||
|
if &joinspaces
|
||
|
return substitute(a:string,'\m\S[.?!] ','& ','g')
|
||
|
else
|
||
|
return a:string
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! s:Distributed_Selection(list, pick) "{{{1
|
||
|
" 'list' is a list-type variable [ item1, item2, ... ]
|
||
|
" 'pick' is a number how many of the list's items we want to choose
|
||
|
"
|
||
|
" This function returns a list which has 'pick' number of items from
|
||
|
" the original list. Items are chosen in distributed manner. For
|
||
|
" example, if 'pick' is 1 then the algorithm chooses an item near the
|
||
|
" center of the 'list'. If 'pick' is 2 then the first one is about 1/3
|
||
|
" from the beginning and the another one about 2/3 from the beginning.
|
||
|
|
||
|
" l:pick_list is a list of 0's and 1's and its length will be the
|
||
|
" same as original list's. Number 1 means that this list item will be
|
||
|
" picked and 0 means that the item will be dropped. Finally
|
||
|
" l:pick_list could look like this: [0, 1, 0, 1, 0]
|
||
|
" (i.e., two items evenly picked from a list of five items)
|
||
|
let l:pick_list = []
|
||
|
|
||
|
" First pick items evenly from the beginning of the list. This also
|
||
|
" actually constructs the list.
|
||
|
let l:div1 = len(a:list) / a:pick
|
||
|
let l:mod1 = len(a:list) % a:pick
|
||
|
for l:i in range(len(a:list)-l:mod1)
|
||
|
if !eval(l:i%l:div1)
|
||
|
let l:pick_list += [1]
|
||
|
else
|
||
|
let l:pick_list += [0]
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
if l:mod1 > 0
|
||
|
" The division wasn't even so we get the remaining items and
|
||
|
" distribute them evenly again to the list.
|
||
|
let l:div2 = len(l:pick_list) / l:mod1
|
||
|
let l:mod2 = len(l:pick_list) % l:mod1
|
||
|
for l:i in range(len(l:pick_list)-l:mod2)
|
||
|
if !eval(l:i%l:div2)
|
||
|
call insert(l:pick_list,0,l:i)
|
||
|
endif
|
||
|
endfor
|
||
|
endif
|
||
|
|
||
|
" There may be very different number of zeros in the beginning and the
|
||
|
" end of the list. We count them.
|
||
|
let l:zeros_begin = 0
|
||
|
for l:i in l:pick_list
|
||
|
if l:i == 0
|
||
|
let l:zeros_begin += 1
|
||
|
else
|
||
|
break
|
||
|
endif
|
||
|
endfor
|
||
|
let l:zeros_end = 0
|
||
|
for l:i in reverse(copy(l:pick_list))
|
||
|
if l:i == 0
|
||
|
let l:zeros_end += 1
|
||
|
else
|
||
|
break
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
" Then we remove them.
|
||
|
if l:zeros_end
|
||
|
" Remove "0" items from the end. We need to remove them first
|
||
|
" from the end because list items' index number will change
|
||
|
" when items are removed from the beginning. Then it would be
|
||
|
" more difficult to remove trailing zeros.
|
||
|
call remove(l:pick_list,len(l:pick_list)-l:zeros_end,-1)
|
||
|
endif
|
||
|
if l:zeros_begin
|
||
|
" Remove zero items from the beginning.
|
||
|
call remove(l:pick_list,0,l:zeros_begin-1)
|
||
|
endif
|
||
|
let l:zeros_both = l:zeros_begin + l:zeros_end
|
||
|
|
||
|
" Put even amount of zeros to beginning and end
|
||
|
for l:i in range(l:zeros_both/2)
|
||
|
call insert(l:pick_list,0,0)
|
||
|
endfor
|
||
|
for l:i in range((l:zeros_both/2)+(l:zeros_both%2))
|
||
|
call add(l:pick_list,0)
|
||
|
endfor
|
||
|
|
||
|
" Finally construct and return a new list which has only the items we
|
||
|
" have chosen.
|
||
|
let l:new_list = []
|
||
|
for l:i in range(len(l:pick_list))
|
||
|
if l:pick_list[l:i] == 1
|
||
|
let l:new_list += [a:list[l:i]]
|
||
|
endif
|
||
|
endfor
|
||
|
return l:new_list
|
||
|
endfunction
|
||
|
|
||
|
function! s:Retab_Indent(column) "{{{1
|
||
|
" column = the left indent column starting from 0 Function returns
|
||
|
" a string of whitespaces, a mixture of tabs and spaces depending on
|
||
|
" the 'expandtab' and 'tabstop' options.
|
||
|
if &expandtab
|
||
|
" Only spaces
|
||
|
return repeat(' ',a:column)
|
||
|
else
|
||
|
" Tabs and spaces
|
||
|
let l:tabs = a:column / &tabstop
|
||
|
let l:spaces = a:column % &tabstop
|
||
|
return repeat("\<Tab>",l:tabs).repeat(' ',l:spaces)
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! s:Reformat_Range(...) range "{{{1
|
||
|
if a:0 == 2
|
||
|
let l:first = a:1
|
||
|
let l:last = a:2
|
||
|
else
|
||
|
let l:first = a:firstline
|
||
|
let l:last = a:lastline
|
||
|
endif
|
||
|
let l:autoindent = &autoindent
|
||
|
setlocal autoindent
|
||
|
execute l:first
|
||
|
normal! 0
|
||
|
execute 'normal! V'.l:last.'G$gw'
|
||
|
let &l:autoindent = l:autoindent
|
||
|
" The formatting may change the last line of the range so we return
|
||
|
" it.
|
||
|
return line("'>")
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Visual_Align_Left() range "{{{1
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Left()'
|
||
|
call s:Reformat_Range(a:firstline,a:lastline)
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Visual_Align_Right() range "{{{1
|
||
|
let l:width = &textwidth
|
||
|
if l:width == 0 | let l:width = s:default_width | endif
|
||
|
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Right('.l:width.')'
|
||
|
normal! '>$
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Visual_Align_Justify() range "{{{1
|
||
|
let l:width = &textwidth
|
||
|
if l:width == 0 | let l:width = s:default_width | endif
|
||
|
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Left()'
|
||
|
|
||
|
let l:last = s:Reformat_Range(a:firstline,a:lastline)
|
||
|
let l:pos = getpos('.')
|
||
|
execute a:firstline.','.l:last.'call s:Align_Range_Justify('.l:width.',1)'
|
||
|
call setpos('.',l:pos)
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Visual_Align_Center() range "{{{1
|
||
|
let l:width = &textwidth
|
||
|
if l:width == 0 | let l:width = s:default_width | endif
|
||
|
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Center('.l:width.')'
|
||
|
normal! '>$
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Quick_Align_Left() "{{{1
|
||
|
let l:autoindent = &autoindent
|
||
|
setlocal autoindent
|
||
|
let l:pos = getpos('.')
|
||
|
silent normal! vip:call s:Align_Range_Left()
|
||
|
call setpos('.',l:pos)
|
||
|
silent normal! gwip
|
||
|
let &l:autoindent = l:autoindent
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Quick_Align_Right() "{{{1
|
||
|
let l:width = &textwidth
|
||
|
if l:width == 0 | let l:width = s:default_width | endif
|
||
|
let l:pos = getpos('.')
|
||
|
silent normal! vip:call s:Align_Range_Right(l:width)
|
||
|
call setpos('.',l:pos)
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Quick_Align_Justify() "{{{1
|
||
|
let l:width = &textwidth
|
||
|
if l:width == 0 | let l:width = s:default_width | endif
|
||
|
let l:autoindent = &autoindent
|
||
|
setlocal autoindent
|
||
|
let l:pos = getpos('.')
|
||
|
silent normal! vip:call s:Align_Range_Left()
|
||
|
call setpos('.',l:pos)
|
||
|
silent normal! gwip
|
||
|
let l:pos = getpos('.')
|
||
|
silent normal! vip:call s:Align_Range_Justify(l:width,1)
|
||
|
call setpos('.',l:pos)
|
||
|
let &l:autoindent = l:autoindent
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Quick_Align_Center() "{{{1
|
||
|
let l:width = &textwidth
|
||
|
if l:width == 0 | let l:width = s:default_width | endif
|
||
|
let l:pos = getpos('.')
|
||
|
silent normal! vip:call s:Align_Range_Center(l:width)
|
||
|
call setpos('.',l:pos)
|
||
|
endfunction
|
||
|
|
||
|
function! textformat#Align_Command(align, ...) range "{{{1
|
||
|
" For left align the optional parameter a:1 is [indent]. For others
|
||
|
" it's [width].
|
||
|
let l:pos = getpos('.')
|
||
|
if a:align ==? 'left'
|
||
|
if a:0 && a:1 >= 0
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Left('.a:1.')'
|
||
|
else
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Left()'
|
||
|
endif
|
||
|
else
|
||
|
if a:0 && a:1 > 0
|
||
|
let l:width = a:1
|
||
|
elseif &textwidth
|
||
|
let l:width = &textwidth
|
||
|
else
|
||
|
let l:width = s:default_width
|
||
|
endif
|
||
|
|
||
|
if a:align ==? 'right'
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Right('.l:width.')'
|
||
|
elseif a:align ==? 'justify'
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Justify('.l:width.')'
|
||
|
elseif a:align ==? 'center'
|
||
|
execute a:firstline.','.a:lastline.'call s:Align_Range_Center('.l:width.')'
|
||
|
endif
|
||
|
endif
|
||
|
call setpos('.',l:pos)
|
||
|
endfunction
|
||
|
|
||
|
"{{{1 The ending stuff
|
||
|
let &cpo = s:save_cpo
|
||
|
|
||
|
" vim600: fdm=marker
|