Utils/Termlib: Extend the completion API
[senf.git] / Utils / Console / Parse.cc
index dc1dbce..5281be5 100644 (file)
@@ -76,11 +76,16 @@ namespace detail {
               info_->builtin(ParseCommandInfo::BuiltinLS);
               setBuiltinPathArg(path); }
 
-        void pushDirectory(std::vector<Token> & path)
+        void builtin_lr(std::vector<Token> & path)
             { info_->clear();
-              info_->builtin(ParseCommandInfo::BuiltinPUSHD);
+              info_->builtin(ParseCommandInfo::BuiltinLR);
               setBuiltinPathArg(path); }
 
+        void pushDirectory()
+            { // Do NOT call clear since pushDirectory is set in ADDITION
+              // to an ordinary command (which may be only a directory name)
+              info_->builtin(ParseCommandInfo::BuiltinPUSHD); }
+
         void popDirectory()
             { info_->clear();
               info_->builtin(ParseCommandInfo::BuiltinPOPD); }
@@ -96,11 +101,12 @@ namespace detail {
 
         void setBuiltinPathArg(std::vector<Token> & path)
             {
-                pushToken(ArgumentGroupOpenToken());
-                for (std::vector<Token>::const_iterator i (path.begin());
-                     i != path.end(); ++i)
-                    pushToken(*i);
-                pushToken(ArgumentGroupCloseToken());
+                info_->command(path);
+//                 pushToken(ArgumentGroupOpenToken());
+//                 for (std::vector<Token>::const_iterator i (path.begin());
+//                      i != path.end(); ++i)
+//                     pushToken(*i);
+//                 pushToken(ArgumentGroupCloseToken());
             }
     };
 
@@ -111,6 +117,12 @@ namespace detail {
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::Token
 
+prefix_ senf::console::Token::Token(TokenType type, std::string token,
+                                    detail::FilePositionWithIndex const & pos)
+    : type_(type), token_ (token), line_ (pos.line), column_ (pos.column), index_ (pos.index)
+{}
+
+
 prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Token const & token)
 {
     static char const * tokenTypeName[] = {
@@ -162,7 +174,7 @@ prefix_ std::ostream & senf::console::operator<<(std::ostream & stream,
         }
     }
     else {
-        char const * builtins[] = { 0, "cd", "ls", "pushd", "popd", "exit", "help" };
+        char const * builtins[] = { 0, "cd", "ls", "lr", "pushd", "popd", "exit", "help" };
         stream << "builtin-" << builtins[info.builtin()];
     }
         
@@ -249,16 +261,46 @@ namespace {
     void throwParserError(Error const & err) 
     {
         static char const * msg [] = { "end of statement expected",
-                                       "'{' or arguments expected",
                                        "path expected",
                                        "')' expected",
                                        "'\"' expected" };
-        boost::spirit::file_position pos (err.where.get_position());
+        senf::console::detail::FilePositionWithIndex pos (err.where.get_position());
         throw senf::console::CommandParser::ParserErrorException(msg[err.descriptor])
             << "\nat " << pos.file << ":" << pos.line << ":" << pos.column;
     }
+
 }
 
+namespace boost { 
+namespace spirit {
+
+    template <>
+    struct position_policy<senf::console::detail::FilePositionWithIndex>
+        : public position_policy<file_position>
+    {
+        typedef position_policy<file_position> Base;
+
+        void next_line(senf::console::detail::FilePositionWithIndex & pos)
+            {
+                Base::next_line(pos);
+                pos.index ++;
+            }
+
+        void next_char(senf::console::detail::FilePositionWithIndex & pos)
+            {
+                Base::next_char(pos);
+                pos.index ++;
+            }
+
+        void tabulation(senf::console::detail::FilePositionWithIndex & pos)
+            {
+                Base::tabulation(pos);
+                pos.index ++;
+            }
+    };
+
+}}
+
 prefix_ senf::console::CommandParser::CommandParser()
     : impl_ (new Impl())
 {}
@@ -273,7 +315,8 @@ template <class Iterator>
 prefix_ Iterator senf::console::CommandParser::parseLoop(Iterator npb, Iterator npe, 
                                                          std::string const & source, Callback cb)
 {
-    typedef boost::spirit::position_iterator<Iterator> PositionIterator;
+    typedef boost::spirit::position_iterator<
+        Iterator, detail::FilePositionWithIndex> PositionIterator;
     PositionIterator b (npb, npe, source);
     PositionIterator e (npe, npe, source);
     ParseCommandInfo info;
@@ -305,7 +348,7 @@ prefix_ Iterator senf::console::CommandParser::parseLoop(Iterator npb, Iterator
                 cb(info);
             }
             catch (senf::ExceptionMixin & ex) {
-                boost::spirit::file_position pos (result.stop.get_position());
+                detail::FilePositionWithIndex pos (result.stop.get_position());
                 ex << "\nat " << pos.file << ":" << pos.line << ":" << pos.column;
                 throw;
             }
@@ -329,7 +372,8 @@ prefix_ void senf::console::CommandParser::parseFile(std::string const & filenam
 prefix_ void senf::console::CommandParser::parseArguments(std::string const & arguments,
                                                           ParseCommandInfo & info)
 {
-    typedef boost::spirit::position_iterator<std::string::const_iterator> PositionIterator;
+    typedef boost::spirit::position_iterator<
+        std::string::const_iterator, detail::FilePositionWithIndex> PositionIterator;
     PositionIterator b (arguments.begin(), arguments.end(), std::string("<unknown>"));
     PositionIterator e (arguments.end(), arguments.end(), std::string("<unknown>"));
     detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
@@ -343,12 +387,36 @@ prefix_ void senf::console::CommandParser::parseArguments(std::string const & ar
         throwParserError(ex);
     }
     if (! result.full) {
-        boost::spirit::file_position pos (result.stop.get_position());
+        detail::FilePositionWithIndex pos (result.stop.get_position());
         throw ParserErrorException("argument expected")
             << "\nat " << pos.file << ":" << pos.line << ":" << pos.column;
     }
 }
 
+prefix_ void senf::console::CommandParser::parsePath(std::string const & path,
+                                                     ParseCommandInfo & info)
+{
+    typedef boost::spirit::position_iterator<
+        std::string::const_iterator, detail::FilePositionWithIndex> PositionIterator;
+    PositionIterator b (path.begin(), path.end(), std::string("<unknown>"));
+    PositionIterator e (path.end(), path.end(), std::string("<unknown>"));
+    detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
+    boost::spirit::parse_info<PositionIterator> result;
+    try {
+        result = boost::spirit::parse( b, e, 
+                                       impl().grammar.use_parser<Impl::Grammar::PathParser>(),
+                                       impl().grammar.use_parser<Impl::Grammar::SkipParser>() );
+    }
+    catch (boost::spirit::parser_error<Impl::Grammar::Errors, PositionIterator> & ex) {
+        throwParserError(ex);
+    }
+    if (! result.full) {
+        detail::FilePositionWithIndex pos (result.stop.get_position());
+        throw ParserErrorException("path expected")
+            << "\nat " << pos.file << ":" << pos.line << ":" << pos.column;
+    }
+}
+
 struct senf::console::CommandParser::SetIncremental
 {
     SetIncremental(CommandParser & parser) : parser_ (parser) {
@@ -370,7 +438,35 @@ senf::console::CommandParser::parseIncremental(std::string const & commands, Cal
                           parseLoop(commands.begin(), commands.end(), "<unknown>", cb) );
 }
 
-///////////////////////////////cc.e////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// Character sets
+
+prefix_ bool senf::console::CommandParser::isSpecialChar(char ch)
+{
+    return Impl::Grammar::special_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isPunctuationChar(char ch)
+{
+    return Impl::Grammar::punctuation_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isSpaceChar(char ch)
+{
+    return Impl::Grammar::space_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isInvalidChar(char ch)
+{
+    return Impl::Grammar::invalid_p.test(ch);
+}
+
+prefix_ bool senf::console::CommandParser::isWordChar(char ch)
+{
+    return Impl::Grammar::word_p.test(ch);
+}
+
+/////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Parse.mpp"