mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Create columnize (no ansi support at this point)
This commit is contained in:
parent
23db1ad010
commit
e49993fbb5
4 changed files with 92 additions and 11 deletions
|
|
@ -35,7 +35,6 @@ class AccountDBManager(TypedObjectManager, UserManager):
|
|||
get_account_from_uid
|
||||
get_account_from_name
|
||||
account_search (equivalent to evennia.search_account)
|
||||
#swap_character
|
||||
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ class Account(DefaultAccount):
|
|||
* Helper methods
|
||||
|
||||
msg(text=None, **kwargs)
|
||||
swap_character(new_character, delete_old_character=False)
|
||||
execute_cmd(raw_string, session=None)
|
||||
search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, account=False)
|
||||
is_typeclass(typeclass, exact=False)
|
||||
|
|
|
|||
|
|
@ -57,6 +57,18 @@ def _get_flat_menu_prototype(caller, refresh=False, validate=False):
|
|||
return flat_prototype
|
||||
|
||||
|
||||
def _get_unchanged_inherited(caller, protname):
|
||||
"""Return prototype values inherited from parent(s), which are not replaced in child"""
|
||||
protototype = _get_menu_prototype(caller)
|
||||
if protname in prototype:
|
||||
return protname[protname], False
|
||||
else:
|
||||
flattened = _get_flat_menu_prototype(caller)
|
||||
if protname in flattened:
|
||||
return protname[protname], True
|
||||
return None, False
|
||||
|
||||
|
||||
def _set_menu_prototype(caller, prototype):
|
||||
"""Set the prototype with existing one"""
|
||||
caller.ndb._menutree.olc_prototype = prototype
|
||||
|
|
@ -515,11 +527,11 @@ def node_index(caller):
|
|||
|c --- Prototype wizard --- |n
|
||||
|
||||
A |cprototype|n is a 'template' for |wspawning|n an in-game entity. A field of the prototype
|
||||
can be hard-coded or scripted using |w$protfuncs|n - for example to randomize the value
|
||||
every time the prototype is used to spawn a new entity.
|
||||
can either be hard-coded, left empty or scripted using |w$protfuncs|n - for example to
|
||||
randomize the value every time a new entity is spawned. The fields whose names start with
|
||||
'Prototype-' are not fields on the object itself but are used for prototype-inheritance, or
|
||||
when saving and loading.
|
||||
|
||||
The prototype fields whose names start with 'Prototype-' are not fields on the object itself
|
||||
but are used in the template and when saving it for you (and maybe others) to use later.
|
||||
Select prototype field to edit. If you are unsure, start from [|w1|n]. Enter [|wh|n]elp at
|
||||
any menu node for more info.
|
||||
|
||||
|
|
@ -544,8 +556,8 @@ def node_index(caller):
|
|||
|c- $protfuncs |n
|
||||
|
||||
Prototype-functions (protfuncs) allow for limited scripting within a prototype. These are
|
||||
entered as a string $funcname(arg, arg, ...) and are evaluated |wat the time of spawning|n only.
|
||||
They can also be nested for combined effects.
|
||||
entered as a string $funcname(arg, arg, ...) and are evaluated |wat the time of spawning|n
|
||||
only. They can also be nested for combined effects.
|
||||
|
||||
{pfuncs}
|
||||
""".format(pfuncs=_format_protfuncs())
|
||||
|
|
@ -951,7 +963,10 @@ def node_aliases(caller):
|
|||
case sensitive.
|
||||
|
||||
{actions}
|
||||
""".format(actions=_format_list_actions("remove", prefix="|w<text>|W to add new alias. Other action: "))
|
||||
{current}
|
||||
""".format(actions=_format_list_actions("remove",
|
||||
prefix="|w<text>|W to add new alias. Other action: "),
|
||||
current)
|
||||
|
||||
helptext = """
|
||||
Aliases are fixed alternative identifiers and are stored with the new object.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ be of use when designing your own game.
|
|||
|
||||
"""
|
||||
from __future__ import division, print_function
|
||||
import itertools
|
||||
from builtins import object, range
|
||||
from future.utils import viewkeys, raise_
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ _MULTIMATCH_TEMPLATE = settings.SEARCH_MULTIMATCH_TEMPLATE
|
|||
_EVENNIA_DIR = settings.EVENNIA_DIR
|
||||
_GAME_DIR = settings.GAME_DIR
|
||||
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
|
|
@ -210,18 +212,27 @@ def justify(text, width=None, align="f", indent=0):
|
|||
gap = " " # minimum gap between words
|
||||
if line_rest > 0:
|
||||
if align == 'l':
|
||||
line[-1] += " " * line_rest
|
||||
if line[-1] == "\n\n":
|
||||
line[-1] = " " * (line_rest-1) + "\n" + " " * width + "\n" + " " * width
|
||||
else:
|
||||
line[-1] += " " * line_rest
|
||||
elif align == 'r':
|
||||
line[0] = " " * line_rest + line[0]
|
||||
elif align == 'c':
|
||||
pad = " " * (line_rest // 2)
|
||||
line[0] = pad + line[0]
|
||||
line[-1] = line[-1] + pad + " " * (line_rest % 2)
|
||||
if line[-1] == "\n\n":
|
||||
line[-1] = line[-1] + pad + " " * (line_rest % 2)
|
||||
else:
|
||||
line[-1] = pad + " " * (line_rest % 2 - 1) + \
|
||||
"\n" + " " * width + "\n" + " " * width
|
||||
else: # align 'f'
|
||||
gap += " " * (line_rest // max(1, ngaps))
|
||||
rest_gap = line_rest % max(1, ngaps)
|
||||
for i in range(rest_gap):
|
||||
line[i] += " "
|
||||
elif not any(line):
|
||||
return [" " * width]
|
||||
return gap.join(line)
|
||||
|
||||
# split into paragraphs and words
|
||||
|
|
@ -262,6 +273,62 @@ def justify(text, width=None, align="f", indent=0):
|
|||
return "\n".join([indentstring + line for line in lines])
|
||||
|
||||
|
||||
def columnize(string, columns=2, spacing=4, align='l', width=None):
|
||||
"""
|
||||
Break a string into a number of columns, using as little
|
||||
vertical space as possible.
|
||||
|
||||
Args:
|
||||
string (str): The string to columnize.
|
||||
columns (int, optional): The number of columns to use.
|
||||
spacing (int, optional): How much space to have between columns.
|
||||
width (int, optional): The max width of the columns.
|
||||
Defaults to client's default width.
|
||||
|
||||
Returns:
|
||||
columns (str): Text divided into columns.
|
||||
|
||||
Raises:
|
||||
RuntimeError: If given invalid values.
|
||||
|
||||
"""
|
||||
columns = max(1, columns)
|
||||
spacing = max(1, spacing)
|
||||
width = width if width else settings.CLIENT_DEFAULT_WIDTH
|
||||
|
||||
w_spaces = (columns - 1) * spacing
|
||||
w_txt = max(1, width - w_spaces)
|
||||
|
||||
if w_spaces + columns > width: # require at least 1 char per column
|
||||
raise RuntimeError("Width too small to fit columns")
|
||||
|
||||
colwidth = int(w_txt / (1.0 * columns))
|
||||
|
||||
# first make a single column which we then split
|
||||
onecol = justify(string, width=colwidth, align=align)
|
||||
onecol = onecol.split("\n")
|
||||
|
||||
nrows, dangling = divmod(len(onecol), columns)
|
||||
nrows = [nrows + 1 if i < dangling else nrows for i in range(columns)]
|
||||
|
||||
height = max(nrows)
|
||||
cols = []
|
||||
istart = 0
|
||||
for irows in nrows:
|
||||
cols.append(onecol[istart:istart+irows])
|
||||
istart = istart + irows
|
||||
for col in cols:
|
||||
if len(col) < height:
|
||||
col.append(" " * colwidth)
|
||||
|
||||
sep = " " * spacing
|
||||
rows = []
|
||||
for irow in range(height):
|
||||
rows.append(sep.join(col[irow] for col in cols))
|
||||
|
||||
return "\n".join(rows)
|
||||
|
||||
|
||||
def list_to_string(inlist, endsep="and", addquote=False):
|
||||
"""
|
||||
This pretty-formats a list as string output, adding an optional
|
||||
|
|
@ -1548,6 +1615,7 @@ def format_table(table, extra_space=1):
|
|||
Examples:
|
||||
|
||||
```python
|
||||
ftable = format_table([[...], [...], ...])
|
||||
for ir, row in enumarate(ftable):
|
||||
if ir == 0:
|
||||
# make first row white
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue