diff --git a/src/autocomplete.cc b/src/autocomplete.cc index c5056b0..a55f97c 100644 --- a/src/autocomplete.cc +++ b/src/autocomplete.cc @@ -156,16 +156,15 @@ void Autocomplete::setup_dialog() { on_changed(index, text); - auto tooltip = get_tooltip(index); - if(tooltip.empty()) + auto set_buffer = set_tooltip_buffer(index); + if(!set_buffer) tooltips.hide(); else { tooltips.clear(); auto iter = CompletionDialog::get()->start_mark->get_iter(); - tooltips.emplace_back(view, view->get_buffer()->create_mark(iter), view->get_buffer()->create_mark(iter), [tooltip_text = std::move(tooltip)](Tooltip &tooltip) { - tooltip.buffer->insert(tooltip.buffer->get_insert()->get_iter(), tooltip_text); + tooltips.emplace_back(view, view->get_buffer()->create_mark(iter), view->get_buffer()->create_mark(iter), [set_buffer = std::move(set_buffer)](Tooltip &tooltip) { + set_buffer(tooltip); }); - tooltips.show(true); } }; diff --git a/src/autocomplete.h b/src/autocomplete.h index 5772b2b..6a2f995 100644 --- a/src/autocomplete.h +++ b/src/autocomplete.h @@ -49,7 +49,7 @@ public: std::function on_changed = [](unsigned int index, const std::string &text) {}; std::function on_select = [](unsigned int index, const std::string &text, bool hide_window) {}; - std::function get_tooltip = [](unsigned int index) { return std::string(); }; + 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); diff --git a/src/source_clang.cc b/src/source_clang.cc index a37d6f1..21c57dd 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -908,8 +908,13 @@ Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::pa } }; - autocomplete.get_tooltip = [this](unsigned int index) { - return completion_strings[index] ? clangmm::to_string(clang_getCompletionBriefComment(completion_strings[index])) : snippet_comments[index]; + autocomplete.set_tooltip_buffer = [this](unsigned int index) -> std::function { + auto tooltip_str = completion_strings[index] ? clangmm::to_string(clang_getCompletionBriefComment(completion_strings[index])) : snippet_comments[index]; + if(tooltip_str.empty()) + return nullptr; + return [tooltip_str = std::move(tooltip_str)](Tooltip &tooltip) { + tooltip.insert_with_links_tagged(tooltip_str); + }; }; } diff --git a/src/source_generic.cc b/src/source_generic.cc index 5e7e9ae..9054af9 100644 --- a/src/source_generic.cc +++ b/src/source_generic.cc @@ -310,7 +310,12 @@ void Source::GenericView::setup_autocomplete() { get_buffer()->insert(CompletionDialog::get()->start_mark->get_iter(), insert); }; - autocomplete.get_tooltip = [this](unsigned int index) { - return autocomplete_comment[index]; + autocomplete.set_tooltip_buffer = [this](unsigned int index) -> std::function { + auto tooltip_str = autocomplete_comment[index]; + if(tooltip_str.empty()) + return nullptr; + return [tooltip_str = std::move(tooltip_str)](Tooltip &tooltip) { + tooltip.insert_with_links_tagged(tooltip_str); + }; }; } diff --git a/src/source_language_protocol.cc b/src/source_language_protocol.cc index bf895f1..f8ca228 100644 --- a/src/source_language_protocol.cc +++ b/src/source_language_protocol.cc @@ -1230,8 +1230,7 @@ void Source::LanguageProtocolView::setup_autocomplete() { }; autocomplete->reparse = [this] { - autocomplete_comment.clear(); - autocomplete_insert.clear(); + autocomplete_rows.clear(); }; if(capabilities.signature_help) { @@ -1355,14 +1354,12 @@ void Source::LanguageProtocolView::setup_autocomplete() { }; autocomplete->on_add_rows_error = [this] { - autocomplete_comment.clear(); - autocomplete_insert.clear(); + autocomplete_rows.clear(); }; autocomplete->add_rows = [this](std::string &buffer, int line_number, int column) { if(autocomplete->state == Autocomplete::State::starting) { - autocomplete_comment.clear(); - autocomplete_insert.clear(); + autocomplete_rows.clear(); std::promise result_processed; if(autocomplete_show_arguments) { if(!capabilities.signature_help) @@ -1375,10 +1372,20 @@ void Source::LanguageProtocolView::setup_autocomplete() { for(auto parameter_it = parameters.begin(); parameter_it != parameters.end(); ++parameter_it) { auto label = parameter_it->second.get("label", ""); auto insert = label; - auto documentation = parameter_it->second.get("documentation", ""); + auto plaintext = parameter_it->second.get("documentation", ""); + std::string markdown; + if(plaintext.empty()) { + auto documentation = parameter_it->second.get_child_optional("documentation"); + if(documentation) { + auto kind = documentation->get("kind", ""); + if(kind == "markdown") + markdown = documentation->get("value", ""); + else + plaintext = documentation->get("value", ""); + } + } autocomplete->rows.emplace_back(std::move(label)); - autocomplete_insert.emplace_back(std::move(insert)); - autocomplete_comment.emplace_back(std::move(documentation)); + autocomplete_rows.emplace_back(AutocompleteRow{std::move(insert), std::move(plaintext), std::move(markdown)}); } } } @@ -1401,9 +1408,18 @@ void Source::LanguageProtocolView::setup_autocomplete() { for(auto it = begin; it != end; ++it) { auto label = it->second.get("label", ""); auto detail = it->second.get("detail", ""); - auto documentation = it->second.get("documentation", ""); - if(documentation.empty()) - documentation = it->second.get("documentation.value", ""); + auto plaintext = it->second.get("documentation", ""); + std::string markdown; + if(plaintext.empty()) { + auto documentation = it->second.get_child_optional("documentation"); + if(documentation) { + auto kind = documentation->get("kind", ""); + if(kind == "markdown") + markdown = documentation->get("value", ""); + else + plaintext = documentation->get("value", ""); + } + } auto insert = it->second.get("insertText", ""); if(insert.empty()) insert = it->second.get("textEdit.newText", ""); @@ -1442,13 +1458,12 @@ void Source::LanguageProtocolView::setup_autocomplete() { } if(prefix.compare(0, prefix.size(), label, 0, prefix.size()) == 0) { autocomplete->rows.emplace_back(std::move(label)); - autocomplete_comment.emplace_back(std::move(detail)); - if(!documentation.empty() && documentation != autocomplete_comment.back()) { - if(!autocomplete_comment.back().empty()) - autocomplete_comment.back() += "\n\n"; - autocomplete_comment.back() += documentation; + if(!plaintext.empty() && detail != plaintext) { + if(!detail.empty()) + detail += "\n\n"; + detail += plaintext; } - autocomplete_insert.emplace_back(std::move(insert)); + autocomplete_rows.emplace_back(AutocompleteRow{std::move(insert), std::move(detail), std::move(markdown)}); } } } @@ -1464,8 +1479,7 @@ void Source::LanguageProtocolView::setup_autocomplete() { for(auto &snippet : *snippets) { if(prefix.compare(0, prefix.size(), snippet.prefix, 0, prefix.size()) == 0) { autocomplete->rows.emplace_back(snippet.prefix); - autocomplete_insert.emplace_back(snippet.body); - autocomplete_comment.emplace_back(snippet.description); + autocomplete_rows.emplace_back(AutocompleteRow{snippet.body, snippet.description, {}}); } } } @@ -1483,12 +1497,11 @@ void Source::LanguageProtocolView::setup_autocomplete() { }; autocomplete->on_hide = [this] { - autocomplete_comment.clear(); - autocomplete_insert.clear(); + autocomplete_rows.clear(); }; autocomplete->on_select = [this](unsigned int index, const std::string &text, bool hide_window) { - Glib::ustring insert = hide_window ? autocomplete_insert[index] : text; + Glib::ustring insert = hide_window ? autocomplete_rows[index].insert : text; get_buffer()->erase(CompletionDialog::get()->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); @@ -1525,8 +1538,20 @@ void Source::LanguageProtocolView::setup_autocomplete() { get_buffer()->insert(CompletionDialog::get()->start_mark->get_iter(), insert); }; - autocomplete->get_tooltip = [this](unsigned int index) { - return autocomplete_comment[index]; + autocomplete->set_tooltip_buffer = [this](unsigned int index) -> std::function { + auto plaintext = autocomplete_rows[index].plaintext; + auto markdown = autocomplete_rows[index].markdown; + if(plaintext.empty() && markdown.empty()) + return nullptr; + return [plaintext = std::move(plaintext), markdown = std::move(markdown)](Tooltip &tooltip) { + if(!plaintext.empty()) + tooltip.insert_with_links_tagged(plaintext); + if(!markdown.empty()) { + if(!plaintext.empty()) + tooltip.buffer->insert(tooltip.buffer->get_insert()->get_iter(), "\n\n"); + tooltip.insert_markdown(markdown); + } + }; }; } diff --git a/src/source_language_protocol.h b/src/source_language_protocol.h index 24c2933..05f3625 100644 --- a/src/source_language_protocol.h +++ b/src/source_language_protocol.h @@ -192,8 +192,14 @@ namespace Source { std::unique_ptr autocomplete; void setup_signals(); void setup_autocomplete(); - std::vector autocomplete_comment; - std::vector autocomplete_insert; + + struct AutocompleteRow { + std::string insert; + std::string plaintext; + std::string markdown; + }; + std::vector autocomplete_rows; + std::atomic autocomplete_enable_snippets = {false}; bool autocomplete_show_arguments = false; sigc::connection autocomplete_delayed_show_arguments_connection;