-
-
Save Raimondi/90071c2bce80481efdcdedd3b7725c77 to your computer and use it in GitHub Desktop.
A sort function for Vim that keeps folded lines intact.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
":[range]SortUnfolded[!] [i][u][r][n][x][o] [/{pattern}/] | |
" Sort visible lines in [range]. Lines inside closed folds | |
" are kept intact; sorting is done only on the first line | |
" of the fold; the other lines inside the fold move with | |
" it as a unit. | |
" Copyright: (C) 2018 Israel Chauca | |
" 2012 Ingo Karkat | |
" The VIM LICENSE applies to this scriptlet; see ':help copyright'. | |
" Inspiration: | |
" http://stackoverflow.com/questions/13554191/sorting-vim-folds | |
function! s:ErrorMsg( text ) | |
let v:errmsg = a:text | |
echohl ErrorMsg | |
echomsg v:errmsg | |
echohl None | |
endfunction | |
function! s:ExceptionMsg( exception ) | |
" v:exception contains what is normally in v:errmsg, but with extra | |
" exception source info prepended, which we cut away. | |
call s:ErrorMsg(substitute(a:exception, '^Vim\%((\a\+)\)\=:', '', '')) | |
endfunction | |
function! s:REEscape( string ) | |
return escape(a:string, '/\^$~.*[') | |
endfunction | |
function! s:GetClosedFolds( startLnum, endLnum ) | |
"****************************************************************************** | |
"* PURPOSE: | |
" Determine the ranges of closed folds within the passed range. | |
"* ASSUMPTIONS / PRECONDITIONS: | |
" None. | |
"* EFFECTS / POSTCONDITIONS: | |
" None. | |
"* INPUTS: | |
" a:startLnum First line of the range. | |
" a:endLnum Last line of the range. | |
"* RETURN VALUES: | |
" List of [foldStartLnum, foldEndLnum] elements. | |
"****************************************************************************** | |
let folds = [] | |
let lnum = a:startLnum | |
while lnum <= a:endLnum | |
let foldEndLnum = foldclosedend(lnum) | |
if foldEndLnum == -1 | |
let lnum += 1 | |
else | |
call add(folds, [lnum, foldEndLnum]) | |
let lnum = foldEndLnum + 1 | |
endif | |
endwhile | |
return folds | |
endfunction | |
function! s:JoinFolded( startLnum, endLnum, separator ) | |
let folds = s:GetClosedFolds(a:startLnum, a:endLnum) | |
if empty(folds) | |
return [0, 0] | |
endif | |
let joinCnt = 0 | |
let save_foldenable = &foldenable | |
set nofoldenable | |
try | |
for [foldStartLnum, foldEndLnum] in reverse(folds) | |
let cnt = foldEndLnum - foldStartLnum | |
for i in range(cnt) | |
let cmd = 'silent %ssubstitute/\n/\=a:separator' | |
execute printf(cmd, foldStartLnum) | |
endfor | |
let joinCnt += cnt | |
endfor | |
finally | |
let &foldenable = save_foldenable | |
endtry | |
return [len(folds), joinCnt] | |
endfunction | |
function! s:SortUnfolded( bang, startLnum, endLnum, sortArgs ) | |
let separator = strtrans(nr2char(1)) | |
let asciiCode = 1 | |
while search(separator, 'wnc') | |
let asciiCode += 1 | |
let separator .= strtrans(nr2char(asciiCode + 1)) | |
echom printf('separator: %s', separator) | |
endwhile | |
let escapedSeparator = s:REEscape(separator) | |
echom printf('separator: %s', strtrans(escapedSeparator)) | |
let [foldNum, joinCnt] = s:JoinFolded(a:startLnum, a:endLnum, separator) | |
if empty(foldNum) | |
call s:ErrorMsg('No folds found') | |
return | |
endif | |
let reducedEndLnum = a:endLnum - joinCnt | |
try | |
execute printf('%d,%dsort%s %s', a:startLnum, reducedEndLnum, a:bang, a:sortArgs) | |
catch /^Vim\%((\a\+)\)\=:E/ | |
call s:ExceptionMsg(v:exception) | |
finally | |
silent execute printf('%d,%dsubstitute/%s/\r/g', a:startLnum, reducedEndLnum, escapedSeparator) | |
endtry | |
endfunction | |
command! -bang -range=% -nargs=* SortUnfolded call setline(<line1>, getline(<line1>)) | call s:SortUnfolded('<bang>', <line1>, <line2>, <q-args>) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment