From ac0c9505f168dffac80ca962dad4f2a4c8d724b3 Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Wed, 8 Jan 2020 20:07:24 -0800 Subject: [PATCH] doc/Factoids.md: add /code section describing Code Factoids --- doc/Factoids.md | 142 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/doc/Factoids.md b/doc/Factoids.md index f6f50787..da96d7e8 100644 --- a/doc/Factoids.md +++ b/doc/Factoids.md @@ -91,6 +91,146 @@ If a factoid begins with `/call ` then PBot will call an existing command. This #### /msg If a factoid begins with `/msg ` then PBot will privately message the factoid text to ``. Only admins can use this command. +### /code +Code Factoids are a special type of factoid whose text is treated as code and executed with a chosen programming language +or interpreter. The output from code is then parsed and treated like any other factoid text. This allows anybody to add +new and unique commands to PBot without the need for installing Plugins or modules. + +Code Factoids are executed within a virtual machine. See the [Virtual Machine](doc/VirtualMachine.md) documentation +for more information. + +To create a Code Factoid, use the `/code` command. The syntax is: + + factadd keyword /code + +The `` parameter selects a programming/scripting language or interpreter to use. + +#### Supported languages + +As of this writing, these are the languages and interpreters that PBot supports. It is easy to add additional +languages or interpreters. For example, [take a look at these language/interpreter files.](../modules/compiler_vm/languages) + +#### Special variables + +All the variables listed in [Special Variables](#special-variables) are expanded within Code Factoids before +the code is executed or interpreted. + +[List variables](#list-variables) are also expanded beforehand as well. You can prevent this by using [`factset`](#factset) +to set the `interpolate` [factoid meta-data](#factoid-metadata-list) to `0`. Alternatively, you can prevent `$variables` in +the code from expanding by prefixing their name with an underscore, i.e. `$_variable`. + +#### testargs example + +Let's make a simple Code Factoid that demonstrates command-line arguments. Let's use +the C programming language because why not? + + !factadd testargs /code c11 printf("/say args: "); while (*++argv) printf("[%s] ", *argv); + testargs added to the global channel. + testargs foo bar + args: [foo] [bar] + testargs "abc 123" xyz + args: [abc 123] [xyz] + +#### Setting a usage message + +Suppose you want command to display a usage message if there are no arguments provided. You can use +the [`factset`](#factset) command to set the `usage` [factoid meta-data](#factoid-metadata-list). + + !testargs + args: + + !factset testargs usage Usage: testargs + [global] testcargs 'usage' set to 'Usage: testargs ' + + !testargs + Usage: testargs + +#### poll/vote example + +Here is a basic poll/vote example. Let's use Perl this time. + +First we add the factoids. Note that we use `$_variable` with underscore prefixing +the name to prevent them from being expanded as [List Variables](#list-variables). + + !factadd startvote /code perl use Storable; my $_question = "@ARGV"; + print "Starting poll: $_question Use `vote ` to record your vote."; + my %_votes = (); my @data = ({%_votes}, $_question); + system 'rm -rf vote-data'; mkdir 'vote-data' or print "$!"; + store \@data, 'vote-data/data'; + !factset startvote usage Usage: startvote + + !factadd vote /code perl use Storable; my $_data = retrieve 'vote-data/data'; + my %_votes = %{shift @$_data}; ($_votes{"$nick"}) = (lc "@ARGV"); + unshift @$_data, {%_votes}; store $_data, 'vote-data/data'; + !factset vote usage Usage: vote + + !factadd votes /code perl no warnings; use Storable; my $_data = retrieve 'vote-data/data'; + my %_votes = %{shift @$_data}; my $_question = shift @$_data; + if (not keys %_votes) { print "No votes for \"$_question\" yet."; exit; } + my %_count; map { $_count{$_}++ } values %_votes; + my $_result = "Poll results for \"$_question\": "; my $_comma = ""; + map { $_result .= "$_comma$_: $_count{$_}"; $_comma = ', '; } + sort { $_count{$b} <=> $_count{$a} } keys %_count; print "/say $_result"; + +And action: + + !startvote Isn't this cool? + Starting poll: Isn't this cool? Use `vote ` to record your vote. + !vote yes + !vote no + !vote yes + !vote hamburger + !votes + Poll results for "Isn't this cool?": yes: 2, no: 1, hamburger: 1 + +#### SpongeBob Mock meme example + +Here is an example demonstrating how Code Factoids and command piping can work together. + +The SpongeBob Mock meme takes something ridiculous somebody said and repeats it with the +letters in alternating lower and upper case. + + Girls are dumb! + smh @ derpy3... gIrLs ArE dUmB! + +Let's make a command, using a Code Factoid, to do this! `sm` stands for "SpongeBob Mock". +This time we'll use the Bash shell scripting language. + + !factadd sm /code bash echo "${@,,}"|perl -pe 's/(? !factset sm usage Usage: sm + + !sm Testing one, two... + tEsTiNg OnE, tWo... + +#### Using command-piping + +You can pipe the output of other commands to Code Factoids. + + !echo Testing three, four... | {sm} + tEsTiNg ThReE, fOuR... + + !version | {sm} + pBoT vErSiOn 2696 2020-01-04 + +#### Improving SpongeBob Mock meme + +Let's improve the SpongeBob Mock meme by using the `recall` command to select +the mock text for us. + +First of all, the `recall` command prints output like this: + + !recall derpy3 girls + [5m30s ago] Girls are dumb! + +So we're going to use the `func` command to invoke the built-in `sed` function +to strip the timestamp and the name, leaving only the message. `smr` stands for +"SpongeBob Mock Recall". + + !factadd smr /call recall $args | {func sed s/^.*?\] (<.*?> )?(\S+:\s*)?//} | {sm} + + !smr derpy3 girls + gIrLs ArE dUmB! + ### Special variables You can use the following variables in a factoid or as an argument to one. @@ -353,7 +493,7 @@ Usage: `factshow [channel] ` ### factset To view [factoid meta-data](#factoid-metadata-list), such as owner, rate-limit, etc, use the `factset` command. -Usage: `factset [ [value]]` +Usage: `factset [channel] [ [value]]` Omit `` and `` to list all the keys and values for a factoid. Specify ``, but omit `` to see the value for a specific key.