Cleaned up the ansi.py module and made it better match the the style rest of the code.

This commit is contained in:
Griatch 2010-09-05 20:59:32 +00:00
parent e125763ea5
commit 7e736d19e2
5 changed files with 91 additions and 93 deletions

View file

@ -84,6 +84,7 @@ def instantiate(cmd):
return cmd()
return cmd
class CmdSet(object):
"""
This class describes a unique cmdset that understands priorities. CmdSets

View file

@ -150,9 +150,3 @@ class HelpEntry(SharedMemoryModel):
def __unicode__(self):
return u'%s' % self.key
def get_entrytext_ingame(self):
"""
Gets the entry text for in-game viewing.
"""
return ansi.parse_ansi(self.entrytext)

View file

@ -48,7 +48,6 @@ from src.server import sessionhandler
from src.players import manager
from src.typeclasses.models import Attribute, TypedObject
from src.permissions import permissions
from src.utils.ansi import parse_ansi
from src.utils import logger
#------------------------------------------------------------
@ -248,12 +247,11 @@ class PlayerDB(TypedObject):
"Delete permission from old ones"
return permissions.del_perm(self, perm)
#
# PlayerDB class access methods
#
def msg(self, message, from_obj=None):
def msg(self, message, from_obj=None, markup=True):
"""
This duplicates the same-named method on the Character.
It forwards messages to the character or uses
@ -268,8 +266,9 @@ class PlayerDB(TypedObject):
except Exception:
pass
if self.at_msg_receive(message, from_obj):
for session in self.sessions:
session.msg(parse_ansi(message))
for session in object.__getattribute__(self, 'sessions'):
session.msg(message, markup)
def emit_to(self, message, from_obj=None):
"""
Deprecated. Use msg instead.

View file

@ -125,11 +125,7 @@ class SessionProtocol(StatefulTelnetProtocol):
except Exception, e:
self.sendLine(str(e))
return
if markup:
message = ansi.parse_ansi(message)
else:
message = ansi.clean_ansi(message)
self.sendLine(message)
self.sendLine(ansi.parse_ansi(message, strip_ansi=not markup))
def get_character(self):
"""

View file

@ -1,11 +1,25 @@
"""
ANSI - gives colour to text.
ANSI - Gives colour to text.
Use the codes defined in ANSIPARSER in your text
to apply colour to text according to the ANSI standard.
Examples:
This is %crRed text%cn and this is normal again.
This is {rRed text{n and this is normal again.
Mostly you should not need to call parse_ansi() explicitly;
it is run by Evennia just before returning data to/from the
user.
"""
import re
class ANSITable(object):
"""
A table of ANSI characters to use when replacing things.
A table defining the
standard ANSI command sequences.
"""
ansi = {}
ansi["beep"] = "\07"
@ -46,41 +60,19 @@ class ANSITable(object):
ansi["tab"] = "\t"
ansi["space"] = " "
class BaseParser(object):
def parse_ansi(self, string, strip_ansi=False, strip_formatting=False):
"""
Parses a string, subbing color codes as needed.
"""
if string == None or string == '':
return ''
# Convert to string to prevent problems with lists, ints, and other types.
string = str(string)
# if strip_formatting:
# char_return = ""
# char_tab = ""
# char_space = ""
# else:
# char_return = ANSITable.ansi["return"]
# char_tab = ANSITable.ansi["tab"]
# char_space = ANSITable.ansi["space"]
for sub in self.ansi_subs:
p = re.compile(sub[0], re.DOTALL)
if strip_ansi:
string = p.sub("", string)
else:
string = p.sub(sub[1], string)
if strip_ansi:
return '%s' % (string)
else:
return '%s%s' % (string, ANSITable.ansi["normal"])
class MuxANSIParser(BaseParser):
class ANSIParser(object):
"""
A class that parses ansi markup
to ANSI command sequences
"""
def __init__(self):
self.ansi_subs = [
"Sets the mappings"
# MUX-style mappings %cr %cn etc
mux_ansi_map = [
(r'%r', ANSITable.ansi["return"]),
(r'%t', ANSITable.ansi["tab"]),
(r'%b', ANSITable.ansi["space"]),
@ -104,52 +96,68 @@ class MuxANSIParser(BaseParser):
(r'%cC', ANSITable.ansi["back_cyan"]),
(r'%cw', ANSITable.ansi["white"]),
(r'%cW', ANSITable.ansi["back_white"]),
]
]
# Expanded mapping {r {n etc
class ExtendedANSIParser(MuxANSIParser):
"""
Extends the standard mux colour commands with {-style commands
(shortcuts for writing light/dark text without background)
"""
def __init__(self):
super(ExtendedANSIParser, self).__init__()
hilite = ANSITable.ansi['hilite']
normal = ANSITable.ansi['normal']
self.ansi_subs.extend( [
(r'{r', hilite + ANSITable.ansi['red']),
(r'{R', normal + ANSITable.ansi['red']),
(r'{g', hilite + ANSITable.ansi['green']),
(r'{G', normal + ANSITable.ansi['green']),
(r'{y', hilite + ANSITable.ansi['yellow']),
(r'{Y', normal + ANSITable.ansi['yellow']),
(r'{b', hilite + ANSITable.ansi['blue']),
(r'{B', normal + ANSITable.ansi['blue']),
(r'{m', hilite + ANSITable.ansi['magenta']),
(r'{M', normal + ANSITable.ansi['magenta']),
(r'{c', hilite + ANSITable.ansi['cyan']),
(r'{C', normal + ANSITable.ansi['cyan']),
(r'{w', hilite + ANSITable.ansi['white']), #white
(r'{W', normal + ANSITable.ansi['white']), #light grey
(r'{x', hilite + ANSITable.ansi['black']), #dark grey
(r'{X', normal + ANSITable.ansi['black']), #pure black
(r'{n', normal) #reset
] )
#ANSI_PARSER = MuxANSIParser()
ANSI_PARSER = ExtendedANSIParser()
ext_ansi_map = [
(r'{r', hilite + ANSITable.ansi['red']),
(r'{R', normal + ANSITable.ansi['red']),
(r'{g', hilite + ANSITable.ansi['green']),
(r'{G', normal + ANSITable.ansi['green']),
(r'{y', hilite + ANSITable.ansi['yellow']),
(r'{Y', normal + ANSITable.ansi['yellow']),
(r'{b', hilite + ANSITable.ansi['blue']),
(r'{B', normal + ANSITable.ansi['blue']),
(r'{m', hilite + ANSITable.ansi['magenta']),
(r'{M', normal + ANSITable.ansi['magenta']),
(r'{c', hilite + ANSITable.ansi['cyan']),
(r'{C', normal + ANSITable.ansi['cyan']),
(r'{w', hilite + ANSITable.ansi['white']), #white
(r'{W', normal + ANSITable.ansi['white']), #light grey
(r'{x', hilite + ANSITable.ansi['black']), #dark grey
(r'{X', normal + ANSITable.ansi['black']), #pure black
(r'{n', normal) #reset
]
def parse_ansi(string, strip_ansi=False, strip_formatting=False, parser=ANSI_PARSER):
self.ansi_map = mux_ansi_map + ext_ansi_map
# prepare regex matching
self.ansi_sub = [(re.compile(sub[0], re.DOTALL), sub[1])
for sub in self.ansi_map]
# prepare matching ansi codes overall
self.ansi_regex = re.compile("\033\[[0-9;]+m")
def parse_ansi(self, string, strip_ansi=False):
"""
Parses a string, subbing color codes according to
the stored mapping.
strip_ansi flag instead removes all ansi markup.
"""
if not string:
return ''
string = str(string)
for sub in self.ansi_sub:
# go through all available mappings and translate them
string = sub[0].sub(sub[1], string)
if strip_ansi:
# remove all ANSI escape codes
string = self.ansi_regex.sub("", string)
return string
ANSI_PARSER = ANSIParser()
#
# Access function
#
def parse_ansi(string, strip_ansi=False, parser=ANSI_PARSER):
"""
Parses a string, subbing color codes as needed.
"""
return parser.parse_ansi(string, strip_ansi=strip_ansi,
strip_formatting=strip_formatting)
def clean_ansi(string):
"""
Cleans all ansi symbols from a string
"""
# convert all to their ansi counterpart
string = parse_ansi(string)
# next, strip it all away
regex = re.compile("\033\[[0-9;]+m")
return regex.sub("", string) #replace all matches with empty strings
return parser.parse_ansi(string, strip_ansi=strip_ansi)