| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef SRC_DEVELOPER_SHELL_JOSH_CONSOLE_REPL_H_ | |
| #define SRC_DEVELOPER_SHELL_JOSH_CONSOLE_REPL_H_ | |
| #include <string> | |
| #include "src/lib/line_input/line_input.h" | |
| #include "third_party/quickjs/quickjs-libc.h" | |
| #include "third_party/quickjs/quickjs.h" | |
| namespace shell::repl { | |
| // This class implements a Javascript repl. | |
| // Once created it can be fed input through FeedInput, until FeedInput returns true (when a \q | |
| // command is detected in the input): the repl will not accept any more input, and all input after | |
| // \q was ignored. | |
| // Before execution, the prompt is hidden and the scripts are wrapped in the | |
| // evalScriptAwaitsPromise() (repl_cc.js) function: this function executes the script, then: | |
| // - if its result is a promise: it waits (through a callback function to the promise) for it to | |
| // resolve (or reject), then prints its result and shows the prompt again | |
| // - else it prints it and shows the prompt immediately | |
| // Three shell specific commands are available: \h for help, \q to exit, c to make the prompt show | |
| // again after an uncaught error in a promise | |
| class Repl { | |
| public: | |
| Repl(JSContext* ctx, const std::string& prompt); | |
| // Takes as argument a buffer containing the characters of input, and the number of characters | |
| // Ignores all input but 'Ctrl-Z' if a command is still running (ie running_ is set to true) | |
| // Returns true if "\q" was entered at the beginning of a line | |
| bool FeedInput(uint8_t* bytes, size_t num_bytes); | |
| // Returns the cmd stored in cur_cmd_ field | |
| const char* GetCmd(); | |
| // Returns the line stored in cur_line_ field | |
| const char* GetLine(); | |
| // Shows the prompt, and sets running_ to false | |
| void ShowPrompt(); | |
| void Write(const char* output); | |
| void ChangeOutput(std::ostream* os); | |
| virtual ~Repl() = default; | |
| protected: | |
| // used for testing | |
| Repl(JSContext* ctx, const std::string& prompt, fit::function<void(const std::string&)> cb); | |
| // sets exit_shell_cmd_ to true if "\q" (exiting the shell) was typed | |
| virtual void HandleLine(const std::string& line); | |
| // calls the JS function evalScriptAwaitsPromise() | |
| virtual void EvalCmd(const std::string& cmd); | |
| // Given a possibly incomplete Javascript script, returns the list of currently open brackets ({[, | |
| // * for block comments and / for regular expressions | |
| std::string OpenSymbols(const std::string& cmd); | |
| private: | |
| std::string GetAndExecuteShellCmd(std::string cmd); | |
| std::string mexpr_; | |
| line_input::LineInputStdout li_; | |
| JSContext* ctx_; | |
| std::ostream* output_; | |
| bool exit_shell_cmd_; | |
| bool running_; // set to true at the beginning of a JS script execution, and set to false by | |
| // ShowPrompt(). | |
| std::string cur_cmd_; | |
| std::string line_to_complete_; | |
| }; | |
| } // namespace shell::repl | |
| #endif // SRC_DEVELOPER_SHELL_JOSH_CONSOLE_REPL_H_ |