Scripting Guide

Building on the Configuration Quick Start, this chapter explains more complex commands and constructs of the scripting language. It also helps with controlling rTorrent from the outside, via the XMLRPC protocol.

It is to become the comprehensive reference to rTorrent’s command language that was always missing, and will only be a success when enough people join forces and thus spread the workload to many shoulders. If you’re a developer or power user, this will be an invaluable tool, so please take the time and contribute what you know.

See the Commands Reference chapter for a list of all relevant XMLRPC and ‘private’ commands of rTorrent with a short explanation. The generated index also lists all the command names.

Another helpful tool is the quite powerful GitHub search. Use it to find information on commands, e.g. their old vs. new syntax variants, what they actually do (i.e. “read the source”), and internal uses in predefined methods, handlers, and schedules. Consider the view.add example.

Introduction

rTorrent scripting uses a strictly line-oriented syntax, with no control structures that span several logical lines. Read Basic Syntax Elements (again) regarding the most fundamental syntax rules. If you skipped Config Template Deconstructed, now is the time to go through it, since it exposes you to common idioms while explaining the core config commands.

Here’s also a short command syntax summary:

  • Comments start with a #.
  • Line continuations work by escaping the line end with \.
  • Commands take the form cmd = arg, (‘old’ syntax) or (cmd, arg, …) (‘new’ syntax).
  • Arguments are a comma-separated list: arg1, arg2, .
  • $cmd=… evaluates cmd and inserts its result value in place of the call. A command in single parentheses is also immediately evaluated.
  • Use double quotes for preserving whitespace, or to pass statements as arguments to other commands (like method.insert and schedule2). Use \" to escape quotes within quoted strings.
  • Within double quotes, a semicolon ; can be used as a delimiter to pass command sequences, e.g. in event handler bodies and scheduled commands.
  • Use double parentheses to pass a command unevaluated to another command.
  • Braces {…, …} pass a list as an argument, used for setting list values, or with boolean operators.
  • All commands are defined in the C++ source files rtorrent/src/command_*.cc of the client’s source code, which is the ultimate reference when it comes to intricate details.

Commands

A command is basically a function call or method, used to either query or change a configuration setting, or cause some side-effect at runtime. They’re called by the configuration file parser, timed schedules, event handlers, and via XMLRPC.

See Object Types for the difference between simple and ‘multi’ commands, and what return types commands can have. You can use method.redirect to define alias names for commands, which is mostly used internally to keep deprecated command names alive for a while.

A deep-dive into defining your own commands can be found in the reference of related method.* commands.

Use the Commands Reference for details on specific commands, and the generated index to find them by name.

Escaping

The most basic form of escaping is when you have to supply a command with multiple arguments to another command as part of an argument list. You have to tell rTorrent which comma belongs to the inner argument list, and which to the outer one, by quoting the inner command using double quotation marks:

outer = arg1, "inner=arg21,arg22", arg3

It’s also good style to avoid deep nesting by defining your own custom commands (see method.insert, and also Config Template Deconstructed and Common Configuration Use-Cases for many examples). You can then use these building blocks in another command, instead of a literal nested group. The additional benefit is you can name things for documentation purposes, and also avoid overly long lines.

In practice, anything but a single nested quote should be avoided, because the next level already gives you the \\\" awkwardness.

Make plenty use of line continuations, i.e. escaping of line ends to break up long physical lines into several short ones. Put the breaks into places where you can use any amount of whitespace, and then indent the parts according to the structure of the logical line.

method.insert = indent_sequence_of_cmds_and_their_args, private|simple,\
    "load.verbose =\
        (cat, (cfg.watch), (argument.0), /*.torrent),\
        (cat, d.category.set=, (argument.0)) ;\
     category.view.update = (argument.0)"

schedule2 = polling, 10, 120,\
    ((d.multicall2, main,\
        "branch=\"or={d.up.rate=,d.down.rate=,}\",\
            poll=$interval.active=,\
            poll=$interval.idle="))

Also note how using combinations of ‘new’ and ‘old’ syntax keeps the needed amount of escaping at bay (double parentheses are also a form of escaping).

Object Types

This is a summary about the possible object types in command_dynamic.cc (applies to 0.9.6).

Subtypes determine certain traits of a command, like immutability (const, enabled directly in a definition, or via method.const.enable). If a command is private, it can only be called from within rTorrent, but not directly via XMLRPC – it will thus also be excluded from system.listMethods.

TODO static?!

value, bool, string, list (subtypes: static, private, const)

These are the standard object types, value is an integer, and bool just a convention of using the integer values 0 for false and 1 for true.

Lists are either generated by commands that return multiple values, like download_list, or defined literally using the {val[, …]} syntax to pass them into commands.

simple (subtypes: static, private, const)

Simple commands are defined once and cannot be changed dynamically like multi ones. They can still contain a sequence of several commands in a given order, using "cmd1=… ; cmd2=…" or (( (cmd1,…), (cmd2,…) )).

Important

Be aware of the time of evaluation of commands in method definitions.

Quoted command sequences are parsed on each execution and thus only evaluated then, while using parentheses means instant evaluation for a single pair, and delayed evaluation for commands in double parentheses.

That delay is not inherited by nested commands. So ((cat, (manifest.constant) )) works as intended, while ((if, (dynamic.value), )) does not (the inner call also needs double parentheses)!

Which means you always have to keep the surrounding context in mind when writing nested command sequences.

multi (subtypes: static, private, const, rlookup)

A multi command is an array of simple commands, indexed by a name. When you call a multi command, the sequence is executed in order of the keys used when defining a single command of the sequence.

Multi commands are used at many places in rTorrent, especially where dynamic user-defined behaviour is needed. All the event handlers are of type multi.

Note that many internal entries in multi commands used by the system are prefixed with either ! or ~, to push them to the front or end of the processing order.

TODO rlookup?!

Formatting & Type Conversions

TODO

Custom Attributes

TODO

Advanced Concepts

‘✴.multicall’ Demystified

TODO

Scripting Best Practices

TODO

Using XMLRPC for Remote Control

See the Commands Reference for descriptions of existing commands, the generated index can help you to quickly find them by their name.

All XMLPPC commands (with a few exceptions like system.listMethods) take an info hash as the first argument when called over the API, to uniquely identify the target object. ‘Target’ is also the term used for that first parameter in error messages like Unsupported target type found, and that message is the one you’ll most likely get if you forgot to provide one.

Commands that do not target a specific item still need to have one (in newer versions of rTorrent), so provide an empty string as a placeholder in those cases.

$ rtxmlrpc view.size default
ERROR    While calling view.size('default'): <Fault -501: 'Unsupported target type found.'>
$ rtxmlrpc view.size '' default
133

Note that f.* commands, p.* commands, and t.* commands, when not called via their associated multicall command, have special target forms with additional information appended: ‹infohash›:f‹file-index›, ‹infohash›:p‹peer-id›, and ‹infohash›:t‹tracker-index›.

TODO

  • TCP vs. Unix domain sockets
  • raw SCGI vs. HTTP gateways
  • XMLRPC buffer size
  • client libs
  • daemon mode