The Battle for Wesnoth  1.19.0-dev
lua_interpreter.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
3  by Chris Beck <render787@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
19 
21 #include "gui/widgets/button.hpp"
22 #include "gui/widgets/label.hpp"
24 #include "gui/widgets/text_box.hpp"
25 #include "gui/widgets/window.hpp"
26 
27 #include "desktop/clipboard.hpp"
28 #include "game_config.hpp"
29 #include "game_errors.hpp"
30 #include "gettext.hpp"
31 #include "play_controller.hpp"
32 #include "resources.hpp" //for help fetching lua kernel pointers
33 #include "scripting/plugins/manager.hpp" //needed for the WHICH_KERNEL version of display
34 #include "scripting/game_lua_kernel.hpp" //needed for the WHICH_KERNEL version of display
37 #include "log.hpp"
38 #include "font/pango/escape.hpp"
39 
40 #include <sstream>
41 #include <string>
42 #include <vector>
43 #include <functional>
44 
45 #ifdef HAVE_HISTORY
46 #include "filesystem.hpp"
47 #include <readline/history.h>
48 #endif
49 
50 static lg::log_domain log_lua_int("lua/interpreter");
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)
55 
56 namespace gui2::dialogs
57 {
58 
59 REGISTER_DIALOG(lua_interpreter)
60 
61 // Model, View, Controller definitions
62 
64 private:
65  scroll_label* msg_label; //the view is extremely simple, it's pretty much just this one widget that gets updated
67 
68 public:
69  view() : msg_label(nullptr), window_(nullptr) {}
70 
71  /** Bind the scroll label widget to my pointer, and configure */
72  void bind(window& window) {
73  window_ = &window;
74  msg_label = find_widget<scroll_label>(&window, "msg", false, true);
75  msg_label->set_use_markup(true);
77  msg_label->set_label("");
78  }
79 
80  /** Update the scroll label contents */
81  void update_contents(const std::string & str)
82  {
83  assert(msg_label);
84  msg_label->set_label(str);
86  }
87 
88  void pg_up()
89  {
90  assert(msg_label);
92  }
93 
94  void pg_down()
95  {
96  assert(msg_label);
98  }
99 };
100 
101 /**
102  * The lua model is responsible to interact with the lua kernel base and keep track of what should be displayed in the console.
103  * It registers its stringstream with the lua kernel when it is created, and unregisters when it is destroyed.
104  *
105  * It is responsible to execute commands as strings, or add dialog messages for the user. It is also responsible to ask
106  * the lua kernel for help with tab completion.
107  */
109 private:
111  std::stringstream log_;
112  std::stringstream raw_log_;
113 
114 public:
116  : L_(lk)
117  , log_()
118  , raw_log_()
119  {
120  DBG_LUA << "constructing a lua_interpreter::model";
121  //DBG_LUA << "incoming:\n" << lk.get_log().rdbuf() << "\n.";
122  log_ << font::escape_text(lk.get_log().str()) << std::flush;
123  raw_log_ << lk.get_log().str() << std::flush;
124  // Lua kernel sends log strings to this function
125  L_.set_external_log([this](const std::string & str) {
126  log_ << font::escape_text(str);
127  raw_log_ << str;
128  });
129  //DBG_LUA << "received:\n" << log_.str() << "\n.";
130 
131  DBG_LUA << "finished constructing a lua_interpreter::model";
132  }
133 
135  {
136  DBG_LUA << "destroying a lua_interpreter::model";
137  L_.set_external_log(nullptr); //deregister our log since it's about to be destroyed
138  }
139 
140  /** Ask the lua kernel to execute a command. No throw of game::lua_error, instead the error message is formatted and printed to console.*/
141  bool execute(const std::string & cmd);
142 
143  /** Add a message from the dialog, formatted in blue to distinguish from issued commands.
144  * This message gets put in the interpreter log, but does not get entered in the kernel log, so if the window is closed this message will
145  * not appear the next time it is opened.
146  **/
147  void add_dialog_message(const std::string & msg);
148 
149  /** Get the log string */
150  std::string get_log() const { return log_.str(); }
151  /** Get the unescaped log */
152  std::string get_raw_log() const { return raw_log_.str(); }
153  /** Get a string describing the name of lua kernel */
154  std::string get_name() const { return L_.my_name(); }
155 
156  /** Clear the console log */
157  void clear_log() {
158  L_.clear_log();
159  log_.str("");
160  log_.clear();
161  raw_log_.str("");
162  raw_log_.clear();
163  }
164 
165  //* Tab completion: Get list of presently defined global variables */
166  std::vector<std::string> get_globals() { return L_.get_global_var_names(); }
167  //* Tab completion: Get list of attributes for variable corresponding to this path. */
168  std::vector<std::string> get_attribute_names(const std::string & s) { return L_.get_attribute_names(s); }
169 };
170 
171 /**
172  * The input_model keeps track of what commands were executed before, and figures out what
173  * should be displayed when the user presses up / down arrows in the input.
174  * It is essentially part of the model, but it isn't connected to the lua kernel so I have implemented it
175  * separately. Putatively it could all be refactored so that there is a single model with private subclass "lua_model"
176  * and also a "command_history_model" but I have decided simply to not implement it that way.
177  */
179 private:
180  std::string prefix_;
182 #ifdef HAVE_HISTORY
183  std::string filename_;
184 #endif
185 
186 public:
188  : prefix_()
189  , end_of_history_(true)
190 #ifdef HAVE_HISTORY
191  , filename_(filesystem::get_user_config_dir() + "/lua_command_history")
192  {
193  using_history();
194  read_history (filename_.c_str());
195  }
196 #else
197  {}
198 #endif
199 
200 #ifdef HAVE_HISTORY
201  ~input_model()
202  {
203  try {
204  const std::size_t history_max = 500;
206  append_history (history_max,filename_.c_str());
207  } else {
208  write_history (filename_.c_str());
209  }
210 
211  history_truncate_file (filename_.c_str(), history_max);
212  } catch (...) { PLAIN_LOG << "Swallowed an exception when trying to write lua command line history";}
213  }
214 #endif
215  void add_to_history ([[maybe_unused]] const std::string& str) {
216  prefix_ = "";
217 #ifdef HAVE_HISTORY
218  add_history(str.c_str());
219 #endif
220  end_of_history_ = true;
221 
222  }
223 
224  void maybe_update_prefix (const std::string & text) {
225  LOG_LUA << "maybe update prefix";
226  LOG_LUA << "prefix_: '"<< prefix_ << "'\t text='"<< text << "'";
227 
228  if (!end_of_history_) return;
229 
230  prefix_ = text;
231  LOG_LUA << "updated prefix";
232  }
233 
234  std::string search([[maybe_unused]] int direction ) {
235 #ifdef HAVE_HISTORY
236  LOG_LUA << "searching in direction " << direction << " from position " << where_history();
237 
238  HIST_ENTRY * e = nullptr;
239  if (end_of_history_) {
240  // if the direction is > 0, do nothing because searching down only takes place when we are in the history records.
241  if (direction < 0) {
242  history_set_pos(history_length);
243 
244  if (prefix_.size() > 0) {
245  int result = history_search_prefix(prefix_.c_str(), direction);
246  if (result == 0) {
247  e = current_history();
248  }
249  } else {
250  e = previous_history();
251  }
252  }
253  } else {
254  e = (direction > 0) ? next_history() : previous_history();
255  if (prefix_.size() > 0 && e) {
256  int result = history_search_prefix(prefix_.c_str(), direction);
257  if (result == 0) {
258  e = current_history();
259  } else {
260  e = nullptr; // if the search misses, it leaves the state as it was, which might not have been on an entry matching prefix.
261  end_of_history_ = true; // we actually want to force it to be null and treat as off the end of history in this case.
262  }
263  }
264  }
265 
266  if (e) {
267  LOG_LUA << "found something at " << where_history();
268  std::string ret = e->line;
269  end_of_history_ = false;
270  return ret;
271  }
272 #endif
273 
274  LOG_LUA << "didn't find anything";
275 
276  // reset, set history to the end and prefix_ to empty, and return the current prefix_ for the user to edit
277  end_of_history_ = true;
278  std::string temp = prefix_;
279  prefix_ = "";
280  return temp;
281  }
282 
283  std::string clear_history() {
284 #ifdef HAVE_HISTORY
285  ::clear_history();
286  write_history (filename_.c_str());
287  return "Cleared history.";
288 #else
289  return "History is disabled, you did not compile with GNU history support.";
290 #endif
291  }
292 
293  std::string list_history() {
294 #ifdef HAVE_HISTORY
295  HIST_ENTRY **the_list;
296 
297  the_list = history_list ();
298  if (the_list) {
299  if (!*the_list) {
300  return "History is empty.";
301  }
302 
303  std::string result;
304  for (int i = 0; the_list[i]; i++) {
305  result += std::to_string(i+history_base);
306  result += ": ";
307  result += the_list[i]->line;
308  result += "\n";
309  }
310  return result;
311  } else {
312  return "Couldn't find history.";
313  }
314 #else
315  return "History is disabled, you did not compile with GNU history support.";
316 #endif
317  }
318 
319  // Does history expansion in a command line. A return value of true indicates an error,
320  // the error message will be returned in the string argument. A return value of false
321  // indicates success and that execution should proceed.
322  bool do_history_expansion ([[maybe_unused]] std::string & cmd) {
323 #ifdef HAVE_HISTORY
324  // Do history expansions
325  std::unique_ptr<char[]> cmd_cstr(new char[cmd.length()+1]);
326  strcpy (cmd_cstr.get(), cmd.c_str());
327 
328  char * expansion;
329 
330  int result = history_expand(cmd_cstr.get(), &expansion);
331 
332  if (result < 0 || result == 2) {
333  cmd = expansion; // return error message in cmd var
334  free(expansion);
335  return true;
336  }
337 
338  cmd = expansion;
339  free(expansion);
340 #endif
341  return false;
342  }
343 };
344 
345 /**
346  * The controller is responsible to hold all the input widgets, and a pointer to the model and view.
347  * It is responsible to bind the input signals to appropriate handler methods, which it holds.
348  * It is also responsible to ask the view to update based on the output of the model, typically in
349  * response to some input.
350  */
352 private:
355 
357  std::string text_entry_;
358 
359  const std::unique_ptr<lua_interpreter::lua_model> lua_model_;
360  const std::unique_ptr<lua_interpreter::input_model> input_model_;
361  const std::unique_ptr<lua_interpreter::view> view_;
362 
363  void execute();
364  void tab();
365  void search(int direction);
366 public:
368  : copy_button(nullptr)
369  , clear_button(nullptr)
370  , text_entry(nullptr)
371  , text_entry_()
374  , view_(new lua_interpreter::view())
375  {}
376 
377  /** Bind my pointers to the widgets found in the window */
378  void bind(window& window);
379 
382 
383  void input_keypress_callback(bool& handled,
384  bool& halt,
385  const SDL_Keycode key,
386  window& window);
387 
388  /** Update the view based on the model */
389  void update_view();
390 
391  friend class lua_interpreter;
392 };
393 
394 // Model impl
395 
396 /** Execute a command, and report any errors encountered. */
397 bool lua_interpreter::lua_model::execute (const std::string & cmd)
398 {
399  LOG_LUA << "lua_interpreter::model::execute...";
400 
401  try {
402  L_.interactive_run(cmd.c_str());
403  return true;
404  } catch (const game::lua_error & e) {
405  add_dialog_message(std::string(e.what()));
406  return false;
407  }
408 }
409 
410 /** Add a dialog message, which will appear in blue. */
412  log_ << "<span color='#8888FF'>" << font::escape_text(msg) << "</span>\n";
413  raw_log_ << msg << '\n';
414 }
415 
416 // View impl
417 
418 // Controller impl
419 
420 /** Update the view based on the model. */
422 {
423  LOG_LUA << "lua_interpreter update_view...";
424  assert(lua_model_);
425  assert(view_);
426 
427  view_->update_contents(lua_model_->get_log());
428 
429  LOG_LUA << "lua_interpreter update_view finished";
430 }
431 
432 /** Find all the widgets managed by the controller and connect them to handler methods. */
434 {
435  LOG_LUA << "Entering lua_interpreter::controller::bind";
436  assert(view_);
437  view_->bind(window);
438 
439  text_entry = find_widget<text_box>(&window, "text_entry", false, true);
440  //text_entry->set_text_changed_callback(
441  // std::bind(&view::filter, this, std::ref(window)));
442  window.keyboard_capture(text_entry);
443  window.set_click_dismiss(false);
445 
447  *text_entry,
449  this,
450  std::placeholders::_3,
451  std::placeholders::_4,
452  std::placeholders::_5,
453  std::ref(window)));
454 
455  copy_button = find_widget<button>(&window, "copy", false, true);
457  *copy_button,
459  this,
460  std::ref(window)));
461 
462  clear_button = find_widget<button>(&window, "clear", false, true);
464  *clear_button,
466  this,
467  std::ref(window)));
468 
470  copy_button->set_active(false);
471  copy_button->set_tooltip(_("Clipboard support not found, contact your packager"));
472  }
473 
474  LOG_LUA << "Exiting lua_interpreter::controller::bind";
475 }
476 
477 /** Copy text to the clipboard */
479 {
480  assert(lua_model_);
481  desktop::clipboard::copy_to_clipboard(lua_model_->get_raw_log(), false);
482 }
483 
484 /** Clear the text */
486 {
487  assert(lua_model_);
488  lua_model_->clear_log();
489  assert(view_);
490  view_->update_contents("");
491 }
492 
493 /** Handle return key (execute) or tab key (tab completion) */
495  bool& halt,
496  const SDL_Keycode key,
497  window& window)
498 {
499  assert(lua_model_);
500  assert(text_entry);
501 
502  LOG_LUA << "keypress_callback";
503  if(key == SDLK_RETURN || key == SDLK_KP_ENTER) { // handle executing whatever is in the command entry field
504  LOG_LUA << "executing...";
505  execute();
506  handled = true;
507  halt = true;
508 
509  // Commands such as `wesnoth.interface.zoom` might cause the display to redraw and leave the window half-drawn.
510  // This preempts that.
512 
513  LOG_LUA << "finished executing";
514  } else if(key == SDLK_TAB) { // handle tab completion
515  tab();
516  handled = true;
517  halt = true;
518  } else if(key == SDLK_UP) {
519  search(-1);
520  handled = true;
521  halt = true;
522  } else if(key == SDLK_DOWN) {
523  search(1);
524  handled = true;
525  halt = true;
526  } else if(key == SDLK_PAGEUP) {
527  view_->pg_up();
528  handled = true;
529  halt = true;
530  } else if(key == SDLK_PAGEDOWN) {
531  view_->pg_down();
532  handled = true;
533  halt = true;
534  }
535 }
536 
538 {
539  std::string cmd = text_entry->get_value();
540  if (cmd.empty()) return; //don't bother with empty string
541 
542  cmd.erase(cmd.find_last_not_of(" \n\r\t")+1); //right trim the string
543 
544  LOG_LUA << "Executing '"<< cmd << "'";
545 
546  if (cmd.size() >= 13 && (cmd.substr(0,13) == "history clear" || cmd.substr(0,13) == "clear history")) {
547  lua_model_->add_dialog_message(input_model_->clear_history());
548  text_entry->set_value("");
549  update_view();
550  return;
551  }
552 
553  if (cmd.size() >= 7 && (cmd.substr(0,7) == "history")) {
554  lua_model_->add_dialog_message(input_model_->list_history());
555  text_entry->set_value("");
556  update_view();
557  return;
558  }
559 
560  if (input_model_->do_history_expansion(cmd)) {
561  lua_model_->add_dialog_message(cmd);
562  update_view();
563  return;
564  }
565 
566  if (lua_model_->execute(cmd)) {
567  input_model_->add_to_history(cmd);
568  text_entry->set_value("");
569  }
570  update_view();
571 }
572 
574 {
575  std::string text = text_entry->get_value();
576 
577  std::string prefix;
578  std::size_t prefix_end_pos = text.find_last_of(" (");
579  if (prefix_end_pos != std::string::npos) {
580  prefix = text.substr(0, prefix_end_pos + 1);
581  text = text.substr(prefix_end_pos + 1);
582  }
583 
584  static std::vector<std::string> static_matches {
585  "and",
586  "break",
587  "else",
588  "elseif",
589  "end",
590  "false",
591  "for",
592  "function",
593  "local",
594  "nil",
595  "not",
596  "repeat",
597  "return",
598  "then",
599  "true",
600  "until",
601  "while"
602  };
603 
604  std::vector<std::string> matches;
605 
606  if (text.find('.') == std::string::npos) {
607  matches = lua_model_->get_globals();
608  matches.insert(matches.end(), static_matches.begin(), static_matches.end());
609  } else {
610  matches = lua_model_->get_attribute_names(text);
611  }
612 
613  //bool line_start = utils::word_completion(text, matches);
614  if (text.size() > 0) { // this if is to avoid weird behavior in word_completion, where it thinks nothing matches the empty string
615  utils::word_completion(text, matches);
616  }
617 
618  if(matches.empty()) {
619  return;
620  }
621 
622  //if(matches.size() == 1) {
623  //text.append(" "); //line_start ? ": " : " ");
624  //} else {
625  if (matches.size() > 1) {
626  //std::string completion_list = utils::join(matches, " ");
627 
628  const std::size_t wrap_limit = 80;
629  std::string buffer;
630 
631  for (std::size_t idx = 0; idx < matches.size(); ++idx) {
632  if (buffer.size() + 1 + matches.at(idx).size() > wrap_limit) {
633  lua_model_->add_dialog_message(buffer);
634  buffer = matches.at(idx);
635  } else {
636  if (buffer.size()) {
637  buffer += (" " + matches.at(idx));
638  } else {
639  buffer = matches.at(idx);
640  }
641  }
642  }
643 
644  lua_model_->add_dialog_message(buffer);
645  update_view();
646  }
647  text_entry->set_value(prefix + text);
648 }
649 
651 {
652  std::string current_text = text_entry->get_value();
653  input_model_->maybe_update_prefix(current_text);
654  text_entry->set_value(input_model_->search(direction));
655 
656 #ifndef HAVE_HISTORY
657  lua_model_->add_dialog_message("History is disabled, you did not compile with GNU history support.");
658  update_view();
659 #endif
660 
661 }
662 
663 // Dialog implementation
664 
665 /** Display a new console, using given video and lua kernel */
667 #ifndef ALWAYS_HAVE_LUA_CONSOLE
670  const std::string& message = _("The lua console can only be used in debug mode! (Run ':debug' first)");
671  chat_man.add_chat_message(time(nullptr), _("lua console"), 0, message, events::chat_handler::MESSAGE_PRIVATE, false);
672  return;
673  }
674 #endif
675  if (!lk) {
676  ERR_LUA << "Tried to open console with a null lua kernel pointer.";
677  return;
678  }
679 
680  lua_interpreter(*lk).show();
681 }
682 
683 /** Helper function to assist those callers which don't want to include resources.hpp */
685  if (which == lua_interpreter::APP) {
686  display(plugins_manager::get()->get_kernel_base());
687  } else if (which == lua_interpreter::GAME) {
689  }
690 }
691 
692 /** Bind the controller, initialize one of the static labels with info about this kernel, and update the view. */
694 {
695  LOG_LUA << "Entering lua_interpreter::view::pre_show";
696  register_text("text_entry", false, controller_->text_entry_, true);
697  controller_->bind(window);
698 
699  label *kernel_type_label = find_widget<label>(&window, "kernel_type", false, true);
700  kernel_type_label->set_label(controller_->lua_model_->get_name());
701 
702  controller_->update_view();
703  //window.invalidate_layout(); // workaround for assertion failure
704  LOG_LUA << "Exiting lua_interpreter::view::pre_show";
705 }
706 
710 {
711  LOG_LUA << "entering lua_interpreter ctor...";
712  LOG_LUA << "finished lua_interpreter ctor...";
713 }
714 
715 } // namespace dialogs
std::string filename_
Definition: action_wml.cpp:538
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()
Simple push button.
Definition: button.hpp:36
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 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_
The input_model keeps track of what commands were executed before, and figures out what should be dis...
bool do_history_expansion([[maybe_unused]] std::string &cmd)
void add_to_history([[maybe_unused]] const std::string &str)
void maybe_update_prefix(const std::string &text)
std::string search([[maybe_unused]] int direction)
The lua model is responsible to interact with the lua kernel base and keep track of what should be di...
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::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.
Definition: message.hpp:36
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 label displays text that can be wrapped but no scrollbars are provided.
Definition: label.hpp:56
Label showing a text.
virtual void set_label(const t_string &label) override
See styled_widget::set_label.
virtual void set_use_markup(bool use_markup) override
See styled_widget::set_use_markup.
@ END
Go to the end position.
Definition: scrollbar.hpp:58
@ JUMP_BACKWARDS
Go the visible items towards the begin.
Definition: scrollbar.hpp:57
void scroll_vertical_scrollbar(const scrollbar_base::scroll_mode scroll)
Scrolls the vertical scrollbar.
@ ALWAYS_VISIBLE
The scrollbar is always shown, whether needed or not.
void set_vertical_scrollbar_mode(const scrollbar_mode scrollbar_mode)
virtual void set_label(const t_string &text)
Class for a single line text area.
Definition: text_box.hpp:142
void queue_redraw()
Indicates that this widget should be redrawn.
Definition: widget.cpp:455
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:63
void set_enter_disabled(const bool enter_disabled)
Disable the enter key.
Definition: window.hpp:327
void keyboard_capture(widget *widget)
Definition: window.cpp:1215
void set_click_dismiss(const bool click_dismiss)
Definition: window.hpp:416
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()
Definition: manager.cpp:58
Declarations for File-IO.
std::size_t i
Definition: function.cpp:968
static std::string _(const char *str)
Definition: gettext.hpp:93
This file contains the window object, this object is a top level container which has the event manage...
Standard logging facilities (interface).
#define PLAIN_LOG
Definition: log.hpp:295
static lg::log_domain log_lua_int("lua/interpreter")
#define ERR_LUA
#define LOG_LUA
#define DBG_LUA
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:32
bool available()
Whether wesnoth was compiled with support for a clipboard.
Definition: clipboard.cpp:53
std::string get_user_config_dir()
Definition: filesystem.cpp:841
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:318
std::string escape_text(const std::string &text)
Escapes the pango markup characters in a text.
Definition: escape.hpp:33
const bool & debug
Definition: game_config.cpp:91
REGISTER_DIALOG(tod_new_schedule)
void connect_signal_pre_key_press(dispatcher &dispatcher, const signal_keyboard &signal)
Connects the signal for 'snooping' on the keypress.
Definition: dispatcher.cpp:172
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:177
game_lua_kernel * lua_kernel
Definition: resources.cpp:25
play_controller * controller
Definition: resources.cpp:21
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="")
Definition: debugger.cpp:109
static std::string flush(std::ostringstream &s)
Definition: reports.cpp:89
Error used to report an error in a lua script or in the lua interpreter.
Definition: game_errors.hpp:54
static map_location::DIRECTION s
#define e