Last active
July 12, 2024 10:04
-
-
Save PeterRincker/582ea9be24a69e6dd8e237eb877b8978 to your computer and use it in GitHub Desktop.
Sort groups of lines in vim
This file contains 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]SortGroup[!] [n|f|o|b|x] /{pattern}/ | |
" e.g. :SortGroup /^header/ | |
" e.g. :SortGroup n /^header/ | |
" See :h :sort for details | |
function! s:sort_by_header(bang, pat) range | |
let pat = a:pat | |
let opts = "" | |
if pat =~ '^\s*[nfxbo]\s' | |
let opts = matchstr(pat, '^\s*\zs[nfxbo]') | |
let pat = matchstr(pat, '^\s*[nfxbo]\s*\zs.*') | |
endif | |
let pat = substitute(pat, '^\s*', '', '') | |
let pat = substitute(pat, '\s*$', '', '') | |
let sep = '/' | |
if len(pat) > 0 && pat[0] == matchstr(pat, '.$') && pat[0] =~ '\W' | |
let [sep, pat] = [pat[0], pat[1:-2]] | |
endif | |
if pat == '' | |
let pat = @/ | |
endif | |
let ranges = [] | |
execute a:firstline . ',' . a:lastline . 'g' . sep . pat . sep . 'call add(ranges, line("."))' | |
let converters = { | |
\ 'n': {s-> str2nr(matchstr(s, '-\?\d\+.*'))}, | |
\ 'x': {s-> str2nr(matchstr(s, '-\?\%(0[xX]\)\?\x\+.*'), 16)}, | |
\ 'o': {s-> str2nr(matchstr(s, '-\?\%(0\)\?\x\+.*'), 8)}, | |
\ 'b': {s-> str2nr(matchstr(s, '-\?\%(0[bB]\)\?\x\+.*'), 2)}, | |
\ 'f': {s-> str2float(matchstr(s, '-\?\d\+.*'))}, | |
\ } | |
let arr = [] | |
for i in range(len(ranges)) | |
let end = max([get(ranges, i+1, a:lastline+1) - 1, ranges[i]]) | |
let line = getline(ranges[i]) | |
let d = {} | |
let d.key = call(get(converters, opts, {s->s}), [strpart(line, match(line, pat))]) | |
let d.group = getline(ranges[i], end) | |
call add(arr, d) | |
endfor | |
call sort(arr, {a,b -> a.key == b.key ? 0 : (a.key < b.key ? -1 : 1)}) | |
if a:bang | |
call reverse(arr) | |
endif | |
let lines = [] | |
call map(arr, 'extend(lines, v:val.group)') | |
let start = max([a:firstline, get(ranges, 0, 0)]) | |
call setline(start, lines) | |
call setpos("'[", start) | |
call setpos("']", start+len(lines)-1) | |
endfunction | |
command! -range=% -bang -nargs=+ SortGroup <line1>,<line2>call <SID>sort_by_header(<bang>0, <q-args>) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Unixware,
:SortGroup
attempts to work similar to:sort
. The pattern determines which lines are considers a header. The matched portion is used for the sort. This means\zs
can be used to set where the match starts. e.g./^## \zs
means for text## foo
thefoo
is the matched text. This might be better with an exampleRunning
:SortGroup /^#/
would yield:With
\zs
you can sort differently.:SortGroup /^# ... \zs/
would yield:Hopefully that make sense.
:SortGroup
takes an optionaln
,f
,o
,b
,x
to change to sort by decimal number, float, octal, binary, or hex. See:h :sort
for more detailsFor more help see: