PLUMB(6)                                                 PLUMB(6)

          plumb - format of plumb messages and rules

          #include <plumb.h>

        Message format
          The messages formed by the plumb(2) library are formatted
          for transmission between processes into textual form, using
          newlines to separate the fields.  Only the data field may
          contain embedded newlines.  The fields occur in a specified
          order, and each has a name, corresponding to the elements of
          the Plumbmsg structure, that is used in the plumbing rules.
          The fields, in order, are:

               src    application/service generating message
               dst    destination `port' for message
               wdir   working directory (used if data is a file name)
               type   form of the data, e.g.  text
               attr   attributes of the message, in name=value pairs
                      separated by white space (the value must follow
                      the usual quoting convention if it contains
                      white space or quote characters or equal signs;
                      it cannot contain a newline)
               ndata  number of bytes of data
               data   the data itself
          At the moment, only textual data (type=text) is supported.

          All fields are optional, but type should usually be set
          since it describes the form of the data, and ndata must be
          an accurate count (possibly zero) of the number of bytes of
          data.  A missing field is represented by an empty line.

        Plumbing rules
          The plumber (see plumb(2)) receives messages on its send
          port (applications send messages there), interprets and
          reformats them, and (typically) emits them from a destina-
          tion port.  Its behavior is determined by a plumbing rules
          file, default /usr/$user/lib/plumbing, which defines a set
          of pattern/action rules with which to analyze, rewrite, and
          dispatch received messages.

          The file is a sequence of rule sets, each of which is a set
          of one-line rules called patterns and actions.  There must
          be at least one pattern and one action in each rule set.
          (The only exception is that a rule set may contain nothing
          but plumb to rules; such a rule set declares the named ports
          but has no other effect.)  A blank line terminates a rule
          set.  Lines beginning with a # character are commentary and

     Page 1                       Plan 9             (printed 7/23/24)

     PLUMB(6)                                                 PLUMB(6)

          are regarded as blank lines.

          A line of the form
               include file
          substitutes the contents of file for the line, much as in a
          C #include statement.  Unlike in C, the file name is not
          quoted.  If file is not an absolute path name, or one begin-
          ning ./ or ../, file is looked for first in the directory in
          which the plumber is executing, and then in /sys/lib/plumb.

          When a message is received by the plumber, the rule sets are
          examined in order.  For each rule set, if the message
          matches all the patterns in the rule set, the actions asso-
          ciated with the rule set are triggered to dispose of the
          message.  If a rule set is triggered, the rest are ignored
          for this message.  If none is triggered, the message is dis-
          carded (giving a write error to the sender) unless it has a
          dst field that specifies an existing port, in which case the
          message is emitted, unchanged, from there.

          Patterns and actions all consist of three components: an
          object, a verb, and arguments.  These are separated by white
          space on the line.  The arguments may contain quoted strings
          and variable substitutions, described below, and in some
          cases contain multiple words.  The object and verb are sin-
          gle words from a pre-defined set.

          The object in a pattern is the name of an element of the
          message, such as src or data, or the special case arg, which
          refers to the argument component of the current rule.  The
          object in an action is always the word plumb.

          The verbs in the pattern rules describe how the objects and
          arguments are to be interpreted.  Within a rule set, the
          patterns are evaluated in sequence; if one fails, the rule
          set fails.  Some verbs are predicates that check properties
          of the message; others rewrite components of the message and
          implicitly always succeed.  Such rewritings are permanent,
          so rules that specify them should be placed after all
          pattern-matching rules in the rule set.

               add     The object must be attr.  Append the argument,
                       which must be a sequence of name=value pairs,
                       to the list of attributes of the message.
               delete  The object must be attr.  If the message has an
                       attribute whose name is the argument, delete it
                       from the list of attributes of the message.
                       (Even if the message does not, the rule matches
                       the message.)
               is      If the text of the object is identical to the
                       text of the argument, the rule matches.
               isdir   If the text of the object is the name of an

     Page 2                       Plan 9             (printed 7/23/24)

     PLUMB(6)                                                 PLUMB(6)

                       existing directory, the rule matches and sets
                       the variable $dir to that directory name.
               isfile  If the text of the object is the name of an
                       existing file (not a directory), the rule
                       matches and sets the variable $file to that
                       file name.
               matches If the entire text of the object matches the
                       regular expression specified in the argument,
                       the rule matches.  This verb is described in
                       more detail below.
               set     The value of the object is set to the value of
                       the argument.
          The matches verb has special properties that enable the
          rules to select which portion of the data is to be sent to
          the destination.  By default, a data matches rule requires
          that the entire text matches the regular expression.  If,
          however, the message has an attribute named click, that
          reports that the message was produced by a mouse click
          within the text and that the regular expressions in the rule
          set should be used to identify what portion of the data the
          user intended.  Typically, a program such as an editor will
          send a white-space delimited block of text containing the
          mouse click, using the value of the click attribute (a num-
          ber starting from 0) to indicate where in the textual data
          the user pointed.
          When the message has a click attribute, the data matches
          rules extract the longest leftmost match to the regular
          expression that contains or abuts the textual location iden-
          tified by the click.  For a sequence of such rules within a
          given rule set, each regular expression, evaluated by this
          specification, must match the same subset of the data for
          the rule set to match the message.  For example, here is a
          pair of patterns that identify a message whose data contains
          the name of an existing file with a conventional ending for
          an encoded picture file:
               data matches '[a-zA-Z0-9_-./]+'
               data matches '([a-zA-Z0-9_-./]+).(jpe?g|gif|bit|ps|pdf)'
          The first expression extracts the largest subset of the data
          around the click that contains file name characters; the
          second sees if it ends with, for example, .jpeg.  If only
          the second pattern were present, a piece of text
          could be misinterpreted as an image file named horse.gif.
          If a click attribute is specified in a message, it will be
          deleted by the plumber before sending the message if the
          data matches rules expand the selection.
          The action rules all have the object plumb.  There are only
          three verbs for action rules:
               to      The argument is the name of the port to which
                       the message will be sent.  If the message has a
                       destination specified, it must match the to
                       port of the rule set or the entire rule set
                       will be skipped.  (This is the only rule that

     Page 3                       Plan 9             (printed 7/23/24)

     PLUMB(6)                                                 PLUMB(6)

                       is evaluated out of order.)
               client  If no application has the port open, the argu-
                       ments to a plumb start rule specify a shell
                       program to run in response to the message.  The
                       message will be held, with the supposition that
                       the program will eventually open the port to
                       retrieve it.
               start   Like client, but the message is discarded.
                       Only one start or client rule should be speci-
                       fied in a rule set.
          The arguments to all rules may contain quoted strings,
          exactly as in rc(1). They may also contain simple string
          variables, identified by a leading dollar sign $.  Variables
          may be set, between rule sets, by assignment statements in
          the style of rc.  Only one variable assignment may appear on
          a line.  The plumber also maintains some built-in variables:
               $0     The text that matched the entire regular expres-
                      sion in a previous data matches rule.  $1, $2,
                      etc. refer to text matching the first, second,
                      etc. parenthesized subexpression.
               $attr  The textual representation of the attributes of
                      the message.
               $data  The contents of the data field of the message.
               $dir   The directory name resulting from a successful
                      isdir rule.  If no such rule has been applied,
                      it is the string constructed syntactically by
                      interpreting data as a file name in wdir.
               $dst   The contents of the dst field of the message.
               $file  The file name resulting from a successful isfile
                      rule.  If no such rule has been applied, it is
                      the string constructed syntactically by inter-
                      preting data as a file name in wdir.
               $type  The contents of the type field of the message.
               $src   The contents of the src field of the message.
               $wdir  The contents of the wdir field of the message.

          The following is a modest, representative file of plumbing
          # these are generally in order from most specific to least,
          # since first rule that fires wins.


          # image files go to page
          type is text
          data matches '[a-zA-Z0-9_\-./]+'
          data matches '([a-zA-Z0-9_\-./]+).(jpe?g|gif|bit)'
          arg isfile $0

     Page 4                       Plan 9             (printed 7/23/24)

     PLUMB(6)                                                 PLUMB(6)

          plumb to image
          plumb start page -w $file

          # URLs go to web browser
          type is text
          data matches $protocol://$domain$file
          plumb to web
          plumb start window webbrowser $0

          # existing files, possibly tagged by line number, go to edit/sam
          type is text
          data matches '([.a-zA-Z0-9_/-]+[a-zA-Z0-9_/\-])('$addr')?'
          arg isfile $1
          data set $file
          attr add addr=$3
          plumb to edit
          plumb start window sam $file

          # .h files are looked up in /sys/include and passed to edit/sam
          type is text
          data matches '([a-zA-Z0-9]+\.h)('$addr')?'
          arg isfile /sys/include/$1
          data set $file
          attr add addr=$3
          plumb to edit
          plumb start window sam $file

          The following simple plumbing rules file is a good beginning
          set of rules.
          # to update: cp /usr/$user/lib/plumbing /mnt/plumb/rules

          editor = acme
          # or editor = sam
          include basic

          /usr/$user/lib/plumbing  default rules file.
          /mnt/plumb               mount point for plumber(4).
          /sys/lib/plumb           directory for include files.
          /sys/lib/plumb/fileaddr  public macro definitions.
          /sys/lib/plumb/basic     basic rule set.

          plumb(1), plumb(2), plumber(4), regexp(6)

     Page 5                       Plan 9             (printed 7/23/24)