#include "../../Utils/Range.hh"
#include "../../Utils/String.hh"
#include "../../Utils/range.hh"
+#include "Server.hh"
//#include "Executor.mpp"
#define prefix_
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())
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
: 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)
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();
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" );
}
{
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" );
}
{
{
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 );
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" );
}
{
reader_->write(data);
}
+prefix_ unsigned senf::console::detail::LineEditorSwitcher::v_width()
+ const
+{
+ return reader_->width();
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::detail::LineEditorClientReader
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)
{
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_;
};
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);
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)
}
}
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()];
}
enum BuiltinCommand { NoBuiltin,
BuiltinCD,
BuiltinLS,
+ BuiltinLR,
BuiltinPUSHD,
BuiltinPOPD,
BuiltinEXIT,
| 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
{ 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)
{
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 );
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" );
}
}
handle().write(data);
}
+prefix_ unsigned senf::console::detail::DumbClientReader::v_width()
+ const
+{
+ return 80;
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::detail::NoninteractiveClientReader
handle().write(data);
}
+prefix_ unsigned senf::console::detail::NoninteractiveClientReader::v_width()
+ const
+{
+ return 80;
+}
+
prefix_ void
senf::console::detail::NoninteractiveClientReader::newData(int event)
{
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();
v_write(data);
}
+prefix_ unsigned senf::console::detail::ClientReader::width()
+ const
+{
+ return v_width();
+}
+
prefix_ senf::console::detail::ClientReader::ClientReader(Client & client)
: client_ (client)
{}
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);
void disablePrompt();
void enablePrompt();
void write(std::string const & data);
+ unsigned width() const;
protected:
ClientReader(Client & client);
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_;
};
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();
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);
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
};
}
prefix_ unsigned senf::term::BaseEditor::width()
+ const
{
return terminal_->width();
}
prefix_ unsigned senf::term::BaseEditor::height()
+ const
{
return terminal_->height();
}
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
}
prefix_ unsigned senf::term::TelnetTerminal::width()
+ const
{
return telnethandler::NAWS::width();
}
prefix_ unsigned senf::term::TelnetTerminal::height()
+ const
{
return telnethandler::NAWS::height();
}
///\{
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);
///\}