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