From d3c4c0801dc51c2a9ebd83a5e130704314c82892 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Thu, 18 May 2023 22:09:54 -0400 Subject: [PATCH] Add support for > and >> prompts with new readline --- luprex/cpp/core/drivenengine.cpp | 14 ++++++++++++++ luprex/cpp/core/drivenengine.hpp | 6 ++++++ luprex/cpp/core/enginewrapper.hpp | 4 ++++ luprex/cpp/core/lpxclient.cpp | 4 ++-- luprex/cpp/core/lpxserver.cpp | 4 ++-- luprex/cpp/core/textgame.cpp | 4 ++-- luprex/cpp/drv/driver.cpp | 5 +++++ luprex/cpp/drv/readline.cpp | 6 ++++++ luprex/cpp/drv/readline.hpp | 9 ++++++--- 9 files changed, 47 insertions(+), 9 deletions(-) diff --git a/luprex/cpp/core/drivenengine.cpp b/luprex/cpp/core/drivenengine.cpp index 684b86ed..6473e63d 100644 --- a/luprex/cpp/core/drivenengine.cpp +++ b/luprex/cpp/core/drivenengine.cpp @@ -126,6 +126,10 @@ SharedChannel DrivenEngine::get_stdio_channel() { return stdio_channel_; } +void DrivenEngine::set_console_prompt(const eng::string &prompt) { + console_prompt_ = prompt; +} + util::LuaSourcePtr DrivenEngine::get_lua_source() { return std::move(lua_source_); } @@ -382,6 +386,11 @@ bool DrivenEngine::drv_get_outgoing_empty(uint32_t chid) const { return (v.size() == 0); } +void DrivenEngine::drv_get_console_prompt(uint32_t *len, const char **data) const { + *len = console_prompt_.size(); + *data = console_prompt_.c_str(); +} + double DrivenEngine::drv_get_clock() const { return clock_; } @@ -497,6 +506,10 @@ static bool drv_get_outgoing_empty(EngineWrapper *w, uint32_t chid) { return w->engine->drv_get_outgoing_empty(chid); } +static void drv_get_console_prompt(EngineWrapper *w, uint32_t *len, const char **data) { + return w->engine->drv_get_console_prompt(len, data); +} + static double drv_get_clock(EngineWrapper *w) { return w->engine->drv_get_clock(); } @@ -906,6 +919,7 @@ static void init_engine_wrapper_helper(EngineWrapper *w) { w->get_channel_released = drv_get_channel_released; w->get_outgoing = drv_get_outgoing; w->get_outgoing_empty = drv_get_outgoing_empty; + w->get_console_prompt = drv_get_console_prompt; w->get_clock = drv_get_clock; w->get_rescan_lua_source = drv_get_rescan_lua_source; w->get_stop_driver = drv_get_stop_driver; diff --git a/luprex/cpp/core/drivenengine.hpp b/luprex/cpp/core/drivenengine.hpp index 2ace82e2..41ebcf86 100644 --- a/luprex/cpp/core/drivenengine.hpp +++ b/luprex/cpp/core/drivenengine.hpp @@ -204,6 +204,10 @@ public: // std::ostream &stdostream() { return get_stdio_channel()->out()->ostream(); } + // Set the prompt for the console. + // + void set_console_prompt(const eng::string &prompt); + // Fetches the lua source, and takes ownership of it. The DrivenEngine // no longer contains the source after calling this. // @@ -262,6 +266,7 @@ public: bool drv_get_channel_released(uint32_t chid) const; void drv_get_outgoing(uint32_t chid, uint32_t *len, const char **data) const; bool drv_get_outgoing_empty(uint32_t chid) const; + void drv_get_console_prompt(uint32_t *len, const char **data) const; double drv_get_clock() const; bool drv_get_rescan_lua_source() const; bool drv_get_stop_driver() const; @@ -294,6 +299,7 @@ private: bool rescan_lua_source_; double clock_; bool stop_driver_; + eng::string console_prompt_; friend class Channel; }; diff --git a/luprex/cpp/core/enginewrapper.hpp b/luprex/cpp/core/enginewrapper.hpp index caf4ad28..8cd482e2 100644 --- a/luprex/cpp/core/enginewrapper.hpp +++ b/luprex/cpp/core/enginewrapper.hpp @@ -88,6 +88,10 @@ struct EngineWrapper { // bool (*get_outgoing_empty)(EngineWrapper *w, uint32_t chid); + // Get the console prompt. + // + void (*get_console_prompt)(EngineWrapper *w, uint32_t *len, const char **data); + // Get the clock. // // Get the current time. This is equal to the last value passed diff --git a/luprex/cpp/core/lpxclient.cpp b/luprex/cpp/core/lpxclient.cpp index 86124db1..4a70d30d 100644 --- a/luprex/cpp/core/lpxclient.cpp +++ b/luprex/cpp/core/lpxclient.cpp @@ -77,7 +77,7 @@ public: channel_ = new_outgoing_channel("nocert:localhost:8085"); // Set the console prompt - // get_stdio_channel()->set_prompt(console_.get_prompt()); + set_console_prompt(console_.get_prompt()); // The driver loads the lua source automatically. // However, we don't need it. Throw it out. @@ -252,7 +252,7 @@ public: eng::string line = get_stdio_channel()->in()->readline(); if (line == "") break; console_.add(line); - // get_stdio_channel()->set_prompt(console_.get_prompt()); + set_console_prompt(console_.get_prompt()); do_command(console_.get_command()); } diff --git a/luprex/cpp/core/lpxserver.cpp b/luprex/cpp/core/lpxserver.cpp index 967a328a..bd2ab855 100644 --- a/luprex/cpp/core/lpxserver.cpp +++ b/luprex/cpp/core/lpxserver.cpp @@ -51,7 +51,7 @@ public: listen_port(8080); // Set the console prompt. - // get_stdio_channel()->set_prompt(console_.get_prompt()); + set_console_prompt(console_.get_prompt()); } void do_luainvoke_command(const util::StringVec &words) { @@ -172,7 +172,7 @@ public: eng::string line = get_stdio_channel()->in()->readline(); if (line == "") break; console_.add(line); - // get_stdio_channel()->set_prompt(console_.get_prompt()); + set_console_prompt(console_.get_prompt()); do_command(console_.get_command()); } diff --git a/luprex/cpp/core/textgame.cpp b/luprex/cpp/core/textgame.cpp index 7de8d5b5..3a7b86f5 100644 --- a/luprex/cpp/core/textgame.cpp +++ b/luprex/cpp/core/textgame.cpp @@ -103,7 +103,7 @@ private: world_->run_unittests(); actor_id_ = world_->create_login_actor(); stdostream() << "Login actor ID: " << actor_id_ << std::endl; - //get_stdio_channel()->set_prompt(console_.get_prompt()); + set_console_prompt(console_.get_prompt()); } void event_update() @@ -113,7 +113,7 @@ private: eng::string line = get_stdio_channel()->in()->readline(); if (line == "") break; console_.add(line); - //get_stdio_channel()->set_prompt(console_.get_prompt()); + set_console_prompt(console_.get_prompt()); do_command(console_.get_command()); if (print_channeler_.channel(world_->get_printbuffer(actor_id_), stdostream())) { world_->invoke(print_channeler_.invocation(actor_id_)); diff --git a/luprex/cpp/drv/driver.cpp b/luprex/cpp/drv/driver.cpp index 694705f8..016fc074 100644 --- a/luprex/cpp/drv/driver.cpp +++ b/luprex/cpp/drv/driver.cpp @@ -214,6 +214,11 @@ class Driver { void handle_console_input() { read_console_recently_ = false; + uint32_t promptlen; + const char *promptdata; + engw.get_console_prompt(&engw, &promptlen, &promptdata); + CodepointString prompt = ReadlineDevice::from_utf8(std::string_view(promptdata, promptlen), nullptr); + readline_device_.set_prompt(prompt); while (true) { CodepointString cps = console_read(); if (cps.size() == 0) break; diff --git a/luprex/cpp/drv/readline.cpp b/luprex/cpp/drv/readline.cpp index 8bb5bbde..f61b103d 100644 --- a/luprex/cpp/drv/readline.cpp +++ b/luprex/cpp/drv/readline.cpp @@ -117,6 +117,11 @@ void ReadlineDevice::set_print_callback(print_callback cb) { print_cb_ = cb; } +void ReadlineDevice::set_prompt(const CodepointString &prompt) { + desired_prompt_ = prompt; + echo_command(); +} + void ReadlineDevice::erase_command() { int ccsize = current_prompt_.size() + current_command_.size(); if (ccsize > 0) { @@ -168,6 +173,7 @@ CodepointString ReadlineDevice::putcode(char32_t c) { desired_command_.clear(); current_prompt_.clear(); current_command_.clear(); + echo_command(); return result; } else if ((c == '\b') || (c == 127)) { int len = desired_command_.size(); diff --git a/luprex/cpp/drv/readline.hpp b/luprex/cpp/drv/readline.hpp index b6d11692..c439f0e4 100644 --- a/luprex/cpp/drv/readline.hpp +++ b/luprex/cpp/drv/readline.hpp @@ -19,8 +19,9 @@ private: CodepointString current_prompt_; char32_t readline_lastc_; - void echo_command(); void erase_command(); + void echo_command(); + public: ReadlineDevice(); @@ -30,6 +31,7 @@ public: // change the prompt. void set_prompt(const CodepointString &prompt); + void set_prompt_utf8(const std::string &prompt); // Use this to print anything on the console. void print(const CodepointString &cps); @@ -44,8 +46,9 @@ public: static std::string to_utf8(const CodepointString &cps); // This can be used to convert UTF8 to a codepoint string. - // Some of the bytes may not be consumed. Returns the Codepoint - // string and the number of bytes consumed. + // Some of the bytes may not be consumed, if the source contains + // a partial utf-8 sequence. Returns the Codepoint string and the + // number of bytes consumed. static CodepointString from_utf8(std::string_view source, int *consumed); };