The Battle for Wesnoth  1.17.0-dev
lua_interpreter.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2021
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 
20 #include "gui/auxiliary/field.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 "play_controller.hpp"
35 #include "resources.hpp" //for help fetching lua kernel pointers
36 #include "scripting/plugins/manager.hpp" //needed for the WHICH_KERNEL version of display
37 #include "scripting/game_lua_kernel.hpp" //needed for the WHICH_KERNEL version of display
41 #include "log.hpp"
42 #include "font/pango/escape.hpp"
43 
44 #include <sstream>
45 #include <string>
46 #include <vector>
47 #include <functional>
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::dialogs
61 {
62 
63 REGISTER_DIALOG(lua_interpreter)
64 
65 // Model, View, Controller definitions
66 
68 private:
69  scroll_label* msg_label; //the view is extremely simple, it's pretty much just this one widget that gets updated
71 
72 public:
73  view() : msg_label(nullptr), window_(nullptr) {}
74 
75  /** Bind the scroll label widget to my pointer, and configure */
76  void bind(window& window) {
77  window_ = &window;
78  msg_label = find_widget<scroll_label>(&window, "msg", false, true);
79  msg_label->set_use_markup(true);
81  msg_label->set_label("");
82  }
83 
84  /** Update the scroll label contents */
85  void update_contents(const std::string & str)
86  {
87  assert(msg_label);
88 
89  msg_label->set_label(str);
90  window_->set_callback_next_draw([this]()
91  {
93  });
94  }
95 
96  void pg_up()
97  {
98  assert(msg_label);
100  }
101 
102  void pg_down()
103  {
104  assert(msg_label);
106  }
107 };
108 
109 /**
110  * The lua model is responsible to interact with the lua kernel base and keep track of what should be displayed in the console.
111  * It registers its stringstream with the lua kernel when it is created, and unregisters when it is destroyed.
112  *
113  * It is responsible to execute commands as strings, or add dialog messages for the user. It is also responsible to ask
114  * the lua kernel for help with tab completion.
115  */
117 private:
119  std::stringstream log_;
120  std::stringstream raw_log_;
121 
122 public:
124  : L_(lk)
125  , log_()
126  , raw_log_()
127  {
128  DBG_LUA << "constructing a lua_interpreter::model\n";
129  //DBG_LUA << "incoming:\n" << lk.get_log().rdbuf() << "\n.\n";
130  log_ << font::escape_text(lk.get_log().str()) << std::flush;
131  raw_log_ << lk.get_log().str() << std::flush;
132  // Lua kernel sends log strings to this function
133  L_.set_external_log([this](const std::string & str) {
134  log_ << font::escape_text(str);
135  raw_log_ << str;
136  });
137  //DBG_LUA << "received:\n" << log_.str() << "\n.\n";
138 
139  DBG_LUA << "finished constructing a lua_interpreter::model\n";
140  }
141 
143  {
144  DBG_LUA << "destroying a lua_interpreter::model\n";
145  L_.set_external_log(nullptr); //deregister our log since it's about to be destroyed
146  }
147 
148  /** Ask the lua kernel to execute a command. No throw of game::lua_error, instead the error message is formatted and printed to console.*/
149  bool execute(const std::string & cmd);
150 
151  /** Add a message from the dialog, formatted in blue to distinguish from issued commands.
152  * 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
153  * not appear the next time it is opened.
154  **/
155  void add_dialog_message(const std::string & msg);
156 
157  /** Get the log string */
158  std::string get_log() const { return log_.str(); }
159  /** Get the unescaped log */
160  std::string get_raw_log() const { return raw_log_.str(); }
161  /** Get a string describing the name of lua kernel */
162  std::string get_name() const { return L_.my_name(); }
163 
164  /** Clear the console log */
165  void clear_log() {
166  L_.clear_log();
167  log_.str("");
168  log_.clear();
169  raw_log_.str("");
170  raw_log_.clear();
171  }
172 
173  //* Tab completion: Get list of presently defined global variables */
174  std::vector<std::string> get_globals() { return L_.get_global_var_names(); }
175  //* Tab completion: Get list of attributes for variable corresponding to this path. */
176  std::vector<std::string> get_attribute_names(const std::string & s) { return L_.get_attribute_names(s); }
177 };
178 
179 /**
180  * The input_model keeps track of what commands were executed before, and figures out what
181  * should be displayed when the user presses up / down arrows in the input.
182  * It is essentially part of the model, but it isn't connected to the lua kernel so I have implemented it
183  * separately. Putatively it could all be refactored so that there is a single model with private subclass "lua_model"
184  * and also a "command_history_model" but I have decided simply to not implement it that way.
185  */
187 private:
188  std::string prefix_;
190 #ifdef HAVE_HISTORY
191  std::string filename_;
192 #endif
193 
194 public:
196  : prefix_()
197  , end_of_history_(true)
198 #ifdef HAVE_HISTORY
199  , filename_(filesystem::get_user_config_dir() + "/lua_command_history")
200  {
201  using_history();
202  read_history (filename_.c_str());
203  }
204 #else
205  {}
206 #endif
207 
208 #ifdef HAVE_HISTORY
209  ~input_model()
210  {
211  try {
212  const std::size_t history_max = 500;
213  if (filesystem::file_exists(filename_)) {
214  append_history (history_max,filename_.c_str());
215  } else {
216  write_history (filename_.c_str());
217  }
218 
219  history_truncate_file (filename_.c_str(), history_max);
220  } catch (...) { std::cerr << "Swallowed an exception when trying to write lua command line history\n";}
221  }
222 #endif
223  void add_to_history ([[maybe_unused]] const std::string& str) {
224  prefix_ = "";
225 #ifdef HAVE_HISTORY
226  add_history(str.c_str());
227 #endif
228  end_of_history_ = true;
229 
230  }
231 
232  void maybe_update_prefix (const std::string & text) {
233  LOG_LUA << "maybe update prefix\n";
234  LOG_LUA << "prefix_: '"<< prefix_ << "'\t text='"<< text << "'\n";
235 
236  if (!end_of_history_) return;
237 
238  prefix_ = text;
239  LOG_LUA << "updated prefix\n";
240  }
241 
242  std::string search([[maybe_unused]] int direction ) {
243 #ifdef HAVE_HISTORY
244  LOG_LUA << "searching in direction " << direction << " from position " << where_history() << "\n";
245 
246  HIST_ENTRY * e = nullptr;
247  if (end_of_history_) {
248  // if the direction is > 0, do nothing because searching down only takes place when we are in the history records.
249  if (direction < 0) {
250  history_set_pos(history_length);
251 
252  if (prefix_.size() > 0) {
253  int result = history_search_prefix(prefix_.c_str(), direction);
254  if (result == 0) {
255  e = current_history();
256  }
257  } else {
258  e = previous_history();
259  }
260  }
261  } else {
262  e = (direction > 0) ? next_history() : previous_history();
263  if (prefix_.size() > 0 && e) {
264  int result = history_search_prefix(prefix_.c_str(), direction);
265  if (result == 0) {
266  e = current_history();
267  } else {
268  e = nullptr; // if the search misses, it leaves the state as it was, which might not have been on an entry matching prefix.
269  end_of_history_ = true; // we actually want to force it to be null and treat as off the end of history in this case.
270  }
271  }
272  }
273 
274  if (e) {
275  LOG_LUA << "found something at " << where_history() << "\n";
276  std::string ret = e->line;
277  end_of_history_ = false;
278  return ret;
279  }
280 #endif
281 
282  LOG_LUA << "didn't find anything\n";
283 
284  // reset, set history to the end and prefix_ to empty, and return the current prefix_ for the user to edit
285  end_of_history_ = true;
286  std::string temp = prefix_;
287  prefix_ = "";
288  return temp;
289  }
290 
291  std::string clear_history() {
292 #ifdef HAVE_HISTORY
293  ::clear_history();
294  write_history (filename_.c_str());
295  return "Cleared history.";
296 #else
297  return "History is disabled, you did not compile with GNU history support.";
298 #endif
299  }
300 
301  std::string list_history() {
302 #ifdef HAVE_HISTORY
303  HIST_ENTRY **the_list;
304 
305  the_list = history_list ();
306  if (the_list) {
307  if (!*the_list) {
308  return "History is empty.";
309  }
310 
311  std::string result;
312  for (int i = 0; the_list[i]; i++) {
313  result += std::to_string(i+history_base);
314  result += ": ";
315  result += the_list[i]->line;
316  result += "\n";
317  }
318  return result;
319  } else {
320  return "Couldn't find history.";
321  }
322 #else
323  return "History is disabled, you did not compile with GNU history support.";
324 #endif
325  }
326 
327  // Does history expansion in a command line. A return value of true indicates an error,
328  // the error message will be returned in the string argument. A return value of false
329  // indicates success and that execution should proceed.
330  bool do_history_expansion ([[maybe_unused]] std::string & cmd) {
331 #ifdef HAVE_HISTORY
332  // Do history expansions
333  std::unique_ptr<char[]> cmd_cstr(new char[cmd.length()+1]);
334  strcpy (cmd_cstr.get(), cmd.c_str());
335 
336  char * expansion;
337 
338  int result = history_expand(cmd_cstr.get(), &expansion);
339 
340  if (result < 0 || result == 2) {
341  cmd = expansion; // return error message in cmd var
342  free(expansion);
343  return true;
344  }
345 
346  cmd = expansion;
347  free(expansion);
348 #endif
349  return false;
350  }
351 };
352 
353 /**
354  * The controller is responsible to hold all the input widgets, and a pointer to the model and view.
355  * It is responsible to bind the input signals to appropriate handler methods, which it holds.
356  * It is also responsible to ask the view to update based on the output of the model, typically in
357  * response to some input.
358  */
360 private:
363 
365  std::string text_entry_;
366 
367  const std::unique_ptr<lua_interpreter::lua_model> lua_model_;
368  const std::unique_ptr<lua_interpreter::input_model> input_model_;
369  const std::unique_ptr<lua_interpreter::view> view_;
370 
371  void execute();
372  void tab();
373  void search(int direction);
374 public:
376  : copy_button(nullptr)
377  , clear_button(nullptr)
378  , text_entry(nullptr)
379  , text_entry_()
380  , lua_model_(new lua_interpreter::lua_model(lk))
381  , input_model_(new lua_interpreter::input_model())
382  , view_(new lua_interpreter::view())
383  {}
384 
385  /** Bind my pointers to the widgets found in the window */
386  void bind(window& window);
387 
388  void handle_copy_button_clicked(window & window);
389  void handle_clear_button_clicked(window & window);
390 
391  void input_keypress_callback(bool& handled,
392  bool& halt,
393  const SDL_Keycode key,
394  window& window);
395 
396  /** Update the view based on the model */
397  void update_view();
398 
399  friend class lua_interpreter;
400 };
401 
402 // Model impl
403 
404 /** Execute a command, and report any errors encountered. */
405 bool lua_interpreter::lua_model::execute (const std::string & cmd)
406 {
407  LOG_LUA << "lua_interpreter::model::execute...\n";
408 
409  try {
410  L_.interactive_run(cmd.c_str());
411  return true;
412  } catch (const game::lua_error & e) {
413  add_dialog_message(std::string(e.what()));
414  return false;
415  }
416 }
417 
418 /** Add a dialog message, which will appear in blue. */
420  log_ << "<span color='#8888FF'>" << font::escape_text(msg) << "</span>\n";
421  raw_log_ << msg << '\n';
422 }
423 
424 // View impl
425 
426 // Controller impl
427 
428 /** Update the view based on the model. */
430 {
431  LOG_LUA << "lua_interpreter update_view...\n";
432  assert(lua_model_);
433  assert(view_);
434 
435  view_->update_contents(lua_model_->get_log());
436 
437  LOG_LUA << "lua_interpreter update_view finished\n";
438 }
439 
440 /** Find all the widgets managed by the controller and connect them to handler methods. */
442 {
443  LOG_LUA << "Entering lua_interpreter::controller::bind" << std::endl;
444  assert(view_);
445  view_->bind(window);
446 
447  text_entry = find_widget<text_box>(&window, "text_entry", false, true);
448  //text_entry->set_text_changed_callback(
449  // std::bind(&view::filter, this, std::ref(window)));
450  window.keyboard_capture(text_entry);
451  window.set_click_dismiss(false);
452  window.set_enter_disabled(true);
453 
455  *text_entry,
457  this,
458  std::placeholders::_3,
459  std::placeholders::_4,
460  std::placeholders::_5,
461  std::ref(window)));
462 
463  copy_button = find_widget<button>(&window, "copy", false, true);
465  *copy_button,
467  this,
468  std::ref(window)));
469 
470  clear_button = find_widget<button>(&window, "clear", false, true);
472  *clear_button,
474  this,
475  std::ref(window)));
476 
478  copy_button->set_active(false);
479  copy_button->set_tooltip(_("Clipboard support not found, contact your packager"));
480  }
481 
482  LOG_LUA << "Exiting lua_interpreter::controller::bind" << std::endl;
483 }
484 
485 /** Copy text to the clipboard */
487 {
488  assert(lua_model_);
489  desktop::clipboard::copy_to_clipboard(lua_model_->get_raw_log(), false);
490 }
491 
492 /** Clear the text */
494 {
495  assert(lua_model_);
496  lua_model_->clear_log();
497  assert(view_);
498  view_->update_contents("");
499 }
500 
501 /** Handle return key (execute) or tab key (tab completion) */
503  bool& halt,
504  const SDL_Keycode key,
505  window& window)
506 {
507  assert(lua_model_);
508  assert(text_entry);
509 
510  LOG_LUA << "keypress_callback\n";
511  if(key == SDLK_RETURN || key == SDLK_KP_ENTER) { // handle executing whatever is in the command entry field
512  LOG_LUA << "executing...\n";
513  execute();
514  handled = true;
515  halt = true;
516 
517  // Commands such as `wesnoth.interface.zoom` might cause the display to redraw and leave the window half-drawn.
518  // This preempts that.
519  window.set_is_dirty(true);
520 
521  LOG_LUA << "finished executing\n";
522  } else if(key == SDLK_TAB) { // handle tab completion
523  tab();
524  handled = true;
525  halt = true;
526  } else if(key == SDLK_UP) {
527  search(-1);
528  handled = true;
529  halt = true;
530  } else if(key == SDLK_DOWN) {
531  search(1);
532  handled = true;
533  halt = true;
534  } else if(key == SDLK_PAGEUP) {
535  view_->pg_up();
536  handled = true;
537  halt = true;
538  } else if(key == SDLK_PAGEDOWN) {
539  view_->pg_down();
540  handled = true;
541  halt = true;
542  }
543 }
544 
546 {
547  std::string cmd = text_entry->get_value();
548  if (cmd.empty()) return; //don't bother with empty string
549 
550  cmd.erase(cmd.find_last_not_of(" \n\r\t")+1); //right trim the string
551 
552  LOG_LUA << "Executing '"<< cmd << "'\n";
553 
554  if (cmd.size() >= 13 && (cmd.substr(0,13) == "history clear" || cmd.substr(0,13) == "clear history")) {
555  lua_model_->add_dialog_message(input_model_->clear_history());
556  text_entry->set_value("");
557  update_view();
558  return;
559  }
560 
561  if (cmd.size() >= 7 && (cmd.substr(0,7) == "history")) {
562  lua_model_->add_dialog_message(input_model_->list_history());
563  text_entry->set_value("");
564  update_view();
565  return;
566  }
567 
568  if (input_model_->do_history_expansion(cmd)) {
569  lua_model_->add_dialog_message(cmd);
570  update_view();
571  return;
572  }
573 
574  if (lua_model_->execute(cmd)) {
575  input_model_->add_to_history(cmd);
576  text_entry->set_value("");
577  }
578  update_view();
579 }
580 
582 {
583  std::string text = text_entry->get_value();
584 
585  std::string prefix;
586  std::size_t prefix_end_pos = text.find_last_of(" (");
587  if (prefix_end_pos != std::string::npos) {
588  prefix = text.substr(0, prefix_end_pos + 1);
589  text = text.substr(prefix_end_pos + 1);
590  }
591 
592  static std::vector<std::string> static_matches {
593  "and",
594  "break",
595  "else",
596  "elseif",
597  "end",
598  "false",
599  "for",
600  "function",
601  "local",
602  "nil",
603  "not",
604  "repeat",
605  "return",
606  "then",
607  "true",
608  "until",
609  "while"
610  };
611 
612  std::vector<std::string> matches;
613 
614  if (text.find('.') == std::string::npos) {
615  matches = lua_model_->get_globals();
616  matches.insert(matches.end(), static_matches.begin(), static_matches.end());
617  } else {
618  matches = lua_model_->get_attribute_names(text);
619  }
620 
621  //bool line_start = utils::word_completion(text, matches);
622  if (text.size() > 0) { // this if is to avoid weird behavior in word_completion, where it thinks nothing matches the empty string
623  utils::word_completion(text, matches);
624  }
625 
626  if(matches.empty()) {
627  return;
628  }
629 
630  //if(matches.size() == 1) {
631  //text.append(" "); //line_start ? ": " : " ");
632  //} else {
633  if (matches.size() > 1) {
634  //std::string completion_list = utils::join(matches, " ");
635 
636  const std::size_t wrap_limit = 80;
637  std::string buffer;
638 
639  for (std::size_t idx = 0; idx < matches.size(); ++idx) {
640  if (buffer.size() + 1 + matches.at(idx).size() > wrap_limit) {
641  lua_model_->add_dialog_message(buffer);
642  buffer = matches.at(idx);
643  } else {
644  if (buffer.size()) {
645  buffer += (" " + matches.at(idx));
646  } else {
647  buffer = matches.at(idx);
648  }
649  }
650  }
651 
652  lua_model_->add_dialog_message(buffer);
653  update_view();
654  }
655  text_entry->set_value(prefix + text);
656 }
657 
659 {
660  std::string current_text = text_entry->get_value();
661  input_model_->maybe_update_prefix(current_text);
662  text_entry->set_value(input_model_->search(direction));
663 
664 #ifndef HAVE_HISTORY
665  lua_model_->add_dialog_message("History is disabled, you did not compile with GNU history support.");
666  update_view();
667 #endif
668 
669 }
670 
671 // Dialog implementation
672 
673 /** Display a new console, using given video and lua kernel */
675 #ifndef ALWAYS_HAVE_LUA_CONSOLE
678  const std::string& message = _("The lua console can only be used in debug mode! (Run ':debug' first)");
679  chat_man.add_chat_message(time(nullptr), _("lua console"), 0, message, events::chat_handler::MESSAGE_PRIVATE, false);
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
std::string get_name() const
Get a string describing the name of lua kernel.
play_controller * controller
Definition: resources.cpp:22
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::string search([[maybe_unused]] int direction)
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:55
bool do_history_expansion([[maybe_unused]] std::string &cmd)
Main class to show messages to the user.
Definition: message.hpp:35
game_display & get_display() override
Get a reference to a display member a derived class uses.
const std::unique_ptr< lua_interpreter::lua_model > lua_model_
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:263
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:110
A label displays a text, the text can be wrapped but no scrollbars are provided.
Definition: label.hpp:57
Implements some helper classes to ease adding fields to a dialog and hide the synchronization needed...
static std::string _(const char *str)
Definition: gettext.hpp:93
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:141
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)
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:564
const std::unique_ptr< controller > controller_
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:61
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.
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:172
void set_is_dirty(const bool is_dirty)
Definition: widget.cpp:466
virtual void pre_show(window &window) override
Bind the controller, initialize one of the static labels with info about this kernel, and update the view.
std::string get_log() const
Get the log string.
const char * what() const noexcept
Definition: exceptions.hpp:36
Label showing a text.
const std::unique_ptr< lua_interpreter::view > view_
void update_view()
Update the view based on the model.
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:33
std::size_t i
Definition: function.cpp:967
Go the visible items towards the begin.
Definition: scrollbar.hpp:60
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:92
bool execute(const std::string &cmd)
Ask the lua kernel to execute a command.
Declarations for File-IO.
const bool & debug
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:763
display_chat_manager & get_chat_manager()
std::vector< std::string > get_globals()
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:34
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:167
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:36
Standard logging facilities (interface).
game_lua_kernel * lua_kernel
Definition: resources.cpp:26
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
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:65
void add_to_history([[maybe_unused]] const std::string &str)
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:423
static plugins_manager * get()
Definition: manager.cpp:59
#define DBG_LUA
Error used to report an error in a lua script or in the lua interpreter.
Definition: game_errors.hpp:54