X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Utils%2FConsole%2FLineEditor.cc;h=31df1f7829717fd48576138b936db6a67019d776;hb=fd3a0e8ac95d1158e9ea661ddf9187b67c70169f;hp=ab2f54820757e80f9f912f07382dde81bd853a67;hpb=368058ef8f5eb65ea7e210351af25f49ddd0f342;p=senf.git diff --git a/Utils/Console/LineEditor.cc b/Utils/Console/LineEditor.cc index ab2f548..31df1f7 100644 --- a/Utils/Console/LineEditor.cc +++ b/Utils/Console/LineEditor.cc @@ -28,6 +28,7 @@ // Custom includes #include "../Logger/SenfLog.hh" +#include "../../Utils/range.hh" //#include "LineEditor.mpp" #define prefix_ @@ -76,6 +77,10 @@ LineEditorClientReader(Client & client, LineEditorSwitcher & switcher) editor_.prompt(promptString()); editor_.defineKey(senf::term::KeyParser::Ctrl('D'), senf::membind(&LineEditorClientReader::deleteCharOrExit, this)); + editor_.defineKey(senf::term::KeyParser::Tab, + boost::bind(&term::bindings::complete, + _1, + senf::membind(&LineEditorClientReader::completePath, this))); } prefix_ void senf::console::detail::LineEditorClientReader::v_setupFailed() @@ -122,6 +127,76 @@ senf::console::detail::LineEditorClientReader::deleteCharOrExit(term::LineEditor term::bindings::deleteChar(editor); } +prefix_ void senf::console::detail::LineEditorClientReader:: +completePath(term::LineEditor & editor, unsigned b, unsigned e, + std::vector & completions) +{ + std::string base (editor.text().substr(b,e)); + CommandParser parser; + ParseCommandInfo cmd; + try { + parser.parsePath(base, cmd); + } + catch (CommandParser::ParserErrorException & ex) { + return; + } + + ParseCommandInfo::TokensRange path (cmd.commandPath()); + if (path.empty()) { + DirectoryNode::ChildrenRange cs (client().cwd().children()); + for (DirectoryNode::ChildrenRange::iterator i (cs.begin()); i != cs.end(); ++i) + completions.push_back(i->first + (i->second->followLink().isDirectory() ? "/" : " ")); + return; + } + + ParseCommandInfo::TokensRange::const_iterator i (path.begin()); + ParseCommandInfo::TokensRange::const_iterator const i_end (boost::prior(path.end())); + DirectoryNode * dir (& client().cwd()); + std::string basePath; + for (; i != i_end; ++i) + if (*i == NoneToken()) { + if (i == path.begin()) { + dir = & client().root(); + basePath = "/"; + } + } + else if (*i == WordToken("..")) { + DirectoryNode * parent (dir->parent().get()); + if (parent) dir = parent; + basePath += "../"; + } + else if (*i == WordToken(".")) + basePath += "./"; + else { + if (dir->hasChild(i->value())) { + try { + dir = & dir->getDirectory(i->value()); + } + catch (std::bad_cast &) { + return; + } + basePath += i->value() + "/"; + } + else { + DirectoryNode::ChildrenRange cs (dir->completions(i->value())); + if (has_one_elt(cs)) { + GenericNode & node (cs.begin()->second->followLink()); + if (!node.isDirectory()) + return; + dir = static_cast(&node); + basePath += cs.begin()->first + "/"; + } + else + return; + } + } + + DirectoryNode::ChildrenRange cs (dir->completions(i->value())); + for (DirectoryNode::ChildrenRange::iterator j (cs.begin()); j != cs.end(); ++j) + completions.push_back(basePath + j->first + + (j->second->followLink().isDirectory() ? "/" : " ")); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "LineEditor.mpp"