Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > a6d417e36f6bb1154f4c003e6717e298 > files > 140

a-a-p-1.090-2mdv2009.0.noarch.rpm

<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter 10. Commands in a Pipe</title><meta name="generator" content="DocBook XSL Stylesheets V1.71.1"><link rel="start" href="index.html" title="A-A-P Recipe Executive"><link rel="up" href="tutorial.html" title="Part I. Tutorial"><link rel="prev" href="tutor-include.html" title="Chapter 9. More Than One Recipe"><link rel="next" href="tutor-port.html" title="Chapter 11. A Ported Application"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><table width="100%" id="navtable"><tbody><tr><td align="left" class="left" width="33%"><b><a href="http://www.a-a-p.org">A-A-P home page</a></b></td><td align="center" class="center" width="34%"><b><a href="index.html">A-A-P Recipe Executive</a></b></td><td align="right" class="right" width="33%"></td></tr><tr><td align="left" class="left"><a accesskey="p" href="tutor-include.html">Prev</a></td><td align="center" class="center">Tutorial</td><td align="right" class="right"><a accesskey="n" href="tutor-port.html">Next</a></td></tr></tbody></table><hr><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="tutor-pipe"></a>Chapter 10. Commands in a Pipe</h2></div></div></div><p>
A selection of commands can be connected together with a pipe.
This means the output of one command is the input for the next command.
It is useful for filtering text from a variable or file and writing the result
in a variable or file.
</p><h2><a name="id2631646"></a>Changing a timestamp</h2><p>
This example shows how you can change the timestamp in a file.
It is done in-place.
</p><pre class="programlisting">
    all:
        :print Setting date in foobar.txt.
        :cat foobar.txt
              | :eval re.sub('Last Change: .*\n', 'Last Change: ' + DATESTR + '\n', stdin)
              &gt;! foobar.txt
</pre><p>
Lets see how this works:
</p><div class="literallayout"><p>    % <strong class="userinput"><code>cat foobar.txt</code></strong><br>
    This is example text for the A-A-P tutorial.<br>
    Last Change: 2002 Feb 29<br>
    The useful contents would start here.<br>
    % <strong class="userinput"><code>aap</code></strong><br>
    Setting date in foobar.txt.<br>
    % <strong class="userinput"><code>cat foobar.txt</code></strong><br>
    This is example text for the A-A-P tutorial.<br>
    Last Change: 2002 Oct 21<br>
    The useful contents would start here.<br>
    %<br>
</p></div><p>
The last command in the example consists of three parts.  First comes the
<code class="computeroutput">:cat</code> command.  It reads the "foobar.txt" file and passes it
throught the pipe to the next command.  "cat" is short for "concatenate".
This is one of the good-old Unix commands that actually does much more than
the name suggests.  In this example nothing is concatenated.  Below you will
see examples where it does.
</p><p>
The second part of the example is the <code class="computeroutput">:eval</code> command.
This is used to read the text coming in through the pipe and modify it with a
Python expression.  In this case the expression is a "re.sub()" function call.
This Python function takes three arguments: A pattern, a replacement string
and the text to operate on.  All occurences of the pattern in the text are
changed to the replacement string.  The pattern "Last Change: .*\n" matches a
line with the date that was inserted previously.  The replacement string
contains <code class="literal">DATESTR</code>, which is an <span class="application">Aap</span> variable that contains today's
date as a string, e.g., "2002 Oct 19".  The text to operate on is
<code class="literal">stdin</code>.  This is the variable that holds the text that is coming in
through the pipe.
</p><p>
The third and last part <code class="computeroutput">&gt;! foobar.txt</code> redirects the
output of the <code class="computeroutput">:eval</code> command back to the file "foobar.txt".
Using just "&gt;" would cause an error, since the file already exists.
</p><p>
Note that in a Unix shell command this pipe
would not work: The "foobar.txt" would be overwritten before it was read.  In
<span class="application">Aap</span> this does not happen, the commands in the pipe are executed one by one.
That makes it easier to use, but it does mean the text is kept in memory.
Don't use pipes for a file that is bigger than half the memory you have
available.
</p><p>
Changing a file in-place has the disadvantage that the normal dependencies
don't work, since there is no separate source and target file.  Often it is
better to use a file "foobar.txt.in" as source, change it like in the example
above and write it as a new file.  The recipe would be:
</p><pre class="programlisting">
    foobar.txt: foobar.txt.in
        :print Setting date in $target.
        :cat $source
                | :eval re.sub('Last Change: .*\n', 'Last Change: ' + DATESTR + '\n', stdin)
                &gt;! $target
</pre><h2><a name="id2633390"></a>Creating a file from pieces</h2><p>
Sometimes you need to generate a file from several pieces.  Here is an example
that concatenates two files and puts a generated text line in between.
</p><pre class="programlisting">
    manual.html: body.html footer.html
        @import time
        :eval time.strftime("%A %d %B %Y", time.localtime(time.time()))
                 | :print $(lt)BR$(gt)Last updated: $stdin$BR
                 | :cat body.html - footer.html &gt;! $target
</pre><p>
There are quite a few items here that need to be explained.  First of all, the
"@import time" line.  This is a Python command to load the "time" module.  So
far we used modules that <span class="application">Aap</span> has already loaded for you.  This one isn't,
and since we use the "time" module in the next <code class="computeroutput">:eval</code>
command it needs to be loaded explicitly.
</p><p>
The Python function "strftime()" formats the date and time in a specified
format.  See the Python documentation for the details.  In this case the
resulting string looks like "Monday 21 October 2002".
</p><p>
The output of the <code class="computeroutput">:eval</code> command is piped into a
<code class="computeroutput">:print</code> command.  The variable <code class="literal">stdin</code> contains
the output of the previous command.  Note that "$(lt)" is used instead of
"$lt".  The meaning is exactly the same: the value of the <code class="literal">lt</code>
variable.  Without the extra parenthesis it would read "$ltBR", which would be
the value of the "ltBR" variable.
</p><p>
The resulting text is:
</p><div class="literallayout"><p>        &lt;BR&gt;Last updated: Monday 21 October 2002\n<br>
</p></div><p>
Note that the first "BR" is the HTML code for a line break, while the "$Br" at
the end is the <span class="application">Aap</span> variable that contains a line break (here displayed as
"\n").
</p><p>
Finally, the <code class="computeroutput">:cat</code> command concatenates the file
"body.html", the output of the <code class="computeroutput">:print</code> command and the file
"footer.html".  Thus the "-" stands for where the pipe input is used.
The result is redirected to <code class="literal">target</code>, which is "manual.html".
</p><h2><a name="id2633554"></a>Pipe output in a variable</h2><p>
The generated date in the previous example could be used elsewhere in the
recipe.  Since we don't want to repeat a complicated expression the result of
the <code class="computeroutput">:eval</code> command should be redirected to a variable, like
this:
</p><pre class="programlisting">
    @import time
    :eval time.strftime("%A %d %B %Y", time.localtime(time.time()))
                | :assign Datestamp

    manual.html: body.html footer.html
           :print $(lt)BR$(gt)Last updated: $Datestamp$Br
                 | :cat body.html - footer.html &gt;! $target
</pre><p>
The <code class="computeroutput">:assign</code> command takes the input from the pipe and puts
it in the variable mentioned as its argument, which is "Datestamp" here.
Actually, the same can be done with a normal assignment and a Python
expression in backticks, but we intentionally wanted to show using a pipe
here.
</p><h2><a name="id2633580"></a>Creating a file from scratch</h2><p>
It is also possible to completely generate a file from scratch.  Here is an
example that generates a C header file:
</p><pre class="programlisting">
1    :include config.aap
2    pathdef.c: config.aap
3       :print Creating $target
4       :print &gt;! $target /* pathdef.c */
5       :print &gt;&gt; $target /* This file is automatically created by main.aap */
6       :print &gt;&gt; $target /* DO NOT EDIT!  Change main.aap only. */
7       :print &gt;&gt; $target $#include "vim.h"
8       :print &gt;&gt; $target char_u *default_vim_dir = (char_u *)"$VIMRCLOC";
9       :print &gt;&gt; $target char_u *all_cflags = (char_u *)"$CC -c -I$srcdir $CFLAGS";
</pre><p>
The first <code class="computeroutput">:print</code> command displays a message, so that it's
clear "pathdef.c" is being generated.  The next line contains "&gt;!" to
overwrite an existing file.  It doesn't matter if the file already existed or
not, it now only contains the line "/* pathdef.c */".  The third and following
lines contain "&gt;&gt;".  This will cause each line to be appended to
"pathdef.c".
</p><p>
In the example the <code class="literal">VIMRCLOC</code> and <code class="literal">srcdir</code> variables are
defined in the recipe "config.aap".  That is why this file is used as a source
in the dependency.  Also note the use of "$#" in line 7.  Since "#" normally
starts a comment it cannot be used directly here. "$#" is a special item that
results in a "#" in the <code class="computeroutput">:print</code> output.  This is the
resulting file:
</p><div class="literallayout"><p>       /* pathdef.c */<br>
       /* This file is automatically created by main.aap */<br>
       /* DO NOT EDIT!  Change main.aap only. */<br>
       #include "vim.h"<br>
       char_u *default_vim_dir = (char_u *)"/usr/local/share/vim61";<br>
       char_u *all_cflags = (char_u *)"cc -c -I. -g -O2";<br>
</p></div><p>
The list of "&gt;&gt;" redirections is quite verbose.  Fortunately there is a
shorter way:
</p><pre class="programlisting">
1    :include config.aap
2    pathdef.c: config.aap
3        :print Creating $target
4        text &lt;&lt; EOF
5            /* pathdef.c */
6            /* This file is automatically created by main.aap */
7            /* DO NOT EDIT!  Change main.aap only. */
8            $#include "vim.h"
9            char_u *default_vim_dir = (char_u *)"$VIMRCLOC";
10           char_u *all_cflags = (char_u *)"$CC -c -I$srcdir $CFLAGS";
11               EOF
12       :print $text &gt;! $target
</pre><p>
In line 4 "text &lt;&lt; EOF" is used.  This is called a block assignment.
The following lines, up to the matching "EOF" line, are assigned to the
variable <code class="literal">text</code>.  You can use something else than "EOF" if you want
to.  It must be a word that does not appear inside of the text as a line on
its own.  White space before and after the word is ignored.
</p><p>
The indent of the text in the block assignment is removed.  The indent of the
first line is used, the same amount of indent is removed from the following
lines.  Thus if the second line has two more spaces worth of indent than the
first line, it will have an indent of two spaces in the result.  Half a tab is
replace with four spaces when necessary (a tab always counts for up to eight
spaces).
</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="tutor-include.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="tutorial.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="tutor-port.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 9. More Than One Recipe </td><td width="20%" align="center"><a accesskey="h" href="index.html">
		    Contents</a></td><td width="40%" align="right" valign="top"> Chapter 11. A Ported Application</td></tr></table></div></body></html>