00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #include "Node.hh"
00027 #include "Node.ih"
00028
00029
00030 #include <senf/Utils/Range.hh>
00031
00032
00033 #define prefix_
00034
00035
00036 prefix_ senf::console::DirectoryNode & senf::console::root()
00037 {
00038 static DirectoryNode::ptr rootNode (new DirectoryNode());
00039 return *rootNode;
00040 }
00041
00042 namespace {
00043 void dodump(std::ostream & output, unsigned level, senf::console::DirectoryNode & node)
00044 {
00045 std::string pad (2*level, ' ');
00046 senf::console::DirectoryNode::child_iterator i (node.children().begin());
00047 senf::console::DirectoryNode::child_iterator const i_end (node.children().end());
00048 for (; i != i_end; ++i) {
00049 output << pad << i->first;
00050 if (i->second->isDirectory()) {
00051 output << "/\n";
00052 dodump(output, level+1,static_cast<senf::console::DirectoryNode&>(*i->second));
00053 }
00054 else if (i->second->isLink())
00055 output << "@ -> " << i->second->followLink().path() << '\n';
00056 else
00057 output << '\n';
00058 }
00059 }
00060 }
00061
00062 prefix_ void senf::console::dump(std::ostream & os, DirectoryNode & dir)
00063 {
00064 dodump(os,0,dir);
00065 }
00066
00067
00068
00069
00070 prefix_ std::string senf::console::GenericNode::path()
00071 const
00072 {
00073 std::string path (name());
00074 ptr node (parent());
00075 while (node) {
00076 path = node->name() + "/" + path;
00077 node = node->parent();
00078 }
00079 return path.empty() ? "/" : path;
00080 }
00081
00082 prefix_ std::string senf::console::GenericNode::path(DirectoryNode const & root)
00083 const
00084 {
00085 std::string path;
00086 cptr node (thisptr());
00087 while (node && node != root.thisptr()) {
00088 if (! path.empty())
00089 path = node->name() + "/" + path;
00090 else
00091 path = node->name();
00092 node = node->parent();
00093 }
00094 if (path.empty() || path[0] != '/')
00095 path = "/" + path;
00096 return path;
00097 }
00098
00099 prefix_ bool senf::console::GenericNode::active()
00100 const
00101 {
00102 cptr node (thisptr());
00103 while (node->parent())
00104 node = node->parent();
00105 return node == root().thisptr();
00106 }
00107
00108 prefix_ bool senf::console::GenericNode::isChildOf(DirectoryNode & parent)
00109 const
00110 {
00111 cptr node (thisptr());
00112 while (node && node != parent.thisptr())
00113 node = node->parent();
00114 return node;
00115 }
00116
00117
00118
00119
00120 prefix_ void senf::console::LinkNode::v_help(std::ostream & os)
00121 const
00122 {
00123 follow().help(os);
00124 }
00125
00126 prefix_ std::string senf::console::LinkNode::v_shorthelp()
00127 const
00128 {
00129 return follow().shorthelp();
00130 }
00131
00132
00133
00134
00135 prefix_ senf::console::DirectoryNode::~DirectoryNode()
00136 {
00137 ChildMap::iterator i (children_.begin());
00138 ChildMap::iterator const i_end (children_.end());
00139 for (; i != i_end; ++i)
00140 i->second->parent_ = 0;
00141 }
00142
00143 prefix_ senf::console::GenericNode::ptr
00144 senf::console::DirectoryNode::remove(std::string const & name)
00145 {
00146 ChildMap::iterator i (children_.find(name));
00147 if (i == children_.end())
00148 throw UnknownNodeNameException() << ": '" << name << "'";
00149 GenericNode::ptr node (i->second);
00150 children_.erase(i);
00151 node->parent_ = 0;
00152 node->name_.clear();
00153 return node;
00154 }
00155
00156 prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node)
00157 {
00158 BOOST_ASSERT( ! node->parent() );
00159 if (node->name().empty()) {
00160 node->name("unnamed");
00161 SENF_LOG((senf::log::MESSAGE)("Adding 'unnamed' node"));
00162 }
00163 if (children_.find(node->name()) != children_.end()) {
00164 unsigned suffix (0);
00165 std::string newName;
00166 do {
00167 ++suffix;
00168 newName = node->name() + "-" + boost::lexical_cast<std::string>(suffix);
00169 } while (children_.find(newName) != children_.end());
00170 SENF_LOG((senf::log::MESSAGE)("Uniquifying node '" << node->name() << "' to '"
00171 << newName << "'"));
00172 node->name(newName);
00173 }
00174 children_.insert(std::make_pair(node->name(),node));
00175 node->parent_ = this;
00176 }
00177
00178 prefix_ senf::console::GenericNode &
00179 senf::console::DirectoryNode::getLink(std::string const & name)
00180 const
00181 {
00182 ChildMap::const_iterator i (children_.find(name));
00183 if (i == children_.end())
00184 throw UnknownNodeNameException() << ": '" << name << "'";
00185 return *(i->second);
00186 }
00187
00188 prefix_ void senf::console::DirectoryNode::v_help(std::ostream & output)
00189 const
00190 {
00191 output << doc_ << "\n";
00192 }
00193
00194 prefix_ std::string senf::console::DirectoryNode::v_shorthelp()
00195 const
00196 {
00197 if (! shortdoc_.empty())
00198 return shortdoc_;
00199 return doc_.substr(0,doc_.find('\n'));
00200 }
00201
00202
00203
00204 #ifndef DOXYGEN
00205
00206 prefix_ void senf::console::detail::NodeTraverser::operator()(std::string const & name)
00207 {
00208 if (! init_) {
00209 init_ = true;
00210 if (name == std::string("")) {
00211 dir_ = root_.thisptr();
00212 return;
00213 }
00214 }
00215 if (! elt_.empty()) {
00216 if (elt_ == "..") {
00217 dir_ = dir_->parent();
00218 if (! dir_ || ! dir_->isChildOf(root_))
00219 dir_ = root_.thisptr();
00220 }
00221 else if (elt_ != "" && elt_ != ".") {
00222 if (! dir_->hasChild(elt_) && autocomplete_) {
00223 DirectoryNode::ChildrenRange completions (dir_->completions(elt_));
00224 if (has_one_elt(completions))
00225 elt_ = completions.begin()->first;
00226 }
00227
00228
00229 DirectoryNode & d (dynamic_cast<DirectoryNode&>( dir_->get(elt_) ));
00230 dir_ = d.thisptr();
00231 }
00232 }
00233 elt_ = name;
00234 }
00235
00236 prefix_ senf::console::GenericNode & senf::console::detail::NodeTraverser::node()
00237 {
00238 if (elt_ != "" && elt_ != ".") {
00239 if (! dir_->hasChild(elt_) && autocomplete_) {
00240 DirectoryNode::ChildrenRange completions (dir_->completions(elt_));
00241 if (has_one_elt(completions))
00242 elt_ = completions.begin()->first;
00243 }
00244 return dir_->get(elt_);
00245 }
00246 else
00247 return * dir_;
00248 }
00249 #endif
00250
00251
00252
00253
00254 prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output)
00255 const
00256 {
00257 output << doc_ << "\n";
00258 }
00259
00260 prefix_ std::string senf::console::SimpleCommandNode::v_shorthelp()
00261 const
00262 {
00263 if (! shortdoc_.empty())
00264 return shortdoc_;
00265 return doc_.substr(0,doc_.find('\n'));
00266 }
00267
00268 prefix_ void senf::console::SimpleCommandNode::v_execute(boost::any & rv, std::ostream & os,
00269 ParseCommandInfo const & command)
00270 const
00271 {
00272 fn_(os, command);
00273 }
00274
00275
00276 #undef prefix_
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288