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