#pragma once #include "dispatcher.hpp" #include "mutex.hpp" #include "tooltips.hpp" #include #include #include class Autocomplete { Source::BaseView *view; bool &interactive_completion; /// If view buffer should be passed to add_rows. Empty buffer is passed if not. /// Also, some utilities, like libclang, require that autocomplete is started at the beginning of a word. bool pass_buffer_and_strip_word; Dispatcher dispatcher; public: enum class State { idle, starting, restarting, canceled }; Mutex prefix_mutex; Glib::ustring prefix GUARDED_BY(prefix_mutex); std::vector rows; Tooltips tooltips; /// Never changed outside main thread std::atomic state = {State::idle}; std::thread thread; std::function is_processing = [] { return true; }; std::function reparse = [] {}; std::function cancel_reparse = [] {}; std::function()> get_parse_lock = [] { return nullptr; }; std::function stop_parse = [] {}; std::function is_continue_key = [this](guint keyval) { return view->is_token_char(gdk_keyval_to_unicode(keyval)); }; std::function is_restart_key = [](guint) { return false; }; std::function run_check = [] { return false; }; std::function before_add_rows = [] {}; std::function after_add_rows = [] {}; std::function on_add_rows_error = [] {}; /// The handler is not run in the main loop if use_thread is true. Should return false on error. std::function add_rows = [](std::string &, int, int) { return true; }; std::function on_show = [] {}; std::function on_hide = [] {}; std::function, const std::string &)> on_change; std::function on_select; std::function(unsigned int)> set_tooltip_buffer = [](unsigned int index) { return nullptr; }; std::function clear_tooltips = [this] { tooltips.hide(); }; Autocomplete(Source::BaseView *view, bool &interactive_completion, guint &last_keyval, bool pass_buffer_and_strip_word, bool use_thread); void run(); void stop(); private: void setup_dialog(); bool use_thread; };