def expand(self, text): """ Looks at mud data and performs any highlights. It returns the final text--even if there were no highlights. @param text: the input text @type text: string @return: the finalized text--even if no highlights were expanded @rtype: string """ if text: faketext = ansi.filter_ansi(text) textlist = ansi.split_ansi_from_text(text) hlist = self._highlights.keys() hlist.sort() for mem in hlist: miter = self._highlights[mem][2].finditer(faketext) for m in miter: # we need to loop for multiple instances of the highlight begin, end = m.span() hl = self._highlights[mem][1] textlist = self.highlight(textlist, begin, end - begin, hl) # here we sweep through the text string to update our current # color and leftover color attributes self._currcolor, self._colorleftover = ansi.figure_color(textlist, self._currcolor, self._colorleftover) text = "".join(textlist) return text
def _decode_colors(self, ses, default_attr, line, pretext=[]): if self.unfinished_.has_key(ses): (currentcolor, leftover) = self.unfinished_[ses] else: currentcolor = list(ansi.DEFAULT_COLOR) leftover = '' for single in line.splitlines(1): current = [] tokens = ansi.split_ansi_from_text(leftover + single) leftover = '' lasttok = '' for tok in tokens: if ansi.is_color_token(tok): currentcolor, leftover = ansi.figure_color([tok], currentcolor, leftover) elif tok: attr = default_attr if currentcolor[ansi.PLACE_BOLD]: attr |= curses.A_BOLD if currentcolor[ansi.PLACE_UNDERLINE]: attr |= curses.A_UNDERLINE if currentcolor[ansi.PLACE_BLINK]: attr |= curses.A_BLINK if currentcolor[ansi.PLACE_REVERSE]: attr |= curses.A_REVERSE foreground = currentcolor[ansi.PLACE_FG] - 30 if 0 <= foreground and foreground <= 7: attr += curses_fore(foreground) background = currentcolor[ansi.PLACE_BG] - 40 if 0 <= background and background <= 7: attr += curses_back(background) lasttok = tok current.append((tok, attr)) if current: lines = self.lines_ current[:0] = pretext if not lasttok.endswith("\n"): # it is a prompt # # Append newline to prompts coming from another sessions if ses != exported.get_current_session(): current.append(("\n", curses.A_NORMAL)) else: if self.cfg_compact_ and self.prompt_ == current: # # Remove the identical prompt from previous output buffer: # lines[self.prompt_index_:self.prompt_index_ + 1] = [] else: self.prompt_ = current self.prompt_index_ = len(lines) self._append(current) # eliminating empty lines: elif current[0][0] != "\n" or not self.cfg_compact_: self._append(current) self.unfinished_[ses] = (currentcolor, leftover)
def _decode_colors(self, ses, default_attr, line, pretext=[]): if self.unfinished_.has_key(ses): (currentcolor, leftover) = self.unfinished_[ses] else: currentcolor = list(ansi.DEFAULT_COLOR) leftover = '' for single in line.splitlines(1): current = [] tokens = ansi.split_ansi_from_text(leftover + single) leftover = '' lasttok = '' for tok in tokens: if ansi.is_color_token(tok): currentcolor, leftover = ansi.figure_color([tok], currentcolor, leftover) elif tok: attr = default_attr if currentcolor[ansi.PLACE_BOLD]: attr |= curses.A_BOLD if currentcolor[ansi.PLACE_UNDERLINE]: attr |= curses.A_UNDERLINE if currentcolor[ansi.PLACE_BLINK]: attr |= curses.A_BLINK if currentcolor[ansi.PLACE_REVERSE]: attr |= curses.A_REVERSE foreground = currentcolor[ansi.PLACE_FG] - 30 if 0 <= foreground and foreground <= 7: attr += curses_fore(foreground) background = currentcolor[ansi.PLACE_BG] - 40 if 0 <= background and background <= 7: attr += curses_back(background) lasttok = tok current.append( (tok, attr) ) if current: lines = self.lines_ current[:0] = pretext if not lasttok.endswith("\n"): # it is a prompt # # Append newline to prompts coming from another sessions if ses != exported.get_current_session(): current.append( ("\n", curses.A_NORMAL) ) else: if self.cfg_compact_ and self.prompt_ == current: # # Remove the identical prompt from previous output buffer: # lines[self.prompt_index_:self.prompt_index_+1] = [] else: self.prompt_ = current self.prompt_index_ = len(lines) self._append(current) # eliminating empty lines: elif current[0][0] != "\n" or not self.cfg_compact_: self._append(current) self.unfinished_[ses] = (currentcolor, leftover)
def buffer_write(msg, txtbuffer, currentcolor, unfinishedcolor): """ Handles writing messages to a Tk Text widget taking into accound ANSI colors, message types, session scoping, and a variety of other things. @param msg: the ui.message.Message to write to the buffer @type msg: ui.message.Message @param txtbuffer: the Tk Text buffer to write to @type txtbuffer: Text @param currentcolor: the current color that we should start with @type currentcolor: color (list of ints) @param unfinishedcolor: the string of unfinished ANSI color stuff that we'll prepend to the string we're printing @type unfinishedcolor: string @returns: the new color and unfinished color @rtype: list of ints, string """ global myui line = msg.data ses = msg.session if msg.type == message.ERROR: if line.endswith("\n"): line = "%s%s%s\n" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) else: line = "%s%s%s" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) elif msg.type == message.USERDATA: if myui._do_i_echo == 1: if line.endswith("\n"): line = "%s%s%s\n" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) else: line = "%s%s%s" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) else: # if echo is not on--we don't print this return currentcolor, unfinishedcolor elif msg.type == message.LTDATA: if line.endswith("\n"): line = "# %s\n" % line[:-1].replace("\n", "\n# ") else: line = "# %s" % line.replace("\n", "\n# ") # now we go through and handle writing all the data index = 0 start = 0 # we prepend the session name to the text if this is not the # current session sending text and if the Message is session # scoped. if ses != None and ses != exported.get_current_session(): pretext = "[%s]" % ses.getName() if line.endswith("\n"): line = pretext + line[:-1].replace("\n", "\n" + pretext) + "\n" else: line = pretext + line.replace("\n", "\n" + pretext) + "\n" # we remove all \\r stuff because it's icky line = line.replace("\r", "") tokens = ansi.split_ansi_from_text(line) # each session has a saved current color for MUDDATA. we grab # that current color--or use our default if we don't have one # for the session yet. additionally, 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 msg.type == message.MUDDATA: color = currentcolor.get(ses, list(DEFAULT_COLOR)) leftover = unfinishedcolor.get(ses, "") else: color = list(DEFAULT_COLOR) leftover = "" for mem in tokens: if ansi.is_color_token(mem): color, leftover = ansi.figure_color([mem], color, leftover) else: format = [] fg = "" bg = "" # handle reverse if color[ansi.PLACE_REVERSE] == 0: if color[ansi.PLACE_FG] == -1: fg = "37" else: fg = str(color[ansi.PLACE_FG]) if color[ansi.PLACE_BG] != -1: bg = str(color[ansi.PLACE_BG]) else: if color[ansi.PLACE_BG] == -1: fg = "30" else: fg = str(color[ansi.PLACE_BG] - 10) if color[ansi.PLACE_FG] == -1: bg = "47" else: bg = str(color[ansi.PLACE_FG] + 10) # handle bold if color[ansi.PLACE_BOLD] == 1: fg = "b" + fg # handle underline if color[ansi.PLACE_UNDERLINE] == 1: format.append("u") format.append(fg) if bg: format.append(bg) # mem = add_special_characters(mem) # insert the text using the formatting tuple we just generated txtbuffer.insert("end", mem.decode(UNICODE_ENCODING), tuple(format)) return color, leftover
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 buffer_write(msg, txtbuffer, currentcolor, unfinishedcolor): """ Handles writing messages to a Tk Text widget taking into accound ANSI colors, message types, session scoping, and a variety of other things. @param msg: the ui.message.Message to write to the buffer @type msg: ui.message.Message @param txtbuffer: the Tk Text buffer to write to @type txtbuffer: Text @param currentcolor: the current color that we should start with @type currentcolor: color (list of ints) @param unfinishedcolor: the string of unfinished ANSI color stuff that we'll prepend to the string we're printing @type unfinishedcolor: string @returns: the new color and unfinished color @rtype: list of ints, string """ global myui line = msg.data ses = msg.session if msg.type == message.ERROR: if line.endswith("\n"): line = "%s%s%s\n" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) else: line = "%s%s%s" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) elif msg.type == message.USERDATA: if myui._do_i_echo == 1: if line.endswith("\n"): line = "%s%s%s\n" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) else: line = "%s%s%s" % (ansi.get_color("b blue"), line[:-1], ansi.get_color("default")) else: # if echo is not on--we don't print this return currentcolor, unfinishedcolor elif msg.type == message.LTDATA: if line.endswith("\n"): line = "# %s\n" % line[:-1].replace("\n", "\n# ") else: line = "# %s" % line.replace("\n", "\n# ") # now we go through and handle writing all the data index = 0 start = 0 # we prepend the session name to the text if this is not the # current session sending text and if the Message is session # scoped. if (ses != None and ses != exported.get_current_session()): pretext = "[%s]" % ses.getName() if line.endswith("\n"): line = (pretext + line[:-1].replace("\n", "\n" + pretext) + "\n") else: line = pretext + line.replace("\n", "\n" + pretext) + "\n" # we remove all \\r stuff because it's icky line = line.replace("\r", "") tokens = ansi.split_ansi_from_text(line) # each session has a saved current color for MUDDATA. we grab # that current color--or use our default if we don't have one # for the session yet. additionally, 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 msg.type == message.MUDDATA: color = currentcolor.get(ses, list(DEFAULT_COLOR)) leftover = unfinishedcolor.get(ses, "") else: color = list(DEFAULT_COLOR) leftover = "" for mem in tokens: if ansi.is_color_token(mem): color, leftover = ansi.figure_color([mem], color, leftover) else: format = [] fg = "" bg = "" # handle reverse if color[ansi.PLACE_REVERSE] == 0: if color[ansi.PLACE_FG] == -1: fg = "37" else: fg = str(color[ansi.PLACE_FG]) if color[ansi.PLACE_BG] != -1: bg = str(color[ansi.PLACE_BG]) else: if color[ansi.PLACE_BG] == -1: fg = "30" else: fg = str(color[ansi.PLACE_BG] - 10) if color[ansi.PLACE_FG] == -1: bg = "47" else: bg = str(color[ansi.PLACE_FG] + 10) # handle bold if color[ansi.PLACE_BOLD] == 1: fg = "b" + fg # handle underline if color[ansi.PLACE_UNDERLINE] == 1: format.append("u") format.append(fg) if bg: format.append(bg) # insert the text using the formatting tuple we just generated txtbuffer.insert('end', _decode(mem), tuple(format)) return color, leftover
def highlight(self, textlist, place, memlength, hl): """ Takes a bunch of stuff and applies the highlight involved. It's messy. @param textlist: the list of strings representing the incoming text--this is usually text interspersed with ansi color tokens. @type textlist: list of strings @param place: the point in the text (skipping over ansi color stuff) that marks the beginning of the highlight @type place: int @param memlength: the length of the string to be highlighted @type memlength: int @param hl: the highlight to apply @type hl: string @returns: the newly adjusted textlist @rtype: list of strings """ # first we find the place to stick the highlight thingy. i = 0 for i in range(0, len(textlist)): if not ansi.is_color_token(textlist[i]): if place > len(textlist[i]): place -= len(textlist[i]) else: break newlist = textlist[:i] newlist.append(textlist[i][:place]) newcolor = ansi.figure_color(newlist, self._currcolor)[0] newlist.append(hl) # if the string to highlight begins and ends in the # same token we deal with that and eject if len(textlist[i][place:]) >= memlength: newlist.append(textlist[i][place:place + memlength]) newlist.append(chr(27) + "[0m") color = ansi.convert_tuple_to_ansi(newcolor) if color: newlist.append(color) newlist.append(textlist[i][place + memlength:]) for mem in textlist[i+1:]: newlist.append(mem) return newlist newlist.append(textlist[i][place:]) # now we have to find the end of the highlight memlength -= len(textlist[i][place:]) j = i+1 for j in range(i+1, len(textlist)): if not ansi.is_color_token(textlist[j]): if memlength > len(textlist[j]): memlength -= len(textlist[j]) newlist.append(textlist[j]) else: break else: newcolor = ansi.figure_color([textlist[j]], newcolor, '')[0] newlist.append(textlist[j][:memlength]) newlist.append(chr(27) + "[0m") color = ansi.convert_tuple_to_ansi(newcolor) if color: newlist.append(color) newlist.append(textlist[j][memlength:]) for mem in textlist[j+1:]: newlist.append(mem) return newlist