-
-
Save PeterRincker/582ea9be24a69e6dd8e237eb877b8978 to your computer and use it in GitHub Desktop.
" :[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>) |
Is it expected that :SortGroup n /a/
turns
a 1
b
a 3
b
a 2
into
a 1
b
a 2
a 3
b
instead of
a 1
b
a 2
b
a 3
?
Yes. Each "group" is defined by the header.
The groups are as follows:
First:
a 1
b
Second:
a 3
b
Third:
a 2
Then each group is sorted by their headers pat
in this case numerically, n
.
Thank you for the clarification on the term group in :SortGroup
.
Maybe this could become a plugin.
@astier I am not really interested in maintaining this as a plugin. Feel free to wrap it up into a plugin if you wish. There is also Ingo Karkat's inkarkat/vim-AdvancedSorters which does far more than this gist
No problem. AdvancedSorters looks good. Thank you.
Hey @PeterRincker , what license is this code under? I assume that you don't care much about it, so it's probably a as-close-to-public-domain-as-possible choice (0BSD
would be that), but I want to verify. :)
@nogweii You can use it however, you wish, as-is. I do not see a license option for gists. I imagine i would choose MIT or maybe something like a BSD license. I really have no desire to maintain this
interesting plugin, as I understand it is only limited to 'letter' only headers , so failing to sort eg markdown (headers with # , ## , ### etc)
@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
the foo
is the matched text. This might be better with an example
# foo a
1
# baz c
3
# foo b
2
Running :SortGroup /^#/
would yield:
# baz c
3
# foo a
1
# foo b
2
With \zs
you can sort differently. :SortGroup /^# ... \zs/
would yield:
# foo a
1
# foo b
2
# baz c
3
Hopefully that make sense.
... as I understand it is only limited to 'letter' only headers ...
:SortGroup
takes an optional n
, f
, o
, b
, x
to change to sort by decimal number, float, octal, binary, or hex. See :h :sort
for more details
For more help see:
:h :sort
:h /\zs
This is remarkably helpful, thank you. I've been working with yaml files a lot lately and it's a real pain to sort certain sections of them. This works perfectly.