Utils: Document new utilities
[senf.git] / Console / Executor.hh
index 189eece..882792a 100644 (file)
 namespace senf {
 namespace console {
 
-    /** \brief
+    /** \brief Execute config/console commands
+
+        The Executor interprets parsed config/console commands and executes them. It manages the
+        current execution context (current directory, directory stack and so on).
+
+        The executor is normally called directly by the parser callback for each command.
+
+        Executing the built-in 'exit' command will throw Executor::ExitException. This exception
+        (which is not derived from std::exception since it's not a real exception) must be handled
+        by the caller.
+
+        All directories are managed using weak pointers. If any of the directories expires (current
+        directory, directory stack, last directory) it will be replaced with the root
+        directory. Directories expire when they are destructed or when they are detached from the
+        config tree root node.
       */
     class Executor
         : boost::noncopyable
     {
         SENF_LOG_CLASS_AREA();
-        SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
+        SENF_LOG_DEFAULT_LEVEL( senf::log::VERBOSE );
     public:
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
-        typedef boost::iterator_range< ParseCommandInfo::argument_iterator> Arguments;
+        /// Thrown by built-in 'exit' command
+        struct ExitException {};        
+
+        /// Executor policy function
+        typedef boost::function<void (DirectoryNode &,std::string const &)> SecurityPolicy;
 
-        struct ExitException {}; // NOT derived from std::exception !
+        /// Thrown by the SecurityPolicy to silently ignore a command
+        struct IgnoreCommandException {};
 
         ///////////////////////////////////////////////////////////////////////////
         //\/name Structors and default members
@@ -62,24 +81,84 @@ namespace console {
         ///\}
         ///////////////////////////////////////////////////////////////////////////
 
-        bool operator()(ParseCommandInfo const & command, std::ostream & output);
-        DirectoryNode & cwd() const;
+        void execute(std::ostream & output, ParseCommandInfo const & command);
+                                        ///< Execute command
+                                        /**< Output will be written to \a output. 
+                                             Same as operator()(). */
+
+        void operator()(std::ostream & output, ParseCommandInfo const & command);
+                                        ///< Execute command
+                                        /**< Output will be written to \a output. 
+                                             Same as execute(). */
+        DirectoryNode & cwd() const;    ///< Current working directory
+        std::string cwdPath() const;    ///< Return pathname of current directory
+        bool skipping() const;          ///< \c true, if currently skipping a directory group
+
+        bool autocd() const;            ///< Get current autocd status
+                                        /**< if autocd is enabled, specifying a directory name as
+                                             command will cd to that directory. Disabled by
+                                             default (but enabled automatically by the interactive
+                                             console). */
+        Executor & autocd(bool v);      ///< Set autocd status
+                                        /**< \see autocd() */
+
+        bool autocomplete() const;      ///< Get current autocomplete status
+                                        /**< if autocomplete is enabled, path components which can
+                                             be uniquely completed will be completed
+                                             automatically. Disabled by default (but enabled
+                                             automatically by the interactive console) void
+                                             autocomplete(bool v). */
+
+        Executor & autocomplete(bool v); ///< Set autocomplete status
+                                        /**< \see autocomplete() */
+
+        DirectoryNode & chroot() const; ///< Get root node
+                                        /**< The root node defaults to senf::console::root(). If
+                                             changed, all path references are relative to this node
+                                             and objects outside that tree cannot be accessed. */ 
+        Executor & chroot(DirectoryNode & node); ///< chroot into given directory
+                                        /**< After this call, all path's are interpreted relative to
+                                             \a node and only nodes in the tree rooted at \a node
+                                             are accessible via the executor. This value defaults to
+                                             senf::console::root(). */
+
+        Executor & policy(SecurityPolicy policy = SecurityPolicy()); ///< Set security policy
+                                        /**< The security policy is called before traversing a node
+                                             to validate that access. */
 
     protected:
 
     private:
-        DirectoryNode & traverseTo(ParseCommandInfo::argument_value_type const & path);
-        CommandNode & traverseToCommand(ParseCommandInfo::CommandPathRange const & path);
+        typedef std::vector<DirectoryNode::weak_ptr> Path;
+
+        void exec(std::ostream & output, ParseCommandInfo const & command);
 
+        void cd(ParseCommandInfo::TokensRange dir);
+        void ls(std::ostream & output, ParseCommandInfo::TokensRange dir);
+        void pushd(ParseCommandInfo::TokensRange dir);
+        void popd();
+        void exit();
+        void help(std::ostream & output, ParseCommandInfo::TokensRange path);
+
+        GenericNode & traverseNode(ParseCommandInfo::TokensRange const & path);
+        void traverseDirectory(ParseCommandInfo::TokensRange const & path,
+                               Path & dir);
+
+        struct InvalidPathException {};
         struct InvalidDirectoryException {};
         struct InvalidCommandException {};
+        
+        DirectoryNode::ptr root_;
+        SecurityPolicy policy_;
+        mutable Path cwd_;
+        Path oldCwd_;
 
-        DirectoryNode::weak_ptr cwd_;
-        DirectoryNode::weak_ptr oldCwd_;
-        typedef std::vector<DirectoryNode::weak_ptr> DirStack;
+        typedef std::vector<Path> DirStack;
         DirStack dirstack_;
-    };
 
+        bool autocd_;
+        bool autocomplete_;
+    };
 
 }}