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 https://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/text_box.hpp"
26 #include "gui/widgets/window.hpp"
27 
28 #include "desktop/clipboard.hpp"
29 #include "game_config.hpp"
30 #include "game_errors.hpp"
31 #include "gettext.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
38 #include "lexical_cast.hpp"
39 #include "log.hpp"
40 #include "font/pango/escape.hpp"
41 
42 #include <sstream>
43 #include <string>
44 #include <vector>
45 #include "utils/functional.hpp"
46 
47 #ifdef HAVE_HISTORY
48 #include "filesystem.hpp"
49 #include <readline/history.h>
50 #endif
51 
52 static lg::log_domain log_lua_int("lua/interpreter");
53 #define DBG_LUA LOG_STREAM(debug, log_lua_int)
54 #define LOG_LUA LOG_STREAM(info, log_lua_int)
55 #define WRN_LUA LOG_STREAM(warn, log_lua_int)
56 #define ERR_LUA LOG_STREAM(err, log_lua_int)
57 
58 namespace gui2
59 {
60 namespace dialogs
61 {
62 
63 /*WIKI
64  * @page = GUIWindowDefinitionWML
65  * @order = 3_lua_interpretter
66  *
67  * == Settings manager ==
68  *
69  * This shows the settings manager
70  *
71  */
72 
73 
74 REGISTER_DIALOG(lua_interpreter)
75 
76 // Model, View, Controller definitions
77 
79 private:
80  scroll_label* msg_label; //the view is extremely simple, it's pretty much just this one widget that gets updated
82 
83 public:
84  view() : msg_label(nullptr), window_(nullptr) {}
85 
86  /** Bind the scroll label widget to my pointer, and configure */
87  void bind(window& window) {
88  window_ = &window;
89  msg_label = find_widget<scroll_label>(&window, "msg", false, true);
90  msg_label->set_use_markup(true);
92  msg_label->set_label("");
93  }
94 
95  /** Update the scroll label contents */
96  void update_contents(const std::string & str)
97  {
98  assert(msg_label);
99 
100  msg_label->set_label(str);
101  window_->set_callback_next_draw([this]()
102  {
104  });
105  }
106 
107  void pg_up()
108  {
109  assert(msg_label);
111  }
112 
113  void pg_down()
114  {
115  assert(msg_label);
117  }
118 };
119 
120 /**
121  * The lua model is responsible to interact with the lua kernel base and keep track of what should be displayed in the console.
122  * It registers its stringstream with the lua kernel when it is created, and unregisters when it is destroyed.
123  *
124  * It is responsible to execute commands as strings, or add dialog messages for the user. It is also responsible to ask
125  * the lua kernel for help with tab completion.
126  */
128 private:
130  std::stringstream log_;
131  std::stringstream raw_log_;
132 
133 public:
135  : L_(lk)
136  , log_()
137  , raw_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  raw_log_ << lk.get_log().str() << std::flush;
143  // Lua kernel sends log strings to this function
144  L_.set_external_log([this](const std::string & str) {
145  log_ << font::escape_text(str);
146  raw_log_ << str;
147  });
148  //DBG_LUA << "received:\n" << log_.str() << "\n.\n";
149 
150  DBG_LUA << "finished constructing a lua_interpreter::model\n";
151  }
152 
154  {
155  DBG_LUA << "destroying a lua_interpreter::model\n";
156  L_.set_external_log(nullptr); //deregister our log since it's about to be destroyed
157  }
158 
159  /** Ask the lua kernel to execute a command. No throw of game::lua_error, instead the error message is formatted and printed to console.*/
160  bool execute(const std::string & cmd);
161 
162  /** Add a message from the dialog, formatted in blue to distinguish from issued commands.
163  * 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
164  * not appear the next time it is opened.
165  **/
166  void add_dialog_message(const std::string & msg);
167 
168  std::string get_log() const { return log_.str(); } ///< Get the log string
169  std::string get_raw_log() const { return raw_log_.str(); } ///< Get the unescaped log
170  std::string get_name() const { return L_.my_name(); } ///< Get a string describing the name of lua kernel
171 
172  /// Clear the console log
173  void clear_log() {
174  L_.clear_log();
175  log_.str("");
176  log_.clear();
177  raw_log_.str("");
178  raw_log_.clear();
179  }
180 
181  //* Tab completion: Get list of presently defined global variables */
182  std::vector<std::string> get_globals() { return L_.get_global_var_names(); }
183  //* Tab completion: Get list of attributes for variable corresponding to this path. */
184  std::vector<std::string> get_attribute_names(const std::string & s) { return L_.get_attribute_names(s); }
185 };
186 
187 /**
188  * The input_model keeps track of what commands were executed before, and figures out what
189  * should be displayed when the user presses up / down arrows in the input.
190  * It is essentially part of the model, but it isn't connected to the lua kernel so I have implemented it
191  * separately. Putatively it could all be refactored so that there is a single model with private subclass "lua_model"
192  * and also a "command_history_model" but I have decided simply to not implement it that way.
193  */
195 private:
196  std::string prefix_;
198 #ifdef HAVE_HISTORY
199  std::string filename_;
200 #endif
201 
202 public:
204  : prefix_()
205  , end_of_history_(true)
206 #ifdef HAVE_HISTORY
207  , filename_(filesystem::get_user_config_dir() + "/lua_command_history")
208  {
209  using_history();
210  read_history (filename_.c_str());
211  }
212 #else
213  {}
214 #endif
215 
216 #ifdef HAVE_HISTORY
217  ~input_model()
218  {
219  try {
220  const std::size_t history_max = 500;
221  if (filesystem::file_exists(filename_)) {
222  append_history (history_max,filename_.c_str());
223  } else {
224  write_history (filename_.c_str());
225  }
226 
227  history_truncate_file (filename_.c_str(), history_max);
228  } catch (...) { std::cerr << "Swallowed an exception when trying to write lua command line history\n";}
229  }
230 #endif
231  void add_to_history (const std::string& str) {
232  prefix_ = "";
233  UNUSED(str);
234 #ifdef HAVE_HISTORY
235  add_history(str.c_str());
236 #endif
237  end_of_history_ = true;
238 
239  }
240 
241  void maybe_update_prefix (const std::string & text) {
242  LOG_LUA << "maybe update prefix\n";
243  LOG_LUA << "prefix_: '"<< prefix_ << "'\t text='"<< text << "'\n";
244 
245  if (!end_of_history_) return;
246 
247  prefix_ = text;
248  LOG_LUA << "updated prefix\n";
249  }
250 
251  std::string search( int direction ) {
252 #ifdef HAVE_HISTORY
253  LOG_LUA << "searching in direction " << direction << " from position " << where_history() << "\n";
254 
255  HIST_ENTRY * e = nullptr;
256  if (end_of_history_) {
257  // if the direction is > 0, do nothing because searching down only takes place when we are in the history records.
258  if (direction < 0) {
259  history_set_pos(history_length);
260 
261  if (prefix_.size() > 0) {
262  int result = history_search_prefix(prefix_.c_str(), direction);
263  if (result == 0) {
264  e = current_history();
265  }
266  } else {
267  e = previous_history();
268  }
269  }
270  } else {
271  e = (direction > 0) ? next_history() : previous_history();
272  if (prefix_.size() > 0 && e) {
273  int result = history_search_prefix(prefix_.c_str(), direction);
274  if (result == 0) {
275  e = current_history();
276  } else {
277  e = nullptr; // if the search misses, it leaves the state as it was, which might not have been on an entry matching prefix.
278  end_of_history_ = true; // we actually want to force it to be null and treat as off the end of history in this case.
279  }
280  }
281  }
282 
283  if (e) {
284  LOG_LUA << "found something at " << where_history() << "\n";
285  std::string ret = e->line;
286  end_of_history_ = false;
287  return ret;
288  }
289 #endif
290 
291  LOG_LUA << "didn't find anything\n";
292 
293  // reset, set history to the end and prefix_ to empty, and return the current prefix_ for the user to edit
294  end_of_history_ = true;
295  UNUSED(direction);
296  std::string temp = prefix_;
297  prefix_ = "";
298  return temp;
299  }
300 
301  std::string clear_history() {
302 #ifdef HAVE_HISTORY
303  ::clear_history();
304  write_history (filename_.c_str());
305  return "Cleared history.";
306 #else
307  return "History is disabled, you did not compile with GNU history support.";
308 #endif
309  }
310 
311  std::string list_history() {
312 #ifdef HAVE_HISTORY
313  HIST_ENTRY **the_list;
314 
315  the_list = history_list ();
316  if (the_list) {
317  if (!*the_list) {
318  return "History is empty.";
319  }
320 
321  std::string result;
322  for (int i = 0; the_list[i]; i++) {
323  result += lexical_cast<std::string, int>(i+history_base);
324  result += ": ";
325  result += the_list[i]->line;
326  result += "\n";
327  }
328  return result;
329  } else {
330  return "Couldn't find history.";
331  }
332 #else
333  return "History is disabled, you did not compile with GNU history support.";
334 #endif
335  }
336 
337  // Does history expansion in a command line. A return value of true indicates an error,
338  // the error message will be returned in the string argument. A return value of false
339  // indicates success and that execution should proceed.
340  bool do_history_expansion (std::string & cmd) {
341 #ifdef HAVE_HISTORY
342  // Do history expansions
343  std::unique_ptr<char[]> cmd_cstr(new char[cmd.length()+1]);
344  strcpy (cmd_cstr.get(), cmd.c_str());
345 
346  char * expansion;
347 
348  int result = history_expand(cmd_cstr.get(), &expansion);
349 
350  if (result < 0 || result == 2) {
351  cmd = expansion; // return error message in cmd var
352  free(expansion);
353  return true;
354  }
355 
356  cmd = expansion;
357  free(expansion);
358 #endif
359  UNUSED(cmd);
360  return false;
361  }
362 };
363 
364 /**
365  * The controller is responsible to hold all the input widgets, and a pointer to the model and view.
366  * It is responsible to bind the input signals to appropriate handler methods, which it holds.
367  * It is also responsible to ask the view to update based on the output of the model, typically in
368  * response to some input.
369  */
371 private:
374 
376  std::string text_entry_;
377 
378  const std::unique_ptr<lua_interpreter::lua_model> lua_model_;
379  const std::unique_ptr<lua_interpreter::input_model> input_model_;
380  const std::unique_ptr<lua_interpreter::view> view_;
381 
382  void execute();
383  void tab();
384  void search(int direction);
385 public:
387  : copy_button(nullptr)
388  , clear_button(nullptr)
389  , text_entry(nullptr)
390  , text_entry_()
391  , lua_model_(new lua_interpreter::lua_model(lk))
392  , input_model_(new lua_interpreter::input_model())
393  , view_(new lua_interpreter::view())
394  {}
395 
396  /** Bind my pointers to the widgets found in the window */
397  void bind(window& window);
398 
399  void handle_copy_button_clicked(window & window);
400  void handle_clear_button_clicked(window & window);
401 
402  void input_keypress_callback(bool& handled,
403  bool& halt,
404  const SDL_Keycode key);
405 
406  void update_view(); ///< Update the view based on the model
407 
408  friend class lua_interpreter;
409 };
410 
411 // Model impl
412 
413 /** Execute a command, and report any errors encountered. */
414 bool lua_interpreter::lua_model::execute (const std::string & cmd)
415 {
416  LOG_LUA << "lua_interpreter::model::execute...\n";
417 
418  try {
419  L_.interactive_run(cmd.c_str());
420  return true;
421  } catch (const game::lua_error & e) {
422  add_dialog_message(std::string(e.what()));
423  return false;
424  }
425 }
426 
427 /** Add a dialog message, which will appear in blue. */
429  log_ << "<span color='#8888FF'>" << font::escape_text(msg) << "</span>\n";
430  raw_log_ << msg << '\n';
431 }
432 
433 // View impl
434 
435 // Controller impl
436 
437 /** Update the view based on the model. */
439 {
440  LOG_LUA << "lua_interpreter update_view...\n";
441  assert(lua_model_);
442  assert(view_);
443 
444  view_->update_contents(lua_model_->get_log());
445 
446  LOG_LUA << "lua_interpreter update_view finished\n";
447 }
448 
449 /** Find all the widgets managed by the controller and connect them to handler methods. */
451 {
452  LOG_LUA << "Entering lua_interpreter::controller::bind" << std::endl;
453  assert(view_);
454  view_->bind(window);
455 
456  text_entry = find_widget<text_box>(&window, "text_entry", false, true);
457  //text_entry->set_text_changed_callback(
458  // std::bind(&view::filter, this, std::ref(window)));
459  window.keyboard_capture(text_entry);
460  window.set_click_dismiss(false);
461  window.set_enter_disabled(true);
462 
464  *text_entry,
466  this,
467  _3,
468  _4,
469  _5));
470 
471  copy_button = find_widget<button>(&window, "copy", false, true);
473  *copy_button,
475  this,
476  std::ref(window)));
477 
478  clear_button = find_widget<button>(&window, "clear", false, true);
480  *clear_button,
482  this,
483  std::ref(window)));
484 
486  copy_button->set_active(false);
487  copy_button->set_tooltip(_("Clipboard support not found, contact your packager"));
488  }
489 
490  LOG_LUA << "Exiting lua_interpreter::controller::bind" << std::endl;
491 }
492 
493 /** Copy text to the clipboard */
495 {
496  assert(lua_model_);
497  desktop::clipboard::copy_to_clipboard(lua_model_->get_raw_log(), false);
498 }
499 
500 /** Clear the text */
502 {
503  assert(lua_model_);
504  lua_model_->clear_log();
505  assert(view_);
506  view_->update_contents("");
507 }
508 
509 /** Handle return key (execute) or tab key (tab completion) */
511  bool& halt,
512  const SDL_Keycode key)
513 {
514  assert(lua_model_);
515  assert(text_entry);
516 
517  LOG_LUA << "keypress_callback\n";
518  if(key == SDLK_RETURN || key == SDLK_KP_ENTER) { // handle executing whatever is in the command entry field
519  LOG_LUA << "executing...\n";
520  execute();
521  handled = true;
522  halt = true;
523 
524  LOG_LUA << "finished executing\n";
525  } else if(key == SDLK_TAB) { // handle tab completion
526  tab();
527  handled = true;
528  halt = true;
529  } else if(key == SDLK_UP) {
530  search(-1);
531  handled = true;
532  halt = true;
533  } else if(key == SDLK_DOWN) {
534  search(1);
535  handled = true;
536  halt = true;
537  } else if(key == SDLK_PAGEUP) {
538  view_->pg_up();
539  handled = true;
540  halt = true;
541  } else if(key == SDLK_PAGEDOWN) {
542  view_->pg_down();
543  handled = true;
544  halt = true;
545  }
546 }
547 
549 {
550  std::string cmd = text_entry->get_value();
551  if (cmd.empty()) return; //don't bother with empty string
552 
553  cmd.erase(cmd.find_last_not_of(" \n\r\t")+1); //right trim the string
554 
555  LOG_LUA << "Executing '"<< cmd << "'\n";
556 
557  if (cmd.size() >= 13 && (cmd.substr(0,13) == "history clear" || cmd.substr(0,13) == "clear history")) {
558  lua_model_->add_dialog_message(input_model_->clear_history());
559  text_entry->set_value("");
560  update_view();
561  return;
562  }
563 
564  if (cmd.size() >= 7 && (cmd.substr(0,7) == "history")) {
565  lua_model_->add_dialog_message(input_model_->list_history());
566  text_entry->set_value("");
567  update_view();
568  return;
569  }
570 
571  if (input_model_->do_history_expansion(cmd)) {
572  lua_model_->add_dialog_message(cmd);
573  update_view();
574  return;
575  }
576 
577  if (lua_model_->execute(cmd)) {
578  input_model_->add_to_history(cmd);
579  text_entry->set_value("");
580  }
581  update_view();
582 }
583 
585 {
586  std::string text = text_entry->get_value();
587 
588  std::string prefix;
589  std::size_t prefix_end_pos = text.find_last_of(" (");
590  if (prefix_end_pos != std::string::npos) {
591  prefix = text.substr(0, prefix_end_pos + 1);
592  text = text.substr(prefix_end_pos + 1);
593  }
594 
595  static std::vector<std::string> static_matches {
596  "and",
597  "break",
598  "else",
599  "elseif",
600  "end",
601  "false",
602  "for",
603  "function",
604  "local",
605  "nil",
606  "not",
607  "repeat",
608  "return",
609  "then",
610  "true",
611  "until",
612  "while"
613  };
614 
615  std::vector<std::string> matches;
616 
617  if (text.find('.') == std::string::npos) {
618  matches = lua_model_->get_globals();
619  matches.insert(matches.end(), static_matches.begin(), static_matches.end());
620  } else {
621  matches = lua_model_->get_attribute_names(text);
622  }
623 
624  //bool line_start = utils::word_completion(text, matches);
625  if (text.size() > 0) { // this if is to avoid weird behavior in word_completion, where it thinks nothing matches the empty string
626  utils::word_completion(text, matches);
627  }
628 
629  if(matches.empty()) {
630  return;
631  }
632 
633  //if(matches.size() == 1) {
634  //text.append(" "); //line_start ? ": " : " ");
635  //} else {
636  if (matches.size() > 1) {
637  //std::string completion_list = utils::join(matches, " ");
638 
639  const std::size_t wrap_limit = 80;
640  std::string buffer;
641 
642  for (std::size_t idx = 0; idx < matches.size(); ++idx) {
643  if (buffer.size() + 1 + matches.at(idx).size() > wrap_limit) {
644  lua_model_->add_dialog_message(buffer);
645  buffer = matches.at(idx);
646  } else {
647  if (buffer.size()) {
648  buffer += (" " + matches.at(idx));
649  } else {
650  buffer = matches.at(idx);
651  }
652  }
653  }
654 
655  lua_model_->add_dialog_message(buffer);
656  update_view();
657  }
658  text_entry->set_value(prefix + text);
659 }
660 
662 {
663  std::string current_text = text_entry->get_value();
664  input_model_->maybe_update_prefix(current_text);
665  text_entry->set_value(input_model_->search(direction));
666 
667 #ifndef HAVE_HISTORY
668  lua_model_->add_dialog_message("History is disabled, you did not compile with GNU history support.");
669  update_view();
670 #endif
671 
672 }
673 
674 // Dialog implementation
675 
676 /** Display a new console, using given video and lua kernel */
678 #ifndef ALWAYS_HAVE_LUA_CONSOLE
679  if(!game_config::debug) {
680  return;
681  }
682 #endif
683  if (!lk) {
684  ERR_LUA << "Tried to open console with a null lua kernel pointer.\n";
685  return;
686  }
687 
688  lua_interpreter(*lk).show();
689 }
690 
691 /** Helper function to assist those callers which don't want to include resources.hpp */
693  if (which == lua_interpreter::APP) {
694  display(plugins_manager::get()->get_kernel_base());
695  } else if (which == lua_interpreter::GAME) {
697  }
698 }
699 
700 /** Bind the controller, initialize one of the static labels with info about this kernel, and update the view. */
702 {
703  LOG_LUA << "Entering lua_interpreter::view::pre_show" << std::endl;
704  register_text("text_entry", false, controller_->text_entry_, true);
705  controller_->bind(window);
706 
707  label *kernel_type_label = find_widget<label>(&window, "kernel_type", false, true);
708  kernel_type_label->set_label(controller_->lua_model_->get_name());
709 
710  controller_->update_view();
711  //window.invalidate_layout(); // workaround for assertion failure
712  LOG_LUA << "Exiting lua_interpreter::view::pre_show" << std::endl;
713 }
714 
717 {
718  LOG_LUA << "entering lua_interpreter ctor...\n";
719  LOG_LUA << "finished lua_interpreter ctor...\n";
720 }
721 
722 } // namespace dialogs
723 } // 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:108
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
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:163
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:32
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:83
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:158
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:62
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:410
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