<?xml version="1.0" encoding="UTF-8"?>

<!-- ====================================================================== -->
<!-- = chapter-2.xml                                                      = -->
<!-- = standard i/o module guide - chapter 2                              = -->
<!-- ====================================================================== -->
<!-- = This  program  is  free  software; you  can redistribute it and/or = -->
<!-- = modify it provided that this copyright notice is kept intact.      = -->
<!-- = This program is distributed in the hope that it will be useful but = -->
<!-- = without  any  warranty;  without  even  the  implied  warranty  of = -->
<!-- = merchantability or fitness for  a  particular purpose. In no event = -->
<!-- = shall  the  copyright  holder be liable for any  direct, indirect, = -->
<!-- = incidental  or special  damages arising  in any way out of the use = -->
<!-- = of this software.                                                  = -->
<!-- ====================================================================== -->
<!-- = copyright (c) 2005-2007 - amaury darsch                            = -->
<!-- ====================================================================== -->

<chapter module="sio" number="2">
  <title>Special i/o objects</title>

  <p>
  This chapter is dedicated to special facilities which are part of
  the standard i/o module.
  </p>

  <!-- directory -->
  <section>
    <title>Directory</title>

    <p>
    The <code>Directory</code> class provides a facility to manipulate
    directories. A directory  object is created either by name or
    without argument by considering the current working
    directory. Once the directory object is created, it is possible to
    retrieve its contents, create new directory or remove empty one. 
    </p>

    <!-- reading a directory -->
    <subsect>
      <title>Reading a directory</title>

      <p>
      A <code>Directory</code> object is created either by name or
      without argument. With no argument, the current directory is
      opened. When the current directory is opened, its full name is
      computed internally and can be retrieved with the
      <code>get-name</code> method. 
      </p>

      <example>
      # print the current directory
      const pwd (afnix:sio:Directory)
      println   (pwd:get-name)
      </example>

      <p>
      Once the directory object is opened, it is possible to list its
      contents. The <code>get-list</code> method returns the full
      contents of the directory object. The <code>get-files</code>
      method returns a list of files in this directory. The
      <code>get-subdirs</code> method returns a list of sub
      directories in this directory.
      </p>

      <example>
      # print a list of files
      const pwd (afnix:sio:Directory)
      const lsf (d:get-files)
      for (name) (lsf) (println name)
      </example>
    </subsect>

    <!-- creating and removing directories -->
    <subsect>
      <title>Creating and removing directories</title>

      <p>
      The <code>mkdir</code> and <code>rmdir</code> methods can be
      used to create or remove a directory. Both methods take a string
      argument and construct a full path name from the directory name
      and the argument. This approach has the advantage of being file
      system independent. If the directory already exists, the
      <code>mkdir</code> methods succeeds. The <code>rmdir</code>
      method requires the directory to be empty.
      </p>

      <example>
      const tmp (afnix:sio:Directory (afnix:sio:absolute-path "tmp"))
      const exp (tmp:mkdir "examples")
      const lsf (exp:get-files)
      println   (lsf:length)
      tmp:rmdir "examples"
      </example>

      <p>
      The function <code>absolute-path</code> constructs an absolute
      path name from the argument list. If relative path needs to be
      constructed, the function <code>relative-path</code> might be
      used instead.
      </p>
    </subsect>
  </section>

  <!-- logtee -->
  <section>
    <title>Logtee</title>

    <p>
    The <code>Logtee</code> class is a message logger facility
    associated with an output stream. When a message is added to the
    logger object, the message is also sent to the output stream,
    depending on the controlling flags. The name "logtee" comes from
    the contraction of "logger" and "tee". One particularity of the
    class is that without a stream, the class behaves like a regular
    logger.
    </p>

    <!-- creating a logger -->
    <subsect>
      <title>Creating a logger</title>

      <p>
      The <code>Logtee</code> default constructor creates a standard
      logger object without an output stream. The instance can also be
      created by size or with an output stream or both. A third method
      can also attach an information string.
      </p>

      <example>
      # create a logger with the interpreter stream
      const log (Logtee (interp:get-output-stream))
      assert true (logger-p log)
      </example>
    </subsect>

    <!-- adding messages -->
    <subsect>
      <title>Adding messages</title>

      <p>
      The process of adding messages is similar to the regular
      logger. The only difference is that the message is placed on the
      output stream if a control flag is set and the message level is
      less or equal the report level. In the other word, the control
      flag controls the message display -- the tee operation -- while
      the report level filters some of the messages.
      </p>

      <example>
      log:add 2 "a level 2 message"
      </example>

      <p>
      The <code>set-tee</code> method sets the control
      flag. The <code>set-report-level</code> method sets the report
      level. Note that the <code>set-report-level</code> and its
      associated <code>get-report-level</code> method is part of the
      base <code>Logger</code> class.
      </p>
    </subsect>
  </section>
</chapter>
