16 #define GETTEXT_DOMAIN "wesnoth-lib"
47 #include <readline/history.h>
51 #define DBG_LUA LOG_STREAM(debug, log_lua_int)
52 #define LOG_LUA LOG_STREAM(info, log_lua_int)
53 #define WRN_LUA LOG_STREAM(warn, log_lua_int)
54 #define ERR_LUA LOG_STREAM(err, log_lua_int)
69 view() : msg_label(nullptr), window_(nullptr) {}
74 msg_label = find_widget<scroll_label>(&
window,
"msg",
false,
true);
120 DBG_LUA <<
"constructing a lua_interpreter::model";
131 DBG_LUA <<
"finished constructing a lua_interpreter::model";
136 DBG_LUA <<
"destroying a lua_interpreter::model";
141 bool execute(
const std::string & cmd);
204 const std::size_t history_max = 500;
206 append_history (history_max,
filename_.c_str());
211 history_truncate_file (
filename_.c_str(), history_max);
212 }
catch (...) {
PLAIN_LOG <<
"Swallowed an exception when trying to write lua command line history";}
218 add_history(str.c_str());
225 LOG_LUA <<
"maybe update prefix";
234 std::string
search([[maybe_unused]]
int direction ) {
236 LOG_LUA <<
"searching in direction " << direction <<
" from position " << where_history();
238 HIST_ENTRY *
e =
nullptr;
242 history_set_pos(history_length);
245 int result = history_search_prefix(
prefix_.c_str(), direction);
247 e = current_history();
250 e = previous_history();
254 e = (direction > 0) ? next_history() : previous_history();
256 int result = history_search_prefix(
prefix_.c_str(), direction);
258 e = current_history();
267 LOG_LUA <<
"found something at " << where_history();
268 std::string ret =
e->line;
274 LOG_LUA <<
"didn't find anything";
287 return "Cleared history.";
289 return "History is disabled, you did not compile with GNU history support.";
295 HIST_ENTRY **the_list;
297 the_list = history_list ();
300 return "History is empty.";
304 for (
int i = 0; the_list[
i];
i++) {
305 result += std::to_string(
i+history_base);
307 result += the_list[
i]->line;
312 return "Couldn't find history.";
315 return "History is disabled, you did not compile with GNU history support.";
334 const std::unique_ptr<lua_interpreter::lua_model>
lua_model_;
336 const std::unique_ptr<lua_interpreter::view>
view_;
340 void search(
int direction);
360 const SDL_Keycode key,
374 LOG_LUA <<
"lua_interpreter::model::execute...";
388 raw_log_ <<
msg <<
'\n';
398 LOG_LUA <<
"lua_interpreter update_view...";
402 view_->update_contents(lua_model_->get_log());
404 LOG_LUA <<
"lua_interpreter update_view finished";
410 LOG_LUA <<
"Entering lua_interpreter::controller::bind";
414 text_entry = find_widget<text_box>(&
window,
"text_entry",
false,
true);
425 std::placeholders::_3,
426 std::placeholders::_4,
427 std::placeholders::_5,
430 copy_button = find_widget<button>(&
window,
"copy",
false,
true);
437 clear_button = find_widget<button>(&
window,
"clear",
false,
true);
445 copy_button->set_active(
false);
446 copy_button->set_tooltip(
_(
"Clipboard support not found, contact your packager"));
449 LOG_LUA <<
"Exiting lua_interpreter::controller::bind";
463 lua_model_->clear_log();
465 view_->update_contents(
"");
471 const SDL_Keycode key,
477 LOG_LUA <<
"keypress_callback";
478 if(key == SDLK_RETURN || key == SDLK_KP_ENTER) {
488 LOG_LUA <<
"finished executing";
489 }
else if(key == SDLK_TAB) {
493 }
else if(key == SDLK_UP) {
497 }
else if(key == SDLK_DOWN) {
501 }
else if(key == SDLK_PAGEUP) {
505 }
else if(key == SDLK_PAGEDOWN) {
514 std::string cmd = text_entry->get_value();
515 if (cmd.empty())
return;
517 cmd.erase(cmd.find_last_not_of(
" \n\r\t")+1);
519 LOG_LUA <<
"Executing '"<< cmd <<
"'";
521 if (cmd.size() >= 13 && (cmd.substr(0,13) ==
"history clear" || cmd.substr(0,13) ==
"clear history")) {
522 lua_model_->add_dialog_message(input_model_->clear_history());
523 text_entry->set_value(
"");
528 if (cmd.size() >= 7 && (cmd.substr(0,7) ==
"history")) {
529 lua_model_->add_dialog_message(input_model_->list_history());
530 text_entry->set_value(
"");
535 if (lua_model_->execute(cmd)) {
536 input_model_->add_to_history(cmd);
537 text_entry->set_value(
"");
544 std::string text = text_entry->get_value();
547 std::size_t prefix_end_pos = text.find_last_of(
" (");
548 if (prefix_end_pos != std::string::npos) {
549 prefix = text.substr(0, prefix_end_pos + 1);
550 text = text.substr(prefix_end_pos + 1);
553 static std::vector<std::string> static_matches {
573 std::vector<std::string> matches;
575 if (text.find(
'.') == std::string::npos) {
576 matches = lua_model_->get_globals();
577 matches.insert(matches.end(), static_matches.begin(), static_matches.end());
579 matches = lua_model_->get_attribute_names(text);
583 if (text.size() > 0) {
587 if(matches.empty()) {
594 if (matches.size() > 1) {
597 const std::size_t wrap_limit = 80;
600 for (std::size_t idx = 0; idx < matches.size(); ++idx) {
601 if (buffer.size() + 1 + matches.at(idx).size() > wrap_limit) {
602 lua_model_->add_dialog_message(buffer);
603 buffer = matches.at(idx);
606 buffer += (
" " + matches.at(idx));
608 buffer = matches.at(idx);
613 lua_model_->add_dialog_message(buffer);
616 text_entry->set_value(prefix + text);
621 std::string current_text = text_entry->get_value();
622 input_model_->maybe_update_prefix(current_text);
623 text_entry->set_value(input_model_->search(direction));
626 lua_model_->add_dialog_message(
"History is disabled, you did not compile with GNU history support.");
636 #ifndef ALWAYS_HAVE_LUA_CONSOLE
639 const std::string&
message =
_(
"The lua console can only be used in debug mode! (Run ':debug' first)");
645 ERR_LUA <<
"Tried to open console with a null lua kernel pointer.";
664 LOG_LUA <<
"Entering lua_interpreter::view::pre_show";
668 label *kernel_type_label = find_widget<label>(&
window,
"kernel_type",
false,
true);
673 LOG_LUA <<
"Exiting lua_interpreter::view::pre_show";
680 LOG_LUA <<
"entering lua_interpreter ctor...";
681 LOG_LUA <<
"finished lua_interpreter ctor...";
void add_chat_message(const std::time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
display_chat_manager & get_chat_manager()
The controller is responsible to hold all the input widgets, and a pointer to the model and view.
void handle_clear_button_clicked(window &window)
Clear the text.
void search(int direction)
void handle_copy_button_clicked(window &window)
Copy text to the clipboard.
void update_view()
Update the view based on the model.
const std::unique_ptr< lua_interpreter::view > view_
void input_keypress_callback(bool &handled, bool &halt, const SDL_Keycode key, window &window)
Handle return key (execute) or tab key (tab completion)
const std::unique_ptr< lua_interpreter::lua_model > lua_model_
void bind(window &window)
Bind my pointers to the widgets found in the window.
const std::unique_ptr< lua_interpreter::input_model > input_model_
controller(lua_kernel_base &lk)
The lua model is responsible to interact with the lua kernel base and keep track of what should be di...
lua_model(lua_kernel_base &lk)
void clear_log()
Clear the console log.
bool execute(const std::string &cmd)
Ask the lua kernel to execute a command.
std::vector< std::string > get_globals()
std::stringstream raw_log_
std::string get_log() const
Get the log string.
std::string get_name() const
Get a string describing the name of lua kernel.
void add_dialog_message(const std::string &msg)
Add a message from the dialog, formatted in blue to distinguish from issued commands.
std::string get_raw_log() const
Get the unescaped log.
std::vector< std::string > get_attribute_names(const std::string &s)
void bind(window &window)
Bind the scroll label widget to my pointer, and configure.
void update_contents(const std::string &str)
Update the scroll label contents.
static void display(lua_kernel_base *lk)
Display a new console, using given video and lua kernel.
virtual const std::string & window_id() const override
The ID of the window to build.
const std::unique_ptr< controller > controller_
lua_interpreter(lua_kernel_base &lk)
virtual void pre_show(window &window) override
Bind the controller, initialize one of the static labels with info about this kernel,...
Main class to show messages to the user.
Abstract base class for all modal dialogs.
field_text * register_text(const std::string &id, const bool mandatory, const std::function< std::string()> callback_load_value=nullptr, const std::function< void(const std::string &)> callback_save_value=nullptr, const bool capture_focus=false)
Creates a new text field.
A widget that allows the user to input text in single line.
base class of top level items, the only item which needs to store the final canvases to draw on.
void set_enter_disabled(const bool enter_disabled)
Disable the enter key.
void keyboard_capture(widget *widget)
void set_click_dismiss(const bool click_dismiss)
void set_external_log(external_log_type lg)
std::vector< std::string > get_global_var_names()
Get tab completion strings.
void interactive_run(char const *prog)
Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it nor...
std::vector< std::string > get_attribute_names(const std::string &var_path)
Gets all attribute names of an extended variable name.
const std::stringstream & get_log()
Access / manipulate logging of lua kernel activities.
virtual std::string my_name()
User-visible name of the lua kernel that they are talking to.
game_display & get_display() override
Get a reference to a display member a derived class uses.
static plugins_manager * get()
Declarations for File-IO.
static std::string _(const char *str)
Standard logging facilities (interface).
static lg::log_domain log_lua_int("lua/interpreter")
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
bool available()
Whether wesnoth was compiled with support for a clipboard.
static bool file_exists(const bfs::path &fpath)
std::string get_lua_history_file()
std::string escape_text(const std::string &text)
Escapes the pango markup characters in a text.
REGISTER_DIALOG(editor_edit_unit)
void connect_signal_pre_key_press(dispatcher &dispatcher, const signal_keyboard &signal)
Connects the signal for 'snooping' on the keypress.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
game_lua_kernel * lua_kernel
play_controller * controller
bool word_completion(std::string &text, std::vector< std::string > &wordlist)
Try to complete the last word of 'text' with the 'wordlist'.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
static std::string flush(std::ostringstream &s)
Error used to report an error in a lua script or in the lua interpreter.
static map_location::DIRECTION s