Browse Source

Fixed rust-analyzer installation

merge-requests/413/head
eidheim 3 years ago
parent
commit
a5858199df
  1. 28
      src/filesystem.cpp
  2. 4
      src/filesystem.hpp
  3. 135
      src/notebook.cpp

28
src/filesystem.cpp

@ -6,7 +6,6 @@
#include <sstream>
boost::optional<boost::filesystem::path> filesystem::rust_sysroot_path;
boost::optional<boost::filesystem::path> filesystem::rust_nightly_sysroot_path;
boost::optional<std::vector<boost::filesystem::path>> 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;

4
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<boost::filesystem::path> 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<boost::filesystem::path> 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 ~)

135
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<Gtk::Window *>(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<int> 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<Gtk::Window *>(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<int> 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");
}

Loading…
Cancel
Save