reader_->write(data);
}
+prefix_ unsigned senf::console::detail::LineEditorSwitcher::v_width()
+ const
+{
+ return reader_->width();
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::detail::LineEditorClientReader
boost::bind(&term::bindings::complete,
_1,
senf::membind(&LineEditorClientReader::completePath, this)));
+ editor_.defineKey(senf::term::KeyParser::Return, &senf::term::bindings::acceptWithRepeat);
}
prefix_ void senf::console::detail::LineEditorClientReader::v_setupFailed()
BaseTelnetProtocol::write(data);
}
+prefix_ unsigned senf::console::detail::LineEditorClientReader::v_width()
+ const
+{
+ return editor_.width();
+}
+
prefix_ void
senf::console::detail::LineEditorClientReader::executeLine(std::string const & text)
{
}
prefix_ void senf::console::detail::LineEditorClientReader::
-completePath(term::LineEditor & editor, unsigned b, unsigned e,
+completePath(term::LineEditor & editor, unsigned & b, unsigned & e, std::string & prefix,
std::vector<std::string> & completions)
{
- std::string base (editor.text().substr(b,e));
+ std::string const & t (editor.text());
+ // Search backward from e finding the longest valid path. This does *not* accept all valid
+ // path's, only those without embedded white-space. However, this is only for completion so
+ // it's ok.
+ if (b<e) {
+ unsigned bb (e-1);
+ for (;;) {
+ if (! CommandParser::isWordChar(t[bb]) && t[bb] != '/') {
+ ++bb;
+ break;
+ }
+ if (bb == b)
+ break;
+ --bb;
+ }
+ b = bb;
+ }
+ std::string base (t.substr(b,e));
CommandParser parser;
ParseCommandInfo cmd;
try {
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 + "/");
- }
+ 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 = "/";
+ prefix = "/";
}
}
else if (*i == WordToken("..")) {
DirectoryNode * parent (dir->parent().get());
if (parent) dir = parent;
- basePath += "../";
+ prefix += "../";
}
else if (*i == WordToken("."))
- ;
+ prefix += "./";
else {
if (dir->hasChild(i->value())) {
- dir = & dir->getDirectory(i->value());
- basePath += i->value() + "/";
- } else {
+ try {
+ dir = & dir->getDirectory(i->value());
+ }
+ catch (std::bad_cast &) {
+ return;
+ }
+ prefix += 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<LinkNode*>(node)->follow();
- if (!node->isDirectory())
+ GenericNode & node (cs.begin()->second->followLink());
+ if (!node.isDirectory())
return;
- dir = static_cast<DirectoryNode*>(node);
- basePath += cs.begin()->first + "/";
+ dir = static_cast<DirectoryNode*>(&node);
+ prefix += 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 + "/");
- }
+ for (DirectoryNode::ChildrenRange::iterator j (cs.begin()); j != cs.end(); ++j)
+ completions.push_back(j->first + (j->second->followLink().isDirectory() ? "/" : " "));
}
///////////////////////////////cc.e////////////////////////////////////////