From 4f384dc514de52b237fa590c6162432548454e5d Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 16 Mar 2015 23:30:23 +0100 Subject: [PATCH] Added support for screen readers via the new option command (which merges the ability to set the screenreader mode with the encoding command). The new setting.SCREENREADER_REGEX_STRIP allows to customize what the screenreader mode strips. --- evennia/commands/default/cmdset_player.py | 2 +- evennia/commands/default/cmdset_unloggedin.py | 1 + evennia/commands/default/player.py | 89 +++++++++---------- evennia/commands/default/unloggedin.py | 22 ++++- evennia/server/serversession.py | 18 ++-- evennia/server/session.py | 3 +- evennia/settings_default.py | 5 ++ 7 files changed, 85 insertions(+), 55 deletions(-) diff --git a/evennia/commands/default/cmdset_player.py b/evennia/commands/default/cmdset_player.py index e1dfd7642..7da8b82e4 100644 --- a/evennia/commands/default/cmdset_player.py +++ b/evennia/commands/default/cmdset_player.py @@ -32,7 +32,7 @@ class PlayerCmdSet(CmdSet): self.add(player.CmdCharCreate()) #self.add(player.CmdSessions()) self.add(player.CmdWho()) - self.add(player.CmdEncoding()) + self.add(player.CmdOption()) self.add(player.CmdQuit()) self.add(player.CmdPassword()) self.add(player.CmdColorTest()) diff --git a/evennia/commands/default/cmdset_unloggedin.py b/evennia/commands/default/cmdset_unloggedin.py index 6038fa5f3..5e43d5e8c 100644 --- a/evennia/commands/default/cmdset_unloggedin.py +++ b/evennia/commands/default/cmdset_unloggedin.py @@ -22,3 +22,4 @@ class UnloggedinCmdSet(CmdSet): self.add(unloggedin.CmdUnconnectedLook()) self.add(unloggedin.CmdUnconnectedHelp()) self.add(unloggedin.CmdUnconnectedEncoding()) + self.add(unloggedin.CmdUnconnectedScreenreader()) diff --git a/evennia/commands/default/player.py b/evennia/commands/default/player.py index ba9bcbaad..6a332e7a2 100644 --- a/evennia/commands/default/player.py +++ b/evennia/commands/default/player.py @@ -30,7 +30,7 @@ MULTISESSION_MODE = settings.MULTISESSION_MODE # limit symbol import for API __all__ = ("CmdOOCLook", "CmdIC", "CmdOOC", "CmdPassword", "CmdQuit", - "CmdCharCreate", "CmdEncoding", "CmdSessions", "CmdWho", + "CmdCharCreate", "CmdOption", "CmdSessions", "CmdWho", "CmdColorTest", "CmdQuell") # force max nr chars to 1 if mode is 0 or 1 @@ -405,67 +405,62 @@ class CmdWho(MuxPlayerCommand): self.msg(string) -class CmdEncoding(MuxPlayerCommand): +class CmdOption(MuxPlayerCommand): """ - set which text encoding to use + Set an account option - Usage: - @encoding/switches [] + @option + @option encoding = [encoding] + @option screenreader = on|off - Switches: - clear - clear your custom encoding + The text encoding is mostly an issue only if you want to use + non-ASCII characters (i.e. letters/symbols not found in English). + If you see that your characters look strange (or you get encoding + errors), you should use this command to set the server encoding to + be the same used in your client program. If given the empty string + (default), the custom encoding will be removed and only Evennia's + defaults will be used. + The screenreader setting strips the text output for users using + screen readers. It strips based on settings.SCREENREADER_REGEX_STRIP. - This sets the text encoding for communicating with Evennia. This is mostly - an issue only if you want to use non-ASCII characters (i.e. letters/symbols - not found in English). If you see that your characters look strange (or you - get encoding errors), you should use this command to set the server - encoding to be the same used in your client program. - - Common encodings are utf-8 (default), latin-1, ISO-8859-1 etc. - - If you don't submit an encoding, the current encoding will be displayed - instead. - """ - - key = "@encoding" - aliases = "@encode" + """ + key = "@option" + aliases = "@options" locks = "cmd:all()" def func(self): """ - Sets the encoding. + Implements the command """ - if self.session is None: return - if 'clear' in self.switches: - # remove customization - old_encoding = self.session.encoding - if old_encoding: - string = "Your custom text encoding ('%s') was cleared." % old_encoding - else: - string = "No custom encoding was set." - self.session.encoding = "utf-8" - elif not self.args: - # just list the encodings supported - pencoding = self.session.encoding - string = "" - if pencoding: - string += "Default encoding: {g%s{n (change with {w@encoding {n)" % pencoding - encodings = settings.ENCODINGS - if encodings: - string += "\nServer's alternative encodings (tested in this order):\n {g%s{n" % ", ".join(encodings) - if not string: - string = "No encodings found." - else: + if not self.args: + # list the option settings + string = "{wEncoding{n:\n" + pencoding = self.session.encoding or "None" + sencodings = settings.ENCODINGS + string += " Custom: %s\n Server: %s" % (pencoding, ", ".join(sencodings)) + string += "\n{wScreen Reader mode:{n %s" % self.session.screenreader + self.caller.msg(string) + return + + if not self.rhs: + self.caller.msg("Usage: @option [name = [value]]") + + if self.lhs == "encoding": # change encoding old_encoding = self.session.encoding - encoding = self.args - self.session.encoding = encoding - string = "Your custom text encoding was changed from '%s' to '%s'." % (old_encoding, encoding) - self.msg(string.strip()) + new_encoding = self.rhs.strip() or "utf-8" + self.session.encoding = new_encoding + self.caller.msg("Encoding was changed from %s to %s." % (old_encoding, new_encoding)) + return + + if self.lhs == "screenreader": + onoff = self.rhs.lower() == "on" + self.session.screenreader = onoff + self.caller.msg("Screen reader mode was turned {w%s{n." % ("on" if onoff else "off")) class CmdPassword(MuxPlayerCommand): diff --git a/evennia/commands/default/unloggedin.py b/evennia/commands/default/unloggedin.py index 09713d4b7..0b5380973 100644 --- a/evennia/commands/default/unloggedin.py +++ b/evennia/commands/default/unloggedin.py @@ -361,6 +361,7 @@ You are not yet logged into the game. Commands available at this point: {wlook{n - re-show the connection screen {whelp{n - show this help {wencoding{n - change the text encoding to match your client + {wscreenreader{n - make the server more suitable for use with screen readers {wquit{n - abort the connection First create an account e.g. with {wcreate Anna c67jHL8p{n @@ -397,7 +398,7 @@ class CmdUnconnectedEncoding(MuxCommand): """ key = "encoding" - aliases = "@encoding, @encode" + aliases = ("@encoding", "@encode") locks = "cmd:all()" def func(self): @@ -435,6 +436,25 @@ class CmdUnconnectedEncoding(MuxCommand): string = "Your custom text encoding was changed from '%s' to '%s'." % (old_encoding, encoding) self.caller.msg(string.strip()) +class CmdUnconnectedScreenreader(MuxCommand): + """ + Activate screenreader mode. + + Usage: + screenreader + + Used to flip screenreader mode on and off before logging in (when + logged in, use @option screenreader on). + """ + key = "screenreader" + aliases = "@screenreader" + + def func(self): + "Flips screenreader setting." + self.session.screenreader = not self.session.screenreader + string = "Screenreader mode turned {w%s{n." % ("on" if self.session.screenreader else "off") + self.caller.msg(string) + def _create_player(session, playername, password, permissions, typeclass=None): """ diff --git a/evennia/server/serversession.py b/evennia/server/serversession.py index 9261ccbb1..1393e29ee 100644 --- a/evennia/server/serversession.py +++ b/evennia/server/serversession.py @@ -7,6 +7,7 @@ It is stored on the Server side (as opposed to protocol-specific sessions which are stored on the Portal side) """ +import re from time import time from datetime import datetime from django.conf import settings @@ -18,11 +19,12 @@ from evennia.commands.cmdhandler import cmdhandler from evennia.commands.cmdsethandler import CmdSetHandler from evennia.server.session import Session -IDLE_COMMAND = settings.IDLE_COMMAND +_IDLE_COMMAND = settings.IDLE_COMMAND _GA = object.__getattribute__ _ObjectDB = None - -INLINEFUNC_ENABLED = settings.INLINEFUNC_ENABLED +_ANSI = None +_INLINEFUNC_ENABLED = settings.INLINEFUNC_ENABLED +_RE_SCREENREADER_REGEX = re.compile(r"%s" % settings.SCREENREADER_REGEX_STRIP, re.DOTALL + re.MULTILINE) # i18n from django.utils.translation import ugettext as _ @@ -205,7 +207,7 @@ class ServerSession(Session): # this is treated as a command input #text = to_unicode(escape_control_sequences(text), encoding=self.encoding) # handle the 'idle' command - if text.strip() == IDLE_COMMAND: + if text.strip() == _IDLE_COMMAND: self.update_session_counters(idle=True) return if self.player: @@ -227,8 +229,14 @@ class ServerSession(Session): Send Evennia -> User """ text = text if text else "" - if INLINEFUNC_ENABLED and not "raw" in kwargs: + if _INLINEFUNC_ENABLED and not "raw" in kwargs: text = parse_inlinefunc(text, strip="strip_inlinefunc" in kwargs, session=self) + if self.screenreader: + global _ANSI + if not _ANSI: + from evennia.utils import ansi as _ANSI + text = _ANSI.parse_ansi(text, strip_ansi=True, xterm256=False, mxp=False) + text = _RE_SCREENREADER_REGEX.sub("", text) session = kwargs.pop('session', None) session = session or self self.sessionhandler.data_out(session, text=text, **kwargs) diff --git a/evennia/server/session.py b/evennia/server/session.py index 2b2d49985..b353b1688 100644 --- a/evennia/server/session.py +++ b/evennia/server/session.py @@ -36,7 +36,7 @@ class Session(object): # names of attributes that should be affected by syncing. _attrs_to_sync = ('protocol_key', 'address', 'suid', 'sessid', 'uid', - 'uname', 'logged_in', 'puid', 'encoding', + 'uname', 'logged_in', 'puid', 'encoding', 'screenreader', 'conn_time', 'cmd_last', 'cmd_last_visible', 'cmd_total', 'protocol_flags', 'server_data', "cmdset_storage_string") @@ -74,6 +74,7 @@ class Session(object): self.cmd_last = self.conn_time self.cmd_total = 0 self.encoding = "utf-8" + self.screenreader = False self.protocol_flags = {} self.server_data = {} diff --git a/evennia/settings_default.py b/evennia/settings_default.py index c132e9283..963bc576f 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -140,6 +140,11 @@ IDLE_COMMAND = "idle" # Add sets for languages/regions your players are likely to use. # (see http://en.wikipedia.org/wiki/Character_encoding) ENCODINGS = ["utf-8", "latin-1", "ISO-8859-1"] +# Regular expression applied to all output to a given session in order +# to strip away characters (usually various forms of decorations) for the benefit +# of users with screen readers. Note that ANSI/MXP doesn't need to +# be stripped this way, that is handled automatically. +SCREENREADER_REGEX_STRIP = r"\+-+|\+$|\+~|--+|~~+|==+" # The game server opens an AMP port so that the portal can # communicate with it. This is an internal functionality of Evennia, usually # operating between two processes on the same machine. You usually don't need to