evennia/docs/6.x/Components/EvEditor.html
2026-02-15 19:06:04 +01:00

340 lines
No EOL
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>EvEditor &#8212; Evennia latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
<link rel="stylesheet" type="text/css" href="../_static/nature.css?v=279e0f84" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css?v=e4a91a55" />
<script src="../_static/documentation_options.js?v=c6e86fd7"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="EvForm" href="EvForm.html" />
<link rel="prev" title="Coding Utils" href="Coding-Utils.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="EvForm.html" title="EvForm"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Coding-Utils.html" title="Coding Utils"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">EvEditor</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="eveditor">
<h1>EvEditor<a class="headerlink" href="#eveditor" title="Link to this heading"></a></h1>
<p>Evennia offers a powerful in-game line editor in <code class="docutils literal notranslate"><span class="pre">evennia.utils.eveditor.EvEditor</span></code>. This editor,
mimicking the well-known VI line editor. It offers line-by-line editing, undo/redo, line deletes,
search/replace, fill, dedent and more.</p>
<section id="launching-the-editor">
<h2>Launching the editor<a class="headerlink" href="#launching-the-editor" title="Link to this heading"></a></h2>
<p>The editor is created as follows:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia.utils.eveditor</span><span class="w"> </span><span class="kn">import</span> <span class="n">EvEditor</span>
<span class="n">EvEditor</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</pre></div>
</div>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">caller</span></code> (Object or Account): The user of the editor.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">loadfunc</span></code> (callable, optional): This is a function called when the editor is first started. It
is called with <code class="docutils literal notranslate"><span class="pre">caller</span></code> as its only argument. The return value from this function is used as the
starting text in the editor buffer.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">savefunc</span></code> (callable, optional): This is called when the user saves their buffer in the editor is
called with two arguments, <code class="docutils literal notranslate"><span class="pre">caller</span></code> and <code class="docutils literal notranslate"><span class="pre">buffer</span></code>, where <code class="docutils literal notranslate"><span class="pre">buffer</span></code> is the current buffer.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">quitfunc</span></code> (callable, optional): This is called when the user quits the editor. If given, all
cleanup and exit messages to the user must be handled by this function.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">key</span></code> (str, optional): This text will be displayed as an identifier and reminder while editing.
It has no other mechanical function.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">persistent</span></code> (default <code class="docutils literal notranslate"><span class="pre">False</span></code>): if set to <code class="docutils literal notranslate"><span class="pre">True</span></code>, the editor will survive a reboot.</p></li>
</ul>
</section>
<section id="working-with-eveditor">
<h2>Working with EvEditor<a class="headerlink" href="#working-with-eveditor" title="Link to this heading"></a></h2>
<p>This is an example command for setting a specific Attribute using the editor.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia</span><span class="w"> </span><span class="kn">import</span> <span class="n">Command</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">evennia.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">eveditor</span>
<span class="k">class</span><span class="w"> </span><span class="nc">CmdSetTestAttr</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Set the &quot;test&quot; Attribute using</span>
<span class="sd"> the line editor.</span>
<span class="sd"> Usage:</span>
<span class="sd"> settestattr</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;settestattr&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;Set up the callbacks and launch the editor&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">load</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<span class="s2">&quot;get the current value&quot;</span>
<span class="k">return</span> <span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;test&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">save</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">buffer</span><span class="p">):</span>
<span class="s2">&quot;save the buffer&quot;</span>
<span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;test&quot;</span><span class="p">,</span> <span class="n">buffer</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">quit</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<span class="s2">&quot;Since we define it, we must handle messages&quot;</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Editor exited&quot;</span><span class="p">)</span>
<span class="n">key</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="si">}</span><span class="s2">/test&quot;</span>
<span class="c1"># launch the editor</span>
<span class="n">eveditor</span><span class="o">.</span><span class="n">EvEditor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="n">load</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="n">save</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="n">quit</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">)</span>
</pre></div>
</div>
<section id="persistent-editor">
<h3>Persistent editor<a class="headerlink" href="#persistent-editor" title="Link to this heading"></a></h3>
<p>If you set the <code class="docutils literal notranslate"><span class="pre">persistent</span></code> keyword to <code class="docutils literal notranslate"><span class="pre">True</span></code> when creating the editor, it will remain open even
when reloading the game. In order to be persistent, an editor needs to have its callback functions
(<code class="docutils literal notranslate"><span class="pre">loadfunc</span></code>, <code class="docutils literal notranslate"><span class="pre">savefunc</span></code> and <code class="docutils literal notranslate"><span class="pre">quitfunc</span></code>) as top-level functions defined in the module. Since these
functions will be stored, Python will need to find them.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">evennia</span><span class="w"> </span><span class="kn">import</span> <span class="n">Command</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">evennia.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">eveditor</span>
<span class="k">def</span><span class="w"> </span><span class="nf">load</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<span class="s2">&quot;get the current value&quot;</span>
<span class="k">return</span> <span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;test&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">save</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">buffer</span><span class="p">):</span>
<span class="s2">&quot;save the buffer&quot;</span>
<span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">&quot;test&quot;</span><span class="p">,</span> <span class="n">buffer</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">quit</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<span class="s2">&quot;Since we define it, we must handle messages&quot;</span>
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Editor exited&quot;</span><span class="p">)</span>
<span class="k">class</span><span class="w"> </span><span class="nc">CmdSetTestAttr</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Set the &quot;test&quot; Attribute using</span>
<span class="sd"> the line editor.</span>
<span class="sd"> Usage:</span>
<span class="sd"> settestattr</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;settestattr&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;Set up the callbacks and launch the editor&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="si">}</span><span class="s2">/test&quot;</span>
<span class="c1"># launch the editor</span>
<span class="n">eveditor</span><span class="o">.</span><span class="n">EvEditor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="n">load</span><span class="p">,</span> <span class="n">savefunc</span><span class="o">=</span><span class="n">save</span><span class="p">,</span> <span class="n">quitfunc</span><span class="o">=</span><span class="n">quit</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span> <span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="line-editor-usage">
<h3>Line editor usage<a class="headerlink" href="#line-editor-usage" title="Link to this heading"></a></h3>
<p>The editor mimics the <code class="docutils literal notranslate"><span class="pre">VIM</span></code> editor as best as possible. The below is an excerpt of the return from
the in-editor help command (<code class="docutils literal notranslate"><span class="pre">:h</span></code>).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> &lt;txt&gt; - any non-command is appended to the end of the buffer.
: &lt;l&gt; - view buffer or only line &lt;l&gt;
:: &lt;l&gt; - view buffer without line numbers or other parsing
::: - print a &#39;:&#39; as the only character on the line...
:h - this help.
:w - save the buffer (don&#39;t quit)
:wq - save buffer and quit
:q - quit (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 state
:dd &lt;l&gt; - delete line &lt;n&gt;
:dw &lt;l&gt; &lt;w&gt; - delete word or regex &lt;w&gt; in entire buffer or on line &lt;l&gt;
:DD - clear buffer
:y &lt;l&gt; - yank (copy) line &lt;l&gt; to the copy buffer
:x &lt;l&gt; - cut line &lt;l&gt; and store it in the copy buffer
:p &lt;l&gt; - put (paste) previously copied line directly before &lt;l&gt;
:i &lt;l&gt; &lt;txt&gt; - insert new text &lt;txt&gt; at line &lt;l&gt;. Old line will move down
:r &lt;l&gt; &lt;txt&gt; - replace line &lt;l&gt; with text &lt;txt&gt;
:I &lt;l&gt; &lt;txt&gt; - insert text at the beginning of line &lt;l&gt;
:A &lt;l&gt; &lt;txt&gt; - append text after the end of line &lt;l&gt;
:s &lt;l&gt; &lt;w&gt; &lt;txt&gt; - search/replace word or regex &lt;w&gt; in buffer or on line &lt;l&gt;
:f &lt;l&gt; - flood-fill entire buffer or line &lt;l&gt;
:fi &lt;l&gt; - indent entire buffer or line &lt;l&gt;
:fd &lt;l&gt; - de-indent entire buffer or line &lt;l&gt;
:echo - turn echoing of the input on/off (helpful for some clients)
Legend:
&lt;l&gt; - line numbers, or range lstart:lend, e.g. &#39;3:7&#39;.
&lt;w&gt; - one word or several enclosed in quotes.
&lt;txt&gt; - longer string, usually not needed to be enclosed in quotes.
</pre></div>
</div>
</section>
<section id="the-eveditor-to-edit-code">
<h3>The EvEditor to edit code<a class="headerlink" href="#the-eveditor-to-edit-code" title="Link to this heading"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">EvEditor</span></code> is also used to edit some Python code in Evennia. The <code class="docutils literal notranslate"><span class="pre">py</span></code> command supports an <code class="docutils literal notranslate"><span class="pre">/edit</span></code> switch that will open the EvEditor in code mode. This mode isnt significantly different from the standard one, except it handles automatic indentation of blocks and a few options to control this behavior.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">:&lt;</span></code> to remove a level of indentation for the future lines.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">:+</span></code> to add a level of indentation for the future lines.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">:=</span></code> to disable automatic indentation altogether.</p></li>
</ul>
<p>Automatic indentation is there to make code editing more simple. Python needs correct indentation, not as an aesthetic addition, but as a requirement to determine beginning and ending of blocks. The EvEditor will try to guess the next level of indentation. If you type a block “if”, for instance, the EvEditor will propose you an additional level of indentation at the next line. This feature cannot be perfect, however, and sometimes, you will have to use the above options to handle indentation.</p>
<p><code class="docutils literal notranslate"><span class="pre">:=</span></code> can be used to turn automatic indentation off completely. This can be very useful when trying
to paste several lines of code that are already correctly indented, for instance.</p>
<p>To see the EvEditor in code mode, you can use the <code class="docutils literal notranslate"><span class="pre">&#64;py/edit</span></code> command. Type in your code (on one or several lines). You can then use the <code class="docutils literal notranslate"><span class="pre">:w</span></code> option (save without quitting) and the code you have
typed will be executed. The <code class="docutils literal notranslate"><span class="pre">:!</span></code> will do the same thing. Executing code while not closing the
editor can be useful if you want to test the code you have typed but add new lines after your test.</p>
</section>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo of Evennia"/>
</a></p>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">EvEditor</a><ul>
<li><a class="reference internal" href="#launching-the-editor">Launching the editor</a></li>
<li><a class="reference internal" href="#working-with-eveditor">Working with EvEditor</a><ul>
<li><a class="reference internal" href="#persistent-editor">Persistent editor</a></li>
<li><a class="reference internal" href="#line-editor-usage">Line editor usage</a></li>
<li><a class="reference internal" href="#the-eveditor-to-edit-code">The EvEditor to edit code</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="Coding-Utils.html"
title="previous chapter">Coding Utils</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="EvForm.html"
title="next chapter">EvForm</a></p>
</div>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Components/EvEditor.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Doc Versions</h3>
<ul>
<li>
<a href="https://www.evennia.com/docs/latest/index.html">latest (main branch)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/5.x/index.html">v5.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/4.x/index.html">v4.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/3.x/index.html">v3.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/2.x/index.html">v2.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/1.x/index.html">v1.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/0.x/index.html">v0.9.5 branch (outdated)</a>
</li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="EvForm.html" title="EvForm"
>next</a> |</li>
<li class="right" >
<a href="Coding-Utils.html" title="Coding Utils"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">EvEditor</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2024, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
</div>
</body>
</html>