Utils/Logger: Remove dependency on libboost_datetime
[senf.git] / Console / Node.cc
index f21ab66..3e16667 100644 (file)
@@ -24,7 +24,7 @@
     \brief Node non-inline non-template implementation */
 
 #include "Node.hh"
-//#include "Node.ih"
+#include "Node.ih"
 
 // Custom includes
 
@@ -53,6 +53,23 @@ prefix_ std::string senf::console::GenericNode::path()
     return path.empty() ? "/" : path;
 }
 
+prefix_ std::string senf::console::GenericNode::path(DirectoryNode const & root)
+    const
+{
+    std::string path;
+    cptr node (thisptr());
+    while (node && node != root.thisptr()) {
+        if (! path.empty())
+            path = node->name() + "/" + path;
+        else
+            path = node->name();
+        node = node->parent();
+    }
+    if (path.empty() || path[0] != '/')
+        path = "/" + path;
+    return path;
+}
+
 prefix_ bool senf::console::GenericNode::active()
     const
 {
@@ -62,6 +79,15 @@ prefix_ bool senf::console::GenericNode::active()
     return node == root().thisptr();
 }
 
+prefix_ bool senf::console::GenericNode::isChildOf(DirectoryNode & parent)
+    const
+{
+    cptr node (thisptr());
+    while (node && node != parent.thisptr())
+        node = node->parent();
+    return node;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 //senf::console::DirectoryNode
 
@@ -73,20 +99,28 @@ senf::console::DirectoryNode::remove(std::string const & name)
         throw UnknownNodeNameException() << ": '" << name << "'";
     GenericNode::ptr node (i->second);
     children_.erase(i);
+    node->parent_ = 0;
+    node->name_.clear();
     return node;
 }
 
 prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node)
 {
     BOOST_ASSERT( ! node->parent() );
+    if (node->name().empty()) {
+        node->name("unnamed");
+        SENF_LOG((senf::log::MESSAGE)("Adding 'unnamed' node"));
+    }
     if (children_.find(node->name()) != children_.end()) {
         unsigned suffix (0);
         std::string newName;
         do {
             ++suffix;
-            newName = node->name() + boost::lexical_cast<std::string>(suffix);
+            newName = node->name() + "-" + boost::lexical_cast<std::string>(suffix);
         } while (children_.find(newName) != children_.end());
-        name(*node, newName);
+        SENF_LOG((senf::log::MESSAGE)("Uniquifying node '" << node->name() << "' to '" 
+                                      << newName << "'"));
+        node->name(newName);
     }
     children_.insert(std::make_pair(node->name(),node));
     node->parent_ = this;
@@ -109,6 +143,62 @@ prefix_ void senf::console::DirectoryNode::v_help(std::ostream & output)
 }
 
 ///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::NodeTraverser
+
+prefix_ void senf::console::detail::NodeTraverser::operator()(std::string const & name)
+{
+    if (! init_) {
+        init_ = true;
+        if (name == std::string("")) {
+            dir_ = root_.thisptr();
+            return;
+        }
+    }
+    if (! elt_.empty()) {
+        if (elt_ == "..") {
+            dir_ = dir_->parent();
+            if (! dir_ || ! dir_->isChildOf(root_))
+                dir_ = root_.thisptr();
+        }
+        else if (elt_ != "" && elt_ != ".") {
+            if (! dir_->hasChild(elt_) && autocomplete_) {
+                DirectoryNode::ChildrenRange completions (dir_->completions(elt_));
+                if (completions.size() == 1)
+                    elt_ = completions.begin()->first;
+            }
+            // Why does g++ give an error on this line ???? :
+            // dir = dynamic_cast<DirectoryNode&>( dir->get(name) ).thisptr();
+            DirectoryNode & d (dynamic_cast<DirectoryNode&>( dir_->get(elt_) ));
+            dir_ = d.thisptr();
+        }
+    }
+    elt_ = name;
+}
+
+prefix_ senf::console::GenericNode & senf::console::detail::NodeTraverser::node()
+{
+    if (elt_ != "" && elt_ != ".") {
+        if (! dir_->hasChild(elt_) && autocomplete_) {
+            DirectoryNode::ChildrenRange completions (dir_->completions(elt_));
+            if (completions.size() == 1)
+                elt_ = completions.begin()->first;
+        }
+        return dir_->get(elt_);
+    }
+    else
+        return * dir_;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SyntaxErrorException
+
+prefix_ char const * senf::console::SyntaxErrorException::what()
+    const throw()
+{
+    return message().empty() ? "syntax error" : message().c_str();
+}
+
+///////////////////////////////////////////////////////////////////////////
 // senf::console::SimpleCommandNode
 
 prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output)
@@ -117,6 +207,13 @@ prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output)
     output << doc_ << "\n";
 }
 
+prefix_ void senf::console::SimpleCommandNode::v_execute(std::ostream & output,
+                                                         ParseCommandInfo const & command)
+    const
+{
+    fn_(output, command);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Node.mpp"