Moved lineditor into utils/eveditor.py. The line editor is accessed by simply importing the class (same as EvTable, EvMenu etc), so the utils.get_line_editor function was removed.
This commit is contained in:
parent
adae4f2ec4
commit
cc2b094bc6
5 changed files with 143 additions and 112 deletions
|
|
@ -13,6 +13,7 @@ from evennia.commands.default.muxcommand import MuxCommand
|
||||||
from evennia.commands.cmdhandler import get_and_merge_cmdsets
|
from evennia.commands.cmdhandler import get_and_merge_cmdsets
|
||||||
from evennia.utils import create, utils, search
|
from evennia.utils import create, utils, search
|
||||||
from evennia.utils.utils import inherits_from
|
from evennia.utils.utils import inherits_from
|
||||||
|
from evennia.utils.eveditor import EvEditor
|
||||||
from evennia.utils.spawner import spawn
|
from evennia.utils.spawner import spawn
|
||||||
from evennia.utils.ansi import raw
|
from evennia.utils.ansi import raw
|
||||||
|
|
||||||
|
|
@ -554,12 +555,11 @@ class CmdDesc(MuxCommand):
|
||||||
self.caller.msg("Saved.")
|
self.caller.msg("Saved.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
self.editor = utils.get_line_editor()(
|
self.editor = EvEditor(
|
||||||
self.caller,
|
self.caller,
|
||||||
loadfunc=load,
|
loadfunc=load,
|
||||||
savefunc=save,
|
savefunc=save,
|
||||||
key="desc",
|
key="desc")
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
|
|
|
||||||
|
|
@ -300,11 +300,6 @@ CMDSET_PLAYER = "commands.default_cmdsets.PlayerCmdSet"
|
||||||
# Location to search for cmdsets if full path not given
|
# Location to search for cmdsets if full path not given
|
||||||
CMDSET_PATHS = ["commands", "evennia", "contribs"]
|
CMDSET_PATHS = ["commands", "evennia", "contribs"]
|
||||||
|
|
||||||
# Line editor path. Points to a line editor class that commands may use to give
|
|
||||||
# users extended editing control. See the default path for a reference implementation
|
|
||||||
# and usage.
|
|
||||||
LINE_EDITOR = 'evennia.commands.default.lineeditor.LineEditor'
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Typeclasses and other paths
|
# Typeclasses and other paths
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
"""
|
"""
|
||||||
Evennia Line Editor
|
EvEditor (Evennia Line Editor)
|
||||||
|
|
||||||
This implements an advanced line editor for editing longer texts
|
This implements an advanced line editor for editing longer texts
|
||||||
in-game. The editor mimics the command mechanisms of the VI editor as
|
in-game. The editor mimics the command mechanisms of the "VI" editor
|
||||||
far as possible.
|
(a famous line-by-line editor) as far as reasonable.
|
||||||
|
|
||||||
Features of the editor:
|
Features of the editor:
|
||||||
|
|
||||||
|
|
@ -13,36 +13,99 @@ Features of the editor:
|
||||||
- formatting of buffer, or selection, to certain width + indentations.
|
- formatting of buffer, or selection, to certain width + indentations.
|
||||||
- allow to echo the input or not, depending on your client.
|
- allow to echo the input or not, depending on your client.
|
||||||
|
|
||||||
Testing / Tutorial:
|
To use the editor, just import EvEditor from this module
|
||||||
|
and initialize it:
|
||||||
|
|
||||||
Whereas the editor is intended to be called from other commands that
|
from evennia.utils.eveditor import EvEditor
|
||||||
requires more elaborate text editing of data, there is also a
|
|
||||||
stand-alone editor command for editing Attributes at the end of this
|
EvEditor(caller,
|
||||||
module. To test it it just import and add it to your default `cmdset`.
|
loadfunc=None, loadfunc_args=None,
|
||||||
|
savefunc=None, savefunc_args=None,
|
||||||
|
quitfunc=None, quitfunc_args=None,
|
||||||
|
key=""):
|
||||||
|
|
||||||
|
Where the load/save/quitfunc are callbacks (with matching arguments)
|
||||||
|
to trigger when the editor loads, saves and quits respectively.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia import Command, CmdSet, utils
|
from evennia import Command, CmdSet, utils
|
||||||
from evennia import syscmdkeys
|
from evennia.commands import cmdhandler
|
||||||
|
|
||||||
__all__ = ("CmdEditor", )
|
# we use cmdhandler instead of evennia.syscmdkeys to
|
||||||
|
# avoid some cases of loading before evennia init'd
|
||||||
|
_CMD_NOMATCH = cmdhandler.CMD_NOMATCH
|
||||||
|
_CMD_NOINPUT = cmdhandler.CMD_NOINPUT
|
||||||
|
|
||||||
CMD_NOMATCH = syscmdkeys.CMD_NOMATCH
|
_RE_GROUP = re.compile(r"\".*?\"|\'.*?\'|\S*")
|
||||||
CMD_NOINPUT = syscmdkeys.CMD_NOINPUT
|
# use NAWS in the future?
|
||||||
|
|
||||||
RE_GROUP = re.compile(r"\".*?\"|\'.*?\'|\S*")
|
|
||||||
_DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
_DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# texts
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
_HELP_TEXT = \
|
||||||
|
"""
|
||||||
|
<txt> - any non-command is appended to the end of the buffer.
|
||||||
|
: <l> - view buffer or only line <l>
|
||||||
|
:: <l> - view buffer without line numbers or other parsing
|
||||||
|
::: - print a ':' as the only character on the line...
|
||||||
|
:h - this help.
|
||||||
|
|
||||||
|
:w - saves the buffer (don't quit)
|
||||||
|
:wq - save buffer and quit
|
||||||
|
:q - quits (will be asked to save if buffer was changed)
|
||||||
|
:q! - quit without saving, no questions asked
|
||||||
|
|
||||||
|
:u - (undo) step backwards in undo history
|
||||||
|
:uu - (redo) step forward in undo history
|
||||||
|
:UU - reset all changes back to initial
|
||||||
|
|
||||||
|
:dd <l> - delete line <n>
|
||||||
|
:dw <l> <w> - delete word or regex <w> in entire buffer or on line <l>
|
||||||
|
:DD - clear buffer
|
||||||
|
|
||||||
|
:y <l> - yank (copy) line <l> to the copy buffer
|
||||||
|
:x <l> - cut line <l> and store it in the copy buffer
|
||||||
|
:p <l> - put (paste) previously copied line directly after <l>
|
||||||
|
:i <l> <txt> - insert new text <txt> at line <l>. Old line will move down
|
||||||
|
:r <l> <txt> - replace line <l> with text <txt>
|
||||||
|
:I <l> <txt> - insert text at the beginning of line <l>
|
||||||
|
:A <l> <txt> - append text after the end of line <l>
|
||||||
|
|
||||||
|
:s <l> <w> <txt> - search/replace word or regex <w> in buffer or on line <l>
|
||||||
|
|
||||||
|
:f <l> - flood-fill entire buffer or line <l>
|
||||||
|
:fi <l> - indent entire buffer or line <l>
|
||||||
|
:fd <l> - de-indent entire buffer or line <l>
|
||||||
|
|
||||||
|
:echo - turn echoing of the input on/off (helpful for some clients)
|
||||||
|
|
||||||
|
Legend:
|
||||||
|
<l> - line numbers, or range lstart:lend, e.g. '3:7'.
|
||||||
|
<w> - one word or several enclosed in quotes.
|
||||||
|
<txt> - longer string, usually not needed to be enclosed in quotes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Handle yes/no quit question
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
class CmdSaveYesNo(Command):
|
class CmdSaveYesNo(Command):
|
||||||
"""
|
"""
|
||||||
Save the editor state on quit. This catches
|
Save the editor state on quit. This catches
|
||||||
nomatches (defaults to Yes), and avoid saves only if
|
nomatches (defaults to Yes), and avoid saves only if
|
||||||
command was given specifically as "no" or "n".
|
command was given specifically as "no" or "n".
|
||||||
"""
|
"""
|
||||||
key = CMD_NOMATCH
|
key = _CMD_NOMATCH
|
||||||
aliases = CMD_NOINPUT
|
aliases = _CMD_NOINPUT
|
||||||
locks = "cmd:all()"
|
locks = "cmd:all()"
|
||||||
help_cateogory = "LineEditor"
|
help_cateogory = "LineEditor"
|
||||||
|
|
||||||
|
|
@ -72,6 +135,12 @@ class SaveYesNoCmdSet(CmdSet):
|
||||||
self.add(CmdSaveYesNo())
|
self.add(CmdSaveYesNo())
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Editor commands
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
class CmdEditorBase(Command):
|
class CmdEditorBase(Command):
|
||||||
"""
|
"""
|
||||||
Base parent for editor commands
|
Base parent for editor commands
|
||||||
|
|
@ -107,7 +176,7 @@ class CmdEditorBase(Command):
|
||||||
# will be kept together and extra whitespace preserved. You
|
# will be kept together and extra whitespace preserved. You
|
||||||
# can input quotes on the line by alternating single and
|
# can input quotes on the line by alternating single and
|
||||||
# double quotes.
|
# double quotes.
|
||||||
arglist = [part for part in RE_GROUP.findall(self.args) if part]
|
arglist = [part for part in _RE_GROUP.findall(self.args) if part]
|
||||||
temp = []
|
temp = []
|
||||||
for arg in arglist:
|
for arg in arglist:
|
||||||
# we want to clean the quotes, but only one type,
|
# we want to clean the quotes, but only one type,
|
||||||
|
|
@ -186,8 +255,8 @@ class CmdLineInput(CmdEditorBase):
|
||||||
"""
|
"""
|
||||||
No command match - Inputs line of text into buffer.
|
No command match - Inputs line of text into buffer.
|
||||||
"""
|
"""
|
||||||
key = CMD_NOMATCH
|
key = _CMD_NOMATCH
|
||||||
aliases = [CMD_NOINPUT]
|
aliases = _CMD_NOINPUT
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -267,9 +336,6 @@ class CmdEditorGroup(CmdEditorBase):
|
||||||
if self.editor.unsaved:
|
if self.editor.unsaved:
|
||||||
caller.cmdset.add(SaveYesNoCmdSet)
|
caller.cmdset.add(SaveYesNoCmdSet)
|
||||||
caller.msg("Save before quitting? {lcyes{lt[Y]{le/{lcno{ltN{le")
|
caller.msg("Save before quitting? {lcyes{lt[Y]{le/{lcno{ltN{le")
|
||||||
#prompt_yesno(caller, "Save before quitting?",
|
|
||||||
# yescode = "self.caller.ndb._lineeditor.save_buffer()\nself.caller.ndb._lineeditor.quit()",
|
|
||||||
# nocode = "self.caller.msg(self.caller.ndb._lineeditor.quit())", default="Y")
|
|
||||||
else:
|
else:
|
||||||
string = editor.quit()
|
string = editor.quit()
|
||||||
elif cmd == ":q!":
|
elif cmd == ":q!":
|
||||||
|
|
@ -429,17 +495,23 @@ class CmdEditorGroup(CmdEditorBase):
|
||||||
caller.msg(string)
|
caller.msg(string)
|
||||||
|
|
||||||
|
|
||||||
class EditorCmdSet(CmdSet):
|
class EvEditorCmdSet(CmdSet):
|
||||||
"CmdSet for the editor commands"
|
"CmdSet for the editor commands"
|
||||||
key = "editorcmdset"
|
key = "editorcmdset"
|
||||||
mergetype = "Replace"
|
mergetype = "Replace"
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Main Editor object
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
class LineEditor(object):
|
class EvEditor(object):
|
||||||
"""
|
"""
|
||||||
This defines a line editor object. It creates all relevant commands
|
This defines a line editor object. It creates all relevant commands
|
||||||
and tracks the current state of the buffer. It also cleans up after
|
and tracks the current state of the buffer. It also cleans up after
|
||||||
itself.
|
itself.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, caller,
|
def __init__(self, caller,
|
||||||
|
|
@ -448,23 +520,29 @@ class LineEditor(object):
|
||||||
quitfunc=None, quitfunc_args=None,
|
quitfunc=None, quitfunc_args=None,
|
||||||
key=""):
|
key=""):
|
||||||
"""
|
"""
|
||||||
caller - who is using the editor.
|
Args:
|
||||||
|
caller (Object): Who is using the editor.
|
||||||
|
loadfunc (callable, optional): This will be called as
|
||||||
|
`func(*loadfunc_args)` when the editor is first started,
|
||||||
|
e.g. for pre-loading text into it.
|
||||||
|
loadfunc_args (tuple, optional): Optional tuple of
|
||||||
|
arguments to supply to `loadfunc`.
|
||||||
|
savefunc (callable, optional): This will be called as
|
||||||
|
`func(*savefunc_args)` when the save-command is given and
|
||||||
|
is used to actually determine where/how result is saved.
|
||||||
|
It should return `True` if save was successful and also
|
||||||
|
handle any feedback to the user.
|
||||||
|
savefunc_args (tuple, optional): Optional tuple of
|
||||||
|
arguments to supply to `savefunc`.
|
||||||
|
quitfunc (callable, optional): This will optionally be
|
||||||
|
called as `func(*quitfunc_args)` when the editor is
|
||||||
|
exited. If defined, it should handle all wanted feedback
|
||||||
|
to the user.
|
||||||
|
quitfunc_args (tuple, optional): Optional tuple of arguments to
|
||||||
|
supply to `quitfunc`.
|
||||||
|
key (str, optional): An optional key for naming this
|
||||||
|
session and make it unique from other editing sessions.
|
||||||
|
|
||||||
loadfunc - this will be called as `func(*loadfunc_args)` when the
|
|
||||||
editor is first started, e.g. for pre-loading text into it.
|
|
||||||
loadfunc_args - optional tuple of arguments to supply to `loadfunc`.
|
|
||||||
savefunc - this will be called as `func(*savefunc_args)` when the
|
|
||||||
save-command is given and is used to actually determine
|
|
||||||
where/how result is saved. It should return `True` if save
|
|
||||||
was successful and also handle any feedback to the user.
|
|
||||||
savefunc_args - optional tuple of arguments to supply to `savefunc`.
|
|
||||||
quitfunc - this will optionally be called as `func(*quitfunc_args)`
|
|
||||||
when the editor is exited. If defined, it should handle
|
|
||||||
all wanted feedback to the user.
|
|
||||||
quitfunc_args - optional tuple of arguments to supply to `quitfunc`.
|
|
||||||
|
|
||||||
key = an optional key for naming this session (such as which attribute
|
|
||||||
is being edited).
|
|
||||||
"""
|
"""
|
||||||
self.key = key
|
self.key = key
|
||||||
self.caller = caller
|
self.caller = caller
|
||||||
|
|
@ -497,7 +575,7 @@ class LineEditor(object):
|
||||||
cmd2.obj = self
|
cmd2.obj = self
|
||||||
cmd2.editor = self
|
cmd2.editor = self
|
||||||
# Populate cmdset and add it to caller
|
# Populate cmdset and add it to caller
|
||||||
editor_cmdset = EditorCmdSet()
|
editor_cmdset = EvEditorCmdSet()
|
||||||
editor_cmdset.add(cmd1)
|
editor_cmdset.add(cmd1)
|
||||||
editor_cmdset.add(cmd2)
|
editor_cmdset.add(cmd2)
|
||||||
self.caller.cmdset.add(editor_cmdset)
|
self.caller.cmdset.add(editor_cmdset)
|
||||||
|
|
@ -544,7 +622,7 @@ class LineEditor(object):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.caller.msg("%s\n{Quit function gave an error. Skipping.{n" % e)
|
self.caller.msg("%s\n{Quit function gave an error. Skipping.{n" % e)
|
||||||
del self.caller.ndb._lineeditor
|
del self.caller.ndb._lineeditor
|
||||||
self.caller.cmdset.remove(EditorCmdSet)
|
self.caller.cmdset.remove(EvEditorCmdSet)
|
||||||
if self.quitfunc:
|
if self.quitfunc:
|
||||||
# if quitfunc is defined, it should manage exit messages.
|
# if quitfunc is defined, it should manage exit messages.
|
||||||
return ""
|
return ""
|
||||||
|
|
@ -620,53 +698,15 @@ class LineEditor(object):
|
||||||
"""
|
"""
|
||||||
Shows the help entry for the editor.
|
Shows the help entry for the editor.
|
||||||
"""
|
"""
|
||||||
string = self.sep * _DEFAULT_WIDTH + """
|
string = self.sep * _DEFAULT_WIDTH + _HELP_TEXT + self.sep * _DEFAULT_WIDTH
|
||||||
<txt> - any non-command is appended to the end of the buffer.
|
|
||||||
: <l> - view buffer or only line <l>
|
|
||||||
:: <l> - view buffer without line numbers or other parsing
|
|
||||||
::: - print a ':' as the only character on the line...
|
|
||||||
:h - this help.
|
|
||||||
|
|
||||||
:w - saves the buffer (don't quit)
|
|
||||||
:wq - save buffer and quit
|
|
||||||
:q - quits (will be asked to save if buffer was changed)
|
|
||||||
:q! - quit without saving, no questions asked
|
|
||||||
|
|
||||||
:u - (undo) step backwards in undo history
|
|
||||||
:uu - (redo) step forward in undo history
|
|
||||||
:UU - reset all changes back to initial
|
|
||||||
|
|
||||||
:dd <l> - delete line <n>
|
|
||||||
:dw <l> <w> - delete word or regex <w> in entire buffer or on line <l>
|
|
||||||
:DD - clear buffer
|
|
||||||
|
|
||||||
:y <l> - yank (copy) line <l> to the copy buffer
|
|
||||||
:x <l> - cut line <l> and store it in the copy buffer
|
|
||||||
:p <l> - put (paste) previously copied line directly after <l>
|
|
||||||
:i <l> <txt> - insert new text <txt> at line <l>. Old line will move down
|
|
||||||
:r <l> <txt> - replace line <l> with text <txt>
|
|
||||||
:I <l> <txt> - insert text at the beginning of line <l>
|
|
||||||
:A <l> <txt> - append text after the end of line <l>
|
|
||||||
|
|
||||||
:s <l> <w> <txt> - search/replace word or regex <w> in buffer or on line <l>
|
|
||||||
|
|
||||||
:f <l> - flood-fill entire buffer or line <l>
|
|
||||||
:fi <l> - indent entire buffer or line <l>
|
|
||||||
:fd <l> - de-indent entire buffer or line <l>
|
|
||||||
|
|
||||||
:echo - turn echoing of the input on/off (helpful for some clients)
|
|
||||||
|
|
||||||
Legend:
|
|
||||||
<l> - line numbers, or range lstart:lend, e.g. '3:7'.
|
|
||||||
<w> - one word or several enclosed in quotes.
|
|
||||||
<txt> - longer string, usually not needed to be enclosed in quotes.
|
|
||||||
""" + self.sep * _DEFAULT_WIDTH
|
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Editor access command for editing a given attribute on an object.
|
# Editor access command for editing a given attribute on an object.
|
||||||
#
|
#
|
||||||
|
#------------------------------------------------------------------
|
||||||
|
|
||||||
class CmdEditor(Command):
|
class CmdEditor(Command):
|
||||||
"""
|
"""
|
||||||
|
|
@ -722,11 +762,12 @@ class CmdEditor(Command):
|
||||||
self.caller.msg("Exited Editor.")
|
self.caller.msg("Exited Editor.")
|
||||||
|
|
||||||
editor_key = "%s/%s" % (self.objname, self.attrname)
|
editor_key = "%s/%s" % (self.objname, self.attrname)
|
||||||
# start editor, it will handle things from here.
|
|
||||||
self.editor = utils.get_line_editor()(
|
# start editor, it will handle things from here. We need to
|
||||||
self.caller,
|
# store it on the command object since we set up callback functions
|
||||||
loadfunc=load_attr,
|
# to refer to it that way.
|
||||||
savefunc=save_attr,
|
self.editor = EvEditor(self.caller,
|
||||||
quitfunc=quit_hook,
|
loadfunc=load_attr,
|
||||||
key=editor_key
|
savefunc=save_attr,
|
||||||
)
|
quitfunc=quit_hook,
|
||||||
|
key=editor_key)
|
||||||
|
|
@ -130,17 +130,19 @@ evennia.utils.evdemo`.
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from inspect import isfunction, getargspec
|
from inspect import isfunction, getargspec
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia import syscmdkeys
|
|
||||||
from evennia import Command, CmdSet
|
from evennia import Command, CmdSet
|
||||||
from evennia.utils.evtable import EvTable
|
from evennia.utils.evtable import EvTable
|
||||||
from evennia.utils.ansi import ANSIString, strip_ansi
|
from evennia.utils.ansi import ANSIString, strip_ansi
|
||||||
from evennia.utils.utils import mod_import, make_iter, pad, m_len
|
from evennia.utils.utils import mod_import, make_iter, pad, m_len
|
||||||
|
from evennia.commands import cmdhandler
|
||||||
|
|
||||||
# read from protocol NAWS later?
|
# read from protocol NAWS later?
|
||||||
_MAX_TEXT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
_MAX_TEXT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
||||||
|
|
||||||
_CMD_NOMATCH = syscmdkeys.CMD_NOMATCH
|
# we use cmdhandler instead of evennia.syscmdkeys to
|
||||||
_CMD_NOINPUT = syscmdkeys.CMD_NOINPUT
|
# avoid some cases of loading before evennia init'd
|
||||||
|
_CMD_NOMATCH = cmdhandler.CMD_NOMATCH
|
||||||
|
_CMD_NOINPUT = cmdhandler.CMD_NOINPUT
|
||||||
|
|
||||||
# Return messages
|
# Return messages
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1226,10 +1226,3 @@ def m_len(target):
|
||||||
if inherits_from(target, basestring):
|
if inherits_from(target, basestring):
|
||||||
return len(ANSI_PARSER.strip_mxp(target))
|
return len(ANSI_PARSER.strip_mxp(target))
|
||||||
return len(target)
|
return len(target)
|
||||||
|
|
||||||
|
|
||||||
def get_line_editor():
|
|
||||||
"""
|
|
||||||
Get the line editor for this game.
|
|
||||||
"""
|
|
||||||
return variable_from_module(*settings.LINE_EDITOR.rsplit('.', 1))
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue