From 403fc547901ada03870a78d09eaef20d5bb77e96 Mon Sep 17 00:00:00 2001 From: Gunter Labes Date: Sun, 16 Mar 2025 19:02:39 +0100 Subject: [PATCH] Leave chat open on failed command execution Also remove unused set_help_on_unknown function. --- src/chat_events.cpp | 10 ++--- src/chat_events.hpp | 2 +- src/map_command_handler.hpp | 90 ++++++++++++++++++------------------- src/menu_events.cpp | 4 +- src/menu_events.hpp | 2 +- src/play_controller.cpp | 5 ++- 6 files changed, 55 insertions(+), 58 deletions(-) diff --git a/src/chat_events.cpp b/src/chat_events.cpp index d42fa631abc..12dd46e9be5 100644 --- a/src/chat_events.cpp +++ b/src/chat_events.cpp @@ -103,25 +103,25 @@ void chat_handler::send_command(const std::string& cmd, const std::string& args send_to_server(data); } -void chat_handler::do_speak(const std::string& message, bool allies_only) +bool chat_handler::do_speak(const std::string& message, bool allies_only) { if (message.empty() || message == "/") { - return; + return false; } bool is_command = (message[0] == '/'); bool quoted_command = (is_command && message[1] == ' '); if (!is_command) { send_chat_message(message, allies_only); - return; + return true; } else if (quoted_command) { send_chat_message(std::string(message.begin() + 2, message.end()), allies_only); - return; + return true; } std::string cmd(message.begin() + 1, message.end()); chat_command_handler cch(*this, allies_only); - cch.dispatch(cmd); + return cch.dispatch(cmd); } void chat_handler::user_relation_changed(const std::string& /*name*/) diff --git a/src/chat_events.hpp b/src/chat_events.hpp index 223828383f9..4c9461c1844 100644 --- a/src/chat_events.hpp +++ b/src/chat_events.hpp @@ -34,7 +34,7 @@ public: virtual void send_to_server(const config& cfg) = 0; protected: - void do_speak(const std::string& message, bool allies_only=false); + bool do_speak(const std::string& message, bool allies_only=false); //called from do_speak virtual void add_chat_message(const std::time_t& time, diff --git a/src/map_command_handler.hpp b/src/map_command_handler.hpp index e4494222614..81547487f60 100644 --- a/src/map_command_handler.hpp +++ b/src/map_command_handler.hpp @@ -158,7 +158,7 @@ public: return command_map_.empty(); } //actual work function - void dispatch(std::string cmd) + bool dispatch(std::string cmd) { if (empty()) { init_map_default(); @@ -177,59 +177,61 @@ public: } if (get_cmd().empty()) { - return; + return false; } if (const command* c = get_command(get_cmd())) { if (is_enabled(*c)) { (static_cast(this)->*(c->handler))(); + return true; } else { print(get_cmd(), _("This command is currently unavailable.")); + return false; } } - else if (help_on_unknown_) { - utils::string_map symbols; - if(!cmd_flag_) { - symbols["help_command"] = cmd_prefix_ + "help"; - symbols["command"] = cmd_prefix_ + get_cmd(); - } - else { - symbols["help_command"] = "help"; - symbols["command"] = get_cmd(); - } - std::string string_user = get_cmd(); - int distance = 0; - // Minimum length of the two compared strings. - int len_min = 0; - bool has_command_proposal = false; - // Compare the input with every command (excluding alias). - for(const auto& [key, index] : command_map_) { - // No need to test commands that are not enabled. - if(is_enabled(index)) { - distance = edit_distance_approx(string_user, key); - len_min = std::min(string_user.length(), key.length()); - // Maximum of a third of the letters are wrong. The ratio - // between the edit distance and the minimum length, multiplied - // by a hundred gives us the percentage of errors. - if(distance * 100 / len_min < 34) { - symbols["command_proposal"] = key; - has_command_proposal = true; - // If a good enough candidate is found, exit the loop. - break; - } + + utils::string_map symbols; + if(!cmd_flag_) { + symbols["help_command"] = cmd_prefix_ + "help"; + symbols["command"] = cmd_prefix_ + get_cmd(); + } + else { + symbols["help_command"] = "help"; + symbols["command"] = get_cmd(); + } + std::string string_user = get_cmd(); + int distance = 0; + // Minimum length of the two compared strings. + int len_min = 0; + bool has_command_proposal = false; + // Compare the input with every command (excluding alias). + for(const auto& [key, index] : command_map_) { + // No need to test commands that are not enabled. + if(is_enabled(index)) { + distance = edit_distance_approx(string_user, key); + len_min = std::min(string_user.length(), key.length()); + // Maximum of a third of the letters are wrong. The ratio + // between the edit distance and the minimum length, multiplied + // by a hundred gives us the percentage of errors. + if(distance * 100 / len_min < 34) { + symbols["command_proposal"] = key; + has_command_proposal = true; + // If a good enough candidate is found, exit the loop. + break; } } - // If a proposal for a command is found, print it - if(has_command_proposal) { - print("help", VGETTEXT("Unknown command ‘$command’, did you mean ‘$command_proposal’? try $help_command " - "for a list of available commands.", symbols)); - } - else { - print("help", VGETTEXT("Unknown command ‘$command’, try $help_command " - "for a list of available commands.", symbols)); - } } + // If a proposal for a command is found, print it + if(has_command_proposal) { + print("help", VGETTEXT("Unknown command ‘$command’, did you mean ‘$command_proposal’? try $help_command " + "for a list of available commands.", symbols)); + } + else { + print("help", VGETTEXT("Unknown command ‘$command’, try $help_command " + "for a list of available commands.", symbols)); + } + return false; } std::vector get_commands_list() const @@ -399,11 +401,6 @@ protected: } cmd_arg_parser cap_; protected: - //show a "try help" message on unknown command? - static void set_help_on_unknown(bool value) - { - help_on_unknown_ = value; - } //this is display-only static void set_cmd_prefix(const std::string& value) { @@ -449,7 +446,6 @@ protected: private: static inline command_map command_map_ {}; static inline command_alias_map command_alias_map_ {}; - static inline bool help_on_unknown_ = true; static inline bool show_unavailable_ = false; static inline std::string cmd_prefix_ {}; static inline bool cmd_flag_ = false; diff --git a/src/menu_events.cpp b/src/menu_events.cpp index 32b51b644a9..8dd4ef27f1b 100644 --- a/src/menu_events.cpp +++ b/src/menu_events.cpp @@ -1000,11 +1000,11 @@ void menu_handler::search() textbox_info_.show(gui::TEXTBOX_SEARCH, msg.str(), "", false, *gui_); } -void menu_handler::do_speak() +bool menu_handler::do_speak() { // None of the two parameters really needs to be passed since the information belong to members of the class. // But since it makes the called method more generic, it is done anyway. - chat_handler::do_speak( + return chat_handler::do_speak( textbox_info_.box()->text(), textbox_info_.check() != nullptr ? textbox_info_.check()->checked() : false); } diff --git a/src/menu_events.hpp b/src/menu_events.hpp index c053ecf2bad..5637fa692c6 100644 --- a/src/menu_events.hpp +++ b/src/menu_events.hpp @@ -115,7 +115,7 @@ public: /** @return Whether or not the recruit was successful */ bool do_recruit(const std::string& name, int side_num, map_location& target_hex); - void do_speak(); + bool do_speak(); void do_search(const std::string& new_search); void do_command(const std::string& str); void do_ai_formula(const std::string& str, int side_num, mouse_handler& mousehandler); diff --git a/src/play_controller.cpp b/src/play_controller.cpp index f8a8c644e21..47a8ac1b0d5 100644 --- a/src/play_controller.cpp +++ b/src/play_controller.cpp @@ -681,8 +681,9 @@ void play_controller::enter_textbox() menu_handler_.get_textbox().close(); break; case gui::TEXTBOX_MESSAGE: - menu_handler_.do_speak(); - menu_handler_.get_textbox().close(); // need to close that one after executing do_speak() ! + if (menu_handler_.do_speak()) { + menu_handler_.get_textbox().close(); + } break; case gui::TEXTBOX_COMMAND: menu_handler_.get_textbox().memorize_command(str);