From 128529c2bf7c18a9f7e7a0c44d7d3a48c1533d28 Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Tue, 27 May 2008 14:00:24 +0000
Subject: [PATCH] Console: Fix autocomplete / autocd support

---
 Console/Executor.cc      | 18 +++++++++++++++---
 Console/Executor.hh      |  1 +
 Console/Executor.test.cc | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/Console/Executor.cc b/Console/Executor.cc
index d5f56fbdc..50001044e 100644
--- a/Console/Executor.cc
+++ b/Console/Executor.cc
@@ -249,7 +249,7 @@ senf::console::Executor::traverseNode(ParseCommandInfo::TokensRange const & path
                               boost::prior(path.end())),
                           dir);
         DirectoryNode & base (*dir.back().lock());
-        std::string const & name (boost::prior(path.end())->value());
+        std::string const & name (complete(base, boost::prior(path.end())->value()));
         if (policy_)
             policy_( base, name );
         return dir.back().lock()->get(name);
@@ -281,9 +281,10 @@ senf::console::Executor::traverseDirectory(ParseCommandInfo::TokensRange const &
                 ;
             else {
                 DirectoryNode & base (*dir.back().lock());
+                std::string name (complete(base, i->value()));
                 if (policy_)
-                    policy_( base, i->value() );
-                dir.push_back(base[i->value()].thisptr());
+                    policy_( base, name );
+                dir.push_back(base[name].thisptr());
             }
         }
     }
@@ -295,6 +296,17 @@ senf::console::Executor::traverseDirectory(ParseCommandInfo::TokensRange const &
     }
 }
 
+prefix_ std::string senf::console::Executor::complete(DirectoryNode & dir,
+                                                      std::string const & name)
+{
+    if (! dir.hasChild(name)) {
+        DirectoryNode::ChildrenRange completions (dir.completions(name));
+        if (completions.size() == 1)
+            return completions.begin()->first;
+    }
+    return name;
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Executor.mpp"
diff --git a/Console/Executor.hh b/Console/Executor.hh
index 81049b1b0..02cff1895 100644
--- a/Console/Executor.hh
+++ b/Console/Executor.hh
@@ -145,6 +145,7 @@ namespace console {
         GenericNode & traverseNode(ParseCommandInfo::TokensRange const & path);
         void traverseDirectory(ParseCommandInfo::TokensRange const & path,
                                Path & dir);
+        std::string complete(DirectoryNode & dir, std::string const & name);
 
         struct InvalidPathException {};
         struct InvalidDirectoryException {};
diff --git a/Console/Executor.test.cc b/Console/Executor.test.cc
index 36f9dcfb2..1266ae099 100644
--- a/Console/Executor.test.cc
+++ b/Console/Executor.test.cc
@@ -229,6 +229,38 @@ BOOST_AUTO_UNIT_TEST(executorPolicy)
     senf::console::root().remove("dir2");
 }
 
+BOOST_AUTO_UNIT_TEST(executorAuto)
+{
+    senf::console::root().mkdir("dir1").mkdir("dir3");
+    senf::console::root().mkdir("dir2").doc("Helptext").add("test",&testCommand);
+
+    senf::console::Executor executor;
+    executor
+        .autocomplete(true)
+        .autocd(true);
+    senf::console::CommandParser parser;
+
+    {
+        std::stringstream os;
+        parser.parse("dir2", &setCommand);
+        executor(os, commands.back());
+        BOOST_CHECK_EQUAL( executor.cwdPath(), "/dir2" );
+        BOOST_CHECK_EQUAL( os.str(), "" );
+    }
+    
+    {
+        std::stringstream os;
+        parser.parse("t", &setCommand);
+        executor(os, commands.back());
+        BOOST_CHECK_EQUAL( os.str(), "testCommand\n" );
+    }
+    
+
+    commands.clear();
+    senf::console::root().remove("dir1");
+    senf::console::root().remove("dir2");
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
-- 
GitLab