Skip to content
Snippets Groups Projects
Commit d95f726f authored by g0dil's avatar g0dil
Browse files

Utils/Console: Move link target in lr output one line up

Utils/Console: Add documentation to Client members
Utils/Console: Add support for std::pair parsing/formatting
Utils/Console: Some more documentation
parent b5e713e0
No related branches found
No related tags found
No related merge requests found
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <boost/range/iterator_range.hpp> #include <boost/range/iterator_range.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/preprocessor/stringize.hpp>
#include "../../Utils/senfassert.hh" #include "../../Utils/senfassert.hh"
#include "../../Utils/Range.hh" #include "../../Utils/Range.hh"
#include "../../Utils/String.hh" #include "../../Utils/String.hh"
...@@ -232,21 +233,15 @@ prefix_ void senf::console::Executor::cd(ParseCommandInfo::TokensRange dir) ...@@ -232,21 +233,15 @@ prefix_ void senf::console::Executor::cd(ParseCommandInfo::TokensRange dir)
prefix_ void senf::console::Executor::ls(std::ostream & output, prefix_ void senf::console::Executor::ls(std::ostream & output,
ParseCommandInfo::TokensRange path) ParseCommandInfo::TokensRange path)
{ {
unsigned width (80); # define HELP_COLUMN 28
try {
width = senf::console::Client::get(output).width(); unsigned width (senf::console::Client::getWidth(output, 80u, 60u)-(HELP_COLUMN+1));
}
catch (std::bad_cast &)
{}
if (width<60)
width = 80;
width -= 28+1;
Path dir (cwd_); Path dir (cwd_);
traverseDirectory(path, dir); traverseDirectory(path, dir);
DirectoryNode & node (*dir.back().lock()); DirectoryNode & node (*dir.back().lock());
DirectoryNode::child_iterator i (node.children().begin()); DirectoryNode::child_iterator i (node.children().begin());
DirectoryNode::child_iterator const i_end (node.children().end()); 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) for (; i != i_end; ++i)
output << fmt output << fmt
% i->first % i->first
...@@ -256,8 +251,12 @@ prefix_ void senf::console::Executor::ls(std::ostream & output, ...@@ -256,8 +251,12 @@ prefix_ void senf::console::Executor::ls(std::ostream & output,
? "@" ? "@"
: "" ) : "" )
% i->second->shorthelp().substr(0,width); % i->second->shorthelp().substr(0,width);
# undef HELP_COLUMN
} }
# define HELP_COLUMN 40
namespace { namespace {
typedef std::map<senf::console::DirectoryNode*,std::string> NodesMap; typedef std::map<senf::console::DirectoryNode*,std::string> NodesMap;
...@@ -265,25 +264,20 @@ namespace { ...@@ -265,25 +264,20 @@ namespace {
void dolr(std::ostream & output, unsigned width, NodesMap & nodes, std::string const & base, void dolr(std::ostream & output, unsigned width, NodesMap & nodes, std::string const & base,
unsigned level, senf::console::DirectoryNode & node) 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, ' '); std::string pad (2*level, ' ');
senf::console::DirectoryNode::child_iterator i (node.children().begin()); senf::console::DirectoryNode::child_iterator i (node.children().begin());
senf::console::DirectoryNode::child_iterator const i_end (node.children().end()); senf::console::DirectoryNode::child_iterator const i_end (node.children().end());
for (; i != i_end; ++i) { 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()) { if (i->second->followLink().isDirectory()) {
senf::console::DirectoryNode & subnode ( senf::console::DirectoryNode & subnode (
static_cast<senf::console::DirectoryNode&>(i->second->followLink())); static_cast<senf::console::DirectoryNode&>(i->second->followLink()));
NodesMap::iterator j (nodes.find(&subnode)); NodesMap::iterator j (nodes.find(&subnode));
if (j == nodes.end()) { 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); std::string subbase (base);
if (! subbase.empty()) if (! subbase.empty())
subbase += "/"; subbase += "/";
...@@ -291,7 +285,14 @@ namespace { ...@@ -291,7 +285,14 @@ namespace {
nodes.insert(std::make_pair(&subnode, subbase)); nodes.insert(std::make_pair(&subnode, subbase));
dolr(output, width, nodes, subbase, level+1, subnode); dolr(output, width, nodes, subbase, level+1, subnode);
} else } 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 { ...@@ -301,22 +302,16 @@ namespace {
prefix_ void senf::console::Executor::lr(std::ostream & output, prefix_ void senf::console::Executor::lr(std::ostream & output,
ParseCommandInfo::TokensRange path) 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_); Path dir (cwd_);
traverseDirectory(path, dir); traverseDirectory(path, dir);
DirectoryNode & node (*dir.back().lock()); DirectoryNode & node (*dir.back().lock());
NodesMap nodes; 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) prefix_ void senf::console::Executor::pushd(ParseCommandInfo::TokensRange dir)
{ {
Path newDir (cwd_); Path newDir (cwd_);
......
...@@ -223,7 +223,17 @@ namespace console { ...@@ -223,7 +223,17 @@ namespace console {
class DirectoryNode; class DirectoryNode;
class CommandNode; class CommandNode;
/** \brief Get console root node */
DirectoryNode & root(); 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()); void dump(std::ostream & os, DirectoryNode & dir=root());
/** \brief Config/console node tree base-class /** \brief Config/console node tree base-class
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
//#include "VectorSupport.ih" //#include "VectorSupport.ih"
// Custom includes // Custom includes
#include <boost/format.hpp>
#define prefix_ #define prefix_
///////////////////////////////ct.p//////////////////////////////////////// ///////////////////////////////ct.p////////////////////////////////////////
...@@ -82,6 +83,42 @@ prefix_ void senf::console::SequenceReturnValueTraits<Sequence>::format(type con ...@@ -82,6 +83,42 @@ prefix_ void senf::console::SequenceReturnValueTraits<Sequence>::format(type con
os << ")"; 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 #endif
///////////////////////////////ct.e//////////////////////////////////////// ///////////////////////////////ct.e////////////////////////////////////////
......
...@@ -78,6 +78,25 @@ namespace console { ...@@ -78,6 +78,25 @@ namespace console {
: public SequenceReturnValueTraits< std::list<T,Alloc> > : 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 #endif
}} }}
......
...@@ -336,6 +336,17 @@ prefix_ void senf::console::Client::v_write(senf::log::time_type timestamp, ...@@ -336,6 +336,17 @@ prefix_ void senf::console::Client::v_write(senf::log::time_type timestamp,
reader_->enablePrompt(); 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 // senf::console::Client::SysBacktrace
......
...@@ -168,18 +168,51 @@ namespace console { ...@@ -168,18 +168,51 @@ namespace console {
void stop(); ///< Stop the client void stop(); ///< Stop the client
/**< This will close the client socket. */ /**< This will close the client socket. */
std::string const & name() const; std::string const & name() const; ///< Get name of the client instance
ClientHandle handle() const; /**< This name is used in the prompt string and is set by
std::ostream & stream(); the server. */
std::string promptString() const; ClientHandle handle() const; ///< Get the client's network socket handle
DirectoryNode & root() const; std::ostream & stream(); ///< Get client's output stream
DirectoryNode & cwd() const; /**< Data sent to this stream is sent out over the network
Server::Mode mode() const; 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; void write(std::string const & data) const;
std::string const & backtrace() const; ///< Write data to network socket
unsigned width() const; /**< 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); 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: protected:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment