Utils/Console: Move link target in lr output one line up
g0dil [Tue, 16 Jun 2009 11:29:12 +0000 (11:29 +0000)]
Utils/Console: Add documentation to Client members
Utils/Console: Add support for std::pair parsing/formatting
Utils/Console: Some more documentation

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1233 270642c3-0616-0410-b53a-bc976706d245

Utils/Console/Executor.cc
Utils/Console/Node.hh
Utils/Console/STLSupport.ct
Utils/Console/STLSupport.hh
Utils/Console/Server.cc
Utils/Console/Server.hh

index 141565a..692af69 100644 (file)
@@ -31,6 +31,7 @@
 #include <boost/range/iterator_range.hpp>
 #include <boost/bind.hpp>
 #include <boost/format.hpp>
+#include <boost/preprocessor/stringize.hpp>
 #include "../../Utils/senfassert.hh"
 #include "../../Utils/Range.hh"
 #include "../../Utils/String.hh"
@@ -232,21 +233,15 @@ prefix_ void senf::console::Executor::cd(ParseCommandInfo::TokensRange dir)
 prefix_ void senf::console::Executor::ls(std::ostream & output,
                                          ParseCommandInfo::TokensRange path)
 {
-    unsigned width (80);
-    try {
-        width = senf::console::Client::get(output).width();
-    }
-    catch (std::bad_cast &)
-    {}
-    if (width<60)
-        width = 80;
-    width -= 28+1;
+#   define HELP_COLUMN 28
+
+    unsigned width (senf::console::Client::getWidth(output, 80u, 60u)-(HELP_COLUMN+1));
     Path dir (cwd_);
     traverseDirectory(path, dir);
     DirectoryNode & node (*dir.back().lock());
     DirectoryNode::child_iterator i (node.children().begin());
     DirectoryNode::child_iterator const i_end (node.children().end());
-    boost::format fmt ("%s%s  %|28t|%s\n");
+    boost::format fmt ("%s%s  %|" BOOST_PP_STRINGIZE(HELP_COLUMN) "t|%s\n");
     for (; i != i_end; ++i)
         output << fmt
             % i->first
@@ -256,8 +251,12 @@ prefix_ void senf::console::Executor::ls(std::ostream & output,
                 ? "@"
                 : "" )
             % i->second->shorthelp().substr(0,width);
+
+#   undef HELP_COLUMN
 }
 
+#   define HELP_COLUMN 40
+
 namespace {
 
     typedef std::map<senf::console::DirectoryNode*,std::string> NodesMap;
@@ -265,25 +264,20 @@ namespace {
     void dolr(std::ostream & output, unsigned width, NodesMap & nodes, std::string const & base, 
               unsigned level, senf::console::DirectoryNode & node)
     {
-        boost::format fmt ("%s%s%s  %|40t|%s\n");
+        boost::format fmt ("%s%s%s  %|" BOOST_PP_STRINGIZE(HELP_COLUMN) "t|%s\n");
         std::string pad (2*level, ' ');
         senf::console::DirectoryNode::child_iterator i (node.children().begin());
         senf::console::DirectoryNode::child_iterator const i_end (node.children().end());
         for (; i != i_end; ++i) {
-            output << fmt
-                % pad
-                % i->first
-                % ( i->second->isDirectory()
-                    ? "/"
-                    : i->second->isLink()
-                    ? "@"
-                    : "" )
-                % i->second->shorthelp().substr(0,width);
             if (i->second->followLink().isDirectory()) {
                 senf::console::DirectoryNode & subnode (
                     static_cast<senf::console::DirectoryNode&>(i->second->followLink()));
                 NodesMap::iterator j (nodes.find(&subnode));
                 if (j == nodes.end()) {
+                    output << fmt
+                        % pad % i->first 
+                        % ( i->second->isDirectory() ? "/" : i->second->isLink() ? "@" : "" )
+                        % i->second->shorthelp().substr(0,width);
                     std::string subbase (base);
                     if (! subbase.empty())
                         subbase += "/";
@@ -291,7 +285,14 @@ namespace {
                     nodes.insert(std::make_pair(&subnode, subbase));
                     dolr(output, width, nodes, subbase, level+1, subnode);
                 } else
-                    output << pad << "  -> " << j->second << "\n";
+                    output << pad << i->first 
+                           << ( i->second->isDirectory() ? "/" : i->second->isLink() ? "@" : "" )
+                           << " -> " << j->second << "\n";
+            } else {
+                output << fmt
+                    % pad % i->first 
+                    % ( i->second->isDirectory() ? "/" : i->second->isLink() ? "@" : "" )
+                    % i->second->shorthelp().substr(0,width);
             }
         }
     }
@@ -301,22 +302,16 @@ namespace {
 prefix_ void senf::console::Executor::lr(std::ostream & output,
                                          ParseCommandInfo::TokensRange path)
 {
-    unsigned width (80);
-    try {
-        width = senf::console::Client::get(output).width();
-    }
-    catch (std::bad_cast &)
-    {}
-    if (width<60)
-        width = 80;
-    width -= 40+1;
     Path dir (cwd_);
     traverseDirectory(path, dir);
     DirectoryNode & node (*dir.back().lock());
     NodesMap nodes;
-    dolr(output, width, nodes, "", 0, node);
+    dolr(output, senf::console::Client::getWidth(output, 80u, 60u)-(HELP_COLUMN+1), 
+         nodes, "", 0, node);
 }
 
+#undef HELP_COLUMN
+
 prefix_ void senf::console::Executor::pushd(ParseCommandInfo::TokensRange dir)
 {
     Path newDir (cwd_);
index 4cd15d1..b8702be 100644 (file)
@@ -223,7 +223,17 @@ namespace console {
     class DirectoryNode;
     class CommandNode;
 
+    /** \brief Get console root node */
     DirectoryNode & root();
+
+    /** \brief Dump console directory structure
+
+        Recursively dumps the console directory structure starting at \a dir. By default, dumps the
+        complete tree beginning at the root node.
+        
+        In contrast to the console 'lr' command, links are dumped by showing the \e absolute path
+        to the target node.
+     */
     void dump(std::ostream & os, DirectoryNode & dir=root());
 
     /** \brief Config/console node tree base-class
index ca7f599..18af3dc 100644 (file)
@@ -26,6 +26,7 @@
 //#include "VectorSupport.ih"
 
 // Custom includes
+#include <boost/format.hpp>
 
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
@@ -82,6 +83,42 @@ prefix_ void senf::console::SequenceReturnValueTraits<Sequence>::format(type con
     os << ")";
 }
 
+template <class T1, class T2>
+prefix_ void senf::console::ArgumentTraits< std::pair<T1,T2> >::
+parse(ParseCommandInfo::TokensRange const & tokens, type & out)
+{
+    CheckedArgumentIteratorWrapper arg (tokens);
+    senf::console::parse( *(arg++), out.first );
+    senf::console::parse( *(arg++), out.second );
+}
+
+template <class T1, class T2>
+prefix_ std::string senf::console::ArgumentTraits< std::pair<T1,T2> >::description()
+{
+    return (boost::format("pair<%s,%s>")
+            % ArgumentTraits<T1>::description()
+            % ArgumentTraits<T2>::description()).str();
+}
+
+template <class T1, class T2>
+prefix_ std::string senf::console::ArgumentTraits< std::pair<T1,T2> >::str(type const & value)
+{
+    std::stringstream ss;
+    senf::console::format(value, ss);
+    return ss.str();
+}
+
+template <class T1, class T2>
+prefix_ void senf::console::ReturnValueTraits< std::pair<T1,T2> >::format(type const & value,
+                                                                          std::ostream & os)
+{
+    os << "(";
+    senf::console::format(value.first, os);
+    os << " ";
+    senf::console::format(value.second, os);
+    os << ")";
+}
+
 #endif
 
 ///////////////////////////////ct.e////////////////////////////////////////
index 69a6e14..d459488 100644 (file)
@@ -78,6 +78,25 @@ namespace console {
         : public SequenceReturnValueTraits< std::list<T,Alloc> >
     {};
 
+    template <class T1, class T2>
+    struct ArgumentTraits< std::pair<T1,T2> >
+    {
+        typedef std::pair<T1,T2> type;
+        static bool const singleToken = false;
+
+        static void parse(ParseCommandInfo::TokensRange const & tokens, type & out);
+        static std::string description();
+        static std::string str(type const & value);
+    };
+
+    template <class T1, class T2>
+    struct ReturnValueTraits< std::pair<T1,T2> >
+    {
+        typedef std::pair<T1,T2> type;
+
+        static void format(type const & value, std::ostream & os);
+    };
+
 #endif
 
 }}
index 58a3dcc..913a271 100644 (file)
@@ -336,6 +336,17 @@ prefix_ void senf::console::Client::v_write(senf::log::time_type timestamp,
     reader_->enablePrompt();
 }
 
+prefix_ unsigned senf::console::Client::getWidth(std::ostream & os, unsigned defaultWidth,
+                                                 unsigned minWidth)
+{
+    unsigned rv (defaultWidth);
+    try { 
+        rv = get(os).width(); 
+    }
+    catch (std::bad_cast &) {}
+    return rv < minWidth ? defaultWidth : rv;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::Client::SysBacktrace
 
index 4c5e66f..9e9471a 100644 (file)
@@ -168,18 +168,51 @@ namespace console {
         void stop();                    ///< Stop the client
                                         /**< This will close the client socket. */
 
-        std::string const & name() const;
-        ClientHandle handle() const;
-        std::ostream & stream();
-        std::string promptString() const;
-        DirectoryNode & root() const;
-        DirectoryNode & cwd() const;
-        Server::Mode mode() const;
+        std::string const & name() const; ///< Get name of the client instance
+                                        /**< This name is used in the prompt string and is set by
+                                             the server. */
+        ClientHandle handle() const;    ///< Get the client's network socket handle
+        std::ostream & stream();        ///< Get client's output stream
+                                        /**< Data sent to this stream is sent out over the network
+                                             via the client's socket handle. Write operation is 
+                                             non-blocking and data may be dropped. Data is written
+                                             using Client::write(). */
+        std::string promptString() const; ///< Get the prompt string
+        DirectoryNode & root() const;   ///< Get configured root node
+        DirectoryNode & cwd() const;    ///< Get current directory
+                                        /**< This is the directory, the console currently is changed
+                                             into by the user of the console. */
+        Server::Mode mode() const;      ///< Get operation mode
+                                        /**< \see Server::mode() */
         void write(std::string const & data) const;
-        std::string const & backtrace() const;
-        unsigned width() const;
+                                        ///< Write data to network socket
+                                        /**< The data is automatically filtered depending on the
+                                             type of connection (e.g. on a telnet connection,
+                                             specific bytes are quoted). */
+        std::string const & backtrace() const; ///< Get backtrace of last console error, if any
+        unsigned width() const;         ///< Get console width
+                                        /**< If possible, this will be the width of the connected
+                                             terminal, otherwise a default value (normally 80) is
+                                             returned. */
 
         static Client & get(std::ostream & os);
+                                        ///< Access client instance
+                                        /**< Allows to access the client instance from console
+                                             command implementations. The first argument to a
+                                             console command is a stream object. \e If this stream
+                                             object belongs to a network console client, this call
+                                             will return the associated Client instance reference.
+                                             \throws std::bad_cast if \a os is not associated with a
+                                                 Client instance. */
+        static unsigned getWidth(std::ostream & os, unsigned defaultWidth = 0, 
+                                 unsigned minWidth = 0);
+                                        ///< Get width of client console if possible
+                                        /**< If possible, the width of the client console attached
+                                             to the stream \a os is returned. If this is not
+                                             possible, the \a defaultValue will be used.
+                                             
+                                             If the width obtained this way is smaller than \a
+                                             minWidth, \a defaultValue will be returned instead. */
 
     protected: