From a5858199dfc64a7d6857a4e567acde1896959379 Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 19 Jun 2023 13:17:07 +0200 Subject: [PATCH] Fixed rust-analyzer installation --- src/filesystem.cpp | 28 ---------- src/filesystem.hpp | 4 -- src/notebook.cpp | 135 ++++++++++++++++++--------------------------- 3 files changed, 53 insertions(+), 114 deletions(-) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index d455fe8..a8015da 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -6,7 +6,6 @@ #include boost::optional filesystem::rust_sysroot_path; -boost::optional filesystem::rust_nightly_sysroot_path; boost::optional> filesystem::executable_search_paths; // Only use on small files @@ -155,33 +154,6 @@ const boost::filesystem::path &filesystem::get_rust_sysroot_path() noexcept { return *rust_sysroot_path; } -boost::filesystem::path filesystem::get_rust_nightly_sysroot_path() noexcept { - auto get_path = [] { - std::string path; - TinyProcessLib::Config processConfig{}; -#ifdef JUCI_FLATPAK_SANDBOX - processConfig.flatpak_spawn_host = true; -#endif - TinyProcessLib::Process process( - // Slightly complicated since "RUSTUP_TOOLCHAIN=nightly rustc --print sysroot" actually installs nightly toolchain if missing... - "rustup toolchain list|grep nightly > /dev/null && RUSTUP_TOOLCHAIN=nightly rustc --print sysroot", "", - [&path](const char *buffer, size_t length) { - path += std::string(buffer, length); - }, - [](const char *buffer, size_t n) {}, false, processConfig); - if(process.get_exit_status() == 0) { - while(!path.empty() && (path.back() == '\n' || path.back() == '\r')) - path.pop_back(); - return boost::filesystem::path(path); - } - return boost::filesystem::path(); - }; - - if(!rust_nightly_sysroot_path) - rust_nightly_sysroot_path = get_path(); - return *rust_nightly_sysroot_path; -} - boost::filesystem::path filesystem::get_short_path(const boost::filesystem::path &path) noexcept { #ifdef _WIN32 return path; diff --git a/src/filesystem.hpp b/src/filesystem.hpp index 77fc059..1dc4918 100644 --- a/src/filesystem.hpp +++ b/src/filesystem.hpp @@ -26,10 +26,6 @@ public: static const boost::filesystem::path &get_rust_sysroot_path() noexcept; /// Set to {} to reset get_rust_sysroot_path static boost::optional rust_sysroot_path; - /// Returns empty path on failure - static boost::filesystem::path get_rust_nightly_sysroot_path() noexcept; - /// Set to {} to reset get_rust_sysroot_path - static boost::optional rust_nightly_sysroot_path; /// Replaces home path with ~ static boost::filesystem::path get_short_path(const boost::filesystem::path &path) noexcept; /// Replaces ~ with home path (boost::filesystem does not recognize ~) diff --git a/src/notebook.cpp b/src/notebook.cpp index 1681c3e..d4f10a8 100644 --- a/src/notebook.cpp +++ b/src/notebook.cpp @@ -89,7 +89,6 @@ Notebook::Notebook() : Gtk::Paned(), notebooks(2) { env = c_env; Glib::setenv("PATH", !env.empty() ? env + delimiter + cargo_bin.string() : cargo_bin.string()); filesystem::rust_sysroot_path = {}; - filesystem::rust_nightly_sysroot_path = {}; filesystem::executable_search_paths = {}; } } @@ -201,90 +200,63 @@ bool Notebook::open(const boost::filesystem::path &file_path_, Position position else if(language && !language_protocol_language_id.empty() && !filesystem::find_executable(language_protocol_language_id + "-language-server").empty()) source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, filesystem::escape_argument(language_protocol_language_id + "-language-server"))); else if(language && language_protocol_language_id == "rust") { - if(!filesystem::find_executable("rust-analyzer").empty()) - source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, "rust-analyzer")); - else { - if(filesystem::find_executable("rustup").empty()) - install_rust(); - if(!filesystem::find_executable("rustup").empty()) { - // Try find rust-analyzer installed with rustup - auto sysroot = filesystem::get_rust_sysroot_path(); - if(!sysroot.empty()) { - auto rust_analyzer = sysroot / "bin" / "rust-analyzer"; - if(filesystem::is_executable(rust_analyzer)) - source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, filesystem::escape_argument(rust_analyzer.string()))); - else { - // Workaround while rust-analyzer is in nightly toolchain only - auto nightly_sysroot = filesystem::get_rust_nightly_sysroot_path(); - if(!nightly_sysroot.empty()) { - auto nightly_rust_analyzer = nightly_sysroot / "bin" / "rust-analyzer"; - if(filesystem::is_executable(nightly_rust_analyzer)) - source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, filesystem::escape_argument(nightly_rust_analyzer.string()))); - } - } + if(filesystem::find_executable("rustup").empty()) + install_rust(); + if(!filesystem::find_executable("rustup").empty()) { + static auto rust_analyzer_installed = []() -> bool { + std::stringstream stdin_stream, stdout_stream; + auto exit_status = Terminal::get().process(stdin_stream, stdout_stream, "rustup component list --installed"); + if(exit_status != 0) + return false; + std::string line; + while(std::getline(stdout_stream, line)) { + if(starts_with(line, "rust-analyzer")) + return true; } - if(source_views_previous_size == source_views.size()) { + return false; + }(); + if(rust_analyzer_installed) + source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, filesystem::escape_argument((filesystem::get_rust_sysroot_path() / "bin" / "rust-analyzer").string()))); + if(source_views_previous_size == source_views.size()) { + static bool show_dialog = true; + if(show_dialog) { + show_dialog = false; // Install rust-analyzer - auto install_rust_analyzer = [this](const std::string &command, bool &show_dialog) { - Gtk::MessageDialog dialog(*static_cast(get_toplevel()), "Install Rust language server?", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); - Gtk::Image image; - image.set_from_icon_name("dialog-question", Gtk::BuiltinIconSize::ICON_SIZE_DIALOG); - dialog.set_image(image); - dialog.set_default_response(Gtk::RESPONSE_YES); - dialog.set_secondary_text("Rust language server not found. Would you like to install rust-analyzer?"); - dialog.show_all(); - int result = dialog.run(); - dialog.hide(); - if(result == Gtk::RESPONSE_YES) { - bool canceled = false; - Dialog::Message message("Installing rust-analyzer", [&canceled] { - canceled = true; - }); - boost::optional exit_status; - - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); - auto process = Terminal::get().async_process(command, "", [&exit_status](int exit_status_) { - exit_status = exit_status_; - }); - bool killed = false; - while(!exit_status) { - if(canceled && !killed) { - process->kill(); - killed = true; - show_dialog = true; // Show dialog again - } - while(Gtk::Main::events_pending()) - Gtk::Main::iteration(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - if(exit_status == 0) { - Terminal::get().print("\e[32mSuccess\e[m: installed rust-analyzer\n"); - return true; + Gtk::MessageDialog dialog(*static_cast(get_toplevel()), "Install Rust language server?", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); + Gtk::Image image; + image.set_from_icon_name("dialog-question", Gtk::BuiltinIconSize::ICON_SIZE_DIALOG); + dialog.set_image(image); + dialog.set_default_response(Gtk::RESPONSE_YES); + dialog.set_secondary_text("Rust language server not found. Would you like to install rust-analyzer?"); + dialog.show_all(); + int result = dialog.run(); + dialog.hide(); + if(result == Gtk::RESPONSE_YES) { + bool canceled = false; + Dialog::Message message("Installing rust-analyzer", [&canceled] { + canceled = true; + }); + boost::optional exit_status; + std::string command = "rustup component add rust-analyzer"; + Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + auto process = Terminal::get().async_process(command, "", [&exit_status](int exit_status_) { + exit_status = exit_status_; + }); + bool killed = false; + while(!exit_status) { + if(canceled && !killed) { + process->kill(); + killed = true; + show_dialog = true; // Show dialog again } + while(Gtk::Main::events_pending()) + Gtk::Main::iteration(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - return false; - }; - static bool show_dialog = true; - if(show_dialog) { - show_dialog = false; - std::stringstream stdin_stream, stdout_stream; - // Workaround while rust-analyzer is called rust-analyzer-preview instead of rust-analyzer - if(Terminal::get().process(stdin_stream, stdout_stream, "rustup component list") == 0) { - bool rust_analyzer_in_toolchain = false; - std::string line; - while(std::getline(stdout_stream, line)) { - if(starts_with(line, "rust-analyzer")) { - if(install_rust_analyzer(std::string("rustup component add ") + (starts_with(line, "rust-analyzer-preview") ? "rust-analyzer-preview" : "rust-analyzer"), show_dialog)) - source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, filesystem::escape_argument((filesystem::get_rust_sysroot_path() / "bin" / "rust-analyzer").string()))); - rust_analyzer_in_toolchain = true; - break; - } - } - // Workaround while rust-analyzer is in nightly toolchain only - if(!rust_analyzer_in_toolchain && install_rust_analyzer("rustup toolchain install nightly --component rust-analyzer-preview", show_dialog)) { - filesystem::rust_nightly_sysroot_path = {}; - source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, filesystem::escape_argument((filesystem::get_rust_nightly_sysroot_path() / "bin" / "rust-analyzer").string()))); - } + if(exit_status == 0) { + Terminal::get().print("\e[32mSuccess\e[m: installed rust-analyzer\n"); + rust_analyzer_installed = true; + source_views.emplace_back(new Source::LanguageProtocolView(file_path, language, language_protocol_language_id, filesystem::escape_argument((filesystem::get_rust_sysroot_path() / "bin" / "rust-analyzer").string()))); } } } @@ -673,7 +645,6 @@ void Notebook::install_rust() { } } filesystem::rust_sysroot_path = {}; - filesystem::rust_nightly_sysroot_path = {}; filesystem::executable_search_paths = {}; Terminal::get().print("\e[32mSuccess\e[m: installed Rust and updated PATH environment variable\n"); }