Tons of updates, text now snarfs all remaining, but we still haven't stopped combining rest in context.

This commit is contained in:
Jeremy Fincher 2004-10-26 20:49:20 +00:00
parent 44d59fc651
commit b32215e169
2 changed files with 75 additions and 43 deletions

View File

@ -289,7 +289,7 @@ def getOtherUser(irc, msg, args, state):
irc.errorNoUser(name=hostmask) irc.errorNoUser(name=hostmask)
def _getRe(f): def _getRe(f):
def get(irc, msg, args, state): def get(irc, msg, args, state, convert=True):
original = args[:] original = args[:]
s = args.pop(0) s = args.pop(0)
def isRe(s): def isRe(s):
@ -302,7 +302,10 @@ def _getRe(f):
while len(s) < 512 and not isRe(s): while len(s) < 512 and not isRe(s):
s += ' ' + args.pop(0) s += ' ' + args.pop(0)
if len(s) < 512: if len(s) < 512:
state.args.append(f(s)) if convert:
state.args.append(f(s))
else:
state.args.append(s)
else: else:
irc.errorInvalid('regular expression', s) irc.errorInvalid('regular expression', s)
except IndexError: except IndexError:
@ -332,7 +335,6 @@ def getSeenNick(irc, msg, args, state, errmsg=None):
errmsg = 'I haven\'t seen %s.' % args[0] errmsg = 'I haven\'t seen %s.' % args[0]
irc.error(errmsg) irc.error(errmsg)
def getChannel(irc, msg, args, state): def getChannel(irc, msg, args, state):
if args and irc.isChannel(args[0]): if args and irc.isChannel(args[0]):
channel = args.pop(0) channel = args.pop(0)
@ -497,6 +499,13 @@ def getIrcColor(irc, msg, args, state):
else: else:
irc.errorInvalid('irc color') irc.errorInvalid('irc color')
def getText(irc, msg, args, state):
if args:
state.args.append(' '.join(args))
args[:] = []
else:
raise IndexError
wrappers = ircutils.IrcDict({ wrappers = ircutils.IrcDict({
'id': getId, 'id': getId,
'ip': getIp, 'ip': getIp,
@ -528,8 +537,8 @@ wrappers = ircutils.IrcDict({
'something': getSomething, 'something': getSomething,
'filename': getSomething, # XXX Check for validity. 'filename': getSomething, # XXX Check for validity.
'commandName': getCommandName, 'commandName': getCommandName,
'text': getText,
'glob': getGlob, 'glob': getGlob,
'text': anything,
'somethingWithoutSpaces': getSomethingNoSpaces, 'somethingWithoutSpaces': getSomethingNoSpaces,
'capability': getSomethingNoSpaces, 'capability': getSomethingNoSpaces,
'channelDb': getChannelDb, 'channelDb': getChannelDb,
@ -594,10 +603,10 @@ class context(object):
self.converter = getConverter(spec) self.converter = getConverter(spec)
def __call__(self, irc, msg, args, state): def __call__(self, irc, msg, args, state):
if args and not (state.types or state.allowExtra): ## if args and not (state.types or state.allowExtra):
# We're the last context/type, we should combine the remaining ## # We're the last context/type, we should combine the remaining
# arguments into one string. ## # arguments into one string.
args[:] = [' '.join(args)] ## args[:] = [' '.join(args)]
log.debug('args before %r: %r', self, args) log.debug('args before %r: %r', self, args)
self.converter(irc, msg, args, state, *self.args) self.converter(irc, msg, args, state, *self.args)
log.debug('args after %r: %r', self, args) log.debug('args after %r: %r', self, args)
@ -605,6 +614,15 @@ class context(object):
def __repr__(self): def __repr__(self):
return '<%s for %s>' % (self.__class__.__name__, self.spec) return '<%s for %s>' % (self.__class__.__name__, self.spec)
class rest(context):
def __call__(self, irc, msg, args, state):
original = args[:]
args[:] = [' '.join(args)]
try:
super(rest, self).__call__(irc, msg, args, state)
except Exception, e:
args[:] = original
# additional means: Look for this (and make sure it's of this type). If # additional means: Look for this (and make sure it's of this type). If
# there are no arguments for us to check, then use our default. # there are no arguments for us to check, then use our default.
class additional(context): class additional(context):
@ -634,7 +652,6 @@ class optional(additional):
class any(context): class any(context):
def __call__(self, irc, msg, args, state): def __call__(self, irc, msg, args, state):
st = state.essence() st = state.essence()
st.types = ["something so context.__call__ won't combineRest."]
try: try:
while args: while args:
super(any, self).__call__(irc, msg, args, st) super(any, self).__call__(irc, msg, args, st)
@ -674,6 +691,25 @@ class reverse(context):
super(reverse, self).__call__(irc, msg, args, state) super(reverse, self).__call__(irc, msg, args, state)
args[:] = args[::-1] args[:] = args[::-1]
class commalist(context):
def __call__(self, irc, msg, args, state):
original = args[:]
st = state.essence()
trailingComma = True
try:
while trailingComma:
arg = args.pop(0)
if not arg.endswith(','):
trailingComma = False
for part in arg.split(','):
if part: # trailing commas
super(commalist, self).__call__(irc, msg, [part], st)
state.args.append(st.args)
except Exception, e:
args[:] = original
raise
class getopts(context): class getopts(context):
"""The empty string indicates that no argument is taken; None indicates """The empty string indicates that no argument is taken; None indicates
that there is no converter for the argument.""" that there is no converter for the argument."""
@ -710,20 +746,6 @@ class getopts(context):
args[:] = rest args[:] = rest
log.debug('args after %r: %r', self, args) log.debug('args after %r: %r', self, args)
# XXX Not ready.
class compose(context):
def __init__(self, *specs):
self.spec = specs
self.specs = list(specs)
utils.mapinto(contextify, self.specs)
def __call__(self, irc, msg, args, state):
st = state.essence()
for context in self.specs:
context(irc, msg, args, st)
args = st.args
state.args.extend(st.args)
### ###
# This is our state object, passed to converters along with irc, msg, and args. # This is our state object, passed to converters along with irc, msg, and args.
### ###
@ -777,8 +799,6 @@ class Spec(object):
raise callbacks.ArgumentError raise callbacks.ArgumentError
return state return state
# This is used below, but we need to rename it so its name isn't
# shadowed by our locals.
def wrap(f, specList=[], **kw): def wrap(f, specList=[], **kw):
spec = Spec(specList, **kw) spec = Spec(specList, **kw)
def newf(self, irc, msg, args, **kwargs): def newf(self, irc, msg, args, **kwargs):
@ -787,10 +807,24 @@ def wrap(f, specList=[], **kw):
return utils.changeFunctionName(newf, f.func_name, f.__doc__) return utils.changeFunctionName(newf, f.func_name, f.__doc__)
__all__ = ['wrap', 'context', 'additional', 'optional', 'any', 'compose', __all__ = [
'Spec', 'first', 'urlSnarfer', 'thread', 'reverse', # Contexts.
'many', 'getopts', 'getConverter', 'addConverter', 'callConverter'] 'any', 'many',
'optional', 'additional',
'rest', 'getopts',
'first', 'reverse',
'commalist',
# Converter helpers.
'getConverter', 'addConverter', 'callConverter',
# Decorators.
'urlSnarfer', 'thread',
# Functions.
'wrap',
# Stuff for testing.
'Spec',
]
# This doesn't work. Suck.
## if world.testing:
## __all__.append('Spec')
if world.testing:
__all__.append('Spec')
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -55,7 +55,7 @@ class CommandsTestCase(SupyTestCase):
self.assertState(['int', 'int', 'int'], ['1', '2', '3'], [1, 2, 3]) self.assertState(['int', 'int', 'int'], ['1', '2', '3'], [1, 2, 3])
def testRestHandling(self): def testRestHandling(self):
self.assertState([None], ['foo', 'bar', 'baz'], ['foo bar baz']) self.assertState([rest(None)], ['foo', 'bar', 'baz'], ['foo bar baz'])
def testOptional(self): def testOptional(self):
spec = [optional('int', 999), None] spec = [optional('int', 999), None]
@ -79,22 +79,11 @@ class CommandsTestCase(SupyTestCase):
['12', '--foo', 'baz', '--bar', '13', '15'], ['12', '--foo', 'baz', '--bar', '13', '15'],
[12, [('foo', 'baz'), ('bar', 13)], 15]) [12, [('foo', 'baz'), ('bar', 13)], 15])
def testCompose(self):
spec = [compose('somethingWithoutSpaces', 'lowered')]
self.assertState(spec, ['FOO'], ['foo'])
self.assertRaises(callbacks.Error,
self.assertState, spec, ['foo bar'], ['asdf'])
def testAny(self): def testAny(self):
self.assertState([any('int')], ['1', '2', '3'], [[1, 2, 3]]) self.assertState([any('int')], ['1', '2', '3'], [[1, 2, 3]])
self.assertState([None, any('int')], ['1', '2', '3'], ['1', [2, 3]]) self.assertState([None, any('int')], ['1', '2', '3'], ['1', [2, 3]])
self.assertState([any('int')], [], [[]]) self.assertState([any('int')], [], [[]])
## def testAny(self):
## self.assertState([None, any('int'), None],
## ['foo', 'bar'],
## ['foo', [], 'bar'])
def testMany(self): def testMany(self):
spec = [many('int')] spec = [many('int')]
self.assertState(spec, ['1', '2', '3'], [[1, 2, 3]]) self.assertState(spec, ['1', '2', '3'], [[1, 2, 3]])
@ -114,6 +103,15 @@ class CommandsTestCase(SupyTestCase):
def testGetId(self): def testGetId(self):
spec = ['id'] spec = ['id']
self.assertState(spec, ['#12'], [12]) self.assertState(spec, ['#12'], [12])
def testCommaList(self):
spec = [commalist('int')]
self.assertState(spec, ['12'], [[12]])
self.assertState(spec, ['12,', '10'], [[12, 10]])
self.assertState(spec, ['12,11,10,', '9'], [[12, 11, 10, 9]])
spec.append('int')
self.assertState(spec, ['12,11,10', '9'], [[12, 11, 10], 9])
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: