vim-argwrap/argwrap.vim

185 lines
6.2 KiB
VimL
Raw Normal View History

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)
let [l:buffer, l:line, l:col, l:offset] = getpos(".")
let l:lineDiff1 = a:range1.lineStart - l:line
let l:colDiff1 = a:range1.colStart - l:col
let l:lineDiff2 = a:range2.lineStart - l:line
let l:colDiff2 = a:range2.colStart - l:col
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)
let [l:lineStart, l:colStart] = searchpairpos(a:braces[0], "", a:braces[1], "Wnb")
let [l:lineEnd, l:colEnd] = searchpairpos(a:braces[0], "", a:braces[1], "Wn")
2014-12-01 08:49:14 +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 = []
for l:braces in [["(", ")"], ["\\[", "\\]"], ["{", "}"]]
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
return sort(l:ranges, "argwrap#compareRanges")[0]
endif
endfunction
2014-12-01 10:33:46 +00:00
function! argwrap#extractArgumentText(range)
2014-11-28 07:37:23 +00:00
let l:text = ""
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
2014-12-01 03:31:53 +00:00
let l:extract = l:lineText[l:extractStart : l:extractEnd - 1]
let l:extract = substitute(l:extract, "^\\s\\+", "", "g")
2014-12-01 09:21:05 +00:00
let l:extract = substitute(l:extract, ",$", ", ", "g")
2014-12-01 03:31:53 +00:00
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)
2014-11-28 08:06:36 +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
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)
2014-12-01 03:31:53 +00:00
let l:stripped = substitute(a:text, "\\s\\+", "", "")
let l:stripped = substitute(l:stripped, "^\\s\\+", "", "")
return l:stripped
endfunction
2014-12-01 10:33:46 +00:00
function! argwrap#extractArguments(text)
2014-11-28 07:37:23 +00:00
let l:stack = []
let l:arguments = []
let l:argument = ""
for l:index in range(strlen(a:text))
let l:char = a:text[l:index]
2014-12-01 10:33:46 +00:00
call argwrap#updateScope(l:stack, l:char)
2014-11-28 08:06:36 +00:00
2014-11-28 07:37:23 +00:00
if len(l:stack) == 0 && l:char == ","
2014-12-01 10:33:46 +00:00
call add(l:arguments, argwrap#trimArgument(l:argument))
2014-11-28 07:37:23 +00:00
let l:argument = ""
else
let l:argument .= l:char
endif
endfor
2014-12-01 10:33:46 +00:00
call add(l:arguments, argwrap#trimArgument(l:argument))
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)
let l:textEnd = getline(a:range.lineEnd)
let l:indent = match(l:textStart, "\\S")
let l:prefix = l:textStart[l:indent : a:range.colStart - 1]
let l:suffix = l:textEnd[a:range.colEnd - 1:]
return {"indent": l:indent, "prefix": l:prefix, "suffix": l:suffix}
2014-12-01 09:21:05 +00:00
endfunction
2014-12-01 10:33:46 +00:00
function! argwrap#wrapContainer(range, container, arguments)
2014-12-01 11:10:17 +00:00
let l:argCount = len(a:arguments)
2014-12-01 21:12:02 +00:00
let l:padding = repeat(" ", a:container.indent)
2014-12-01 11:10:17 +00:00
let l:line = a:range.lineStart
2014-12-01 21:12:02 +00:00
call setline(l:line, l:padding . a:container.prefix)
2014-12-01 11:10:17 +00:00
for l:index in range(l:argCount)
2014-12-01 21:12:02 +00:00
let l:text = l:padding . a:arguments[l:index]
2014-12-01 11:10:17 +00:00
if l:index < l:argCount - 1
let l:text .= ","
endif
call append(l:line, l:text)
2014-12-01 09:21:05 +00:00
let l:line += 1
2014-12-01 09:53:00 +00:00
exec printf("%s>", l:line)
2014-12-01 09:21:05 +00:00
endfor
2014-12-01 21:12:02 +00:00
call append(l:line, l:padding . a:container.suffix)
2014-12-01 08:49:14 +00:00
endfunction
2014-12-01 10:33:46 +00:00
function! argwrap#unwrapContainer(range, container, arguments)
2014-12-01 21:12:02 +00:00
let l:text = repeat(" ", a:container.indent) . a:container.prefix . join(a:arguments, ", ") . a:container.suffix
2014-12-01 09:53:00 +00:00
call setline(a:range.lineStart, l:text)
exec printf("%d,%dd", a:range.lineStart + 1, a:range.lineEnd)
endfunction
2014-12-01 10:46:47 +00:00
function! argwrap#toggle()
2014-12-01 13:34:52 +00:00
let l:range = argwrap#findClosestRange()
if !argwrap#validateRange(l:range)
2014-12-01 10:46:47 +00:00
return
endif
2014-12-01 09:53:00 +00:00
2014-12-01 10:33:46 +00:00
let l:argText = argwrap#extractArgumentText(l:range)
let l:arguments = argwrap#extractArguments(l:argText)
let l:container = argwrap#extractContainer(l:range)
2014-11-28 07:37:23 +00:00
2014-12-01 10:46:47 +00:00
if l:range.lineStart == l:range.lineEnd
call argwrap#wrapContainer(l:range, l:container, l:arguments)
else
call argwrap#unwrapContainer(l:range, l:container, l:arguments)
endif
2014-11-28 07:37:23 +00:00
endfunction