X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Utils%2FConsole%2FLineEditor.cc;h=95f1153b706f5fea45e4fe347b9929bfe77e153f;hb=0461eef93912cb9d454d726b4a7b4ccf50ed31bd;hp=ab2f54820757e80f9f912f07382dde81bd853a67;hpb=368058ef8f5eb65ea7e210351af25f49ddd0f342;p=senf.git diff --git a/Utils/Console/LineEditor.cc b/Utils/Console/LineEditor.cc index ab2f548..95f1153 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,77 @@ 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); + if (i->second->isDirectory()) + completions.push_back(i->first + "/"); + } + 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(".")) + ; + else { + if (dir->hasChild(i->value())) { + dir = & dir->getDirectory(i->value()); + basePath += i->value() + "/"; + } else { + DirectoryNode::ChildrenRange cs (dir->completions(i->value())); + if (has_one_elt(cs)) { + GenericNode * node (cs.begin()->second.get()); + if (node->isLink()) + node = & static_cast(node)->follow(); + 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); + if (j->second->isDirectory()) + completions.push_back(basePath + j->first + "/"); + } +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "LineEditor.mpp"