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