You are using a browser which doesn't fully support Cascading Style Sheets. This site will look much better in a browser that supports web standards, but its content is accessible to any browser or Internet device.

Paragraph filters: preprocess your paragraphs

Imagine you write a document that describes a programming technique, and illustrates it with various code examples. The examples are taken from real project code, so they are simply cut and pasted into your PerlPoint. Here is an example code snippet (in Perl):

    Look at this example:
  
      # do important things
      doImportantThings();
  
      # function definition
      sub doImportantThings
       {
        # just do it
        do {$things->important};
       }

This works, but the code in the produced document looks a bit plain - it looked much nicer in the editor where it was syntax-highlighted!

However, colors can be added to examples by tags or macros. Let's say we defined several color macros and decide to highlight comments in Green. The PerlPoint source now looks like this:

    Look at this example:
  
      \GREEN<# do important things>
      doImportantThings();
  
      \GREEN<# function definition>
      sub doImportantThings
       {
        \GREEN<# just do it>
        do {$things->important};
       }

This looks better, but it comes at a price - one has to modify each code snippet manually. Which doesn't work well with many examples, or if the code has to be adapted to the project later on, or if you are in a hurry.

And this is the point where paragraph filters can help. Paragraph filters take an entire paragraph and send it to a predefined function, which supplies a modified version of it. The modified version then replaces the original paragraph.

To define a paragraph filter first we need to write the filter function (or to load it with an included source). A function to add \GREEN tags to all comments of a Perl (or UNIX shell, or makefile, or ...) source can be defined like this:

    \EMBED{lang=perl}
  
    # define a paragraph filter to highlight Perl style comments
    # (beginning with a "#")
    sub formatComments
     {
      $main::_pfilterText=~s/((?<!([\":$]))#.+)$/\\GREEN<$1>/mg;
      $main::_pfilterText;
     }
  
    # declare a shortcut
    *co=\&formatComments;
  
    # supply "PerlPoint"
    '';
  
    \END_EMBED

As you can see, a filter gets the paragraph source in a global variable $main::_pfilterText, and returns the new paragraph source (which for that reason should be valid PerlPoint). In our example, we use a pattern to find all occurences of a # character and wrap a \GREEN macro around this character and everything that follows at the same line. (This is a rather simple approach, but it turns out it works in almost all cases.)

Now, to apply the filter to a paragraph two things are required. First, perlpoint needs to be called with the -active option to allow Active Contents, as running the filter means invoking user code. Second, we have to mark a paragraph that the filter should be applied to. This is done by a preceding ||<filter>|| sequence right at the beginning of the first paragraph line:

    Look at this example:
  
    ||co||  # do important things
      doImportantThings();
  
      # function definition
      sub doImportantThings
       {
        # just do it
        do {$things->important};
       }

Note that the filter directive ( ||co||) starts with the first character of the line. The character that indicates the paragraph type - one or more whitespaces in case of an example block - follows the filter. In other words, to apply a filter to a paragraph the paragraph can remain unchanged, one just has to precede it with the filter expression.

Now that you know this, you see why we defined a shortcut for the filter function ;-)

Our example above produces something like this:

    # do important things
    doImportantThings();
  
    # function definition
    sub doImportantThings
     {
      # just do it
      do {$things->important};
     }

Quite nice, isn't it? 2

Here is the definition of another filter. This time we want to center a paragraph, which especially for examples makes the result looking better. With macros \CENTER_ON and CENTER_OFF, the filter is simply this:

    \EMBED{lang=perl}
  
    sub center
     {
      # just wrap what you found
      "\n\n\\CENTER_ON\n\n$main::_pfilterText\n\n\\CENTER_OFF\n\n";
     }
  
    # declare shortcut
    *c=\¢er;
  
    # supply "PerlPoint"
    '';
  
    \END_EMBED

Now with this filter, centering an example is simply done by adding ||c|| in front of it, like here:

    Look at this example:
  
    ||c||  # do important things
      doImportantThings();
  
      # function definition
      sub doImportantThings
       {
        # just do it
        do {$things->important};
       }

Which makes it look this way:

    # do important things
    doImportantThings();
  
    # function definition
    sub doImportantThings
     {
      # just do it
      do {$things->important};
     }

Well ... if only the highlightning had been survived :-( But wait - filters can be chained. To apply more than one filter, separate the filter names by a pipe character ( |) - in fact the result of the first filter is "piped" to the next one, and so on. This way we can get both highlightning and centering:

    Look at this example:
  
    ||co|c||  # do important things
      doImportantThings();
  
      # function definition
      sub doImportantThings
       {
        # just do it
        do {$things->important};
       }

Which makes it look this way:

    # do important things
    doImportantThings();
  
    # function definition
    sub doImportantThings
     {
      # just do it
      do {$things->important};
     }

Paragraph filters are not limited to examples, but are of a great value there.


2: For a more sophisticated code highlighter, please see the next chapter.