#pragma once #include "dispatcher.hpp" #include "mutex.hpp" #include "tooltips.hpp" #include #include #include class Autocomplete { Gtk::TextView *view; bool &interactive_completion; /// If text_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 = [](guint keyval) { return (keyval >= '0' && keyval <= '9') || (keyval >= 'a' && keyval <= 'z') || (keyval >= 'A' && keyval <= 'Z') || keyval == '_' || gdk_keyval_to_unicode(keyval) >= 0x00C0; }; 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. std::function add_rows = [](std::string &, int, int) {}; 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; }; Autocomplete(Gtk::TextView *view, bool &interactive_completion, guint &last_keyval, bool pass_buffer_and_strip_word); void run(); void stop(); private: void setup_dialog(); };