The Battle for Wesnoth  1.15.0-dev
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/widgets/button.hpp"
23 #include "gui/widgets/label.hpp"
25 #include "gui/widgets/settings.hpp"
26 #include "gui/widgets/text_box.hpp"
27 #include "gui/widgets/window.hpp"
28 
29 #include "desktop/clipboard.hpp"
30 #include "game_config.hpp"
31 #include "game_errors.hpp"
32 #include "gettext.hpp"
33 #include "resources.hpp" //for help fetching lua kernel pointers
34 #include "scripting/plugins/manager.hpp" //needed for the WHICH_KERNEL version of display
35 #include "scripting/game_lua_kernel.hpp" //needed for the WHICH_KERNEL version of display
39 #include "lexical_cast.hpp"
40 #include "log.hpp"
41 #include "font/pango/escape.hpp"
42 
43 #include <sstream>
44 #include <string>
45 #include <vector>
46 #include "utils/functional.hpp"
47 
48 #ifdef HAVE_HISTORY
49 #include "filesystem.hpp"
50 #include <readline/history.h>
51 #endif
52 
53 static lg::log_domain log_lua_int("lua/interpreter");
54 #define DBG_LUA LOG_STREAM(debug, log_lua_int)
55 #define LOG_LUA LOG_STREAM(info, log_lua_int)
56 #define WRN_LUA LOG_STREAM(warn, log_lua_int)
57 #define ERR_LUA LOG_STREAM(err, log_lua_int)
58 
59 namespace gui2
60 {
61 namespace dialogs
62 {
63 
64 /*WIKI
65  * @page = GUIWindowDefinitionWML
66  * @order = 3_lua_interpretter
67  *
68  * == Settings manager ==
69  *
70  * This shows the settings manager
71  *
72  */
73 
74 
75 REGISTER_DIALOG(lua_interpreter)
76 
77 // Model, View, Controller definitions
78 
80 private:
81  scroll_label* msg_label; //the view is extremely simple, it's pretty much just this one widget that gets updated
83 
84 public:
85  view() : msg_label(nullptr), window_(nullptr) {}
86 
87  /** Bind the scroll label widget to my pointer, and configure */
88  void bind(window& window) {
89  window_ = &window;
90  msg_label = find_widget<scroll_label>(&window, "msg", false, true);
91  msg_label->set_use_markup(true);
93  msg_label->set_label("");
94  }
95 
96  /** Update the scroll label contents */
97  void update_contents(const std::string & str)
98  {
99  assert(msg_label);
100 
101  msg_label->set_label(str);
102  window_->set_callback_next_draw([this]()
103  {
105  });
106  }
107 
108  void pg_up()
109  {
110  assert(msg_label);
112  }
113 
114  void pg_down()
115  {
116  assert(msg_label);
118  }
119 };
120 
121 /**
122  * The lua model is responsible to interact with the lua kernel base and keep track of what should be displayed in the console.
123  * It registers its stringstream with the lua kernel when it is created, and unregisters when it is destroyed.
124  *
125  * It is responsible to execute commands as strings, or add dialog messages for the user. It is also responsible to ask
126  * the lua kernel for help with tab completion.
127  */
129 private:
131  std::stringstream log_;
132  std::stringstream raw_log_;
133 
134 public:
136  : L_(lk)
137  , log_()
138  , raw_log_()
139  {
140  DBG_LUA << "constructing a lua_interpreter::model\n";
141  //DBG_LUA << "incoming:\n" << lk.get_log().rdbuf() << "\n.\n";
142  log_ << font::escape_text(lk.get_log().str()) << std::flush;
143  raw_log_ << lk.get_log().str() << std::flush;
144  // Lua kernel sends log strings to this function
145  L_.set_external_log([this](const std::string & str) {
146  log_ << font::escape_text(str);
147  raw_log_ << str;
148  });
149  //DBG_LUA << "received:\n" << log_.str() << "\n.\n";
150 
151  DBG_LUA << "finished constructing a lua_interpreter::model\n";
152  }
153 
155  {
156  DBG_LUA << "destroying a lua_interpreter::model\n";
157  L_.set_external_log(nullptr); //deregister our log since it's about to be destroyed
158  }
159 
160  /** Ask the lua kernel to execute a command. No throw of game::lua_error, instead the error message is formatted and printed to console.*/
161  bool execute(const std::string & cmd);
162 
163  /** Add a message from the dialog, formatted in blue to distinguish from issued commands.
164  * 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
165  * not appear the next time it is opened.
166  **/
167  void add_dialog_message(const std::string & msg);
168 
169  std::string get_log() const { return log_.str(); } ///< Get the log string
170  std::string get_raw_log() const { return raw_log_.str(); } ///< Get the unescaped log
171  std::string get_name() const { return L_.my_name(); } ///< Get a string describing the name of lua kernel
172 
173  /// Clear the console log
174  void clear_log() {
175  L_.clear_log();
176  log_.str("");
177  log_.clear();
178  raw_log_.str("");
179  raw_log_.clear();
180  }
181 
182  //* Tab completion: Get list of presently defined global variables */
183  std::vector<std::string> get_globals() { return L_.get_global_var_names(); }
184  //* Tab completion: Get list of attributes for variable corresponding to this path. */
185  std::vector<std::string> get_attribute_names(const std::string & s) { return L_.get_attribute_names(s); }
186 };
187 
188 /**
189  * The input_model keeps track of what commands were executed before, and figures out what
190  * should be displayed when the user presses up / down arrows in the input.
191  * It is essentially part of the model, but it isn't connected to the lua kernel so I have implemented it
192  * separately. Putatively it could all be refactored so that there is a single model with private subclass "lua_model"
193  * and also a "command_history_model" but I have decided simply to not implement it that way.
194  */
196 private:
197  std::string prefix_;
199 #ifdef HAVE_HISTORY
200  std::string filename_;
201 #endif
202 
203 public:
205  : prefix_()
206  , end_of_history_(true)
207 #ifdef HAVE_HISTORY
208  , filename_(filesystem::get_user_config_dir() + "/lua_command_history")
209  {
210  using_history();
211  read_history (filename_.c_str());
212  }
213 #else
214  {}
215 #endif
216 
217 #ifdef HAVE_HISTORY
218  ~input_model()
219  {
220  try {
221  const std::size_t history_max = 500;
222  if (filesystem::file_exists(filename_)) {
223  append_history (history_max,filename_.c_str());
224  } else {
225  write_history (filename_.c_str());
226  }
227 
228  history_truncate_file (filename_.c_str(), history_max);
229  } catch (...) { std::cerr << "Swallowed an exception when trying to write lua command line history\n";}
230  }
231 #endif
232  void add_to_history (const std::string& str) {
233  prefix_ = "";
234  UNUSED(str);
235 #ifdef HAVE_HISTORY
236  add_history(str.c_str());
237 #endif
238  end_of_history_ = true;
239 
240  }
241 
242  void maybe_update_prefix (const std::string & text) {
243  LOG_LUA << "maybe update prefix\n";
244  LOG_LUA << "prefix_: '"<< prefix_ << "'\t text='"<< text << "'\n";
245 
246  if (!end_of_history_) return;
247 
248  prefix_ = text;
249  LOG_LUA << "updated prefix\n";
250  }
251 
252  std::string search( int direction ) {
253 #ifdef HAVE_HISTORY
254  LOG_LUA << "searching in direction " << direction << " from position " << where_history() << "\n";
255 
256  HIST_ENTRY * e = nullptr;
257  if (end_of_history_) {
258  // if the direction is > 0, do nothing because searching down only takes place when we are in the history records.
259  if (direction < 0) {
260  history_set_pos(history_length);
261 
262  if (prefix_.size() > 0) {
263  int result = history_search_prefix(prefix_.c_str(), direction);
264  if (result == 0) {
265  e = current_history();
266  }
267  } else {
268  e = previous_history();
269  }
270  }
271  } else {
272  e = (direction > 0) ? next_history() : previous_history();
273  if (prefix_.size() > 0 && e) {
274  int result = history_search_prefix(prefix_.c_str(), direction);
275  if (result == 0) {
276  e = current_history();
277  } else {
278  e = nullptr; // if the search misses, it leaves the state as it was, which might not have been on an entry matching prefix.
279  end_of_history_ = true; // we actually want to force it to be null and treat as off the end of history in this case.
280  }
281  }
282  }
283 
284  if (e) {
285  LOG_LUA << "found something at " << where_history() << "\n";
286  std::string ret = e->line;
287  end_of_history_ = false;
288  return ret;
289  }
290 #endif
291 
292  LOG_LUA << "didn't find anything\n";
293 
294  // reset, set history to the end and prefix_ to empty, and return the current prefix_ for the user to edit
295  end_of_history_ = true;
296  UNUSED(direction);
297  std::string temp = prefix_;
298  prefix_ = "";
299  return temp;
300  }
301 
302  std::string clear_history() {
303 #ifdef HAVE_HISTORY
304  ::clear_history();
305  write_history (filename_.c_str());
306  return "Cleared history.";
307 #else
308  return "History is disabled, you did not compile with GNU history support.";
309 #endif
310  }
311 
312  std::string list_history() {
313 #ifdef HAVE_HISTORY
314  HIST_ENTRY **the_list;
315 
316  the_list = history_list ();
317  if (the_list) {
318  if (!*the_list) {
319  return "History is empty.";
320  }
321 
322  std::string result;
323  for (int i = 0; the_list[i]; i++) {
324  result += lexical_cast<std::string, int>(i+history_base);
325  result += ": ";
326  result += the_list[i]->line;
327  result += "\n";
328  }
329  return result;
330  } else {
331  return "Couldn't find history.";
332  }
333 #else
334  return "History is disabled, you did not compile with GNU history support.";
335 #endif
336  }
337 
338  // Does history expansion in a command line. A return value of true indicates an error,
339  // the error message will be returned in the string argument. A return value of false
340  // indicates success and that execution should proceed.
341  bool do_history_expansion (std::string & cmd) {
342 #ifdef HAVE_HISTORY
343  // Do history expansions
344  std::unique_ptr<char[]> cmd_cstr(new char[cmd.length()+1]);
345  strcpy (cmd_cstr.get(), cmd.c_str());
346 
347  char * expansion;
348 
349  int result = history_expand(cmd_cstr.get(), &expansion);
350 
351  if (result < 0 || result == 2) {
352  cmd = expansion; // return error message in cmd var
353  free(expansion);
354  return true;
355  }
356 
357  cmd = expansion;
358  free(expansion);
359 #endif
360  UNUSED(cmd);
361  return false;
362  }
363 };
364 
365 /**
366  * The controller is responsible to hold all the input widgets, and a pointer to the model and view.
367  * It is responsible to bind the input signals to appropriate handler methods, which it holds.
368  * It is also responsible to ask the view to update based on the output of the model, typically in
369  * response to some input.
370  */
372 private:
375 
377  std::string text_entry_;
378 
379  const std::unique_ptr<lua_interpreter::lua_model> lua_model_;
380  const std::unique_ptr<lua_interpreter::input_model> input_model_;
381  const std::unique_ptr<lua_interpreter::view> view_;
382 
383  void execute();
384  void tab();
385  void search(int direction);
386 public:
388  : copy_button(nullptr)
389  , clear_button(nullptr)
390  , text_entry(nullptr)
391  , text_entry_()
392  , lua_model_(new lua_interpreter::lua_model(lk))
393  , input_model_(new lua_interpreter::input_model())
394  , view_(new lua_interpreter::view())
395  {}
396 
397  /** Bind my pointers to the widgets found in the window */
398  void bind(window& window);
399 
400  void handle_copy_button_clicked(window & window);
401  void handle_clear_button_clicked(window & window);
402 
403  void input_keypress_callback(bool& handled,
404  bool& halt,
405  const SDL_Keycode key);
406 
407  void update_view(); ///< Update the view based on the model
408 
409  friend class lua_interpreter;
410 };
411 
412 // Model impl
413 
414 /** Execute a command, and report any errors encountered. */
415 bool lua_interpreter::lua_model::execute (const std::string & cmd)
416 {
417  LOG_LUA << "lua_interpreter::model::execute...\n";
418 
419  try {
420  L_.interactive_run(cmd.c_str());
421  return true;
422  } catch (const game::lua_error & e) {
423  add_dialog_message(std::string(e.what()));
424  return false;
425  }
426 }
427 
428 /** Add a dialog message, which will appear in blue. */
430  log_ << "<span color='#8888FF'>" << font::escape_text(msg) << "</span>\n";
431  raw_log_ << msg << '\n';
432 }
433 
434 // View impl
435 
436 // Controller impl
437 
438 /** Update the view based on the model. */
440 {
441  LOG_LUA << "lua_interpreter update_view...\n";
442  assert(lua_model_);
443  assert(view_);
444 
445  view_->update_contents(lua_model_->get_log());
446 
447  LOG_LUA << "lua_interpreter update_view finished\n";
448 }
449 
450 /** Find all the widgets managed by the controller and connect them to handler methods. */
452 {
453  LOG_LUA << "Entering lua_interpreter::controller::bind" << std::endl;
454  assert(view_);
455  view_->bind(window);
456 
457  text_entry = find_widget<text_box>(&window, "text_entry", false, true);
458  //text_entry->set_text_changed_callback(
459  // std::bind(&view::filter, this, std::ref(window)));
460  window.keyboard_capture(text_entry);
461  window.set_click_dismiss(false);
462  window.set_enter_disabled(true);
463 
465  *text_entry,
467  this,
468  _3,
469  _4,
470  _5));
471 
472  copy_button = find_widget<button>(&window, "copy", false, true);
474  *copy_button,
476  this,
477  std::ref(window)));
478 
479  clear_button = find_widget<button>(&window, "clear", false, true);
481  *clear_button,
483  this,
484  std::ref(window)));
485 
487  copy_button->set_active(false);
488  copy_button->set_tooltip(_("Clipboard support not found, contact your packager"));
489  }
490 
491  LOG_LUA << "Exiting lua_interpreter::controller::bind" << std::endl;
492 }
493 
494 /** Copy text to the clipboard */
496 {
497  assert(lua_model_);
498  desktop::clipboard::copy_to_clipboard(lua_model_->get_raw_log(), false);
499 }
500 
501 /** Clear the text */
503 {
504  assert(lua_model_);
505  lua_model_->clear_log();
506  assert(view_);
507  view_->update_contents("");
508 }
509 
510 /** Handle return key (execute) or tab key (tab completion) */
512  bool& halt,
513  const SDL_Keycode key)
514 {
515  assert(lua_model_);
516  assert(text_entry);
517 
518  LOG_LUA << "keypress_callback\n";
519  if(key == SDLK_RETURN || key == SDLK_KP_ENTER) { // handle executing whatever is in the command entry field
520  LOG_LUA << "executing...\n";
521  execute();
522  handled = true;
523  halt = 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  std::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 std::size_t wrap_limit = 80;
641  std::string buffer;
642 
643  for (std::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
std::string get_name() const
Get a string describing the name of lua kernel.
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...
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
static bool file_exists(const fs::path &fpath)
Definition: filesystem.cpp:300
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)
std::string get_raw_log() const
Get the unescaped log.
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:555
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:164
virtual void pre_show(window &window) override
Inherited from modal_dialog.
std::string get_log() const
Get the log string.
const char * what() const noexcept
Definition: exceptions.hpp:37
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.
#define UNUSED(x)
Definition: global.hpp:34
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
std::size_t i
Definition: function.cpp:933
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.
static std::string flush(std::ostringstream &s)
Definition: reports.cpp:82
bool execute(const std::string &cmd)
Ask the lua kernel to execute a command.
Declarations for File-IO.
const bool & debug
void input_keypress_callback(bool &handled, bool &halt, const SDL_Keycode key)
Handle return key (execute) or tab key (tab completion)
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()
Definition: filesystem.cpp:720
The paths manager is responsible for recording the various paths that binary files may be located at...
Definition: fs_commit.cpp:37
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 &#39;snooping&#39; on the keypress.
Definition: dispatcher.cpp:159
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.
#define LOG_LUA
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:63
bool word_completion(std::string &text, std::vector< std::string > &wordlist)
Try to complete the last word of &#39;text&#39; with the &#39;wordlist&#39;.
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:411
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