summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorKevin McCarthy <kevin@8t8.us>2020-07-15 19:44:52 -0700
committerKevin McCarthy <kevin@8t8.us>2020-07-19 14:23:52 -0700
commit40ce20c8e3d704a14ee3ed8e89effb04a02796a4 (patch)
tree0014c11657a72ef7cd23a2f50bada47e9d93730c /doc
parentc5c448d465388b4043f9a25e73d17a88f207db15 (diff)
Add first version of MuttLisp.
This is somewhat simple enhancement to muttrc processing, not a full-blown embedded scripting language. There are no variables, functions, types, or abilities that compete with macros. MuttLisp can be invoked using the "run" command. If $muttlisp_inline_eval is set, it can also be invoked with a bare parenthesis expression as a command argument. $muttlisp_inline_eval defaults unset, to avoid breaking existing configurations, which might have bare parenthesis arguments for regexps.
Diffstat (limited to 'doc')
-rw-r--r--doc/manual.xml.head367
1 files changed, 355 insertions, 12 deletions
diff --git a/doc/manual.xml.head b/doc/manual.xml.head
index 7021b44d..b395fe7a 100644
--- a/doc/manual.xml.head
+++ b/doc/manual.xml.head
@@ -2235,6 +2235,20 @@ affected.
</para>
<para>
+If <link linkend="muttlisp-inline-eval">$muttlisp_inline_eval</link> is set, an unquoted
+parenthesis-enclosed expression will be evaluated as MuttLisp. See the
+<link linkend="muttlisp">Using MuttLisp</link> section for more details.
+</para>
+
+<example id="ex-rc-muttlisp">
+<title>Using MuttLisp expresions</title>
+<screen>
+set signature = \
+ (if (equal $my_name "Kevin McCarthy") ~/kevin.sig ~/other.sig)
+</screen>
+</example>
+
+<para>
The commands understood by Mutt are explained in the next paragraphs.
For a complete list, see the <link linkend="commands">command
reference</link>.
@@ -7326,6 +7340,326 @@ macro index ,a "&lt;save-message&gt;=archive&lt;enter&gt;&lt;enter-command&gt;ec
</itemizedlist>
</sect1>
+<sect1 id="muttlisp">
+ <title>Using MuttLisp (EXPERIMENTAL)</title>
+ <para>
+ MuttLisp is a Lisp-like enhancement for the Mutt configuration
+ file. It is currently experimental, meaning new releases may
+ change or break syntax. MuttLisp is not a real language, and is
+ not meant to be an alternative to macros. The features are
+ purposely minimal, with the actual work still being done by Mutt
+ <link linkend="commands">commands</link>.
+ </para>
+ <para>
+ There are two ways to invoke MuttLisp: via the
+ <literal>run</literal> command, or interpolated as a command
+ argument.
+ </para>
+
+ <sect2 id="run">
+ <title>Running a command generated by MuttLisp</title>
+ <para>
+ Usage:
+ </para>
+ <cmdsynopsis>
+ <command>run</command>
+ <arg choice="plain">
+ <replaceable class="parameter">MuttLisp</replaceable>
+ </arg>
+ </cmdsynopsis>
+
+ <para>
+ The <literal>run</literal> command evaulates the MuttLisp argument.
+ The output of the MuttLisp is then executed as a
+ Mutt command, as if it were typed in the muttrc instead.
+ </para>
+
+<screen>
+run (concat "set my_name = '" \
+ (or $ENV_NAME "Test User") "'")
+
+ ==> generates and runs the line:
+ set my_name = 'Text User'
+</screen>
+
+ <para>
+ This will set the Mutt <link linkend="set-myvar">User-Defined Variable</link>
+ <literal>$my_name</literal> to either the environment variable $ENV_NAME, if
+ defined, or else "Test User".
+ </para>
+ </sect2>
+
+ <sect2 id="muttlisp-interpolate">
+ <title>Interpolating MuttLisp in a Command Argument</title>
+ <para>
+ The second way of running is directly as a command argument.
+ An unquoted parenthesis expression will be evaluated, and the result
+ substituted as the argument.
+ </para>
+ <para>
+ To avoid breaking existing configurations, this is disabled by
+ default. It can be enabled by setting <link
+ linkend="muttlisp-inline-eval">$muttlisp_inline_eval</link>. Before doing so, you should
+ review your Mutt configuration to ensure you don't have any bare
+ parenthesis expressions elsewhere, such as the regexp parameter
+ of a <link linkend="folder-hook">folder-hook</link>. These can typically be
+ surrounded by single or double-quotes to prevent being evaluated as
+ MuttLisp.
+ </para>
+
+<screen>
+set my_name = (or $ENV_NAME "Test User")
+</screen>
+
+ <para>
+ The result of the MuttLisp is directly assigned as the argument.
+ It isn't reinterpreted, so there is no need for the outer
+ quotes. This is in contrast with the <link
+ linkend="run">run</link> command, where the output is
+ reinterpreted by the muttrc parser.
+ </para>
+ </sect2>
+
+ <sect2 id="muttlisp-syntax">
+ <title>MuttLisp Syntax</title>
+ <para>
+ MuttLisp was inspired by Lisp, and so follows the same basic
+ syntax. All statements are surrounded by parenthesis. The first argument
+ inside the parenthesis is a function to invoke. The remaining arguments
+ are passed as parameters.
+ </para>
+ <para>
+ The arguments to functions are read and evaluated using <link
+ linkend="muttrc-syntax">muttrc syntax</link>. This means Mutt
+ variables or environment variables can be passed directly, or
+ interpolated inside a double-quoted string.
+ </para>
+ <para>
+ Although the arguments to a function are evaluated, the result
+ of the function call is not.
+ </para>
+<screen>
+echo (concat '$' 'spoolfile')
+ ==> $spoolfile
+</screen>
+
+ <para>
+ MuttLisp has no types - everything is stored and evaluated as
+ a string, just as with the muttrc. True is defined as a non-empty
+ string, and false as the empty string.
+ </para>
+ <para>
+ The muttrc is evaluated line by line, and MuttLisp is similarly
+ constrained. Input can be continued on more than one line by
+ placing a backslash at the end of the line.
+ </para>
+ </sect2>
+
+ <sect2 id="muttlisp-funcs">
+ <title>MuttLisp Functions</title>
+
+ <sect3 id="muttlisp-concat">
+ <title>concat</title>
+ <para>
+ Combines all arguments into a single string.
+ </para>
+<screen>
+echo (concat one two three)
+ ==> onetwothree
+</screen>
+ </sect3>
+
+ <sect3 id="muttlisp-quote">
+ <title>quote</title>
+ <para>
+ Prevents interpretation of the list. Note that the list must
+ still obey MuttLisp syntax: single quotes, double quotes,
+ backticks, and parenthesis are still parsed prior to
+ <literal>quote</literal> running and must be matching.
+ </para>
+<screen>
+echo (quote one two three)
+ ==> one two three
+
+echo (quote $spoolfile)
+ ==> $spoolfile
+
+echo (quote (one two three))
+ ==> (one two three)
+</screen>
+ </sect3>
+
+ <sect3 id="muttlisp-equal">
+ <title>equal</title>
+ <para>
+ Performs a case-sensitive comparison of each argument. Stops evaluating
+ arguments when it finds the first one that is not equal. Returns
+ "t" if they are all equal, and the empty string if not.
+ </para>
+<screen>
+echo (equal one one)
+ ==> "t"
+
+echo (equal one `echo one`)
+ ==> "t"
+
+echo (equal one one two `echo three`)
+ ==> ""
+ note: `echo three` does not execute.
+
+echo (equal "one two" `echo one two`)
+ ==> ""
+ note: backticks generate two arguments "one" and "two"
+
+echo (equal "one two" "`echo one two`")
+ ==> "t"
+ note: backticks inside double quotes generates a single argument: "one two"
+</screen>
+ </sect3>
+
+ <sect3 id="muttlisp-not">
+ <title>not</title>
+ <para>
+ Accepts a single argument only.
+ Returns "t" if the argument evaluates to the empty string.
+ Otherwise returns the empty string.
+ </para>
+<screen>
+echo (not one)
+ ==> ""
+
+echo (not "")
+ ==> "t"
+
+echo (not (equal one two))
+ ==> "t"
+</screen>
+ </sect3>
+
+ <sect3 id="muttlisp-and">
+ <title>and</title>
+ <para>
+ Returns the first argument that evalutes to the empty string.
+ Otherwise returns the last argument, or "t" if there are no arguments.
+ </para>
+<screen>
+echo (and one two)
+ ==> "two"
+
+echo (and "" two `echo three`)
+ ==> ""
+ note: `echo three` does not execute.
+
+echo (and)
+ ==> "t"
+</screen>
+ </sect3>
+
+ <sect3 id="muttlisp-or">
+ <title>or</title>
+ <para>
+ Returns the first argument that evaluates to a non-empty string. Otherwise
+ returns the empty string.
+ </para>
+<screen>
+echo (or one two)
+ ==> "one"
+
+echo (or "" two `echo three`)
+ ==> "two"
+ note: `echo three` does not execute.
+
+echo (or)
+ ==> ""
+</screen>
+ </sect3>
+
+ <sect3 id="muttlisp-if">
+ <title>if</title>
+ <para>
+ Requires 2 or 3 arguments. The first is a conditional. If it
+ evaluates to "true" (a non-empty string), the second argument is
+ evaluated and returned. Otherwise the third argument is evaluated
+ and returned.
+ </para>
+<screen>
+echo (if a one two)
+ ==> "one"
+
+echo (if "" one two)
+ ==> "two"
+
+set spoolfile = "/var/mail/user"
+echo (if (equal $spoolfile "/var/mail/user") yes no)
+ ==> "yes"
+</screen>
+ </sect3>
+ </sect2>
+
+ <sect2 id="muttlisp-examples">
+ <title>Examples</title>
+<screen>
+# A three-way toggle of $index_format:
+
+set muttlisp_inline_eval
+set my_idx1 = "one"
+set my_idx2 = "two"
+set my_idx3 = "three"
+set index_format = $my_idx1
+
+macro index i '&lt;enter-command&gt;set index_format = \
+ (or \
+ (if (equal $index_format $my_idx1) $my_idx2) \
+ (if (equal $index_format $my_idx2) $my_idx3) \
+ $my_idx1) \
+&lt;enter&gt;'
+</screen>
+ <para>
+ It's important to rememember that function arguments are
+ evaluated, but the result is not. Also, the result of an
+ interpolated command argument is used directly, and needs no
+ quoting.
+ </para>
+
+<screen>
+# Conditionally set up background editing in tmux or GNU Screen:
+
+run \
+ (if (or $STY $TMUX) \
+ (concat \
+ 'set background_edit;' \
+ 'set editor = "bgedit-screen-tmux.sh vim"') \
+ (concat \
+ 'unset background_edit;' \
+ 'set editor = "vim"'))
+</screen>
+ <para>
+ The output of the run command is re-evaluated by the muttrc
+ parser. So it's important to pay more attention to quoting
+ issues when generating the command string.
+ </para>
+
+<screen>
+# Use a Mutt variable inside backticks.
+
+set spoolfile = "/var/mail/testuser"
+
+# This will generate and then run the command string:
+# set my_var = "`~/bin/myscript.sh /var/mail/testuser`"
+run \
+ (concat \
+ 'set my_var = "`~/bin/myscript.sh ' \
+ $spoolfile \
+ '`"')
+</screen>
+ <para>
+ Because backticks are evaluated by MuttLisp too, we need to use
+ the run command and pay close attention to quoting.
+ </para>
+ </sect2>
+
+</sect1>
+
<sect1 id="misc-topics">
<title>Miscellany</title>
@@ -11465,6 +11799,27 @@ The following are the commands understood by Mutt:
<listitem>
<cmdsynopsis>
+<command><link linkend="reply-hook">reply-hook</link></command>
+<arg choice="plain">
+<replaceable class="parameter">[!]pattern</replaceable>
+</arg>
+<arg choice="plain">
+<replaceable class="parameter">command</replaceable>
+</arg>
+</cmdsynopsis>
+</listitem>
+
+<listitem>
+<cmdsynopsis>
+<command><link linkend="run">run</link></command>
+<arg choice="plain">
+<replaceable class="parameter">MuttLisp</replaceable>
+</arg>
+</cmdsynopsis>
+</listitem>
+
+<listitem>
+<cmdsynopsis>
<command><link linkend="save-hook">save-hook</link></command>
<arg choice="plain">
<replaceable class="parameter">[!]pattern</replaceable>
@@ -11499,18 +11854,6 @@ The following are the commands understood by Mutt:
<listitem>
<cmdsynopsis>
-<command><link linkend="reply-hook">reply-hook</link></command>
-<arg choice="plain">
-<replaceable class="parameter">[!]pattern</replaceable>
-</arg>
-<arg choice="plain">
-<replaceable class="parameter">command</replaceable>
-</arg>
-</cmdsynopsis>
-</listitem>
-
-<listitem>
-<cmdsynopsis>
<command><link linkend="send-hook">send-hook</link></command>
<arg choice="plain">
<replaceable class="parameter">[!]pattern</replaceable>