<commit_before>"""
Evennia Mutltidescer

Contrib - Griatch 2016

A "multidescer" is a concept from the MUSH world. It allows for
creating, managing and switching between multiple character
descriptions. This multidescer will not require any changes to the
Character class, rather it will use the `multidescs` Attribute (a
list) and create it if it does not exist.

This contrib also works well together with the rpsystem contrib (which
also adds the short descriptions and the `sdesc` command).


Installation:

Edit `mygame/commands/default_cmdsets.py` and add
`from contrib.multidesc import CmdMultiDesc` to the top.

Next, look up the `at_cmdset_create` method of the `CharacterCmdSet`
class and add a line `self.add(CmdMultiDesc())` to the end
of it.

Reload the server and you should have the +desc command available (it
will replace the default `desc` command).

"""
import re
from evennia import default_cmds
from evennia.utils.utils import crop
from evennia.utils.eveditor import EvEditor


# regex for the set functionality
_RE_KEYS = re.compile(r"([\w\s]+)(?:\+*?)", re.U + re.I)


# Helper functions for the Command

class DescValidateError(ValueError):
    "Used for tracebacks from desc systems"
    pass


def _update_store(caller, key=None, desc=None, delete=False, swapkey=None):
    """
    Helper function for updating the database store.

    Args:
        caller (Object): The caller of the command.
        key (str): Description identifier
        desc (str): Description text.
        delete (bool): Delete given key.
        swapkey (str): Swap list positions of `key` and this key.

    """
    if not caller.db.multidesc:
        # initialize the multidesc attribute
        caller.db.multidesc = [("caller", caller.db.desc or "")]
    if not key:
        return
    lokey = key.lower()
    match = [ind for ind, tup in enumerate(caller.db.multidesc) if tup[0] == lokey]
    if match:
        idesc = match[0]
        if delete:
            # delete entry
            del caller.db.multidesc[idesc]
        elif swapkey:
            # swap positions
            loswapkey = swapkey.lower()
            swapmatch = [ind for ind, tup in enumerate(caller.db.multidesc) if tup[0] == loswapkey]
            if swapmatch:
                iswap = swapmatch[0]
                if idesc == iswap:
                    raise DescValidateError("Swapping a key with itself does nothing.")
                temp = caller.db.multidesc[idesc]
                caller.db.multidesc[idesc] = caller.db.multidesc[iswap]
                caller.db.multidesc[iswap] = temp
            else:
                raise DescValidateError("Description key '|w%s|n' not found." % swapkey)
        elif desc:
            # update in-place
            caller.db.multidesc[idesc] = (lokey, desc)
        else:
            raise DescValidateError("No description was set.")
    else:
        # no matching key
        if delete or swapkey:
            raise DescValidateError("Description key '|w%s|n' not found." % key)
        elif desc:
            # insert new at the top of the stack
            caller.db.multidesc.insert(0, (lokey, desc))
        else:
            raise DescValidateError("No description was set.")

# eveditor save/load/quit functions

def _save_editor(caller, buffer):
    "Called when the editor saves its contents"
    key = caller.db._multidesc_editkey
    _update_store(caller, key, buffer)
    caller.msg("Saved description to key '%s'." % key)
    return True

def _load_editor(caller):
    "Called when the editor loads contents"
    key = caller.db._multidesc_editkey
    match = [ind for ind, tup in enumerate(caller.db.multidesc) if tup[0] == key]
    if match:
        return caller.db.multidesc[match[0]][1]
    return ""

def _quit_editor(caller):
    "Called when the editor quits"
    del caller.db._multidesc_editkey
    caller.msg("Exited editor.")


# The actual command class

class CmdMultiDesc(default_cmds.MuxCommand):
    """
    Manage multiple descriptions

    Usage:
        +desc [key]                - show current desc desc with <key>
        +desc <key> = <text>       - add/replace desc with <key>
        +desc/list                 - list descriptions (abbreviated)
        +desc/list/full            - list descriptions (full texts)
        +desc/edit <key>           - add/edit desc <key> in line editor
        +desc/del <key>            - delete desc <key>
        +desc/swap <key1>-<key2>   - swap positions of <key1> and <key2> in list
        +desc/set <key> [+key+...] - set desc as default or combine multiple descs

    Notes:
        When combining multiple descs with +desc/set <key> + <key2> + ...,
        you can add custom text between the '+' signs. Any text
        not a '+' or identified a as a desc key will be added to the
        final string. Use e.g. ansi line break ||/ to add a new
        paragraph. Whitespace around keys (only) will be stripped.

    """
    key = "+desc"
    aliases = ["desc"]
    locks = "cmd:all()"<commit_msg>Clarified the multidescer docstring a little.<commit_after>"""
Evennia Mutltidescer

Contrib - Griatch 2016

A "multidescer" is a concept from the MUSH world. It allows for
creating, managing and switching between multiple character
descriptions. This multidescer will not require any changes to the
Character class, rather it will use the `multidescs` Attribute (a
list) and create it if it does not exist.

This contrib also works well together with the rpsystem contrib (which
also adds the short descriptions and the `sdesc` command).


Installation:

Edit `mygame/commands/default_cmdsets.py` and add
`from contrib.multidesc import CmdMultiDesc` to the top.

Next, look up the `at_cmdset_create` method of the `CharacterCmdSet`
class and add a line `self.add(CmdMultiDesc())` to the end
of it.

Reload the server and you should have the +desc command available (it
will replace the default `desc` command).

"""
import re
from evennia import default_cmds
from evennia.utils.utils import crop
from evennia.utils.eveditor import EvEditor


# regex for the set functionality
_RE_KEYS = re.compile(r"([\w\s]+)(?:\+*?)", re.U + re.I)


# Helper functions for the Command

class DescValidateError(ValueError):
    "Used for tracebacks from desc systems"
    pass


def _update_store(caller, key=None, desc=None, delete=False, swapkey=None):
    """
    Helper function for updating the database store.

    Args:
        caller (Object): The caller of the command.
        key (str): Description identifier
        desc (str): Description text.
        delete (bool): Delete given key.
        swapkey (str): Swap list positions of `key` and this key.

    """
    if not caller.db.multidesc:
        # initialize the multidesc attribute
        caller.db.multidesc = [("caller", caller.db.desc or "")]
    if not key:
        return
    lokey = key.lower()
    match = [ind for ind, tup in enumerate(caller.db.multidesc) if tup[0] == lokey]
    if match:
        idesc = match[0]
        if delete:
            # delete entry
            del caller.db.multidesc[idesc]
        elif swapkey:
            # swap positions
            loswapkey = swapkey.lower()
            swapmatch = [ind for ind, tup in enumerate(caller.db.multidesc) if tup[0] == loswapkey]
            if swapmatch:
                iswap = swapmatch[0]
                if idesc == iswap:
                    raise DescValidateError("Swapping a key with itself does nothing.")
                temp = caller.db.multidesc[idesc]
                caller.db.multidesc[idesc] = caller.db.multidesc[iswap]
                caller.db.multidesc[iswap] = temp
            else:
                raise DescValidateError("Description key '|w%s|n' not found." % swapkey)
        elif desc:
            # update in-place
            caller.db.multidesc[idesc] = (lokey, desc)
        else:
            raise DescValidateError("No description was set.")
    else:
        # no matching key
        if delete or swapkey:
            raise DescValidateError("Description key '|w%s|n' not found." % key)
        elif desc:
            # insert new at the top of the stack
            caller.db.multidesc.insert(0, (lokey, desc))
        else:
            raise DescValidateError("No description was set.")

# eveditor save/load/quit functions

def _save_editor(caller, buffer):
    "Called when the editor saves its contents"
    key = caller.db._multidesc_editkey
    _update_store(caller, key, buffer)
    caller.msg("Saved description to key '%s'." % key)
    return True

def _load_editor(caller):
    "Called when the editor loads contents"
    key = caller.db._multidesc_editkey
    match = [ind for ind, tup in enumerate(caller.db.multidesc) if tup[0] == key]
    if match:
        return caller.db.multidesc[match[0]][1]
    return ""

def _quit_editor(caller):
    "Called when the editor quits"
    del caller.db._multidesc_editkey
    caller.msg("Exited editor.")


# The actual command class

class CmdMultiDesc(default_cmds.MuxCommand):
    """
    Manage multiple descriptions

    Usage:
        +desc [key]                - show current desc desc with <key>
        +desc <key> = <text>       - add/replace desc with <key>
        +desc/list                 - list descriptions (abbreviated)
        +desc/list/full            - list descriptions (full texts)
        +desc/edit <key>           - add/edit desc <key> in line editor
        +desc/del <key>            - delete desc <key>
        +desc/swap <key1>-<key2>   - swap positions of <key1> and <key2> in list
        +desc/set <key> [+key+...] - set desc as default or combine multiple descs

    Notes:
        When combining multiple descs with +desc/set <key> + <key2> + ...,
        any keys not matching an actual description will be inserted
        as plain text. Use e.g. ansi line break ||/ to add a new
        paragraph and + + or ansi space ||_ to add extra whitespace.

    """
    key = "+desc"
    aliases = ["desc"]
    locks = "cmd:all()"
{'fraction_non_alphanumeric': 0.09522379092820667, 'fraction_numerical': 0.0034044257534795236, 'mean_word_length': 2.4536652835408024, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6062069', 'n_tokens_mistral': 2993, 'n_tokens_neox': 2962, 'n_words': 1036}