Utils/Termlib: Add width() member to AbstractTerminal
g0dil [Wed, 3 Jun 2009 22:20:28 +0000 (22:20 +0000)]
Utils/Console: Add 'lr' command

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

19 files changed:
Utils/Console/Executor.cc
Utils/Console/Executor.hh
Utils/Console/Executor.test.cc
Utils/Console/LineEditor.cc
Utils/Console/LineEditor.hh
Utils/Console/Parse.cc
Utils/Console/Parse.hh
Utils/Console/Parse.ih
Utils/Console/Parse.test.cc
Utils/Console/ParsedCommand.test.cc
Utils/Console/Server.cc
Utils/Console/Server.cci
Utils/Console/Server.hh
Utils/Console/Server.ih
Utils/Termlib/AbstractTerminal.hh
Utils/Termlib/Editor.cc
Utils/Termlib/Editor.hh
Utils/Termlib/TelnetTerminal.cc
Utils/Termlib/TelnetTerminal.hh

index e3f0921..10d45df 100644 (file)
@@ -35,6 +35,7 @@
 #include "../../Utils/Range.hh"
 #include "../../Utils/String.hh"
 #include "../../Utils/range.hh"
+#include "Server.hh"
 
 //#include "Executor.mpp"
 #define prefix_
@@ -112,6 +113,13 @@ prefix_ void senf::console::Executor::execute(std::ostream & output,
             ls( output, command.commandPath() );
             break;
 
+        case ParseCommandInfo::BuiltinLR :
+            if (skipping())
+                break;
+            // The parser ensures, we have either one or no argument
+            lr( output, command.commandPath() );
+            break;
+
         case ParseCommandInfo::BuiltinPUSHD :
             // The parser ensures, we have exactly one argument
             if (skipping())
@@ -218,12 +226,21 @@ 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;
     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  %|20t|%.59s\n");
+    boost::format fmt ("%s%s  %|28t|%s\n");
     for (; i != i_end; ++i)
         output << fmt
             % i->first
@@ -232,7 +249,66 @@ prefix_ void senf::console::Executor::ls(std::ostream & output,
                 : i->second->isLink()
                 ? "@"
                 : "" )
-            % i->second->shorthelp();
+            % i->second->shorthelp().substr(0,width);
+}
+
+namespace {
+
+    typedef std::map<senf::console::DirectoryNode*,std::string> NodesMap;
+
+    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");
+        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()) {
+                    std::string subbase (base);
+                    if (! subbase.empty())
+                        subbase += "/";
+                    subbase += i->first;
+                    nodes.insert(std::make_pair(&subnode, subbase));
+                    dolr(output, width, nodes, subbase, level+1, subnode);
+                } else
+                    output << pad << "  -> " << j->second << "\n";
+            }
+        }
+    }
+
+}
+
+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);
 }
 
 prefix_ void senf::console::Executor::pushd(ParseCommandInfo::TokensRange dir)
index 9341ded..2fc9c06 100644 (file)
@@ -138,6 +138,7 @@ namespace console {
 
         void cd(ParseCommandInfo::TokensRange dir);
         void ls(std::ostream & output, ParseCommandInfo::TokensRange dir);
+        void lr(std::ostream & output, ParseCommandInfo::TokensRange dir);
         void pushd(ParseCommandInfo::TokensRange dir);
         void popd();
         void exit();
index f02943b..d4df850 100644 (file)
@@ -100,9 +100,9 @@ BOOST_AUTO_UNIT_TEST(executor)
         executor(os, commands.back());
         BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS );
         BOOST_CHECK_EQUAL( os.str(), 
-                           "dir1/               \n"
-                           "dir2/               Helptext\n"
-                           "sys/                \n" );
+                           "dir1/                       \n"
+                           "dir2/                       Helptext\n"
+                           "sys/                        \n" );
     }
 
     {
@@ -110,7 +110,7 @@ BOOST_AUTO_UNIT_TEST(executor)
         parser.parse("ls dir1", &setCommand);
         executor(os, commands.back());
         BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS );
-        BOOST_CHECK_EQUAL( os.str(), "dir3/               \n" );
+        BOOST_CHECK_EQUAL( os.str(), "dir3/                       \n" );
     }
 
     {
@@ -123,6 +123,19 @@ BOOST_AUTO_UNIT_TEST(executor)
     
     {
         std::stringstream os;
+        parser.parse("lr", &setCommand);
+        executor(os, commands.back());
+        BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLR );
+        BOOST_CHECK_EQUAL( os.str().substr(0,213),
+                           "dir1/                                   \n"
+                           "  dir3/                                 \n"
+                           "dir2/                                   Helptext\n"
+                           "  test                                  \n"
+                           "sys/                                    \n" );
+    }
+
+    {
+        std::stringstream os;
         parser.parse("dir1/dir3 { }", &setCommand);
         executor(os, commands.rbegin()[1]);
         BOOST_CHECK_EQUAL( commands.rbegin()[1].builtin(), senf::console::ParseCommandInfo::BuiltinPUSHD );
@@ -216,7 +229,7 @@ BOOST_AUTO_UNIT_TEST(executorPolicy)
         parser.parse("ls dir1", &setCommand);
         executor(os, commands.back());
         BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS );
-        BOOST_CHECK_EQUAL( os.str(), "dir3/               \n" );
+        BOOST_CHECK_EQUAL( os.str(), "dir3/                       \n" );
     }
 
     {
index 31df1f7..df9d065 100644 (file)
@@ -65,6 +65,12 @@ prefix_ void senf::console::detail::LineEditorSwitcher::v_write(std::string cons
     reader_->write(data);
 }
 
+prefix_ unsigned senf::console::detail::LineEditorSwitcher::v_width()
+    const
+{
+    return reader_->width();
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::detail::LineEditorClientReader
 
@@ -109,6 +115,12 @@ prefix_ void senf::console::detail::LineEditorClientReader::v_write(std::string
     BaseTelnetProtocol::write(data);
 }
 
+prefix_ unsigned senf::console::detail::LineEditorClientReader::v_width()
+    const
+{
+    return editor_.width();
+}
+
 prefix_ void
 senf::console::detail::LineEditorClientReader::executeLine(std::string const & text)
 {
index 2a94a7e..6fe3ea3 100644 (file)
@@ -60,6 +60,7 @@ namespace detail {
         virtual void v_disablePrompt();
         virtual void v_enablePrompt();
         virtual void v_write(std::string const & data);
+        virtual unsigned v_width() const;
 
         boost::scoped_ptr<ClientReader> reader_;
     };
@@ -83,6 +84,7 @@ namespace detail {
         virtual void v_disablePrompt();
         virtual void v_enablePrompt();
         virtual void v_write(std::string const & data);
+        virtual unsigned v_width() const;
 
         // Editor callbacks
         void executeLine(std::string const & text);
index 28fa61a..5281be5 100644 (file)
@@ -76,6 +76,11 @@ namespace detail {
               info_->builtin(ParseCommandInfo::BuiltinLS);
               setBuiltinPathArg(path); }
 
+        void builtin_lr(std::vector<Token> & path)
+            { info_->clear();
+              info_->builtin(ParseCommandInfo::BuiltinLR);
+              setBuiltinPathArg(path); }
+
         void pushDirectory()
             { // Do NOT call clear since pushDirectory is set in ADDITION
               // to an ordinary command (which may be only a directory name)
@@ -169,7 +174,7 @@ prefix_ std::ostream & senf::console::operator<<(std::ostream & stream,
         }
     }
     else {
-        char const * builtins[] = { 0, "cd", "ls", "pushd", "popd", "exit", "help" };
+        char const * builtins[] = { 0, "cd", "ls", "lr", "pushd", "popd", "exit", "help" };
         stream << "builtin-" << builtins[info.builtin()];
     }
         
index 4303fc2..e7712e0 100644 (file)
@@ -366,6 +366,7 @@ namespace console {
         enum BuiltinCommand { NoBuiltin, 
                               BuiltinCD, 
                               BuiltinLS, 
+                              BuiltinLR,
                               BuiltinPUSHD, 
                               BuiltinPOPD,
                               BuiltinEXIT,
index d99e168..00745cc 100644 (file)
@@ -220,6 +220,9 @@ namespace detail {
                     |    self.keyword_p("ls")
                       >> ! path
                       >> eps_p                    [ bind(&PD::builtin_ls)(d_, path_) ]
+                    |    self.keyword_p("lr")
+                      >> ! path
+                      >> eps_p                    [ bind(&PD::builtin_lr)(d_, path_) ]
                     |    self.keyword_p("exit")   [ bind(&PD::builtin_exit)(d_) ]
                     |    self.keyword_p("help")
                       >> ! path
index 5d625e3..bbc2c68 100644 (file)
@@ -66,6 +66,8 @@ namespace
             { os_ << "builtin_cd( " << senf::stringJoin(path, "/") << " )\n"; }
         void builtin_ls(std::vector<senf::console::Token> const & path)
             { os_ << "builtin_ls( " << senf::stringJoin(path, "/") << " )\n"; }
+        void builtin_lr(std::vector<senf::console::Token> const & path)
+            { os_ << "builtin_lr( " << senf::stringJoin(path, "/") << " )\n"; }
         void builtin_exit()
             { os_ << "builtin_exit()\n"; }
         void builtin_help(std::vector<senf::console::Token> const & path)
@@ -133,6 +135,15 @@ BOOST_AUTO_UNIT_TEST(commandGrammar)
     {
         ss.str("");
         BOOST_CHECK( boost::spirit::parse( 
+                         "lr /foo/bar;", 
+                         grammar.use_parser<Grammar::CommandParser>(), 
+                         grammar.use_parser<Grammar::SkipParser>() ) . full );
+        BOOST_CHECK_EQUAL( ss.str(), "builtin_lr( None('')/Word('foo')/Word('bar') )\n" );
+    }
+
+    {
+        ss.str("");
+        BOOST_CHECK( boost::spirit::parse( 
                          "cd /foo/bar;", 
                          grammar.use_parser<Grammar::CommandParser>(), 
                          grammar.use_parser<Grammar::SkipParser>() ) . full );
index 5953658..b9c095a 100644 (file)
@@ -303,7 +303,9 @@ BOOST_AUTO_UNIT_TEST(directoryReturn)
         SENF_CHECK_NO_THROW(
             parser.parse("test/test { ls; }",
                          boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
-        BOOST_CHECK_EQUAL( ss.str(), "<Directory at '/test/dircb'>\ncb1                 \n" );
+        BOOST_CHECK_EQUAL( ss.str(), 
+                           "<Directory at '/test/dircb'>\n"
+                           "cb1                         \n" );
     }
     
 }
index 41475c2..afcf922 100644 (file)
@@ -180,6 +180,12 @@ prefix_ void senf::console::detail::DumbClientReader::v_write(std::string const
     handle().write(data);
 }
 
+prefix_ unsigned senf::console::detail::DumbClientReader::v_width()
+    const
+{
+    return 80;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::detail::NoninteractiveClientReader
 
@@ -202,6 +208,12 @@ prefix_ void senf::console::detail::NoninteractiveClientReader::v_write(std::str
     handle().write(data);
 }
 
+prefix_ unsigned senf::console::detail::NoninteractiveClientReader::v_width()
+    const
+{
+    return 80;
+}
+
 prefix_ void
 senf::console::detail::NoninteractiveClientReader::newData(int event)
 {
index 62e6fad..488fb3a 100644 (file)
@@ -163,6 +163,12 @@ prefix_ std::string const & senf::console::Client::backtrace()
     return backtrace_;
 }
 
+prefix_ unsigned senf::console::Client::width()
+    const
+{
+    return reader_->width();
+}
+
 prefix_ senf::console::Client & senf::console::Client::get(std::ostream & os)
 {
     return dynamic_cast<detail::NonblockingSocketOStream&>(os)->client();
@@ -236,6 +242,12 @@ prefix_ void senf::console::detail::ClientReader::write(std::string const & data
     v_write(data);
 }
 
+prefix_ unsigned senf::console::detail::ClientReader::width()
+    const
+{
+    return v_width();
+}
+
 prefix_ senf::console::detail::ClientReader::ClientReader(Client & client)
     : client_ (client)
 {}
index 7d0a10d..4c5e66f 100644 (file)
@@ -177,6 +177,7 @@ namespace console {
         Server::Mode mode() const;
         void write(std::string const & data) const;
         std::string const & backtrace() const;
+        unsigned width() const;
 
         static Client & get(std::ostream & os);
 
index d97c1c9..aa77d74 100644 (file)
@@ -114,6 +114,7 @@ namespace detail {
         void disablePrompt();
         void enablePrompt();
         void write(std::string const & data);
+        unsigned width() const;
 
     protected:
         ClientReader(Client & client);
@@ -122,6 +123,7 @@ namespace detail {
         virtual void v_disablePrompt() = 0;
         virtual void v_enablePrompt() = 0;
         virtual void v_write(std::string const & data) = 0;
+        virtual unsigned v_width() const = 0;
 
         Client & client_;
     };
@@ -141,6 +143,7 @@ namespace detail {
         virtual void v_disablePrompt();
         virtual void v_enablePrompt();
         virtual void v_write(std::string const & data);
+        virtual unsigned v_width() const;
 
         void clientData(senf::ReadHelper<ClientHandle>::ptr helper);
         void showPrompt();
@@ -165,6 +168,7 @@ namespace detail {
         virtual void v_disablePrompt();
         virtual void v_enablePrompt();
         virtual void v_write(std::string const & data);
+        virtual unsigned v_width() const;
 
         void newData(int event);
 
index b3f396d..95408f6 100644 (file)
@@ -69,8 +69,8 @@ namespace term {
         virtual void setCallbacks(Callbacks & cb) = 0; ///< Register terminal callbacks
 
         virtual std::string terminalType() = 0; ///< Get the terminal type
-        virtual unsigned width() = 0;   ///< Get current terminal window width
-        virtual unsigned height() = 0;  ///< Get current terminal window height
+        virtual unsigned width() const = 0;   ///< Get current terminal window width
+        virtual unsigned height() const = 0;  ///< Get current terminal window height
 
         virtual void write(char ch) = 0; ///< Write character to terminal
     };
index ce6a3fb..0122904 100644 (file)
@@ -253,11 +253,13 @@ prefix_ void senf::term::BaseEditor::processKeys()
 }
 
 prefix_ unsigned senf::term::BaseEditor::width()
+    const
 {
     return terminal_->width();
 }
 
 prefix_ unsigned senf::term::BaseEditor::height()
+    const
 {
     return terminal_->height();
 }
index bacfeff..952291f 100644 (file)
@@ -81,8 +81,8 @@ namespace term {
 
         unsigned currentColumn() const; ///< Return number of current column
         unsigned currentLine() const;   ///< Return number of current relative line
-        unsigned width();               ///< Return current screen width
-        unsigned height();              ///< Return current screen height
+        unsigned width() const;         ///< Return current screen width
+        unsigned height() const;        ///< Return current screen height
 
     protected:
         virtual bool cb_init();         ///< Called when terminal is initialized
index 3445d5c..758a360 100644 (file)
@@ -51,11 +51,13 @@ prefix_ std::string senf::term::TelnetTerminal::terminalType()
 }
 
 prefix_ unsigned senf::term::TelnetTerminal::width()
+    const
 {
     return telnethandler::NAWS::width();
 }
 
 prefix_ unsigned senf::term::TelnetTerminal::height()
+    const
 {
     return telnethandler::NAWS::height();
 }
index 650ce1f..09aea80 100644 (file)
@@ -62,8 +62,8 @@ namespace term {
         ///\{
         virtual void setCallbacks(AbstractTerminal::Callbacks & cb);
         virtual std::string terminalType();
-        virtual unsigned width();
-        virtual unsigned height();
+        virtual unsigned width() const;
+        virtual unsigned height() const;
         virtual void write(char ch);
         ///\}