__END__ =head1 NAME Guide To Irssi Scripting. =head1 DESCRIPTION This page presents a bunch of additional information about scripting for Irssi that doesn't fit well anywhere else. It contains useful tips, common pitfalls, and a bunch of other handy things. At least, I hope so. =head1 LOADING AND UNLOADING SCRIPTS =head2 File Locations Packaged Irssi script files are usually placed in F, but custom scripts or those required by a single user can be placed in F<~/.irssi/scripts/>. =head3 Autorunning Scripts If you require a script be run when Irssi starts, you can place the file (or better, create a symlink to it) into F<~/.irssi/scripts/autorun/>. Alternatively, if you want more control over the order in which scripts are autoloaded, you can place SCRIPT LOAD script1 SCRIPT LOAD script2 SCRIPT LOAD script3 into your F<~/.irssi/startup> file. I on Freenode/#irssi>. =head2 Testing =for comment B =head3 C The C>. A default Irssi configuration also provides the C alias as an alternative to C. Loaded scripts will exist in the Irssi namespace as: CnameE>>, where I is the filename stripped of its F<.pl> extension. =head2 Unloading A script can be unloaded via the C> command. The name is typically the script filename without the F<.pl> extension, so F becomes C. As part of the unloading process, if the script contains a sub UNLOAD { ... } function, it will be run just before the script is unloaded and all variables destroyed. This can be used to clean up any temporary files, shut down any network connections or processes, and restore any Irssi modifications made. =head1 ANATOMY OF A SCRIPT In this section, we develop a very simplistic script and look at the necessary code. B This section has considerable overlap with L, which you may also wish to read. B =head2 Preamble All scripts should contain a header as follows: use strict; use warnings; use vars qw($VERSION %IRSSI); use Irssi; $VERSION = '1.00'; %IRSSI = ( authors => 'Author Name(s)', contact => 'author_email@example.com', name => 'Script Title', description => 'Longer script description ', license => 'Public Domain', ); The first two lines are optional, but strongly advised. They provide far greater error checking and diagnostics should you make a mistake in your code. The C defines two global variables, which are then set below to the appropriate values. C tells the script to make the various L support functions available. Additional parameters passed here with C can be used to import functions into the current script namespace. =head1 COMMONLY SCRIPTED TASKS =head2 Modifying an input line before sending B =head2 Responding to a public message B =head2 Responding to a private message B =head1 USEFUL THINGS =head2 Dealing with Blocking IO B on SIO> - fork and use pipes to communicate. Also remember to pidwait the child> =head2 Getting the Response Value of a Remote Command B =head2 Getting the Response Value of a Local Command B There is no simple way to achieve this. The data backing most common activities can be extracted through other API calls, but there are some exceptions. Maybe, look up the format, intercept gui print text, try to match it against what you're expecting? Can this be generalised at all? =head2 Sharing Code Between Scripts There are 2 main ways for scripts to communicate, either via emitting and handling Irssi signals, or by calling functions from one another directly. =head3 Using Signals In order to use custom signals, they must first be registered with Irssi. During registration, a list of the parameters must also be specified. Once specified, it cannot be changed without restarting Irssi, so be warned. After registration, your script can simply listen for signals with L, or generate them for others to handle with L For example: B =head3 Using Functions Because scripts exist in a well-defined namespace of C, it is possible to manipulate the perl symbol table to call functions directly on them, assuming they are loaded. Because the following code depends on I, it is necessary to tell Perl to allow them, despite normally being prohibited by C. The C line takes care of this, and reenables them at the end of the snippet. no strict 'refs'; if (defined %{ 'Irssi::Script::SOMEPACKAGE::' }) { if (defined &{'Irssi::Script::SOMEPACKAGE::SOME_FUNC'} ) { (&{'Irssi::Script::SOMEPAKAGE::SOME_FUNC'}(@args)); } else { print("Err: can't find Irssi::Script::SOMEPACKAGE::SOME_FUNC"); } } use strict 'refs'; Here, C is the name of the script package which contains the function you want to call, and C is the name of the function within it you wish to call. The first 2 C lines take care of ensuring that the package and function exist, and generate an error otherwise. Other error handling is possible, including executing a C to load the necessary script and retry, but is not shown here. I on Freenode/#irssi>. =head2 If In Doubt, Dump! C is an extremely good way to inspect Irssi internals if you're looking for an undocumented feature. The C alias by L provides an easy way to check object fields. Dump perl object (e.g. C): /alias DUMP script exec use Data::Dumper\; print Data::Dumper->new([\\$0-])->Dump =head2 Making Scripts Act Native An important part of creating a good script is to make it behave as though it were a part of Irssi. Adhering to some of the standard conventions can make this easier. =head3 Provide Help Scripts commonly store information about how to use them in comments at the top of their file. Whilst better than no documentation at all, a preferable approach is to allow that help to be accessed from within Irssi itself, using the C command. my $help = "this is help for b"; Irssi::command_bind('help', sub { if ($_[0] eq 'test_b') { Irssi::print($help, MSGLEVEL_CLIENTCRAP); Irssi::signal_stop; } } ); This example demonstrates overriding the C command, and if the argument matches our command, print some custom help and prevent the internal Irssi help function from being called. Otherwise, it falls back to the default help. I on Freenode/#irssi>. =head3 Use Tab Completion One of the great features of Irssi is the ability to complete commands, subcommands and even certain arguments. Using the subcommands processing feature described below automatically allows those subcommands to be tab-completed, but for more complex tasks, you can hook into the autocompletion system itself. In order to create your own completions, you must intercept the C<"complete word"> signal and return a list of completion candidates. sub do_complete { my ($strings, $window, $word, $linestart, $want_space) = @_; # only provide these completions if the input line is otherwise empty. return unless ($linestart eq '' && $word eq ''); # add the completion candidates push @$strings, qw/foo bar baz bacon/; # indicate that we want to include a space after the completion $$want_space = 1; # prevent internal Irssi completion from responding Irssi::signal_stop; } Irssi::signal_add_first('complete word', \&do_complete); I|http://scripts.irssi.org/scripts/complete_lastspoke.pl> by Daenyth> =head3 Use Settings for Customisation Many scripts require the setting of various parameters to affect how they behave. One approach is to require the user to directly edit the script file, but this is less than ideal for a number of reasons. Firstly, it is easy to introduce errors into a script by accidentally deleting closing quotes or semicolons. Secondly, it has no effect until the script is reloaded, leading to confusion. A much better alternative is to use Irssi's inbuilt settings mechanism to allow users to set these parameters from within Irssi, as well as to C their settings for subsequent invocations. B B B =head3 Use Subcommands to Group Script Functionality A common theme in Irssi scripts is to define commands with a prefix, such as C, C, etc. This helps to avoid accidentally clobbering native commands and those defined by other scripts, but is a problem better solved with I. Subcommands allow you to bind commands such as C and C. Completions are automatically handled for both the primary command, and any subcommands contained within it. The following example demonstrates how to use subcommands from within a script: Irssi::command_bind("foo bar", \&subcmd_bar); Irssi::command_bind("foo", \&subcmd_handler); sub subcmd_handler { my ($data, $server, $item) = @_; $data =~ s/\s+$//g; # strip trailing whitespace. Irssi::command_runsub('foo', $data, $server, $item); } sub subcmd_bar { my ($args) = @_; print "subcommand called with: $args"; } =head1 AUTHOR & THANKS This page was written by Tom Feist C, but draws on the help of many many people. The denizens of Freenode/#irssi have been particularly helpful, especially C and C. To report bugs or suggestions, email me at the address before, or come talk to me in C<#irssi> on C. =head1 OTHER RESOURCES The documentation assembled here and elsewhere on this site has been drawn from many different places, and a lot of valuable information is available from the following sites. =over =item L =item L =item L =item L =item L =item L =item L =item L =back