Permalink
Browse files

Fix bug in prefix/suffix strip operators.

I had to make a table to show that we always consider N prefixes and
suffixes, and that the order is exactly revesred for # vs ## an % and
%%.

Uncovered by k-script-build.
  • Loading branch information...
Andy Chu
Andy Chu committed Jan 21, 2018
1 parent 11033b1 commit a9a7fad022309de40b80efb825a935af8a57d6ae
Showing with 70 additions and 4 deletions.
  1. +8 −4 core/libstr.py
  2. +42 −0 core/libstr_test.py
  3. +20 −0 spec/var-op-strip.test.sh
View
@@ -85,31 +85,35 @@ def DoUnarySuffixOp(s, op, arg):
n = len(s)
if op.op_id == Id.VOp1_Pound: # shortest prefix
for i in xrange(1, n):
# 'abcd': match 'a', 'ab', 'abc', ...
for i in xrange(1, n+1):
#log('Matching pattern %r with %r', arg, s[:i])
if libc.fnmatch(arg, s[:i]):
return s[i:]
else:
return s
elif op.op_id == Id.VOp1_DPound: # longest prefix
for i in xrange(-1, -n, -1):
# 'abcd': match 'abc', 'ab', 'a'
for i in xrange(n, 0, -1):
#log('Matching pattern %r with %r', arg, s[:i])
if libc.fnmatch(arg, s[:i]):
return s[i:]
else:
return s
elif op.op_id == Id.VOp1_Percent: # shortest suffix
for i in xrange(-1, -n, -1):
# 'abcd': match 'abc', 'ab', 'a'
for i in xrange(n-1, -1, -1):
#log('Matching pattern %r with %r', arg, s[:i])
if libc.fnmatch(arg, s[i:]):
return s[:i]
else:
return s
elif op.op_id == Id.VOp1_DPercent: # longest suffix
for i in xrange(1, n):
# 'abcd': match 'abc', 'bc', 'c', ...
for i in xrange(0, n):
#log('Matching pattern %r with %r', arg, s[:i])
if libc.fnmatch(arg, s[i:]):
return s[:i]
View
@@ -0,0 +1,42 @@
#!/usr/bin/python -S
"""
libstr_test.py: Tests for libstr.py
"""
import unittest
import libstr # module under test
class LibStrTest(unittest.TestCase):
def testUnarySuffixOpDemo(self):
s = 'abcd'
n = len(s)
# All of these loops test exactly 4.
# NOTE: These are manually copied into DoUnarySuffixOp
print('## shortest prefix')
for i in xrange(1, n+1):
print '%d test %06r return %06r' % (i, s[:i], s[i:])
print
print('# longest prefix')
for i in xrange(n, 0, -1):
print '%d test %06r return %06r' % (i, s[:i], s[i:])
print
print('% shortest suffix')
for i in xrange(n-1, -1, -1):
print '%d test %06r return %06r' % (i, s[i:], s[:i])
print
print('%% longest suffix')
for i in xrange(0, n):
print '%d test %06r return %06r' % (i, s[i:], s[:i])
print
if __name__ == '__main__':
unittest.main()
View
@@ -67,3 +67,23 @@ echo ${v#?} # ? is a glob that stands for one character
# stdout: -
# BUG dash/mksh stdout-repr: '\xbc-\n'
# BUG zsh stdout-repr: '\n'
### Bug fix: Test that you can remove everything with glob
s='--x--'
argv "${s%%-*}" "${s%-*}" "${s#*-}" "${s##*-}"
## STDOUT:
['', '--x-', '-x--', '']
## END
### Test that you can remove everything with const
s='abcd'
argv "${s%%abcd}" "${s%abcd}" "${s#abcd}" "${s##abcd}"
# failure case:
argv "${s%%abcde}" "${s%abcde}" "${s#abcde}" "${s##abcde}"
## STDOUT:
['', '', '', '']
['abcd', 'abcd', 'abcd', 'abcd']
## END

0 comments on commit a9a7fad

Please sign in to comment.