def createInputEvent(self, tkevent): """ Handles the <KeyPress-Return> event.""" val = fix_unicode(self.get()) ## # JLP: remove special characters ## val = val.replace("à", "a") ## val = val.replace("â", "a") ## val = val.replace("ç", "c") ## val = val.replace("é", "e") ## val = val.replace("è", "e") ## val = val.replace("ê", "e") ## val = val.replace("î", "i") ## val = val.replace("ô", "o") ## val = val.replace("ù", "u") ## val = val.replace("û", "u") self._partk.handleinput(val) # self._inputstack.insert(0, val) # if len(self._inputstack) > 30: # self._inputstack = self._inputstack[:-1] if exported.get_config("saveinputhighlight") == 1: self.selection_range(0, 'end') else: self.delete(0, 'end') self.hist_index = -1 if val == exported.get_config("commandchar") + "end": self._partk._topframe.quit()
def snoop_cmd(ses, args, input): """ Sets the session specified into or out of snooping mode. When a session is in snoop mode, you will see mud data from that session regardless of what session is the current session. examples: #snoop a -- tells you whether a is in snoop mode #snoop a on -- sets snoop mode for a category: commands """ snoopsession = args["session"] mode = args["mode"] ses = exported.get_session(snoopsession) if ses == None: exported.write_error("snoop: session '%s' does not exist." % snoopsession) return if mode != None: ses.setSnoop(mode) if exported.get_config("snoop", ses, 1) == 1: exported.write_message("snoop: snooping is enabled for %s." % snoopsession) else: exported.write_message("snoop: snooping is disabled for %s." % snoopsession)
def createInputEvent(self, tkevent): """ Handles the <KeyPress-Return> event.""" val = fix_unicode(self.get()) self._partk.handleinput(val) # self._inputstack.insert(0, val) # if len(self._inputstack) > 30: # self._inputstack = self._inputstack[:-1] if exported.get_config("saveinputhighlight") == 1: self.selection_range(0, 'end') else: self.delete(0, 'end') self.hist_index = -1 if val == exported.get_config("commandchar") + "end": self._partk._topframe.quit()
def callBinding(self, tkevent): """ Handles arbitrary bindings of function call keypresses.""" # handle all the function keys except F1 if tkevent.keysym == "F1": self._partk.handleinput(exported.get_config("commandchar") + "help") return "break" if self._executeBinding("VK_%s" % tkevent.keysym) == 1: return "break"
def mudfilter(self, args): """ mud_filter_hook function to perform substitutions on data that comes from the mud. """ ses = args["session"] text = args["dataadj"] if exported.get_config("ignoresubs", ses, 0) == 0: text = self.expand(ses, text) return text
def mudfilter(self, args): """ mud_filter_hook function to check for actions when data comes from the mud. """ ses = args["session"] text = args["dataadj"] if exported.get_config("ignoreactions", ses, 0) == 0: if self._actions.has_key(ses): self._actions[ses].checkActions(text) return text
def __init__(self): base.BaseUI.__init__(self) locale.setlocale(locale.LC_ALL, "") exported.hook_register("startup_hook", startup_hook) exported.hook_register("to_user_hook", self.write) exported.hook_register("config_change_hook", self.config_changed) exported.hook_register("bell_hook", lambda x: sys.stdout.write('\07')) exported.hook_register( "prompt_hook", lambda x: self.write({ 'message': message.Message(x["prompt"], message.MUDDATA, x["session"]) })) exported.hook_register("write_hook", bindings_persist) self.unfinished_ = {} self.prompt_ = [("", curses.A_NORMAL)] self.lines_ = [self.prompt_] self.prompt_index_ = 0 self.running_ = 1 self.cfg_lazy_ = exported.get_config("curses.lazy") self.cfg_maxscrollback_ = exported.get_config("curses.maxscrollback") self.cfg_keydebug_ = exported.get_config("curses.keydebug") self.cfg_compact_ = exported.get_config("curses.compact") self.cfg_echo_ = exported.get_config("mudecho") global color_lookup self.attr_error_ = color_lookup[exported.get_config( "curses.attr.error")] self.attr_session_ = color_lookup[exported.get_config( "curses.attr.session")] self.attr_lyntin_ = color_lookup[exported.get_config( "curses.attr.lyntin")] self.attr_user_ = color_lookup[exported.get_config("curses.attr.user")] self.output_ = os.pipe() # MUD output signalling pipe
def runui(self): global HELP_TEXT exported.add_help("textui", HELP_TEXT) exported.write_message("For textui help, type \"#help textui\".") # termios is the module that allows us to change echo for a terminal # but only if the module is present try: import termios except ImportError: self._tio = 0 else: self._tio = 1 echonew = termios.tcgetattr(self._stdin.fileno()) self._onecho_attr = echonew[3] self._offecho_attr = echonew[3] & ~termios.ECHO if config.options.has_key("readline"): try: import readline except ImportError: self._rline = 0 exported.write_error("Readline not available for your system.") else: self._rline = 1 # we do some stuff to grab the readlinerc file if they have one # so the user can set some readline oriented things which makes # things a little nicer for the user. d = exported.get_config("datadir") try: readline.read_init_file(d + "readlinerc") except: exported.write_error( "Note: No readlinerc file available in %s." % d) exported.write_message("Readline enabled.") if self._tio == 0 or self._rline == 1: exported.write_error("Warming: echo off is unavailable. " + "Your password will be visible.") # go into the main loop self.run()
def showTextForSession(self, ses): """ Returns whether or not we should show text for this session--it's a convenience method. We return a 1 if the session is None, it doesn't have a _snoop attribute, it's the current session, or get_config("snoop", ses) == 1. @param ses: the session we're looking at--if it's None we return a 1 @type ses: Session @returns: 1 if we should show text, 0 if not @rtype: boolean """ if ses == None or getattr(ses, "_snoop", None) == None \ or exported.get_current_session() == ses \ or exported.get_config("snoop", ses, 1) == 1: return 1 return 0
def write(self, args): """ Handles writing information from the mud and/or Lyntin to the user. """ msg = args["message"] if type(msg) == types.StringType: msg = message.Message(msg, message.LTDATA) if not hasattr(msg, "data"): return line = msg.data ses = msg.session if line == '' or self.showTextForSession(ses) == 0: return # we prepend the session name to the text if this is not the # current session sending text. pretext = "" if ses != None and ses != exported.get_current_session(): pretext = "[" + ses.getName() + "] " if msg.type == message.ERROR or msg.type == message.LTDATA: if msg.type == message.ERROR: pretext = "error: " + pretext line = pretext + utils.chomp(line).replace("\n", "\n" + pretext) self.window.write(line+"\n") return elif msg.type == message.MUDDATA: if "\n" not in msg.data: msg.data = msg.data + "\n" self.window.write(msg.data) return if exported.get_config("ansicolor") == 0: if pretext: if line.endswith("\n"): line = (pretext + line[:-1].replace("\n", "\n" + pretext) + "\n") else: line = pretext + line.replace("\n", "\n" + pretext) self.window.write(line) return
def userfilter(self, args): """ user_filter_hook function to check for speedwalking expansion. """ ses = args["session"] internal = args["internal"] verbatim = args["verbatim"] text = args["dataadj"] if not self._hashes.has_key(ses) or exported.get_config( "speedwalk", ses) == 0 or verbatim == 1: return text sdata = self._hashes[ses] if not sdata._dirs or not sdata._regexp or text in sdata._excludes \ or text in sdata._aliases or not sdata._regexp.match(text): return text swdirs = [] dir = num = "" for char in text: if char.isdigit(): num = num + char else: dir = dir + char if dir in sdata._dirs_available: if num: count = int(num) else: count = 1 for i in range(count): swdirs.append(sdata._dirs[dir]) dir = num = "" output = ";".join(swdirs) if output == text: return text else: # anything that gets recursed on should be recursed internally exported.lyntin_command(output, 1, ses) return None
def handleUserData(self, input, internal=0): """ Handles input in the context of this session specifically. @param input: the user data @type input: string @param internal: whether the command came from interally. we won't spam hooks and may at some point prevent output for internal stuff too. 1 if internal, 0 if not. @type internal: boolean """ # this is the point of much recursion. everything is registered # as a filter and recurses accordingly. spamargs = { "session": self, "internal": internal, "verbatim": exported.get_config("verbatim", self), "data": input, "dataadj": input } spamargs = exported.filter_mapper_hook_spam("user_filter_hook", spamargs) if spamargs == None: return else: input = spamargs["dataadj"] # after this point we don't do any more recursion. so it's # safe to unescape things and such. input = input.replace("\\;", ";") input = input.replace("\\$", "$") input = input.replace("\\%", "%") # just regular data to the mud self.writeSocket(input + "\n")
def write(self, args): """ Handles writing information from the mud and/or Lyntin to the user. """ msg = args["message"] if type(msg) == types.StringType: msg = message.Message(msg, message.LTDATA) line = msg.data ses = msg.session if line == '' or self.showTextForSession(ses) == 0: return # we prepend the session name to the text if this is not the # current session sending text. pretext = "" if ses != None and ses != exported.get_current_session(): pretext = "[" + ses.getName() + "] " if msg.type == message.ERROR or msg.type == message.LTDATA: if msg.type == message.ERROR: pretext = "error: " + pretext else: pretext = "lyntin: " + pretext line = pretext + utils.chomp(line).replace("\n", "\n" + pretext) if exported.get_config("ansicolor") == 1: line = DEFAULT_ANSI + line sys.stdout.write(line + "\n") return elif msg.type == message.USERDATA: # we don't print user data in the textui return if exported.get_config("ansicolor") == 0: if pretext: if line.endswith("\n"): line = (pretext + line[:-1].replace("\n", "\n" + pretext) + "\n") else: line = pretext + line.replace("\n", "\n" + pretext) sys.stdout.write(line) sys.stdout.flush() return # each session has a saved current color for mud data. we grab # that current color--or user our default if we don't have one # for the session yet. if self._currcolors.has_key(ses): color = self._currcolors[ses] else: # need a copy of the list and not a reference to the list itself. color = list(DEFAULT_COLOR) # some sessions have an unfinished color as well--in case we # got a part of an ansi color code in a mud message, and the other # part is in another message. if self._unfinishedcolor.has_key(ses): leftover = self._unfinishedcolor[ses] else: leftover = "" lines = line.splitlines(1) if lines: for i in range(0, len(lines)): mem = lines[i] acolor = ansi.convert_tuple_to_ansi(color) color, leftover = ansi.figure_color(mem, color, leftover) if pretext: lines[i] = DEFAULT_ANSI + pretext + acolor + mem else: lines[i] = DEFAULT_ANSI + acolor + mem sys.stdout.write("".join(lines) + DEFAULT_ANSI) sys.stdout.flush() self._currcolors[ses] = color self._unfinishedcolor[ses] = leftover
def deathHandler(self, tkevent): """ This catches the event where the window is being closed. We can't stop it from closing, but we can try to shut down the app. """ self._partk.handleinput(exported.get_config("commandchar") + "end")
else: f = open(filename, "r") contents = f.readlines() f.close() except Exception, e: exported.write_error( "read: file %s cannot be opened.\n%s" % (filename, e), ses) return contents = [m for m in contents if len(m.strip()) > 0] if len(contents) == 0: exported.write_message("read: %s had no data." % filename, ses) return c = exported.get_config("commandchar") if not contents[0].startswith(c): exported.lyntin_command("%sconfig commandchar %s" % (c, contents[0][0]), internal=1, session=ses) command = "" continued = 0 # FIXME - should this be a config setting? esc = "\\" for mem in contents: mem = mem.strip() if len(mem) > 0: # handle multi-line commands
def read_cmd(ses, args, input): """ Reads in a file running each line as a Lyntin command. This is the opposite of #write which allows you to save session settings and restore them using #read. You can also read in via the commandline when you start Lyntin: lyntin --read 3k And read can handle HTTP urls: lyntin --read http://lyntin.sourceforge.net/lyntinrc #read http://lyntin.sourceforge.net/lyntinrc Note: the first non-whitespace char is used to set the Lyntin command character. If you use non Lyntin commands in your file, make sure the first one is a command char. If not, use #nop . It will skip blank lines. If you don't specify a directory, Lyntin will look for the file in your datadir. category: commands """ filename = args["filename"] import os if os.sep not in filename and not filename.startswith("http://"): filename = config.options["datadir"] + filename if filename.startswith("~"): filename = os.path.expanduser(filename) try: # http reading contributed by Sebastian John if filename.startswith("http://"): contents = utils.http_get(filename).split("\n") else: f = open(filename, "rb") contents = f.readlines() f.close() except Exception as e: exported.write_error( "read: file %s cannot be opened.\n%s" % (filename, e), ses) return contents = [x.decode("utf-8") for x in contents] contents = [m for m in contents if len(m.strip()) > 0] if len(contents) == 0: exported.write_message("read: %s had no data." % filename, ses) return c = exported.get_config("commandchar") if not contents[0].startswith(c): exported.lyntin_command("%sconfig commandchar %s" % (c, contents[0][0]), internal=1, session=ses) command = "" continued = 0 # FIXME - should this be a config setting? esc = "\\" for mem in contents: mem = mem.strip() if len(mem) > 0: # handle multi-line commands if mem.endswith(esc): mem = mem.rstrip(esc) continued = 1 else: continued = 0 command = command + mem if not continued: exported.lyntin_command(command, internal=1, session=ses) command = "" exported.write_message("read: file %s read." % filename, ses)