132 lines
3.7 KiB
Python
132 lines
3.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Nemubot is a modulable IRC bot, built around XML configuration files.
|
|
# Copyright (C) 2012 Mercier Pierre-Olivier
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import imp
|
|
import os
|
|
import readline
|
|
import shlex
|
|
import sys
|
|
import traceback
|
|
|
|
from . import builtins
|
|
|
|
|
|
class Prompt:
|
|
|
|
def __init__(self):
|
|
self.selectedServer = None
|
|
|
|
self.HOOKS_CAPS = dict()
|
|
self.HOOKS_LIST = dict()
|
|
|
|
def add_cap_hook(self, name, call, data=None):
|
|
self.HOOKS_CAPS[name] = (lambda d, t, c, p: call(d, t, c, p), data)
|
|
|
|
def add_list_hook(self, name, call):
|
|
self.HOOKS_LIST[name] = call
|
|
|
|
def lex_cmd(self, line):
|
|
"""Return an array of tokens
|
|
|
|
Argument:
|
|
line -- the line to lex
|
|
"""
|
|
|
|
try:
|
|
cmds = shlex.split(line)
|
|
except:
|
|
exc_type, exc_value, _ = sys.exc_info()
|
|
sys.stderr.write(traceback.format_exception_only(exc_type,
|
|
exc_value)[0])
|
|
return
|
|
|
|
bgn = 0
|
|
|
|
# Separate commands (command separator: ;)
|
|
for i in range(0, len(cmds)):
|
|
if cmds[i][-1] == ';':
|
|
if i != bgn:
|
|
yield cmds[bgn:i]
|
|
bgn = i + 1
|
|
|
|
# Return rest of the command (that not end with a ;)
|
|
if bgn != len(cmds):
|
|
yield cmds[bgn:]
|
|
|
|
def exec_cmd(self, toks, context):
|
|
"""Execute the command
|
|
|
|
Arguments:
|
|
toks -- lexed tokens to executes
|
|
context -- current bot context
|
|
"""
|
|
|
|
if toks[0] in builtins.CAPS:
|
|
return builtins.CAPS[toks[0]](toks, context, self)
|
|
elif toks[0] in self.HOOKS_CAPS:
|
|
f, d = self.HOOKS_CAPS[toks[0]]
|
|
return f(d, toks, context, self)
|
|
else:
|
|
print("Unknown command: `%s'" % toks[0])
|
|
return ""
|
|
|
|
def getPS1(self):
|
|
"""Get the PS1 associated to the selected server"""
|
|
if self.selectedServer is None:
|
|
return "nemubot"
|
|
else:
|
|
return self.selectedServer.id
|
|
|
|
def run(self, context):
|
|
"""Launch the prompt
|
|
|
|
Argument:
|
|
context -- current bot context
|
|
"""
|
|
|
|
ret = ""
|
|
while ret != "quit" and ret != "reset" and ret != "refresh":
|
|
try:
|
|
line = input("\033[0;33m%s§\033[0m " % self.getPS1())
|
|
cmds = self.lex_cmd(line.strip())
|
|
for toks in cmds:
|
|
try:
|
|
ret = self.exec_cmd(toks, context)
|
|
except:
|
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
traceback.print_exception(exc_type, exc_value,
|
|
exc_traceback)
|
|
except KeyboardInterrupt:
|
|
print("")
|
|
except EOFError:
|
|
ret = "quit"
|
|
print("quit")
|
|
return ret != "quit"
|
|
|
|
|
|
def hotswap(bak):
|
|
p = Prompt()
|
|
p.HOOKS_CAPS = bak.HOOKS_CAPS
|
|
p.HOOKS_LIST = bak.HOOKS_LIST
|
|
return p
|
|
|
|
|
|
def reload():
|
|
import prompt.builtins
|
|
imp.reload(prompt.builtins)
|