mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 13:56:30 +01:00
567 lines
No EOL
60 KiB
HTML
567 lines
No EOL
60 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>The Inline Function Parser — Evennia 1.0-dev documentation</title>
|
||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<link rel="shortcut 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="MonitorHandler" href="MonitorHandler.html" />
|
||
<link rel="prev" title="EvTable" href="EvTable.html" />
|
||
</head><body>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<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="MonitorHandler.html" title="MonitorHandler"
|
||
accesskey="N">next</a> |</li>
|
||
<li class="right" >
|
||
<a href="EvTable.html" title="EvTable"
|
||
accesskey="P">previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">The Inline Function Parser</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
|
||
<div class="document">
|
||
|
||
<div class="documentwrapper">
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<p class="logo"><a href="../index.html">
|
||
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
|
||
</a></p>
|
||
<div 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" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<script>$('#searchbox').show(0);</script>
|
||
<h3><a href="../index.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">The Inline Function Parser</a><ul>
|
||
<li><a class="reference internal" href="#uses-in-default-evennia">Uses in default Evennia</a></li>
|
||
<li><a class="reference internal" href="#using-the-funcparser">Using the FuncParser</a></li>
|
||
<li><a class="reference internal" href="#defining-custom-callables">Defining custom callables</a><ul>
|
||
<li><a class="reference internal" href="#escaping-special-character">Escaping special character</a></li>
|
||
<li><a class="reference internal" href="#safe-convertion-of-inputs">Safe convertion of inputs</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#default-callables">Default callables</a><ul>
|
||
<li><a class="reference internal" href="#evennia-utils-funcparser-funcparser-callables"><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.FUNCPARSER_CALLABLES</span></code></a></li>
|
||
<li><a class="reference internal" href="#evennia-utils-funcparser-searching-callables"><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.SEARCHING_CALLABLES</span></code></a></li>
|
||
<li><a class="reference internal" href="#evennia-utils-funcparser-actor-stance-callables"><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.ACTOR_STANCE_CALLABLES</span></code></a></li>
|
||
<li><a class="reference internal" href="#example">Example</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="EvTable.html"
|
||
title="previous chapter">EvTable</a></p>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="MonitorHandler.html"
|
||
title="next chapter">MonitorHandler</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<!--h3>This Page</h3-->
|
||
<ul class="this-page-menu">
|
||
<li><a href="../_sources/Components/FuncParser.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div><h3>Links</h3>
|
||
<ul>
|
||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||
<li><a href="https://github.com/evennia/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>Versions</h3>
|
||
<ul>
|
||
<li><a href="FuncParser.html">1.0-dev (develop branch)</a></li>
|
||
<ul>
|
||
<li><a href="../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section class="tex2jax_ignore mathjax_ignore" id="the-inline-function-parser">
|
||
<h1>The Inline Function Parser<a class="headerlink" href="#the-inline-function-parser" title="Permalink to this headline">¶</a></h1>
|
||
<p>The <a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.FuncParser" title="evennia.utils.funcparser.FuncParser"><span class="xref myst py py-class">FuncParser</span></a> extracts and executes ‘inline functions’ embedded in a string on the form <code class="docutils literal notranslate"><span class="pre">$funcname(args,</span> <span class="pre">kwargs)</span></code>. Under the hood, this will lead to a call to a Python function you control. The inline function call will be replaced by the return from the function.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.funcparser</span> <span class="kn">import</span> <span class="n">FuncParser</span>
|
||
|
||
<span class="k">def</span> <span class="nf">_power_callable</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="sd">"""This will be callable as $pow(number, power=<num>) in string"""</span>
|
||
<span class="nb">pow</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'power'</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>
|
||
<span class="k">return</span> <span class="nb">float</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">**</span> <span class="nb">pow</span>
|
||
|
||
<span class="c1"># create a parser and tell it that '$pow' means using _power_callable</span>
|
||
<span class="n">parser</span> <span class="o">=</span> <span class="n">FuncParser</span><span class="p">({</span><span class="s2">"pow"</span><span class="p">:</span> <span class="n">_power_callable</span><span class="p">})</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
<p>Next, just pass a string into the parser, containing <code class="docutils literal notranslate"><span class="pre">$func(...)</span></code> markers:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"We have that 4 x 4 x 4 is $pow(4, power=3)."</span><span class="p">)</span>
|
||
<span class="s2">"We have that 4 x 4 x 4 is 64."</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Normally the return is always converted to a string but you can also get the actual data type from the call:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="s2">"$pow(4)"</span><span class="p">)</span>
|
||
<span class="mi">16</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>To show a <code class="docutils literal notranslate"><span class="pre">$func()</span></code> verbatim in your code without parsing it, escape it as either <code class="docutils literal notranslate"><span class="pre">$$func()</span></code> or <code class="docutils literal notranslate"><span class="pre">\$func()</span></code>:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"This is an escaped $$pow(4) and so is this \$pow(3)"</span><span class="p">)</span>
|
||
<span class="s2">"This is an escaped $pow(4) and so is this $pow(3)"</span>
|
||
</pre></div>
|
||
</div>
|
||
<section id="uses-in-default-evennia">
|
||
<h2>Uses in default Evennia<a class="headerlink" href="#uses-in-default-evennia" title="Permalink to this headline">¶</a></h2>
|
||
<p>The FuncParser can be applied to any string. Out of the box it’s applied in a few situations:</p>
|
||
<ul class="simple">
|
||
<li><p><em>Outgoing messages</em>. All messages sent from the server is processed through FuncParser and every
|
||
callable is provided the <a class="reference internal" href="Sessions.html"><span class="doc std std-doc">Session</span></a> of the object receiving the message. This potentially
|
||
allows a message to be modified on the fly to look different for different recipients.</p></li>
|
||
<li><p><em>Prototype values</em>. A <a class="reference internal" href="Prototypes.html"><span class="doc std std-doc">Prototype</span></a> dict’s values are run through the parser such that every
|
||
callable gets a reference to the rest of the prototype. In the Prototype ORM, this would allow builders
|
||
to safely call functions to set non-string values to prototype values, get random values, reference
|
||
other fields of the prototype, and more.</p></li>
|
||
<li><p><em>Actor-stance in messages to others</em>. In the
|
||
<a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.msg_contents" title="evennia.objects.objects.DefaultObject.msg_contents"><span class="xref myst py py-meth">Object.msg_contents</span></a> method,
|
||
the outgoing string is parsed for special <code class="docutils literal notranslate"><span class="pre">$You()</span></code> and <code class="docutils literal notranslate"><span class="pre">$conj()</span></code> callables to decide if a given recipient
|
||
should see “You” or the character’s name.</p></li>
|
||
</ul>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>The inline-function parser is not intended as a ‘softcode’ programming language. It does not
|
||
have things like loops and conditionals, for example. While you could in principle extend it to
|
||
do very advanced things and allow builders a lot of power, all-out coding is something
|
||
Evennia expects you to do in a proper text editor, outside of the game, not from inside it.</p>
|
||
</div>
|
||
</section>
|
||
<section id="using-the-funcparser">
|
||
<h2>Using the FuncParser<a class="headerlink" href="#using-the-funcparser" title="Permalink to this headline">¶</a></h2>
|
||
<p>You can apply inline function parsing to any string. The
|
||
<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.FuncParser" title="evennia.utils.funcparser.FuncParser"><span class="xref myst py py-class">FuncParser</span></a> is imported as <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser</span></code>.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">funcparser</span>
|
||
|
||
<span class="n">parser</span> <span class="o">=</span> <span class="n">FuncParser</span><span class="p">(</span><span class="n">callables</span><span class="p">,</span> <span class="o">**</span><span class="n">default_kwargs</span><span class="p">)</span>
|
||
<span class="n">parsed_string</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">input_string</span><span class="p">,</span> <span class="n">raise_errors</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
||
<span class="n">escape</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">strip</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
||
<span class="n">return_str</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="o">**</span><span class="n">reserved_kwargs</span><span class="p">)</span>
|
||
|
||
<span class="c1"># callables can also be passed as paths to modules</span>
|
||
<span class="n">parser</span> <span class="o">=</span> <span class="n">FuncParser</span><span class="p">([</span><span class="s2">"game.myfuncparser_callables"</span><span class="p">,</span> <span class="s2">"game.more_funcparser_callables"</span><span class="p">])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here, <code class="docutils literal notranslate"><span class="pre">callables</span></code> points to a collection of normal Python functions (see next section) for you to make
|
||
available to the parser as you parse strings with it. It can either be</p>
|
||
<ul class="simple">
|
||
<li><p>A <code class="docutils literal notranslate"><span class="pre">dict</span></code> of <code class="docutils literal notranslate"><span class="pre">{"functionname":</span> <span class="pre">callable,</span> <span class="pre">...}</span></code>. This allows you do pick and choose exactly which callables
|
||
to include and how they should be named. Do you want a callable to be available under more than one name?
|
||
Just add it multiple times to the dict, with a different key.</p></li>
|
||
<li><p>A <code class="docutils literal notranslate"><span class="pre">module</span></code> or (more commonly) a <code class="docutils literal notranslate"><span class="pre">python-path</span></code> to a module. This module can define a dict
|
||
<code class="docutils literal notranslate"><span class="pre">FUNCPARSER_CALLABLES</span> <span class="pre">=</span> <span class="pre">{"funcname":</span> <span class="pre">callable,</span> <span class="pre">...}</span></code> - this will be imported and used like the <code class="docutils literal notranslate"><span class="pre">dict</span></code> above.
|
||
If no such variable is defined, <em>every</em> top-level function in the module (whose name doesn’t start with
|
||
an underscore <code class="docutils literal notranslate"><span class="pre">_</span></code>) will be considered a suitable callable. The name of the function will be the <code class="docutils literal notranslate"><span class="pre">$funcname</span></code>
|
||
by which it can be called.</p></li>
|
||
<li><p>A <code class="docutils literal notranslate"><span class="pre">list</span></code> of modules/paths. This allows you to pull in modules from many sources for your parsing.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">**default</span></code> kwargs are optional kwargs that will be passed to <em>all</em>
|
||
callables every time this parser is used - unless the user overrides it explicitly in
|
||
their call. This is great for providing sensible standards that the user can
|
||
tweak as needed.</p></li>
|
||
</ul>
|
||
<p><code class="docutils literal notranslate"><span class="pre">FuncParser.parse</span></code> takes further arguments, and can vary for every string parsed.</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> - By default, any errors from a callable will be quietly ignored and the result
|
||
will be that the failing function call will show verbatim. If <code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> is set,
|
||
then parsing will stop and whatever exception happened will be raised. It’d be up to you to handle
|
||
this properly.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">escape</span></code> - Returns a string where every <code class="docutils literal notranslate"><span class="pre">$func(...)</span></code> has been escaped as <code class="docutils literal notranslate"><span class="pre">\$func()</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">strip</span></code> - Remove all <code class="docutils literal notranslate"><span class="pre">$func(...)</span></code> calls from string (as if each returned <code class="docutils literal notranslate"><span class="pre">''</span></code>).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">return_str</span></code> - When <code class="docutils literal notranslate"><span class="pre">True</span></code> (default), <code class="docutils literal notranslate"><span class="pre">parser</span></code> always returns a string. If <code class="docutils literal notranslate"><span class="pre">False</span></code>, it may return
|
||
the return value of a single function call in the string. This is the same as using the <code class="docutils literal notranslate"><span class="pre">.parse_to_any</span></code>
|
||
method.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">**reserved_keywords</span></code> are <em>always</em> passed to every callable in the string.
|
||
They override any <code class="docutils literal notranslate"><span class="pre">**defaults</span></code> given when instantiating the parser and cannot
|
||
be overridden by the user - if they enter the same kwarg it will be ignored.
|
||
This is great for providing the current session, settings etc.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">funcparser</span></code> and <code class="docutils literal notranslate"><span class="pre">raise_errors</span></code>
|
||
are always added as reserved keywords - the first is a
|
||
back-reference to the <code class="docutils literal notranslate"><span class="pre">FuncParser</span></code> instance and the second
|
||
is the <code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> boolean given to <code class="docutils literal notranslate"><span class="pre">FuncParser.parse</span></code>.</p></li>
|
||
</ul>
|
||
<p>Here’s an example of using the default/reserved keywords:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">_test</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="c1"># do stuff</span>
|
||
<span class="k">return</span> <span class="n">something</span>
|
||
|
||
<span class="n">parser</span> <span class="o">=</span> <span class="n">funcparser</span><span class="o">.</span><span class="n">FuncParser</span><span class="p">({</span><span class="s2">"test"</span><span class="p">:</span> <span class="n">_test</span><span class="p">},</span> <span class="n">mydefault</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"$test(foo, bar=4)"</span><span class="p">,</span> <span class="n">myreserved</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here the callable will be called as</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">_test</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="s1">'4'</span><span class="p">,</span> <span class="n">mydefault</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">myreserved</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span>
|
||
<span class="n">funcparser</span><span class="o">=<</span><span class="n">FuncParser</span><span class="o">></span><span class="p">,</span> <span class="n">raise_errors</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">mydefault=2</span></code> kwarg could be overwritten if we made the call as <code class="docutils literal notranslate"><span class="pre">$test(mydefault=...)</span></code>
|
||
but <code class="docutils literal notranslate"><span class="pre">myreserved=[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> will <em>always</em> be sent as-is and will override a call <code class="docutils literal notranslate"><span class="pre">$test(myreserved=...)</span></code>.
|
||
The <code class="docutils literal notranslate"><span class="pre">funcparser</span></code>/<code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> kwargs are also always included as reserved kwargs.</p>
|
||
</section>
|
||
<section id="defining-custom-callables">
|
||
<h2>Defining custom callables<a class="headerlink" href="#defining-custom-callables" title="Permalink to this headline">¶</a></h2>
|
||
<p>All callables made available to the parser must have the following signature:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">funcname</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="c1"># ...</span>
|
||
<span class="k">return</span> <span class="n">something</span>
|
||
</pre></div>
|
||
</div>
|
||
<blockquote>
|
||
<div><p>The <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> must always be included. If you are unsure how <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> work in Python,
|
||
<a class="reference external" href="https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3">read about them here</a>.</p>
|
||
</div></blockquote>
|
||
<p>The input from the innermost <code class="docutils literal notranslate"><span class="pre">$funcname(...)</span></code> call in your callable will always be a <code class="docutils literal notranslate"><span class="pre">str</span></code>. Here’s
|
||
an example of an <code class="docutils literal notranslate"><span class="pre">$toint</span></code> function; it converts numbers to integers.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>"There's a $toint(22.0)% chance of survival."
|
||
</pre></div>
|
||
</div>
|
||
<p>What will enter the <code class="docutils literal notranslate"><span class="pre">$toint</span></code> callable (as <code class="docutils literal notranslate"><span class="pre">args[0]</span></code>) is the <em>string</em> <code class="docutils literal notranslate"><span class="pre">"22.0"</span></code>. The function is responsible
|
||
for converting this to a number so that we can convert it to an integer. We must also properly handle invalid
|
||
inputs (like non-numbers).</p>
|
||
<p>If you want to mark an error, raise <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.ParsingError</span></code>. This stops the entire parsing
|
||
of the string and may or may not raise the exception depending on what you set <code class="docutils literal notranslate"><span class="pre">raise_errors</span></code> to when you
|
||
created the parser.</p>
|
||
<p>However, if you <em>nest</em> functions, the return of the innermost function may be something other than
|
||
a string. Let’s introduce the <code class="docutils literal notranslate"><span class="pre">$eval</span></code> function, which evaluates simple expressions using
|
||
Python’s <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> and/or <code class="docutils literal notranslate"><span class="pre">simple_eval</span></code>. It returns whatever data type it
|
||
evaluates to.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>"There's a $toint($eval(10 * 2.2))% chance of survival."
|
||
</pre></div>
|
||
</div>
|
||
<p>Since the <code class="docutils literal notranslate"><span class="pre">$eval</span></code> is the innermost call, it will get a string as input - the string <code class="docutils literal notranslate"><span class="pre">"10</span> <span class="pre">*</span> <span class="pre">2.2"</span></code>.
|
||
It evaluates this and returns the <code class="docutils literal notranslate"><span class="pre">float</span></code> <code class="docutils literal notranslate"><span class="pre">22.0</span></code>. This time the outermost <code class="docutils literal notranslate"><span class="pre">$toint</span></code> will be called with
|
||
this <code class="docutils literal notranslate"><span class="pre">float</span></code> instead of with a string.</p>
|
||
<blockquote>
|
||
<div><p>It’s important to safely validate your inputs since users may end up nesting your callables in any order.
|
||
See the next section for useful tools to help with this.</p>
|
||
</div></blockquote>
|
||
<p>In these examples, the result will be embedded in the larger string, so the result of the entire parsing
|
||
will be a string:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">above_string</span><span class="p">)</span>
|
||
<span class="s2">"There's a 22</span><span class="si">% c</span><span class="s2">hance of survival."</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However, if you use the <code class="docutils literal notranslate"><span class="pre">parse_to_any</span></code> (or <code class="docutils literal notranslate"><span class="pre">parse(...,</span> <span class="pre">return_str=False)</span></code>) and
|
||
<em>don’t add any extra string around the outermost function call</em>,
|
||
you’ll get the return type of the outermost callable back:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="s2">"$toint($eval(10 * 2.2)"</span><span class="p">)</span>
|
||
<span class="mi">22</span>
|
||
<span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="s2">"the number $toint($eval(10 * 2.2)."</span><span class="p">)</span>
|
||
<span class="s2">"the number 22"</span>
|
||
<span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="s2">"$toint($eval(10 * 2.2)%"</span><span class="p">)</span>
|
||
<span class="s2">"22%"</span>
|
||
</pre></div>
|
||
</div>
|
||
<section id="escaping-special-character">
|
||
<h3>Escaping special character<a class="headerlink" href="#escaping-special-character" title="Permalink to this headline">¶</a></h3>
|
||
<p>When entering funcparser callables in strings, it looks like a regular
|
||
function call inside a string:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="s2">"This is a $myfunc(arg1, arg2, kwarg=foo)."</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Commas (<code class="docutils literal notranslate"><span class="pre">,</span></code>) and equal-signs (<code class="docutils literal notranslate"><span class="pre">=</span></code>) are considered to separate the arguments and
|
||
kwargs. In the same way, the right parenthesis (<code class="docutils literal notranslate"><span class="pre">)</span></code>) closes the argument list.
|
||
Sometimes you want to include commas in the argument without it breaking the
|
||
argument list.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="s2">"The $format(forest's smallest meadow, with dandelions) is to the west."</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>You can escape in various ways.</p>
|
||
<ul class="simple">
|
||
<li><p>Prepending special characters like <code class="docutils literal notranslate"><span class="pre">,</span></code> and <code class="docutils literal notranslate"><span class="pre">=</span></code> with the escape character <code class="docutils literal notranslate"><span class="pre">\</span></code></p></li>
|
||
</ul>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="s2">"The $format(forest's smallest meadow\, with dandelions) is to the west."</span>
|
||
</pre></div>
|
||
</div>
|
||
<ul class="simple">
|
||
<li><p>Wrapping your strings in double quotes. Unlike in raw Python, you
|
||
can’t escape with single quotes <code class="docutils literal notranslate"><span class="pre">'</span></code> since these could also be apostrophes (like
|
||
<code class="docutils literal notranslate"><span class="pre">forest's</span></code> above). The result will be a verbatim string that contains
|
||
everything but the outermost double quotes.</p></li>
|
||
</ul>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="s1">'The $format("forest'</span><span class="n">s</span> <span class="n">smallest</span> <span class="n">meadow</span><span class="p">,</span> <span class="k">with</span> <span class="n">dandelions</span><span class="s2">") is to the west.'</span>
|
||
</pre></div>
|
||
</div>
|
||
<ul class="simple">
|
||
<li><p>If you want verbatim double-quotes to appear in your string, you can escape
|
||
them with <code class="docutils literal notranslate"><span class="pre">\"</span></code> in turn.</p></li>
|
||
</ul>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="s1">'The $format("forest'</span><span class="n">s</span> <span class="n">smallest</span> <span class="n">meadow</span><span class="p">,</span> <span class="k">with</span> \<span class="s2">"dandelions</span><span class="se">\"</span><span class="s2">') is to the west.'</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="safe-convertion-of-inputs">
|
||
<h3>Safe convertion of inputs<a class="headerlink" href="#safe-convertion-of-inputs" title="Permalink to this headline">¶</a></h3>
|
||
<p>Since you don’t know in which order users may use your callables, they should
|
||
always check the types of its inputs and convert to the type the callable needs.
|
||
Note also that when converting from strings, there are limits what inputs you
|
||
can support. This is because FunctionParser strings can be used by
|
||
non-developer players/builders and some things (such as complex
|
||
classes/callables etc) are just not safe/possible to convert from string
|
||
representation.</p>
|
||
<p>In <code class="docutils literal notranslate"><span class="pre">evennia.utils.utils</span></code> is a helper called
|
||
<a class="reference internal" href="../api/evennia.utils.utils.html#evennia.utils.utils.safe_convert_to_types" title="evennia.utils.utils.safe_convert_to_types"><span class="xref myst py py-func">safe_convert_to_types</span></a>. This function
|
||
automates the conversion of simple data types in a safe way:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.utils</span> <span class="kn">import</span> <span class="n">safe_convert_to_types</span>
|
||
|
||
<span class="k">def</span> <span class="nf">_process_callable</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="sd">"""</span>
|
||
<span class="sd"> $process(expression, local, extra1=34, extra2=foo)</span>
|
||
|
||
<span class="sd"> """</span>
|
||
<span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">safe_convert_to_type</span><span class="p">(</span>
|
||
<span class="p">((</span><span class="s1">'py'</span><span class="p">,</span> <span class="nb">str</span><span class="p">),</span> <span class="p">{</span><span class="s1">'extra1'</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="s1">'extra2'</span><span class="p">:</span> <span class="nb">str</span><span class="p">}),</span>
|
||
<span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
|
||
<span class="c1"># args/kwargs should be correct types now</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
<p>In other words, in the callable <code class="docutils literal notranslate"><span class="pre">$process(expression,</span> <span class="pre">local,</span> <span class="pre">extra1=..,</span> <span class="pre">extra2=...)</span></code>, the first argument will be handled by the ‘py’ converter
|
||
(described below), the second will passed through regular Python <code class="docutils literal notranslate"><span class="pre">str</span></code>,
|
||
kwargs will be handled by <code class="docutils literal notranslate"><span class="pre">int</span></code> and <code class="docutils literal notranslate"><span class="pre">str</span></code> respectively. You can supply
|
||
your own converter function as long as it takes one argument and returns
|
||
the converted result.</p>
|
||
<p>In other words,</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">safe_convert_to_type</span><span class="p">(</span>
|
||
<span class="p">(</span><span class="n">tuple_of_arg_converters</span><span class="p">,</span> <span class="n">dict_of_kwarg_converters</span><span class="p">),</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The special converter <code class="docutils literal notranslate"><span class="pre">"py"</span></code> will try to convert a string argument to a Python structure with the help of the
|
||
following tools (which you may also find useful to experiment with on your own):</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference external" href="https://docs.python.org/3.8/library/ast.html#ast.literal_eval">ast.literal_eval</a> is an in-built Python
|
||
function. It
|
||
<em>only</em> supports strings, bytes, numbers, tuples, lists, dicts, sets, booleans and <code class="docutils literal notranslate"><span class="pre">None</span></code>. That’s
|
||
it - no arithmetic or modifications of data is allowed. This is good for converting individual values and
|
||
lists/dicts from the input line to real Python objects.</p></li>
|
||
<li><p><a class="reference external" href="https://pypi.org/project/simpleeval/">simpleeval</a> is a third-party tool included with Evennia. This
|
||
allows for evaluation of simple (and thus safe) expressions. One can operate on numbers and strings
|
||
with <code class="docutils literal notranslate"><span class="pre">+-/*</span></code> as well as do simple comparisons like <code class="docutils literal notranslate"><span class="pre">4</span> <span class="pre">></span> <span class="pre">3</span></code> and more. It does <em>not</em> accept more complex
|
||
containers like lists/dicts etc, so this and <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> are complementary to each other.</p></li>
|
||
</ul>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>It may be tempting to run use Python’s in-built <code class="docutils literal notranslate"><span class="pre">eval()</span></code> or <code class="docutils literal notranslate"><span class="pre">exec()</span></code> functions as converters since
|
||
these are able to convert any valid Python source code to Python. NEVER DO THIS unless you really, really
|
||
know that ONLY developers will ever modify the string going into the callable. The parser is intended
|
||
for untrusted users (if you were trusted you’d have access to Python already). Letting untrusted users
|
||
pass strings to <code class="docutils literal notranslate"><span class="pre">eval</span></code>/<code class="docutils literal notranslate"><span class="pre">exec</span></code> is a MAJOR security risk. It allows the caller to run arbitrary
|
||
Python code on your server. This is the path to maliciously deleted hard drives. Just don’t do it and
|
||
sleep better at night.</p>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="default-callables">
|
||
<h2>Default callables<a class="headerlink" href="#default-callables" title="Permalink to this headline">¶</a></h2>
|
||
<p>These are some example callables you can import and add your parser. They are divided into
|
||
global-level dicts in <code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser</span></code>. Just import the dict(s) and merge/add one or
|
||
more to them when you create your <code class="docutils literal notranslate"><span class="pre">FuncParser</span></code> instance to have those callables be available.</p>
|
||
<section id="evennia-utils-funcparser-funcparser-callables">
|
||
<h3><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.FUNCPARSER_CALLABLES</span></code><a class="headerlink" href="#evennia-utils-funcparser-funcparser-callables" title="Permalink to this headline">¶</a></h3>
|
||
<p>These are the ‘base’ callables.</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$eval(expression)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_eval" title="evennia.utils.funcparser.funcparser_callable_eval"><span class="xref myst py py-func">code</span></a>) -
|
||
this uses <code class="docutils literal notranslate"><span class="pre">literal_eval</span></code> and <code class="docutils literal notranslate"><span class="pre">simple_eval</span></code> (see previous section) attemt to convert a string expression
|
||
to a python object. This handles e.g. lists of literals <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> and simple expressions like <code class="docutils literal notranslate"><span class="pre">"1</span> <span class="pre">+</span> <span class="pre">2"</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$toint(number)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_toint" title="evennia.utils.funcparser.funcparser_callable_toint"><span class="xref myst py py-func">code</span></a>) -
|
||
always converts an output to an integer, if possible.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$add/sub/mult/div(obj1,</span> <span class="pre">obj2)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_add" title="evennia.utils.funcparser.funcparser_callable_add"><span class="xref myst py py-func">code</span></a>) -
|
||
this adds/subtracts/multiplies and divides to elements together. While simple addition could be done with
|
||
<code class="docutils literal notranslate"><span class="pre">$eval</span></code>, this could for example be used also to add two lists together, which is not possible with <code class="docutils literal notranslate"><span class="pre">eval</span></code>;
|
||
for example <code class="docutils literal notranslate"><span class="pre">$add($eval([1,2,3]),</span> <span class="pre">$eval([4,5,6]))</span> <span class="pre">-></span> <span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3,</span> <span class="pre">4,</span> <span class="pre">5,</span> <span class="pre">6]</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$round(float,</span> <span class="pre">significant)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_round" title="evennia.utils.funcparser.funcparser_callable_round"><span class="xref myst py py-func">code</span></a>) -
|
||
rounds an input float into the number of provided significant digits. For example <code class="docutils literal notranslate"><span class="pre">$round(3.54343,</span> <span class="pre">3)</span> <span class="pre">-></span> <span class="pre">3.543</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$random([start,</span> <span class="pre">[end]])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_random" title="evennia.utils.funcparser.funcparser_callable_random"><span class="xref myst py py-func">code</span></a>) -
|
||
this works like the Python <code class="docutils literal notranslate"><span class="pre">random()</span></code> function, but will randomize to an integer value if both start/end are
|
||
integers. Without argument, will return a float between 0 and 1.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$randint([start,</span> <span class="pre">[end]])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_randint" title="evennia.utils.funcparser.funcparser_callable_randint"><span class="xref myst py py-func">code</span></a>) -
|
||
works like the <code class="docutils literal notranslate"><span class="pre">randint()</span></code> python function and always returns an integer.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$choice(list)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_choice" title="evennia.utils.funcparser.funcparser_callable_choice"><span class="xref myst py py-func">code</span></a>) -
|
||
the input will automatically be parsed the same way as <code class="docutils literal notranslate"><span class="pre">$eval</span></code> and is expected to be an iterable. A random
|
||
element of this list will be returned.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$pad(text[,</span> <span class="pre">width,</span> <span class="pre">align,</span> <span class="pre">fillchar])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_pad" title="evennia.utils.funcparser.funcparser_callable_pad"><span class="xref myst py py-func">code</span></a>) -
|
||
this will pad content. <code class="docutils literal notranslate"><span class="pre">$pad("Hello",</span> <span class="pre">30,</span> <span class="pre">c,</span> <span class="pre">-)</span></code> will lead to a text centered in a 30-wide block surrounded by <code class="docutils literal notranslate"><span class="pre">-</span></code>
|
||
characters.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$crop(text,</span> <span class="pre">width=78,</span> <span class="pre">suffix='[...]')</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_crop" title="evennia.utils.funcparser.funcparser_callable_crop"><span class="xref myst py py-func">code</span></a>) -
|
||
this will crop a text longer than the width, by default ending it with a <code class="docutils literal notranslate"><span class="pre">[...]</span></code>-suffix that also fits within
|
||
the width. If no width is given, the client width or <code class="docutils literal notranslate"><span class="pre">settings.DEFAULT_CLIENT_WIDTH</span></code> will be used.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$space(num)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_space" title="evennia.utils.funcparser.funcparser_callable_space"><span class="xref myst py py-func">code</span></a>) -
|
||
this will insert <code class="docutils literal notranslate"><span class="pre">num</span></code> spaces.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$just(string,</span> <span class="pre">width=40,</span> <span class="pre">align=c,</span> <span class="pre">indent=2)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_justify" title="evennia.utils.funcparser.funcparser_callable_justify"><span class="xref myst py py-func">code</span></a>) -
|
||
justifies the text to a given width, aligning it left/right/center or ‘f’ for full (spread text across width).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$ljust</span></code> - shortcut to justify-left. Takes all other kwarg of <code class="docutils literal notranslate"><span class="pre">$just</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$rjust</span></code> - shortcut to right justify.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$cjust</span></code> - shortcut to center justify.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$clr(startcolor,</span> <span class="pre">text[,</span> <span class="pre">endcolor])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_clr" title="evennia.utils.funcparser.funcparser_callable_clr"><span class="xref myst py py-func">code</span></a>) -
|
||
color text. The color is given with one or two characters without the preceeding <code class="docutils literal notranslate"><span class="pre">|</span></code>. If no endcolor is
|
||
given, the string will go back to neutral, so <code class="docutils literal notranslate"><span class="pre">$clr(r,</span> <span class="pre">Hello)</span></code> is equivalent to <code class="docutils literal notranslate"><span class="pre">|rHello|n</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="evennia-utils-funcparser-searching-callables">
|
||
<h3><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.SEARCHING_CALLABLES</span></code><a class="headerlink" href="#evennia-utils-funcparser-searching-callables" title="Permalink to this headline">¶</a></h3>
|
||
<p>These are callables that requires access-checks in order to search for objects. So they require some
|
||
extra reserved kwargs to be passed when running the parser:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
|
||
<span class="n">parser</span><span class="o">.</span><span class="n">parse_to_any</span><span class="p">(</span><span class="n">string</span><span class="p">,</span> <span class="n">caller</span><span class="o">=<</span><span class="nb">object</span> <span class="ow">or</span> <span class="n">account</span><span class="o">></span><span class="p">,</span> <span class="n">access</span><span class="o">=</span><span class="s2">"control"</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">caller</span></code> is required, it’s the the object to do the access-check for. The <code class="docutils literal notranslate"><span class="pre">access</span></code> kwarg is the
|
||
<a class="reference internal" href="Locks.html"><span class="doc std std-doc">lock type</span></a> to check, default being <code class="docutils literal notranslate"><span class="pre">"control"</span></code>.</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$search(query,type=account|script,return_list=False)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_search" title="evennia.utils.funcparser.funcparser_callable_search"><span class="xref myst py py-func">code</span></a>) -
|
||
this will look up and try to match an object by key or alias. Use the <code class="docutils literal notranslate"><span class="pre">type</span></code> kwarg to
|
||
search for <code class="docutils literal notranslate"><span class="pre">account</span></code> or <code class="docutils literal notranslate"><span class="pre">script</span></code> instead. By default this will return nothing if there are more than one
|
||
match; if <code class="docutils literal notranslate"><span class="pre">return_list</span></code> is <code class="docutils literal notranslate"><span class="pre">True</span></code> a list of 0, 1 or more matches will be returned instead.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$obj(query)</span></code>, <code class="docutils literal notranslate"><span class="pre">$dbref(query)</span></code> - legacy aliases for <code class="docutils literal notranslate"><span class="pre">$search</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$objlist(query)</span></code> - legacy alias for <code class="docutils literal notranslate"><span class="pre">$search</span></code>, always returning a list.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="evennia-utils-funcparser-actor-stance-callables">
|
||
<h3><code class="docutils literal notranslate"><span class="pre">evennia.utils.funcparser.ACTOR_STANCE_CALLABLES</span></code><a class="headerlink" href="#evennia-utils-funcparser-actor-stance-callables" title="Permalink to this headline">¶</a></h3>
|
||
<p>These are used to implement actor-stance emoting. They are used by the
|
||
<a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject.msg_contents" title="evennia.objects.objects.DefaultObject.msg_contents"><span class="xref myst py py-meth">DefaultObject.msg_contents</span></a> method
|
||
by default. You can read a lot more about this on the page
|
||
<a class="reference internal" href="../Concepts/Change-Message-Per-Receiver.html"><span class="doc std std-doc">Change messages per receiver</span></a>.</p>
|
||
<p>On the parser side, all these inline functions require extra kwargs be passed into the parser
|
||
(done by <code class="docutils literal notranslate"><span class="pre">msg_contents</span></code> by default):</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">string</span><span class="p">,</span> <span class="n">caller</span><span class="o">=<</span><span class="n">obj</span><span class="o">></span><span class="p">,</span> <span class="n">receiver</span><span class="o">=<</span><span class="n">obj</span><span class="o">></span><span class="p">,</span> <span class="n">mapping</span><span class="o">=</span><span class="p">{</span><span class="s1">'key'</span><span class="p">:</span> <span class="o"><</span><span class="n">obj</span><span class="o">></span><span class="p">,</span> <span class="o">...</span><span class="p">})</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here the <code class="docutils literal notranslate"><span class="pre">caller</span></code> is the one sending the message and <code class="docutils literal notranslate"><span class="pre">receiver</span></code> the one to see it. The <code class="docutils literal notranslate"><span class="pre">mapping</span></code> contains
|
||
references to other objects accessible via these callables.</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$you([key])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_you" title="evennia.utils.funcparser.funcparser_callable_you"><span class="xref myst py py-func">code</span></a>) -
|
||
if no <code class="docutils literal notranslate"><span class="pre">key</span></code> is given, this represents the <code class="docutils literal notranslate"><span class="pre">caller</span></code>, otherwise an object from <code class="docutils literal notranslate"><span class="pre">mapping</span></code>
|
||
will be used. As this message is sent to different recipients, the <code class="docutils literal notranslate"><span class="pre">receiver</span></code> will change and this will
|
||
be replaced either with the string <code class="docutils literal notranslate"><span class="pre">you</span></code> (if you and the receiver is the same entity) or with the
|
||
result of <code class="docutils literal notranslate"><span class="pre">you_obj.get_display_name(looker=receiver)</span></code>. This allows for a single string to echo differently
|
||
depending on who sees it, and also to reference other people in the same way.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$You([key])</span></code> - same as <code class="docutils literal notranslate"><span class="pre">$you</span></code> but always capitalized.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$conj(verb)</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_conjugate" title="evennia.utils.funcparser.funcparser_callable_conjugate"><span class="xref myst py py-func">code</span></a>) - conjugates a verb
|
||
between 2nd person presens to 3rd person presence depending on who
|
||
sees the string. For example <code class="docutils literal notranslate"><span class="pre">"$You()</span> <span class="pre">$conj(smiles)".</span></code> will show as “You smile.” and “Tom smiles.” depending
|
||
on who sees it. This makes use of the tools in <a class="reference internal" href="../api/evennia.utils.verb_conjugation.html#evennia-utils-verb-conjugation"><span class="std std-ref">evennia.utils.verb_conjugation</span></a>
|
||
to do this, and only works for English verbs.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">$pron(pronoun</span> <span class="pre">[,options])</span></code> (<a class="reference internal" href="../api/evennia.utils.funcparser.html#evennia.utils.funcparser.funcparser_callable_pronoun" title="evennia.utils.funcparser.funcparser_callable_pronoun"><span class="xref myst py py-func">code</span></a>) - Dynamically
|
||
map pronouns (like his, herself, you, its etc) between 1st/2nd person to 3rd person.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="example">
|
||
<h3>Example<a class="headerlink" href="#example" title="Permalink to this headline">¶</a></h3>
|
||
<p>Here’s an example of including the default callables together with two custom ones.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">funcparser</span>
|
||
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">gametime</span>
|
||
|
||
<span class="k">def</span> <span class="nf">_dashline</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="s2">-------- </span><span class="si">{</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2"> --------"</span>
|
||
<span class="k">return</span> <span class="s1">''</span>
|
||
|
||
<span class="k">def</span> <span class="nf">_uptime</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">gametime</span><span class="o">.</span><span class="n">uptime</span><span class="p">()</span>
|
||
|
||
<span class="n">callables</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">"dashline"</span><span class="p">:</span> <span class="n">_dashline</span><span class="p">,</span>
|
||
<span class="s2">"uptime"</span><span class="p">:</span> <span class="n">_uptime</span><span class="p">,</span>
|
||
<span class="o">**</span><span class="n">funcparser</span><span class="o">.</span><span class="n">FUNCPARSER_CALLABLES</span><span class="p">,</span>
|
||
<span class="o">**</span><span class="n">funcparser</span><span class="o">.</span><span class="n">ACTOR_STANCE_CALLABLES</span><span class="p">,</span>
|
||
<span class="o">**</span><span class="n">funcparser</span><span class="o">.</span><span class="n">SEARCHING_CALLABLES</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="n">parser</span> <span class="o">=</span> <span class="n">funcparser</span><span class="o">.</span><span class="n">FuncParser</span><span class="p">(</span><span class="n">callables</span><span class="p">)</span>
|
||
|
||
<span class="n">string</span> <span class="o">=</span> <span class="s2">"This is the current uptime:$dashline($toint($uptime()) seconds)"</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
|
||
|
||
</pre></div>
|
||
</div>
|
||
<p>Above we define two callables <code class="docutils literal notranslate"><span class="pre">_dashline</span></code> and <code class="docutils literal notranslate"><span class="pre">_uptime</span></code> and map them to names <code class="docutils literal notranslate"><span class="pre">"dashline"</span></code> and <code class="docutils literal notranslate"><span class="pre">"uptime"</span></code>,
|
||
which is what we then can call as <code class="docutils literal notranslate"><span class="pre">$header</span></code> and <code class="docutils literal notranslate"><span class="pre">$uptime</span></code> in the string. We also have access to
|
||
all the defaults (like <code class="docutils literal notranslate"><span class="pre">$toint()</span></code>).</p>
|
||
<p>The parsed result of the above would be something like this:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>This is the current uptime:
|
||
------- 343 seconds -------
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<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="MonitorHandler.html" title="MonitorHandler"
|
||
>next</a> |</li>
|
||
<li class="right" >
|
||
<a href="EvTable.html" title="EvTable"
|
||
>previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">The Inline Function Parser</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2022, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||
</div>
|
||
</body>
|
||
</html> |