From 41ca29c8d67aed57702ec07e2b2a6a5136e6df5c Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Sat, 30 Sep 2017 09:18:01 +0200 Subject: [PATCH] FIX: Number of 0-padding is wrong in 0-prefixed number sequences Align the behavior with Bash: If either start or end number is 0-padded, use the _longest source number width_ as overall width (not longest resulting number, as previously implemented). FIX: Need to base-10 convert l:sequenceElements (to l:numberElements) to avoid Vim converting into octal number. Add tests for 0-padded sequences. --- autoload/ingo/subs/BraceExpansion.vim | 12 +++++++----- .../BraceExpansion/t1000-BraceExpansion.vim | 2 -- .../t1030-BraceExpansion-sequences.vim | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 tests/subs/BraceExpansion/t1030-BraceExpansion-sequences.vim diff --git a/autoload/ingo/subs/BraceExpansion.vim b/autoload/ingo/subs/BraceExpansion.vim index 7e47b7d..98ea186 100644 --- a/autoload/ingo/subs/BraceExpansion.vim +++ b/autoload/ingo/subs/BraceExpansion.vim @@ -69,19 +69,21 @@ function! s:ExpandOneLevel( TailCall, text, level ) endif let l:isNumericSequence = (len(filter(copy(l:sequenceElements), 'v:val !~# "^[+-]\\?\\d\\+$"')) == 0) if l:isNumericSequence - let l:step = ingo#compat#abs(get(l:sequenceElements, 2, 1)) + let l:numberElements = map(copy(l:sequenceElements), 'str2nr(v:val)') + let l:step = ingo#compat#abs(get(l:numberElements, 2, 1)) if l:step == 0 | let l:step = 1 | endif let l:isZeroPadding = (l:sequenceElements[0] =~# '^0\d' || l:sequenceElements[1] =~# '^0\d') - if l:sequenceElements[0] > l:sequenceElements[1] + if l:numberElements[0] > l:numberElements[1] let l:step = l:step * -1 endif - let l:braceElements = range(l:sequenceElements[0], l:sequenceElements[1], l:step) + let l:braceElements = range(l:numberElements[0], l:numberElements[1], l:step) if l:isZeroPadding - call map(l:braceElements, 'printf("%0" . strlen(max(l:braceElements)) . "d", v:val)') + let l:digitNum = max(map(l:sequenceElements[0:1], 'len(v:val)')) + call map(l:braceElements, 'printf("%0" . l:digitNum . "d", v:val)') endif else - let l:step = ingo#compat#abs(get(l:sequenceElements, 2, 1)) + let l:step = ingo#compat#abs(str2nr(get(l:sequenceElements, 2, 1))) if l:step == 0 | let l:step = 1 | endif let [l:nrParameter0, l:nrParameter1] = [char2nr(l:sequenceElements[0]), char2nr(l:sequenceElements[1])] if l:nrParameter0 > l:nrParameter1 diff --git a/tests/subs/BraceExpansion/t1000-BraceExpansion.vim b/tests/subs/BraceExpansion/t1000-BraceExpansion.vim index 571b986..e0e3b0e 100644 --- a/tests/subs/BraceExpansion/t1000-BraceExpansion.vim +++ b/tests/subs/BraceExpansion/t1000-BraceExpansion.vim @@ -11,7 +11,6 @@ call vimtap#Is(s:Call('fo{!,X,o}'), 'fo! foX foo', 'same prefix, different suffi call vimtap#Is(s:Call('fo{x,oy,obar}'), 'fox fooy foobar', 'same prefix, different length suffixes') call vimtap#Is(s:Call('{my,their,our}foo'), 'myfoo theirfoo ourfoo', 'different prefixes, same suffix') call vimtap#Is(s:Call('{my,their,our}fo{!,X,o}'), 'myfo! myfoX myfoo theirfo! theirfoX theirfoo ourfo! ourfoX ourfoo', 'different prefixes, different suffixes') -"call vimtap#Is(s:Call('{my,their,our}fo{!,X,o}'), 'myfo! theirfoX ourfoo', 'different prefixes, different suffixes') call vimtap#Is(s:Call('foo{1..3}'), 'foo1 foo2 foo3', 'same prefix, number sequence') call vimtap#Is(s:Call('foo{1,2}'), 'foo1 foo2', 'same prefix, short number sequence') @@ -25,7 +24,6 @@ call vimtap#Is(s:Call('foo{{X..Z},{1..5..2}}'), 'fooX fooY fooZ foo1 foo3 foo5', call vimtap#Is(s:Call('Foo{Has,Is,Can}Boo'), 'FooHasBoo FooIsBoo FooCanBoo', 'two commons in outside') call vimtap#Is(s:Call('{my,their,our}Foo{Has,Is,Can}Boo{Here,Now,More}'), 'myFooHasBooHere myFooHasBooNow myFooHasBooMore myFooIsBooHere myFooIsBooNow myFooIsBooMore myFooCanBooHere myFooCanBooNow myFooCanBooMore theirFooHasBooHere theirFooHasBooNow theirFooHasBooMore theirFooIsBooHere theirFooIsBooNow theirFooIsBooMore theirFooCanBooHere theirFooCanBooNow theirFooCanBooMore ourFooHasBooHere ourFooHasBooNow ourFooHasBooMore ourFooIsBooHere ourFooIsBooNow ourFooIsBooMore ourFooCanBooHere ourFooCanBooNow ourFooCanBooMore', 'two commons in the middle') -"call vimtap#Is(s:Call('{my,their,our}Foo{Has,Is,Can}Boo{Here,Now,More}'), 'myFooHasBooHere theirFooIsBooNow ourFooCanBooMore', 'two commons in the middle') call vimtap#Is(s:Call('foo{\,bar\,,xy}'), 'foo,bar, fooxy', 'embedded commas') call vimtap#Is(s:Call('foo{bar,\{O\},xy}'), 'foobar foo{O} fooxy', 'embedded braces in one word') diff --git a/tests/subs/BraceExpansion/t1030-BraceExpansion-sequences.vim b/tests/subs/BraceExpansion/t1030-BraceExpansion-sequences.vim new file mode 100644 index 0000000..472ecdb --- /dev/null +++ b/tests/subs/BraceExpansion/t1030-BraceExpansion-sequences.vim @@ -0,0 +1,18 @@ +" Test brace expansion of sequences. + +function! s:Call( text ) + return join(ingo#subs#BraceExpansion#ExpandStrict(a:text), ' ') +endfunction + +call vimtest#StartTap() +call vimtap#Plan(6) + +call vimtap#Is(s:Call('foo{1..10}'), 'foo1 foo2 foo3 foo4 foo5 foo6 foo7 foo8 foo9 foo10', 'same prefix, number sequence') +call vimtap#Is(s:Call('foo{01..10}'), 'foo01 foo02 foo03 foo04 foo05 foo06 foo07 foo08 foo09 foo10', 'same prefix, 0-padded start number') +call vimtap#Is(s:Call('foo{001..10}'), 'foo001 foo002 foo003 foo004 foo005 foo006 foo007 foo008 foo009 foo010', 'same prefix, 00-padded start number') +call vimtap#Is(s:Call('foo{1..010}'), 'foo001 foo002 foo003 foo004 foo005 foo006 foo007 foo008 foo009 foo010', 'same prefix, 0-padded end number') +call vimtap#Is(s:Call('foo{01..010}'), 'foo001 foo002 foo003 foo004 foo005 foo006 foo007 foo008 foo009 foo010', 'same prefix, 0-padded start and end number') +call vimtap#Is(s:Call('foo{00..100..010}'), 'foo000 foo010 foo020 foo030 foo040 foo050 foo060 foo070 foo080 foo090 foo100', 'same prefix, 00-padded start number, 0-padded step') + +call vimtest#Quit() +