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