From ad40d40bcbe5dfa93daea1e1a5fcec26b579e0aa Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Wed, 3 Jun 2009 22:20:28 +0000 Subject: [PATCH] Utils/Termlib: Add width() member to AbstractTerminal Utils/Console: Add 'lr' command --- Utils/Console/Executor.cc | 80 ++++++++++++++++++++++++++++- Utils/Console/Executor.hh | 1 + Utils/Console/Executor.test.cc | 23 +++++++-- Utils/Console/LineEditor.cc | 12 +++++ Utils/Console/LineEditor.hh | 2 + Utils/Console/Parse.cc | 7 ++- Utils/Console/Parse.hh | 1 + Utils/Console/Parse.ih | 3 ++ Utils/Console/Parse.test.cc | 11 ++++ Utils/Console/ParsedCommand.test.cc | 4 +- Utils/Console/Server.cc | 12 +++++ Utils/Console/Server.cci | 12 +++++ Utils/Console/Server.hh | 1 + Utils/Console/Server.ih | 4 ++ Utils/Termlib/AbstractTerminal.hh | 4 +- Utils/Termlib/Editor.cc | 2 + Utils/Termlib/Editor.hh | 4 +- Utils/Termlib/TelnetTerminal.cc | 2 + Utils/Termlib/TelnetTerminal.hh | 4 +- 19 files changed, 174 insertions(+), 15 deletions(-) diff --git a/Utils/Console/Executor.cc b/Utils/Console/Executor.cc index e3f09216..10d45df3 100644 --- a/Utils/Console/Executor.cc +++ b/Utils/Console/Executor.cc @@ -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) diff --git a/Utils/Console/Executor.hh b/Utils/Console/Executor.hh index 9341dede..2fc9c06e 100644 --- a/Utils/Console/Executor.hh +++ b/Utils/Console/Executor.hh @@ -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(); diff --git a/Utils/Console/Executor.test.cc b/Utils/Console/Executor.test.cc index f02943bf..d4df850b 100644 --- a/Utils/Console/Executor.test.cc +++ b/Utils/Console/Executor.test.cc @@ -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" ); } { @@ -121,6 +121,19 @@ BOOST_AUTO_UNIT_TEST(executor) BOOST_CHECK_EQUAL( os.str(), "" ); } + { + 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); @@ -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" ); } { diff --git a/Utils/Console/LineEditor.cc b/Utils/Console/LineEditor.cc index 31df1f78..df9d0652 100644 --- a/Utils/Console/LineEditor.cc +++ b/Utils/Console/LineEditor.cc @@ -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) { diff --git a/Utils/Console/LineEditor.hh b/Utils/Console/LineEditor.hh index 2a94a7e6..6fe3ea33 100644 --- a/Utils/Console/LineEditor.hh +++ b/Utils/Console/LineEditor.hh @@ -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); diff --git a/Utils/Console/Parse.cc b/Utils/Console/Parse.cc index 28fa61a0..5281be5d 100644 --- a/Utils/Console/Parse.cc +++ b/Utils/Console/Parse.cc @@ -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()]; } diff --git a/Utils/Console/Parse.hh b/Utils/Console/Parse.hh index 4303fc2a..e7712e00 100644 --- a/Utils/Console/Parse.hh +++ b/Utils/Console/Parse.hh @@ -366,6 +366,7 @@ namespace console { enum BuiltinCommand { NoBuiltin, BuiltinCD, BuiltinLS, + BuiltinLR, BuiltinPUSHD, BuiltinPOPD, BuiltinEXIT, diff --git a/Utils/Console/Parse.ih b/Utils/Console/Parse.ih index d99e168f..00745cce 100644 --- a/Utils/Console/Parse.ih +++ b/Utils/Console/Parse.ih @@ -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 diff --git a/Utils/Console/Parse.test.cc b/Utils/Console/Parse.test.cc index 5d625e33..bbc2c686 100644 --- a/Utils/Console/Parse.test.cc +++ b/Utils/Console/Parse.test.cc @@ -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) @@ -130,6 +132,15 @@ BOOST_AUTO_UNIT_TEST(commandGrammar) BOOST_CHECK_EQUAL( ss.str(), "builtin_ls( None('')/Word('foo')/Word('bar') )\n" ); } + { + 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( diff --git a/Utils/Console/ParsedCommand.test.cc b/Utils/Console/ParsedCommand.test.cc index 59536584..b9c095a7 100644 --- a/Utils/Console/ParsedCommand.test.cc +++ b/Utils/Console/ParsedCommand.test.cc @@ -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" ); } } diff --git a/Utils/Console/Server.cc b/Utils/Console/Server.cc index 41475c29..afcf9228 100644 --- a/Utils/Console/Server.cc +++ b/Utils/Console/Server.cc @@ -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) { diff --git a/Utils/Console/Server.cci b/Utils/Console/Server.cci index 62e6fade..488fb3a7 100644 --- a/Utils/Console/Server.cci +++ b/Utils/Console/Server.cci @@ -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) {} diff --git a/Utils/Console/Server.hh b/Utils/Console/Server.hh index 7d0a10de..4c5e66ff 100644 --- a/Utils/Console/Server.hh +++ b/Utils/Console/Server.hh @@ -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); diff --git a/Utils/Console/Server.ih b/Utils/Console/Server.ih index d97c1c9c..aa77d74d 100644 --- a/Utils/Console/Server.ih +++ b/Utils/Console/Server.ih @@ -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); diff --git a/Utils/Termlib/AbstractTerminal.hh b/Utils/Termlib/AbstractTerminal.hh index b3f396d0..95408f6b 100644 --- a/Utils/Termlib/AbstractTerminal.hh +++ b/Utils/Termlib/AbstractTerminal.hh @@ -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 }; diff --git a/Utils/Termlib/Editor.cc b/Utils/Termlib/Editor.cc index ce6a3fb1..0122904d 100644 --- a/Utils/Termlib/Editor.cc +++ b/Utils/Termlib/Editor.cc @@ -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(); } diff --git a/Utils/Termlib/Editor.hh b/Utils/Termlib/Editor.hh index bacfeff1..952291fa 100644 --- a/Utils/Termlib/Editor.hh +++ b/Utils/Termlib/Editor.hh @@ -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 diff --git a/Utils/Termlib/TelnetTerminal.cc b/Utils/Termlib/TelnetTerminal.cc index 3445d5c2..758a3607 100644 --- a/Utils/Termlib/TelnetTerminal.cc +++ b/Utils/Termlib/TelnetTerminal.cc @@ -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(); } diff --git a/Utils/Termlib/TelnetTerminal.hh b/Utils/Termlib/TelnetTerminal.hh index 650ce1f9..09aea808 100644 --- a/Utils/Termlib/TelnetTerminal.hh +++ b/Utils/Termlib/TelnetTerminal.hh @@ -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); ///\} -- GitLab