Author: Tobias Schlitt
Date: 2006-01-23 14:16:25 +0100 (Mon, 23 Jan 2006)
New Revision: 2007

Log:
- Add ConsoleTools acrticle to be published on ez.no.

Added:
   docs/articles/ConsoleTools/
   docs/articles/ConsoleTools/introduction/
   docs/articles/ConsoleTools/introduction/img/
   
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_06.png
   
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_07.png
   
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_08.png
   
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_09.png
   
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_10.png
   docs/articles/ConsoleTools/introduction/introduction.txt
Removed:
   docs/articles/examples/

Added: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_06.png
===================================================================
(Binary files differ)


Property changes on: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_06.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_07.png
===================================================================
(Binary files differ)


Property changes on: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_07.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_08.png
===================================================================
(Binary files differ)


Property changes on: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_08.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_09.png
===================================================================
(Binary files differ)


Property changes on: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_09.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_10.png
===================================================================
(Binary files differ)


Property changes on: 
docs/articles/ConsoleTools/introduction/img/consoletools_tutorial_example_10.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: docs/articles/ConsoleTools/introduction/introduction.txt
===================================================================
--- docs/articles/ConsoleTools/introduction/introduction.txt    2006-01-23 
12:37:50 UTC (rev 2006)
+++ docs/articles/ConsoleTools/introduction/introduction.txt    2006-01-23 
13:16:25 UTC (rev 2007)
@@ -0,0 +1,517 @@
+eZ components - ConsoleTools
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. contents:: Table of Contents
+
+Introduction
+============
+
+The ConsoleTools component provides several useful tools to build
+applications that run on a computers console (sometimes also called shell or
+command line). Usually one would not expect to see a component like this for a
+language like PHP, but since PHP 4 more and more features were included in PHP
+which make the language quite neat as a shell scripting language. Indeed you
+can find many situations, where a console based application extends the
+functionality of a web application perfectly or where a pure shell application
+makes sense to be written in PHP. For example eZ publish has several shell
+scripts included, which perform tasks like clearing caches.
+
+The ConsoleTools components offers several (mostly independent) classes to 
+perform different tasks. The main classes are:
+
+Class overview
+==============
+
+This section gives you an overview on all classes, that are intended to be
+used directly.
+
+ezcConsoleOutput
+  ezcConsoleOutput is responsible for printing text to the console. It allows 
+  you to print texts in different colors and using different background colors.
+  Beside that, it can apply other styling information to the text, like making
+  it bold or underlined. Another feature is, that it can automatically wrap 
text
+  for you after a certain amount of characters were printed (keeping words
+  intact) and handle output of different verbosity levels.
+
+ezcConsoleInput
+  Using this little tool, you can handle the options and arguments provided to
+  your shell application. It is capable of handling and validating 3 types of
+  option data-types (string, int and none), can handle optional and mandatory
+  options as well as rules to define relations between those. Rules can include
+  dependencies and exclusions between options.
+
+ezcConsoleProgressbar
+  Most often you will use a console application in favor of a web application,
+  when it comes to processing of very time consuming tasks. To indicate the
+  current progress to the user of an application mostlike a kind of "status 
+  indicator" will be used, which is most commonly a progress bar. 
+  ezcConsoleProgressbar gives you an easy to use interface to realize this 
+  very fast. It will keep track of redrawing the bar as needed, showing actual 
+  and maximum values, as well as the fraction of the current status. It is 
+  fully configurable in respect to it's visual appearance.
+
+ezcConsoleStatusbar
+  ezcConsoleStatusbar is the little brother of ezcConsoleProgressbar. It
+  also allows you to display the progress of a time consuming action, but does
+  not use a fixed bar-like appearance. Instead it simple indicates succeeded
+  and failed operation by displaying a specific character and keeps track of
+  the count of successes and failures for you. This allows you to indicate
+  progress of a process where yoi don't know the number of actions to be 
+  performed before you do it.
+
+ezcConsoleTable
+  This handy class let's you easily create tables to be displayed on the
+  console. It has a very convenient interface to create a table and manage the
+  data it contains. Beside that it is highly configurable on how the table
+  will look like (like different color and style information for content
+  and borders on a per-cell basis, character selection for borders, variable
+  width of the table,...). ezcConsoleTable will also take care of measuring 
the 
+  best width for the table columns (to make your content fit best), 
automatically
+  wrapping too long content and aligning the content in the cells as you like.
+
+Installation
+============
+
+This tutorial assumes that you have set-up an eZ components environment. For
+information on how to do this, please refer to the ComponentsIntroduction_.
+
+.. _ComponentsIntroduction: 
http://ez.no/community/articles/an_introduction_to_ez_components
+
+
+Usage
+=====
+
+Printing text to the console
+----------------------------
+
+As already mentioned, the class ezcConsoleOutput is the tool of choice for
+printing text to the console. Let's look at a basic example:
+
+.. include:: examples/tutorial_example_01.php
+   :literal:
+
+As you can see, the ezcConsoleOutput object is simply instantiated. If you
+like to, you can submit further options and predefined formating options to
+it's constructor, but this can also be done later.
+
+In line 7 you see how a format is defined. Formats are created on the fly, as
+soon as you access them (for reading or writing) through the $output->formats
+attribute. We create a format called "info" and assign the color value "blue"
+to it. This will make all text printed with the format "info" occur in blue.
+
+Finally we print some text using this format on line 9. 
+
+As easy as this was, we can define more formats and assign more attributes to
+them, as the next example shows:
+
+.. include:: examples/tutorial_example_02.php
+   :literal:
+
+As seen before, we start with the simple "info" format. After that, we create
+a format named "error". This format does have style attribute set, which makes
+it appear bold. As you can see, style attributes are set using an array,
+because you can assign multiple style options to a format. The last format in
+this example is even more extensive: "fatal" will be printed with red
+foreground color, it will appear bold and have an underlining, additionally 
+its background will be black.
+
+After defining the formats, we print some text with them. In lines 16-18 you
+can see, that the ezcConsoleOutput::outputText() method does not add a line
+break after the text. This allows you to display differently styled text in 1
+line. You can also print manual line breaks with outputText() as shown in line
+19. This is not recommended, since it may extend your formatting to the next
+line, which will look strange for background colors.
+
+A nice convenience method is ezcConsoleOutput::outputLine(), which
+automatically adds a line break after your text, which is feasible for the
+system your program runs on. Last we print some standard text in line 23,
+which uses the default format of the console (by simply leaving out the format
+parameter).
+
+Two things are left to show for ezcConsoleOutput:
+
+.. include:: examples/tutorial_example_03.php
+   :literal:
+
+Again we define a format for later use. After that, we now set some options
+for ezcConsoleOutput, what is new in this example. The "autobreak" option
+makes ezcConsoleOutput wrap your printed text automatically after a certain
+number of characters (78 in this case). The "verbosityLevel" option defines,
+what text will be printed or not.
+
+Let's first see how "autobreak" works. In line 17 you see a very long text
+submitted to ezcConsoleOutput::outputLine() method. Since in most cases, the
+console of the user running your program will not be that long, your text will
+probably be wrapped by the console automatically. The issue here is, that the
+console will not take any kind of respect regarding your word boundaries. So
+it's most likely to happen, that your text will be wrapped in the middle of a
+word. Using "autobreak" prevents this issue, because then ezcConsoleOutput
+will take care of wrapping your texts  nicely for you. After printed some 
+auto-wrapped text, we print an explicit newline in the example.
+
+On lines 23 and 25 you see 2 examples for the optional "verbosityLevel"
+parameter, which both output*() options can take optionally. We remember, that
+we set the "verbosityLevel" option earlier in our options. In this place we 
+submit the level of verbosity, to indicate when a text will be displayed to 
the 
+user or not. The first text will not be displayed, if the verbosity is set to 
a 
+level below 10. We chose 3, so this will not be printed out. But the text 
+printed on line 22 will be visible, since 2 is smaller then the currently
+defined "verbosityLevel".
+
+Mastering options and arguments
+-------------------------------
+
+After we saw how to print information to the user, we will take a look at how 
+we can request it from him. This can be done using the class ezcConsoleInput.
+Let's start again by looking at an example.
+
+.. include:: examples/tutorial_example_04.php
+   :literal:
+   
+First we create a simple instance of ezcConsoleInput. After that (line 7), we
+register our first option. Registering an option means, that this option will
+be available for the user to submit, when he runs our program from the
+console. An option itself is represented by an object of type
+ezcConsoleOption. What every option must have, is at least a "shortname" and a
+"longname" (the first 2 parameters for ezcConsoleOption::__construct()). Out 
first 
+registered option will therefore be available later using "-h" or "--help". The
+ezcConsoleInput::registerOption() method returns the registered object again,
+so we can store it for later access.
+
+After we successfully registered the option, we tell ezcConsoleInput to
+parse the options submitted by the user (line 16). Although we did not
+register any option so far, that could potentially make the call to
+ezcConsoleInput::process() throw an exception (we'll see when this may occur a
+little bit later in this article), we wrap it in a try block. Usually one
+would expect to catch all ezcConsoleInput exceptions here. We don't do that,
+since the a special exception type exists, that is thrown, whenever an issue
+with user supplied options occurs. That way, we leave exceptions which are 
+thrown because we maybe made a mistake while programming or of any other
+reason untouched.
+
+Finally, we check what the user has submitted to our program. If an option was
+submitted, it's value attribute is generally (we'll see in a few seconds, what
+generally means) set to bool true. If it was not submitted, it's value is 
false.
+As you see, all options are optional by default.
+
+This was a very basic example, so let's dig into some more advanced things, 
+ezcConsoleInput can do for you:
+
+.. include:: examples/tutorial_example_05.php
+   :literal:
+
+Again we register the -h/--help option as you've seen in the previous example.
+Next we register a second option which will be available as -i/--input to the
+user. For this option we provide a type attribute, that makes the option take
+a string value. This is the first case, where ezcConsoleInput::process() can
+throw an exception that derives from ezcConsoleOptionException (as mentioned
+earlier). This will happen, if the user provided -i or --input to our program, 
+without giving it a value (e.g. "--input=/some/path" or "-i /some/path").
+
+The third option we create (-o/--output, see line 22) has also the type
+string, but this time we set it after creating the option itself, by accessing
+the ezcConsoleOption::$type attribute. After that, we see an even more
+advanced feature of ezcConsoleInput: The ability to manage dependencies. A
+dependency is always an object of ezcConsoleOptionRule, because you can also
+define a rule for an option to be excluded, using almost the same syntax, and
+even depend on a certain value of an option. But this topic would go to far
+for this tutorial. So, basically we make the --input and --output option
+depend on each other.
+
+Now it's time to process the options again. In this example, the try-catch
+block really makes sense, since ezcConsoleInput::process() may possibly throw
+exceptions now. The first case has already been mentioned: If an option that
+has a different value type than ezcConsoleInput::TYPE_NONE (which is the
+default one) is submitted without a value, ezcConsoleInput::process() will 
throw
+an exception about this, that is derived from ezcConsoleOptionException. So
+basically, I lied a bit to you in the first example for option handling,
+because if -h/--help (which has the value type "none") is submitted with a
+value assigned, ezcConsoleInput::process() will also throw an exception, 
because it
+does not expect that. In this sense, we were right in the earlier example to
+have the try-catch block in place. Another case where
+ezcConsoleInput::process() will throw an exception is when one of these
+parameters is submitted, without the other one.
+
+Next we check the --help option again. If help is requested, we print out some
+help: First of all we will display the synopsis of our program.
+ezcConsoleInput will generate it for us, so we just need to print it out. The
+synopsis includes all possible options (by default, you can also change that) 
+and indicates if parameters may carry values, of which type they must be and 
+much more information. If you request help, the synopsis printed may for 
+example look like this: ::
+
+  $ ./examples/tutorial_example_05.php [-h] [-i <string> [-o <string>] ]  
[[--] <args>] 
+
+As you can see, all options we defined are available, the types of values are
+indicated and even the dependencies are reflected. Beside that, we have an
+indicator that one may also supply arguments to the program. More on that a
+little bit later in this example.
+
+After printing the synopsis we iterate through all of our options and print out
+their ezcConsoleOption::$shorthelp attribute. Huh? The "shorthelp" attribute? 
+But we did not assign anything like this? True, so the output will be "No help
+available." right now. We could (and should) have set this before to a
+sensible help text, explaining the means of the option in short. The
+counterpart to ezcConsoleOption::$shorthelp is ezcConsoleOption::$longhelp,
+which takes a longer description of the options meaning and stores it for you.
+
+Last but not least we print out information about the --input and --output
+options, if they were submitted. We only have to care to check if the 
+$outputOption (or the $inputOption, as you like) was set in this case, since 
+ezcConsoleInput already assures that both are present, if one of them is set. 
+In the same place we also print information about the arguments that were 
+passed to our application. We can access the arguments passed to the program 
by 
+calling ezcConsoleInput::getArguments(), which will return an array of all 
+submitted arguments.
+
+To make this more clear, here is an example call, including it's output: ::
+
+  $ ./examples/tutorial_example_05.php -i /var/www -o /tmp foo bar 
+
+For this input the program will print: ::
+
+  Input: /var/www, Output: /tmp
+  Arguments: foo, bar
+   
+As you can already see in these 2 simple examples, ezcConsoleInput provides
+you a powerful way to manage the options and arguments provided to a console
+based application. We only touched a few of the many possibilities offered.
+For further information, please refer to the API documentation of
+ezcConsoleInput_.
+
+.. _ezcConsoleInput: 
http://ez.no/doc/components/view/(file)/1.0rc1/ConsoleTools/ezcConsoleInput.html
+
+Progress should happen
+----------------------
+
+Next, let's take a look on indicating progress to the user, by providing a
+progressbar:
+
+.. include:: examples/tutorial_example_06.php
+   :literal:
+
+In the example we first create an output handler to print text on the console.
+This is necessary, because ezcConsoleProgressbar utilizes it to print the
+progressbar. The second parameter provided is the number to which the
+progressbar shall count to. This means, that we have to call 15 times the
+ezcConsoleProgressbar::advance() method (line 11) until the progressbar 
reaches 
+the 100% value. Note, that we are emulating some action here, by making the
+program sleep for a random time. In the real world you would have some time
+consuming action here.
+
+This is basically all you have to do, to create a basic progressbar, which 
will 
+look like this after we called advance() for a couple of times:
+
+.. image:: img/consoletools_tutorial_example_06.png
+
+The bar will constantly move forward, every time you call advance() and
+reach it's end (and the 100% value) when you call advance() for the 15th time.
+The bar itself will always stay on the same line on the users console and 
+will redraw itself on every call to ezcConsoleProgressbar::advance() 
+automatically. You can even output some text before starting the bar and this 
+will stay in front of the bar all the time.
+
+But usually one wants to customize a progressbar to fit ones own special
+needs. This can be done easily with ezcConsoleProgressbar, too. Take a look at
+the following advanced example:
+
+.. include:: examples/tutorial_example_07.php
+   :literal:
+
+This time, we define a format to be applied to the bar itself and call it
+"bar" (lines 7+8). Then we create an array of options for the 
+ezcConsoleProgressbar::__construct() constructor. The first 2 values define, 
+how the bar itself will look like. The "emptyChar" defines, which character 
+is used to fill the "not yet covered space" of the bar. The "barChar" value 
+indicates the character that is used to fill the bar up. 
+
+The "formatString" option is a little bit more complex. It contains the string
+into which the progressbar is rendered later. To make that a bit more clear,
+see here, how the progressbar will look like, when you render it: 
+
+.. image:: img/consoletools_tutorial_example_07.png
+
+As you can see, we have the fraction value displayed at the beginning this
+time, followed by the progressbar itself (which looks quite different to the
+last one we generated), followed by 2 values which indicate the progress in
+kilobyte so far. So, if you compare the output with the definition of the
+"formatString" you can easily see how we did that. The "formatString" value 
+is a simple string, that may contain any character (sure, you should avoid
+newlines) and beside of that, a number of place-holders where
+ezcConsoleProgressbar will fill in the specific values. "%fraction%" is the
+place-holder for the fraction value, "%bar%" indicates, in which place the bar
+itself will be rendered.
+
+The example code also shows you another method of ezcConsoleOutput, which we
+did not see, yet: ezcConsoleOutput::formatText(). This method can be used to
+apply a format to a string without printing it directly. As you can see in the
+example result, this makes the bar itself appear in blue (as defined for the
+"bar" format). 
+
+The last option, "redrawFrequency", indicates, that ezcConsoleProgressbar
+should not redraw the progressbar on every call to
+ezcConsoleProgressbar::advance(), but only every 50th time. When your maximum
+value is very high and you indicate steps frequently (as you may already have
+guessed, the example emulates uploading a 1MB file kilobyte-wise, so we have
+1024 calls to ezcConsoleProgressbar::advance()), this makes a lot of sense.
+Else the bar would be updated so frequently, that it would jitter and
+the values displayed would definitely not be readable any more.
+
+So, let's take a short look at the little brother of ezcConsoleProgressbar, the
+ezcConsoleStatusbar:
+
+.. include:: examples/tutorial_example_08.php
+   :literal:
+
+As usual, we define some output formats, this time one called "success" and the
+other one called "failure". These formats are then used in the $options
+array we define for our ezcConsoleStatusbar. This simple class takes only 2
+possible options: "successChar" will be used to indicate a successful action
+and "failureChar" will be used to indicate a failed action.
+
+Then we instantiate the statusbar object (line 15) using our
+ezcConsoleOutput object and the options. Again we emulate some action by using
+a for-loop and some random sleeping (line 21) time and this time we also 
emulate 
+random success and failure values (line 19). Adding success and failure values 
to 
+the statusbar is easy: We just call the ezcConsoleStatusbar::add() method and
+submit either true (indicating success) or false to it (line 20).
+
+Finally we get the number of successes and failures from the statusbar by
+calling ezcConsoleStatusbar::getSuccessCount() and
+ezcConsoleStatusbar::getFailureCount() to display them to the user. Take a
+look at the result here:
+
+.. image:: img/consoletools_tutorial_example_08.png
+
+If you want to know more about indicating progress to the user from your shell
+application, take a look at the API documentation of ezcConsoleProgressbar_ and
+ezcConsoleStatusbar_.
+
+.. _ezcConsoleProgressbar: 
http://ez.no/doc/components/view/(file)/1.0rc1/ConsoleTools/ezcConsoleProgressbar.html
+.. _ezcConsoleStatusbar: 
http://ez.no/doc/components/view/(file)/1.0rc1/ConsoleTools/ezcConsoleStatusbar.html
+
+Large data served on a table
+----------------------------
+
+Actually it should have been "in a table", but who cares in a methaphor?
+Anyway: Whenever you want to display a larger amount of structured data, a
+table layout is what you need. While this can easily be achieved in HTML, it's
+pretty hard to create a table on the console. Therefore, the ConsoleTools
+package also has a class to generate tables: ezcConsoleTable. Before we look
+at some example code, let me first show you, how the table will look like,
+that we want to create:
+
+.. image:: img/consoletools_tutorial_example_09.png
+
+As you can see, a table with a nice headline is created. Now, guess how much
+code you need for just generating such a table? No idea? So, here we go:
+
+.. include:: examples/tutorial_example_09.php
+   :literal:
+
+Also this example looks quite long, you will see that it is not the generation
+of the table itself, which makes it that long. From line 5 to 12 we define an
+array of data we want to display in the table. As you can see, the array
+already reflects the later table structure here, which might in the real world
+not be the case. After that, we define the formats we want to use in the table
+(lines 14-20). You already know how that works pretty well by now.
+
+After that the real table creation starts. We instantiate a new ezcConsoleTable
+object in line 22, providing the maximal width, the table may have on the
+console. After that, we define the default format for table borders. These
+will later appear gray on the console. So far, the code should be nothing
+special.
+
+So, let's see what's next. The lines 26-28 might look confusing to you in the
+first place. The $table variable contains an object of type ezcConsoleTable,
+so why do we access it like an array here? The answer is simple and lies in a
+new interfaces, provided by the PHP extension SPL_, which is called
+ArrayAccess_. This allows you to provide array like access to your object, by
+implementing the necessary methods. So, when accessing $table[0] (for the
+first time), you automatically create an instance of ezcConsoleTableRow in 
your 
+table.
+
+.. _SPL:         http://php.net/spl
+.. _ArrayAccess: 
http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html
+
+Knowing this, we see, that in line 26 the first table row is created and it's
+"borderFormat" property is set to our "headBorder". On lines 27 and 28 we
+access this table row again, while it already exists there. With setting the
+"format" property of a row, we define which format will be applied to the
+content of the cells contained in that row (we'll see more in a bit).
+Actually, this is just the default format for those cells and might be
+overwritten in the cell object itself. The same applies to the alignment
+value, we set on line 28 for the first row in our table. Alignment values may
+indicate left, right and center directed alignments.
+
+So, we formated our head row accordingly and can start with adding data to our
+table. The 2 nested foreach loops iterate through our array (imagine this are
+database results in a result object). On line 34 we actually set the content
+of our cells. As you can see, the ezcConsoleTableCell objects contained in a
+row are also accessible using the ArrayAccess_ interface. So we are creating
+a cell for every element of our nested array. The data contained in a cell is
+stored in its "content" property.
+
+So, we are at the end, yet. On line 38 we print out some additional data and
+line 39 prints our table to the console. A finishing newline ends our example.
+That was quite easy, wasn't it?
+
+Let's see, if we can also produce something funny with ezcConsoleTable:
+
+.. include:: examples/tutorial_example_10.php
+   :literal:
+
+As you already might have guessed, the code does not really make much sense in
+general, but it shows some more of the handling of console based tables and
+the result looks quite funny. So, let's dig into it.
+
+We again define some formats, namely "blue", "red" and "green" to have a
+rainbow-like color mixture. Then we define 2 arrays, 1 containing all the
+names of the formats we recently defined, the other one containing all
+possible alignment values, offered by ezcConsoleTable. Then we create our
+table object again, with the same width as the previous one.
+
+So far nothing new. In the lines 19-22 we see some more options of
+ezcConsoleTable. The "corner", "lineVertical" and "lineHorizontal" values
+specify, which characters are used to render the table borders. As you have
+seen, the default for the "corner" character is '+', the "lineHorizontal" is
+represented by '|' and the vertical lines are rendered using '-'. In our
+example we replace each of these with a simple space. The last option we set
+is "widthType". This indicates, how ezcConsoleTable should deal with the width
+value we provided to its constructor. The default value here would be
+ezcConsoleTable::WIDTH_MAX, which allows ezcConsoleTable to render a table
+with a smaller width, if the content fits into it. In this example we disallow
+this and tell ezcConsoleTable to always make the table 78 character wide.
+
+Next we fill our table with content. This time we use 2 nested for loops
+which generate us a 10x10 table. For the content we always use a '*'. The
+format and align values (this time we don't set those on the row, but on the
+cell, so it is individual for each cell) are set randomly, so we will get a
+very colorful picture from it. Let's take a look at this:
+
+.. image:: img/consoletools_tutorial_example_10.png
+
+Funny and senseless, but I hope you got to know the concept behind
+ezcConsoleTable a bit better.
+
+Conclusion
+==========
+
+The ConsoleTools component offers you a variety of powerful tools to create
+shell based applications more comfortable and efficiently. Having this tools 
+playing together you are able to create shell scripts and even complex 
+applications for the console very fast and comfortably. I hope you got a 
detailed 
+introduction into this component here. If you have any feedback you want to 
+provide, if you have ideas for new features or how to improve ConsoleTools or 
if 
+you want to throw critics at it, please don't hesitate to start a discussion 
+in our Forum_.
+
+.. _Forum: http://ez.no/community/forum/ez_components
+
+
+..
+   Local Variables:
+   mode: rst
+   fill-column: 79
+   End: 
+   vim: et syn=rst tw=79


Property changes on: docs/articles/ConsoleTools/introduction/introduction.txt
___________________________________________________________________
Name: svn:eol-style
   + native

-- 
svn-components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to