2014-11-28 07:37:23 +00:00
|
|
|
" Copyright (c) 2014 Alex Yatskov <alex@foosoft.net>
|
|
|
|
"
|
|
|
|
" 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.
|
|
|
|
|
|
|
|
|
2014-12-01 13:34:52 +00:00
|
|
|
function! argwrap#validateRange(range)
|
|
|
|
return len(a:range) > 0 && !(a:range.lineStart == 0 && a:range.colStart == 0 || a:range.lineEnd == 0 && a:range.colEnd == 0)
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! argwrap#compareRanges(range1, range2)
|
2014-12-02 00:57:39 +00:00
|
|
|
let [l:buffer, l:line, l:col, l:offset] = getpos('.')
|
2014-12-01 13:34:52 +00:00
|
|
|
|
|
|
|
let l:lineDiff1 = a:range1.lineStart - l:line
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:colDiff1 = a:range1.colStart - l:col
|
2014-12-01 13:34:52 +00:00
|
|
|
let l:lineDiff2 = a:range2.lineStart - l:line
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:colDiff2 = a:range2.colStart - l:col
|
2014-12-01 13:34:52 +00:00
|
|
|
|
|
|
|
if l:lineDiff1 < l:lineDiff2
|
|
|
|
return 1
|
|
|
|
elseif l:lineDiff1 > l:lineDiff2
|
|
|
|
return -1
|
|
|
|
elseif l:colDiff1 < l:colDiff2
|
|
|
|
return 1
|
|
|
|
elseif l:colDiff1 > l:colDiff2
|
|
|
|
return -1
|
|
|
|
else
|
|
|
|
return 0
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! argwrap#findRange(braces)
|
2015-07-09 04:45:47 +00:00
|
|
|
let l:filter = 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"'
|
|
|
|
let [l:lineStart, l:colStart] = searchpairpos(a:braces[0], '', a:braces[1], 'Wnb', filter)
|
|
|
|
let [l:lineEnd, l:colEnd] = searchpairpos(a:braces[0], '', a:braces[1], 'Wcn', filter)
|
2014-12-02 00:57:39 +00:00
|
|
|
return {'lineStart': l:lineStart, 'colStart': l:colStart, 'lineEnd': l:lineEnd, 'colEnd': l:colEnd}
|
2014-11-28 07:37:23 +00:00
|
|
|
endfunction
|
|
|
|
|
2014-12-01 13:34:52 +00:00
|
|
|
function! argwrap#findClosestRange()
|
|
|
|
let l:ranges = []
|
2014-12-02 00:57:39 +00:00
|
|
|
for l:braces in [['(', ')'], ['\[', '\]'], ['{', '}']]
|
2014-12-01 13:34:52 +00:00
|
|
|
let l:range = argwrap#findRange(braces)
|
|
|
|
if argwrap#validateRange(l:range)
|
|
|
|
call add(l:ranges, l:range)
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
if len(l:ranges) == 0
|
|
|
|
return {}
|
|
|
|
else
|
2014-12-02 00:57:39 +00:00
|
|
|
return sort(l:ranges, 'argwrap#compareRanges')[0]
|
2014-12-01 13:34:52 +00:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2015-12-17 11:23:45 +00:00
|
|
|
function! argwrap#extractContainerArgText(range, linePrefix)
|
2014-12-02 00:57:39 +00:00
|
|
|
let l:text = ''
|
2020-06-06 13:16:27 +00:00
|
|
|
let l:trimPattern = printf('\m^\s*\(.\{-}\%%(%s\)\?\)\s*$', escape(a:linePrefix, '\$.*^['))
|
2014-11-28 07:37:23 +00:00
|
|
|
|
2014-12-01 08:49:14 +00:00
|
|
|
for l:lineIndex in range(a:range.lineStart, a:range.lineEnd)
|
2014-11-28 07:37:23 +00:00
|
|
|
let l:lineText = getline(l:lineIndex)
|
|
|
|
|
|
|
|
let l:extractStart = 0
|
2014-12-01 08:49:14 +00:00
|
|
|
if l:lineIndex == a:range.lineStart
|
|
|
|
let l:extractStart = a:range.colStart
|
2014-11-28 07:37:23 +00:00
|
|
|
endif
|
|
|
|
|
|
|
|
let l:extractEnd = strlen(l:lineText)
|
2014-12-01 08:49:14 +00:00
|
|
|
if l:lineIndex == a:range.lineEnd
|
|
|
|
let l:extractEnd = a:range.colEnd - 1
|
2014-11-28 07:37:23 +00:00
|
|
|
endif
|
|
|
|
|
|
|
|
if l:extractStart < l:extractEnd
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:extract = l:lineText[l:extractStart : l:extractEnd - 1]
|
2020-06-06 13:16:27 +00:00
|
|
|
let l:extract = substitute(l:extract, l:trimPattern, '\1', '')
|
2015-12-17 11:23:45 +00:00
|
|
|
if stridx(l:extract, a:linePrefix) == 0
|
|
|
|
let l:extract = l:extract[len(a:linePrefix):]
|
|
|
|
endif
|
2015-08-05 11:13:07 +00:00
|
|
|
let l:extract = substitute(l:extract, ',$', ', ', '')
|
|
|
|
let l:text .= l:extract
|
2014-11-28 07:37:23 +00:00
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
return l:text
|
|
|
|
endfunction
|
|
|
|
|
2014-12-01 10:33:46 +00:00
|
|
|
function! argwrap#updateScope(stack, char)
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:pairs = {'"': '"', '''': '''', ')': '(', ']': '[', '}': '{'}
|
2014-11-28 07:37:23 +00:00
|
|
|
let l:length = len(a:stack)
|
2014-11-28 08:06:36 +00:00
|
|
|
|
2014-12-02 00:57:39 +00:00
|
|
|
if l:length > 0 && get(l:pairs, a:char, '') == a:stack[l:length - 1]
|
2014-11-28 07:37:23 +00:00
|
|
|
call remove(a:stack, l:length - 1)
|
2014-11-28 08:06:36 +00:00
|
|
|
elseif index(values(l:pairs), a:char) >= 0
|
2014-11-28 07:37:23 +00:00
|
|
|
call add(a:stack, a:char)
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-12-01 10:33:46 +00:00
|
|
|
function! argwrap#trimArgument(text)
|
2015-02-19 04:00:02 +00:00
|
|
|
let l:trim = substitute(a:text, '^\s*\(.\{-}\)\s*$', '\1', '')
|
2015-02-20 04:03:38 +00:00
|
|
|
let l:trim = substitute(l:trim, '\([:=]\)\s\{2,}', '\1 ', '')
|
|
|
|
return substitute(l:trim, '\s\{2,}\([:=]\)', ' \1', '')
|
2014-12-01 03:31:53 +00:00
|
|
|
endfunction
|
|
|
|
|
2014-12-02 03:15:21 +00:00
|
|
|
function! argwrap#extractContainerArgs(text)
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:text = substitute(a:text, '^\s*\(.\{-}\)\s*$', '\1', '')
|
2014-11-28 08:06:36 +00:00
|
|
|
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:stack = []
|
|
|
|
let l:arguments = []
|
|
|
|
let l:argument = ''
|
|
|
|
|
|
|
|
if len(l:text) > 0
|
|
|
|
for l:index in range(strlen(l:text))
|
|
|
|
let l:char = l:text[l:index]
|
|
|
|
call argwrap#updateScope(l:stack, l:char)
|
|
|
|
|
|
|
|
if len(l:stack) == 0 && l:char == ','
|
2015-08-05 11:13:07 +00:00
|
|
|
let l:argument = argwrap#trimArgument(l:argument)
|
|
|
|
if len(l:argument) > 0
|
|
|
|
call add(l:arguments, l:argument)
|
|
|
|
endif
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:argument = ''
|
|
|
|
else
|
|
|
|
let l:argument .= l:char
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
2015-08-05 11:13:07 +00:00
|
|
|
let l:argument = argwrap#trimArgument(l:argument)
|
|
|
|
if len(l:argument) > 0
|
|
|
|
call add(l:arguments, l:argument)
|
|
|
|
endif
|
2015-03-26 09:28:22 +00:00
|
|
|
endif
|
2014-11-28 07:37:23 +00:00
|
|
|
|
|
|
|
return l:arguments
|
|
|
|
endfunction
|
|
|
|
|
2014-12-01 10:33:46 +00:00
|
|
|
function! argwrap#extractContainer(range)
|
2014-12-01 21:12:02 +00:00
|
|
|
let l:textStart = getline(a:range.lineStart)
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:textEnd = getline(a:range.lineEnd)
|
2014-12-01 21:12:02 +00:00
|
|
|
|
2014-12-03 04:44:31 +00:00
|
|
|
let l:indent = matchstr(l:textStart, '\s*')
|
|
|
|
let l:prefix = l:textStart[strlen(l:indent) : a:range.colStart - 1]
|
2014-12-01 21:12:02 +00:00
|
|
|
let l:suffix = l:textEnd[a:range.colEnd - 1:]
|
|
|
|
|
2014-12-02 00:36:14 +00:00
|
|
|
return {'indent': l:indent, 'prefix': l:prefix, 'suffix': l:suffix}
|
2014-12-01 09:21:05 +00:00
|
|
|
endfunction
|
|
|
|
|
2018-03-30 17:06:27 +00:00
|
|
|
function! argwrap#wrapContainer(range, container, arguments, wrapBrace, tailComma, tailCommaBraces, tailIndentBraces, linePrefix, commaFirst, commaFirstIndent)
|
2014-12-01 11:10:17 +00:00
|
|
|
let l:argCount = len(a:arguments)
|
2015-03-26 09:28:22 +00:00
|
|
|
let l:line = a:range.lineStart
|
2016-10-12 21:49:06 +00:00
|
|
|
let l:prefix = a:container.prefix[len(a:container.prefix) - 1]
|
2014-12-01 11:10:17 +00:00
|
|
|
|
2015-03-25 05:17:45 +00:00
|
|
|
call setline(l:line, a:container.indent . a:container.prefix)
|
2014-12-03 01:34:28 +00:00
|
|
|
|
2015-03-25 05:17:45 +00:00
|
|
|
for l:index in range(l:argCount)
|
2016-05-19 16:21:17 +00:00
|
|
|
let l:last = l:index == l:argCount - 1
|
2016-06-02 05:19:00 +00:00
|
|
|
let l:first = l:index == 0
|
|
|
|
let l:text = ''
|
|
|
|
|
|
|
|
if a:commaFirst
|
|
|
|
let l:text .= a:container.indent . a:linePrefix
|
|
|
|
if !l:first
|
|
|
|
let l:text .= ', '
|
|
|
|
end
|
|
|
|
let l:text .= a:arguments[l:index]
|
|
|
|
else
|
|
|
|
let l:text .= a:container.indent . a:linePrefix . a:arguments[l:index]
|
2016-10-12 21:49:06 +00:00
|
|
|
if !l:last || a:tailComma || a:tailCommaBraces =~ l:prefix
|
2016-06-02 05:19:00 +00:00
|
|
|
let l:text .= ','
|
|
|
|
end
|
2016-05-19 16:21:17 +00:00
|
|
|
end
|
2016-06-02 05:19:00 +00:00
|
|
|
|
2016-05-19 16:21:17 +00:00
|
|
|
if l:last && !a:wrapBrace
|
2015-03-25 05:17:45 +00:00
|
|
|
let l:text .= a:container.suffix
|
2016-05-19 16:21:17 +00:00
|
|
|
end
|
2014-12-01 11:10:17 +00:00
|
|
|
|
2015-03-25 05:17:45 +00:00
|
|
|
call append(l:line, l:text)
|
|
|
|
let l:line += 1
|
2017-07-01 01:41:17 +00:00
|
|
|
silent! exec printf('%s>', l:line)
|
2018-03-30 17:06:27 +00:00
|
|
|
|
|
|
|
if l:first && a:commaFirstIndent
|
|
|
|
let width = &l:shiftwidth
|
|
|
|
let &l:shiftwidth = 2
|
|
|
|
silent! exec printf('%s>', l:line)
|
|
|
|
let &l:shiftwidth = l:width
|
|
|
|
end
|
2015-03-25 05:17:45 +00:00
|
|
|
endfor
|
2014-12-03 01:34:28 +00:00
|
|
|
|
2015-03-25 05:17:45 +00:00
|
|
|
if a:wrapBrace
|
2015-12-17 11:23:45 +00:00
|
|
|
call append(l:line, a:container.indent . a:linePrefix . a:container.suffix)
|
2018-03-30 17:06:27 +00:00
|
|
|
if a:tailIndentBraces =~ l:prefix
|
|
|
|
silent! exec printf('%s>', l:line + 1)
|
|
|
|
end
|
2014-12-03 01:34:28 +00:00
|
|
|
endif
|
2014-12-01 08:49:14 +00:00
|
|
|
endfunction
|
|
|
|
|
2015-01-28 04:40:42 +00:00
|
|
|
function! argwrap#unwrapContainer(range, container, arguments, padded)
|
|
|
|
let l:brace = a:container.prefix[strlen(a:container.prefix) - 1]
|
|
|
|
if stridx(a:padded, l:brace) == -1
|
|
|
|
let l:padding = ''
|
|
|
|
else
|
|
|
|
let l:padding = ' '
|
|
|
|
endif
|
|
|
|
|
|
|
|
let l:text = a:container.indent . a:container.prefix . l:padding . join(a:arguments, ', ') . l:padding . a:container.suffix
|
2014-12-01 09:53:00 +00:00
|
|
|
call setline(a:range.lineStart, l:text)
|
2014-12-02 03:18:15 +00:00
|
|
|
exec printf('silent %d,%dd_', a:range.lineStart + 1, a:range.lineEnd)
|
2014-12-01 09:53:00 +00:00
|
|
|
endfunction
|
|
|
|
|
2015-12-17 10:18:39 +00:00
|
|
|
function! argwrap#getSetting(name, default)
|
2015-12-17 11:23:45 +00:00
|
|
|
let l:bName = 'b:argwrap_' . a:name
|
|
|
|
let l:gName = 'g:argwrap_' . a:name
|
2015-01-28 04:40:42 +00:00
|
|
|
|
2015-12-17 10:18:39 +00:00
|
|
|
if exists(l:bName)
|
|
|
|
return {l:bName}
|
|
|
|
elseif exists(l:gName)
|
|
|
|
return {l:gName}
|
2015-01-28 04:40:42 +00:00
|
|
|
else
|
2015-12-17 10:18:39 +00:00
|
|
|
return a:default
|
2015-01-28 04:40:42 +00:00
|
|
|
endif
|
2015-12-17 10:18:39 +00:00
|
|
|
endfunction
|
2015-01-28 04:40:42 +00:00
|
|
|
|
2015-12-17 10:18:39 +00:00
|
|
|
function! argwrap#toggle()
|
2014-12-02 03:31:44 +00:00
|
|
|
let l:cursor = getpos('.')
|
2014-12-02 03:15:21 +00:00
|
|
|
|
2015-12-17 13:03:08 +00:00
|
|
|
let l:linePrefix = argwrap#getSetting('line_prefix', '')
|
|
|
|
let l:padded = argwrap#getSetting('padded_braces', '')
|
2015-12-17 10:18:39 +00:00
|
|
|
let l:tailComma = argwrap#getSetting('tail_comma', 0)
|
2016-10-12 21:23:20 +00:00
|
|
|
let l:tailCommaBraces = argwrap#getSetting('tail_comma_braces', '')
|
2018-03-30 17:06:27 +00:00
|
|
|
let l:tailIndentBraces = argwrap#getSetting('tail_indent_braces', '')
|
2015-12-17 10:18:39 +00:00
|
|
|
let l:wrapBrace = argwrap#getSetting('wrap_closing_brace', 1)
|
2016-06-02 05:19:00 +00:00
|
|
|
let l:commaFirst = argwrap#getSetting('comma_first', 0)
|
2018-03-30 17:06:27 +00:00
|
|
|
let l:commaFirstIndent = argwrap#getSetting('comma_first_indent', 0)
|
2015-12-17 10:18:39 +00:00
|
|
|
|
2014-12-01 13:34:52 +00:00
|
|
|
let l:range = argwrap#findClosestRange()
|
|
|
|
if !argwrap#validateRange(l:range)
|
2014-12-02 03:15:21 +00:00
|
|
|
return
|
2014-12-01 10:46:47 +00:00
|
|
|
endif
|
2014-12-01 09:53:00 +00:00
|
|
|
|
2015-12-17 11:23:45 +00:00
|
|
|
let l:argText = argwrap#extractContainerArgText(l:range, l:linePrefix)
|
2014-12-02 03:15:21 +00:00
|
|
|
let l:arguments = argwrap#extractContainerArgs(l:argText)
|
2014-12-02 03:31:44 +00:00
|
|
|
if len(l:arguments) == 0
|
|
|
|
return
|
|
|
|
endif
|
2014-11-28 07:37:23 +00:00
|
|
|
|
2014-12-02 03:31:44 +00:00
|
|
|
let l:container = argwrap#extractContainer(l:range)
|
2014-12-01 10:46:47 +00:00
|
|
|
if l:range.lineStart == l:range.lineEnd
|
2020-06-07 13:26:06 +00:00
|
|
|
call argwrap#hooks#execute('pre_wrap', l:range, l:container, l:arguments)
|
|
|
|
|
2018-03-30 17:06:27 +00:00
|
|
|
call argwrap#wrapContainer(l:range, l:container, l:arguments, l:wrapBrace, l:tailComma, l:tailCommaBraces, l:tailIndentBraces, l:linePrefix, l:commaFirst, l:commaFirstIndent)
|
2018-05-26 15:08:07 +00:00
|
|
|
let l:cursor[1] = l:range.lineStart + 1
|
2020-06-06 17:49:50 +00:00
|
|
|
|
2020-06-07 13:26:06 +00:00
|
|
|
call argwrap#hooks#execute('post_wrap', l:range, l:container, l:arguments)
|
2014-12-01 10:46:47 +00:00
|
|
|
else
|
2020-06-07 13:26:06 +00:00
|
|
|
call argwrap#hooks#execute('pre_unwrap', l:range, l:container, l:arguments)
|
|
|
|
|
2015-01-28 04:40:42 +00:00
|
|
|
call argwrap#unwrapContainer(l:range, l:container, l:arguments, l:padded)
|
2018-05-26 15:03:30 +00:00
|
|
|
let l:cursor[1] = l:range.lineStart
|
2020-06-06 17:49:50 +00:00
|
|
|
|
2020-06-07 13:26:06 +00:00
|
|
|
call argwrap#hooks#execute('post_unwrap', l:range, l:container, l:arguments)
|
2014-12-01 10:46:47 +00:00
|
|
|
endif
|
2014-12-02 03:31:44 +00:00
|
|
|
|
|
|
|
call setpos('.', l:cursor)
|
2014-11-28 07:37:23 +00:00
|
|
|
endfunction
|