diff --git a/src/notebook.cc b/src/notebook.cc index 1905709..51f40d7 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -417,6 +417,21 @@ void Notebook::open(const boost::filesystem::path &file_path_, size_t notebook_i focus_view(source_view); } +void Notebook::open_uri(const std::string &uri) { +#ifdef __APPLE__ + Terminal::get().process("open " + filesystem::escape_argument(uri)); +#else + GError *error = nullptr; +#if GTK_VERSION_GE(3, 22) + gtk_show_uri_on_window(nullptr, uri.c_str(), GDK_CURRENT_TIME, &error); +#else + gtk_show_uri(nullptr, uri.c_str(), GDK_CURRENT_TIME, &error); +#endif + g_clear_error(&error); +#endif +} + + void Notebook::configure(size_t index) { auto source_font_description = Pango::FontDescription(Config::get().source.font); auto source_map_font_desc = Pango::FontDescription(static_cast(source_font_description.get_family()) + " " + Config::get().source.map_font_size); diff --git a/src/notebook.h b/src/notebook.h index 19bca11..2577ca0 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -35,6 +35,7 @@ public: std::vector &get_views(); void open(const boost::filesystem::path &file_path, size_t notebook_index = -1); + void open_uri(const std::string &uri); void configure(size_t index); bool save(size_t index); bool save_current(); diff --git a/src/project.cc b/src/project.cc index a457420..61bfedf 100644 --- a/src/project.cc +++ b/src/project.cc @@ -983,21 +983,7 @@ void Project::JavaScript::compile_and_run() { } void Project::HTML::compile_and_run() { - auto uri = Notebook::get().get_current_view()->file_path.string(); -#ifdef __APPLE__ - Terminal::get().process("open " + filesystem::escape_argument(uri)); -#else -#ifdef __linux - uri = "file://" + uri; -#endif - GError *error = nullptr; -#if GTK_VERSION_GE(3, 22) - gtk_show_uri_on_window(nullptr, uri.c_str(), GDK_CURRENT_TIME, &error); -#else - gtk_show_uri(nullptr, uri.c_str(), GDK_CURRENT_TIME, &error); -#endif - g_clear_error(&error); -#endif + Notebook::get().open_uri(std::string("file://") + Notebook::get().get_current_view()->file_path.string()); } std::pair Project::Rust::get_run_arguments() { diff --git a/src/source.cc b/src/source.cc index 48a9f57..ae3f8c1 100644 --- a/src/source.cc +++ b/src/source.cc @@ -952,6 +952,20 @@ void Source::View::hide_dialogs() { CompletionDialog::get()->hide(); } +void Source::View::insert_with_links_tagged(const Glib::RefPtr &buffer, const std::string &text) { + static std::regex http_regex("(https?://[a-zA-Z0-9\\-._~:/?#\\[\\]@!$&'()*+,;=]+[a-zA-Z0-9\\-_~/@$*+;=])"); + std::smatch sm; + std::sregex_iterator it(text.begin(), text.end(), http_regex); + std::sregex_iterator end; + size_t start_pos = 0; + for(; it != end; ++it) { + buffer->insert(buffer->get_insert()->get_iter(), &text[start_pos], &text[it->position()]); + buffer->insert_with_tag(buffer->get_insert()->get_iter(), &text[it->position()], &text[it->position() + it->length()], link_tag); + start_pos = it->position() + it->length(); + } + buffer->insert(buffer->get_insert()->get_iter(), &text[start_pos], &text[text.size()]); +} + void Source::View::add_diagnostic_tooltip(const Gtk::TextIter &start, const Gtk::TextIter &end, bool error, std::function &)> &&set_buffer) { diagnostic_offsets.emplace(start.get_offset()); diff --git a/src/source.h b/src/source.h index 412ce85..f717a1c 100644 --- a/src/source.h +++ b/src/source.h @@ -101,6 +101,9 @@ namespace Source { virtual void apply_clickable_tag(const Gtk::TextIter &iter) {} bool clickable_tag_applied = false; + Glib::RefPtr link_tag; /// Used in tooltips + void insert_with_links_tagged(const Glib::RefPtr &buffer, const std::string &text); + virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { diagnostic_tooltips.show(rectangle); } void add_diagnostic_tooltip(const Gtk::TextIter &start, const Gtk::TextIter &end, bool error, std::function &)> &&set_buffer); void clear_diagnostic_tooltips(); @@ -150,8 +153,6 @@ namespace Source { int multiple_cursors_erase_backward_length; int multiple_cursors_erase_forward_length; bool on_key_press_event_multiple_cursors(GdkEventKey *key); - - Glib::RefPtr link_tag; /// Used in tooltips }; class GenericView : public View { diff --git a/src/source_clang.cc b/src/source_clang.cc index 59daabc..f90be76 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -389,7 +389,7 @@ void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle) buffer->insert(buffer->get_insert()->get_iter(), "Type: " + token.get_cursor().get_type_description()); auto brief_comment = token.get_cursor().get_brief_comments(); if(brief_comment != "") - buffer->insert(buffer->get_insert()->get_iter(), "\n\n" + brief_comment); + insert_with_links_tagged(buffer, "\n\n" + brief_comment); #ifdef JUCI_ENABLE_DEBUG if(Debug::LLDB::get().is_stopped()) { diff --git a/src/source_language_protocol.cc b/src/source_language_protocol.cc index e22b160..fabec01 100644 --- a/src/source_language_protocol.cc +++ b/src/source_language_protocol.cc @@ -896,7 +896,7 @@ void Source::LanguageProtocolView::update_diagnostics(std::vectorinsert_at_cursor(diagnostic.related_informations[i].message); buffer->insert_at_cursor(": "); auto pos = buffer->get_insert()->get_iter(); - buffer->insert_with_tag(pos, link, "link"); + buffer->insert_with_tag(pos, link, link_tag); if(i != diagnostic.related_informations.size() - 1) buffer->insert_at_cursor("\n"); } @@ -979,7 +979,7 @@ void Source::LanguageProtocolView::show_type_tooltips(const Gdk::Rectangle &rect while(((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_') && end.forward_char()) { } type_tooltips.emplace_back(this, get_buffer()->create_mark(start), get_buffer()->create_mark(end), [this, offset, content](const Glib::RefPtr &buffer) { - buffer->insert(buffer->get_insert()->get_iter(), *content); + insert_with_links_tagged(buffer, *content); #ifdef JUCI_ENABLE_DEBUG if(language_id == "rust" && capabilities.definition) { diff --git a/src/tooltips.cc b/src/tooltips.cc index 9d4e72b..9e7ae54 100644 --- a/src/tooltips.cc +++ b/src/tooltips.cc @@ -116,6 +116,12 @@ void Tooltip::show(bool disregard_drawn, const std::function &on_motion) auto end = iter; end.forward_to_tag_toggle(link_tag); std::string text = tooltip_text_view->get_buffer()->get_text(start, end); + + if(text.compare(0, 7, "http://") == 0 || text.compare(0, 8, "https://") == 0) { + Notebook::get().open_uri(text); + return true; + } + static std::regex regex("^([^:]+):([^:]+):([^:]+)$"); std::smatch sm; if(std::regex_match(text, sm, regex)) { diff --git a/src/window.cc b/src/window.cc index b5dc824..d9509c8 100644 --- a/src/window.cc +++ b/src/window.cc @@ -724,9 +724,9 @@ void Window::set_menu_actions() { if(auto view = Notebook::get().get_current_view()) { if(view->get_token_data) { auto data = view->get_token_data(); - std::string url; + std::string uri; if(data.size() == 1) - url = data[0]; + uri = data[0]; else if(data.size() > 1) { auto documentation_search = Config::get().source.documentation_searches.find(data[0]); if(documentation_search != Config::get().source.documentation_searches.end()) { @@ -748,22 +748,12 @@ void Window::set_menu_actions() { query = documentation_search->second.queries.find("@any"); if(query != documentation_search->second.queries.end()) - url = query->second + token_query; + uri = query->second + token_query; } } } - if(!url.empty()) { -#ifdef __APPLE__ - Terminal::get().process("open \"" + url + "\""); -#else - GError *error = nullptr; -#if GTK_VERSION_GE(3, 22) - gtk_show_uri_on_window(nullptr, url.c_str(), GDK_CURRENT_TIME, &error); -#else - gtk_show_uri(nullptr, url.c_str(), GDK_CURRENT_TIME, &error); -#endif - g_clear_error(&error); -#endif + if(!uri.empty()) { + Notebook::get().open_uri(uri); } } }