Added ability to make batch functions in the shell, and did some reworking of the event system in gamebase to allow it
This commit is contained in:
parent
9055d8b257
commit
bc70bad1c7
3 changed files with 130 additions and 54 deletions
68
gamebase.py
68
gamebase.py
|
@ -25,6 +25,7 @@ class GameBase(object):
|
||||||
self.ps2 = '? '
|
self.ps2 = '? '
|
||||||
self.eventQueue = []
|
self.eventQueue = []
|
||||||
self.gameTime = 0.0
|
self.gameTime = 0.0
|
||||||
|
self.skipLoop = True
|
||||||
|
|
||||||
# player info
|
# player info
|
||||||
self.playerx = -1
|
self.playerx = -1
|
||||||
|
@ -187,18 +188,18 @@ The letter is not case-sensitive."""
|
||||||
|
|
||||||
# Now we have a heading! Let's see if we can get there...
|
# Now we have a heading! Let's see if we can get there...
|
||||||
if (x, y) == (self.playerx, self.playery):
|
if (x, y) == (self.playerx, self.playery):
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.ArriveEvent(self.playerName, x, y, 0.0)))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.ArriveEvent(self.playerName, x, y, 0.0)))
|
||||||
return
|
return
|
||||||
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
||||||
if dist == -1:
|
if dist == -1:
|
||||||
print('{0} cannot reach {1}{2}.'.format(self.playerName, self.numberToLetter(x), y), file = self.outstream)
|
print('{0} cannot reach {1}{2}.'.format(self.playerName, self.numberToLetter(x), y), file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
pos = self.level.coordsToInt(self.playerx, self.playery)
|
pos = self.level.coordsToInt(self.playerx, self.playery)
|
||||||
space = path[pos]
|
space = path[pos]
|
||||||
if space == -1:
|
if space == -1:
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.ArriveEvent(self.playerName, self.playerx, self.playery, 0.0)))
|
self.setEvent(0.0, _ge.ArriveEvent(self.playerName, self.playerx, self.playery, 0.0))
|
||||||
return
|
return
|
||||||
#target = self.level.coordsToInt(x, y)
|
#target = self.level.coordsToInt(x, y)
|
||||||
t = 1
|
t = 1
|
||||||
|
@ -207,12 +208,11 @@ The letter is not case-sensitive."""
|
||||||
newx, newy = self.level.intToCoords(space)
|
newx, newy = self.level.intToCoords(space)
|
||||||
space = path[space]
|
space = path[space]
|
||||||
if space != -1:
|
if space != -1:
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
self.setEvent(t * speed, _ge.GoEvent(self.playerName, newx, newy))
|
||||||
else:
|
else:
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.ArriveEvent(self.playerName, newx, newy, t * speed)))
|
self.setEvent(t * speed, _ge.ArriveEvent(self.playerName, newx, newy, t * speed))
|
||||||
break
|
break
|
||||||
t += 1
|
t += 1
|
||||||
|
|
||||||
#newx, newy = self.level.intToCoords(space)
|
#newx, newy = self.level.intToCoords(space)
|
||||||
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.ArriveEvent(self.playerName, newx, newy, t * speed)))
|
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.ArriveEvent(self.playerName, newx, newy, t * speed)))
|
||||||
return
|
return
|
||||||
|
@ -236,7 +236,7 @@ Object can be the name of the object, or its coordinates."""
|
||||||
print(self.justifyText(str(thing)), file = self.outstream)
|
print(self.justifyText(str(thing)), file = self.outstream)
|
||||||
else:
|
else:
|
||||||
print("There is nothing to see here.\n", file = self.outstream)
|
print("There is nothing to see here.\n", file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
|
|
||||||
def use(self, args):
|
def use(self, args):
|
||||||
"""use [-r] [the] object [on [the] object2]
|
"""use [-r] [the] object [on [the] object2]
|
||||||
|
@ -261,21 +261,21 @@ the name of an item in the player's inventory."""
|
||||||
thing, x, y = self.parseCoords(args)
|
thing, x, y = self.parseCoords(args)
|
||||||
if thing == None:
|
if thing == None:
|
||||||
print("There is nothing to use.", file = self.outstream)
|
print("There is nothing to use.", file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
if thing.thingType != 'u' and thing.name not in self.playerInv:
|
if thing.thingType != 'u' and thing.name not in self.playerInv:
|
||||||
print("The {0} cannot be used.".format(thing.name), file = self.outstream)
|
print("The {0} cannot be used.".format(thing.name), file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Similar to go, but not quite the same.
|
# Similar to go, but not quite the same.
|
||||||
if (x, y) == (self.playerx, self.playery) or thing.name in self.playerInv:
|
if (x, y) == (self.playerx, self.playery) or thing.name in self.playerInv:
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + 0.125, _ge.UseEvent(thing)))
|
self.setEvent(0.125, _ge.UseEvent(thing))
|
||||||
return
|
return
|
||||||
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
||||||
if dist == -1:
|
if dist == -1:
|
||||||
print('{0} cannot reach the {1}.'.format(self.playerName, thing.name), file = self.outstream)
|
print('{0} cannot reach the {1}.'.format(self.playerName, thing.name), file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
pos = self.level.coordsToInt(self.playerx, self.playery)
|
pos = self.level.coordsToInt(self.playerx, self.playery)
|
||||||
|
@ -286,11 +286,11 @@ the name of an item in the player's inventory."""
|
||||||
while space != -1:
|
while space != -1:
|
||||||
newx, newy = self.level.intToCoords(space)
|
newx, newy = self.level.intToCoords(space)
|
||||||
space = path[space]
|
space = path[space]
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
self.setEvent(t * speed, _ge.GoEvent(self.playerName, newx, newy))
|
||||||
t += 1
|
t += 1
|
||||||
#newx, newy = self.level.intToCoords(space)
|
#newx, newy = self.level.intToCoords(space)
|
||||||
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed + 0.125, _ge.UseEvent(thing)))
|
self.setEvent(t * speed + 0.125, _ge.UseEvent(thing))
|
||||||
return
|
return
|
||||||
|
|
||||||
def useOn(self, args, speed):
|
def useOn(self, args, speed):
|
||||||
|
@ -302,16 +302,16 @@ the name of an item in the player's inventory."""
|
||||||
thing, x, y = self.parseCoords(args[onIndex+1:])
|
thing, x, y = self.parseCoords(args[onIndex+1:])
|
||||||
if item == None or item.name not in self.playerInv:
|
if item == None or item.name not in self.playerInv:
|
||||||
print("There is no {0} in the inventory.".format(item.name), file = self.outstream)
|
print("There is no {0} in the inventory.".format(item.name), file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
if thing == None and x < 0 and y < 0:
|
if thing == None and x < 0 and y < 0:
|
||||||
print("Argument contains 'to' but with no real predicate.", file = self.outstream)
|
print("Argument contains 'to' but with no real predicate.", file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Similar to go, but not quite the same.
|
# Similar to go, but not quite the same.
|
||||||
if (x, y) == (self.playerx, self.playery):
|
if (x, y) == (self.playerx, self.playery):
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + 0.125, _ge.UseOnEvent(item, thing)))
|
self.setEvent(0.125, _ge.UseOnEvent(item, thing))
|
||||||
return
|
return
|
||||||
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
||||||
if dist == -1:
|
if dist == -1:
|
||||||
|
@ -319,7 +319,7 @@ the name of an item in the player's inventory."""
|
||||||
print('{0} cannot reach the {1}.'.format(self.playerName, thing.name), file = self.outstream)
|
print('{0} cannot reach the {1}.'.format(self.playerName, thing.name), file = self.outstream)
|
||||||
else:
|
else:
|
||||||
print('{0} cannot reach {1}{2}.'.format(self.playerName, self.numberToLetter(x), y), file = self.outstream)
|
print('{0} cannot reach {1}{2}.'.format(self.playerName, self.numberToLetter(x), y), file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
pos = self.level.coordsToInt(self.playerx, self.playery)
|
pos = self.level.coordsToInt(self.playerx, self.playery)
|
||||||
|
@ -330,11 +330,11 @@ the name of an item in the player's inventory."""
|
||||||
while space != -1:
|
while space != -1:
|
||||||
newx, newy = self.level.intToCoords(space)
|
newx, newy = self.level.intToCoords(space)
|
||||||
space = path[space]
|
space = path[space]
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
self.setEvent(t * speed, _ge.GoEvent(self.playerName, newx, newy))
|
||||||
t += 1
|
t += 1
|
||||||
#newx, newy = self.level.intToCoords(space)
|
#newx, newy = self.level.intToCoords(space)
|
||||||
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed + 0.125, _ge.UseOnEvent(item, thing)))
|
self.setEvent(t * speed + 0.125, _ge.UseOnEvent(item, thing))
|
||||||
return
|
return
|
||||||
|
|
||||||
def take(self, args):
|
def take(self, args):
|
||||||
|
@ -357,17 +357,17 @@ Object can be the name of the object, or its coordinates."""
|
||||||
return
|
return
|
||||||
if thing.thingType != 'i':
|
if thing.thingType != 'i':
|
||||||
print("The {0} cannot be taken.".format(thing.name), file = self.outstream)
|
print("The {0} cannot be taken.".format(thing.name), file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Similar to go, but not quite the same.
|
# Similar to go, but not quite the same.
|
||||||
if (x, y) == (self.playerx, self.playery):
|
if (x, y) == (self.playerx, self.playery):
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + 0.125, _ge.TakeEvent(thing)))
|
self.setEvent(0.125, _ge.TakeEvent(thing))
|
||||||
return
|
return
|
||||||
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
dist, path = self.level.path(x, y, self.playerx, self.playery)
|
||||||
if dist == -1:
|
if dist == -1:
|
||||||
print('{0} cannot reach the {1}.'.format(self.playerName, thing.name), file = self.outstream)
|
print('{0} cannot reach the {1}.'.format(self.playerName, thing.name), file = self.outstream)
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
pos = self.level.coordsToInt(self.playerx, self.playery)
|
pos = self.level.coordsToInt(self.playerx, self.playery)
|
||||||
|
@ -378,11 +378,11 @@ Object can be the name of the object, or its coordinates."""
|
||||||
while space != -1:
|
while space != -1:
|
||||||
newx, newy = self.level.intToCoords(space)
|
newx, newy = self.level.intToCoords(space)
|
||||||
space = path[space]
|
space = path[space]
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
self.setEvent(t * speed, _ge.GoEvent(self.playerName, newx, newy))
|
||||||
t += 1
|
t += 1
|
||||||
#newx, newy = self.level.intToCoords(space)
|
#newx, newy = self.level.intToCoords(space)
|
||||||
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
#_hq.heappush(self.eventQueue, (self.gameTime + t * speed, _ge.GoEvent(self.playerName, newx, newy)))
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + t * speed + 0.125, _ge.TakeEvent(thing)))
|
self.setEvent(t * speed + 0.125, _ge.TakeEvent(thing))
|
||||||
return
|
return
|
||||||
|
|
||||||
def drop(self, args):
|
def drop(self, args):
|
||||||
|
@ -390,7 +390,7 @@ Object can be the name of the object, or its coordinates."""
|
||||||
if args[0] == 'the':
|
if args[0] == 'the':
|
||||||
args.pop(0)
|
args.pop(0)
|
||||||
if args[0] in self.playerInv:
|
if args[0] in self.playerInv:
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.DropEvent(self.playerInv[args[0]])))
|
self.setEvent(0.0, _ge.DropEvent(self.playerInv[args[0]]))
|
||||||
else:
|
else:
|
||||||
print('{0} do not have a {1}.'.format(self.playerName, args[0]), file = self.outstream)
|
print('{0} do not have a {1}.'.format(self.playerName, args[0]), file = self.outstream)
|
||||||
|
|
||||||
|
@ -464,7 +464,7 @@ Object can be the name of the object, or its coordinates."""
|
||||||
del self.persist[self.level.name][i]
|
del self.persist[self.level.name][i]
|
||||||
|
|
||||||
# push a no-op event so that saving doesn't cost player characters time
|
# push a no-op event so that saving doesn't cost player characters time
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadGame(self, args):
|
def loadGame(self, args):
|
||||||
|
@ -483,19 +483,29 @@ Object can be the name of the object, or its coordinates."""
|
||||||
self.playerName, x, y, self.playerInv, levelname, self.persist, self.eventQueue, self.gameTime = _pi.load(f)
|
self.playerName, x, y, self.playerInv, levelname, self.persist, self.eventQueue, self.gameTime = _pi.load(f)
|
||||||
#print(levelname, x, y, file = self.outstream)
|
#print(levelname, x, y, file = self.outstream)
|
||||||
self.loadMap((levelname, x, y))
|
self.loadMap((levelname, x, y))
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
#_hq.heappush(self.eventQueue, (self.gameTime, _ge.NoOpEvent()))
|
||||||
return
|
return
|
||||||
|
|
||||||
def gameEventLoop(self):
|
def gameEventLoop(self):
|
||||||
|
#print(self.skipLoop)
|
||||||
|
if self.skipLoop:
|
||||||
|
return
|
||||||
|
#print(self.skipLoop)
|
||||||
while len(self.eventQueue) > 0:
|
while len(self.eventQueue) > 0:
|
||||||
ev = _hq.heappop(self.eventQueue)
|
ev = _hq.heappop(self.eventQueue)
|
||||||
self.gameTime = ev[0]
|
self.gameTime = ev[0]
|
||||||
e = ev[1]
|
e = ev[1]
|
||||||
if self.__gameEvents[e.eventType](e):
|
if self.__gameEvents[e.eventType](e):
|
||||||
|
#print('break loop')
|
||||||
break
|
break
|
||||||
if len(self.eventQueue) == 0:
|
if len(self.eventQueue) == 0:
|
||||||
self.gameTime = 0.0
|
self.gameTime = 0.0
|
||||||
_ge.resetEventNum()
|
_ge.resetEventNum()
|
||||||
|
self.skipLoop = True
|
||||||
|
|
||||||
|
def setEvent(self, t, e, skip = False):
|
||||||
|
_hq.heappush(self.eventQueue, (self.gameTime + t, e))
|
||||||
|
self.skipLoop = skip
|
||||||
|
|
||||||
# default event handlers
|
# default event handlers
|
||||||
|
|
||||||
|
@ -540,14 +550,14 @@ Object can be the name of the object, or its coordinates."""
|
||||||
if e.thing.useFunc == '':
|
if e.thing.useFunc == '':
|
||||||
print('The {0} cannot be used by itself.'.format(e.thing.name), file = self.outstream)
|
print('The {0} cannot be used by itself.'.format(e.thing.name), file = self.outstream)
|
||||||
return True
|
return True
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + self.__useFuncs[e.thing.useFunc](e.thing), _ge.NoOpEvent()))
|
self.setEvent(self.__useFuncs[e.thing.useFunc](e.thing), _ge.NoOpEvent())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handleUseOn(self, e):
|
def handleUseOn(self, e):
|
||||||
if e.item.useOnFunc == '':
|
if e.item.useOnFunc == '':
|
||||||
print('The {0} cannot be used on other objects.'.format(e.item.name), file = self.outstream)
|
print('The {0} cannot be used on other objects.'.format(e.item.name), file = self.outstream)
|
||||||
return True
|
return True
|
||||||
_hq.heappush(self.eventQueue, (self.gameTime + self.__useFuncs[e.item.useOnFunc](e.item, e.thing), _ge.NoOpEvent()))
|
self.setEvent(self.__useFuncs[e.item.useOnFunc](e.item, e.thing), _ge.NoOpEvent())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handleTake(self, e):
|
def handleTake(self, e):
|
||||||
|
|
|
@ -54,7 +54,7 @@ class GameShell(Shell):
|
||||||
|
|
||||||
def man(self, args):
|
def man(self, args):
|
||||||
super(GameShell, self).man(args)
|
super(GameShell, self).man(args)
|
||||||
heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
|
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
|
||||||
|
|
||||||
def options(self, args):
|
def options(self, args):
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -182,7 +182,7 @@ If -l is given, a map legend will be printed under the map."""
|
||||||
for i in doors:
|
for i in doors:
|
||||||
legend.append(' {0}D{1}{2} - {3}'.format(self.color(doors[i][1][1:]), i, self.clearColor(), doors[i][0]))
|
legend.append(' {0}D{1}{2} - {3}'.format(self.color(doors[i][1][1:]), i, self.clearColor(), doors[i][0]))
|
||||||
print('\n'.join(legend))
|
print('\n'.join(legend))
|
||||||
heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
|
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
|
||||||
return
|
return
|
||||||
|
|
||||||
def status(self, args):
|
def status(self, args):
|
||||||
|
@ -199,7 +199,7 @@ If -l is given, a map legend will be printed under the map."""
|
||||||
ret.append("Player position:{0:.>64}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.playerx), self.gameBase.playery)))
|
ret.append("Player position:{0:.>64}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.playerx), self.gameBase.playery)))
|
||||||
ret.append("Prev. position:{0:.>65}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.prevx), self.gameBase.prevy)))
|
ret.append("Prev. position:{0:.>65}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.prevx), self.gameBase.prevy)))
|
||||||
print('\n'.join(ret))
|
print('\n'.join(ret))
|
||||||
heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
|
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
|
||||||
return
|
return
|
||||||
|
|
||||||
def inv(self, args):
|
def inv(self, args):
|
||||||
|
|
108
shell.py
108
shell.py
|
@ -20,22 +20,24 @@
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
# MA 02110-1301, USA.
|
# MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
# Ver. 0.1.0029
|
# Ver. 0.1.0032
|
||||||
|
|
||||||
|
|
||||||
import types as _types
|
import types as _types
|
||||||
import traceback as _tb
|
import traceback as _tb
|
||||||
import math as _math
|
import math as _math
|
||||||
|
import re as _re
|
||||||
|
|
||||||
_CONV24TO8 = 6 / 256
|
_CONV24TO8 = 6 / 256
|
||||||
|
|
||||||
class Shell(object):
|
class Shell(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__commands = {'exit': self.exitShell}
|
self.__commands = {'exit': self.exitShell, 'batch': self.batch, 'alias': self.makeAlias, 'def': self.defineBatch}
|
||||||
self.__aliases = {}
|
self.__aliases = {}
|
||||||
|
self.__batches = {}
|
||||||
self.ps1 = '> '
|
self.ps1 = '> '
|
||||||
self.ps2 = '> '
|
self.ps2 = '. '
|
||||||
self.colorMode = 0 # bits of color depth. Supports: 0, 3, 4, 8, 24
|
self.colorMode = 0 # bits of color depth. Supports: 0, 3, 4, 8, 24
|
||||||
self.prevColor = '\x1b[0m'
|
self.prevColor = '\x1b[0m'
|
||||||
self.__exit = False
|
self.__exit = False
|
||||||
|
@ -126,16 +128,7 @@ class Shell(object):
|
||||||
print(self.ps1, end = '')
|
print(self.ps1, end = '')
|
||||||
command = self.scanInput()
|
command = self.scanInput()
|
||||||
# we have to handle shell built-ins first (when we get some)
|
# we have to handle shell built-ins first (when we get some)
|
||||||
if len(command) == 0:
|
self.handleCommand(command)
|
||||||
continue
|
|
||||||
if command[0] in self.__commands:
|
|
||||||
try:
|
|
||||||
self.__commands[command[0]](command[1:])
|
|
||||||
except Exception as e:
|
|
||||||
_tb.print_exc()
|
|
||||||
print(e)
|
|
||||||
else:
|
|
||||||
self.handleUnknownCommand(command)
|
|
||||||
self.update()
|
self.update()
|
||||||
self.__exit = False
|
self.__exit = False
|
||||||
|
|
||||||
|
@ -152,20 +145,23 @@ conventionally called args or argv"""
|
||||||
'a' must be one token, but original can be multiple."""
|
'a' must be one token, but original can be multiple."""
|
||||||
self.__aliases[a] = original
|
self.__aliases[a] = original
|
||||||
|
|
||||||
|
def registerBatch(self, name: str, commands: list):
|
||||||
|
self.__batches[name] = commands
|
||||||
|
|
||||||
def getAlias(self, a: str):
|
def getAlias(self, a: str):
|
||||||
if a in self.__aliases:
|
if a in self.__aliases:
|
||||||
return self.__aliases[a]
|
return self.__aliases[a]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def exitShell(self, args):
|
def getBatch(self, name: str):
|
||||||
"""The default exit command."""
|
if name in self.__batches:
|
||||||
self.__exit = True
|
return ['batch']
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
# Beyond this point are functions that are called within the main loop.
|
def scanLine(self, instr):
|
||||||
def scanInput(self):
|
"""Take a line of text and turn it into an argument list"""
|
||||||
"""Parses input. Override this for custom input parsing, or input source."""
|
|
||||||
instr = input()
|
|
||||||
if instr == '':
|
if instr == '':
|
||||||
return []
|
return []
|
||||||
inQuotes = False
|
inQuotes = False
|
||||||
|
@ -193,9 +189,79 @@ conventionally called args or argv"""
|
||||||
ret.append(instr[argStart:c])
|
ret.append(instr[argStart:c])
|
||||||
a = self.getAlias(ret[0])
|
a = self.getAlias(ret[0])
|
||||||
if a:
|
if a:
|
||||||
ret = a[:] + ret[1:]
|
ret = a + ret[1:]
|
||||||
|
b = self.getBatch(ret[0])
|
||||||
|
if b:
|
||||||
|
ret = b + ret
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
# Default functions
|
||||||
|
|
||||||
|
def exitShell(self, args):
|
||||||
|
"""The default exit command."""
|
||||||
|
self.__exit = True
|
||||||
|
|
||||||
|
def makeAlias(self, args):
|
||||||
|
"""Make an alias."""
|
||||||
|
self.registerAlias(args[0], args[1:])
|
||||||
|
|
||||||
|
def defineBatch(self, args):
|
||||||
|
"""Define a batch file."""
|
||||||
|
if len(args) != 1:
|
||||||
|
raise ValueError('def takes only one argument')
|
||||||
|
ret = []
|
||||||
|
command = input(self.ps2)
|
||||||
|
while command != 'end':
|
||||||
|
ret.append(command)
|
||||||
|
command = input(self.ps2)
|
||||||
|
self.registerBatch(args[0], ret)
|
||||||
|
|
||||||
|
def batch(self, args):
|
||||||
|
"""Run commands in batch mode
|
||||||
|
$0 is the name of the batch
|
||||||
|
$1 - $n are individual arguments
|
||||||
|
$* is all the arguments except 0
|
||||||
|
$>0 - $>n is all arguments after the nth
|
||||||
|
$>=0 - $>=n is the nth and later arguments"""
|
||||||
|
script = self.__batches[args[0]]
|
||||||
|
var = _re.compile(r'\$((?:[>][=]?)?[0-9]+)')
|
||||||
|
u = False
|
||||||
|
for line in script:
|
||||||
|
if u:
|
||||||
|
self.update()
|
||||||
|
else:
|
||||||
|
u = True
|
||||||
|
newLine = line.replace(r'$*', ' '.join(args[1:]))
|
||||||
|
matches = var.finditer(newLine)
|
||||||
|
for m in matches:
|
||||||
|
n = m.group(1)
|
||||||
|
if n[0] == '>':
|
||||||
|
if n[1] == '=':
|
||||||
|
num = int(n[2:])
|
||||||
|
else:
|
||||||
|
num = int(n[1:])+1
|
||||||
|
newLine = newLine.replace(m.group(), ' '.join(args[num:]))
|
||||||
|
else:
|
||||||
|
newLine = newLine.replace(m.group(), args[int(n)])
|
||||||
|
self.handleCommand(self.scanLine(newLine))
|
||||||
|
|
||||||
|
# Beyond this point are functions that are called within the main loop.
|
||||||
|
def scanInput(self):
|
||||||
|
"""Parses input. Override this for custom input parsing, or input source."""
|
||||||
|
return self.scanLine(input())
|
||||||
|
|
||||||
|
def handleCommand(self, command):
|
||||||
|
if len(command) == 0:
|
||||||
|
return
|
||||||
|
if command[0] in self.__commands:
|
||||||
|
try:
|
||||||
|
self.__commands[command[0]](command[1:])
|
||||||
|
except Exception as e:
|
||||||
|
_tb.print_exc()
|
||||||
|
print(e)
|
||||||
|
else:
|
||||||
|
self.handleUnknownCommand(command)
|
||||||
|
|
||||||
def handleUnknownCommand(self, command):
|
def handleUnknownCommand(self, command):
|
||||||
"""Handle commands that aren't registered. Override this if you want to do
|
"""Handle commands that aren't registered. Override this if you want to do
|
||||||
something with those commands."""
|
something with those commands."""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue